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 
46 namespace gl3cts
47 {
48 
49 /** Constructor
50  *
51  * @param context Test context
52  **/
programInfo(deqp::Context & context)53 Utils::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  **/
~programInfo()62 Utils::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  **/
build(const glw::GLchar * fragment_shader_code,const glw::GLchar * vertex_shader_code)98 void 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  **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const133 void 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  **/
link() const182 void 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  */
setUniform(Utils::_variable_type type,const glw::GLchar * name,const glw::GLvoid * data)241 void 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 		break;
300 	}
301 
302 	GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform");
303 }
304 
305 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
306  *
307  * @param token           Token string
308  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
309  * @param text            String that will be used as replacement for <token>
310  * @param string          String to work on
311  **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)312 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
313 						 std::string& string)
314 {
315 	const size_t text_length	= strlen(text);
316 	const size_t token_length   = strlen(token);
317 	const size_t token_position = string.find(token, search_position);
318 
319 	string.replace(token_position, token_length, text, text_length);
320 
321 	search_position = token_position + text_length;
322 }
323 
324 /* Constants used by GPUShader5ImplicitConversionsTest */
325 const glw::GLsizei GPUShader5ImplicitConversionsTest::m_width  = 8;
326 const glw::GLsizei GPUShader5ImplicitConversionsTest::m_height = 8;
327 
328 /** Constructor.
329  *
330  * @param context Rendering context.
331  **/
GPUShader5ImplicitConversionsTest(deqp::Context & context)332 GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context)
333 	: TestCase(context, "implicit_conversions",
334 			   "Verifies that implicit conversions are accepted and executed as explicit ones")
335 	, m_fbo_id(0)
336 	, m_tex_id(0)
337 	, m_vao_id(0)
338 
339 {
340 	/* Left blank intentionally */
341 }
342 
343 /** Constructor.
344  *
345  * @param context     Rendering context.
346  * @param name        Name of test
347  * @param description Describes test
348  **/
GPUShader5ImplicitConversionsTest(deqp::Context & context,const char * name,const char * description)349 GPUShader5ImplicitConversionsTest::GPUShader5ImplicitConversionsTest(deqp::Context& context, const char* name,
350 																	 const char* description)
351 	: TestCase(context, name, description), m_fbo_id(0), m_tex_id(0), m_vao_id(0)
352 
353 {
354 	/* Left blank intentionally */
355 }
356 
357 /** Deinitializes all GL objects that may have been created during
358  *  test execution.
359  **/
deinit()360 void GPUShader5ImplicitConversionsTest::deinit()
361 {
362 	if (m_fbo_id != 0)
363 	{
364 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
365 		gl.deleteFramebuffers(1, &m_fbo_id);
366 
367 		m_fbo_id = 0;
368 	}
369 
370 	if (m_tex_id != 0)
371 	{
372 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
373 		gl.deleteTextures(1, &m_tex_id);
374 
375 		m_tex_id = 0;
376 	}
377 
378 	if (m_vao_id != 0)
379 	{
380 		const glw::Functions& gl = m_context.getRenderContext().getFunctions();
381 		gl.deleteVertexArrays(1, &m_vao_id);
382 
383 		m_vao_id = 0;
384 	}
385 }
386 
387 /** Executes test iteration.
388  *
389  *  @return Returns STOP.
390  */
iterate()391 tcu::TestNode::IterateResult GPUShader5ImplicitConversionsTest::iterate()
392 {
393 	/* Defines data used as u1 and u2 uniforms */
394 	static const glw::GLint  uni_data_int_1[4]  = { 112, -1122, 111222, -1222111222 };
395 	static const glw::GLint  uni_data_int_2[4]  = { -112, 1122, -111222, 1222111222 };
396 	static const glw::GLuint uni_data_uint_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
397 	static const glw::GLuint uni_data_uint_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
398 
399 	/* Defines test cases */
400 	static const testCase test_cases[] = {
401 		{ "uint", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> uint */,
402 		{ "uint", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_1 },
403 		{ "float", false, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_1, uni_data_int_2 } /* int >> float */,
404 		{ "float", true, "int", Utils::VARIABLE_TYPE_INT, uni_data_int_2, uni_data_int_2 },
405 		{ "uvec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> uvec2 */,
406 		{ "uvec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
407 		{ "vec2", false, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_2 } /* ivec2 >> vec2 */,
408 		{ "vec2", true, "ivec2", Utils::VARIABLE_TYPE_IVEC2, uni_data_int_1, uni_data_int_1 },
409 		{ "uvec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> uvec3 */,
410 		{ "uvec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
411 		{ "vec3", false, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_1, uni_data_int_2 } /* ivec3 >> vec3 */,
412 		{ "vec3", true, "ivec3", Utils::VARIABLE_TYPE_IVEC3, uni_data_int_2, uni_data_int_2 },
413 		{ "uvec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> uvec4 */,
414 		{ "uvec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
415 		{ "vec4", false, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_2 } /* ivec4 >> vec4 */,
416 		{ "vec4", true, "ivec4", Utils::VARIABLE_TYPE_IVEC4, uni_data_int_1, uni_data_int_1 },
417 		{ "float", false, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_1, uni_data_uint_2 } /* uint >> float */,
418 		{ "float", true, "uint", Utils::VARIABLE_TYPE_UINT, uni_data_uint_2, uni_data_uint_2 },
419 		{ "vec2", false, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_2 } /* uvec2 >> vec2 */,
420 		{ "vec2", true, "uvec2", Utils::VARIABLE_TYPE_UVEC2, uni_data_uint_1, uni_data_uint_1 },
421 		{ "vec3", false, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_1, uni_data_uint_2 } /* uvec3 >> vec3 */,
422 		{ "vec3", true, "uvec3", Utils::VARIABLE_TYPE_UVEC3, uni_data_uint_2, uni_data_uint_2 },
423 		{ "vec4", false, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_2 } /* uvec4 >> vec4 */,
424 		{ "vec4", true, "uvec4", Utils::VARIABLE_TYPE_UVEC4, uni_data_uint_1, uni_data_uint_1 },
425 	};
426 	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
427 
428 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
429 	{
430 		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
431 	}
432 
433 	testInit();
434 
435 	/* Execute test cases */
436 	for (size_t i = 0; i < n_test_cases; ++i)
437 	{
438 		const testCase& test_case = test_cases[i];
439 
440 		executeTestCase(test_case);
441 	}
442 
443 	/* Set result - exceptions are thrown in case of any error */
444 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
445 
446 	/* Done */
447 	return STOP;
448 }
449 
450 /** Initializes frame buffer and vertex array
451  *
452  **/
testInit()453 void GPUShader5ImplicitConversionsTest::testInit()
454 {
455 	/*  */
456 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
457 
458 	/* Prepare texture for color attachment 0 */
459 	gl.genTextures(1, &m_tex_id);
460 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
461 
462 	gl.bindTexture(GL_TEXTURE_2D, m_tex_id);
463 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
464 
465 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_width, m_height);
466 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
467 
468 	/* Prepare FBO with color attachment 0 */
469 	gl.genFramebuffers(1, &m_fbo_id);
470 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
471 
472 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
473 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
474 
475 	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_tex_id, 0 /* level */);
476 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
477 
478 	/* Set Viewport */
479 	gl.viewport(0 /* x */, 0 /* y */, m_width, m_height);
480 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
481 
482 	/* Prepare blank VAO */
483 	gl.genVertexArrays(1, &m_vao_id);
484 	GLU_EXPECT_NO_ERROR(gl.getError(), "genVertexArrays");
485 
486 	gl.bindVertexArray(m_vao_id);
487 	GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
488 }
489 
490 /** Verifies if image is filled with <color>
491  *
492  * @param color       Color to be checked
493  * @param is_expected Selects if image is expected to be filled with given color or not
494  **/
verifyImage(glw::GLuint color,bool is_expected) const495 void GPUShader5ImplicitConversionsTest::verifyImage(glw::GLuint color, bool is_expected) const
496 {
497 	/*  */
498 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
499 
500 	/* Storage for image data */
501 	glw::GLuint result_image[m_width * m_height];
502 
503 	/* Get image data */
504 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
505 	GLU_EXPECT_NO_ERROR(gl.getError(), "getTexImage");
506 
507 	/* Inspect data */
508 	if (true == is_expected)
509 	{
510 		for (size_t i = 0; i < m_width * m_height; ++i)
511 		{
512 			const glw::GLuint pixel_data = result_image[i];
513 
514 			if (color != pixel_data)
515 			{
516 				TCU_FAIL("Found invalid pixel during verification of drawn image");
517 			}
518 		}
519 	}
520 	else
521 	{
522 		for (size_t i = 0; i < m_width * m_height; ++i)
523 		{
524 			const glw::GLuint pixel_data = result_image[i];
525 
526 			if (color == pixel_data)
527 			{
528 				TCU_FAIL("Found invalid pixel during verification of drawn image");
529 			}
530 		}
531 	}
532 }
533 
534 /** Executes test case
535  *
536  * @param test_case Defines test case parameters
537  */
executeTestCase(const testCase & test_case)538 void GPUShader5ImplicitConversionsTest::executeTestCase(const testCase& test_case)
539 {
540 	static const glw::GLuint white_color = 0xffffffff;
541 
542 	/*  */
543 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
544 
545 	/* Run test case */
546 	{
547 		/* Get shaders */
548 		const std::string& fs = getFragmentShader();
549 		const std::string& vs = getVertexShader(test_case.m_destination_type, test_case.m_source_type);
550 
551 		/* Prepare program */
552 		Utils::programInfo program(m_context);
553 
554 		program.build(fs.c_str(), vs.c_str());
555 
556 		gl.useProgram(program.m_program_object_id);
557 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
558 
559 		program.setUniform(test_case.m_source_variable_type, "u1", test_case.m_u1_data);
560 		program.setUniform(test_case.m_source_variable_type, "u2", test_case.m_u2_data);
561 
562 		/* Clear FBO */
563 		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
564 		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
565 
566 		gl.clear(GL_COLOR_BUFFER_BIT);
567 		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
568 
569 		/* Draw a triangle strip */
570 		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
571 		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
572 	}
573 
574 	/* Verification */
575 	verifyImage(white_color, test_case.m_is_white_expected);
576 }
577 
578 /** Get vertex shader source.
579  *
580  * @param destination_type Name of type
581  * @param source_type      Name of type
582  *
583  * @return String with source of shader
584  */
getVertexShader(const glw::GLchar * destination_type,const glw::GLchar * source_type)585 std::string GPUShader5ImplicitConversionsTest::getVertexShader(const glw::GLchar* destination_type,
586 															   const glw::GLchar* source_type)
587 {
588 	/* Vertex shader template */
589 	const char* vs_body_template = "#version 150\n"
590 								   "#extension GL_ARB_gpu_shader5 : require\n"
591 								   "\n"
592 								   "uniform SOURCE_TYPE u1;\n"
593 								   "uniform SOURCE_TYPE u2;\n"
594 								   "\n"
595 								   "out     vec4 result;\n"
596 								   "\n"
597 								   "void main()\n"
598 								   "{\n"
599 								   "    DESTINATION_TYPE v = ZERO;\n"
600 								   "\n"
601 								   "    v = DESTINATION_TYPE(u2) - u1;\n"
602 								   "\n"
603 								   "    result = vec4(0.0, 0.0, 0.0, 0.0);\n"
604 								   "    if (ZERO == v)\n"
605 								   "    {\n"
606 								   "      result = vec4(1.0, 1.0, 1.0, 1.0);\n"
607 								   "    }\n"
608 								   "\n"
609 								   "    switch (gl_VertexID)\n"
610 								   "    {\n"
611 								   "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
612 								   "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
613 								   "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
614 								   "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
615 								   "    }\n"
616 								   "}\n"
617 								   "\n";
618 
619 	std::string vs_body = vs_body_template;
620 
621 	/* Tokens */
622 	size_t search_position = 0;
623 
624 	Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
625 	Utils::replaceToken("SOURCE_TYPE", search_position, source_type, vs_body);
626 
627 	search_position = 0;
628 	Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
629 	Utils::replaceToken("DESTINATION_TYPE", search_position, destination_type, vs_body);
630 
631 	search_position = 0;
632 	if (!strcmp(destination_type, "int") || !strcmp(destination_type, "uint"))
633 	{
634 		Utils::replaceToken("ZERO", search_position, "0", vs_body);
635 		Utils::replaceToken("ZERO", search_position, "0", vs_body);
636 	}
637 	else if (!strcmp(destination_type, "float"))
638 	{
639 		Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
640 		Utils::replaceToken("ZERO", search_position, "0.0", vs_body);
641 	}
642 	else if (!strcmp(destination_type, "ivec2"))
643 	{
644 		Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
645 		Utils::replaceToken("ZERO", search_position, "ivec2(0,0)", vs_body);
646 	}
647 	else if (!strcmp(destination_type, "ivec3"))
648 	{
649 		Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
650 		Utils::replaceToken("ZERO", search_position, "ivec3(0,0,0)", vs_body);
651 	}
652 	else if (!strcmp(destination_type, "ivec4"))
653 	{
654 		Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
655 		Utils::replaceToken("ZERO", search_position, "ivec4(0,0,0,0)", vs_body);
656 	}
657 	else if (!strcmp(destination_type, "uvec2"))
658 	{
659 		Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
660 		Utils::replaceToken("ZERO", search_position, "uvec2(0,0)", vs_body);
661 	}
662 	else if (!strcmp(destination_type, "uvec3"))
663 	{
664 		Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
665 		Utils::replaceToken("ZERO", search_position, "uvec3(0,0,0)", vs_body);
666 	}
667 	else if (!strcmp(destination_type, "uvec4"))
668 	{
669 		Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
670 		Utils::replaceToken("ZERO", search_position, "uvec4(0,0,0,0)", vs_body);
671 	}
672 	else if (!strcmp(destination_type, "vec2"))
673 	{
674 		Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
675 		Utils::replaceToken("ZERO", search_position, "vec2(0,0)", vs_body);
676 	}
677 	else if (!strcmp(destination_type, "vec3"))
678 	{
679 		Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
680 		Utils::replaceToken("ZERO", search_position, "vec3(0,0,0)", vs_body);
681 	}
682 	else if (!strcmp(destination_type, "vec4"))
683 	{
684 		Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
685 		Utils::replaceToken("ZERO", search_position, "vec4(0,0,0,0)", vs_body);
686 	}
687 
688 	return vs_body;
689 }
690 
691 /** Get fragment shader source.
692  *
693  * @return String with source of shader
694  */
getFragmentShader()695 std::string GPUShader5ImplicitConversionsTest::getFragmentShader()
696 {
697 	const char* fs_body_template = "#version 150\n"
698 								   "\n"
699 								   "in  vec4 result;\n"
700 								   "out vec4 color;\n"
701 								   "\n"
702 								   "void main()\n"
703 								   "{\n"
704 								   "    color = result;\n"
705 								   "}\n"
706 								   "\n";
707 
708 	std::string fs_body = fs_body_template;
709 
710 	return fs_body;
711 }
712 
713 /** Constructor.
714  *
715  *  @param context Rendering context.
716  *
717  **/
GPUShader5FunctionOverloadingTest(deqp::Context & context)718 GPUShader5FunctionOverloadingTest::GPUShader5FunctionOverloadingTest(deqp::Context& context)
719 	: GPUShader5ImplicitConversionsTest(context, "function_overloading",
720 										"Verifies that function overloading is accepted")
721 {
722 	/* Left blank intentionally */
723 }
724 
725 /** Executes test iteration.
726  *
727  *  @return Returns STOP.
728  */
iterate()729 tcu::TestNode::IterateResult GPUShader5FunctionOverloadingTest::iterate()
730 {
731 	/* Defines data used as u1 and u2 uniforms */
732 	static const glw::GLint  u1_data_1[4] = { (glw::GLint)0xffff0000, 0x0000ffff, 0x00ffffff, (glw::GLint)0xffffffff };
733 	static const glw::GLint  u1_data_2[4] = { -112, 1122, -111222, 1222111222 };
734 	static const glw::GLuint u2_data_1[4] = { 0xffff0000, 0x0000ffff, 0x00ffffff, 0xffffffff };
735 	static const glw::GLuint u2_data_2[4] = { 0xfff70000, 0x00007fff, 0x007fffff, 0xfffffff7 };
736 
737 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
738 	{
739 		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
740 	}
741 
742 	testInit();
743 
744 	/* Execute test case */
745 	execute(u1_data_1, u2_data_1, true);
746 	execute(u1_data_2, u2_data_2, false);
747 
748 	/* Set result - exceptions are thrown in case of any error */
749 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
750 
751 	/* Done */
752 	return STOP;
753 }
754 
755 /** Executes test case
756  *
757  * @param u1_data   Pointer to data that will used as u1 uniform
758  * @param u2_data   Pointer to data that will used as u2 uniform
759  * @param test_case Defines test case parameters
760  */
execute(const glw::GLint * u1_data,const glw::GLuint * u2_data,bool is_black_expected)761 void GPUShader5FunctionOverloadingTest::execute(const glw::GLint* u1_data, const glw::GLuint* u2_data,
762 												bool is_black_expected)
763 {
764 	static const glw::GLuint black_color = 0x00000000;
765 
766 	/*  */
767 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
768 
769 	/* Run test case */
770 	{
771 		/* Shaders */
772 		const char* fs = "#version 150\n"
773 						 "\n"
774 						 "in  vec4 result;\n"
775 						 "out vec4 color;\n"
776 						 "\n"
777 						 "void main()\n"
778 						 "{\n"
779 						 "    color = result;\n"
780 						 "}\n"
781 						 "\n";
782 
783 		const char* vs = "#version 150\n"
784 						 "#extension GL_ARB_gpu_shader5 : require\n"
785 						 "\n"
786 						 "uniform ivec4 u1;\n"
787 						 "uniform uvec4 u2;\n"
788 						 "\n"
789 						 "out     vec4  result;\n"
790 						 "\n"
791 						 "vec4 f(in vec4 a, in vec4 b)\n"
792 						 "{\n"
793 						 "    return a * b;\n"
794 						 "}\n"
795 						 "\n"
796 						 "vec4 f(in uvec4 a, in uvec4 b)\n"
797 						 "{\n"
798 						 "    return vec4(a - b);\n"
799 						 "}\n"
800 						 "\n"
801 						 "void main()\n"
802 						 "{\n"
803 						 "    result = f(u1, u2);\n"
804 						 "\n"
805 						 "    switch (gl_VertexID)\n"
806 						 "    {\n"
807 						 "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
808 						 "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
809 						 "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
810 						 "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
811 						 "    }\n"
812 						 "}\n"
813 						 "\n";
814 
815 		/* Prepare program */
816 		Utils::programInfo program(m_context);
817 
818 		program.build(fs, vs);
819 
820 		gl.useProgram(program.m_program_object_id);
821 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
822 
823 		program.setUniform(Utils::VARIABLE_TYPE_IVEC4, "u1", u1_data);
824 		program.setUniform(Utils::VARIABLE_TYPE_UVEC4, "u2", u2_data);
825 
826 		/* Clear FBO */
827 		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
828 		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
829 
830 		gl.clear(GL_COLOR_BUFFER_BIT);
831 		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
832 
833 		/* Draw a triangle strip */
834 		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
835 		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
836 	}
837 
838 	/* Verification */
839 	verifyImage(black_color, is_black_expected);
840 }
841 
842 /** Constructor.
843  *
844  *  @param context Rendering context.
845  *
846  **/
GPUShader5FloatEncodingTest(deqp::Context & context)847 GPUShader5FloatEncodingTest::GPUShader5FloatEncodingTest(deqp::Context& context)
848 	: GPUShader5ImplicitConversionsTest(context, "float_encoding",
849 										"Verifies that functions encoding floats as bits work as expected")
850 {
851 	/* Left blank intentionally */
852 }
853 
854 /** Executes test iteration.
855  *
856  *  @return Returns STOP.
857  */
iterate()858 tcu::TestNode::IterateResult GPUShader5FloatEncodingTest::iterate()
859 {
860 	/* Defines data used as u1 and u2 uniforms */
861 	static const glw::GLfloat floats[4] = { -1.0f, -1234.0f, 1.0f, 1234.0f };
862 	static const glw::GLint   ints[4]   = { -1, -1234, 1, 1234 };
863 	static const glw::GLuint  uints[4]  = { 0xffffffff, 0xfffffb2e, 1, 0x4d2 };
864 
865 	/* Defines tested cases */
866 	static const testCase test_cases[] = {
867 		{ /* float >> int - invalid */
868 		  { Utils::VARIABLE_TYPE_INT, "int", ints },
869 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
870 		  "floatBitsToInt",
871 		  false },
872 		{ /* float >> int - valid */
873 		  { Utils::VARIABLE_TYPE_INT, "int", floats },
874 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
875 		  "floatBitsToInt",
876 		  true },
877 		{ /* vec2 >> ivec2 - invalid */
878 		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
879 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
880 		  "floatBitsToInt",
881 		  false },
882 		{ /* vec2 >> ivec2 - valid */
883 		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
884 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
885 		  "floatBitsToInt",
886 		  true },
887 		{ /* vec3 >> ivec3 - invalid */
888 		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
889 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
890 		  "floatBitsToInt",
891 		  false },
892 		{ /* vec3 >> ivec3 - valid */
893 		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
894 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
895 		  "floatBitsToInt",
896 		  true },
897 		{ /* vec4 >> ivec4 - invalid */
898 		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
899 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
900 		  "floatBitsToInt",
901 		  false },
902 		{ /* vec4 >> ivec4 - valid */
903 		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
904 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
905 		  "floatBitsToInt",
906 		  true },
907 		{ /* float >> uint - invalid */
908 		  { Utils::VARIABLE_TYPE_UINT, "uint", uints },
909 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
910 		  "floatBitsToUint",
911 		  false },
912 		{ /* float >> uint - valid */
913 		  { Utils::VARIABLE_TYPE_UINT, "uint", floats },
914 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
915 		  "floatBitsToUint",
916 		  true },
917 		{ /* vec2 >> uvec2 - invalid */
918 		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
919 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
920 		  "floatBitsToUint",
921 		  false },
922 		{ /* vec2 >> uvec2 - valid */
923 		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
924 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
925 		  "floatBitsToUint",
926 		  true },
927 		{ /* vec3 >> uvec3 - invalid */
928 		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
929 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
930 		  "floatBitsToUint",
931 		  false },
932 		{ /* vec3 >> uvec3 - valid */
933 		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
934 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
935 		  "floatBitsToUint",
936 		  true },
937 		{ /* vec4 >> ivec4 - invalid */
938 		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
939 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
940 		  "floatBitsToUint",
941 		  false },
942 		{ /* vec4 >> uvec4 - valid */
943 		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
944 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
945 		  "floatBitsToUint",
946 		  true },
947 		{ /* int >> float - invalid */
948 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
949 		  { Utils::VARIABLE_TYPE_INT, "int", ints },
950 		  "intBitsToFloat",
951 		  false },
952 		{ /* int >> float - valid */
953 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
954 		  { Utils::VARIABLE_TYPE_INT, "int", floats },
955 		  "intBitsToFloat",
956 		  true },
957 		{ /* ivec2 >> vec2 - invalid */
958 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
959 		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", ints },
960 		  "intBitsToFloat",
961 		  false },
962 		{ /* ivec2 >> vec2 - valid */
963 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
964 		  { Utils::VARIABLE_TYPE_IVEC2, "ivec2", floats },
965 		  "intBitsToFloat",
966 		  true },
967 		{ /* ivec3 >> vec3 - invalid */
968 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
969 		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", ints },
970 		  "intBitsToFloat",
971 		  false },
972 		{ /* ivec3 >> vec3 - valid */
973 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
974 		  { Utils::VARIABLE_TYPE_IVEC3, "ivec3", floats },
975 		  "intBitsToFloat",
976 		  true },
977 		{ /* ivec4 >> vec4 - invalid */
978 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
979 		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", ints },
980 		  "intBitsToFloat",
981 		  false },
982 		{ /* ivec4 >> vec4 - valid */
983 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
984 		  { Utils::VARIABLE_TYPE_IVEC4, "ivec4", floats },
985 		  "intBitsToFloat",
986 		  true },
987 		{ /* uint >> float - invalid */
988 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
989 		  { Utils::VARIABLE_TYPE_UINT, "uint", uints },
990 		  "uintBitsToFloat",
991 		  false },
992 		{ /* uint >> float - valid */
993 		  { Utils::VARIABLE_TYPE_FLOAT, "float", floats },
994 		  { Utils::VARIABLE_TYPE_UINT, "uint", floats },
995 		  "uintBitsToFloat",
996 		  true },
997 		{ /* uvec2 >> vec2 - invalid */
998 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
999 		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", uints },
1000 		  "uintBitsToFloat",
1001 		  false },
1002 		{ /* uvec2 >> vec2 - valid */
1003 		  { Utils::VARIABLE_TYPE_VEC2, "vec2", floats },
1004 		  { Utils::VARIABLE_TYPE_UVEC2, "uvec2", floats },
1005 		  "uintBitsToFloat",
1006 		  true },
1007 		{ /* uvec3 >> vec3 - invalid */
1008 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1009 		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", uints },
1010 		  "uintBitsToFloat",
1011 		  false },
1012 		{ /* uvec3 >> vec3 - valid */
1013 		  { Utils::VARIABLE_TYPE_VEC3, "vec3", floats },
1014 		  { Utils::VARIABLE_TYPE_UVEC3, "uvec3", floats },
1015 		  "uintBitsToFloat",
1016 		  true },
1017 		{ /* uvec4 >> vec4 - invalid */
1018 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1019 		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", uints },
1020 		  "uintBitsToFloat",
1021 		  false },
1022 		{ /* uvec4 >> vec4 - valid */
1023 		  { Utils::VARIABLE_TYPE_VEC4, "vec4", floats },
1024 		  { Utils::VARIABLE_TYPE_UVEC4, "uvec4", floats },
1025 		  "uintBitsToFloat",
1026 		  true },
1027 	};
1028 	static const size_t n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
1029 
1030 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5"))
1031 	{
1032 		throw tcu::NotSupportedError("GL_ARB_gpu_shader5 is not supported.");
1033 	}
1034 
1035 	testInit();
1036 
1037 	/* Execute test case */
1038 	for (size_t i = 0; i < n_test_cases; ++i)
1039 	{
1040 		const testCase& test_case = test_cases[i];
1041 
1042 		execute(test_case);
1043 	}
1044 
1045 	/* Set result - exceptions are thrown in case of any error */
1046 	m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
1047 
1048 	/* Done */
1049 	return STOP;
1050 }
1051 
1052 /** Executes test case
1053  *
1054  * @param test_case Tested case
1055  *
1056  * @param test_case Defines test case parameters
1057  */
execute(const testCase & test_case)1058 void GPUShader5FloatEncodingTest::execute(const testCase& test_case)
1059 {
1060 	static const glw::GLuint white_color = 0xffffffff;
1061 
1062 	/*  */
1063 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1064 
1065 	/* Run test case */
1066 	{
1067 		/* Shaders */
1068 		const char* fs = "#version 150\n"
1069 						 "\n"
1070 						 "in  vec4 result;\n"
1071 						 "out vec4 color;\n"
1072 						 "\n"
1073 						 "void main()\n"
1074 						 "{\n"
1075 						 "    color = result;\n"
1076 						 "}\n"
1077 						 "\n";
1078 
1079 		const std::string& vs = getVertexShader(test_case);
1080 
1081 		/* Prepare program */
1082 		Utils::programInfo program(m_context);
1083 
1084 		program.build(fs, vs.c_str());
1085 
1086 		gl.useProgram(program.m_program_object_id);
1087 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
1088 
1089 		program.setUniform(test_case.m_expected_value.m_type, "expected_value", test_case.m_expected_value.m_data);
1090 		program.setUniform(test_case.m_value.m_type, "value", test_case.m_value.m_data);
1091 
1092 		/* Clear FBO */
1093 		gl.clearColor(0.5f, 0.5f, 0.5f, 0.5f);
1094 		GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
1095 
1096 		gl.clear(GL_COLOR_BUFFER_BIT);
1097 		GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
1098 
1099 		/* Draw a triangle strip */
1100 		gl.drawArrays(GL_TRIANGLE_STRIP, 0 /* first */, 4 /* count */);
1101 		GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
1102 	}
1103 
1104 	/* Verification */
1105 	verifyImage(white_color, test_case.m_is_white_expected);
1106 }
1107 
1108 /** Get vertex shader source.
1109  *
1110  * @param test_case Tested case
1111  *
1112  * @return String with source of shader
1113  */
getVertexShader(const testCase & test_case) const1114 std::string GPUShader5FloatEncodingTest::getVertexShader(const testCase& test_case) const
1115 {
1116 	/* Vertex shader template */
1117 	const char* vs_body_template = "#version 150\n"
1118 								   "#extension GL_ARB_gpu_shader5 : require\n"
1119 								   "\n"
1120 								   "uniform EXPECTED_VALUE_TYPE expected_value;\n"
1121 								   "uniform VALUE_TYPE value;\n"
1122 								   "\n"
1123 								   "out     vec4 result;\n"
1124 								   "\n"
1125 								   "void main()\n"
1126 								   "{\n"
1127 								   "    result = vec4(1.0, 1.0, 1.0, 1.0);\n"
1128 								   "\n"
1129 								   "    EXPECTED_VALUE_TYPE ret_val = TESTED_FUNCTION(value);\n"
1130 								   "\n"
1131 								   "    if (expected_value != ret_val)\n"
1132 								   "    {\n"
1133 								   "        result = vec4(0.0, 0.0, 0.0, 0.0);\n"
1134 								   "    }\n"
1135 								   "\n"
1136 								   "    switch (gl_VertexID)\n"
1137 								   "    {\n"
1138 								   "      case 0: gl_Position = vec4(-1.0, 1.0, 0.0, 1.0); break; \n"
1139 								   "      case 1: gl_Position = vec4( 1.0, 1.0, 0.0, 1.0); break; \n"
1140 								   "      case 2: gl_Position = vec4(-1.0,-1.0, 0.0, 1.0); break; \n"
1141 								   "      case 3: gl_Position = vec4( 1.0,-1.0, 0.0, 1.0); break; \n"
1142 								   "    }\n"
1143 								   "}\n"
1144 								   "\n";
1145 
1146 	std::string vs_body = vs_body_template;
1147 
1148 	/* Tokens */
1149 	size_t search_position = 0;
1150 
1151 	Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1152 	Utils::replaceToken("VALUE_TYPE", search_position, test_case.m_value.m_type_name, vs_body);
1153 	Utils::replaceToken("EXPECTED_VALUE_TYPE", search_position, test_case.m_expected_value.m_type_name, vs_body);
1154 	Utils::replaceToken("TESTED_FUNCTION", search_position, test_case.m_function_name, vs_body);
1155 
1156 	return vs_body;
1157 }
1158 
1159 /** Constructor.
1160  *
1161  *  @param context Rendering context.
1162  **/
GPUShader5Tests(deqp::Context & context)1163 GPUShader5Tests::GPUShader5Tests(deqp::Context& context)
1164 	: TestCaseGroup(context, "gpu_shader5_gl", "Verifies \"gpu_shader5\" functionality")
1165 {
1166 	/* Left blank on purpose */
1167 }
1168 
1169 /** Initializes a texture_storage_multisample test group.
1170  *
1171  **/
init(void)1172 void GPUShader5Tests::init(void)
1173 {
1174 	addChild(new GPUShader5ImplicitConversionsTest(m_context));
1175 	addChild(new GPUShader5FunctionOverloadingTest(m_context));
1176 	addChild(new GPUShader5FloatEncodingTest(m_context));
1177 }
1178 } /* glcts namespace */
1179