• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-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  gl4GPUShaderFP64Tests.cpp
26  * \brief Implements conformance tests for "GPU Shader FP64" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cGPUShaderFP64Tests.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 "deUniquePtr.hpp"
39 #include "tcuMatrixUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 
42 #include <cstdlib>
43 #include <cstring>
44 #include <limits>
45 #include <memory>
46 
47 namespace gl4cts
48 {
49 
50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9;
51 
52 /** Constructor
53  *
54  * @param context Test context
55  **/
programInfo(deqp::Context & context)56 Utils::programInfo::programInfo(deqp::Context& context)
57 	: m_context(context)
58 	, m_compute_shader_id(0)
59 	, m_fragment_shader_id(0)
60 	, m_geometry_shader_id(0)
61 	, m_program_object_id(0)
62 	, m_tesselation_control_shader_id(0)
63 	, m_tesselation_evaluation_shader_id(0)
64 	, m_vertex_shader_id(0)
65 {
66 	/* Nothing to be done here */
67 }
68 
69 /** Destructor
70  *
71  **/
~programInfo()72 Utils::programInfo::~programInfo()
73 {
74 	/* GL entry points */
75 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
76 
77 	/* Make sure program object is no longer used by GL */
78 	gl.useProgram(0);
79 
80 	/* Clean program object */
81 	if (0 != m_program_object_id)
82 	{
83 		gl.deleteProgram(m_program_object_id);
84 		m_program_object_id = 0;
85 	}
86 
87 	/* Clean shaders */
88 	if (0 != m_compute_shader_id)
89 	{
90 		gl.deleteShader(m_compute_shader_id);
91 		m_compute_shader_id = 0;
92 	}
93 
94 	if (0 != m_fragment_shader_id)
95 	{
96 		gl.deleteShader(m_fragment_shader_id);
97 		m_fragment_shader_id = 0;
98 	}
99 
100 	if (0 != m_geometry_shader_id)
101 	{
102 		gl.deleteShader(m_geometry_shader_id);
103 		m_geometry_shader_id = 0;
104 	}
105 
106 	if (0 != m_tesselation_control_shader_id)
107 	{
108 		gl.deleteShader(m_tesselation_control_shader_id);
109 		m_tesselation_control_shader_id = 0;
110 	}
111 
112 	if (0 != m_tesselation_evaluation_shader_id)
113 	{
114 		gl.deleteShader(m_tesselation_evaluation_shader_id);
115 		m_tesselation_evaluation_shader_id = 0;
116 	}
117 
118 	if (0 != m_vertex_shader_id)
119 	{
120 		gl.deleteShader(m_vertex_shader_id);
121 		m_vertex_shader_id = 0;
122 	}
123 }
124 
125 /** Build program
126  *
127  * @param compute_shader_code                Compute shader source code
128  * @param fragment_shader_code               Fragment shader source code
129  * @param geometry_shader_code               Geometry shader source code
130  * @param tesselation_control_shader_code    Tesselation control shader source code
131  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
132  * @param vertex_shader_code                 Vertex shader source code
133  * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
134  * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
135  **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names)136 void Utils::programInfo::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
137 							   const glw::GLchar* geometry_shader_code,
138 							   const glw::GLchar* tesselation_control_shader_code,
139 							   const glw::GLchar* tesselation_evaluation_shader_code,
140 							   const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names,
141 							   glw::GLuint n_varying_names)
142 {
143 	/* GL entry points */
144 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
145 
146 	/* Create shader objects and compile */
147 	if (0 != compute_shader_code)
148 	{
149 		m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
150 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
151 
152 		compile(m_compute_shader_id, compute_shader_code);
153 	}
154 
155 	if (0 != fragment_shader_code)
156 	{
157 		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
158 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
159 
160 		compile(m_fragment_shader_id, fragment_shader_code);
161 	}
162 
163 	if (0 != geometry_shader_code)
164 	{
165 		m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
166 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
167 
168 		compile(m_geometry_shader_id, geometry_shader_code);
169 	}
170 
171 	if (0 != tesselation_control_shader_code)
172 	{
173 		m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
174 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
175 
176 		compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
177 	}
178 
179 	if (0 != tesselation_evaluation_shader_code)
180 	{
181 		m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
182 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
183 
184 		compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
185 	}
186 
187 	if (0 != vertex_shader_code)
188 	{
189 		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
190 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
191 
192 		compile(m_vertex_shader_id, vertex_shader_code);
193 	}
194 
195 	/* Create program object */
196 	m_program_object_id = gl.createProgram();
197 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
198 
199 	/* Set up captyured varyings' names */
200 	if (0 != n_varying_names)
201 	{
202 		gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
203 		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
204 	}
205 
206 	/* Link program */
207 	link();
208 }
209 
210 /** Compile shader
211  *
212  * @param shader_id   Shader object id
213  * @param shader_code Shader source code
214  **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
216 {
217 	/* GL entry points */
218 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
219 
220 	/* Compilation status */
221 	glw::GLint status = GL_FALSE;
222 
223 	/* Set source code */
224 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
225 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
226 
227 	/* Compile */
228 	gl.compileShader(shader_id);
229 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
230 
231 	/* Get compilation status */
232 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
233 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
234 
235 	/* Log compilation error */
236 	if (GL_TRUE != status)
237 	{
238 		glw::GLint				 length = 0;
239 		std::vector<glw::GLchar> message;
240 
241 		/* Error log length */
242 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
243 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
244 
245 		/* Prepare storage */
246 		message.resize(length);
247 
248 		/* Get error log */
249 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
250 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
251 
252 		/* Log */
253 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
254 											<< &message[0] << "\nShader source\n"
255 											<< shader_code << tcu::TestLog::EndMessage;
256 
257 		TCU_FAIL("Failed to compile shader");
258 	}
259 }
260 
261 /** Attach shaders and link program
262  *
263  **/
link() const264 void Utils::programInfo::link() const
265 {
266 	/* GL entry points */
267 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
268 
269 	/* Link status */
270 	glw::GLint status = GL_FALSE;
271 
272 	/* Attach shaders */
273 	if (0 != m_compute_shader_id)
274 	{
275 		gl.attachShader(m_program_object_id, m_compute_shader_id);
276 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
277 	}
278 
279 	if (0 != m_fragment_shader_id)
280 	{
281 		gl.attachShader(m_program_object_id, m_fragment_shader_id);
282 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
283 	}
284 
285 	if (0 != m_geometry_shader_id)
286 	{
287 		gl.attachShader(m_program_object_id, m_geometry_shader_id);
288 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
289 	}
290 
291 	if (0 != m_tesselation_control_shader_id)
292 	{
293 		gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
294 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
295 	}
296 
297 	if (0 != m_tesselation_evaluation_shader_id)
298 	{
299 		gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
300 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
301 	}
302 
303 	if (0 != m_vertex_shader_id)
304 	{
305 		gl.attachShader(m_program_object_id, m_vertex_shader_id);
306 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
307 	}
308 
309 	/* Link */
310 	gl.linkProgram(m_program_object_id);
311 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
312 
313 	/* Get link status */
314 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
315 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
316 
317 	/* Log link error */
318 	if (GL_TRUE != status)
319 	{
320 		glw::GLint				 length = 0;
321 		std::vector<glw::GLchar> message;
322 
323 		/* Get error log length */
324 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
325 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
326 
327 		message.resize(length);
328 
329 		/* Get error log */
330 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
331 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
332 
333 		/* Log */
334 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
335 											<< &message[0] << tcu::TestLog::EndMessage;
336 
337 		TCU_FAIL("Failed to link program");
338 	}
339 }
340 
341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision
342  *  matrix types.
343  *
344  *  @param type Variable type to return base type for.
345  *
346  *  @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized.
347  **/
getBaseVariableType(_variable_type type)348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type)
349 {
350 	_variable_type result = VARIABLE_TYPE_UNKNOWN;
351 
352 	switch (type)
353 	{
354 	case VARIABLE_TYPE_BOOL:
355 	{
356 		result = VARIABLE_TYPE_BOOL;
357 
358 		break;
359 	}
360 
361 	case VARIABLE_TYPE_DOUBLE:
362 	case VARIABLE_TYPE_DMAT2:
363 	case VARIABLE_TYPE_DMAT2X3:
364 	case VARIABLE_TYPE_DMAT2X4:
365 	case VARIABLE_TYPE_DMAT3:
366 	case VARIABLE_TYPE_DMAT3X2:
367 	case VARIABLE_TYPE_DMAT3X4:
368 	case VARIABLE_TYPE_DMAT4:
369 	case VARIABLE_TYPE_DMAT4X2:
370 	case VARIABLE_TYPE_DMAT4X3:
371 	case VARIABLE_TYPE_DVEC2:
372 	case VARIABLE_TYPE_DVEC3:
373 	case VARIABLE_TYPE_DVEC4:
374 	{
375 		result = VARIABLE_TYPE_DOUBLE;
376 
377 		break;
378 	}
379 
380 	case VARIABLE_TYPE_INT:
381 	case VARIABLE_TYPE_IVEC2:
382 	case VARIABLE_TYPE_IVEC3:
383 	case VARIABLE_TYPE_IVEC4:
384 	{
385 		result = VARIABLE_TYPE_INT;
386 
387 		break;
388 	}
389 
390 	case VARIABLE_TYPE_UINT:
391 	case VARIABLE_TYPE_UVEC2:
392 	case VARIABLE_TYPE_UVEC3:
393 	case VARIABLE_TYPE_UVEC4:
394 	{
395 		result = VARIABLE_TYPE_UINT;
396 
397 		break;
398 	}
399 
400 	case VARIABLE_TYPE_FLOAT:
401 	case VARIABLE_TYPE_MAT2:
402 	case VARIABLE_TYPE_MAT2X3:
403 	case VARIABLE_TYPE_MAT2X4:
404 	case VARIABLE_TYPE_MAT3:
405 	case VARIABLE_TYPE_MAT3X2:
406 	case VARIABLE_TYPE_MAT3X4:
407 	case VARIABLE_TYPE_MAT4:
408 	case VARIABLE_TYPE_MAT4X2:
409 	case VARIABLE_TYPE_MAT4X3:
410 	case VARIABLE_TYPE_VEC2:
411 	case VARIABLE_TYPE_VEC3:
412 	case VARIABLE_TYPE_VEC4:
413 	{
414 		result = VARIABLE_TYPE_FLOAT;
415 
416 		break;
417 	}
418 
419 	default:
420 	{
421 		TCU_FAIL("Unrecognized variable type");
422 	}
423 	} /* switch (type) */
424 
425 	return result;
426 }
427 
428 /** Returns size (in bytes) of a single component of a base variable type.
429  *
430  *  @param type Base variable type to use for the query.
431  *
432  *  @return Requested value or 0 if @param type was not recognized.
433  **/
getBaseVariableTypeComponentSize(_variable_type type)434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type)
435 {
436 	unsigned int result = 0;
437 
438 	switch (type)
439 	{
440 	case VARIABLE_TYPE_BOOL:
441 		result = sizeof(bool);
442 		break;
443 	case VARIABLE_TYPE_DOUBLE:
444 		result = sizeof(double);
445 		break;
446 	case VARIABLE_TYPE_FLOAT:
447 		result = sizeof(float);
448 		break;
449 	case VARIABLE_TYPE_INT:
450 		result = sizeof(int);
451 		break;
452 	case VARIABLE_TYPE_UINT:
453 		result = sizeof(unsigned int);
454 		break;
455 
456 	default:
457 	{
458 		TCU_FAIL("Unrecognized variable type");
459 	}
460 	} /* switch (type) */
461 
462 	return result;
463 }
464 
465 /** Returns component, corresponding to user-specified index
466  *  (eg. index:0 corresponds to 'x', index:1 corresponds to 'y',
467  *  and so on.
468  *
469  *  @param index Component index.
470  *
471  *  @return As per description.
472  **/
getComponentAtIndex(unsigned int index)473 unsigned char Utils::getComponentAtIndex(unsigned int index)
474 {
475 	unsigned char result = '?';
476 
477 	switch (index)
478 	{
479 	case 0:
480 		result = 'x';
481 		break;
482 	case 1:
483 		result = 'y';
484 		break;
485 	case 2:
486 		result = 'z';
487 		break;
488 	case 3:
489 		result = 'w';
490 		break;
491 
492 	default:
493 	{
494 		TCU_FAIL("Unrecognized component index");
495 	}
496 	}
497 
498 	return result;
499 }
500 
501 /** Get _variable_type representing double-precision type with given dimmensions
502  *
503  * @param n_columns Number of columns
504  * @param n_row     Number of rows
505  *
506  * @return Corresponding _variable_type
507  **/
getDoubleVariableType(glw::GLuint n_columns,glw::GLuint n_rows)508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
509 {
510 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
511 
512 	static const _variable_type types[4][4] = {
513 		{ VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 },
514 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 },
515 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 },
516 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 }
517 	};
518 
519 	type = types[n_columns - 1][n_rows - 1];
520 
521 	return type;
522 }
523 
524 /** Returns a single-precision equivalent of a double-precision floating-point variable
525  *  type.
526  *
527  *  @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
528  *              are accepted.
529  *
530  *  @return Requested GLSL type.
531  **/
getFPVariableTypeStringForVariableType(_variable_type type)532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
533 {
534 	std::string result = "[?]";
535 
536 	switch (type)
537 	{
538 	case VARIABLE_TYPE_DOUBLE:
539 		result = "float";
540 		break;
541 	case VARIABLE_TYPE_DMAT2:
542 		result = "mat2";
543 		break;
544 	case VARIABLE_TYPE_DMAT2X3:
545 		result = "mat2x3";
546 		break;
547 	case VARIABLE_TYPE_DMAT2X4:
548 		result = "mat2x4";
549 		break;
550 	case VARIABLE_TYPE_DMAT3:
551 		result = "mat3";
552 		break;
553 	case VARIABLE_TYPE_DMAT3X2:
554 		result = "mat3x2";
555 		break;
556 	case VARIABLE_TYPE_DMAT3X4:
557 		result = "mat3x4";
558 		break;
559 	case VARIABLE_TYPE_DMAT4:
560 		result = "mat4";
561 		break;
562 	case VARIABLE_TYPE_DMAT4X2:
563 		result = "mat4x2";
564 		break;
565 	case VARIABLE_TYPE_DMAT4X3:
566 		result = "mat4x3";
567 		break;
568 	case VARIABLE_TYPE_DVEC2:
569 		result = "vec2";
570 		break;
571 	case VARIABLE_TYPE_DVEC3:
572 		result = "vec3";
573 		break;
574 	case VARIABLE_TYPE_DVEC4:
575 		result = "vec4";
576 		break;
577 
578 	default:
579 	{
580 		TCU_FAIL("Unrecognized variable type");
581 	}
582 	}; /* switch (type) */
583 
584 	return result;
585 }
586 
587 /** Returns GL data type enum corresponding to user-provided base variable type.
588  *
589  *  @param type Base variable type to return corresponding GLenum value for.
590  *
591  *  @return Corresponding GLenum value or GL_NONE if the input value was not
592  *          recognized.
593  **/
getGLDataTypeOfBaseVariableType(_variable_type type)594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
595 {
596 	glw::GLenum result = GL_NONE;
597 
598 	switch (type)
599 	{
600 	case VARIABLE_TYPE_BOOL:
601 		result = GL_BOOL;
602 		break;
603 	case VARIABLE_TYPE_DOUBLE:
604 		result = GL_DOUBLE;
605 		break;
606 	case VARIABLE_TYPE_FLOAT:
607 		result = GL_FLOAT;
608 		break;
609 	case VARIABLE_TYPE_INT:
610 		result = GL_INT;
611 		break;
612 	case VARIABLE_TYPE_UINT:
613 		result = GL_UNSIGNED_INT;
614 		break;
615 
616 	default:
617 	{
618 		TCU_FAIL("Unrecognized variable type");
619 	}
620 	}
621 
622 	return result;
623 }
624 
625 /** Return GLenum representing given <type>
626  *
627  * @param type Type of variable
628  *
629  * @return GL enumeration
630  **/
getGLDataTypeOfVariableType(_variable_type type)631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
632 {
633 	glw::GLenum result = GL_NONE;
634 
635 	switch (type)
636 	{
637 	case VARIABLE_TYPE_BOOL:
638 		result = GL_BOOL;
639 		break;
640 	case VARIABLE_TYPE_DOUBLE:
641 		result = GL_DOUBLE;
642 		break;
643 	case VARIABLE_TYPE_DMAT2:
644 		result = GL_DOUBLE_MAT2;
645 		break;
646 	case VARIABLE_TYPE_DMAT2X3:
647 		result = GL_DOUBLE_MAT2x3;
648 		break;
649 	case VARIABLE_TYPE_DMAT2X4:
650 		result = GL_DOUBLE_MAT2x4;
651 		break;
652 	case VARIABLE_TYPE_DMAT3:
653 		result = GL_DOUBLE_MAT3;
654 		break;
655 	case VARIABLE_TYPE_DMAT3X2:
656 		result = GL_DOUBLE_MAT3x2;
657 		break;
658 	case VARIABLE_TYPE_DMAT3X4:
659 		result = GL_DOUBLE_MAT3x4;
660 		break;
661 	case VARIABLE_TYPE_DMAT4:
662 		result = GL_DOUBLE_MAT4;
663 		break;
664 	case VARIABLE_TYPE_DMAT4X2:
665 		result = GL_DOUBLE_MAT4x2;
666 		break;
667 	case VARIABLE_TYPE_DMAT4X3:
668 		result = GL_DOUBLE_MAT4x3;
669 		break;
670 	case VARIABLE_TYPE_DVEC2:
671 		result = GL_DOUBLE_VEC2;
672 		break;
673 	case VARIABLE_TYPE_DVEC3:
674 		result = GL_DOUBLE_VEC3;
675 		break;
676 	case VARIABLE_TYPE_DVEC4:
677 		result = GL_DOUBLE_VEC4;
678 		break;
679 	case VARIABLE_TYPE_FLOAT:
680 		result = GL_FLOAT;
681 		break;
682 	case VARIABLE_TYPE_INT:
683 		result = GL_INT;
684 		break;
685 	case VARIABLE_TYPE_IVEC2:
686 		result = GL_INT_VEC2;
687 		break;
688 	case VARIABLE_TYPE_IVEC3:
689 		result = GL_INT_VEC3;
690 		break;
691 	case VARIABLE_TYPE_IVEC4:
692 		result = GL_INT_VEC4;
693 		break;
694 	case VARIABLE_TYPE_MAT2:
695 		result = GL_FLOAT_MAT2;
696 		break;
697 	case VARIABLE_TYPE_MAT2X3:
698 		result = GL_FLOAT_MAT2x3;
699 		break;
700 	case VARIABLE_TYPE_MAT2X4:
701 		result = GL_FLOAT_MAT2x4;
702 		break;
703 	case VARIABLE_TYPE_MAT3:
704 		result = GL_FLOAT_MAT3;
705 		break;
706 	case VARIABLE_TYPE_MAT3X2:
707 		result = GL_FLOAT_MAT3x2;
708 		break;
709 	case VARIABLE_TYPE_MAT3X4:
710 		result = GL_FLOAT_MAT3x4;
711 		break;
712 	case VARIABLE_TYPE_MAT4:
713 		result = GL_FLOAT_MAT4;
714 		break;
715 	case VARIABLE_TYPE_MAT4X2:
716 		result = GL_FLOAT_MAT4x2;
717 		break;
718 	case VARIABLE_TYPE_MAT4X3:
719 		result = GL_FLOAT_MAT4x3;
720 		break;
721 	case VARIABLE_TYPE_UINT:
722 		result = GL_UNSIGNED_INT;
723 		break;
724 	case VARIABLE_TYPE_UVEC2:
725 		result = GL_UNSIGNED_INT_VEC2;
726 		break;
727 	case VARIABLE_TYPE_UVEC3:
728 		result = GL_UNSIGNED_INT_VEC3;
729 		break;
730 	case VARIABLE_TYPE_UVEC4:
731 		result = GL_UNSIGNED_INT_VEC4;
732 		break;
733 	case VARIABLE_TYPE_VEC2:
734 		result = GL_FLOAT_VEC2;
735 		break;
736 	case VARIABLE_TYPE_VEC3:
737 		result = GL_FLOAT_VEC3;
738 		break;
739 	case VARIABLE_TYPE_VEC4:
740 		result = GL_FLOAT_VEC4;
741 		break;
742 
743 	default:
744 	{
745 		TCU_FAIL("Unrecognized variable type");
746 	}
747 	}
748 
749 	return result;
750 }
751 
752 /** Get _variable_type representing integer type with given dimmensions
753  *
754  * @param n_columns Number of columns
755  * @param n_row     Number of rows
756  *
757  * @return Corresponding _variable_type
758  **/
getIntVariableType(glw::GLuint n_columns,glw::GLuint n_rows)759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
760 {
761 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
762 
763 	static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
764 											 VARIABLE_TYPE_IVEC4 };
765 
766 	if (1 != n_columns)
767 	{
768 		TCU_FAIL("Not implemented");
769 	}
770 	else
771 	{
772 		type = types[n_rows - 1];
773 	}
774 
775 	return type;
776 }
777 
778 /** Returns te number of components that variables defined with user-specified type
779  *  support. For matrix types, total amount of values accessible for the type will be
780  *  returned.
781  *
782  *  @param type Variable type to return the described vale for.
783  *
784  *  @return As per description or 0 if @param type was not recognized.
785  */
getNumberOfComponentsForVariableType(_variable_type type)786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
787 {
788 	unsigned int result = 0;
789 
790 	switch (type)
791 	{
792 	case VARIABLE_TYPE_BOOL:
793 	case VARIABLE_TYPE_DOUBLE:
794 	case VARIABLE_TYPE_FLOAT:
795 	case VARIABLE_TYPE_INT:
796 	case VARIABLE_TYPE_UINT:
797 	{
798 		result = 1;
799 
800 		break;
801 	}
802 
803 	case VARIABLE_TYPE_DVEC2:
804 	case VARIABLE_TYPE_IVEC2:
805 	case VARIABLE_TYPE_UVEC2:
806 	case VARIABLE_TYPE_VEC2:
807 	{
808 		result = 2;
809 
810 		break;
811 	}
812 
813 	case VARIABLE_TYPE_DVEC3:
814 	case VARIABLE_TYPE_IVEC3:
815 	case VARIABLE_TYPE_UVEC3:
816 	case VARIABLE_TYPE_VEC3:
817 	{
818 		result = 3;
819 
820 		break;
821 	}
822 
823 	case VARIABLE_TYPE_DVEC4:
824 	case VARIABLE_TYPE_IVEC4:
825 	case VARIABLE_TYPE_UVEC4:
826 	case VARIABLE_TYPE_VEC4:
827 	{
828 		result = 4;
829 
830 		break;
831 	}
832 
833 	case VARIABLE_TYPE_DMAT2:
834 	case VARIABLE_TYPE_MAT2:
835 	{
836 		result = 2 * 2;
837 
838 		break;
839 	}
840 
841 	case VARIABLE_TYPE_DMAT2X3:
842 	case VARIABLE_TYPE_DMAT3X2:
843 	case VARIABLE_TYPE_MAT2X3:
844 	case VARIABLE_TYPE_MAT3X2:
845 	{
846 		result = 2 * 3;
847 
848 		break;
849 	}
850 
851 	case VARIABLE_TYPE_DMAT2X4:
852 	case VARIABLE_TYPE_DMAT4X2:
853 	case VARIABLE_TYPE_MAT2X4:
854 	case VARIABLE_TYPE_MAT4X2:
855 	{
856 		result = 2 * 4;
857 
858 		break;
859 	}
860 
861 	case VARIABLE_TYPE_DMAT3:
862 	case VARIABLE_TYPE_MAT3:
863 	{
864 		result = 3 * 3;
865 
866 		break;
867 	}
868 
869 	case VARIABLE_TYPE_DMAT3X4:
870 	case VARIABLE_TYPE_DMAT4X3:
871 	case VARIABLE_TYPE_MAT3X4:
872 	case VARIABLE_TYPE_MAT4X3:
873 	{
874 		result = 3 * 4;
875 
876 		break;
877 	}
878 
879 	case VARIABLE_TYPE_DMAT4:
880 	case VARIABLE_TYPE_MAT4:
881 	{
882 		result = 4 * 4;
883 
884 		break;
885 	}
886 
887 	default:
888 	{
889 		TCU_FAIL("Unrecognized type");
890 	}
891 	} /* switch (type) */
892 
893 	return result;
894 }
895 
896 /** Returns number of columns user-specified matrix variable type describes.
897  *
898  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
899  *              values are valid.
900  *
901  *  @return As per description.
902  **/
getNumberOfColumnsForVariableType(_variable_type type)903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
904 {
905 	unsigned int result = 0;
906 
907 	switch (type)
908 	{
909 	case VARIABLE_TYPE_BOOL:
910 	case VARIABLE_TYPE_DOUBLE:
911 	case VARIABLE_TYPE_FLOAT:
912 	case VARIABLE_TYPE_INT:
913 	case VARIABLE_TYPE_UINT:
914 	case VARIABLE_TYPE_DVEC2:
915 	case VARIABLE_TYPE_IVEC2:
916 	case VARIABLE_TYPE_UVEC2:
917 	case VARIABLE_TYPE_VEC2:
918 	case VARIABLE_TYPE_DVEC3:
919 	case VARIABLE_TYPE_IVEC3:
920 	case VARIABLE_TYPE_UVEC3:
921 	case VARIABLE_TYPE_VEC3:
922 	case VARIABLE_TYPE_DVEC4:
923 	case VARIABLE_TYPE_IVEC4:
924 	case VARIABLE_TYPE_UVEC4:
925 	case VARIABLE_TYPE_VEC4:
926 	{
927 		result = 1;
928 
929 		break;
930 	}
931 
932 	case VARIABLE_TYPE_DMAT2:
933 	case VARIABLE_TYPE_DMAT2X3:
934 	case VARIABLE_TYPE_DMAT2X4:
935 	case VARIABLE_TYPE_MAT2:
936 	case VARIABLE_TYPE_MAT2X3:
937 	case VARIABLE_TYPE_MAT2X4:
938 	{
939 		result = 2;
940 
941 		break;
942 	}
943 
944 	case VARIABLE_TYPE_DMAT3:
945 	case VARIABLE_TYPE_DMAT3X2:
946 	case VARIABLE_TYPE_DMAT3X4:
947 	case VARIABLE_TYPE_MAT3:
948 	case VARIABLE_TYPE_MAT3X2:
949 	case VARIABLE_TYPE_MAT3X4:
950 	{
951 		result = 3;
952 
953 		break;
954 	}
955 
956 	case VARIABLE_TYPE_DMAT4:
957 	case VARIABLE_TYPE_DMAT4X2:
958 	case VARIABLE_TYPE_DMAT4X3:
959 	case VARIABLE_TYPE_MAT4:
960 	case VARIABLE_TYPE_MAT4X2:
961 	case VARIABLE_TYPE_MAT4X3:
962 	{
963 		result = 4;
964 
965 		break;
966 	}
967 
968 	default:
969 	{
970 		TCU_FAIL("Unrecognized type");
971 	}
972 	} /* switch (type) */
973 
974 	return result;
975 }
976 
977 /** Returns maximum number of uniform locations taken by user-specified double-precision
978  *  variable type.
979  *
980  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
981  *
982  *  @return As per description.
983  **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
985 {
986 	unsigned int result = 0;
987 
988 	switch (type)
989 	{
990 	case VARIABLE_TYPE_DOUBLE:
991 		result = 1;
992 		break;
993 	case VARIABLE_TYPE_DVEC2:
994 		result = 1;
995 		break;
996 	case VARIABLE_TYPE_DVEC3:
997 		result = 2;
998 		break;
999 	case VARIABLE_TYPE_DVEC4:
1000 		result = 2;
1001 		break;
1002 	case VARIABLE_TYPE_DMAT2:
1003 		result = 2;
1004 		break;
1005 	case VARIABLE_TYPE_DMAT2X3:
1006 		result = 6;
1007 		break;
1008 	case VARIABLE_TYPE_DMAT2X4:
1009 		result = 8;
1010 		break;
1011 	case VARIABLE_TYPE_DMAT3:
1012 		result = 6;
1013 		break;
1014 	case VARIABLE_TYPE_DMAT3X2:
1015 		result = 4;
1016 		break;
1017 	case VARIABLE_TYPE_DMAT3X4:
1018 		result = 8;
1019 		break;
1020 	case VARIABLE_TYPE_DMAT4:
1021 		result = 8;
1022 		break;
1023 	case VARIABLE_TYPE_DMAT4X2:
1024 		result = 4;
1025 		break;
1026 	case VARIABLE_TYPE_DMAT4X3:
1027 		result = 6;
1028 		break;
1029 
1030 	default:
1031 	{
1032 		TCU_FAIL("Unrecognized type");
1033 	}
1034 	} /* switch (type) */
1035 
1036 	return result;
1037 }
1038 
1039 /** Get number of rows for given variable type
1040  *
1041  * @param type Type of variable
1042  *
1043  * @return Number of rows
1044  **/
getNumberOfRowsForVariableType(_variable_type type)1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1046 {
1047 	unsigned int result = 0;
1048 
1049 	switch (type)
1050 	{
1051 	case VARIABLE_TYPE_BOOL:
1052 	case VARIABLE_TYPE_DOUBLE:
1053 	case VARIABLE_TYPE_FLOAT:
1054 	case VARIABLE_TYPE_INT:
1055 	case VARIABLE_TYPE_UINT:
1056 	{
1057 		result = 1;
1058 
1059 		break;
1060 	}
1061 
1062 	case VARIABLE_TYPE_DVEC2:
1063 	case VARIABLE_TYPE_IVEC2:
1064 	case VARIABLE_TYPE_UVEC2:
1065 	case VARIABLE_TYPE_VEC2:
1066 	case VARIABLE_TYPE_DMAT2:
1067 	case VARIABLE_TYPE_DMAT3X2:
1068 	case VARIABLE_TYPE_DMAT4X2:
1069 	case VARIABLE_TYPE_MAT2:
1070 	case VARIABLE_TYPE_MAT3X2:
1071 	case VARIABLE_TYPE_MAT4X2:
1072 	{
1073 		result = 2;
1074 
1075 		break;
1076 	}
1077 
1078 	case VARIABLE_TYPE_DVEC3:
1079 	case VARIABLE_TYPE_IVEC3:
1080 	case VARIABLE_TYPE_UVEC3:
1081 	case VARIABLE_TYPE_VEC3:
1082 	case VARIABLE_TYPE_DMAT2X3:
1083 	case VARIABLE_TYPE_DMAT3:
1084 	case VARIABLE_TYPE_DMAT4X3:
1085 	case VARIABLE_TYPE_MAT2X3:
1086 	case VARIABLE_TYPE_MAT3:
1087 	case VARIABLE_TYPE_MAT4X3:
1088 	{
1089 		result = 3;
1090 
1091 		break;
1092 	}
1093 
1094 	case VARIABLE_TYPE_DVEC4:
1095 	case VARIABLE_TYPE_IVEC4:
1096 	case VARIABLE_TYPE_UVEC4:
1097 	case VARIABLE_TYPE_VEC4:
1098 	case VARIABLE_TYPE_DMAT2X4:
1099 	case VARIABLE_TYPE_DMAT3X4:
1100 	case VARIABLE_TYPE_DMAT4:
1101 	case VARIABLE_TYPE_MAT2X4:
1102 	case VARIABLE_TYPE_MAT3X4:
1103 	case VARIABLE_TYPE_MAT4:
1104 	{
1105 		result = 4;
1106 
1107 		break;
1108 	}
1109 
1110 	default:
1111 	{
1112 		TCU_FAIL("Unrecognized type");
1113 	}
1114 	} /* switch (type) */
1115 
1116 	return result;
1117 }
1118 
1119 /** Returns variable type of a matrix constructed by multiplying two matrices.
1120  *
1121  *  @param type_matrix_a L-side matrix type.
1122  *  @param type_matrix_b R-side matrix type.
1123  *
1124  *  @return As per description.
1125  **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,_variable_type type_matrix_b)1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1127 																	 _variable_type type_matrix_b)
1128 {
1129 	const unsigned int	n_a_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1130 	const unsigned int	n_a_components   = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1131 	const unsigned int	n_a_rows		   = n_a_components / n_a_columns;
1132 	const unsigned int	n_b_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1133 	const unsigned int	n_result_columns = n_b_columns;
1134 	const unsigned int	n_result_rows	= n_a_rows;
1135 	Utils::_variable_type result;
1136 
1137 	switch (n_result_columns)
1138 	{
1139 	case 2:
1140 	{
1141 		switch (n_result_rows)
1142 		{
1143 		case 2:
1144 			result = VARIABLE_TYPE_DMAT2;
1145 			break;
1146 		case 3:
1147 			result = VARIABLE_TYPE_DMAT2X3;
1148 			break;
1149 		case 4:
1150 			result = VARIABLE_TYPE_DMAT2X4;
1151 			break;
1152 
1153 		default:
1154 		{
1155 			TCU_FAIL("Unrecognized amount of rows in result variable");
1156 		}
1157 		} /* switch (n_result_rows) */
1158 
1159 		break;
1160 	} /* case 2: */
1161 
1162 	case 3:
1163 	{
1164 		switch (n_result_rows)
1165 		{
1166 		case 2:
1167 			result = VARIABLE_TYPE_DMAT3X2;
1168 			break;
1169 		case 3:
1170 			result = VARIABLE_TYPE_DMAT3;
1171 			break;
1172 		case 4:
1173 			result = VARIABLE_TYPE_DMAT3X4;
1174 			break;
1175 
1176 		default:
1177 		{
1178 			TCU_FAIL("Unrecognized amount of rows in result variable");
1179 		}
1180 		} /* switch (n_result_rows) */
1181 
1182 		break;
1183 	} /* case 3: */
1184 
1185 	case 4:
1186 	{
1187 		switch (n_result_rows)
1188 		{
1189 		case 2:
1190 			result = VARIABLE_TYPE_DMAT4X2;
1191 			break;
1192 		case 3:
1193 			result = VARIABLE_TYPE_DMAT4X3;
1194 			break;
1195 		case 4:
1196 			result = VARIABLE_TYPE_DMAT4;
1197 			break;
1198 
1199 		default:
1200 		{
1201 			TCU_FAIL("Unrecognized amount of rows in result variable");
1202 		}
1203 		} /* switch (n_result_rows) */
1204 
1205 		break;
1206 	} /* case 4: */
1207 
1208 	default:
1209 	{
1210 		TCU_FAIL("Unrecognized amount of columns in result variable");
1211 	}
1212 	} /* switch (n_result_columns) */
1213 
1214 	/* Done */
1215 	return result;
1216 }
1217 
1218 /** Returns a string holding the value represented by user-provided variable, for which
1219  *  the data are represented in @param type variable type.
1220  *
1221  *  @return As per description.
1222  **/
getStringForVariableTypeValue(_variable_type type,const unsigned char * data_ptr)1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)
1224 {
1225 	std::stringstream result_sstream;
1226 
1227 	switch (type)
1228 	{
1229 	case VARIABLE_TYPE_BOOL:
1230 		result_sstream << *((bool*)data_ptr);
1231 		break;
1232 	case VARIABLE_TYPE_DOUBLE:
1233 		result_sstream << *((double*)data_ptr);
1234 		break;
1235 	case VARIABLE_TYPE_FLOAT:
1236 		result_sstream << *((float*)data_ptr);
1237 		break;
1238 	case VARIABLE_TYPE_INT:
1239 		result_sstream << *((int*)data_ptr);
1240 		break;
1241 	case VARIABLE_TYPE_UINT:
1242 		result_sstream << *((unsigned int*)data_ptr);
1243 		break;
1244 
1245 	default:
1246 	{
1247 		TCU_FAIL("Unrecognized variable type requested");
1248 	}
1249 	} /* switch (type) */
1250 
1251 	return result_sstream.str();
1252 }
1253 
1254 /** Returns variable type of a transposed matrix of user-specified variable type.
1255  *
1256  *  @param type Variable type of the matrix to be transposed.
1257  *
1258  *  @return Transposed matrix variable type.
1259  **/
getTransposedMatrixVariableType(Utils::_variable_type type)1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1261 {
1262 	Utils::_variable_type result;
1263 
1264 	switch (type)
1265 	{
1266 	case VARIABLE_TYPE_DMAT2:
1267 		result = VARIABLE_TYPE_DMAT2;
1268 		break;
1269 	case VARIABLE_TYPE_DMAT2X3:
1270 		result = VARIABLE_TYPE_DMAT3X2;
1271 		break;
1272 	case VARIABLE_TYPE_DMAT2X4:
1273 		result = VARIABLE_TYPE_DMAT4X2;
1274 		break;
1275 	case VARIABLE_TYPE_DMAT3:
1276 		result = VARIABLE_TYPE_DMAT3;
1277 		break;
1278 	case VARIABLE_TYPE_DMAT3X2:
1279 		result = VARIABLE_TYPE_DMAT2X3;
1280 		break;
1281 	case VARIABLE_TYPE_DMAT3X4:
1282 		result = VARIABLE_TYPE_DMAT4X3;
1283 		break;
1284 	case VARIABLE_TYPE_DMAT4:
1285 		result = VARIABLE_TYPE_DMAT4;
1286 		break;
1287 	case VARIABLE_TYPE_DMAT4X2:
1288 		result = VARIABLE_TYPE_DMAT2X4;
1289 		break;
1290 	case VARIABLE_TYPE_DMAT4X3:
1291 		result = VARIABLE_TYPE_DMAT3X4;
1292 		break;
1293 
1294 	default:
1295 	{
1296 		TCU_FAIL("Unrecognized double-precision matrix variable type.");
1297 	}
1298 	} /* switch (type) */
1299 
1300 	return result;
1301 }
1302 
1303 /** Get _variable_type representing unsigned integer type with given dimmensions
1304  *
1305  * @param n_columns Number of columns
1306  * @param n_row     Number of rows
1307  *
1308  * @return Corresponding _variable_type
1309  **/
getUintVariableType(glw::GLuint n_columns,glw::GLuint n_rows)1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1311 {
1312 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1313 
1314 	static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1315 											 VARIABLE_TYPE_UVEC4 };
1316 
1317 	if (1 != n_columns)
1318 	{
1319 		TCU_FAIL("Not implemented");
1320 	}
1321 	else
1322 	{
1323 		type = types[n_rows - 1];
1324 	}
1325 
1326 	return type;
1327 }
1328 
1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1330  *  variable type.
1331  *
1332  *  @param type Variable type to use for the query.
1333  *
1334  *  @return Requested GLSL keyword or [?] if @param type was not recognized.
1335  **/
getVariableTypeString(_variable_type type)1336 std::string Utils::getVariableTypeString(_variable_type type)
1337 {
1338 	std::string result = "[?]";
1339 
1340 	switch (type)
1341 	{
1342 	case VARIABLE_TYPE_BOOL:
1343 		result = "bool";
1344 		break;
1345 	case VARIABLE_TYPE_BVEC2:
1346 		result = "bvec2";
1347 		break;
1348 	case VARIABLE_TYPE_BVEC3:
1349 		result = "bvec3";
1350 		break;
1351 	case VARIABLE_TYPE_BVEC4:
1352 		result = "bvec4";
1353 		break;
1354 	case VARIABLE_TYPE_DOUBLE:
1355 		result = "double";
1356 		break;
1357 	case VARIABLE_TYPE_DMAT2:
1358 		result = "dmat2";
1359 		break;
1360 	case VARIABLE_TYPE_DMAT2X3:
1361 		result = "dmat2x3";
1362 		break;
1363 	case VARIABLE_TYPE_DMAT2X4:
1364 		result = "dmat2x4";
1365 		break;
1366 	case VARIABLE_TYPE_DMAT3:
1367 		result = "dmat3";
1368 		break;
1369 	case VARIABLE_TYPE_DMAT3X2:
1370 		result = "dmat3x2";
1371 		break;
1372 	case VARIABLE_TYPE_DMAT3X4:
1373 		result = "dmat3x4";
1374 		break;
1375 	case VARIABLE_TYPE_DMAT4:
1376 		result = "dmat4";
1377 		break;
1378 	case VARIABLE_TYPE_DMAT4X2:
1379 		result = "dmat4x2";
1380 		break;
1381 	case VARIABLE_TYPE_DMAT4X3:
1382 		result = "dmat4x3";
1383 		break;
1384 	case VARIABLE_TYPE_DVEC2:
1385 		result = "dvec2";
1386 		break;
1387 	case VARIABLE_TYPE_DVEC3:
1388 		result = "dvec3";
1389 		break;
1390 	case VARIABLE_TYPE_DVEC4:
1391 		result = "dvec4";
1392 		break;
1393 	case VARIABLE_TYPE_FLOAT:
1394 		result = "float";
1395 		break;
1396 	case VARIABLE_TYPE_INT:
1397 		result = "int";
1398 		break;
1399 	case VARIABLE_TYPE_IVEC2:
1400 		result = "ivec2";
1401 		break;
1402 	case VARIABLE_TYPE_IVEC3:
1403 		result = "ivec3";
1404 		break;
1405 	case VARIABLE_TYPE_IVEC4:
1406 		result = "ivec4";
1407 		break;
1408 	case VARIABLE_TYPE_MAT2:
1409 		result = "mat2";
1410 		break;
1411 	case VARIABLE_TYPE_MAT2X3:
1412 		result = "mat2x3";
1413 		break;
1414 	case VARIABLE_TYPE_MAT2X4:
1415 		result = "mat2x4";
1416 		break;
1417 	case VARIABLE_TYPE_MAT3:
1418 		result = "mat3";
1419 		break;
1420 	case VARIABLE_TYPE_MAT3X2:
1421 		result = "mat3x2";
1422 		break;
1423 	case VARIABLE_TYPE_MAT3X4:
1424 		result = "mat3x4";
1425 		break;
1426 	case VARIABLE_TYPE_MAT4:
1427 		result = "mat4";
1428 		break;
1429 	case VARIABLE_TYPE_MAT4X2:
1430 		result = "mat4x2";
1431 		break;
1432 	case VARIABLE_TYPE_MAT4X3:
1433 		result = "mat4x3";
1434 		break;
1435 	case VARIABLE_TYPE_UINT:
1436 		result = "uint";
1437 		break;
1438 	case VARIABLE_TYPE_UVEC2:
1439 		result = "uvec2";
1440 		break;
1441 	case VARIABLE_TYPE_UVEC3:
1442 		result = "uvec3";
1443 		break;
1444 	case VARIABLE_TYPE_UVEC4:
1445 		result = "uvec4";
1446 		break;
1447 	case VARIABLE_TYPE_VEC2:
1448 		result = "vec2";
1449 		break;
1450 	case VARIABLE_TYPE_VEC3:
1451 		result = "vec3";
1452 		break;
1453 	case VARIABLE_TYPE_VEC4:
1454 		result = "vec4";
1455 		break;
1456 
1457 	default:
1458 	{
1459 		TCU_FAIL("Unrecognized variable type");
1460 	}
1461 	}; /* switch (type) */
1462 
1463 	return result;
1464 }
1465 
1466 /** Check if GL context meets version requirements
1467  *
1468  * @param gl             Functions
1469  * @param required_major Minimum required MAJOR_VERSION
1470  * @param required_minor Minimum required MINOR_VERSION
1471  *
1472  * @return true if GL context version is at least as requested, false otherwise
1473  **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
1475 {
1476 	glw::GLint major = 0;
1477 	glw::GLint minor = 0;
1478 
1479 	gl.getIntegerv(GL_MAJOR_VERSION, &major);
1480 	gl.getIntegerv(GL_MINOR_VERSION, &minor);
1481 
1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483 
1484 	if (major > required_major)
1485 	{
1486 		/* Major is higher than required one */
1487 		return true;
1488 	}
1489 	else if (major == required_major)
1490 	{
1491 		if (minor >= required_minor)
1492 		{
1493 			/* Major is equal to required one */
1494 			/* Minor is higher than or equal to required one */
1495 			return true;
1496 		}
1497 		else
1498 		{
1499 			/* Major is equal to required one */
1500 			/* Minor is lower than required one */
1501 			return false;
1502 		}
1503 	}
1504 	else
1505 	{
1506 		/* Major is lower than required one */
1507 		return false;
1508 	}
1509 }
1510 
1511 /** Tells whether user-specified variable type corresponds to a matrix type.
1512  *
1513  *  @param type Variable type to use for the query.
1514  *
1515  *  @return true if the variable type describes a matrix, false otherwise.
1516  **/
isMatrixVariableType(_variable_type type)1517 bool Utils::isMatrixVariableType(_variable_type type)
1518 {
1519 	return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1520 			type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1521 			type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1522 			type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1523 			type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1524 			type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1525 }
1526 
1527 /** Tells whether user-specified variable type is scalar.
1528  *
1529  *  @return true if @param type is a scalar variable type, false otherwise.
1530  **/
isScalarVariableType(_variable_type type)1531 bool Utils::isScalarVariableType(_variable_type type)
1532 {
1533 	bool result = false;
1534 
1535 	switch (type)
1536 	{
1537 	case VARIABLE_TYPE_BOOL:
1538 		result = true;
1539 		break;
1540 	case VARIABLE_TYPE_DOUBLE:
1541 		result = true;
1542 		break;
1543 	case VARIABLE_TYPE_FLOAT:
1544 		result = true;
1545 		break;
1546 	case VARIABLE_TYPE_INT:
1547 		result = true;
1548 		break;
1549 	case VARIABLE_TYPE_UINT:
1550 		result = true;
1551 		break;
1552 	default:
1553 		break;
1554 	}; /* switch (type) */
1555 
1556 	return result;
1557 }
1558 
1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1560  *
1561  * @param token           Token string
1562  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1563  * @param text            String that will be used as replacement for <token>
1564  * @param string          String to work on
1565  **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
1567 						 std::string& string)
1568 {
1569 	const size_t text_length	= strlen(text);
1570 	const size_t token_length   = strlen(token);
1571 	const size_t token_position = string.find(token, search_position);
1572 
1573 	string.replace(token_position, token_length, text, text_length);
1574 
1575 	search_position = token_position + text_length;
1576 }
1577 
1578 /** Constructor.
1579  *
1580  *  @param context Rendering context.
1581  *
1582  **/
GPUShaderFP64Test1(deqp::Context & context)1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context)
1584 	: TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision "
1585 								  "float uniform support & glUniform*() / glUniformMatrix*() API "
1586 								  " are reported correctly.")
1587 	, m_has_test_passed(true)
1588 	, m_po_bool_arr_uniform_location(0)
1589 	, m_po_bool_uniform_location(0)
1590 	, m_po_bvec2_arr_uniform_location(0)
1591 	, m_po_bvec2_uniform_location(0)
1592 	, m_po_bvec3_arr_uniform_location(0)
1593 	, m_po_bvec3_uniform_location(0)
1594 	, m_po_bvec4_arr_uniform_location(0)
1595 	, m_po_bvec4_uniform_location(0)
1596 	, m_po_dmat2_arr_uniform_location(0)
1597 	, m_po_dmat2_uniform_location(0)
1598 	, m_po_dmat2x3_arr_uniform_location(0)
1599 	, m_po_dmat2x3_uniform_location(0)
1600 	, m_po_dmat2x4_arr_uniform_location(0)
1601 	, m_po_dmat2x4_uniform_location(0)
1602 	, m_po_dmat3_arr_uniform_location(0)
1603 	, m_po_dmat3_uniform_location(0)
1604 	, m_po_dmat3x2_arr_uniform_location(0)
1605 	, m_po_dmat3x2_uniform_location(0)
1606 	, m_po_dmat3x4_arr_uniform_location(0)
1607 	, m_po_dmat3x4_uniform_location(0)
1608 	, m_po_dmat4_arr_uniform_location(0)
1609 	, m_po_dmat4_uniform_location(0)
1610 	, m_po_dmat4x2_arr_uniform_location(0)
1611 	, m_po_dmat4x2_uniform_location(0)
1612 	, m_po_dmat4x3_arr_uniform_location(0)
1613 	, m_po_dmat4x3_uniform_location(0)
1614 	, m_po_double_arr_uniform_location(0)
1615 	, m_po_double_uniform_location(0)
1616 	, m_po_dvec2_arr_uniform_location(0)
1617 	, m_po_dvec2_uniform_location(0)
1618 	, m_po_dvec3_arr_uniform_location(0)
1619 	, m_po_dvec3_uniform_location(0)
1620 	, m_po_dvec4_arr_uniform_location(0)
1621 	, m_po_dvec4_uniform_location(0)
1622 	, m_po_float_arr_uniform_location(0)
1623 	, m_po_float_uniform_location(0)
1624 	, m_po_int_arr_uniform_location(0)
1625 	, m_po_int_uniform_location(0)
1626 	, m_po_ivec2_arr_uniform_location(0)
1627 	, m_po_ivec2_uniform_location(0)
1628 	, m_po_ivec3_arr_uniform_location(0)
1629 	, m_po_ivec3_uniform_location(0)
1630 	, m_po_ivec4_arr_uniform_location(0)
1631 	, m_po_ivec4_uniform_location(0)
1632 	, m_po_sampler_uniform_location(0)
1633 	, m_po_uint_arr_uniform_location(0)
1634 	, m_po_uint_uniform_location(0)
1635 	, m_po_uvec2_arr_uniform_location(0)
1636 	, m_po_uvec2_uniform_location(0)
1637 	, m_po_uvec3_arr_uniform_location(0)
1638 	, m_po_uvec3_uniform_location(0)
1639 	, m_po_uvec4_arr_uniform_location(0)
1640 	, m_po_uvec4_uniform_location(0)
1641 	, m_po_vec2_arr_uniform_location(0)
1642 	, m_po_vec2_uniform_location(0)
1643 	, m_po_vec3_arr_uniform_location(0)
1644 	, m_po_vec3_uniform_location(0)
1645 	, m_po_vec4_arr_uniform_location(0)
1646 	, m_po_vec4_uniform_location(0)
1647 	, m_po_id(0)
1648 	, m_vs_id(0)
1649 {
1650 	/* Left blank intentionally */
1651 }
1652 
1653 /** Deinitializes all GL objects that may have been created during
1654  *  test execution.
1655  **/
deinit()1656 void GPUShaderFP64Test1::deinit()
1657 {
1658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1659 
1660 	if (m_po_id != 0)
1661 	{
1662 		gl.deleteProgram(m_po_id);
1663 
1664 		m_po_id = 0;
1665 	}
1666 
1667 	if (m_vs_id != 0)
1668 	{
1669 		gl.deleteShader(m_vs_id);
1670 
1671 		m_vs_id = 0;
1672 	}
1673 }
1674 
1675 /** Returns a string describing GL API function represented by user-provided enum.
1676  *
1677  *  @param func Uniform function to return the string for.
1678  *
1679  *  @return As per description. [?] will be returned if the function was not recognized.
1680  **/
getUniformFunctionString(_uniform_function func)1681 const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func)
1682 {
1683 	const char* result = "[?]";
1684 
1685 	switch (func)
1686 	{
1687 	case UNIFORM_FUNCTION_1D:
1688 		result = "glUniform1d";
1689 		break;
1690 	case UNIFORM_FUNCTION_1DV:
1691 		result = "glUniform1dv";
1692 		break;
1693 	case UNIFORM_FUNCTION_2D:
1694 		result = "glUniform2d";
1695 		break;
1696 	case UNIFORM_FUNCTION_2DV:
1697 		result = "glUniform2dv";
1698 		break;
1699 	case UNIFORM_FUNCTION_3D:
1700 		result = "glUniform3d";
1701 		break;
1702 	case UNIFORM_FUNCTION_3DV:
1703 		result = "glUniform3dv";
1704 		break;
1705 	case UNIFORM_FUNCTION_4D:
1706 		result = "glUniform4d";
1707 		break;
1708 	case UNIFORM_FUNCTION_4DV:
1709 		result = "glUniform4dv";
1710 		break;
1711 	case UNIFORM_FUNCTION_MATRIX2DV:
1712 		result = "glUniformMatrix2dv";
1713 		break;
1714 	case UNIFORM_FUNCTION_MATRIX2X3DV:
1715 		result = "glUniformMatrix2x3dv";
1716 		break;
1717 	case UNIFORM_FUNCTION_MATRIX2X4DV:
1718 		result = "glUniformMatrix2x4dv";
1719 		break;
1720 	case UNIFORM_FUNCTION_MATRIX3DV:
1721 		result = "glUniformMatrix3dv";
1722 		break;
1723 	case UNIFORM_FUNCTION_MATRIX3X2DV:
1724 		result = "glUniformMatrix3x2dv";
1725 		break;
1726 	case UNIFORM_FUNCTION_MATRIX3X4DV:
1727 		result = "glUniformMatrix3x4dv";
1728 		break;
1729 	case UNIFORM_FUNCTION_MATRIX4DV:
1730 		result = "glUniformMatrix4dv";
1731 		break;
1732 	case UNIFORM_FUNCTION_MATRIX4X2DV:
1733 		result = "glUniformMatrix4x2dv";
1734 		break;
1735 	case UNIFORM_FUNCTION_MATRIX4X3DV:
1736 		result = "glUniformMatrix4x3dv";
1737 		break;
1738 	default:
1739 		break;
1740 	}
1741 
1742 	return result;
1743 }
1744 
1745 /** Returns name of an uniform bound to user-provided location.
1746  *
1747  *  @param location Location of the uniform to return the name for.
1748  *
1749  *  @return As per description. [?] will be returned if the location was not
1750  *          recognized.
1751  **/
getUniformNameForLocation(glw::GLint location)1752 const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location)
1753 {
1754 	const char* result = "[?]";
1755 
1756 	if (location == m_po_bool_arr_uniform_location)
1757 		result = "uniform_bool_arr";
1758 	else if (location == m_po_bool_uniform_location)
1759 		result = "uniform_bool";
1760 	else if (location == m_po_bvec2_arr_uniform_location)
1761 		result = "uniform_bvec2_arr";
1762 	else if (location == m_po_bvec2_uniform_location)
1763 		result = "uniform_bvec2";
1764 	else if (location == m_po_bvec3_arr_uniform_location)
1765 		result = "uniform_bvec3_arr";
1766 	else if (location == m_po_bvec3_uniform_location)
1767 		result = "uniform_bvec3";
1768 	else if (location == m_po_bvec4_arr_uniform_location)
1769 		result = "uniform_bvec4_arr";
1770 	else if (location == m_po_bvec4_uniform_location)
1771 		result = "uniform_bvec4";
1772 	else if (location == m_po_dmat2_arr_uniform_location)
1773 		result = "uniform_dmat2_arr";
1774 	else if (location == m_po_dmat2_uniform_location)
1775 		result = "uniform_dmat2";
1776 	else if (location == m_po_dmat2x3_arr_uniform_location)
1777 		result = "uniform_dmat2x3_arr";
1778 	else if (location == m_po_dmat2x3_uniform_location)
1779 		result = "uniform_dmat2x3";
1780 	else if (location == m_po_dmat2x4_arr_uniform_location)
1781 		result = "uniform_dmat2x4_arr";
1782 	else if (location == m_po_dmat2x4_uniform_location)
1783 		result = "uniform_dmat2x4";
1784 	else if (location == m_po_dmat3_arr_uniform_location)
1785 		result = "uniform_dmat3_arr";
1786 	else if (location == m_po_dmat3_uniform_location)
1787 		result = "uniform_dmat3";
1788 	else if (location == m_po_dmat3x2_arr_uniform_location)
1789 		result = "uniform_dmat3x2_arr";
1790 	else if (location == m_po_dmat3x2_uniform_location)
1791 		result = "uniform_dmat3x2";
1792 	else if (location == m_po_dmat3x4_arr_uniform_location)
1793 		result = "uniform_dmat3x4_arr";
1794 	else if (location == m_po_dmat3x4_uniform_location)
1795 		result = "uniform_dmat3x4";
1796 	else if (location == m_po_dmat4_arr_uniform_location)
1797 		result = "uniform_dmat4_arr";
1798 	else if (location == m_po_dmat4_uniform_location)
1799 		result = "uniform_dmat4";
1800 	else if (location == m_po_dmat4x2_arr_uniform_location)
1801 		result = "uniform_dmat4x2_arr";
1802 	else if (location == m_po_dmat4x2_uniform_location)
1803 		result = "uniform_dmat4x2";
1804 	else if (location == m_po_dmat4x3_arr_uniform_location)
1805 		result = "uniform_dmat4x3_arr";
1806 	else if (location == m_po_dmat4x3_uniform_location)
1807 		result = "uniform_dmat4x3";
1808 	else if (location == m_po_double_arr_uniform_location)
1809 		result = "uniform_double_arr";
1810 	else if (location == m_po_double_uniform_location)
1811 		result = "uniform_double";
1812 	else if (location == m_po_dvec2_arr_uniform_location)
1813 		result = "uniform_dvec2_arr";
1814 	else if (location == m_po_dvec2_uniform_location)
1815 		result = "uniform_dvec2";
1816 	else if (location == m_po_dvec3_arr_uniform_location)
1817 		result = "uniform_dvec3_arr";
1818 	else if (location == m_po_dvec3_uniform_location)
1819 		result = "uniform_dvec3";
1820 	else if (location == m_po_dvec4_arr_uniform_location)
1821 		result = "uniform_dvec4_arr";
1822 	else if (location == m_po_dvec4_uniform_location)
1823 		result = "uniform_dvec4";
1824 	else if (location == m_po_float_arr_uniform_location)
1825 		result = "uniform_float_arr";
1826 	else if (location == m_po_float_uniform_location)
1827 		result = "uniform_float";
1828 	else if (location == m_po_int_arr_uniform_location)
1829 		result = "uniform_int_arr";
1830 	else if (location == m_po_int_uniform_location)
1831 		result = "uniform_int";
1832 	else if (location == m_po_ivec2_arr_uniform_location)
1833 		result = "uniform_ivec2_arr";
1834 	else if (location == m_po_ivec2_uniform_location)
1835 		result = "uniform_ivec2";
1836 	else if (location == m_po_ivec3_arr_uniform_location)
1837 		result = "uniform_ivec3_arr";
1838 	else if (location == m_po_ivec3_uniform_location)
1839 		result = "uniform_ivec3";
1840 	else if (location == m_po_ivec4_arr_uniform_location)
1841 		result = "uniform_ivec4_arr";
1842 	else if (location == m_po_ivec4_uniform_location)
1843 		result = "uniform_ivec4";
1844 	else if (location == m_po_uint_arr_uniform_location)
1845 		result = "uniform_uint_arr";
1846 	else if (location == m_po_uint_uniform_location)
1847 		result = "uniform_uint";
1848 	else if (location == m_po_uvec2_arr_uniform_location)
1849 		result = "uniform_uvec2_arr";
1850 	else if (location == m_po_uvec2_uniform_location)
1851 		result = "uniform_uvec2";
1852 	else if (location == m_po_uvec3_arr_uniform_location)
1853 		result = "uniform_uvec3_arr";
1854 	else if (location == m_po_uvec3_uniform_location)
1855 		result = "uniform_uvec3";
1856 	else if (location == m_po_uvec4_arr_uniform_location)
1857 		result = "uniform_uvec4_arr";
1858 	else if (location == m_po_uvec4_uniform_location)
1859 		result = "uniform_uvec4";
1860 	else if (location == m_po_vec2_arr_uniform_location)
1861 		result = "uniform_vec2_arr";
1862 	else if (location == m_po_vec2_uniform_location)
1863 		result = "uniform_vec2";
1864 	else if (location == m_po_vec3_arr_uniform_location)
1865 		result = "uniform_vec3_arr";
1866 	else if (location == m_po_vec3_uniform_location)
1867 		result = "uniform_vec3";
1868 	else if (location == m_po_vec4_arr_uniform_location)
1869 		result = "uniform_vec4_arr";
1870 	else if (location == m_po_vec4_uniform_location)
1871 		result = "uniform_vec4";
1872 
1873 	return result;
1874 }
1875 
1876 /** Initializes all GL objects required to run the test. Also extracts locations of all
1877  *  uniforms used by the test.
1878  *
1879  *  This function can throw a TestError exception if the implementation misbehaves.
1880  */
initTest()1881 void GPUShaderFP64Test1::initTest()
1882 {
1883 	glw::GLint			  compile_status = GL_FALSE;
1884 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
1885 	glw::GLint			  link_status	= GL_FALSE;
1886 
1887 	/* Set up a program object using all new double-precision types */
1888 	const char* vs_body =
1889 		"#version 400\n"
1890 		"\n"
1891 		"uniform bool      uniform_bool;\n"
1892 		"uniform bvec2     uniform_bvec2;\n"
1893 		"uniform bvec3     uniform_bvec3;\n"
1894 		"uniform bvec4     uniform_bvec4;\n"
1895 		"uniform dmat2     uniform_dmat2;\n"
1896 		"uniform dmat2x3   uniform_dmat2x3;\n"
1897 		"uniform dmat2x4   uniform_dmat2x4;\n"
1898 		"uniform dmat3     uniform_dmat3;\n"
1899 		"uniform dmat3x2   uniform_dmat3x2;\n"
1900 		"uniform dmat3x4   uniform_dmat3x4;\n"
1901 		"uniform dmat4     uniform_dmat4;\n"
1902 		"uniform dmat4x2   uniform_dmat4x2;\n"
1903 		"uniform dmat4x3   uniform_dmat4x3;\n"
1904 		"uniform double    uniform_double;\n"
1905 		"uniform dvec2     uniform_dvec2;\n"
1906 		"uniform dvec3     uniform_dvec3;\n"
1907 		"uniform dvec4     uniform_dvec4;\n"
1908 		"uniform float     uniform_float;\n"
1909 		"uniform int       uniform_int;\n"
1910 		"uniform ivec2     uniform_ivec2;\n"
1911 		"uniform ivec3     uniform_ivec3;\n"
1912 		"uniform ivec4     uniform_ivec4;\n"
1913 		"uniform sampler2D uniform_sampler;\n"
1914 		"uniform uint      uniform_uint;\n"
1915 		"uniform uvec2     uniform_uvec2;\n"
1916 		"uniform uvec3     uniform_uvec3;\n"
1917 		"uniform uvec4     uniform_uvec4;\n"
1918 		"uniform vec2      uniform_vec2;\n"
1919 		"uniform vec3      uniform_vec3;\n"
1920 		"uniform vec4      uniform_vec4;\n"
1921 		"uniform bool      uniform_bool_arr   [2];\n"
1922 		"uniform bvec2     uniform_bvec2_arr  [2];\n"
1923 		"uniform bvec3     uniform_bvec3_arr  [2];\n"
1924 		"uniform bvec4     uniform_bvec4_arr  [2];\n"
1925 		"uniform dmat2     uniform_dmat2_arr  [2];\n"
1926 		"uniform dmat2x3   uniform_dmat2x3_arr[2];\n"
1927 		"uniform dmat2x4   uniform_dmat2x4_arr[2];\n"
1928 		"uniform dmat3     uniform_dmat3_arr  [2];\n"
1929 		"uniform dmat3x2   uniform_dmat3x2_arr[2];\n"
1930 		"uniform dmat3x4   uniform_dmat3x4_arr[2];\n"
1931 		"uniform dmat4     uniform_dmat4_arr  [2];\n"
1932 		"uniform dmat4x2   uniform_dmat4x2_arr[2];\n"
1933 		"uniform dmat4x3   uniform_dmat4x3_arr[2];\n"
1934 		"uniform double    uniform_double_arr [2];\n"
1935 		"uniform dvec2     uniform_dvec2_arr  [2];\n"
1936 		"uniform dvec3     uniform_dvec3_arr  [2];\n"
1937 		"uniform dvec4     uniform_dvec4_arr  [2];\n"
1938 		"uniform float     uniform_float_arr  [2];\n"
1939 		"uniform int       uniform_int_arr    [2];\n"
1940 		"uniform ivec2     uniform_ivec2_arr  [2];\n"
1941 		"uniform ivec3     uniform_ivec3_arr  [2];\n"
1942 		"uniform ivec4     uniform_ivec4_arr  [2];\n"
1943 		"uniform uint      uniform_uint_arr   [2];\n"
1944 		"uniform uvec2     uniform_uvec2_arr  [2];\n"
1945 		"uniform uvec3     uniform_uvec3_arr  [2];\n"
1946 		"uniform uvec4     uniform_uvec4_arr  [2];\n"
1947 		"uniform vec2      uniform_vec2_arr   [2];\n"
1948 		"uniform vec3      uniform_vec3_arr   [2];\n"
1949 		"uniform vec4      uniform_vec4_arr   [2];\n"
1950 		"\n"
1951 		"void main()\n"
1952 		"{\n"
1953 		"    gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n"
1954 		"\n"
1955 		"    if (uniform_bool        && uniform_bvec2.y        && uniform_bvec3.z        && uniform_bvec4.w        &&\n"
1956 		"        uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n"
1957 		"    {\n"
1958 		"        double sum = uniform_dmat2       [0].x + uniform_dmat2x3       [0].x + uniform_dmat2x4       [0].x +\n"
1959 		"                     uniform_dmat3       [0].x + uniform_dmat3x2       [0].x + uniform_dmat3x4       [0].x +\n"
1960 		"                     uniform_dmat4       [0].x + uniform_dmat4x2       [0].x + uniform_dmat4x3       [0].x +\n"
1961 		"                     uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n"
1962 		"                     uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n"
1963 		"                     uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n"
1964 		"                     uniform_double            + uniform_double_arr [0]      +\n"
1965 		"                     uniform_dvec2.x           + uniform_dvec3.x             + uniform_dvec4.x        +\n"
1966 		"                     uniform_dvec2_arr[0].x    + uniform_dvec3_arr[0].x      + uniform_dvec4_arr[0].x;\n"
1967 		"        int   sum2 = uniform_int               + uniform_ivec2.x             + uniform_ivec3.x        +\n"
1968 		"                     uniform_ivec4.x           + uniform_ivec2_arr[0].x      + uniform_ivec3_arr[0].x +\n"
1969 		"                     uniform_ivec4_arr[0].x    + uniform_int_arr[0];\n"
1970 		"        uint  sum3 = uniform_uint              + uniform_uvec2.x             + uniform_uvec3.x        +\n"
1971 		"                     uniform_uvec4.x           + uniform_uint_arr[0]         + uniform_uvec2_arr[0].x +\n"
1972 		"                     uniform_uvec3_arr[0].x    + uniform_uvec4_arr[0].x;\n"
1973 		"        float sum4 = uniform_float             + uniform_float_arr[0]  + \n"
1974 		"                     uniform_vec2.x            + uniform_vec2_arr[0].x + \n"
1975 		"                     uniform_vec3.x            + uniform_vec3_arr[0].x + \n"
1976 		"                     uniform_vec4.x            + uniform_vec4_arr[0].x;\n"
1977 		"\n"
1978 		"        if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n"
1979 		"        {\n"
1980 		"            gl_Position = vec4(1);\n"
1981 		"        }\n"
1982 		"    }\n"
1983 		"}\n";
1984 
1985 	m_po_id = gl.createProgram();
1986 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1987 
1988 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1989 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
1990 
1991 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
1992 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1993 
1994 	gl.compileShader(m_vs_id);
1995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1996 
1997 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1999 
2000 	if (compile_status != GL_TRUE)
2001 	{
2002 		TCU_FAIL("Shader compilation failed.");
2003 	}
2004 
2005 	gl.attachShader(m_po_id, m_vs_id);
2006 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
2007 
2008 	gl.linkProgram(m_po_id);
2009 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2010 
2011 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
2012 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2013 
2014 	if (link_status != GL_TRUE)
2015 	{
2016 		TCU_FAIL("Program linking failed.");
2017 	}
2018 
2019 	m_po_bool_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]");
2020 	m_po_bool_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bool");
2021 	m_po_bvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]");
2022 	m_po_bvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec2");
2023 	m_po_bvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]");
2024 	m_po_bvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec3");
2025 	m_po_bvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]");
2026 	m_po_bvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec4");
2027 	m_po_dmat2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]");
2028 	m_po_dmat2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat2");
2029 	m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]");
2030 	m_po_dmat2x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x3");
2031 	m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]");
2032 	m_po_dmat2x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x4");
2033 	m_po_dmat3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]");
2034 	m_po_dmat3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat3");
2035 	m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]");
2036 	m_po_dmat3x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x2");
2037 	m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]");
2038 	m_po_dmat3x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x4");
2039 	m_po_dmat4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]");
2040 	m_po_dmat4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat4");
2041 	m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]");
2042 	m_po_dmat4x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x2");
2043 	m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]");
2044 	m_po_dmat4x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x3");
2045 	m_po_double_arr_uniform_location  = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]");
2046 	m_po_double_uniform_location	  = gl.getUniformLocation(m_po_id, "uniform_double");
2047 	m_po_dvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]");
2048 	m_po_dvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec2");
2049 	m_po_dvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]");
2050 	m_po_dvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec3");
2051 	m_po_dvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]");
2052 	m_po_dvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec4");
2053 	m_po_float_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]");
2054 	m_po_float_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_float");
2055 	m_po_int_arr_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]");
2056 	m_po_int_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_int");
2057 	m_po_ivec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]");
2058 	m_po_ivec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec2");
2059 	m_po_ivec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]");
2060 	m_po_ivec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec3");
2061 	m_po_ivec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]");
2062 	m_po_ivec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec4");
2063 	m_po_sampler_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_sampler");
2064 	m_po_uint_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]");
2065 	m_po_uint_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uint");
2066 	m_po_uvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]");
2067 	m_po_uvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec2");
2068 	m_po_uvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]");
2069 	m_po_uvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec3");
2070 	m_po_uvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]");
2071 	m_po_uvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec4");
2072 	m_po_vec2_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]");
2073 	m_po_vec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec2");
2074 	m_po_vec3_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]");
2075 	m_po_vec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec3");
2076 	m_po_vec4_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]");
2077 	m_po_vec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec4");
2078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
2079 
2080 	if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 ||
2081 		m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 ||
2082 		m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 ||
2083 		m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 ||
2084 		m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 ||
2085 		m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 ||
2086 		m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 ||
2087 		m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 ||
2088 		m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 ||
2089 		m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 ||
2090 		m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 ||
2091 		m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 ||
2092 		m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 ||
2093 		m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 ||
2094 		m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 ||
2095 		m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 ||
2096 		m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 ||
2097 		m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 ||
2098 		m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 ||
2099 		m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 ||
2100 		m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 ||
2101 		m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 ||
2102 		m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 ||
2103 		m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 ||
2104 		m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 ||
2105 		m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 ||
2106 		m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 ||
2107 		m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 ||
2108 		m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1)
2109 	{
2110 		TCU_FAIL("At last one of the required uniforms is considered inactive.");
2111 	}
2112 }
2113 
2114 /** Tells wheter uniform at user-specified location represents a double-precision
2115  *  matrix uniform.
2116  *
2117  *  @param uniform_location Location of the uniform to use for the query.
2118  *
2119  *  @return Requested information.
2120  **/
isMatrixUniform(glw::GLint uniform_location)2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location)
2122 {
2123 	return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location ||
2124 			uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location ||
2125 			uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location ||
2126 			uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location ||
2127 			uniform_location == m_po_dmat4x3_uniform_location);
2128 }
2129 
2130 /** Tells whether user-specified uniform function corresponds to one of the
2131  *  functions in glUniformMatrix*() class.
2132  *
2133  *  @param func Uniform function enum to use for the query.
2134  *
2135  *  @return true if the specified enum represents one of the glUniformMatrix*() functions,
2136  *          false otherwise.
2137  **/
isMatrixUniformFunction(_uniform_function func)2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func)
2139 {
2140 	return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV ||
2141 			func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV ||
2142 			func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV ||
2143 			func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV ||
2144 			func == UNIFORM_FUNCTION_MATRIX4X3DV);
2145 }
2146 
2147 /** Executes test iteration.
2148  *
2149  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2150  */
iterate()2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate()
2152 {
2153 	/* Do not execute the test if GL_ARB_texture_view is not supported */
2154 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
2155 	{
2156 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
2157 	}
2158 
2159 	/* Initialize all ES objects required to run all the checks */
2160 	initTest();
2161 
2162 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() and
2163 	 * glUniformMatrix*() functions if there is no current program object.
2164 	 */
2165 	m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO();
2166 
2167 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() if
2168 	 * the size of the uniform variable declared in the shader does not
2169 	 * match the size indicated by the command.
2170 	 */
2171 	m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions();
2172 
2173 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2174 	 * glUniformMatrix*() are used to load a uniform variable of type
2175 	 * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4,
2176 	 * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array
2177 	 * of these.
2178 	 */
2179 	m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions();
2180 
2181 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2182 	 * glUniformMatrix*() are used to load incompatible double-typed
2183 	 * uniforms, as presented below:
2184 	 *
2185 	 * I.    double-typed uniform configured by glUniform2d();
2186 	 * II.   double-typed uniform configured by glUniform3d();
2187 	 * III.  double-typed uniform configured by glUniform4d();
2188 	 * IV.   double-typed uniform configured by glUniformMatrix*();
2189 	 * V.    dvec2-typed  uniform configured by glUniform1d();
2190 	 * VI.   dvec2-typed  uniform configured by glUniform3d();
2191 	 * VII.  dvec2-typed  uniform configured by glUniform4d();
2192 	 * VIII. dvec2-typed  uniform configured by glUniformMatrix*();
2193 	 *
2194 	 *                          (etc.)
2195 	 *
2196 	 */
2197 	m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions();
2198 
2199 	/* Make sure GL_INVALID_OPERATION is generated if <location> of
2200 	 * glUniform*() and glUniformMatrix*() is an invalid uniform
2201 	 * location for the current program object and location is not
2202 	 * equal to -1.
2203 	 */
2204 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation();
2205 
2206 	/* Make sure GL_INVALID_VALUE is generated if <count> of
2207 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2208 	 * negative.
2209 	 */
2210 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount();
2211 
2212 	/* Make sure GL_INVALID_OPERATION is generated if <count> of
2213 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2214 	 * greater than 1 and the indicated uniform variable is not an
2215 	 * array variable.
2216 	 */
2217 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount();
2218 
2219 	/* Make sure GL_INVALID_OPERATION is generated if a sampler is
2220 	 * loaded by glUniform*() and glUniformMatrix*().
2221 	 */
2222 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers();
2223 
2224 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2225 	 * glUniformMatrix*() is used to load values for uniforms of
2226 	 * boolean types.
2227 	 */
2228 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans();
2229 
2230 	if (m_has_test_passed)
2231 	{
2232 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2233 	}
2234 	else
2235 	{
2236 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2237 	}
2238 
2239 	return STOP;
2240 }
2241 
2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2243  *  glUniformMatrix*dv() functions is used to load a boolean uniform.
2244  *
2245  *  @return true if the implementation was found to behave as expected, false otherwise.
2246  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()
2248 {
2249 	const double double_data[] = {
2250 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2251 	};
2252 	const glw::Functions& gl				  = m_context.getRenderContext().getFunctions();
2253 	bool				  result			  = true;
2254 	glw::GLint			  uniform_locations[] = { m_po_bool_arr_uniform_location,  m_po_bool_uniform_location,
2255 									   m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2256 									   m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2257 									   m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location };
2258 	const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2259 
2260 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2261 		 ++n_uniform_function)
2262 	{
2263 		const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2264 
2265 		for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2266 		{
2267 			const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2268 
2269 			switch (uniform_function)
2270 			{
2271 			case UNIFORM_FUNCTION_1D:
2272 				gl.uniform1d(uniform_location, 0.0);
2273 				break;
2274 			case UNIFORM_FUNCTION_2D:
2275 				gl.uniform2d(uniform_location, 0.0, 1.0);
2276 				break;
2277 			case UNIFORM_FUNCTION_3D:
2278 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2279 				break;
2280 			case UNIFORM_FUNCTION_4D:
2281 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2282 				break;
2283 
2284 			case UNIFORM_FUNCTION_1DV:
2285 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2286 				break;
2287 			case UNIFORM_FUNCTION_2DV:
2288 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2289 				break;
2290 			case UNIFORM_FUNCTION_3DV:
2291 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2292 				break;
2293 			case UNIFORM_FUNCTION_4DV:
2294 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2295 				break;
2296 
2297 			case UNIFORM_FUNCTION_MATRIX2DV:
2298 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2299 				break;
2300 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2301 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2302 				break;
2303 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2304 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2305 				break;
2306 			case UNIFORM_FUNCTION_MATRIX3DV:
2307 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2308 				break;
2309 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2310 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2311 				break;
2312 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2313 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2314 				break;
2315 			case UNIFORM_FUNCTION_MATRIX4DV:
2316 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2317 				break;
2318 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2319 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2320 				break;
2321 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2322 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2323 				break;
2324 
2325 			default:
2326 			{
2327 				TCU_FAIL("Unrecognized uniform function");
2328 			}
2329 			}
2330 
2331 			/* Make sure GL_INVALID_OPERATION was generated by the call */
2332 			const glw::GLenum error_code = gl.getError();
2333 
2334 			if (error_code != GL_INVALID_OPERATION)
2335 			{
2336 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2337 								   << "() did not generate an error"
2338 									  " when applied against a boolean uniform."
2339 								   << tcu::TestLog::EndMessage;
2340 
2341 				result = false;
2342 			}
2343 		} /* for (all bool uniforms) */
2344 	}	 /* for (all uniform functions) */
2345 
2346 	return result;
2347 }
2348 
2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2350  *  glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2351  *
2352  *  @return true if the implementation was found to behave as expected, false otherwise.
2353  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2355 {
2356 	const double double_data[] = {
2357 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2358 	};
2359 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2360 	bool				  result = true;
2361 
2362 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2363 		 ++n_uniform_function)
2364 	{
2365 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2366 
2367 		switch (uniform_function)
2368 		{
2369 		case UNIFORM_FUNCTION_1D:
2370 			gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2371 			break;
2372 		case UNIFORM_FUNCTION_2D:
2373 			gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2374 			break;
2375 		case UNIFORM_FUNCTION_3D:
2376 			gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2377 			break;
2378 		case UNIFORM_FUNCTION_4D:
2379 			gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2380 			break;
2381 
2382 		case UNIFORM_FUNCTION_1DV:
2383 			gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2384 			break;
2385 		case UNIFORM_FUNCTION_2DV:
2386 			gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2387 			break;
2388 		case UNIFORM_FUNCTION_3DV:
2389 			gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2390 			break;
2391 		case UNIFORM_FUNCTION_4DV:
2392 			gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2393 			break;
2394 
2395 		case UNIFORM_FUNCTION_MATRIX2DV:
2396 			gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2397 			break;
2398 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2399 			gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2400 			break;
2401 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2402 			gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2403 			break;
2404 		case UNIFORM_FUNCTION_MATRIX3DV:
2405 			gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2406 			break;
2407 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2408 			gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2409 			break;
2410 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2411 			gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2412 			break;
2413 		case UNIFORM_FUNCTION_MATRIX4DV:
2414 			gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2415 			break;
2416 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2417 			gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2418 			break;
2419 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2420 			gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2421 			break;
2422 
2423 		default:
2424 		{
2425 			TCU_FAIL("Unrecognized uniform function");
2426 		}
2427 		}
2428 
2429 		/* Make sure GL_INVALID_OPERATION was generated by the call */
2430 		const glw::GLenum error_code = gl.getError();
2431 
2432 		if (error_code != GL_INVALID_OPERATION)
2433 		{
2434 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2435 							   << "() did not generate an error"
2436 								  " when applied against a sampler uniform."
2437 							   << tcu::TestLog::EndMessage;
2438 
2439 			result = false;
2440 		}
2441 	} /* for (all uniform functions) */
2442 
2443 	return result;
2444 }
2445 
2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2447  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2448  *  invalid <count> argument.
2449  *
2450  *  @return true if the implementation was found to behave as expected, false otherwise.
2451  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2453 {
2454 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2455 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2456 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2457 	bool					result				= true;
2458 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2459 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2460 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2461 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2462 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2463 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2464 													UNIFORM_FUNCTION_MATRIX4X3DV };
2465 	const glw::GLint uniforms[] = {
2466 		m_po_bool_uniform_location,	m_po_bvec2_uniform_location,  m_po_bvec3_uniform_location,
2467 		m_po_bvec4_uniform_location,   m_po_dmat2_uniform_location,  m_po_dmat2x3_uniform_location,
2468 		m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,  m_po_dmat3x2_uniform_location,
2469 		m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location,  m_po_dmat4x2_uniform_location,
2470 		m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2471 		m_po_dvec3_uniform_location,   m_po_dvec4_uniform_location,  m_po_float_uniform_location,
2472 		m_po_int_uniform_location,	 m_po_ivec2_uniform_location,  m_po_ivec3_uniform_location,
2473 		m_po_ivec4_uniform_location,   m_po_uint_uniform_location,   m_po_uvec2_uniform_location,
2474 		m_po_uvec3_uniform_location,   m_po_uvec4_uniform_location,  m_po_vec2_uniform_location,
2475 		m_po_vec3_uniform_location,	m_po_vec4_uniform_location
2476 	};
2477 
2478 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2479 	const unsigned int n_uniforms		   = sizeof(uniforms) / sizeof(uniforms[0]);
2480 
2481 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2482 	{
2483 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2484 
2485 		for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2486 		{
2487 			glw::GLint uniform_location = uniforms[n_uniform];
2488 
2489 			/* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2490 			 * and glUniform*() functions with vector uniforms.
2491 			 */
2492 			bool is_matrix_uniform = isMatrixUniform(uniform_location);
2493 
2494 			if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2495 				((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2496 			{
2497 				continue;
2498 			}
2499 
2500 			/* Issue the call with an invalid <count> argument */
2501 			switch (uniform_function)
2502 			{
2503 			case UNIFORM_FUNCTION_1DV:
2504 				gl.uniform1dv(uniform_location, 2, double_values);
2505 				break;
2506 			case UNIFORM_FUNCTION_2DV:
2507 				gl.uniform2dv(uniform_location, 2, double_values);
2508 				break;
2509 			case UNIFORM_FUNCTION_3DV:
2510 				gl.uniform3dv(uniform_location, 2, double_values);
2511 				break;
2512 			case UNIFORM_FUNCTION_4DV:
2513 				gl.uniform4dv(uniform_location, 2, double_values);
2514 				break;
2515 			case UNIFORM_FUNCTION_MATRIX2DV:
2516 				gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2517 				break;
2518 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2519 				gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2520 				break;
2521 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2522 				gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2523 				break;
2524 			case UNIFORM_FUNCTION_MATRIX3DV:
2525 				gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2526 				break;
2527 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2528 				gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2529 				break;
2530 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2531 				gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2532 				break;
2533 			case UNIFORM_FUNCTION_MATRIX4DV:
2534 				gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2535 				break;
2536 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2537 				gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2538 				break;
2539 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2540 				gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2541 				break;
2542 
2543 			default:
2544 			{
2545 				TCU_FAIL("Unrecognized uniform function");
2546 			}
2547 			} /* switch (uniform_function) */
2548 
2549 			/* Make sure GL_INVALID_VALUE was generated */
2550 			glw::GLenum error_code = gl.getError();
2551 
2552 			if (error_code != GL_INVALID_OPERATION)
2553 			{
2554 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2555 								   << "() "
2556 									  "was called with an invalid count argument but did not generate a "
2557 									  "GL_INVALID_OPERATION error"
2558 								   << tcu::TestLog::EndMessage;
2559 
2560 				result = false;
2561 			}
2562 		} /* for (all non-arrayed uniforms) */
2563 	}	 /* for (all uniform functions) */
2564 
2565 	return result;
2566 }
2567 
2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2569  *  glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2570  *
2571  *  @return true if the implementation was found to behave as expected, false otherwise.
2572  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2574 {
2575 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2576 	bool				  result = true;
2577 
2578 	/* Find the largest valid uniform location */
2579 	const glw::GLint uniform_locations[] = {
2580 		m_po_bool_arr_uniform_location,	m_po_bool_uniform_location,		  m_po_bvec2_arr_uniform_location,
2581 		m_po_bvec2_uniform_location,	   m_po_bvec3_arr_uniform_location,   m_po_bvec3_uniform_location,
2582 		m_po_bvec4_arr_uniform_location,   m_po_bvec4_uniform_location,		  m_po_dmat2_arr_uniform_location,
2583 		m_po_dmat2_uniform_location,	   m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2584 		m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location,	 m_po_dmat3_arr_uniform_location,
2585 		m_po_dmat3_uniform_location,	   m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2586 		m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location,	 m_po_dmat4_arr_uniform_location,
2587 		m_po_dmat4_uniform_location,	   m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2588 		m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location,	 m_po_double_arr_uniform_location,
2589 		m_po_double_uniform_location,	  m_po_dvec2_arr_uniform_location,   m_po_dvec2_uniform_location,
2590 		m_po_dvec3_arr_uniform_location,   m_po_dvec3_uniform_location,		  m_po_dvec4_arr_uniform_location,
2591 		m_po_dvec4_uniform_location,	   m_po_float_arr_uniform_location,   m_po_float_uniform_location,
2592 		m_po_int_arr_uniform_location,	 m_po_int_uniform_location,		  m_po_ivec2_arr_uniform_location,
2593 		m_po_ivec2_uniform_location,	   m_po_ivec3_arr_uniform_location,   m_po_ivec3_uniform_location,
2594 		m_po_ivec4_arr_uniform_location,   m_po_ivec4_uniform_location,		  m_po_uint_arr_uniform_location,
2595 		m_po_uint_uniform_location,		   m_po_uvec2_arr_uniform_location,   m_po_uvec2_uniform_location,
2596 		m_po_uvec3_arr_uniform_location,   m_po_uvec3_uniform_location,		  m_po_uvec4_arr_uniform_location,
2597 		m_po_uvec4_uniform_location,	   m_po_vec2_arr_uniform_location,	m_po_vec2_uniform_location,
2598 		m_po_vec3_arr_uniform_location,	m_po_vec3_uniform_location,		  m_po_vec4_arr_uniform_location,
2599 		m_po_vec4_uniform_location
2600 	};
2601 	const unsigned int n_uniform_locations	= sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2602 	glw::GLint		   valid_uniform_location = -1;
2603 
2604 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2605 	{
2606 		glw::GLint uniform_location = uniform_locations[n_uniform_location];
2607 
2608 		if (uniform_location > valid_uniform_location)
2609 		{
2610 			valid_uniform_location = uniform_location;
2611 		}
2612 	} /* for (all  uniform locations) */
2613 
2614 	/* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2615 	 * for invalid uniform location that is != -1
2616 	 */
2617 	const double double_data[] = {
2618 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2619 	};
2620 	const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2621 
2622 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2623 		 ++n_uniform_function)
2624 	{
2625 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2626 
2627 		switch (uniform_function)
2628 		{
2629 		case UNIFORM_FUNCTION_1D:
2630 			gl.uniform1d(invalid_uniform_location, 0.0);
2631 			break;
2632 		case UNIFORM_FUNCTION_2D:
2633 			gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2634 			break;
2635 		case UNIFORM_FUNCTION_3D:
2636 			gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2637 			break;
2638 		case UNIFORM_FUNCTION_4D:
2639 			gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2640 			break;
2641 
2642 		case UNIFORM_FUNCTION_1DV:
2643 			gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2644 			break;
2645 		case UNIFORM_FUNCTION_2DV:
2646 			gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2647 			break;
2648 		case UNIFORM_FUNCTION_3DV:
2649 			gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2650 			break;
2651 		case UNIFORM_FUNCTION_4DV:
2652 			gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2653 			break;
2654 
2655 		case UNIFORM_FUNCTION_MATRIX2DV:
2656 			gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657 			break;
2658 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2659 			gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660 			break;
2661 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2662 			gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663 			break;
2664 		case UNIFORM_FUNCTION_MATRIX3DV:
2665 			gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666 			break;
2667 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2668 			gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669 			break;
2670 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2671 			gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672 			break;
2673 		case UNIFORM_FUNCTION_MATRIX4DV:
2674 			gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675 			break;
2676 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2677 			gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2678 			break;
2679 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2680 			gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2681 			break;
2682 
2683 		default:
2684 		{
2685 			TCU_FAIL("Unrecognized uniform function");
2686 		}
2687 		}
2688 
2689 		const glw::GLenum error_code = gl.getError();
2690 
2691 		if (error_code != GL_INVALID_OPERATION)
2692 		{
2693 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2694 							   << "() did not generate an error"
2695 								  " when passed an invalid uniform location different from -1."
2696 							   << tcu::TestLog::EndMessage;
2697 
2698 			result = false;
2699 		}
2700 	} /* for (all uniform functions) */
2701 
2702 	return result;
2703 }
2704 
2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2706  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2707  *  invalid <count> argument of -1.
2708  *
2709  *  @return true if the implementation was found to behave as expected, false otherwise.
2710  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2712 {
2713 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2714 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2715 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2716 	bool					result				= true;
2717 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2718 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2719 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2720 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2721 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2722 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2723 													UNIFORM_FUNCTION_MATRIX4X3DV };
2724 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2725 
2726 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2727 	{
2728 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2729 
2730 		switch (uniform_function)
2731 		{
2732 		case UNIFORM_FUNCTION_1DV:
2733 			gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2734 			break;
2735 		case UNIFORM_FUNCTION_2DV:
2736 			gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2737 			break;
2738 		case UNIFORM_FUNCTION_3DV:
2739 			gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2740 			break;
2741 		case UNIFORM_FUNCTION_4DV:
2742 			gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2743 			break;
2744 		case UNIFORM_FUNCTION_MATRIX2DV:
2745 			gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2746 			break;
2747 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2748 			gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2749 			break;
2750 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2751 			gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2752 			break;
2753 		case UNIFORM_FUNCTION_MATRIX3DV:
2754 			gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2755 			break;
2756 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2757 			gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2758 			break;
2759 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2760 			gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2761 			break;
2762 		case UNIFORM_FUNCTION_MATRIX4DV:
2763 			gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2764 			break;
2765 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2766 			gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2767 			break;
2768 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2769 			gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2770 			break;
2771 
2772 		default:
2773 		{
2774 			TCU_FAIL("Unrecognized uniform function");
2775 		}
2776 		} /* switch (uniform_function) */
2777 
2778 		/* Make sure GL_INVALID_VALUE was generated */
2779 		glw::GLenum error_code = gl.getError();
2780 
2781 		if (error_code != GL_INVALID_VALUE)
2782 		{
2783 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2784 							   << "() "
2785 								  "was called with a negative count argument but did not generate a "
2786 								  "GL_INVALID_VALUE error"
2787 							   << tcu::TestLog::EndMessage;
2788 
2789 			result = false;
2790 		}
2791 	} /* for (all uniform functions) */
2792 
2793 	return result;
2794 }
2795 
2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2797  *  glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2798  *  function (as per spec).
2799  *
2800  *  @return true if the implementation was found to behave as expected, false otherwise.
2801  **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2803 {
2804 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2805 	glw::GLenum			  error_code	= GL_NO_ERROR;
2806 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2807 	bool				  result		= true;
2808 
2809 	const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location,   m_po_dmat2x3_uniform_location,
2810 													m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,
2811 													m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2812 													m_po_dmat4_uniform_location,   m_po_dmat4x2_uniform_location,
2813 													m_po_dmat4x3_uniform_location, m_po_double_uniform_location,
2814 													m_po_dvec2_uniform_location,   m_po_dvec3_uniform_location,
2815 													m_po_dvec4_uniform_location };
2816 	const unsigned int n_double_uniform_locations =
2817 		sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2818 
2819 	gl.useProgram(m_po_id);
2820 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2821 
2822 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2823 	{
2824 		glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2825 
2826 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2827 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2828 		{
2829 			_uniform_function e_function = static_cast<_uniform_function>(function);
2830 			/* Exclude valid combinations */
2831 			if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2832 				((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2833 				((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2834 				((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2835 				((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2836 				((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2837 				((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2838 				((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2839 				((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2840 				((uniform_location == m_po_double_uniform_location) &&
2841 				 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2842 				((uniform_location == m_po_dvec2_uniform_location) &&
2843 				 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2844 				((uniform_location == m_po_dvec3_uniform_location) &&
2845 				 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2846 				((uniform_location == m_po_dvec4_uniform_location) &&
2847 				 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2848 			{
2849 				continue;
2850 			}
2851 
2852 			switch (e_function)
2853 			{
2854 			case UNIFORM_FUNCTION_1D:
2855 			{
2856 				gl.uniform1d(uniform_location, double_data[0]);
2857 
2858 				break;
2859 			}
2860 
2861 			case UNIFORM_FUNCTION_2D:
2862 			{
2863 				gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2864 
2865 				break;
2866 			}
2867 
2868 			case UNIFORM_FUNCTION_3D:
2869 			{
2870 				gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2871 
2872 				break;
2873 			}
2874 
2875 			case UNIFORM_FUNCTION_4D:
2876 			{
2877 				gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2878 
2879 				break;
2880 			}
2881 
2882 			case UNIFORM_FUNCTION_1DV:
2883 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2884 				break;
2885 			case UNIFORM_FUNCTION_2DV:
2886 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2887 				break;
2888 			case UNIFORM_FUNCTION_3DV:
2889 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2890 				break;
2891 			case UNIFORM_FUNCTION_4DV:
2892 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2893 				break;
2894 			case UNIFORM_FUNCTION_MATRIX2DV:
2895 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2896 				break;
2897 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2898 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2899 				break;
2900 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2901 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2902 				break;
2903 			case UNIFORM_FUNCTION_MATRIX3DV:
2904 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2905 				break;
2906 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2907 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2908 				break;
2909 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2910 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2911 				break;
2912 			case UNIFORM_FUNCTION_MATRIX4DV:
2913 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2914 				break;
2915 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2916 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2917 				break;
2918 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2919 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2920 				break;
2921 
2922 			default:
2923 			{
2924 				TCU_FAIL("Unrecognized function");
2925 			}
2926 			} /* switch (function) */
2927 
2928 			/* Make sure GL_INVALID_OPERATION error was generated */
2929 			error_code = gl.getError();
2930 
2931 			if (error_code != GL_INVALID_OPERATION)
2932 			{
2933 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2934 								   << "] was generated when a mismatched "
2935 									  "double-precision uniform function "
2936 								   << getUniformFunctionString(e_function) << "() was used to configure uniform "
2937 								   << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2938 
2939 				result = false;
2940 			}
2941 		} /* for (all uniform functions) */
2942 	}	 /* for (all uniform locations) */
2943 
2944 	return result;
2945 }
2946 
2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2948  *  glUniform*dv() functions is used to load an uniform, size of which is incompatible
2949  *  with the function.
2950  *
2951  *  @return true if the implementation was found to behave as expected, false otherwise.
2952  **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2954 {
2955 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2956 	glw::GLenum			  error_code	= GL_NO_ERROR;
2957 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2958 	bool				  result		= true;
2959 
2960 	const int data[] = {
2961 		/* API function */ /* Uniform location */ /* Count (dv functions only) */
2962 		(int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV,
2963 		m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0,
2964 		(int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2965 		m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2,
2966 		(int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2967 		m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0,
2968 		(int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2969 		m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2,
2970 		(int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2971 		m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0,
2972 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2973 		m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2,
2974 		(int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2975 		m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0,
2976 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D,
2977 		m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2,
2978 	};
2979 	const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
2980 
2981 	gl.useProgram(m_po_id);
2982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2983 
2984 	for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
2985 	{
2986 		_uniform_function function		   = (_uniform_function)data[n_check * 3 + 0];
2987 		int				  uniform_location = data[n_check * 3 + 1];
2988 		int				  uniform_count	= data[n_check * 3 + 2];
2989 
2990 		switch (function)
2991 		{
2992 		case UNIFORM_FUNCTION_1D:
2993 			gl.uniform1d(uniform_location, 0.0);
2994 			break;
2995 		case UNIFORM_FUNCTION_1DV:
2996 			gl.uniform1dv(uniform_location, uniform_count, double_data);
2997 			break;
2998 		case UNIFORM_FUNCTION_2D:
2999 			gl.uniform2d(uniform_location, 0.0, 1.0);
3000 			break;
3001 		case UNIFORM_FUNCTION_2DV:
3002 			gl.uniform2dv(uniform_location, uniform_count, double_data);
3003 			break;
3004 		case UNIFORM_FUNCTION_3D:
3005 			gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3006 			break;
3007 		case UNIFORM_FUNCTION_3DV:
3008 			gl.uniform3dv(uniform_location, uniform_count, double_data);
3009 			break;
3010 		case UNIFORM_FUNCTION_4D:
3011 			gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3012 			break;
3013 		case UNIFORM_FUNCTION_4DV:
3014 			gl.uniform4dv(uniform_location, uniform_count, double_data);
3015 			break;
3016 
3017 		default:
3018 		{
3019 			DE_ASSERT(false);
3020 		}
3021 		} /* switch (function) */
3022 
3023 		error_code = gl.getError();
3024 		if (error_code != GL_INVALID_OPERATION)
3025 		{
3026 			m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3027 							   << "() function did not generate GL_INVALID_OPERATION error when called for"
3028 								  " a uniform of incompatible size. (check index: "
3029 							   << n_check << ")" << tcu::TestLog::EndMessage;
3030 
3031 			result = false;
3032 		}
3033 	} /* for (all checks) */
3034 
3035 	return result;
3036 }
3037 
3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3039  *  glUniform*dv() functions is used to load an uniform, type of which is incompatible
3040  *  with the function.
3041  *
3042  *  @return true if the implementation was found to behave as expected, false otherwise.
3043  **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3045 {
3046 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
3047 	glw::GLenum			  error_code	= GL_NO_ERROR;
3048 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
3049 	bool				  result		= true;
3050 
3051 	const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location,  m_po_bvec2_uniform_location,
3052 													   m_po_bvec3_uniform_location, m_po_bvec4_uniform_location,
3053 													   m_po_float_uniform_location, m_po_int_uniform_location,
3054 													   m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
3055 													   m_po_ivec4_uniform_location, m_po_uint_uniform_location,
3056 													   m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3057 													   m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
3058 													   m_po_vec3_uniform_location,  m_po_vec4_uniform_location };
3059 	const unsigned int n_nondouble_uniform_locations =
3060 		sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3061 
3062 	gl.useProgram(m_po_id);
3063 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3064 
3065 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3066 	{
3067 		glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3068 
3069 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3070 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3071 		{
3072 			switch (static_cast<_uniform_function>(function))
3073 			{
3074 			case UNIFORM_FUNCTION_1D:
3075 				gl.uniform1d(uniform_location, 0.0);
3076 				break;
3077 			case UNIFORM_FUNCTION_1DV:
3078 				gl.uniform1dv(uniform_location, 1, double_data);
3079 				break;
3080 			case UNIFORM_FUNCTION_2D:
3081 				gl.uniform2d(uniform_location, 0.0, 1.0);
3082 				break;
3083 			case UNIFORM_FUNCTION_2DV:
3084 				gl.uniform2dv(uniform_location, 1, double_data);
3085 				break;
3086 			case UNIFORM_FUNCTION_3D:
3087 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3088 				break;
3089 			case UNIFORM_FUNCTION_3DV:
3090 				gl.uniform3dv(uniform_location, 1, double_data);
3091 				break;
3092 			case UNIFORM_FUNCTION_4D:
3093 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3094 				break;
3095 			case UNIFORM_FUNCTION_4DV:
3096 				gl.uniform4dv(uniform_location, 1, double_data);
3097 				break;
3098 
3099 			case UNIFORM_FUNCTION_MATRIX2DV:
3100 				gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3101 				break;
3102 			case UNIFORM_FUNCTION_MATRIX2X3DV:
3103 				gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3104 				break;
3105 			case UNIFORM_FUNCTION_MATRIX2X4DV:
3106 				gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3107 				break;
3108 			case UNIFORM_FUNCTION_MATRIX3DV:
3109 				gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3110 				break;
3111 			case UNIFORM_FUNCTION_MATRIX3X2DV:
3112 				gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3113 				break;
3114 			case UNIFORM_FUNCTION_MATRIX3X4DV:
3115 				gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3116 				break;
3117 			case UNIFORM_FUNCTION_MATRIX4DV:
3118 				gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3119 				break;
3120 			case UNIFORM_FUNCTION_MATRIX4X2DV:
3121 				gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3122 				break;
3123 			case UNIFORM_FUNCTION_MATRIX4X3DV:
3124 				gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3125 				break;
3126 
3127 			default:
3128 			{
3129 				DE_ASSERT(false);
3130 			}
3131 			} /* switch (function) */
3132 
3133 			error_code = gl.getError();
3134 			if (error_code != GL_INVALID_OPERATION)
3135 			{
3136 				m_testCtx.getLog() << tcu::TestLog::Message
3137 								   << getUniformFunctionString(static_cast<_uniform_function>(function))
3138 								   << "() function did not generate GL_INVALID_OPERATION error when called for"
3139 									  " a uniform of incompatible type."
3140 								   << tcu::TestLog::EndMessage;
3141 
3142 				result = false;
3143 			}
3144 		}
3145 	} /* for (all checks) */
3146 
3147 	return result;
3148 }
3149 
3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3151  *  glUniform*dv() functions are called without a bound program object.
3152  *
3153  *  @return true if the implementation was found to behave as expected, false otherwise.
3154  **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3156 {
3157 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3158 	bool				  result = true;
3159 
3160 	for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3161 		 function++)
3162 	{
3163 		const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
3164 
3165 		switch (static_cast<_uniform_function>(function))
3166 		{
3167 		case UNIFORM_FUNCTION_1D:
3168 			gl.uniform1d(m_po_double_uniform_location, 0.0);
3169 			break;
3170 		case UNIFORM_FUNCTION_1DV:
3171 			gl.uniform1dv(m_po_double_uniform_location, 1, data);
3172 			break;
3173 		case UNIFORM_FUNCTION_2D:
3174 			gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3175 			break;
3176 		case UNIFORM_FUNCTION_2DV:
3177 			gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3178 			break;
3179 		case UNIFORM_FUNCTION_3D:
3180 			gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3181 			break;
3182 		case UNIFORM_FUNCTION_3DV:
3183 			gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3184 			break;
3185 		case UNIFORM_FUNCTION_4D:
3186 			gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3187 			break;
3188 		case UNIFORM_FUNCTION_4DV:
3189 			gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3190 			break;
3191 
3192 		case UNIFORM_FUNCTION_MATRIX2DV:
3193 			gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3194 			break;
3195 		case UNIFORM_FUNCTION_MATRIX2X3DV:
3196 			gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3197 			break;
3198 		case UNIFORM_FUNCTION_MATRIX2X4DV:
3199 			gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3200 			break;
3201 		case UNIFORM_FUNCTION_MATRIX3DV:
3202 			gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3203 			break;
3204 		case UNIFORM_FUNCTION_MATRIX3X2DV:
3205 			gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3206 			break;
3207 		case UNIFORM_FUNCTION_MATRIX3X4DV:
3208 			gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3209 			break;
3210 		case UNIFORM_FUNCTION_MATRIX4DV:
3211 			gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3212 			break;
3213 		case UNIFORM_FUNCTION_MATRIX4X2DV:
3214 			gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3215 			break;
3216 		case UNIFORM_FUNCTION_MATRIX4X3DV:
3217 			gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3218 			break;
3219 
3220 		default:
3221 		{
3222 			TCU_FAIL("Unrecognized uniform function");
3223 		}
3224 		} /* switch (func) */
3225 
3226 		/* Query the error code */
3227 		glw::GLenum error_code = gl.getError();
3228 
3229 		if (error_code != GL_INVALID_OPERATION)
3230 		{
3231 			m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3232 							   << getUniformFunctionString(static_cast<_uniform_function>(function))
3233 							   << "() was called without an active program object" << tcu::TestLog::EndMessage;
3234 
3235 			result = false;
3236 		}
3237 	} /* for (all uniform functions) */
3238 
3239 	return result;
3240 }
3241 
3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3244 const glw::GLint  GPUShaderFP64Test2::m_result_failure	 = 2;
3245 const glw::GLint  GPUShaderFP64Test2::m_result_success	 = 1;
3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width	  = 32;
3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height	 = m_n_captured_results / m_texture_width;
3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3249 	m_n_captured_results * sizeof(captured_varying_type);
3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name				  = "UniformBlock";
3251 const glw::GLenum  GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3252 
3253 /** Constructor
3254  *
3255  * @param context Test context
3256  **/
GPUShaderFP64Test2(deqp::Context & context)3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context)
3258 	: TestCase(context, "max_uniform_components",
3259 			   "Verifies that maximum allowed uniform components can be used as double-precision float types")
3260 	, m_pDispatchCompute(0)
3261 	, m_framebuffer_id(0)
3262 	, m_texture_id(0)
3263 	, m_transform_feedback_buffer_id(0)
3264 	, m_uniform_buffer_id(0)
3265 	, m_vertex_array_object_id(0)
3266 {
3267 	/* Nothing to be done */
3268 }
3269 
3270 /** Deinitialize test
3271  *
3272  **/
deinit()3273 void GPUShaderFP64Test2::deinit()
3274 {
3275 	/* GL entry points */
3276 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3277 
3278 	/* Clean frambuffer */
3279 	if (0 != m_framebuffer_id)
3280 	{
3281 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3282 		gl.deleteFramebuffers(1, &m_framebuffer_id);
3283 		m_framebuffer_id = 0;
3284 	}
3285 
3286 	/* Clean texture */
3287 	if (0 != m_texture_id)
3288 	{
3289 		gl.bindTexture(GL_TEXTURE_2D, 0);
3290 		gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3291 							GL_READ_ONLY, GL_RGBA8);
3292 		gl.deleteTextures(1, &m_texture_id);
3293 		m_texture_id = 0;
3294 	}
3295 
3296 	/* Clean buffers */
3297 	if (0 != m_transform_feedback_buffer_id)
3298 	{
3299 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3300 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3301 		m_transform_feedback_buffer_id = 0;
3302 	}
3303 
3304 	if (0 != m_uniform_buffer_id)
3305 	{
3306 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3307 		gl.deleteBuffers(1, &m_uniform_buffer_id);
3308 		m_uniform_buffer_id = 0;
3309 	}
3310 
3311 	/* Clean VAO */
3312 	if (0 != m_vertex_array_object_id)
3313 	{
3314 		gl.bindVertexArray(0);
3315 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3316 		m_vertex_array_object_id = 0;
3317 	}
3318 }
3319 
3320 /** Execute test
3321  *
3322  * @return tcu::TestNode::STOP
3323  **/
iterate()3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3325 {
3326 	bool result = true;
3327 
3328 	/* Check if extension is supported */
3329 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3330 	{
3331 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3332 	}
3333 
3334 	/* Initialize test */
3335 	testInit();
3336 
3337 	prepareShaderStages();
3338 	prepareUniformTypes();
3339 
3340 	/* For all shaders and uniform type combinations */
3341 	for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3342 		 m_shader_stages.end() != shader_stage; ++shader_stage)
3343 	{
3344 		for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3345 			 m_uniform_types.end() != uniform_type; ++uniform_type)
3346 		{
3347 			/* Execute test */
3348 			if (false == test(*shader_stage, *uniform_type))
3349 			{
3350 				result = false;
3351 			}
3352 		}
3353 	}
3354 
3355 	/* Set result */
3356 	if (true == result)
3357 	{
3358 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3359 	}
3360 	else
3361 	{
3362 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3363 	}
3364 
3365 	/* Done */
3366 	return tcu::TestNode::STOP;
3367 }
3368 
3369 /** Constructor
3370  *
3371  * @param n_columns Number of columns
3372  * @param n_rows    Number of rows
3373  **/
uniformTypeDetails(glw::GLuint n_columns,glw::GLuint n_rows)3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3375 	: m_n_columns(n_columns), m_n_rows(n_rows)
3376 {
3377 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3378 
3379 	m_type_name = Utils::getVariableTypeString(type);
3380 	m_type		= Utils::getGLDataTypeOfVariableType(type);
3381 }
3382 
3383 /** Get primitive type captured with transform feedback
3384  *
3385  * @param shader_stage Tested shader stage id
3386  *
3387  * @return Primitive type
3388  **/
getCapturedPrimitiveType(shaderStage shader_stage) const3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3390 {
3391 	switch (shader_stage)
3392 	{
3393 	case GEOMETRY_SHADER:
3394 	case TESS_CTRL_SHADER:
3395 	case TESS_EVAL_SHADER:
3396 	case VERTEX_SHADER:
3397 		return GL_POINTS;
3398 		break;
3399 
3400 	default:
3401 		return GL_NONE;
3402 		break;
3403 	}
3404 }
3405 
3406 /** Get primitive type drawn with DrawArrays
3407  *
3408  * @param shader_stage Tested shader stage id
3409  *
3410  * @return Primitive type
3411  **/
getDrawPrimitiveType(shaderStage shader_stage) const3412 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3413 {
3414 	switch (shader_stage)
3415 	{
3416 	case FRAGMENT_SHADER:
3417 		return GL_TRIANGLE_FAN;
3418 		break;
3419 
3420 	case GEOMETRY_SHADER:
3421 	case VERTEX_SHADER:
3422 		return GL_POINTS;
3423 		break;
3424 
3425 	case TESS_CTRL_SHADER:
3426 	case TESS_EVAL_SHADER:
3427 		return GL_PATCHES;
3428 		break;
3429 
3430 	default:
3431 		return GL_NONE;
3432 		break;
3433 	}
3434 }
3435 
3436 /** Get maximum allowed number of uniform components
3437  *
3438  * @param shader_stage Tested shader stage id
3439  *
3440  * @return Maxmimum uniform components
3441  **/
getMaxUniformComponents(shaderStage shader_stage) const3442 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3443 {
3444 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3445 	glw::GLint			  max_uniform_components = 0;
3446 	glw::GLenum			  pname					 = 0;
3447 
3448 	switch (shader_stage)
3449 	{
3450 	case COMPUTE_SHADER:
3451 		pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3452 		break;
3453 	case FRAGMENT_SHADER:
3454 		pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3455 		break;
3456 	case GEOMETRY_SHADER:
3457 		pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3458 		break;
3459 	case TESS_CTRL_SHADER:
3460 		pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3461 		break;
3462 	case TESS_EVAL_SHADER:
3463 		pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3464 		break;
3465 	case VERTEX_SHADER:
3466 		pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3467 		break;
3468 	}
3469 
3470 	gl.getIntegerv(pname, &max_uniform_components);
3471 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3472 
3473 	return max_uniform_components;
3474 }
3475 
3476 /** Get maximum size allowed for an uniform block
3477  *
3478  * @return Maxmimum uniform block size
3479  **/
getMaxUniformBlockSize() const3480 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3481 {
3482 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3483 	glw::GLint			  max_uniform_block_size = 0;
3484 
3485 	gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3486 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3487 
3488 	return max_uniform_block_size;
3489 }
3490 
3491 /** Get number of components required to store single uniform of given type
3492  *
3493  * @param uniform_type Tested uniform type
3494  *
3495  * @return Number of components
3496  **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3497 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3498 {
3499 	static const glw::GLuint type_size	 = 2; /* double takes 2 N */
3500 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3501 
3502 	if (1 == uniform_type.m_n_columns)
3503 	{
3504 		return type_size * column_length;
3505 	}
3506 	else
3507 	{
3508 		const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3509 
3510 		return alignment * uniform_type.m_n_columns;
3511 	}
3512 }
3513 
3514 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3515  *
3516  * @param uniform_type Tested uniform type
3517  *
3518  * @return Size of a single member
3519  **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3520 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3521 {
3522 	static const glw::GLuint vec4_size	 = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3523 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3524 
3525 	/** Size for a layout(std140, column_major) uniform_type uniform[] **/
3526 	return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3527 }
3528 
3529 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3530  *
3531  * @param shader_stage Tested shader stage id
3532  * @param uniform_type Tested uniform type
3533  *
3534  * @return Number of components
3535  **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3536 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage				shader_stage,
3537 												  const uniformTypeDetails& uniform_type) const
3538 {
3539 	const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
3540 	const glw::GLuint required_components	  = getRequiredComponentsNumber(uniform_type);
3541 	const glw::GLuint n_uniforms			   = max_uniform_components / required_components;
3542 	const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
3543 	const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3544 	const glw::GLuint max_uniforms			   = max_uniform_block_size / uniform_type_member_size;
3545 
3546 	return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3547 }
3548 
3549 /** Get name of shader stage
3550  *
3551  * @param shader_stage Tested shader stage id
3552  *
3553  * @return Name
3554  **/
getShaderStageName(shaderStage shader_stage) const3555 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3556 {
3557 	switch (shader_stage)
3558 	{
3559 	case COMPUTE_SHADER:
3560 		return "compute shader";
3561 		break;
3562 	case FRAGMENT_SHADER:
3563 		return "fragment shader";
3564 		break;
3565 	case GEOMETRY_SHADER:
3566 		return "geometry shader";
3567 		break;
3568 	case TESS_CTRL_SHADER:
3569 		return "tesselation control shader";
3570 		break;
3571 	case TESS_EVAL_SHADER:
3572 		return "tesselation evaluation shader";
3573 		break;
3574 	case VERTEX_SHADER:
3575 		return "vertex shader";
3576 		break;
3577 	}
3578 
3579 	return 0;
3580 }
3581 
3582 /** Inspect program to get: buffer_size, offset, strides and block index
3583  *
3584  * @param program_id          Program id
3585  * @param out_buffer_size     Size of uniform buffer
3586  * @param out_uniform_details Uniform offset and strides
3587  * @param uniform_block_index Uniform block index
3588  **/
inspectProgram(glw::GLuint program_id,glw::GLint n_uniforms,const uniformTypeDetails & uniform_type,glw::GLint & out_buffer_size,uniformDetails & out_uniform_details,glw::GLuint uniform_block_index) const3589 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3590 										const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3591 										uniformDetails& out_uniform_details, glw::GLuint uniform_block_index) const
3592 {
3593 	glw::GLint				 array_stride = 0;
3594 	std::vector<glw::GLchar> extracted_uniform_name;
3595 	const glw::Functions&	gl			   = m_context.getRenderContext().getFunctions();
3596 	glw::GLuint				 index		   = 0;
3597 	glw::GLint				 matrix_stride = 0;
3598 	glw::GLint				 offset		   = 0;
3599 	glw::GLsizei			 size		   = 0;
3600 	glw::GLenum				 type		   = 0;
3601 	const glw::GLchar*		 uniform_name  = 0;
3602 	std::string				 uniform_name_str;
3603 	std::stringstream		 uniform_name_stream;
3604 
3605 	/* Get index of uniform block */
3606 	uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3607 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3608 
3609 	if (GL_INVALID_INDEX == uniform_block_index)
3610 	{
3611 		TCU_FAIL("Unifom block is inactive");
3612 	}
3613 
3614 	/* Get size of uniform block */
3615 	gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3616 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3617 
3618 	if (0 == out_buffer_size)
3619 	{
3620 		TCU_FAIL("Unifom block size is 0");
3621 	}
3622 
3623 	/* Prepare uniform name */
3624 	uniform_name_stream << "uniform_array";
3625 
3626 	uniform_name_str = uniform_name_stream.str();
3627 	uniform_name	 = uniform_name_str.c_str();
3628 
3629 	/* Get index of uniform */
3630 	gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3632 
3633 	if (GL_INVALID_INDEX == index)
3634 	{
3635 		TCU_FAIL("Unifom is inactive");
3636 	}
3637 
3638 	/* Verify getActiveUniform results */
3639 	extracted_uniform_name.resize(uniform_name_str.length() * 2);
3640 
3641 	gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3642 						&extracted_uniform_name[0]);
3643 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3644 
3645 	if ((n_uniforms != size) || (uniform_type.m_type != type))
3646 	{
3647 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3648 											<< " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3649 											<< " expected: " << uniform_type.m_type
3650 											<< ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3651 
3652 		TCU_FAIL("Invalid GetActiveUniform results");
3653 	}
3654 
3655 	/* Get offset of uniform */
3656 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3657 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3658 
3659 	if (-1 == offset)
3660 	{
3661 		TCU_FAIL("Unifom has invalid offset");
3662 	}
3663 
3664 	out_uniform_details.m_offset = offset;
3665 
3666 	/* Get matrix stride of uniform */
3667 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3668 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3669 
3670 	if (-1 == matrix_stride)
3671 	{
3672 		TCU_FAIL("Unifom has invalid matrix stride");
3673 	}
3674 
3675 	out_uniform_details.m_matrix_stride = matrix_stride;
3676 
3677 	/* Get array stride of uniform */
3678 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3679 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3680 
3681 	if (-1 == matrix_stride)
3682 	{
3683 		TCU_FAIL("Unifom has invalid matrix stride");
3684 	}
3685 
3686 	out_uniform_details.m_array_stride = array_stride;
3687 }
3688 
3689 /** Prepare source code for "boilerplate" shaders
3690  *
3691  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3692  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3693  * @param out_source_code          Source code
3694  **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3695 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3696 												  const glw::GLchar* stage_specific_main_body,
3697 												  std::string&		 out_source_code) const
3698 {
3699 	/* Shader template */
3700 	static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3701 																 "\n"
3702 																 "precision highp float;\n"
3703 																 "\n"
3704 																 "STAGE_SPECIFIC_LAYOUT"
3705 																 "void main()\n"
3706 																 "{\n"
3707 																 "STAGE_SPECIFIC_MAIN_BODY"
3708 																 "}\n"
3709 																 "\n";
3710 
3711 	std::string string = boilerplate_shader_template_code;
3712 
3713 	/* Tokens */
3714 	static const glw::GLchar* body_token   = "STAGE_SPECIFIC_MAIN_BODY";
3715 	static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3716 
3717 	size_t search_position = 0;
3718 
3719 	/* Replace tokens */
3720 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3721 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3722 
3723 	/* Store resuls */
3724 	out_source_code = string;
3725 }
3726 
3727 /** Prepare program for given combination of shader stage and uniform type
3728  *
3729  * @param shader_stage     Shader stage
3730  * @param uniform_type     Uniform type
3731  * @param out_program_info Instance of programInfo
3732  **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3733 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3734 										Utils::programInfo& out_program_info) const
3735 {
3736 	/* Stage specific layouts */
3737 	static const glw::GLchar* geometry_shader_layout_code = "layout(points)                   in;\n"
3738 															"layout(points, max_vertices = 1) out;\n"
3739 															"\n";
3740 
3741 	static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3742 															 "\n";
3743 
3744 	static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3745 															 "\n";
3746 
3747 	/* Stage specific main body */
3748 	static const glw::GLchar* boilerplate_fragment_shader_body_code = "    discard;\n";
3749 
3750 	static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
3751 																	   "    gl_TessLevelOuter[1] = 1.0;\n"
3752 																	   "    gl_TessLevelOuter[2] = 1.0;\n"
3753 																	   "    gl_TessLevelOuter[3] = 1.0;\n"
3754 																	   "    gl_TessLevelInner[0] = 1.0;\n"
3755 																	   "    gl_TessLevelInner[1] = 1.0;\n";
3756 
3757 	static const glw::GLchar* boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
3758 
3759 	static const glw::GLchar* corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
3760 															   "    {\n"
3761 															   "        gl_Position = vec4(-1, -1, 0, 1);\n"
3762 															   "    }\n"
3763 															   "    else if (1 == gl_VertexID)\n"
3764 															   "    {\n"
3765 															   "        gl_Position = vec4(-1, 1, 0, 1);\n"
3766 															   "    }\n"
3767 															   "    else if (2 == gl_VertexID)\n"
3768 															   "    {\n"
3769 															   "        gl_Position = vec4(1, 1, 0, 1);\n"
3770 															   "    }\n"
3771 															   "    else if (3 == gl_VertexID)\n"
3772 															   "    {\n"
3773 															   "        gl_Position = vec4(1, -1, 0, 1);\n"
3774 															   "    }\n";
3775 
3776 	static const glw::GLchar* passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
3777 
3778 	static const glw::GLchar* test_shader_body_code = "\n    result = verification_result;\n";
3779 
3780 	static const glw::GLchar* test_geometry_shader_body_code = "\n    result = verification_result;\n"
3781 															   "\n"
3782 															   "    EmitVertex();\n"
3783 															   "    EndPrimitive();\n";
3784 
3785 	static const glw::GLchar* test_tess_ctrl_shader_body_code =
3786 		"\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
3787 		"\n"
3788 		"    gl_TessLevelOuter[0] = 1.0;\n"
3789 		"    gl_TessLevelOuter[1] = 1.0;\n"
3790 		"    gl_TessLevelOuter[2] = 1.0;\n"
3791 		"    gl_TessLevelOuter[3] = 1.0;\n"
3792 		"    gl_TessLevelInner[0] = 1.0;\n"
3793 		"    gl_TessLevelInner[1] = 1.0;\n";
3794 
3795 	/* In variables */
3796 	static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
3797 
3798 	/* Out variables */
3799 	static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3800 
3801 	static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3802 
3803 	static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3804 
3805 	/* Varying name */
3806 	static const glw::GLchar* varying_name = "result";
3807 	glw::GLuint				  n_varyings   = 1;
3808 
3809 	/* Storage for ready shaders */
3810 	std::string compute_shader_code;
3811 	std::string fragment_shader_code;
3812 	std::string geometry_shader_code;
3813 	std::string tess_ctrl_shader_code;
3814 	std::string tess_eval_shader_code;
3815 	std::string vertex_shader_code;
3816 
3817 	/* Storage for uniform definition and verification code */
3818 	std::string uniform_definitions;
3819 	std::string uniform_verification;
3820 
3821 	/* Get uniform definition and verification code */
3822 	prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3823 	prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3824 
3825 	/* Prepare vertex shader */
3826 	switch (shader_stage)
3827 	{
3828 	case FRAGMENT_SHADER:
3829 
3830 		prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3831 
3832 		break;
3833 
3834 	case GEOMETRY_SHADER:
3835 	case TESS_CTRL_SHADER:
3836 	case TESS_EVAL_SHADER:
3837 
3838 		prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3839 
3840 		break;
3841 
3842 	case VERTEX_SHADER:
3843 
3844 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3845 						  test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3846 						  test_shader_body_code /* body */, vertex_shader_code);
3847 
3848 		break;
3849 
3850 	default:
3851 		break;
3852 	}
3853 
3854 	/* Prepare fragment shader */
3855 	switch (shader_stage)
3856 	{
3857 	case FRAGMENT_SHADER:
3858 
3859 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3860 						  test_fragment_shader_out_variable /* out var */,
3861 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3862 						  fragment_shader_code);
3863 
3864 		break;
3865 
3866 	case GEOMETRY_SHADER:
3867 	case TESS_CTRL_SHADER:
3868 	case TESS_EVAL_SHADER:
3869 	case VERTEX_SHADER:
3870 
3871 		prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3872 								 fragment_shader_code);
3873 
3874 		break;
3875 
3876 	default:
3877 		break;
3878 	}
3879 
3880 	/* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3881 	switch (shader_stage)
3882 	{
3883 	case COMPUTE_SHADER:
3884 
3885 		prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3886 
3887 		break;
3888 
3889 	case GEOMETRY_SHADER:
3890 
3891 		prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3892 						  "" /* in var */, test_shader_out_variable /* out var */,
3893 						  uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3894 						  geometry_shader_code);
3895 
3896 		break;
3897 
3898 	case TESS_CTRL_SHADER:
3899 
3900 		prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3901 						  "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3902 						  uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3903 						  tess_ctrl_shader_code);
3904 
3905 		prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3906 						  test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3907 						  "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3908 						  tess_eval_shader_code);
3909 
3910 		break;
3911 
3912 	case TESS_EVAL_SHADER:
3913 
3914 		prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3915 								 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3916 
3917 		prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3918 						  "" /* in var */, test_shader_out_variable /* out var */,
3919 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3920 						  tess_eval_shader_code);
3921 
3922 		break;
3923 
3924 	default:
3925 		break;
3926 	};
3927 
3928 	/* Select shaders that will be used by program */
3929 	const glw::GLchar* cs_c_str  = 0;
3930 	const glw::GLchar* fs_c_str  = 0;
3931 	const glw::GLchar* gs_c_str  = 0;
3932 	const glw::GLchar* tcs_c_str = 0;
3933 	const glw::GLchar* tes_c_str = 0;
3934 	const glw::GLchar* vs_c_str  = 0;
3935 
3936 	if (false == compute_shader_code.empty())
3937 	{
3938 		cs_c_str = compute_shader_code.c_str();
3939 	}
3940 
3941 	if (false == fragment_shader_code.empty())
3942 	{
3943 		fs_c_str = fragment_shader_code.c_str();
3944 	}
3945 
3946 	if (false == geometry_shader_code.empty())
3947 	{
3948 		gs_c_str = geometry_shader_code.c_str();
3949 	}
3950 
3951 	if (false == tess_ctrl_shader_code.empty())
3952 	{
3953 		tcs_c_str = tess_ctrl_shader_code.c_str();
3954 	}
3955 
3956 	if (false == tess_eval_shader_code.empty())
3957 	{
3958 		tes_c_str = tess_eval_shader_code.c_str();
3959 	}
3960 
3961 	if (false == vertex_shader_code.empty())
3962 	{
3963 		vs_c_str = vertex_shader_code.c_str();
3964 	}
3965 
3966 	/* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3967 	if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3968 	{
3969 		n_varyings = 0;
3970 	}
3971 
3972 	/* Build */
3973 	out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
3974 }
3975 
3976 /** Prepare collection of tested shader stages
3977  *
3978  */
prepareShaderStages()3979 void GPUShaderFP64Test2::prepareShaderStages()
3980 {
3981 	/* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3982 	if (0 != m_pDispatchCompute)
3983 	{
3984 		m_shader_stages.push_back(COMPUTE_SHADER);
3985 	}
3986 
3987 	m_shader_stages.push_back(FRAGMENT_SHADER);
3988 	m_shader_stages.push_back(GEOMETRY_SHADER);
3989 	m_shader_stages.push_back(TESS_CTRL_SHADER);
3990 	m_shader_stages.push_back(TESS_EVAL_SHADER);
3991 	m_shader_stages.push_back(VERTEX_SHADER);
3992 }
3993 
3994 /** Prepare source code for "tested" shader stage
3995  *
3996  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3997  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
3998  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
3999  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
4000  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
4001  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
4002  * @param out_source_code          Shader source code
4003  **/
prepareTestShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * uniform_definitions,const glw::GLchar * in_variable_definitions,const glw::GLchar * out_variable_definitions,const glw::GLchar * uniform_verification,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const4004 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
4005 										   const glw::GLchar* uniform_definitions,
4006 										   const glw::GLchar* in_variable_definitions,
4007 										   const glw::GLchar* out_variable_definitions,
4008 										   const glw::GLchar* uniform_verification,
4009 										   const glw::GLchar* stage_specific_main_body,
4010 										   std::string&		  out_source_code) const
4011 {
4012 	/* Shader template */
4013 	static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4014 														  "\n"
4015 														  "precision highp float;\n"
4016 														  "\n"
4017 														  "STAGE_SPECIFIC_LAYOUT"
4018 														  "UNIFORM_DEFINITIONS"
4019 														  "IN_VARIABLE_DEFINITION"
4020 														  "OUT_VARIABLE_DEFINITION"
4021 														  "\n"
4022 														  "void main()\n"
4023 														  "{\n"
4024 														  "UNIFORM_VERIFICATION"
4025 														  "STAGE_SPECIFIC_MAIN_BODY"
4026 														  "}\n"
4027 														  "\n";
4028 
4029 	std::string string = test_shader_template_code;
4030 
4031 	/* Tokens */
4032 	static const glw::GLchar* body_token	= "STAGE_SPECIFIC_MAIN_BODY";
4033 	static const glw::GLchar* in_var_token  = "IN_VARIABLE_DEFINITION";
4034 	static const glw::GLchar* layout_token  = "STAGE_SPECIFIC_LAYOUT";
4035 	static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4036 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4037 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4038 
4039 	size_t search_position = 0;
4040 
4041 	/* Replace tokens */
4042 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4043 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4044 	Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4045 	Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4046 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4047 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4048 
4049 	/* Store resuls */
4050 	out_source_code = string;
4051 }
4052 
4053 /** Prepare source code for "tested" compute shaders
4054  *
4055  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
4056  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4057  * @param out_source_code      Source code
4058  **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4059 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4060 												  const glw::GLchar* uniform_verification,
4061 												  std::string&		 out_source_code) const
4062 {
4063 	/* Shader template */
4064 	static const glw::GLchar* test_shader_template_code =
4065 		"#version 420 core\n"
4066 		"#extension GL_ARB_compute_shader          : require\n"
4067 		"#extension GL_ARB_shader_image_load_store : require\n"
4068 		"\n"
4069 		"precision highp float;\n"
4070 		"\n"
4071 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4072 		"\n"
4073 		"UNIFORM_DEFINITIONS"
4074 		"layout(r32i) writeonly uniform iimage2D result;\n"
4075 		"\n"
4076 		"void main()\n"
4077 		"{\n"
4078 		"UNIFORM_VERIFICATION"
4079 		"\n"
4080 		"    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4081 		"}\n"
4082 		"\n";
4083 
4084 	std::string string = test_shader_template_code;
4085 
4086 	/* Tokens */
4087 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4088 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4089 
4090 	size_t search_position = 0;
4091 
4092 	/* Replace tokens */
4093 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4094 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4095 
4096 	/* Store resuls */
4097 	out_source_code = string;
4098 }
4099 
4100 /** Prepare source code which defines uniforms for tested shader stage
4101  *
4102  * @param shader_stage    Shader stage id
4103  * @param uniform_type    Details of uniform type
4104  * @param out_source_code Source code
4105  **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4106 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4107 												   std::string& out_source_code) const
4108 {
4109 	const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4110 	std::stringstream stream;
4111 
4112 	/*
4113 	 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4114 	 * {
4115 	 *     TYPE_NAME uniform_array[N_UNIFORMS];
4116 	 * };
4117 	 */
4118 	stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4119 																   "{\n";
4120 
4121 	stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4122 
4123 	stream << "};\n\n";
4124 
4125 	out_source_code = stream.str();
4126 }
4127 
4128 /** Prepare uniform buffer for test
4129  *
4130  * @param shader_stage Shader stage id
4131  * @param uniform_type Details of uniform type
4132  * @param program_info Program object info
4133  **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4134 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4135 										 const Utils::programInfo& program_info) const
4136 {
4137 	glw::GLint				  buffer_size	 = 0;
4138 	glw::GLuint				  element_ordinal = 1;
4139 	const glw::Functions&	 gl			  = m_context.getRenderContext().getFunctions();
4140 	const glw::GLuint		  n_columns		  = uniform_type.m_n_columns;
4141 	const glw::GLuint		  n_rows		  = uniform_type.m_n_rows;
4142 	const glw::GLuint		  n_elements	  = n_columns * n_rows;
4143 	uniformDetails			  uniform_details;
4144 	const glw::GLuint		  program_id = program_info.m_program_object_id;
4145 	const glw::GLint		  n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4146 	std::vector<glw::GLubyte> uniform_buffer_data;
4147 	glw::GLuint				  uniform_block_index = 0;
4148 
4149 	/* Get uniform details */
4150 	inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4151 
4152 	/* Uniform offset and strides */
4153 	const glw::GLuint array_stride   = uniform_details.m_array_stride;
4154 	const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
4155 	const glw::GLuint uniform_offset = uniform_details.m_offset;
4156 
4157 	/* Prepare storage for buffer data */
4158 	uniform_buffer_data.resize(buffer_size);
4159 
4160 	/* Prepare uniform data */
4161 	for (glw::GLint i = 0; i < n_uniforms; ++i)
4162 	{
4163 		const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4164 
4165 		for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4166 		{
4167 			const glw::GLuint   column		 = element / n_rows;
4168 			const glw::GLuint   column_elem  = element % n_rows;
4169 			const glw::GLdouble value		 = element_ordinal;
4170 			const glw::GLuint   value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4171 																	  column_elem * sizeof(glw::GLdouble));
4172 			glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4173 
4174 			*value_dst = value;
4175 		}
4176 	}
4177 
4178 	/* Update uniform buffer with new set of data */
4179 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4180 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4181 
4182 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4183 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4184 
4185 	/* Bind uniform block to uniform buffer */
4186 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4187 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4188 
4189 	gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4190 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4191 }
4192 
4193 /** Prepare collection of tested uniform types
4194  *
4195  **/
prepareUniformTypes()4196 void GPUShaderFP64Test2::prepareUniformTypes()
4197 {
4198 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4199 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4200 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4201 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4202 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4203 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4204 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4205 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4206 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4207 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4208 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4209 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4210 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4211 }
4212 
4213 /** Prepare source code that verifes uniform values
4214  *
4215  * @param shader_stage    Shader stage id
4216  * @param uniform_type    Details of uniform type
4217  * @param out_source_code Source code
4218  **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4219 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4220 													std::string& out_source_code) const
4221 {
4222 	glw::GLuint		  element_ordinal = 1;
4223 	const glw::GLuint n_columns		  = uniform_type.m_n_columns;
4224 	const glw::GLuint n_rows		  = uniform_type.m_n_rows;
4225 	const glw::GLuint n_elements	  = n_columns * n_rows;
4226 	const glw::GLuint n_uniforms	  = getAmountUniforms(shader_stage, uniform_type);
4227 	std::stringstream stream;
4228 
4229 	/*
4230 	 * int verification_result = M_RESULT_SUCCESS;
4231 	 *
4232 	 * for (int i = 0; i < N_UNIFORMS; ++i)
4233 	 * {
4234 	 *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4235 	 *     {
4236 	 *         verification_result = M_RESULT_FAILURE
4237 	 *     }
4238 	 * }
4239 	 */
4240 	stream << "    int verification_result = " << m_result_success << ";\n"
4241 																	  "\n"
4242 																	  "    for (int i = 0; i < "
4243 		   << n_uniforms << "; ++i)\n"
4244 							"    {\n"
4245 							"        if ("
4246 		   << uniform_type.m_type_name << "(";
4247 
4248 	for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4249 	{
4250 		stream << "i * (" << n_elements << ") + " << element + 1;
4251 
4252 		if (n_elements != element + 1)
4253 		{
4254 			stream << ", ";
4255 		}
4256 	}
4257 
4258 	stream << ") != uniform_array[i])\n"
4259 			  "        {\n"
4260 			  "           verification_result = "
4261 		   << m_result_failure << ";\n"
4262 								  "        }\n"
4263 								  "    }\n";
4264 
4265 	out_source_code = stream.str();
4266 }
4267 
4268 /** Execute test for given combination of "tested" shader stage and uniform type
4269  *
4270  * @param shader_stage Tested shader stage id
4271  * @param uniform_type Tested uniform type
4272  *
4273  * @return true if test passed, false otherwise
4274  **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4275 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4276 {
4277 	const glw::GLenum		draw_primitive = getDrawPrimitiveType(shader_stage);
4278 	static const glw::GLint first_vertex   = 0;
4279 	const glw::Functions&   gl			   = m_context.getRenderContext().getFunctions();
4280 	const glw::GLsizei		n_vertices	 = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4281 	Utils::programInfo		program_info(m_context);
4282 	bool					result = true;
4283 
4284 	/* Prepare program */
4285 	prepareProgram(shader_stage, uniform_type, program_info);
4286 
4287 	gl.useProgram(program_info.m_program_object_id);
4288 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4289 
4290 	/* Prepare uniform buffer and bind it with uniform block */
4291 	prepareUniforms(shader_stage, uniform_type, program_info);
4292 
4293 	/* Prepare storage for test results */
4294 	testBegin(program_info.m_program_object_id, shader_stage);
4295 
4296 	/* Execute */
4297 	if (COMPUTE_SHADER == shader_stage)
4298 	{
4299 		m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4300 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4301 	}
4302 	else
4303 	{
4304 		gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4305 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4306 	}
4307 
4308 	/* Clean after test */
4309 	testEnd(shader_stage);
4310 
4311 	/* Check results */
4312 	if (false == verifyResults(shader_stage))
4313 	{
4314 		m_context.getTestContext().getLog()
4315 			<< tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4316 			<< ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4317 
4318 		result = false;
4319 	}
4320 
4321 	return result;
4322 }
4323 
4324 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4325  *
4326  * @param program_id   Program object id
4327  * @param shader_stage Tested shader stage id
4328  **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4329 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4330 {
4331 	std::vector<glw::GLint> buffer_data;
4332 	const glw::GLenum		captured_primitive = getCapturedPrimitiveType(shader_stage);
4333 	const glw::Functions&   gl				   = m_context.getRenderContext().getFunctions();
4334 
4335 	/* Prepare buffer filled with m_result_failure */
4336 	buffer_data.resize(m_n_captured_results);
4337 	for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4338 	{
4339 		buffer_data[i] = m_result_failure;
4340 	}
4341 
4342 	/* Prepare buffer for test results */
4343 	switch (shader_stage)
4344 	{
4345 	case GEOMETRY_SHADER:
4346 	case TESS_CTRL_SHADER:
4347 	case TESS_EVAL_SHADER:
4348 	case VERTEX_SHADER:
4349 
4350 		/* Verify getTransformFeedbackVarying results */
4351 		{
4352 			glw::GLsizei size = 0;
4353 			glw::GLenum  type = 0;
4354 			glw::GLchar  name[16];
4355 
4356 			gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4357 										   name);
4358 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4359 
4360 			if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4361 			{
4362 				m_context.getTestContext().getLog()
4363 					<< tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4364 					<< " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4365 					<< ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4366 
4367 				TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4368 			}
4369 		}
4370 
4371 		/* Create/clean transform feedback buffer */
4372 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4373 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4374 
4375 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4376 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4377 
4378 		/* Set up transform feedback buffer */
4379 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4380 						   m_transform_feedback_buffer_size);
4381 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4382 
4383 		gl.beginTransformFeedback(captured_primitive);
4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4385 
4386 		break;
4387 
4388 	case FRAGMENT_SHADER:
4389 
4390 		/* Clean texture */
4391 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4392 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4393 
4394 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4395 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4396 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4397 
4398 		/* Set up texture as color attachment 0 */
4399 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4400 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4401 
4402 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4403 		GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4404 
4405 		gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4406 		GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4407 
4408 		break;
4409 
4410 	case COMPUTE_SHADER:
4411 
4412 		/* Clean texture */
4413 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4414 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4415 
4416 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4417 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4418 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4419 
4420 		glw::GLint location = gl.getUniformLocation(program_id, "result");
4421 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4422 
4423 		if (-1 == location)
4424 		{
4425 			TCU_FAIL("Inactive uniform \"result\"");
4426 		}
4427 
4428 		gl.uniform1i(location, 0 /* first image unit */);
4429 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4430 
4431 		/* Bind texture to first image unit */
4432 		gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4433 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4434 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4435 
4436 		break;
4437 	}
4438 }
4439 
4440 /** Unbind transform feedback buffer, framebuffer or image unit
4441  *
4442  * @param shader_stage Tested shader stage id
4443  **/
testEnd(shaderStage shader_stage) const4444 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4445 {
4446 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4447 
4448 	switch (shader_stage)
4449 	{
4450 	case GEOMETRY_SHADER:
4451 	case TESS_CTRL_SHADER:
4452 	case TESS_EVAL_SHADER:
4453 	case VERTEX_SHADER:
4454 
4455 		gl.endTransformFeedback();
4456 
4457 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4458 
4459 		break;
4460 
4461 	case FRAGMENT_SHADER:
4462 
4463 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4464 								0 /* level */);
4465 
4466 		gl.bindTexture(GL_TEXTURE_2D, 0);
4467 
4468 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4469 
4470 		break;
4471 
4472 	case COMPUTE_SHADER:
4473 
4474 		gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4475 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4476 
4477 		break;
4478 	}
4479 }
4480 
4481 /** Initialize OpenGL objects for test
4482  *
4483  **/
testInit()4484 void GPUShaderFP64Test2::testInit()
4485 {
4486 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4487 
4488 	/* The test is in 4.0 group. However:
4489 	 * - compute_shader is core since 4.3
4490 	 * - compute_shader require at least version 4.2 of GL */
4491 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4492 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4493 	{
4494 		m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4495 	}
4496 
4497 	/* Tesselation patch set up */
4498 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
4499 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4500 
4501 	/* Generate FBO */
4502 	gl.genFramebuffers(1, &m_framebuffer_id);
4503 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4504 
4505 	/* Prepare texture */
4506 	gl.genTextures(1, &m_texture_id);
4507 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4508 
4509 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4510 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4511 
4512 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4513 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4514 
4515 	/* Prepare transform feedback buffer */
4516 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
4517 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4518 
4519 	/* Generate uniform buffer */
4520 	gl.genBuffers(1, &m_uniform_buffer_id);
4521 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4522 
4523 	/* Prepare VAO */
4524 	gl.genVertexArrays(1, &m_vertex_array_object_id);
4525 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4526 
4527 	gl.bindVertexArray(m_vertex_array_object_id);
4528 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4529 }
4530 
4531 /** Result verification, expected result is that whole buffer is filled with m_result_success
4532  *
4533  * @param shader_stage Tested shader stage id
4534  **/
verifyResults(shaderStage shader_stage) const4535 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4536 {
4537 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4538 
4539 	if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4540 	{
4541 		/* Verify contents of texture */
4542 
4543 		/* Prepare storage for testure data */
4544 		std::vector<glw::GLint> image_data;
4545 		image_data.resize(m_texture_width * m_texture_height);
4546 
4547 		/* Get texture contents */
4548 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4549 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4550 
4551 		gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4552 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4553 
4554 		for (glw::GLuint y = 0; y < m_texture_width; ++y)
4555 		{
4556 			for (glw::GLuint x = 0; x < m_texture_height; ++x)
4557 			{
4558 				const glw::GLuint offset = y * m_texture_width + x;
4559 				const glw::GLint  value  = image_data[offset];
4560 
4561 				if (m_result_success != value)
4562 				{
4563 					m_context.getTestContext().getLog()
4564 						<< tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4565 						<< tcu::TestLog::EndMessage;
4566 
4567 					return false;
4568 				}
4569 			}
4570 		}
4571 
4572 		return true;
4573 	}
4574 	else
4575 	{
4576 		/* Verify contents of transform feedback buffer */
4577 
4578 		bool result = true;
4579 
4580 		/* Get transform feedback data */
4581 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4582 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4583 
4584 		glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4585 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4586 
4587 		for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4588 		{
4589 			const glw::GLint value = feedback_data[i];
4590 
4591 			if (m_result_success != value)
4592 			{
4593 				m_context.getTestContext().getLog() << tcu::TestLog::Message
4594 													<< "Error. Transform feedback buffer contents are wrong at " << i
4595 													<< tcu::TestLog::EndMessage;
4596 
4597 				result = false;
4598 				break;
4599 			}
4600 		}
4601 
4602 		/* Unmap transform feedback buffer */
4603 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4604 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4605 
4606 		return result;
4607 	}
4608 }
4609 
4610 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4611 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4612 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4613 
4614 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name			 = "UniformBlock";
4615 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4616 
4617 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
4618 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result	= "gs_fs_gs_result";
4619 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
4620 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
4621 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result	= "gs_fs_vs_result";
4622 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4623 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
4624 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
4625 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
4626 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
4627 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
4628 
4629 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4630 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset			 = -1;
4631 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride	= -1;
4632 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4633 
4634 /** Constructor
4635  *
4636  * @param context Test context
4637  **/
GPUShaderFP64Test3(deqp::Context & context)4638 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4639 	: TestCase(context, "named_uniform_blocks",
4640 			   "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4641 {
4642 	/* Nothing to be done */
4643 }
4644 
4645 /** Deinitialize test
4646  *
4647  **/
deinit()4648 void GPUShaderFP64Test3::deinit()
4649 {
4650 	/* GL entry points */
4651 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4652 
4653 	/* Clean programs */
4654 	m_packed_program.deinit(m_context);
4655 	m_shared_program.deinit(m_context);
4656 	m_std140_program.deinit(m_context);
4657 
4658 	/* Clean frambuffer */
4659 	if (0 != m_framebuffer_id)
4660 	{
4661 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4662 		gl.deleteFramebuffers(1, &m_framebuffer_id);
4663 
4664 		m_framebuffer_id = 0;
4665 	}
4666 
4667 	/* Clean texture */
4668 	if (0 != m_color_texture_id)
4669 	{
4670 		gl.bindTexture(GL_TEXTURE_2D, 0);
4671 		gl.deleteTextures(1, &m_color_texture_id);
4672 
4673 		m_color_texture_id = 0;
4674 	}
4675 
4676 	/* Clean buffers */
4677 	if (0 != m_transform_feedback_buffer_id)
4678 	{
4679 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4680 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4681 
4682 		m_transform_feedback_buffer_id = 0;
4683 	}
4684 
4685 	if (0 != m_uniform_buffer_id)
4686 	{
4687 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4688 		gl.deleteBuffers(1, &m_uniform_buffer_id);
4689 
4690 		m_uniform_buffer_id = 0;
4691 	}
4692 
4693 	/* Clean VAO */
4694 	if (0 != m_vertex_array_object_id)
4695 	{
4696 		gl.bindVertexArray(0);
4697 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4698 
4699 		m_vertex_array_object_id = 0;
4700 	}
4701 }
4702 
4703 /** Execute test
4704  *
4705  * @return tcu::TestNode::STOP
4706  **/
iterate()4707 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4708 {
4709 	bool result = true;
4710 
4711 	/* Check if extension is supported */
4712 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4713 	{
4714 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4715 	}
4716 
4717 	/* Initialize test */
4718 	testInit();
4719 
4720 	/* Test "packed" uniform buffer layout */
4721 	if (false == test(PACKED))
4722 	{
4723 		result = false;
4724 	}
4725 
4726 	/* Test "shared" uniform buffer layout */
4727 	if (false == test(SHARED))
4728 	{
4729 		result = false;
4730 	}
4731 
4732 	/* Test "std140" uniform buffer layout */
4733 	if (false == test(STD140))
4734 	{
4735 		result = false;
4736 	}
4737 
4738 	/* Set result */
4739 	if (true == result)
4740 	{
4741 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4742 	}
4743 	else
4744 	{
4745 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4746 	}
4747 
4748 	/* Done */
4749 	return tcu::TestNode::STOP;
4750 }
4751 
4752 /** Constructor
4753  *
4754  **/
programInfo()4755 GPUShaderFP64Test3::programInfo::programInfo()
4756 	: m_fragment_shader_id(0)
4757 	, m_geometry_shader_id(0)
4758 	, m_program_object_id(0)
4759 	, m_tesselation_control_shader_id(0)
4760 	, m_tesselation_evaluation_shader_id(0)
4761 	, m_vertex_shader_id(0)
4762 	, m_buffer_size(0)
4763 	, m_uniform_block_index(0)
4764 {
4765 	/* Nothing to be done here */
4766 }
4767 
4768 /** Compile shader
4769  *
4770  * @param context     Test context
4771  * @param shader_id   Shader object id
4772  * @param shader_code Shader source code
4773  **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4774 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4775 											  const glw::GLchar* shader_code) const
4776 {
4777 	/* GL entry points */
4778 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4779 
4780 	/* Compilation status */
4781 	glw::GLint status = GL_FALSE;
4782 
4783 	/* Set source code */
4784 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4785 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4786 
4787 	/* Compile */
4788 	gl.compileShader(shader_id);
4789 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4790 
4791 	/* Get compilation status */
4792 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4793 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4794 
4795 	/* Log compilation error */
4796 	if (GL_TRUE != status)
4797 	{
4798 		glw::GLint				 length = 0;
4799 		std::vector<glw::GLchar> message;
4800 
4801 		/* Error log length */
4802 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4803 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4804 
4805 		/* Prepare storage */
4806 		message.resize(length);
4807 
4808 		/* Get error log */
4809 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4810 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4811 
4812 		/* Log */
4813 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4814 										  << &message[0] << "\nShader source\n"
4815 										  << shader_code << tcu::TestLog::EndMessage;
4816 
4817 		TCU_FAIL("Failed to compile shader");
4818 	}
4819 }
4820 
4821 /** Cleans program and attached shaders
4822  *
4823  * @param context Test context
4824  **/
deinit(deqp::Context & context)4825 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4826 {
4827 	/* GL entry points */
4828 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4829 
4830 	/* Restore default program */
4831 	gl.useProgram(0);
4832 
4833 	/* Clean program object */
4834 	if (0 != m_program_object_id)
4835 	{
4836 		gl.deleteProgram(m_program_object_id);
4837 		m_program_object_id = 0;
4838 	}
4839 
4840 	/* Clean shaders */
4841 	if (0 != m_fragment_shader_id)
4842 	{
4843 		gl.deleteShader(m_fragment_shader_id);
4844 		m_fragment_shader_id = 0;
4845 	}
4846 
4847 	if (0 != m_geometry_shader_id)
4848 	{
4849 		gl.deleteShader(m_geometry_shader_id);
4850 		m_geometry_shader_id = 0;
4851 	}
4852 
4853 	if (0 != m_tesselation_control_shader_id)
4854 	{
4855 		gl.deleteShader(m_tesselation_control_shader_id);
4856 		m_tesselation_control_shader_id = 0;
4857 	}
4858 
4859 	if (0 != m_tesselation_evaluation_shader_id)
4860 	{
4861 		gl.deleteShader(m_tesselation_evaluation_shader_id);
4862 		m_tesselation_evaluation_shader_id = 0;
4863 	}
4864 
4865 	if (0 != m_vertex_shader_id)
4866 	{
4867 		gl.deleteShader(m_vertex_shader_id);
4868 		m_vertex_shader_id = 0;
4869 	}
4870 }
4871 
4872 /** Build program and query for uniform layout
4873  *
4874  * @param context                            Test context
4875  * @param uniform_details                  Collection of uniform details
4876  * @param fragment_shader_code               Fragment shader source code
4877  * @param geometry_shader_code               Geometry shader source code
4878  * @param tesselation_control_shader_code    Tesselation control shader source code
4879  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4880  * @param vertex_shader_code                 Vertex shader source code
4881  **/
init(deqp::Context & context,const std::vector<uniformDetails> uniform_details,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code)4882 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4883 										   const glw::GLchar* fragment_shader_code,
4884 										   const glw::GLchar* geometry_shader_code,
4885 										   const glw::GLchar* tesselation_control_shader_code,
4886 										   const glw::GLchar* tesselation_evaluation_shader_code,
4887 										   const glw::GLchar* vertex_shader_code)
4888 {
4889 	/* GL entry points */
4890 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4891 
4892 	/* Names of varyings to be captured with transform feedback */
4893 	static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4894 												  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4895 	static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4896 
4897 	/* Create shader objects */
4898 	m_fragment_shader_id			   = gl.createShader(GL_FRAGMENT_SHADER);
4899 	m_geometry_shader_id			   = gl.createShader(GL_GEOMETRY_SHADER);
4900 	m_tesselation_control_shader_id	= gl.createShader(GL_TESS_CONTROL_SHADER);
4901 	m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4902 	m_vertex_shader_id				   = gl.createShader(GL_VERTEX_SHADER);
4903 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4904 
4905 	/* Create program object */
4906 	m_program_object_id = gl.createProgram();
4907 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4908 
4909 	/* Set up names of varyings to be captured with transform feedback */
4910 	gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4911 	GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4912 
4913 	/* Compile shaders */
4914 	compile(context, m_fragment_shader_id, fragment_shader_code);
4915 	compile(context, m_geometry_shader_id, geometry_shader_code);
4916 	compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4917 	compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4918 	compile(context, m_vertex_shader_id, vertex_shader_code);
4919 
4920 	/* Link program */
4921 	link(context);
4922 
4923 	/* Inspect program object */
4924 	/* Get index of named uniform block */
4925 	m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4926 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4927 
4928 	if (GL_INVALID_INDEX == m_uniform_block_index)
4929 	{
4930 		TCU_FAIL("Unifom block is inactive");
4931 	}
4932 
4933 	/* Get size of named uniform block */
4934 	gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4935 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4936 
4937 	if (0 == m_buffer_size)
4938 	{
4939 		TCU_FAIL("Unifom block size is 0");
4940 	}
4941 
4942 	/* Get information about "double precision" uniforms */
4943 	for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4944 		 end != it; ++it)
4945 	{
4946 		const glw::GLchar* uniform_name = 0;
4947 		std::string		   uniform_name_str;
4948 		std::stringstream  uniform_name_stream;
4949 		glw::GLuint		   index		 = 0;
4950 		glw::GLint		   offset		 = 0;
4951 		glw::GLint		   matrix_stride = 0;
4952 
4953 		/* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4954 		uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4955 
4956 		uniform_name_str = uniform_name_stream.str();
4957 		uniform_name	 = uniform_name_str.c_str();
4958 
4959 		/* Get index of uniform */
4960 		gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4961 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4962 
4963 		if (GL_INVALID_INDEX == index)
4964 		{
4965 			TCU_FAIL("Unifom is inactive");
4966 		}
4967 
4968 		/* Get offset of uniform */
4969 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4970 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4971 
4972 		if (m_invalid_uniform_offset == offset)
4973 		{
4974 			TCU_FAIL("Unifom has invalid offset");
4975 		}
4976 
4977 		m_uniform_offsets.push_back(offset);
4978 
4979 		/* Get matrix stride of uniform */
4980 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4981 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4982 
4983 		if (m_invalid_uniform_matrix_stride == offset)
4984 		{
4985 			TCU_FAIL("Unifom has invalid matrix stride");
4986 		}
4987 
4988 		m_uniform_matrix_strides.push_back(matrix_stride);
4989 	}
4990 }
4991 
4992 /** Attach shaders and link program
4993  *
4994  * @param context Test context
4995  **/
link(deqp::Context & context) const4996 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4997 {
4998 	/* GL entry points */
4999 	const glw::Functions& gl = context.getRenderContext().getFunctions();
5000 
5001 	/* Link status */
5002 	glw::GLint status = GL_FALSE;
5003 
5004 	/* Attach shaders */
5005 	gl.attachShader(m_program_object_id, m_fragment_shader_id);
5006 	gl.attachShader(m_program_object_id, m_geometry_shader_id);
5007 	gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
5008 	gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
5009 	gl.attachShader(m_program_object_id, m_vertex_shader_id);
5010 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
5011 
5012 	/* Link */
5013 	gl.linkProgram(m_program_object_id);
5014 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5015 
5016 	/* Get link status */
5017 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5018 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5019 
5020 	/* Log link error */
5021 	if (GL_TRUE != status)
5022 	{
5023 		glw::GLint				 length = 0;
5024 		std::vector<glw::GLchar> message;
5025 
5026 		/* Get error log length */
5027 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5028 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5029 
5030 		message.resize(length);
5031 
5032 		/* Get error log */
5033 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5034 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5035 
5036 		/* Log */
5037 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5038 										  << &message[0] << tcu::TestLog::EndMessage;
5039 
5040 		TCU_FAIL("Failed to link program");
5041 	}
5042 }
5043 
5044 /** Returns "predefined" values that will be used to fill uniform data
5045  *
5046  * @param type_ordinal Ordinal number of "double precision" uniform type
5047  * @param element      Index of element in uniform
5048  *
5049  * @return "Predefined" value
5050  **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5051 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5052 {
5053 	return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5054 		   ((m_base_element - (glw::GLdouble)element) / 4.0);
5055 }
5056 
5057 /** Returns a reference of programInfo instance specific for given buffer layout
5058  *
5059  * @param uniform_data_layout Buffer layout
5060  *
5061  * @return Reference to an instance of programInfo
5062  **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5063 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5064 {
5065 	const programInfo* program_info = 0;
5066 
5067 	switch (uniform_data_layout)
5068 	{
5069 	case PACKED:
5070 
5071 		program_info = &m_packed_program;
5072 
5073 		break;
5074 
5075 	case SHARED:
5076 
5077 		program_info = &m_shared_program;
5078 
5079 		break;
5080 
5081 	case STD140:
5082 
5083 		program_info = &m_std140_program;
5084 
5085 		break;
5086 	}
5087 
5088 	return *program_info;
5089 }
5090 
5091 /** Get "name" of buffer layout
5092  *
5093  * @param uniform_data_layout Buffer layout
5094  *
5095  * @return "Name" of layout
5096  **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5097 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5098 {
5099 	const glw::GLchar* layout = "";
5100 
5101 	switch (uniform_data_layout)
5102 	{
5103 	case PACKED:
5104 		layout = "packed";
5105 		break;
5106 	case SHARED:
5107 		layout = "shared";
5108 		break;
5109 	case STD140:
5110 		layout = "std140";
5111 		break;
5112 	}
5113 
5114 	return layout;
5115 }
5116 
5117 /** Prepare programInfo instance for specific buffer layout
5118  *
5119  * @param program_info        Instance of programInfo
5120  * @param uniform_data_layout Buffer layout
5121  **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5122 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5123 {
5124 	/* Storage for shader source code */
5125 	std::stringstream fragment_shader_code;
5126 	std::stringstream geometry_shader_code;
5127 	std::stringstream tess_control_shader_code;
5128 	std::stringstream tess_eval_shader_code;
5129 	std::stringstream vertex_shader_code;
5130 
5131 	/* Write preambles */
5132 	writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5133 	writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5134 	writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5135 	writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5136 	writePreamble(vertex_shader_code, VERTEX_SHADER);
5137 
5138 	/* Write definition of named uniform block */
5139 	writeUniformBlock(fragment_shader_code, uniform_data_layout);
5140 	writeUniformBlock(geometry_shader_code, uniform_data_layout);
5141 	writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5142 	writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5143 	writeUniformBlock(vertex_shader_code, uniform_data_layout);
5144 
5145 	/* Write definitions of varyings */
5146 	writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5147 	writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5148 	writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5149 	writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5150 	writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5151 
5152 	/* Write main routine */
5153 	writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5154 	writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5155 	writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5156 	writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5157 	writeMainBody(vertex_shader_code, VERTEX_SHADER);
5158 
5159 	/* Init programInfo instance */
5160 	program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5161 					  geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5162 					  tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5163 }
5164 
5165 /** Prepare uniform buffer
5166  *
5167  * @param program_info   Instance of programInfo
5168  * @param verify_offsets If uniform offsets should be verified against expected values
5169  *
5170  * @return false if uniform offsets verification result is failure, true otherwise
5171  **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5172 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5173 {
5174 	const glw::GLuint							buffer_size = program_info.m_buffer_size;
5175 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
5176 	bool										offset_verification_result = true;
5177 	glw::GLuint									type_ordinal			   = 1;
5178 	std::vector<uniformDetails>::const_iterator it_uniform_details		   = m_uniform_details.begin();
5179 	std::vector<glw::GLint>::const_iterator		it_uniform_offsets		   = program_info.m_uniform_offsets.begin();
5180 	std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5181 
5182 	/* Prepare storage for uniform buffer data */
5183 	std::vector<glw::GLubyte> buffer_data;
5184 	buffer_data.resize(buffer_size);
5185 
5186 	/* For each "double precision" uniform */
5187 	for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5188 		 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5189 	{
5190 		const glw::GLint  matrix_stride  = *it_uniform_matrix_strides;
5191 		const glw::GLuint n_columns		 = it_uniform_details->m_n_columns;
5192 		const glw::GLuint n_elements	 = it_uniform_details->m_n_elements;
5193 		const glw::GLuint column_length  = n_elements / n_columns;
5194 		const glw::GLint  uniform_offset = *it_uniform_offsets;
5195 
5196 		/* For each element of uniform */
5197 		for (glw::GLuint element = 0; element < n_elements; ++element)
5198 		{
5199 			const glw::GLuint   column		= element / column_length;
5200 			const glw::GLuint   column_elem = element % column_length;
5201 			const glw::GLdouble value		= getExpectedValue(type_ordinal, element);
5202 			const glw::GLuint   value_offset =
5203 				static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5204 
5205 			glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5206 
5207 			/* Store value */
5208 			*value_dst = value;
5209 		}
5210 
5211 		/* Uniform offset verification */
5212 		if (true == verify_offsets)
5213 		{
5214 			const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5215 
5216 			if (expected_offset != uniform_offset)
5217 			{
5218 				if (true == offset_verification_result)
5219 				{
5220 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5221 				}
5222 
5223 				m_context.getTestContext().getLog()
5224 					<< tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5225 					<< " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5226 					<< tcu::TestLog::EndMessage;
5227 
5228 				offset_verification_result = false;
5229 			}
5230 		}
5231 	}
5232 
5233 	/* Update uniform buffer with prepared data */
5234 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5235 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5236 
5237 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5238 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5239 
5240 	/* Bind uniform buffer as data source for named uniform block */
5241 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5242 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5243 
5244 	gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5245 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5246 
5247 	/* Done */
5248 	return offset_verification_result;
5249 }
5250 
5251 /** Prepare data, execute draw call and verify results
5252  *
5253  * @param uniform_data_layout
5254  *
5255  * @return true if test pass, false otherwise
5256  **/
test(uniformDataLayout uniform_data_layout) const5257 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5258 {
5259 	bool				  are_offsets_verified		 = (STD140 == uniform_data_layout);
5260 	const glw::Functions& gl						 = m_context.getRenderContext().getFunctions();
5261 	bool				  offset_verification_result = true;
5262 	const programInfo&	program_info				 = getProgramInfo(uniform_data_layout);
5263 	bool				  result					 = true;
5264 
5265 	/* Set up program */
5266 	gl.useProgram(program_info.m_program_object_id);
5267 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5268 
5269 	/* Prepare uniform buffer */
5270 	offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5271 
5272 	if (true == are_offsets_verified && false == offset_verification_result)
5273 	{
5274 		/* Offsets verification failure was already reported, add info about buffer layout */
5275 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5276 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5277 											<< tcu::TestLog::EndMessage;
5278 
5279 		result = false;
5280 	}
5281 
5282 	/* Set up transform feedback buffer */
5283 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5284 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5285 
5286 	/* Begin transform feedback */
5287 	gl.beginTransformFeedback(GL_POINTS);
5288 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5289 
5290 	/* Execute draw call for singe vertex */
5291 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5292 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5293 
5294 	/* Stop transform feedback */
5295 	gl.endTransformFeedback();
5296 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5297 
5298 	/* Verify results */
5299 	if (false == verifyResults())
5300 	{
5301 		/* Result verificatioon failure was already reported, add info about layout */
5302 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5303 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5304 											<< tcu::TestLog::EndMessage;
5305 
5306 		result = false;
5307 	}
5308 
5309 	/* Done */
5310 	return result;
5311 }
5312 
testInit()5313 void GPUShaderFP64Test3::testInit()
5314 {
5315 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5316 
5317 	/* Uniform block declaration with std140 offsets calculated
5318 	 *                       | align | loc_req | begins | ends | offset in bytes | imp |
5319 	 * ivec3   dummy1[3]     |     4 |      12 |      0 |   12 |               0 |     |
5320 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5321 	 * bool    dummy2        |     1 |       1 |     14 |   15 |              56 |     |
5322 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5323 	 * bvec3   dummy3        |     4 |       4 |     20 |   24 |              80 |     |
5324 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5325 	 * int     dummy4[3]     |     4 |      12 |     32 |   44 |             128 |     |
5326 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5327 	 * bool    dummy5        |     1 |       1 |     56 |   57 |             224 |     |
5328 	 * bool    dummy6[2]     |     4 |       8 |     60 |   68 |             240 |     |
5329 	 * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
5330 	 * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
5331 	 * bool    dummy7        |     1 |       1 |    104 |  105 |             416 |     |
5332 	 * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
5333 	 * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
5334 	 * uvec3   dummy8        |     4 |       4 |    160 |  164 |             640 |     |
5335 	 * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
5336 	 * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
5337 	 * bool    dummy9        |     1 |       1 |    196 |  197 |             784 |     |
5338 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5339 	 * int     dummy10       |     1 |       1 |    224 |  225 |             896 |     |
5340 	 * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
5341 	 * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
5342 	 */
5343 
5344 	/* Prepare "double precision" unfiorms' details */
5345 	m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5346 											   1 /* n_elements */, "double" /* type_name */));
5347 	m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5348 											   2 /* n_elements */, "dvec2" /* type_name */));
5349 	m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5350 											   3 /* n_elements */, "dvec3" /* type_name */));
5351 	m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5352 											   4 /* n_elements */, "dvec4" /* type_name */));
5353 	m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5354 											   4 /* n_elements */, "dmat2" /* type_name */));
5355 	m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5356 											   9 /* n_elements */, "dmat3" /* type_name */));
5357 	m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5358 											   16 /* n_elements */, "dmat4" /* type_name */));
5359 	m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5360 											   6 /* n_elements */, "dmat2x3" /* type_name */));
5361 	m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5362 											   8 /* n_elements */, "dmat2x4" /* type_name */));
5363 	m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5364 											   6 /* n_elements */, "dmat3x2" /* type_name */));
5365 	m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5366 											   12 /* n_elements */, "dmat3x4" /* type_name */));
5367 	m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5368 											   8 /* n_elements */, "dmat4x2" /* type_name */));
5369 	m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5370 											   12 /* n_elements */, "dmat4x3" /* type_name */));
5371 
5372 	/* Get random values for getExpectedValue */
5373 	m_base_element		= (glw::GLdouble)(rand() % 13);
5374 	m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5375 
5376 	/* Prepare programInfos for all buffer layouts */
5377 	prepareProgram(m_packed_program, PACKED);
5378 	prepareProgram(m_shared_program, SHARED);
5379 	prepareProgram(m_std140_program, STD140);
5380 
5381 	/* Generate buffers */
5382 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
5383 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5384 
5385 	gl.genBuffers(1, &m_uniform_buffer_id);
5386 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5387 
5388 	/* Prepare transform feedback buffer */
5389 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5390 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5391 
5392 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5393 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5394 
5395 	/* Prepare texture for color attachment 0 */
5396 	gl.genTextures(1, &m_color_texture_id);
5397 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5398 
5399 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5400 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5401 
5402 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5403 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5404 
5405 	/* Prepare FBO with color attachment 0 */
5406 	gl.genFramebuffers(1, &m_framebuffer_id);
5407 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5408 
5409 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5410 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5411 
5412 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5413 							0 /* level */);
5414 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5415 
5416 	gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5417 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5418 
5419 	/* Prepare VAO */
5420 	gl.genVertexArrays(1, &m_vertex_array_object_id);
5421 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5422 
5423 	gl.bindVertexArray(m_vertex_array_object_id);
5424 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5425 
5426 	/* Tesselation patch set up */
5427 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
5428 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5429 }
5430 
5431 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5432  *
5433  * @return true if all values are as expected, false otherwise
5434  **/
verifyResults() const5435 bool GPUShaderFP64Test3::verifyResults() const
5436 {
5437 	glw::GLint*			  feedback_data			  = 0;
5438 	bool				  fragment_shader_result  = false;
5439 	bool				  geometry_shader_result  = false;
5440 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
5441 	bool				  tess_ctrl_shader_result = false;
5442 	bool				  tess_eval_shader_result = false;
5443 	bool				  vertex_shader_result	= false;
5444 
5445 	/* Prepare storage for testure data */
5446 	std::vector<glw::GLint> image_data;
5447 	image_data.resize(1);
5448 
5449 	/* Get texture contents */
5450 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5451 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5452 
5453 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5454 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5455 
5456 	/* Get transform feedback data */
5457 	feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5458 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5459 
5460 	/* Verify results */
5461 	fragment_shader_result  = (m_result_success == image_data[0]);
5462 	geometry_shader_result  = (m_result_success == feedback_data[0]);
5463 	tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5464 	tess_eval_shader_result = (m_result_success == feedback_data[2]);
5465 	vertex_shader_result	= (m_result_success == feedback_data[3]);
5466 
5467 	/* Unmap transform feedback buffer */
5468 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5469 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5470 
5471 	/* Set result */
5472 	if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5473 				 tess_eval_shader_result && vertex_shader_result))
5474 	{
5475 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5476 
5477 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 											<< "Vertex shader stage result: " << vertex_shader_result
5479 											<< tcu::TestLog::EndMessage;
5480 
5481 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 											<< "Tesselation control shader stage result: " << tess_ctrl_shader_result
5483 											<< tcu::TestLog::EndMessage;
5484 
5485 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5486 											<< "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5487 											<< tcu::TestLog::EndMessage;
5488 
5489 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5490 											<< "Geometry shader stage result: " << geometry_shader_result
5491 											<< tcu::TestLog::EndMessage;
5492 
5493 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5494 											<< "Fragment shader stage result: " << fragment_shader_result
5495 											<< tcu::TestLog::EndMessage;
5496 
5497 		return false;
5498 	}
5499 	else
5500 	{
5501 		return true;
5502 	}
5503 }
5504 
5505 /** Write main routine of <shader_stage> shader to stream
5506  *
5507  * @param stream       Output stream with source code of shader
5508  * @param shader_stage Shader stage
5509  **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5510 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5511 {
5512 	glw::GLuint		   type_ordinal = 1;
5513 	const glw::GLchar* varying_name = "";
5514 
5515 	/* Select name for varying that will hold result of "that" shader_stage */
5516 	switch (shader_stage)
5517 	{
5518 	case FRAGMENT_SHADER:
5519 		varying_name = m_varying_name_fs_out_fs_result;
5520 		break;
5521 	case GEOMETRY_SHADER:
5522 		varying_name = m_varying_name_gs_fs_gs_result;
5523 		break;
5524 	case TESS_CONTROL_SHADER:
5525 		varying_name = m_varying_name_tcs_tes_tcs_result;
5526 		break;
5527 	case TESS_EVAL_SHADER:
5528 		varying_name = m_varying_name_tes_gs_tes_result;
5529 		break;
5530 	case VERTEX_SHADER:
5531 		varying_name = m_varying_name_vs_tcs_vs_result;
5532 		break;
5533 	}
5534 
5535 	/* void main() */
5536 	stream << "void main()\n"
5537 			  "{\n";
5538 
5539 	/* Tesselation levels output */
5540 	if (TESS_CONTROL_SHADER == shader_stage)
5541 	{
5542 		stream << "gl_TessLevelOuter[0] = 1.0;\n"
5543 				  "gl_TessLevelOuter[1] = 1.0;\n"
5544 				  "gl_TessLevelOuter[2] = 1.0;\n"
5545 				  "gl_TessLevelOuter[3] = 1.0;\n"
5546 				  "gl_TessLevelInner[0] = 1.0;\n"
5547 				  "gl_TessLevelInner[1] = 1.0;\n"
5548 				  "\n";
5549 	}
5550 
5551 	/* For each "double precision" uniform
5552 	 *
5553 	 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5554 	 * {
5555 	 *     VARYING_NAME = m_result_failure;
5556 	 * }
5557 	 */
5558 	for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5559 		 end != it; ++it, ++type_ordinal)
5560 	{
5561 		stream << "    ";
5562 
5563 		/* First comparison is done with if, next with else if */
5564 		if (1 != type_ordinal)
5565 		{
5566 			stream << "else ";
5567 		}
5568 
5569 		/* if (TYPE_NAME( */
5570 		stream << "if (" << it->m_type_name << "(";
5571 
5572 		/* PREDIFINED_VALUES */
5573 		for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5574 		{
5575 			stream << getExpectedValue(type_ordinal, element);
5576 
5577 			/* Separate with comma */
5578 			if (it->m_n_elements != element + 1)
5579 			{
5580 				stream << ", ";
5581 			}
5582 		}
5583 
5584 		/*
5585 		 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5586 		 * {
5587 		 *     VARYING_NAME
5588 		 */
5589 		stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5590 																				   "    {\n"
5591 																				   "        "
5592 			   << varying_name;
5593 
5594 		/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5595 		if (TESS_CONTROL_SHADER == shader_stage)
5596 		{
5597 			stream << "[gl_InvocationID]";
5598 		}
5599 
5600 		/*
5601 		 * = m_result_failure;
5602 		 * }
5603 		 */
5604 		stream << " = " << m_result_failure << ";\n"
5605 			   << "    }\n";
5606 	}
5607 
5608 	/* If all comparisons are ok
5609 	 *
5610 	 *     else
5611 	 *     {
5612 	 *         VARYING_NAME = m_result_success;
5613 	 *     }
5614 	 */
5615 
5616 	/*
5617 	 * else
5618 	 * {
5619 	 *     VARYING_NAME
5620 	 */
5621 	stream << "    else\n"
5622 			  "    {\n"
5623 			  "        "
5624 		   << varying_name;
5625 
5626 	/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5627 	if (TESS_CONTROL_SHADER == shader_stage)
5628 	{
5629 		stream << "[gl_InvocationID]";
5630 	}
5631 
5632 	/*
5633 	 * = m_result_success;
5634 	 * }
5635 	 *
5636 	 */
5637 	stream << " = " << m_result_success << ";\n"
5638 		   << "    }\n"
5639 		   << "\n";
5640 
5641 	/* For each pair of "input/output" varyings
5642 	 *
5643 	 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5644 	 **/
5645 	writeVaryingPassthrough(stream, shader_stage);
5646 
5647 	/* Geometry shader have to emit vertex */
5648 	if (GEOMETRY_SHADER == shader_stage)
5649 	{
5650 		stream << "\n"
5651 				  "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5652 				  "EmitVertex();\n"
5653 				  "EndPrimitive();\n";
5654 	}
5655 
5656 	/* Close scope of main */
5657 	stream << "}\n\n";
5658 }
5659 
5660 /** Write shader preamble to stream
5661  *
5662  * @param stream       Output stream with source code of shader
5663  * @param shader_stage Shader stage
5664  **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5665 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5666 {
5667 	stream << "#version 400 core\n"
5668 			  "\n"
5669 			  "precision highp float;\n"
5670 			  "\n";
5671 
5672 	switch (shader_stage)
5673 	{
5674 	case FRAGMENT_SHADER:
5675 		break;
5676 	case GEOMETRY_SHADER:
5677 		stream << "layout(points)                   in;\n"
5678 				  "layout(points, max_vertices = 1) out;\n"
5679 				  "\n";
5680 		break;
5681 	case TESS_CONTROL_SHADER:
5682 		stream << "layout(vertices = 1) out;\n"
5683 				  "\n";
5684 		break;
5685 	case TESS_EVAL_SHADER:
5686 		stream << "layout(isolines, point_mode) in;\n"
5687 				  "\n";
5688 		break;
5689 	case VERTEX_SHADER:
5690 		break;
5691 	}
5692 }
5693 
5694 /** Write name uniform blcok definition with specific layout to stream
5695  *
5696  * @param stream              Output stream with source code of shader
5697  * @param uniform_data_layout Buffer layout
5698  **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5699 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5700 {
5701 	const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5702 
5703 	stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5704 																			 "{\n"
5705 																			 "    ivec3   dummy1[3];\n"
5706 																			 "    double  double_value;\n"
5707 																			 "    bool    dummy2;\n"
5708 																			 "    dvec2   dvec2_value;\n"
5709 																			 "    bvec3   dummy3;\n"
5710 																			 "    dvec3   dvec3_value;\n"
5711 																			 "    int     dummy4[3];\n"
5712 																			 "    dvec4   dvec4_value;\n"
5713 																			 "    bool    dummy5;\n"
5714 																			 "    bool    dummy6[2];\n"
5715 																			 "    dmat2   dmat2_value;\n"
5716 																			 "    dmat3   dmat3_value;\n"
5717 																			 "    bool    dummy7;\n"
5718 																			 "    dmat4   dmat4_value;\n"
5719 																			 "    dmat2x3 dmat2x3_value;\n"
5720 																			 "    uvec3   dummy8;\n"
5721 																			 "    dmat2x4 dmat2x4_value;\n"
5722 																			 "    dmat3x2 dmat3x2_value;\n"
5723 																			 "    bool    dummy9;\n"
5724 																			 "    dmat3x4 dmat3x4_value;\n"
5725 																			 "    int     dummy10;\n"
5726 																			 "    dmat4x2 dmat4x2_value;\n"
5727 																			 "    dmat4x3 dmat4x3_value;\n"
5728 																			 "} "
5729 		   << m_uniform_block_instance_name << ";\n";
5730 
5731 	stream << "\n";
5732 }
5733 
5734 /** Write definitions of varyings specific for given <shader_stage> to stream
5735  *
5736  * @param stream       Output stream with source code of shader
5737  * @param shader_stage Shader stage
5738  **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5739 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5740 {
5741 	static const glw::GLchar* const varying_type = "int";
5742 
5743 	switch (shader_stage)
5744 	{
5745 	case FRAGMENT_SHADER:
5746 
5747 		/* In */
5748 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5749 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5750 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5751 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5752 
5753 		stream << "\n";
5754 
5755 		/* Out */
5756 		stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5757 
5758 		break;
5759 
5760 	case GEOMETRY_SHADER:
5761 
5762 		/* In */
5763 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5764 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5765 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5766 
5767 		stream << "\n";
5768 
5769 		/* Out */
5770 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5771 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5772 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5773 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5774 
5775 		break;
5776 
5777 	case TESS_CONTROL_SHADER:
5778 
5779 		/* In */
5780 		stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5781 
5782 		stream << "\n";
5783 
5784 		/* Out */
5785 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5786 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5787 
5788 		break;
5789 
5790 	case TESS_EVAL_SHADER:
5791 
5792 		/* In */
5793 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5794 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5795 
5796 		stream << "\n";
5797 
5798 		/* Out */
5799 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5800 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5801 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5802 
5803 		break;
5804 
5805 	case VERTEX_SHADER:
5806 
5807 		/* Out */
5808 		stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5809 
5810 		break;
5811 	}
5812 
5813 	stream << "\n";
5814 }
5815 
5816 /** Write passthrough code of "input/output" varying pairs to stream
5817  *
5818  * @param stream       Output stream with source code of shader
5819  * @param shader_stage Shader stage
5820  **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5821 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5822 {
5823 	switch (shader_stage)
5824 	{
5825 	case FRAGMENT_SHADER:
5826 		break;
5827 
5828 	case GEOMETRY_SHADER:
5829 
5830 		stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5831 		stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5832 		stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5833 
5834 		break;
5835 
5836 	case TESS_CONTROL_SHADER:
5837 
5838 		stream << "    " << m_varying_name_tcs_tes_vs_result
5839 			   << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5840 
5841 		break;
5842 
5843 	case TESS_EVAL_SHADER:
5844 
5845 		stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5846 		stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5847 
5848 		break;
5849 
5850 	case VERTEX_SHADER:
5851 
5852 		break;
5853 	}
5854 }
5855 
5856 /** Constructor. Sets all uniform locations to -1 and sets all
5857  *  values to 0.
5858  */
_data()5859 GPUShaderFP64Test4::_data::_data()
5860 {
5861 	memset(&uniform_double, 0, sizeof(uniform_double));
5862 	memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5863 	memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5864 	memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5865 	memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5866 	memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5867 	memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5868 
5869 	uniform_location_double		   = -1;
5870 	uniform_location_double_arr[0] = -1;
5871 	uniform_location_double_arr[1] = -1;
5872 	uniform_location_dvec2		   = -1;
5873 	uniform_location_dvec2_arr[0]  = -1;
5874 	uniform_location_dvec2_arr[1]  = -1;
5875 	uniform_location_dvec3		   = -1;
5876 	uniform_location_dvec3_arr[0]  = -1;
5877 	uniform_location_dvec3_arr[1]  = -1;
5878 	uniform_location_dvec4		   = -1;
5879 	uniform_location_dvec4_arr[0]  = -1;
5880 	uniform_location_dvec4_arr[1]  = -1;
5881 }
5882 
5883 /** Constructor
5884  *
5885  *  @param context Rendering context.
5886  */
GPUShaderFP64Test4(deqp::Context & context)5887 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5888 	: TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5889 									   " report correct properties of & values assigned to double-precision uniforms.")
5890 	, m_has_test_passed(true)
5891 	, m_uniform_name_buffer(0)
5892 	, m_cs_id(0)
5893 	, m_fs_id(0)
5894 	, m_gs_id(0)
5895 	, m_po_cs_id(0)
5896 	, m_po_noncs_id(0)
5897 	, m_tc_id(0)
5898 	, m_te_id(0)
5899 	, m_vs_id(0)
5900 {
5901 	/* Left blank intentionally */
5902 }
5903 
5904 /** Deinitializes all GL objects, as well as releases all bufers, that may
5905  *  have beenallocated or  created during test execution.
5906  **/
deinit()5907 void GPUShaderFP64Test4::deinit()
5908 {
5909 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5910 
5911 	if (m_cs_id != 0)
5912 	{
5913 		gl.deleteShader(m_cs_id);
5914 
5915 		m_cs_id = 0;
5916 	}
5917 
5918 	if (m_fs_id != 0)
5919 	{
5920 		gl.deleteShader(m_fs_id);
5921 
5922 		m_fs_id = 0;
5923 	}
5924 
5925 	if (m_gs_id != 0)
5926 	{
5927 		gl.deleteShader(m_gs_id);
5928 
5929 		m_gs_id = 0;
5930 	}
5931 
5932 	if (m_po_cs_id != 0)
5933 	{
5934 		gl.deleteProgram(m_po_cs_id);
5935 
5936 		m_po_cs_id = 0;
5937 	}
5938 
5939 	if (m_po_noncs_id != 0)
5940 	{
5941 		gl.deleteProgram(m_po_noncs_id);
5942 
5943 		m_po_noncs_id = 0;
5944 	}
5945 
5946 	if (m_tc_id != 0)
5947 	{
5948 		gl.deleteShader(m_tc_id);
5949 
5950 		m_tc_id = 0;
5951 	}
5952 
5953 	if (m_te_id != 0)
5954 	{
5955 		gl.deleteShader(m_te_id);
5956 
5957 		m_te_id = 0;
5958 	}
5959 
5960 	if (m_uniform_name_buffer != DE_NULL)
5961 	{
5962 		delete[] m_uniform_name_buffer;
5963 
5964 		m_uniform_name_buffer = DE_NULL;
5965 	}
5966 
5967 	if (m_vs_id != 0)
5968 	{
5969 		gl.deleteShader(m_vs_id);
5970 
5971 		m_vs_id = 0;
5972 	}
5973 }
5974 
5975 /** Generates double-precision values for all uniforms defined for all program objects
5976  *  used by the test.
5977  *
5978  *  This function DOES NOT use any GL API. It only calculates & stores the values
5979  *  in internal storage for further usage.
5980  */
generateUniformValues()5981 void GPUShaderFP64Test4::generateUniformValues()
5982 {
5983 	_stage_data*	   stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5984 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5985 
5986 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5987 	{
5988 		_stage_data* stage_ptr = stages[n_stage];
5989 
5990 		/* Iterate through all uniform components and assign them double values */
5991 		double* double_ptrs[] = {
5992 			&stage_ptr->uniform_structure_arrays[0].uniform_double,
5993 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5994 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5995 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5996 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5997 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 2,
5998 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 3,
5999 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
6000 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
6001 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
6002 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 3,
6003 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 4,
6004 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 5,
6005 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
6006 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
6007 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
6008 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
6009 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 4,
6010 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 5,
6011 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 6,
6012 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 7,
6013 			&stage_ptr->uniform_structure_arrays[1].uniform_double,
6014 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
6015 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
6016 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
6017 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
6018 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 2,
6019 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 3,
6020 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
6021 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
6022 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6023 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 3,
6024 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 4,
6025 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 5,
6026 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6027 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6028 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6029 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6030 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 4,
6031 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 5,
6032 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 6,
6033 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 7,
6034 			&stage_ptr->uniforms.uniform_double,
6035 			stage_ptr->uniforms.uniform_double_arr + 0,
6036 			stage_ptr->uniforms.uniform_double_arr + 1,
6037 			stage_ptr->uniforms.uniform_dvec2 + 0,
6038 			stage_ptr->uniforms.uniform_dvec2 + 1,
6039 			stage_ptr->uniforms.uniform_dvec2_arr + 0,
6040 			stage_ptr->uniforms.uniform_dvec2_arr + 1,
6041 			stage_ptr->uniforms.uniform_dvec2_arr + 2,
6042 			stage_ptr->uniforms.uniform_dvec2_arr + 3,
6043 			stage_ptr->uniforms.uniform_dvec3 + 0,
6044 			stage_ptr->uniforms.uniform_dvec3 + 1,
6045 			stage_ptr->uniforms.uniform_dvec3 + 2,
6046 			stage_ptr->uniforms.uniform_dvec3_arr + 0,
6047 			stage_ptr->uniforms.uniform_dvec3_arr + 1,
6048 			stage_ptr->uniforms.uniform_dvec3_arr + 2,
6049 			stage_ptr->uniforms.uniform_dvec3_arr + 3,
6050 			stage_ptr->uniforms.uniform_dvec3_arr + 4,
6051 			stage_ptr->uniforms.uniform_dvec3_arr + 5,
6052 			stage_ptr->uniforms.uniform_dvec4 + 0,
6053 			stage_ptr->uniforms.uniform_dvec4 + 1,
6054 			stage_ptr->uniforms.uniform_dvec4 + 2,
6055 			stage_ptr->uniforms.uniform_dvec4 + 3,
6056 			stage_ptr->uniforms.uniform_dvec4_arr + 0,
6057 			stage_ptr->uniforms.uniform_dvec4_arr + 1,
6058 			stage_ptr->uniforms.uniform_dvec4_arr + 2,
6059 			stage_ptr->uniforms.uniform_dvec4_arr + 3,
6060 			stage_ptr->uniforms.uniform_dvec4_arr + 4,
6061 			stage_ptr->uniforms.uniform_dvec4_arr + 5,
6062 			stage_ptr->uniforms.uniform_dvec4_arr + 6,
6063 			stage_ptr->uniforms.uniform_dvec4_arr + 7,
6064 		};
6065 		const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6066 
6067 		for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6068 		{
6069 			double* double_ptr = double_ptrs[n_double_ptr];
6070 
6071 			/* Generate the value. Use magic numbers to generate a set of double-precision
6072 			 * floating-point numbers.
6073 			 */
6074 			static int seed = 16762362;
6075 
6076 			*double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6077 
6078 			seed += 751;
6079 		} /* for (all pointers to double variables) */
6080 	}	 /* for (all stages) */
6081 }
6082 
6083 /** Initializes all program & shader objects required to run the test. The function also
6084  *  retrieves locations of all uniforms defined by both program objects.
6085  **/
initProgramObjects()6086 void GPUShaderFP64Test4::initProgramObjects()
6087 {
6088 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6089 
6090 	/* Create program & shader objects */
6091 
6092 	/* Compute shader support and GL 4.2 required */
6093 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6094 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6095 	{
6096 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6097 	}
6098 
6099 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6100 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6101 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6102 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6103 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6104 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6105 
6106 	/* m_cs_id is initialized only if compute shaders are supported */
6107 	if (0 != m_cs_id)
6108 	{
6109 		m_po_cs_id = gl.createProgram();
6110 	}
6111 
6112 	m_po_noncs_id = gl.createProgram();
6113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6114 
6115 	/* Configure compute shader body */
6116 	const char* cs_body = "#version 420\n"
6117 						  "#extension GL_ARB_compute_shader          : require\n"
6118 						  "\n"
6119 						  "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6120 						  "\n"
6121 						  "layout(rgba32f) uniform image2D testImage;\n"
6122 						  "\n"
6123 						  "uniform double cs_double;\n"
6124 						  "uniform dvec2  cs_dvec2;\n"
6125 						  "uniform dvec3  cs_dvec3;\n"
6126 						  "uniform dvec4  cs_dvec4;\n"
6127 						  "uniform double cs_double_arr[2];\n"
6128 						  "uniform dvec2  cs_dvec2_arr [2];\n"
6129 						  "uniform dvec3  cs_dvec3_arr [2];\n"
6130 						  "uniform dvec4  cs_dvec4_arr [2];\n"
6131 						  "\n"
6132 						  "uniform struct cs_struct\n"
6133 						  "{\n"
6134 						  "    double struct_double;\n"
6135 						  "    dvec2  struct_dvec2;\n"
6136 						  "    dvec3  struct_dvec3;\n"
6137 						  "    dvec4  struct_dvec4;\n"
6138 						  "} cs_array[2];\n"
6139 						  "\n"
6140 						  "void main()\n"
6141 						  "{\n"
6142 						  "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
6143 						  "          * cs_dvec4.z                 *\n"
6144 						  "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
6145 						  "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
6146 						  "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
6147 						  "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
6148 						  "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
6149 						  "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6150 						  "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
6151 						  "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6152 						  "\n"
6153 						  "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6154 						  "}\n";
6155 
6156 	/* m_cs_id is initialized only if compute shaders are supported */
6157 	if (0 != m_cs_id)
6158 	{
6159 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6160 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6161 	}
6162 
6163 	/* Configure vertex shader body */
6164 	const char* vs_body = "#version 400\n"
6165 						  "\n"
6166 						  "uniform double vs_double;\n"
6167 						  "uniform dvec2  vs_dvec2;\n"
6168 						  "uniform dvec3  vs_dvec3;\n"
6169 						  "uniform dvec4  vs_dvec4;\n"
6170 						  "uniform double vs_double_arr[2];\n"
6171 						  "uniform dvec2  vs_dvec2_arr [2];\n"
6172 						  "uniform dvec3  vs_dvec3_arr [2];\n"
6173 						  "uniform dvec4  vs_dvec4_arr [2];\n"
6174 						  "\n"
6175 						  "uniform struct vs_struct\n"
6176 						  "{\n"
6177 						  "    double struct_double;\n"
6178 						  "    dvec2  struct_dvec2;\n"
6179 						  "    dvec3  struct_dvec3;\n"
6180 						  "    dvec4  struct_dvec4;\n"
6181 						  "} vs_array[2];\n"
6182 						  "\n"
6183 						  "void main()\n"
6184 						  "{\n"
6185 						  "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
6186 						  "* vs_dvec4.x                 *\n"
6187 						  "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
6188 						  "* vs_dvec4_arr[0].x          *\n"
6189 						  "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
6190 						  "* vs_dvec4_arr[1].x          *\n"
6191 						  "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6192 						  "* vs_array[0].struct_dvec4.x *\n"
6193 						  "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6194 						  "* vs_array[1].struct_dvec4.x > 1.0)\n"
6195 						  "    {\n"
6196 						  "        gl_Position = vec4(0);\n"
6197 						  "    }\n"
6198 						  "    else\n"
6199 						  "    {\n"
6200 						  "        gl_Position = vec4(1);\n"
6201 						  "    }\n"
6202 						  "}\n";
6203 
6204 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6205 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6206 
6207 	/* Configure tessellation control shader body */
6208 	const char* tc_body = "#version 400\n"
6209 						  "\n"
6210 						  "uniform double tc_double;\n"
6211 						  "uniform dvec2  tc_dvec2;\n"
6212 						  "uniform dvec3  tc_dvec3;\n"
6213 						  "uniform dvec4  tc_dvec4;\n"
6214 						  "uniform double tc_double_arr[2];\n"
6215 						  "uniform dvec2  tc_dvec2_arr [2];\n"
6216 						  "uniform dvec3  tc_dvec3_arr [2];\n"
6217 						  "uniform dvec4  tc_dvec4_arr [2];\n"
6218 						  "\n"
6219 						  "uniform struct tc_struct\n"
6220 						  "{\n"
6221 						  "    double struct_double;\n"
6222 						  "    dvec2  struct_dvec2;\n"
6223 						  "    dvec3  struct_dvec3;\n"
6224 						  "    dvec4  struct_dvec4;\n"
6225 						  "} tc_array[2];\n"
6226 						  "\n"
6227 						  "layout(vertices = 4) out;\n"
6228 						  "\n"
6229 						  "void main()\n"
6230 						  "{\n"
6231 						  "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
6232 						  "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
6233 						  "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
6234 						  "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
6235 						  "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6236 						  "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6237 						  "\n"
6238 						  "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
6239 						  "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
6240 						  "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
6241 						  "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
6242 						  "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6243 						  "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
6244 						  "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6245 						  "    {\n"
6246 						  "        gl_TessLevelInner[1] = 3.0;\n"
6247 						  "    }\n"
6248 						  "}\n";
6249 
6250 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6251 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6252 
6253 	/* Configure tessellation evaluation shader body */
6254 	const char* te_body = "#version 400\n"
6255 						  "\n"
6256 						  "uniform double te_double;\n"
6257 						  "uniform dvec2  te_dvec2;\n"
6258 						  "uniform dvec3  te_dvec3;\n"
6259 						  "uniform dvec4  te_dvec4;\n"
6260 						  "uniform double te_double_arr[2];\n"
6261 						  "uniform dvec2  te_dvec2_arr [2];\n"
6262 						  "uniform dvec3  te_dvec3_arr [2];\n"
6263 						  "uniform dvec4  te_dvec4_arr [2];\n"
6264 						  "\n"
6265 						  "uniform struct te_struct\n"
6266 						  "{\n"
6267 						  "    double struct_double;\n"
6268 						  "    dvec2  struct_dvec2;\n"
6269 						  "    dvec3  struct_dvec3;\n"
6270 						  "    dvec4  struct_dvec4;\n"
6271 						  "} te_array[2];\n"
6272 						  "\n"
6273 						  "layout(triangles) in;\n"
6274 						  "\n"
6275 						  "void main()\n"
6276 						  "{\n"
6277 						  "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
6278 						  "* te_dvec4.x                 *\n"
6279 						  "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
6280 						  "* te_dvec4_arr[0].x          *\n"
6281 						  "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
6282 						  "* te_dvec4_arr[1].x          *\n"
6283 						  "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6284 						  "* te_array[0].struct_dvec4.x *\n"
6285 						  "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6286 						  "* te_array[1].struct_dvec4.x > 1.0)\n"
6287 						  "    {\n"
6288 						  "        gl_Position = gl_in[0].gl_Position;\n"
6289 						  "    }\n"
6290 						  "    else\n"
6291 						  "    {\n"
6292 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6293 						  "    }\n"
6294 						  "}\n";
6295 
6296 	gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6297 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6298 
6299 	/* Configure geometry shader body */
6300 	const char* gs_body = "#version 400\n"
6301 						  "\n"
6302 						  "uniform double gs_double;\n"
6303 						  "uniform dvec2  gs_dvec2;\n"
6304 						  "uniform dvec3  gs_dvec3;\n"
6305 						  "uniform dvec4  gs_dvec4;\n"
6306 						  "uniform double gs_double_arr[2];\n"
6307 						  "uniform dvec2  gs_dvec2_arr [2];\n"
6308 						  "uniform dvec3  gs_dvec3_arr [2];\n"
6309 						  "uniform dvec4  gs_dvec4_arr [2];\n"
6310 						  "\n"
6311 						  "uniform struct gs_struct\n"
6312 						  "{\n"
6313 						  "    double struct_double;\n"
6314 						  "    dvec2  struct_dvec2;\n"
6315 						  "    dvec3  struct_dvec3;\n"
6316 						  "    dvec4  struct_dvec4;\n"
6317 						  "} gs_array[2];\n"
6318 						  "\n"
6319 						  "layout (points)                   in;\n"
6320 						  "layout (points, max_vertices = 1) out;\n"
6321 						  "\n"
6322 						  "void main()\n"
6323 						  "{\n"
6324 						  "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
6325 						  "* gs_dvec4.x        *\n"
6326 						  "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
6327 						  "* gs_dvec4_arr[0].x *\n"
6328 						  "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
6329 						  "* gs_dvec4_arr[1].x *\n"
6330 						  "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6331 						  "* gs_array[0].struct_dvec4.x *\n"
6332 						  "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6333 						  "* gs_array[1].struct_dvec4.x > 1.0)\n"
6334 						  "    {\n"
6335 						  "        gl_Position = gl_in[0].gl_Position;\n"
6336 						  "    }\n"
6337 						  "    else\n"
6338 						  "    {\n"
6339 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6340 						  "    }\n"
6341 						  "\n"
6342 						  "    EmitVertex();\n"
6343 						  "}\n";
6344 
6345 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6347 
6348 	/* Configure fragment shader body */
6349 	const char* fs_body = "#version 400\n"
6350 						  "\n"
6351 						  "uniform double fs_double;\n"
6352 						  "uniform dvec2  fs_dvec2;\n"
6353 						  "uniform dvec3  fs_dvec3;\n"
6354 						  "uniform dvec4  fs_dvec4;\n"
6355 						  "uniform double fs_double_arr[2];\n"
6356 						  "uniform dvec2  fs_dvec2_arr [2];\n"
6357 						  "uniform dvec3  fs_dvec3_arr [2];\n"
6358 						  "uniform dvec4  fs_dvec4_arr [2];\n"
6359 						  "\n"
6360 						  "uniform struct fs_struct\n"
6361 						  "{\n"
6362 						  "    double struct_double;\n"
6363 						  "    dvec2  struct_dvec2;\n"
6364 						  "    dvec3  struct_dvec3;\n"
6365 						  "    dvec4  struct_dvec4;\n"
6366 						  "} fs_array[2];\n"
6367 						  "\n"
6368 						  "out vec4 result;\n"
6369 						  "\n"
6370 						  "void main()\n"
6371 						  "{\n"
6372 						  "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
6373 						  "* fs_dvec4.x        *\n"
6374 						  "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
6375 						  "* fs_dvec4_arr[0].x *\n"
6376 						  "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
6377 						  "* fs_dvec4_arr[1].x *\n"
6378 						  "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6379 						  "* fs_array[0].struct_dvec4.x *\n"
6380 						  "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6381 						  "* fs_array[1].struct_dvec4.x > 1.0)\n"
6382 						  "    {\n"
6383 						  "        result = vec4(0.0);\n"
6384 						  "    }\n"
6385 						  "    else\n"
6386 						  "    {\n"
6387 						  "        result = vec4(1.0);\n"
6388 						  "    }\n"
6389 						  "}\n";
6390 
6391 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6392 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6393 
6394 	/* Compile the shaders */
6395 	const glw::GLuint  shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6396 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6397 
6398 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6399 	{
6400 		glw::GLint  compile_status = GL_FALSE;
6401 		glw::GLuint so_id		   = shaders[n_shader];
6402 
6403 		/* Skip compute shader if not supported */
6404 		if (0 == so_id)
6405 		{
6406 			continue;
6407 		}
6408 
6409 		gl.compileShader(so_id);
6410 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6411 
6412 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6413 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6414 
6415 		if (compile_status != GL_TRUE)
6416 		{
6417 			TCU_FAIL("Shader compilation failed");
6418 		}
6419 
6420 		if (so_id == m_cs_id)
6421 		{
6422 			gl.attachShader(m_po_cs_id, so_id);
6423 		}
6424 		else
6425 		{
6426 			gl.attachShader(m_po_noncs_id, so_id);
6427 		}
6428 
6429 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6430 	} /* for (all shaders) */
6431 
6432 	/* Link the program */
6433 	const glw::GLuint  programs[]  = { m_po_cs_id, m_po_noncs_id };
6434 	const unsigned int n_programs  = sizeof(programs) / sizeof(programs[0]);
6435 	glw::GLint		   link_status = GL_FALSE;
6436 
6437 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6438 	{
6439 		glw::GLuint po_id = programs[n_program];
6440 
6441 		/* Skip compute shader program if not supported */
6442 		if (0 == po_id)
6443 		{
6444 			continue;
6445 		}
6446 
6447 		gl.linkProgram(po_id);
6448 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6449 
6450 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6451 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6452 
6453 		if (link_status != GL_TRUE)
6454 		{
6455 			TCU_FAIL("Program linking failed");
6456 		}
6457 	} /* for (both program objects) */
6458 
6459 	/* Retrieve uniform locations */
6460 	_stage_data*			  cs_stage_data[]		= { &m_data_cs };
6461 	static const char*		  cs_uniform_prefixes[] = { "cs_" };
6462 	static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6463 
6464 	_stage_data*			  noncs_stage_data[]	   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6465 	static const char*		  noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6466 	static const unsigned int n_noncs_uniform_prefixes =
6467 		sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6468 
6469 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6470 	{
6471 		unsigned int  n_uniform_prefixes = DE_NULL;
6472 		glw::GLuint   po_id				 = programs[n_program];
6473 		_stage_data** stages_data		 = DE_NULL;
6474 		const char**  uniform_prefixes   = DE_NULL;
6475 
6476 		if (n_program == 0)
6477 		{
6478 			stages_data		   = cs_stage_data;
6479 			uniform_prefixes   = cs_uniform_prefixes;
6480 			n_uniform_prefixes = n_cs_uniform_prefixes;
6481 		}
6482 		else
6483 		{
6484 			stages_data		   = noncs_stage_data;
6485 			uniform_prefixes   = noncs_uniform_prefixes;
6486 			n_uniform_prefixes = n_noncs_uniform_prefixes;
6487 		}
6488 
6489 		/* Skip compute shader program if not supported */
6490 		if (0 == po_id)
6491 		{
6492 			continue;
6493 		}
6494 
6495 		/* Uniform names used by the test program consist of a prefix (different for each
6496 		 * shader stage) and a common part.
6497 		 */
6498 		for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6499 		{
6500 			_stage_data* stage_data				  = stages_data[n_uniform_prefix];
6501 			std::string  uniform_prefix			  = std::string(uniform_prefixes[n_uniform_prefix]);
6502 			std::string  uniform_double_name	  = uniform_prefix + "double";
6503 			std::string  uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6504 			std::string  uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6505 			std::string  uniform_dvec2_name		  = uniform_prefix + "dvec2";
6506 			std::string  uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
6507 			std::string  uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
6508 			std::string  uniform_dvec3_name		  = uniform_prefix + "dvec3";
6509 			std::string  uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
6510 			std::string  uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
6511 			std::string  uniform_dvec4_name		  = uniform_prefix + "dvec4";
6512 			std::string  uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
6513 			std::string  uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
6514 			std::string  uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6515 			std::string  uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
6516 			std::string  uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
6517 			std::string  uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
6518 			std::string  uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6519 			std::string  uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
6520 			std::string  uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
6521 			std::string  uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
6522 
6523 			/* Retrieve uniform locations */
6524 			stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6525 			stage_data->uniforms.uniform_location_double_arr[0] =
6526 				gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6527 			stage_data->uniforms.uniform_location_double_arr[1] =
6528 				gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6529 			stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6530 			stage_data->uniforms.uniform_location_dvec2_arr[0] =
6531 				gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6532 			stage_data->uniforms.uniform_location_dvec2_arr[1] =
6533 				gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6534 			stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6535 			stage_data->uniforms.uniform_location_dvec3_arr[0] =
6536 				gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6537 			stage_data->uniforms.uniform_location_dvec3_arr[1] =
6538 				gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6539 			stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6540 			stage_data->uniforms.uniform_location_dvec4_arr[0] =
6541 				gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6542 			stage_data->uniforms.uniform_location_dvec4_arr[1] =
6543 				gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6544 			stage_data->uniform_structure_arrays[0].uniform_location_double =
6545 				gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6546 			stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6547 				gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6548 			stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6549 				gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6550 			stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6551 				gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6552 			stage_data->uniform_structure_arrays[1].uniform_location_double =
6553 				gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6554 			stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6555 				gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6556 			stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6557 				gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6558 			stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6559 				gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6560 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6561 
6562 			if (stage_data->uniforms.uniform_location_double == -1 ||
6563 				stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6564 				stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6565 				stage_data->uniforms.uniform_location_dvec2 == -1 ||
6566 				stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6567 				stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6568 				stage_data->uniforms.uniform_location_dvec3 == -1 ||
6569 				stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6570 				stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6571 				stage_data->uniforms.uniform_location_dvec4 == -1 ||
6572 				stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6573 				stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6574 				stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6575 				stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6576 				stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6577 				stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6578 				stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6579 				stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6580 				stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6581 				stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6582 			{
6583 				TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6584 			}
6585 
6586 			/* Make sure locations of subsequent items in array uniforms are correct */
6587 			if (stage_data->uniforms.uniform_location_double_arr[1] !=
6588 					(stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6589 				stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6590 					(stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6591 				stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6592 					(stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6593 				stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6594 					(stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6595 			{
6596 				m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6597 															   " double_arr[0]:"
6598 								   << stage_data->uniforms.uniform_location_double_arr[0]
6599 								   << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6600 								   << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6601 								   << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6602 								   << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6603 								   << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6604 								   << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6605 								   << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6606 								   << tcu::TestLog::EndMessage;
6607 
6608 				TCU_FAIL("Double-precision uniform array item locations are invalid.");
6609 			}
6610 		} /* for (all uniform prefixes) */
6611 	}	 /* for (both program objects) */
6612 }
6613 
6614 /** Initializes all objects required to run the test. */
initTest()6615 void GPUShaderFP64Test4::initTest()
6616 {
6617 	initProgramObjects();
6618 
6619 	generateUniformValues();
6620 	initUniformValues();
6621 }
6622 
6623 /** Assigns values generated by generateUniformValues() to uniforms defined by
6624  *  both program objects.
6625  **/
initUniformValues()6626 void GPUShaderFP64Test4::initUniformValues()
6627 {
6628 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6629 
6630 	/* Iterate through all programs */
6631 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6632 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6633 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6634 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6635 
6636 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6637 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6638 
6639 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6640 	{
6641 		glw::GLuint   po_id		 = programs[n_program];
6642 		unsigned int  n_stages   = 0;
6643 		_stage_data** stage_data = DE_NULL;
6644 
6645 		if (po_id == m_po_cs_id)
6646 		{
6647 			n_stages   = n_cs_stages;
6648 			stage_data = cs_stages;
6649 		}
6650 		else
6651 		{
6652 			n_stages   = n_noncs_stages;
6653 			stage_data = noncs_stages;
6654 		}
6655 
6656 		/* Skip compute shader program if not supported */
6657 		if (0 == po_id)
6658 		{
6659 			continue;
6660 		}
6661 
6662 		gl.useProgram(po_id);
6663 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6664 
6665 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6666 		{
6667 			/* Iterate through all uniforms */
6668 			_stage_data* stage_ptr = stage_data[n_stage];
6669 
6670 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6671 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6672 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6673 			gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6674 						 stage_ptr->uniform_structure_arrays[0].uniform_double);
6675 			gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6676 						 stage_ptr->uniform_structure_arrays[1].uniform_double);
6677 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6678 
6679 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6680 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6681 						  stage_ptr->uniforms.uniform_dvec2_arr + 0);
6682 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6683 						  stage_ptr->uniforms.uniform_dvec2_arr + 2);
6684 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6685 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6686 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6687 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6688 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6689 
6690 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6691 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6692 						  stage_ptr->uniforms.uniform_dvec3_arr + 0);
6693 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6694 						  stage_ptr->uniforms.uniform_dvec3_arr + 3);
6695 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6696 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6697 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6698 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6699 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6700 
6701 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6702 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6703 						  stage_ptr->uniforms.uniform_dvec4_arr + 0);
6704 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6705 						  stage_ptr->uniforms.uniform_dvec4_arr + 4);
6706 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6707 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6708 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6709 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6710 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6711 		} /* for (all shader stages) */
6712 	}	 /* for (both program objects) */
6713 }
6714 
6715 /** Executes test iteration.
6716  *
6717  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6718  */
iterate()6719 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6720 {
6721 	/* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6722 
6723 	/* Initialize all objects required to run the test */
6724 	initTest();
6725 
6726 	/* Verify the implementation reports correct values for all stages we've configured */
6727 	m_has_test_passed &= verifyUniformValues();
6728 
6729 	/* Is this also the case when "program interface query" mechanism is used? */
6730 	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6731 	{
6732 		m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6733 	}
6734 
6735 	/* We're done */
6736 	if (m_has_test_passed)
6737 	{
6738 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6739 	}
6740 	else
6741 	{
6742 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6743 	}
6744 
6745 	return STOP;
6746 }
6747 
6748 /** Verifies that:
6749  *
6750  *  a) glGetProgramResourceIndex()
6751  *  b) glGetProgramResourceiv()
6752  *  c) glGetProgramResourceName()
6753  *
6754  *  functions return correct values for double-precision uniforms.
6755  *
6756  *  @return true if the verification was passed, false otherwise.
6757  */
verifyProgramInterfaceQuerySupport()6758 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6759 {
6760 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6761 	bool				  result = true;
6762 
6763 	/* Iterate through all programs */
6764 	const char*		   cs_prefixes[]	= { "cs_" };
6765 	_stage_data*	   cs_stages[]		= { &m_data_cs };
6766 	const char*		   noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6767 	_stage_data*	   noncs_stages[]   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6768 	const unsigned int n_cs_stages		= sizeof(cs_stages) / sizeof(cs_stages[0]);
6769 	const unsigned int n_noncs_stages   = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6770 
6771 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6772 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6773 
6774 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6775 	{
6776 		glw::GLuint   po_id			 = programs[n_program];
6777 		unsigned int  n_stages		 = 0;
6778 		const char**  stage_prefixes = DE_NULL;
6779 		_stage_data** stage_data	 = DE_NULL;
6780 
6781 		if (po_id == m_po_cs_id)
6782 		{
6783 			n_stages	   = n_cs_stages;
6784 			stage_data	 = cs_stages;
6785 			stage_prefixes = cs_prefixes;
6786 		}
6787 		else
6788 		{
6789 			n_stages	   = n_noncs_stages;
6790 			stage_data	 = noncs_stages;
6791 			stage_prefixes = noncs_prefixes;
6792 		}
6793 
6794 		/* Skip compute shader program if not supported */
6795 		if (0 == po_id)
6796 		{
6797 			continue;
6798 		}
6799 
6800 		/* Determine maximum uniform name length */
6801 		glw::GLint max_uniform_name_length = 0;
6802 
6803 		gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6804 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6805 
6806 		/* Allocate a buffer we will use to hold uniform names */
6807 		m_uniform_name_buffer = new char[max_uniform_name_length];
6808 
6809 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6810 		{
6811 			/* Iterate through all uniforms */
6812 			_stage_data* stage_ptr	= stage_data[n_stage];
6813 			const char*  stage_prefix = stage_prefixes[n_stage];
6814 
6815 			/* Construct an array that will be used to run the test in an automated manner */
6816 			_program_interface_query_test_item uniforms[] = {
6817 				/* array size */ /* name */ /* type */ /* location */
6818 				{ 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6819 				{ 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6820 				{ 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6821 				{ 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6822 				{ 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6823 				{ 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6824 				{ 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6825 				{ 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6826 				{ 1, "array[0].struct_double", GL_DOUBLE,
6827 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6828 				{ 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6829 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6830 				{ 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6831 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6832 				{ 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6833 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6834 				{ 1, "array[1].struct_double", GL_DOUBLE,
6835 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6836 				{ 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6837 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6838 				{ 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6839 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6840 				{ 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6841 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6842 			};
6843 			const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6844 
6845 			/* Prefix the names with stage-specific string */
6846 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6847 			{
6848 				_program_interface_query_test_item& current_item = uniforms[n_uniform];
6849 
6850 				current_item.name = std::string(stage_prefix) + current_item.name;
6851 			} /* for (all uniform descriptors) */
6852 
6853 			const glw::GLenum  properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6854 			const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6855 
6856 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6857 			{
6858 				_program_interface_query_test_item& current_item		  = uniforms[n_uniform];
6859 				glw::GLint							n_written_items		  = 0;
6860 				glw::GLint							retrieved_array_size  = 0;
6861 				glw::GLint							retrieved_name_length = 0;
6862 				glw::GLenum							retrieved_type		  = GL_NONE;
6863 				glw::GLint							temp_buffer[2]		  = { 0, GL_NONE };
6864 
6865 				/* Retrieve index of the iteration-specific uniform */
6866 				glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6867 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6868 
6869 				/* Make sure glGetProgramResourceName() returns correct values */
6870 				memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6871 
6872 				gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6873 										  resource_index, max_uniform_name_length, &retrieved_name_length,
6874 										  m_uniform_name_buffer);
6875 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6876 
6877 				if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6878 					memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6879 				{
6880 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6881 									   << resource_index << "]"
6882 															": expected:["
6883 									   << current_item.name << "]"
6884 															   ", reported:["
6885 									   << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6886 
6887 					result = false;
6888 					continue;
6889 				}
6890 
6891 				/* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6892 				gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6893 										resource_index, n_properties, properties,
6894 										sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6895 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6896 
6897 				if (n_written_items != n_properties)
6898 				{
6899 					TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6900 				}
6901 
6902 				/* For clarity, copy the retrieved values to separate variables */
6903 				retrieved_array_size = temp_buffer[0];
6904 				retrieved_type		 = temp_buffer[1];
6905 
6906 				/* Verify the values */
6907 				if (retrieved_array_size != current_item.expected_array_size)
6908 				{
6909 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6910 									   << current_item.name << "]"
6911 									   << ": expected:[" << current_item.expected_array_size << "]"
6912 																								", reported:["
6913 									   << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6914 
6915 					result = false;
6916 				}
6917 
6918 				if (retrieved_type != current_item.expected_type)
6919 				{
6920 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6921 									   << current_item.name << "]"
6922 									   << ": expected:[" << current_item.expected_type << "]"
6923 																						  ", reported:["
6924 									   << retrieved_type << "]" << tcu::TestLog::EndMessage;
6925 
6926 					result = false;
6927 				}
6928 			} /* for (all uniforms) */
6929 		}	 /* for (all shader stages) */
6930 
6931 		/* We're now OK to release the buffer we used to hold uniform names for
6932 		 * the program */
6933 		if (m_uniform_name_buffer != DE_NULL)
6934 		{
6935 			delete[] m_uniform_name_buffer;
6936 
6937 			m_uniform_name_buffer = DE_NULL;
6938 		}
6939 	} /* for (both program objects) */
6940 
6941 	return result;
6942 }
6943 
6944 /** Verifies glGetUniform*() calls return correct values assigned to
6945  *  double-precision uniforms.
6946  *
6947  *  @return true if all values reported by OpenGL were found to be correct,
6948  *          false otherwise.
6949  **/
verifyUniformValues()6950 bool GPUShaderFP64Test4::verifyUniformValues()
6951 {
6952 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6953 	bool				  result = true;
6954 
6955 	/* Iterate through all programs */
6956 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6957 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6958 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6959 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6960 
6961 	const glw::GLuint programs[] = {
6962 		m_po_noncs_id, m_po_cs_id,
6963 	};
6964 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6965 
6966 	/* Set up rounding for the tests */
6967 	deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
6968 
6969 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6970 	{
6971 		glw::GLuint   po_id		 = programs[n_program];
6972 		unsigned int  n_stages   = 0;
6973 		_stage_data** stage_data = DE_NULL;
6974 
6975 		if (po_id == m_po_cs_id)
6976 		{
6977 			n_stages   = n_cs_stages;
6978 			stage_data = cs_stages;
6979 		}
6980 		else
6981 		{
6982 			n_stages   = n_noncs_stages;
6983 			stage_data = noncs_stages;
6984 		}
6985 
6986 		/* Skip compute shader program if not supported */
6987 		if (0 == po_id)
6988 		{
6989 			continue;
6990 		}
6991 
6992 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6993 		{
6994 			/* Iterate through all uniforms */
6995 			_stage_data* stage_ptr = stage_data[n_stage];
6996 
6997 			/* Set up arrays that we will guide the automated testing */
6998 			const uniform_value_pair double_uniforms[] = {
6999 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
7000 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
7001 								   stage_ptr->uniforms.uniform_double_arr + 0),
7002 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
7003 								   stage_ptr->uniforms.uniform_double_arr + 1),
7004 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
7005 								   &stage_ptr->uniform_structure_arrays[0].uniform_double),
7006 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
7007 								   &stage_ptr->uniform_structure_arrays[1].uniform_double)
7008 			};
7009 			const uniform_value_pair dvec2_uniforms[] = {
7010 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
7011 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
7012 								   stage_ptr->uniforms.uniform_dvec2_arr + 0),
7013 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
7014 								   stage_ptr->uniforms.uniform_dvec2_arr + 2),
7015 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
7016 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
7017 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
7018 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
7019 			};
7020 			const uniform_value_pair dvec3_uniforms[] = {
7021 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
7022 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
7023 								   stage_ptr->uniforms.uniform_dvec3_arr + 0),
7024 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
7025 								   stage_ptr->uniforms.uniform_dvec3_arr + 3),
7026 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
7027 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
7028 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
7029 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7030 			};
7031 			const uniform_value_pair dvec4_uniforms[] = {
7032 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7033 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7034 								   stage_ptr->uniforms.uniform_dvec4_arr + 0),
7035 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7036 								   stage_ptr->uniforms.uniform_dvec4_arr + 4),
7037 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7038 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7039 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7040 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7041 			};
7042 
7043 			/* Iterate over all uniforms and verify the values reported by the API */
7044 			double		 returned_double_data[4];
7045 			float		 returned_float_data[4];
7046 			int			 returned_int_data[4];
7047 			unsigned int returned_uint_data[4];
7048 
7049 			for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7050 			{
7051 				const uniform_value_pair* current_uv_pairs  = NULL;
7052 				const unsigned int		  n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7053 				unsigned int			  n_pairs			= 0;
7054 
7055 				switch (n_type)
7056 				{
7057 				case 0: /* double */
7058 				{
7059 					current_uv_pairs = double_uniforms;
7060 					n_pairs			 = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7061 
7062 					break;
7063 				}
7064 
7065 				case 1: /* dvec2 */
7066 				{
7067 					current_uv_pairs = dvec2_uniforms;
7068 					n_pairs			 = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7069 
7070 					break;
7071 				}
7072 
7073 				case 2: /* dvec3 */
7074 				{
7075 					current_uv_pairs = dvec3_uniforms;
7076 					n_pairs			 = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7077 
7078 					break;
7079 				}
7080 
7081 				case 3: /* dvec4 */
7082 				{
7083 					current_uv_pairs = dvec4_uniforms;
7084 					n_pairs			 = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7085 
7086 					break;
7087 				}
7088 
7089 				default:
7090 				{
7091 					TCU_FAIL("Invalid type index requested");
7092 				}
7093 				} /* switch (n_type) */
7094 
7095 				for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7096 				{
7097 					const uniform_value_pair& current_uv_pair  = current_uv_pairs[n_pair];
7098 					glw::GLint				  uniform_location = current_uv_pair.first;
7099 					const double*			  uniform_value	= current_uv_pair.second;
7100 
7101 					/* Retrieve the values from the GL implementation*/
7102 					gl.getUniformdv(po_id, uniform_location, returned_double_data);
7103 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7104 
7105 					gl.getUniformfv(po_id, uniform_location, returned_float_data);
7106 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7107 
7108 					gl.getUniformiv(po_id, uniform_location, returned_int_data);
7109 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7110 
7111 					gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7112 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7113 
7114 					/* Make sure the values reported match the reference values */
7115 					bool		can_continue = true;
7116 					const float epsilon		 = 1e-5f;
7117 
7118 					for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7119 					{
7120 						if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7121 						{
7122 							m_testCtx.getLog()
7123 								<< tcu::TestLog::Message
7124 								<< "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7125 								<< uniform_location << "]"
7126 													   " and component ["
7127 								<< n_component << "]"
7128 												  ": retrieved:["
7129 								<< returned_double_data[n_component] << "]"
7130 																		", expected:["
7131 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7132 
7133 							result = false;
7134 						}
7135 
7136 						if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7137 						{
7138 							m_testCtx.getLog()
7139 								<< tcu::TestLog::Message
7140 								<< "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7141 								<< uniform_location << "]"
7142 													   " and component ["
7143 								<< n_component << "]"
7144 												  ": retrieved:["
7145 								<< returned_float_data[n_component] << "]"
7146 																	   ", expected:["
7147 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7148 
7149 							result = false;
7150 						}
7151 
7152 						/* ints */
7153 						int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7154 						unsigned int rounded_uniform_value_uint =
7155 							(unsigned int)(uniform_value[n_component] > 0.0) ?
7156 								((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7157 								0;
7158 
7159 						if (returned_int_data[n_component] != rounded_uniform_value_sint)
7160 						{
7161 							m_testCtx.getLog()
7162 								<< tcu::TestLog::Message
7163 								<< "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7164 								<< uniform_location << "]"
7165 													   " and component ["
7166 								<< n_component << "]"
7167 												  ": retrieved:["
7168 								<< returned_int_data[n_component] << "]"
7169 																	 ", expected:["
7170 								<< rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7171 
7172 							result = false;
7173 						}
7174 
7175 						if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7176 						{
7177 							m_testCtx.getLog()
7178 								<< tcu::TestLog::Message
7179 								<< "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7180 								<< uniform_location << "]"
7181 													   " and component ["
7182 								<< n_component << "]"
7183 												  ": retrieved:["
7184 								<< returned_uint_data[n_component] << "]"
7185 																	  ", expected:["
7186 								<< rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7187 
7188 							result = false;
7189 						}
7190 					} /* for (all components) */
7191 				}	 /* for (all uniform+value pairs) */
7192 			}		  /* for (all 4 uniform types) */
7193 		}			  /* for (all shader stages) */
7194 	}				  /* for (both program objects) */
7195 
7196 	/* All done! */
7197 	return result;
7198 }
7199 
7200 /** Constructor
7201  *
7202  *  @param context Rendering context.
7203  */
GPUShaderFP64Test5(deqp::Context & context)7204 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7205 	: TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7206 									   " floating-point variables work correctly")
7207 	, m_base_value_bo_data(DE_NULL)
7208 	, m_base_value_bo_id(0)
7209 	, m_has_test_passed(true)
7210 	, m_po_base_value_attribute_location(-1)
7211 	, m_po_id(0)
7212 	, m_vao_id(0)
7213 	, m_vs_id(0)
7214 	, m_xfb_bo_id(0)
7215 	, m_xfb_bo_size(0)
7216 {
7217 	/* Set up base value array (as per test spec) */
7218 	m_base_values[0] = -25.12065f;
7219 	m_base_values[1] = 0.0f;
7220 	m_base_values[2] = 0.001f;
7221 	m_base_values[3] = 1.0f;
7222 	m_base_values[4] = 256.78901f;
7223 
7224 	/* Set up swizzle matrix */
7225 	m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7226 	m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7227 	m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7228 	m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7229 	m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7230 	m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7231 	m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7232 	m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7233 	m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7234 	m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7235 	m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7236 	m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7237 	m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7238 	m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7239 	m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7240 	m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7241 }
7242 
deinit()7243 void GPUShaderFP64Test5::deinit()
7244 {
7245 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7246 
7247 	if (m_base_value_bo_data != DE_NULL)
7248 	{
7249 		delete[] m_base_value_bo_data;
7250 
7251 		m_base_value_bo_data = DE_NULL;
7252 	}
7253 
7254 	if (m_base_value_bo_id != 0)
7255 	{
7256 		gl.deleteBuffers(1, &m_base_value_bo_id);
7257 
7258 		m_base_value_bo_id = 0;
7259 	}
7260 
7261 	if (m_vao_id != 0)
7262 	{
7263 		gl.deleteVertexArrays(1, &m_vao_id);
7264 
7265 		m_vao_id = 0;
7266 	}
7267 
7268 	if (m_xfb_bo_id != 0)
7269 	{
7270 		gl.deleteBuffers(1, &m_xfb_bo_id);
7271 
7272 		m_xfb_bo_id = 0;
7273 	}
7274 
7275 	/* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7276 	 * take care of it here
7277 	 */
7278 	deinitInteration();
7279 }
7280 
7281 /** Deinitializes all buffers and GL objects that may have been generated
7282  *  during test execution.
7283  **/
deinitInteration()7284 void GPUShaderFP64Test5::deinitInteration()
7285 {
7286 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7287 
7288 	if (m_po_id != 0)
7289 	{
7290 		gl.deleteProgram(m_po_id);
7291 
7292 		m_po_id = 0;
7293 	}
7294 
7295 	if (m_vs_id != 0)
7296 	{
7297 		gl.deleteShader(m_vs_id);
7298 
7299 		m_vs_id = 0;
7300 	}
7301 }
7302 
7303 /** Executes a single test case iteration using user-provided test case descriptor.
7304  *
7305  *  This function may throw a TestError exception if GL implementation misbehaves.
7306  *
7307  *  @param test_case Test case descriptor to use.
7308  *
7309  *  @return true if the values returned by GL implementation were found to be valid,
7310  *          false otherwise.
7311  **/
executeIteration(const _test_case & test_case)7312 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7313 {
7314 	bool result = true;
7315 
7316 	/* Convert the base values array to the type of input attribute we'll be using
7317 	 * for the iteration.
7318 	 */
7319 	Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7320 
7321 	if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7322 	{
7323 		/* bools are actually represented by ints, since bool varyings are not allowed */
7324 		base_value_type = Utils::VARIABLE_TYPE_INT;
7325 	}
7326 
7327 	const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7328 	const unsigned int n_base_values			 = sizeof(m_base_values) / sizeof(m_base_values[0]);
7329 
7330 	m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7331 
7332 	unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7333 
7334 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7335 	{
7336 		switch (base_value_type)
7337 		{
7338 		case Utils::VARIABLE_TYPE_DOUBLE:
7339 			*((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7340 			break;
7341 		case Utils::VARIABLE_TYPE_FLOAT:
7342 			*((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7343 			break;
7344 		case Utils::VARIABLE_TYPE_INT:
7345 			*((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7346 			break;
7347 		case Utils::VARIABLE_TYPE_UINT:
7348 			*((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7349 			break;
7350 
7351 		default:
7352 		{
7353 			TCU_FAIL("Unrecognized base value type");
7354 		}
7355 		}
7356 
7357 		base_value_traveller_ptr += base_value_component_size;
7358 	} /* for (all base values) */
7359 
7360 	/* Update buffer object storage with the data we've just finished preparing. */
7361 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7362 
7363 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7365 
7366 	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7367 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7368 
7369 	/* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7370 	 * new data is interpreted correctly.
7371 	 */
7372 	if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7373 	{
7374 		gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,							  /* size */
7375 							   Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7376 							   0,																  /* stride */
7377 							   DE_NULL);														  /* pointer */
7378 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7379 	}
7380 	else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7381 	{
7382 		gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,						/* size */
7383 								Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7384 								DE_NULL);													/* pointer */
7385 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7386 	}
7387 	else
7388 	{
7389 		DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7390 
7391 		gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7392 								GL_DOUBLE, 0,						   /* stride */
7393 								DE_NULL);							   /* pointer */
7394 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7395 	}
7396 
7397 	gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7398 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7399 
7400 	/* Execute the draw call */
7401 	gl.useProgram(m_po_id);
7402 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7403 
7404 	gl.beginTransformFeedback(GL_POINTS);
7405 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7406 	{
7407 		gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7408 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7409 	}
7410 	gl.endTransformFeedback();
7411 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7412 
7413 	/* Map the XFB buffer object into process space */
7414 	void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7415 
7416 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7417 	DE_ASSERT(xfb_data_ptr != NULL);
7418 
7419 	/* Verify the data */
7420 	result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7421 
7422 	/* Unmap the XFB BO */
7423 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7424 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7425 
7426 	/** Good to release the data buffer at this point */
7427 	if (m_base_value_bo_data != DE_NULL)
7428 	{
7429 		delete[] m_base_value_bo_data;
7430 
7431 		m_base_value_bo_data = DE_NULL;
7432 	}
7433 
7434 	/* All done */
7435 	return result;
7436 }
7437 
7438 /** Returns properties of a swizzle operator described by @param type swizzle type.
7439  *
7440  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
7441  *                             corresponding to the specific swizzle operator.
7442  *                             Must not be NULL.
7443  *  @param out_n_components    Deref will be used to store the amount of components
7444  *                             used by the operator. Must not be NULL.
7445  *  @param out_component_order Deref will be used to store up to 4 integer values,
7446  *                             corresponding to component indices described by the
7447  *                             operator for a particular position.  Must not be NULL.
7448  **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7449 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7450 												  unsigned int* out_n_components, unsigned int* out_component_order)
7451 {
7452 	unsigned int result_component_order[4] = { 0 };
7453 	unsigned int result_n_components	   = 0;
7454 	std::string  result_swizzle_string;
7455 
7456 	switch (type)
7457 	{
7458 	case SWIZZLE_TYPE_NONE:
7459 	{
7460 		result_swizzle_string = "";
7461 		result_n_components   = 0;
7462 
7463 		break;
7464 	}
7465 
7466 	case SWIZZLE_TYPE_XWZY:
7467 	{
7468 		result_swizzle_string	 = "xwzy";
7469 		result_n_components		  = 4;
7470 		result_component_order[0] = 0;
7471 		result_component_order[1] = 3;
7472 		result_component_order[2] = 2;
7473 		result_component_order[3] = 1;
7474 
7475 		break;
7476 	}
7477 
7478 	case SWIZZLE_TYPE_XZXY:
7479 	{
7480 		result_swizzle_string	 = "xzxy";
7481 		result_n_components		  = 4;
7482 		result_component_order[0] = 0;
7483 		result_component_order[1] = 2;
7484 		result_component_order[2] = 0;
7485 		result_component_order[3] = 1;
7486 
7487 		break;
7488 	}
7489 
7490 	case SWIZZLE_TYPE_XZY:
7491 	{
7492 		result_swizzle_string	 = "xzy";
7493 		result_n_components		  = 3;
7494 		result_component_order[0] = 0;
7495 		result_component_order[1] = 2;
7496 		result_component_order[2] = 1;
7497 
7498 		break;
7499 	}
7500 
7501 	case SWIZZLE_TYPE_XZYW:
7502 	{
7503 		result_swizzle_string	 = "xzyw";
7504 		result_n_components		  = 4;
7505 		result_component_order[0] = 0;
7506 		result_component_order[1] = 2;
7507 		result_component_order[2] = 1;
7508 		result_component_order[3] = 3;
7509 
7510 		break;
7511 	}
7512 
7513 	case SWIZZLE_TYPE_Y:
7514 	{
7515 		result_swizzle_string	 = "y";
7516 		result_n_components		  = 1;
7517 		result_component_order[0] = 1;
7518 
7519 		break;
7520 	}
7521 
7522 	case SWIZZLE_TYPE_YX:
7523 	{
7524 		result_swizzle_string	 = "yx";
7525 		result_n_components		  = 2;
7526 		result_component_order[0] = 1;
7527 		result_component_order[1] = 0;
7528 
7529 		break;
7530 	}
7531 
7532 	case SWIZZLE_TYPE_YXX:
7533 	{
7534 		result_swizzle_string	 = "yxx";
7535 		result_n_components		  = 3;
7536 		result_component_order[0] = 1;
7537 		result_component_order[1] = 0;
7538 		result_component_order[2] = 0;
7539 
7540 		break;
7541 	}
7542 
7543 	case SWIZZLE_TYPE_YXXY:
7544 	{
7545 		result_swizzle_string	 = "yxxy";
7546 		result_n_components		  = 4;
7547 		result_component_order[0] = 1;
7548 		result_component_order[1] = 0;
7549 		result_component_order[2] = 0;
7550 		result_component_order[3] = 1;
7551 
7552 		break;
7553 	}
7554 
7555 	case SWIZZLE_TYPE_Z:
7556 	{
7557 		result_swizzle_string	 = "z";
7558 		result_n_components		  = 1;
7559 		result_component_order[0] = 2;
7560 
7561 		break;
7562 	}
7563 
7564 	case SWIZZLE_TYPE_ZY:
7565 	{
7566 		result_swizzle_string	 = "zy";
7567 		result_n_components		  = 2;
7568 		result_component_order[0] = 2;
7569 		result_component_order[1] = 1;
7570 
7571 		break;
7572 	}
7573 
7574 	case SWIZZLE_TYPE_W:
7575 	{
7576 		result_swizzle_string	 = "w";
7577 		result_n_components		  = 1;
7578 		result_component_order[0] = 3;
7579 
7580 		break;
7581 	}
7582 
7583 	case SWIZZLE_TYPE_WX:
7584 	{
7585 		result_swizzle_string	 = "wx";
7586 		result_n_components		  = 2;
7587 		result_component_order[0] = 3;
7588 		result_component_order[1] = 0;
7589 
7590 		break;
7591 	}
7592 
7593 	default:
7594 	{
7595 		TCU_FAIL("Unrecognized swizzle type");
7596 	}
7597 	} /* switch (type) */
7598 
7599 	if (out_swizzle_string != DE_NULL)
7600 	{
7601 		*out_swizzle_string = result_swizzle_string;
7602 	}
7603 
7604 	if (out_n_components != DE_NULL)
7605 	{
7606 		*out_n_components = result_n_components;
7607 	}
7608 
7609 	if (out_component_order != DE_NULL)
7610 	{
7611 		memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7612 	}
7613 }
7614 
7615 /** Returns body of a vertex shader that should be used for particular test case,
7616  *  given user-specified test case descriptor.
7617  *
7618  *  @param test_case Descriptor to use for the query.
7619  *
7620  *  @return Requested data.
7621  **/
getVertexShaderBody(const _test_case & test_case)7622 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7623 {
7624 	std::stringstream  result;
7625 	const std::string  base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7626 	const std::string  dst_type_string  = Utils::getVariableTypeString(test_case.dst_type);
7627 	const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7628 	const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7629 	const std::string  src_type_string  = Utils::getVariableTypeString(test_case.src_type);
7630 
7631 	/* Add version preamble */
7632 	result << "#version 420\n"
7633 			  "\n";
7634 
7635 	/* Declare output variables. Note that boolean output variables are not supported, so we need
7636 	 * to handle that special case correctly */
7637 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7638 	{
7639 		result << "out int result;\n";
7640 	}
7641 	else
7642 	{
7643 		result << "out " << dst_type_string << " result;\n";
7644 	}
7645 
7646 	/* Declare input variables. Handle the bool case exclusively. */
7647 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7648 	{
7649 		/* Use ints for bools. We will cast them to bool in the code later. */
7650 		result << "in int base_value;\n";
7651 	}
7652 	else
7653 	{
7654 		result << "in " << base_type_string << " base_value;\n";
7655 	}
7656 
7657 	/* Declare main() and construct the value we will be casting from.
7658 	 *
7659 	 * Note: Addition operations on bool values cause an implicit conversion to int
7660 	 *       which is not allowed. Hence, we skip these operations for this special
7661 	 *       case.
7662 	 */
7663 	result << "void main()\n"
7664 			  "{\n"
7665 		   << src_type_string << " lside_value = ";
7666 
7667 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7668 	{
7669 		result << src_type_string << "(0 != ";
7670 	}
7671 	else
7672 	{
7673 		result << src_type_string << "(";
7674 	}
7675 
7676 	if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7677 	{
7678 		for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7679 		{
7680 			result << "base_value + " << n_component;
7681 
7682 			if (n_component != (n_src_components - 1))
7683 			{
7684 				result << ", ";
7685 			}
7686 		} /* for (all components) */
7687 	}
7688 	else
7689 	{
7690 		DE_ASSERT(n_src_components == 1);
7691 
7692 		result << "base_value";
7693 	}
7694 
7695 	result << ");\n";
7696 
7697 	/* Perform the casting operation. Add swizzle operator if possible. */
7698 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7699 	{
7700 		/* Handle the bool case exclusively */
7701 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7702 		{
7703 			result << "result = (bool(lside_value) == false) ? 0 : 1";
7704 		}
7705 		else
7706 		{
7707 			result << "result = (lside_value == false) ? 0 : 1";
7708 		}
7709 	}
7710 	else
7711 	{
7712 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7713 		{
7714 			result << "result = " << dst_type_string << "(lside_value)";
7715 		}
7716 		else
7717 		{
7718 			result << "result = lside_value";
7719 		}
7720 	}
7721 
7722 	if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7723 	{
7724 		/* Add a swizzle operator  */
7725 		DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7726 		DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7727 
7728 		unsigned int  swizzle_component_order[4] = { 0 };
7729 		unsigned int  swizzle_n_components		 = 0;
7730 		_swizzle_type swizzle_operator			 = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7731 		std::string   swizzle_string;
7732 
7733 		getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7734 
7735 		if (swizzle_n_components > 0)
7736 		{
7737 			result << "." << swizzle_string;
7738 		}
7739 	}
7740 
7741 	/* Close the shader implementation. */
7742 	result << ";\n"
7743 			  "}\n";
7744 
7745 	return result.str();
7746 }
7747 
7748 /** Initializes program & shader objects needed to run the iteration, given
7749  *  user-specified test case descriptor.
7750  *
7751  *  This function can throw a TestError exception if a GL error is detected
7752  *  during execution.
7753  *
7754  *  @param test_case Descriptor to use for the iteration.
7755  **/
initIteration(_test_case & test_case)7756 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7757 {
7758 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7759 
7760 	/* Create program & shader objects */
7761 	m_po_id = gl.createProgram();
7762 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7763 
7764 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7765 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7766 
7767 	/* Configure shader body */
7768 	std::string body		 = getVertexShaderBody(test_case);
7769 	const char* body_raw_ptr = body.c_str();
7770 
7771 	gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7773 
7774 	/* Store it in the test case descriptor for logging purposes */
7775 	test_case.shader_body = body;
7776 
7777 	/* Compile the shader */
7778 	glw::GLint compile_status = GL_FALSE;
7779 
7780 	gl.compileShader(m_vs_id);
7781 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7782 
7783 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7784 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7785 
7786 	if (compile_status != GL_TRUE)
7787 	{
7788 		TCU_FAIL("Shader compilation failed");
7789 	}
7790 
7791 	/* Attach the shader to the program obejct */
7792 	gl.attachShader(m_po_id, m_vs_id);
7793 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7794 
7795 	/* Configure XFB for the program object */
7796 	const char* xfb_varying_name = "result";
7797 
7798 	gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7799 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7800 
7801 	/* Link the program object */
7802 	glw::GLint link_status = GL_FALSE;
7803 
7804 	gl.linkProgram(m_po_id);
7805 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7806 
7807 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7808 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7809 
7810 	if (link_status != GL_TRUE)
7811 	{
7812 		TCU_FAIL("Program linking failed");
7813 	}
7814 
7815 	/* Retrieve attribute locations */
7816 	m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7817 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7818 
7819 	if (m_po_base_value_attribute_location == -1)
7820 	{
7821 		TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7822 	}
7823 }
7824 
7825 /** Initializes GL objects used by all test cases.
7826  *
7827  *  This function may throw a TestError exception if GL implementation reports
7828  *  an error at any point.
7829  **/
initTest()7830 void GPUShaderFP64Test5::initTest()
7831 {
7832 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7833 
7834 	/* Generate buffer object IDs */
7835 	gl.genBuffers(1, &m_base_value_bo_id);
7836 	gl.genBuffers(1, &m_xfb_bo_id);
7837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7838 
7839 	/* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7840 	 * will never eat up more than 1 double (as per test spec) and we will be drawing
7841 	 * as many points in a single draw call as there are defined in m_base_values array.
7842 	 */
7843 	const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7844 
7845 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7846 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7847 
7848 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7849 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7850 
7851 	/* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7852 	 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7853 	 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7854 	 */
7855 	const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7856 
7857 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7858 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7859 
7860 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7862 
7863 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7864 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7865 
7866 	/* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7867 	m_xfb_bo_size = xfb_bo_size;
7868 
7869 	/* Generate a vertex array object we will need to use for the draw calls */
7870 	gl.genVertexArrays(1, &m_vao_id);
7871 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7872 
7873 	gl.bindVertexArray(m_vao_id);
7874 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7875 }
7876 
7877 /** Executes test iteration.
7878  *
7879  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7880  */
iterate()7881 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7882 {
7883 	/* Do not execute the test if GL_ARB_texture_view is not supported */
7884 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7885 	{
7886 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7887 	}
7888 
7889 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7890 	{
7891 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7892 	}
7893 
7894 	/* Initialize GL objects needed to run the tests */
7895 	initTest();
7896 
7897 	/* Build iteration array to run the tests in an automated manner */
7898 	_test_case test_cases[] = {
7899 		/* test case type */ /* source type */ /* destination type */
7900 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7901 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7902 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7903 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7904 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7905 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7906 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7907 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7908 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7909 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7910 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7911 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7912 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7913 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7914 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7915 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7916 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7917 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7918 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7919 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7920 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7921 
7922 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7923 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7924 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7925 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7926 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7927 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7928 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7929 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7930 	};
7931 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7932 
7933 	/* Execute all iterations */
7934 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7935 	{
7936 		_test_case& test_case = test_cases[n_test_case];
7937 
7938 		/* Initialize a program object we will use to perform the casting */
7939 		initIteration(test_case);
7940 
7941 		/* Use the program object to XFB the results */
7942 		m_has_test_passed &= executeIteration(test_case);
7943 
7944 		/* Release the GL Resource for this sub test */
7945 		deinitInteration();
7946 
7947 	} /* for (all test cases) */
7948 	/* We're done */
7949 	if (m_has_test_passed)
7950 	{
7951 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7952 	}
7953 	else
7954 	{
7955 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7956 	}
7957 
7958 	return STOP;
7959 }
7960 
7961 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7962  *  for which the data have been generated.
7963  *
7964  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
7965  *  @param test_case Descriptor of the test case, for which the vertex shader was
7966  *                   generated.
7967  *
7968  *  @return true if the data were found to be valid, false otherwise.
7969  **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7970 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7971 {
7972 	const Utils::_variable_type base_dst_type		= Utils::getBaseVariableType(test_case.dst_type);
7973 	const Utils::_variable_type base_src_type		= Utils::getBaseVariableType(test_case.src_type);
7974 	const float					epsilon				= 1e-5f;
7975 	const unsigned int			n_base_values		= sizeof(m_base_values) / sizeof(m_base_values[0]);
7976 	const unsigned int			n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7977 	const unsigned int			n_src_components	= Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7978 	bool						result				= true;
7979 	_swizzle_type				swizzle_operator	= SWIZZLE_TYPE_NONE;
7980 	unsigned int				swizzle_order[4]	= { 0 };
7981 	const unsigned char*		traveller_ptr		= data_ptr;
7982 
7983 	if (!Utils::isMatrixVariableType(test_case.src_type))
7984 	{
7985 		DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7986 		DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7987 
7988 		swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7989 
7990 		getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7991 								 DE_NULL,					/* out_n_components */
7992 								 swizzle_order);
7993 	}
7994 
7995 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7996 	{
7997 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7998 		{
7999 			unsigned int n_swizzled_component = n_result_component;
8000 
8001 			if (swizzle_operator != SWIZZLE_TYPE_NONE)
8002 			{
8003 				n_swizzled_component =
8004 					(n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
8005 			}
8006 
8007 			switch (base_dst_type)
8008 			{
8009 			case Utils::VARIABLE_TYPE_BOOL:
8010 			case Utils::VARIABLE_TYPE_INT:
8011 			{
8012 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8013 				double expected_value	 = ref_expected_value;
8014 				int	result_value		  = *((int*)traveller_ptr);
8015 
8016 				if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
8017 				{
8018 					if (expected_value != 0.0)
8019 					{
8020 						expected_value = 1.0;
8021 					}
8022 				}
8023 
8024 				if (result_value != (int)expected_value)
8025 				{
8026 					m_testCtx.getLog() << tcu::TestLog::Message
8027 									   << "Invalid boolean/integer value obtained when doing an "
8028 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8029 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8030 									   << "]"
8031 										  ", component index: ["
8032 									   << n_swizzled_component << "]"
8033 																  ", value: ["
8034 									   << ref_expected_value << "]"
8035 																" to GLSL type ["
8036 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8037 																							  ", retrieved value: ["
8038 									   << result_value << "]"
8039 														  ", expected value: ["
8040 									   << (int)expected_value << "]"
8041 																 ", shader used:\n"
8042 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8043 
8044 					result = false;
8045 				}
8046 
8047 				traveller_ptr += sizeof(int);
8048 				break;
8049 			} /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8050 
8051 			case Utils::VARIABLE_TYPE_DOUBLE:
8052 			{
8053 				double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8054 				double expected_value	 = ref_expected_value;
8055 				double result_value		  = *((double*)traveller_ptr);
8056 
8057 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8058 				{
8059 					expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8060 				}
8061 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8062 				{
8063 					expected_value = (int)expected_value;
8064 				}
8065 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8066 				{
8067 					// Negative values in base values array when converted to unsigned int will be ZERO
8068 					// Addition operations done inside the shader in such cases will operate on ZERO rather
8069 					// than the negative value being passed.
8070 					// Replicate the sequence of conversion and addition operations done on the
8071 					// shader input, to calculate the expected values in XFB data in the
8072 					// problematic cases.
8073 					if (expected_value < 0)
8074 					{
8075 						expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8076 					}
8077 					expected_value = (unsigned int)expected_value;
8078 				}
8079 
8080 				traveller_ptr += sizeof(double);
8081 				if (de::abs(result_value - expected_value) > epsilon)
8082 				{
8083 					m_testCtx.getLog() << tcu::TestLog::Message
8084 									   << "Invalid double-precision floating-point value obtained when doing an "
8085 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8086 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8087 									   << "]"
8088 										  ", component index: ["
8089 									   << n_swizzled_component << "]"
8090 																  ", value: ["
8091 									   << ref_expected_value << "]"
8092 																" to GLSL type ["
8093 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8094 																							  ", retrieved value: ["
8095 									   << std::setprecision(16) << result_value << "]"
8096 																				   ", expected value: ["
8097 									   << std::setprecision(16) << expected_value << "]"
8098 																					 ", shader used:\n"
8099 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8100 
8101 					result = false;
8102 				}
8103 
8104 				break;
8105 			} /* VARIABLE_TYPE_DOUBLE case */
8106 
8107 			case Utils::VARIABLE_TYPE_FLOAT:
8108 			{
8109 				float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8110 				float expected_value	 = ref_expected_value;
8111 				float result_value		 = *((float*)traveller_ptr);
8112 
8113 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8114 				{
8115 					expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8116 				}
8117 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8118 				{
8119 					expected_value = (float)((int)expected_value);
8120 				}
8121 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8122 				{
8123 					expected_value = (float)((unsigned int)expected_value);
8124 				}
8125 
8126 				traveller_ptr += sizeof(float);
8127 				if (de::abs(result_value - expected_value) > epsilon)
8128 				{
8129 					m_testCtx.getLog() << tcu::TestLog::Message
8130 									   << "Invalid single-precision floating-point value obtained when doing an "
8131 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8132 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8133 									   << "]"
8134 										  ", component index: ["
8135 									   << n_swizzled_component << "]"
8136 																  ", value: ["
8137 									   << ref_expected_value << "]"
8138 																" to GLSL type ["
8139 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8140 																							  ", retrieved value: ["
8141 									   << std::setprecision(16) << result_value << "]"
8142 																				   ", expected value: ["
8143 									   << std::setprecision(16) << expected_value << "]"
8144 																					 ", shader used:\n"
8145 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8146 
8147 					result = false;
8148 				}
8149 
8150 				break;
8151 			} /* VARIABLE_TYPE_FLOAT case */
8152 
8153 			case Utils::VARIABLE_TYPE_UINT:
8154 			{
8155 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8156 				double expected_value	 = ref_expected_value;
8157 				unsigned int result_value = *((unsigned int*)traveller_ptr);
8158 
8159 				traveller_ptr += sizeof(unsigned int);
8160 				if (result_value != (unsigned int)expected_value)
8161 				{
8162 					if (expected_value < 0.0)
8163 					{
8164 						// It is undefined to convert a negative floating-point value to an uint.
8165 						break;
8166 					}
8167 
8168 					m_testCtx.getLog() << tcu::TestLog::Message
8169 									   << "Invalid unsigned integer value obtained when doing an "
8170 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8171 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8172 									   << "]"
8173 										  ", component index: ["
8174 									   << n_swizzled_component << "]"
8175 																  ", value: ["
8176 									   << ref_expected_value << "]"
8177 																" to GLSL type ["
8178 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8179 																							  ", retrieved value: ["
8180 									   << result_value << "]"
8181 														  ", expected value: ["
8182 									   << (unsigned int)expected_value << "]"
8183 																		  ", shader used:\n"
8184 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8185 
8186 					result = false;
8187 				}
8188 
8189 				break;
8190 			} /* VARIABLE_TYPE_UINT case */
8191 
8192 			default:
8193 			{
8194 				TCU_FAIL("Unrecognized variable type");
8195 			}
8196 			} /* switch (test_case.dst_type) */
8197 		}	 /* for (all result components) */
8198 	}		  /* for (all base values) */
8199 
8200 	return result;
8201 }
8202 
8203 /** Constructor
8204  *
8205  *  @param context Rendering context.
8206  */
GPUShaderFP64Test6(deqp::Context & context)8207 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8208 	: TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8209 											   "during compilation time.")
8210 	, m_cs_id(0)
8211 	, m_fs_id(0)
8212 	, m_gs_id(0)
8213 	, m_tc_id(0)
8214 	, m_te_id(0)
8215 	, m_vs_id(0)
8216 	, m_has_test_passed(true)
8217 {
8218 }
8219 
8220 /** Deinitializes all buffers and GL objects that may have been generated
8221  *  during test execution.
8222  **/
deinit()8223 void GPUShaderFP64Test6::deinit()
8224 {
8225 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8226 
8227 	if (m_cs_id != 0)
8228 	{
8229 		gl.deleteShader(m_cs_id);
8230 
8231 		m_cs_id = 0;
8232 	}
8233 
8234 	if (m_fs_id != 0)
8235 	{
8236 		gl.deleteShader(m_fs_id);
8237 
8238 		m_fs_id = 0;
8239 	}
8240 
8241 	if (m_gs_id != 0)
8242 	{
8243 		gl.deleteShader(m_gs_id);
8244 
8245 		m_gs_id = 0;
8246 	}
8247 
8248 	if (m_tc_id != 0)
8249 	{
8250 		gl.deleteShader(m_tc_id);
8251 
8252 		m_tc_id = 0;
8253 	}
8254 
8255 	if (m_te_id != 0)
8256 	{
8257 		gl.deleteShader(m_te_id);
8258 
8259 		m_te_id = 0;
8260 	}
8261 
8262 	if (m_vs_id != 0)
8263 	{
8264 		gl.deleteShader(m_vs_id);
8265 
8266 		m_vs_id = 0;
8267 	}
8268 }
8269 
8270 /** Executes a single test case.
8271  *
8272  *  This function can throw TestError exceptions if GL implementation reports
8273  *  an error.
8274  *
8275  *  @param test_case Test case descriptor.
8276  *
8277  *  @return true if test case passed, false otherwise.
8278  **/
executeIteration(const _test_case & test_case)8279 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8280 {
8281 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
8282 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8283 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
8284 	bool				  result	 = true;
8285 	const char*			  stage_body = NULL;
8286 	const char*			  stage_name = NULL;
8287 
8288 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8289 	{
8290 		const glw::GLuint so_id = so_ids[n_so_id];
8291 
8292 		/* Skip compute shader if it is not supported */
8293 		if (0 == so_id)
8294 		{
8295 			continue;
8296 		}
8297 
8298 		/* Compile the shader */
8299 		gl.compileShader(so_id);
8300 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8301 
8302 		/* Has the compilation failed as expected? */
8303 		glw::GLint compile_status = GL_TRUE;
8304 
8305 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8306 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8307 
8308 		if (compile_status == GL_TRUE)
8309 		{
8310 			/* What is the current stage's name? */
8311 			if (so_id == m_cs_id)
8312 			{
8313 				stage_body = test_case.cs_shader_body.c_str();
8314 				stage_name = "Compute shader";
8315 			}
8316 			else if (so_id == m_fs_id)
8317 			{
8318 				stage_body = test_case.fs_shader_body.c_str();
8319 				stage_name = "Fragment shader";
8320 			}
8321 			else if (so_id == m_gs_id)
8322 			{
8323 				stage_body = test_case.gs_shader_body.c_str();
8324 				stage_name = "Geometry shader";
8325 			}
8326 			else if (so_id == m_tc_id)
8327 			{
8328 				stage_body = test_case.tc_shader_body.c_str();
8329 				stage_name = "Tessellation control shader";
8330 			}
8331 			else if (so_id == m_te_id)
8332 			{
8333 				stage_body = test_case.te_shader_body.c_str();
8334 				stage_name = "Tessellation evaluation shader";
8335 			}
8336 			else if (so_id == m_vs_id)
8337 			{
8338 				stage_body = test_case.vs_shader_body.c_str();
8339 				stage_name = "Vertex shader";
8340 			}
8341 			else
8342 			{
8343 				/* Doesn't make much sense to throw exceptions here so.. */
8344 				stage_body = "";
8345 				stage_name = "[?]";
8346 			}
8347 
8348 			/* This shader should have never compiled successfully! */
8349 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8350 							   << " has been compiled successfully, even though the shader was malformed."
8351 								  " Following is shader body:\n"
8352 							   << stage_body << tcu::TestLog::EndMessage;
8353 
8354 			result = false;
8355 		}
8356 	} /* for (all shader objects) */
8357 
8358 	return result;
8359 }
8360 
8361 /** Retrieves body of a compute shader that should be used for the purpose of
8362  *  user-specified test case.
8363  *
8364  *  @param test_case Test case descriptor to use.
8365  *
8366  *  @return Requested string.
8367  **/
getComputeShaderBody(const _test_case & test_case)8368 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8369 {
8370 	std::stringstream result_sstream;
8371 
8372 	/* Add pre-amble */
8373 	result_sstream << "#version 420\n"
8374 					  "#extension GL_ARB_compute_shader          : require\n"
8375 					  "\n"
8376 					  "layout(local_size_x = 6) in;\n"
8377 					  "\n"
8378 					  "void main()\n"
8379 					  "{\n";
8380 
8381 	/* Add local variable declarations */
8382 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8383 
8384 	if (test_case.src_array_size > 1)
8385 	{
8386 		result_sstream << "[" << test_case.src_array_size << "]";
8387 	}
8388 
8389 	result_sstream << ";\n";
8390 
8391 	if (test_case.wrap_dst_type_in_structure)
8392 	{
8393 		result_sstream << "struct\n"
8394 						  "{\n"
8395 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8396 	}
8397 	else
8398 	{
8399 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8400 	}
8401 
8402 	result_sstream << ";\n";
8403 
8404 	if (test_case.wrap_dst_type_in_structure)
8405 	{
8406 		result_sstream << "\n} dst;\n";
8407 	}
8408 
8409 	/* Add actual body */
8410 	result_sstream << "dst = src;\n"
8411 					  "}\n";
8412 
8413 	/* Return the body */
8414 	return result_sstream.str();
8415 }
8416 
8417 /** Retrieves body of a fragment shader that should be used for the purpose of
8418  *  user-specified test case.
8419  *
8420  *  @param test_case Test case descriptor to use.
8421  *
8422  *  @return Requested string.
8423  **/
getFragmentShaderBody(const _test_case & test_case)8424 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8425 {
8426 	std::stringstream result_sstream;
8427 
8428 	/* Add pre-amble */
8429 	result_sstream << "#version 420\n"
8430 					  "\n"
8431 					  "void main()\n"
8432 					  "{\n";
8433 
8434 	/* Add local variable declarations */
8435 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8436 
8437 	if (test_case.src_array_size > 1)
8438 	{
8439 		result_sstream << "[" << test_case.src_array_size << "]";
8440 	}
8441 
8442 	result_sstream << ";\n";
8443 
8444 	if (test_case.wrap_dst_type_in_structure)
8445 	{
8446 		result_sstream << "struct\n"
8447 						  "{\n"
8448 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8449 	}
8450 	else
8451 	{
8452 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8453 	}
8454 
8455 	result_sstream << ";\n";
8456 
8457 	if (test_case.wrap_dst_type_in_structure)
8458 	{
8459 		result_sstream << "\n} dst;\n";
8460 	}
8461 
8462 	/* Add actual body */
8463 	result_sstream << "dst = src;\n"
8464 					  "}\n";
8465 
8466 	/* Return the body */
8467 	return result_sstream.str();
8468 }
8469 
8470 /** Retrieves body of a geometry shader that should be used for the purpose of
8471  *  user-specified test case.
8472  *
8473  *  @param test_case Test case descriptor to use.
8474  *
8475  *  @return Requested string.
8476  **/
getGeometryShaderBody(const _test_case & test_case)8477 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8478 {
8479 	std::stringstream result_sstream;
8480 
8481 	/* Add preamble */
8482 	result_sstream << "#version 420\n"
8483 					  "\n"
8484 					  "layout(points)                 in;\n"
8485 					  "layout(max_vertices=1, points) out;\n"
8486 					  "\n"
8487 					  "void main()\n"
8488 					  "{\n";
8489 
8490 	/* Add local variable declarations */
8491 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8492 
8493 	if (test_case.src_array_size > 1)
8494 	{
8495 		result_sstream << "[" << test_case.src_array_size << "]";
8496 	}
8497 
8498 	result_sstream << ";\n";
8499 
8500 	if (test_case.wrap_dst_type_in_structure)
8501 	{
8502 		result_sstream << "struct\n"
8503 						  "{\n"
8504 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8505 	}
8506 	else
8507 	{
8508 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8509 	}
8510 
8511 	result_sstream << ";\n"
8512 					  "\n";
8513 
8514 	if (test_case.wrap_dst_type_in_structure)
8515 	{
8516 		result_sstream << "} dst;\n";
8517 	}
8518 
8519 	/* Add actual body */
8520 	result_sstream << "dst = src;\n"
8521 					  "}\n";
8522 
8523 	/* We're done! */
8524 	return result_sstream.str();
8525 }
8526 
8527 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8528  *  user-specified test case.
8529  *
8530  *  @param test_case Test case descriptor to use.
8531  *
8532  *  @return Requested string.
8533  **/
getTessellationControlShaderBody(const _test_case & test_case)8534 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8535 {
8536 	std::stringstream result_sstream;
8537 
8538 	/* Add preamble */
8539 	result_sstream << "#version 420\n"
8540 					  "\n"
8541 					  "layout(vertices=4) out;\n"
8542 					  "\n"
8543 					  "void main()\n"
8544 					  "{\n";
8545 
8546 	/* Add local variable declarations. */
8547 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8548 
8549 	if (test_case.src_array_size > 1)
8550 	{
8551 		result_sstream << "[" << test_case.src_array_size << "]";
8552 	}
8553 
8554 	result_sstream << ";\n";
8555 
8556 	if (test_case.wrap_dst_type_in_structure)
8557 	{
8558 		result_sstream << "struct\n"
8559 						  "{\n"
8560 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8561 	}
8562 	else
8563 	{
8564 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8565 	}
8566 
8567 	if (test_case.wrap_dst_type_in_structure)
8568 	{
8569 		result_sstream << ";\n"
8570 						  "} dst;\n";
8571 	}
8572 	else
8573 	{
8574 		result_sstream << ";\n";
8575 	}
8576 
8577 	/* Continue with the actual body. */
8578 	result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8579 					  "gl_TessLevelOuter[1] = 1.0;\n"
8580 					  "dst                  = src;\n"
8581 					  "}\n";
8582 
8583 	/* Return the body */
8584 	return result_sstream.str();
8585 }
8586 
8587 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8588  *  user-specified test case.
8589  *
8590  *  @param test_case Test case descriptor to use.
8591  *
8592  *  @return Requested string.
8593  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8594 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8595 {
8596 	std::stringstream result_sstream;
8597 
8598 	/* Add preamble */
8599 	result_sstream << "#version 420\n"
8600 					  "\n"
8601 					  "layout(isolines) in;\n"
8602 					  "\n"
8603 					  "void main()\n"
8604 					  "{\n";
8605 
8606 	/* Add local variable declarations */
8607 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8608 
8609 	if (test_case.src_array_size > 1)
8610 	{
8611 		result_sstream << "[" << test_case.src_array_size << "]";
8612 	}
8613 
8614 	result_sstream << ";\n";
8615 
8616 	if (test_case.wrap_dst_type_in_structure)
8617 	{
8618 		result_sstream << "struct\n"
8619 						  "{\n"
8620 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8621 	}
8622 	else
8623 	{
8624 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8625 	}
8626 
8627 	if (test_case.wrap_dst_type_in_structure)
8628 	{
8629 		result_sstream << ";\n"
8630 						  "} dst;\n";
8631 	}
8632 	else
8633 	{
8634 		result_sstream << ";\n";
8635 	}
8636 
8637 	/* Continue with the actual body. */
8638 	result_sstream << "dst = src;\n";
8639 
8640 	/* Complete the body */
8641 	result_sstream << "}\n";
8642 
8643 	/* Return the body */
8644 	return result_sstream.str();
8645 }
8646 
8647 /** Retrieves body of a vertex shader that should be used for the purpose of
8648  *  user-specified test case.
8649  *
8650  *  @param test_case Test case descriptor to use.
8651  *
8652  *  @return Requested string.
8653  **/
getVertexShaderBody(const _test_case & test_case)8654 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8655 {
8656 	std::stringstream result_sstream;
8657 
8658 	/* Add preamble */
8659 	result_sstream << "#version 420\n"
8660 					  "\n"
8661 					  "void main()\n"
8662 					  "{\n";
8663 
8664 	/* Add local variables */
8665 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8666 
8667 	if (test_case.src_array_size > 1)
8668 	{
8669 		result_sstream << "[" << test_case.src_array_size << "]";
8670 	}
8671 
8672 	result_sstream << ";\n";
8673 
8674 	if (test_case.wrap_dst_type_in_structure)
8675 	{
8676 		result_sstream << "struct\n"
8677 						  "{\n"
8678 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8679 	}
8680 	else
8681 	{
8682 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8683 	}
8684 
8685 	if (test_case.wrap_dst_type_in_structure)
8686 	{
8687 		result_sstream << ";\n"
8688 						  "} dst;\n";
8689 	}
8690 	else
8691 	{
8692 		result_sstream << ";\n";
8693 	}
8694 
8695 	/* Start actual body */
8696 	result_sstream << "dst         = src;\n"
8697 					  "gl_Position = vec4(1.0);\n"
8698 					  "}";
8699 
8700 	return result_sstream.str();
8701 }
8702 
8703 /** Initializes shader objects required to run the test. */
initTest()8704 void GPUShaderFP64Test6::initTest()
8705 {
8706 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8707 
8708 	/* Generate shader objects */
8709 
8710 	/* Compute shader support and GL 4.2 required */
8711 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8712 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8713 	{
8714 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8715 	}
8716 
8717 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8718 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8719 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8720 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8721 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8722 
8723 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8724 }
8725 
8726 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8727  *
8728  *  @param test_case Test case descriptor to generate the shader bodies for.
8729  **/
initIteration(_test_case & test_case)8730 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8731 {
8732 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8733 
8734 	test_case.cs_shader_body = getComputeShaderBody(test_case);
8735 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
8736 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
8737 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8738 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8739 	test_case.vs_shader_body = getVertexShaderBody(test_case);
8740 
8741 	/* Assign the bodies to relevant shaders */
8742 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8743 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8744 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8745 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8746 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8747 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8748 
8749 	/* m_cs_id is initialized only if compute_shader is supported */
8750 	if (0 != m_cs_id)
8751 	{
8752 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8753 	}
8754 
8755 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8756 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8757 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8758 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8759 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8760 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8761 }
8762 
8763 /** Executes test iteration.
8764  *
8765  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8766  */
iterate()8767 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8768 {
8769 	/* Do not execute the test if GL_ARB_texture_view is not supported */
8770 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8771 	{
8772 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8773 	}
8774 
8775 	/* Initialize GL objects needed to run the tests */
8776 	initTest();
8777 
8778 	/* Build iteration array to run the tests in an automated manner */
8779 	_test_case test_cases[] = {
8780 		/* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8781 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8782 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8783 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8784 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8785 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8786 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8787 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8788 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8789 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8790 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8791 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8792 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8793 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8794 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8795 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8796 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8797 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8798 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8799 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8800 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8801 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8802 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8803 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8804 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8805 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8806 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8807 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8808 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8809 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8810 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8811 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8812 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8813 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8814 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8815 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8816 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8817 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8818 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8819 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8820 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8821 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8822 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8823 	};
8824 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8825 
8826 	/* Execute all iterations */
8827 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8828 	{
8829 		_test_case& test_case = test_cases[n_test_case];
8830 
8831 		/* Initialize a program object we will use to perform the casting */
8832 		initIteration(test_case);
8833 
8834 		/* Use the program object to XFB the results */
8835 		m_has_test_passed &= executeIteration(test_case);
8836 
8837 	} /* for (all test cases) */
8838 
8839 	/* We're done */
8840 	if (m_has_test_passed)
8841 	{
8842 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8843 	}
8844 	else
8845 	{
8846 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8847 	}
8848 
8849 	return STOP;
8850 }
8851 
8852 /** Constructor
8853  *
8854  *  @param context Rendering context.
8855  */
GPUShaderFP64Test7(deqp::Context & context)8856 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8857 	: TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8858 									"in all shader stages.")
8859 	, m_are_double_inputs_supported(false)
8860 	, m_fbo_id(0)
8861 	, m_fs_id(0)
8862 	, m_gs_id(0)
8863 	, m_has_test_passed(true)
8864 	, m_n_max_components_per_stage(0)
8865 	, m_n_xfb_varyings(0)
8866 	, m_po_id(0)
8867 	, m_tc_id(0)
8868 	, m_te_id(0)
8869 	, m_to_id(0)
8870 	, m_to_data(NULL)
8871 	, m_to_height(4)
8872 	, m_to_width(4)
8873 	, m_xfb_bo_id(0)
8874 	, m_xfb_varyings(NULL)
8875 	, m_vao_id(0)
8876 	, m_vs_id(0)
8877 {
8878 }
8879 
8880 /** Compiles all shaders attached to test program object and links it.
8881  *
8882  *  @param variables
8883  *
8884  *  @return true if the process was executed successfully, false otherwise.
8885  */
buildTestProgram(_variables & variables)8886 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8887 {
8888 	std::string			  fs_body = getFragmentShaderBody(variables);
8889 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
8890 	std::string			  gs_body = getGeometryShaderBody(variables);
8891 	std::string			  tc_body = getTessellationControlShaderBody(variables);
8892 	std::string			  te_body = getTessellationEvaluationShaderBody(variables);
8893 	std::string			  vs_body = getVertexShaderBody(variables);
8894 	bool				  result  = false;
8895 
8896 	/* Try to link the program object */
8897 	glw::GLint link_status = GL_FALSE;
8898 
8899 	/* Compile the shaders */
8900 	if (!compileShader(m_fs_id, fs_body))
8901 	{
8902 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8903 
8904 		goto end;
8905 	}
8906 
8907 	if (!compileShader(m_gs_id, gs_body))
8908 	{
8909 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8910 
8911 		goto end;
8912 	}
8913 
8914 	if (!compileShader(m_tc_id, tc_body))
8915 	{
8916 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8917 						   << tcu::TestLog::EndMessage;
8918 
8919 		goto end;
8920 	}
8921 
8922 	if (!compileShader(m_te_id, te_body))
8923 	{
8924 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8925 						   << tcu::TestLog::EndMessage;
8926 
8927 		goto end;
8928 	}
8929 
8930 	if (!compileShader(m_vs_id, vs_body))
8931 	{
8932 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8933 
8934 		goto end;
8935 	}
8936 
8937 	/* Configure XFB */
8938 	releaseXFBVaryingNames();
8939 	generateXFBVaryingNames(variables);
8940 
8941 	gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8942 
8943 	gl.linkProgram(m_po_id);
8944 
8945 	/* Have we succeeded? */
8946 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8947 
8948 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8949 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8950 
8951 	if (link_status != GL_TRUE)
8952 	{
8953 		m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8954 						   << tcu::TestLog::EndMessage;
8955 
8956 		goto end;
8957 	}
8958 
8959 	/* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8960 	if (m_are_double_inputs_supported)
8961 	{
8962 		const size_t n_variables = variables.size();
8963 
8964 		for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8965 		{
8966 			_variable&		  current_variable = variables[n_variable];
8967 			std::stringstream attribute_name_sstream;
8968 
8969 			attribute_name_sstream << "in_vs_variable" << n_variable;
8970 
8971 			if (current_variable.array_size > 1)
8972 			{
8973 				attribute_name_sstream << "[0]";
8974 			}
8975 
8976 			current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8977 
8978 			if (current_variable.attribute_location == -1)
8979 			{
8980 				m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8981 								   << attribute_name_sstream.str().c_str()
8982 								   << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8983 
8984 				m_has_test_passed = false;
8985 				goto end;
8986 			}
8987 		} /* for (all test variables) */
8988 	}	 /* if (m_are_double_inputs_supported) */
8989 
8990 	m_current_fs_body = fs_body;
8991 	m_current_gs_body = gs_body;
8992 	m_current_tc_body = tc_body;
8993 	m_current_te_body = te_body;
8994 	m_current_vs_body = vs_body;
8995 
8996 	result = true;
8997 
8998 end:
8999 	return result;
9000 }
9001 
9002 /** Updates shader object's body and then compiles the shader.
9003  *
9004  *  @param body Body to use for the shader.
9005  *
9006  *  @return true if the shader compiled successfully, false otherwise.
9007  **/
compileShader(glw::GLint shader_id,const std::string & body)9008 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
9009 {
9010 	const char*			  body_raw_ptr   = body.c_str();
9011 	glw::GLint			  compile_status = GL_FALSE;
9012 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
9013 
9014 	gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
9015 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
9016 
9017 	gl.compileShader(shader_id);
9018 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9019 
9020 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
9021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9022 
9023 	return (compile_status == GL_TRUE);
9024 }
9025 
9026 /** Configure storage of a buffer object used for capturing XFB data.
9027  *
9028  *  @param variables Holds descriptor for all variables used for the iteration the
9029  *                   BO is being configured for. Storage size will be directly related
9030  *                   to the number of the variables and their type.
9031  */
configureXFBBuffer(const _variables & variables)9032 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9033 {
9034 	DE_ASSERT(m_n_xfb_varyings != 0);
9035 
9036 	/* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9037 	 * The test only draws a single patch, and triangles are caught by transform feed-back.
9038 	 * Let's initialize the storage, according to the list of variables that will be used
9039 	 * for the test run.
9040 	 */
9041 	unsigned int bo_size = 0;
9042 
9043 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9044 		 variables_iterator++)
9045 	{
9046 		const _variable& variable		= *variables_iterator;
9047 		unsigned int	 n_bytes_needed = static_cast<unsigned int>(
9048 			Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9049 
9050 		bo_size += n_bytes_needed;
9051 	} /* for (all variables) */
9052 
9053 	bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9054 
9055 	/* Set up the BO storage */
9056 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9057 
9058 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9059 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9060 }
9061 
9062 /** Deinitializes all buffers and GL objects that may have been generated
9063  *  during test execution.
9064  **/
deinit()9065 void GPUShaderFP64Test7::deinit()
9066 {
9067 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9068 
9069 	if (m_fbo_id != 0)
9070 	{
9071 		gl.deleteFramebuffers(1, &m_fbo_id);
9072 
9073 		m_fbo_id = 0;
9074 	}
9075 
9076 	if (m_fs_id != 0)
9077 	{
9078 		gl.deleteShader(m_fs_id);
9079 
9080 		m_fs_id = 0;
9081 	}
9082 
9083 	if (m_gs_id != 0)
9084 	{
9085 		gl.deleteShader(m_gs_id);
9086 
9087 		m_gs_id = 0;
9088 	}
9089 
9090 	if (m_po_id != 0)
9091 	{
9092 		gl.deleteProgram(m_po_id);
9093 
9094 		m_po_id = 0;
9095 	}
9096 
9097 	if (m_tc_id != 0)
9098 	{
9099 		gl.deleteShader(m_tc_id);
9100 
9101 		m_tc_id = 0;
9102 	}
9103 
9104 	if (m_te_id != 0)
9105 	{
9106 		gl.deleteShader(m_te_id);
9107 
9108 		m_te_id = 0;
9109 	}
9110 
9111 	if (m_to_data != NULL)
9112 	{
9113 		delete[] m_to_data;
9114 
9115 		m_to_data = NULL;
9116 	}
9117 
9118 	if (m_to_id != 0)
9119 	{
9120 		gl.deleteTextures(1, &m_to_id);
9121 
9122 		m_to_id = 0;
9123 	}
9124 
9125 	if (m_xfb_bo_id != 0)
9126 	{
9127 		gl.deleteBuffers(1, &m_xfb_bo_id);
9128 
9129 		m_xfb_bo_id = 0;
9130 	}
9131 
9132 	if (m_xfb_varyings != DE_NULL)
9133 	{
9134 		releaseXFBVaryingNames();
9135 	}
9136 
9137 	if (m_vao_id != 0)
9138 	{
9139 		gl.deleteVertexArrays(1, &m_vao_id);
9140 
9141 		m_vao_id = 0;
9142 	}
9143 
9144 	if (m_vs_id != 0)
9145 	{
9146 		gl.deleteShader(m_vs_id);
9147 
9148 		m_vs_id = 0;
9149 	}
9150 }
9151 
9152 /** Executes the functional part of the test (case a) from the test spec)
9153  *
9154  *  @param variables Vector of variable descriptors defining properties of
9155  *                   variables that should be used for the iteration.
9156  *
9157  *  @return true if the test passed, false otherwise.
9158  **/
executeFunctionalTest(_variables & variables)9159 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9160 {
9161 	bool result = true;
9162 
9163 	/* Build the test program */
9164 	if (!buildTestProgram(variables))
9165 	{
9166 		return false;
9167 	}
9168 
9169 	/* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9170 	if (m_are_double_inputs_supported)
9171 	{
9172 		setInputAttributeValues(variables);
9173 	}
9174 
9175 	/* Set up buffer object to hold XFB data. The data will be used for logging purposes
9176 	 * only, if a data mismatch is detected.
9177 	 */
9178 	configureXFBBuffer(variables);
9179 
9180 	/* Issue a draw call using the test program */
9181 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9182 
9183 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9184 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9185 
9186 	gl.clear(GL_COLOR_BUFFER_BIT);
9187 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9188 
9189 	gl.useProgram(m_po_id);
9190 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9191 
9192 	gl.viewport(0, /* x */
9193 				0, /* y */
9194 				m_to_width, m_to_height);
9195 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9196 
9197 	gl.beginTransformFeedback(GL_TRIANGLES);
9198 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9199 	{
9200 		gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9201 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9202 	}
9203 	gl.endTransformFeedback();
9204 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9205 
9206 	/* Verify color attachment contents */
9207 	const float epsilon = 1.0f / 255.0f;
9208 
9209 	gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9210 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9211 
9212 	for (unsigned int y = 0; y < m_to_height; ++y)
9213 	{
9214 		const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9215 
9216 		for (unsigned int x = 0; x < m_to_width; ++x)
9217 		{
9218 			const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9219 
9220 			if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9221 				de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9222 			{
9223 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9224 								   << ")"
9225 									  "; expected:(0, 255, 0, 0), found: ("
9226 								   << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9227 								   << ", " << (int)pixel_ptr[3]
9228 								   << "), with the following variable types used as varyings:"
9229 								   << tcu::TestLog::EndMessage;
9230 
9231 				/* List the variable types that failed the test */
9232 				const size_t n_variables = variables.size();
9233 
9234 				for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9235 				{
9236 					m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9237 									   << Utils::getVariableTypeString(variables[n_variable].type)
9238 									   << " (array size:" << variables[n_variable].array_size << ")"
9239 									   << tcu::TestLog::EndMessage;
9240 				} /* for (all variable types) */
9241 
9242 				/* Log the variable contents */
9243 				logVariableContents(variables);
9244 
9245 				/* Log shaders used for the iteration */
9246 				m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9247 															   "\n"
9248 															   "(VS):\n"
9249 								   << m_current_vs_body.c_str() << "\n"
9250 								   << "(TC):\n"
9251 									  "\n"
9252 								   << m_current_tc_body.c_str() << "\n"
9253 																   "(TE):\n"
9254 																   "\n"
9255 								   << m_current_te_body.c_str() << "\n"
9256 																   "(GS):\n"
9257 								   << m_current_gs_body.c_str() << "\n"
9258 																   "(FS):\n"
9259 																   "\n"
9260 								   << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9261 
9262 				result = false;
9263 
9264 				goto end;
9265 			}
9266 		} /* for (all columns) */
9267 	}	 /* for (all rows) */
9268 
9269 /* All done! */
9270 end:
9271 	return result;
9272 }
9273 
9274 /** Takes user-input vector of test variables and allocates & fills an array of strings
9275  *  holding names of geometry shader stage varyings that should be captured during
9276  *  transform feedback operation. The array will be stored in m_xfb_varyings.
9277  *
9278  *  @param variables Holds all test variable descriptors to be used for the iteration.
9279  */
generateXFBVaryingNames(const _variables & variables)9280 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9281 {
9282 	unsigned int n_variable = 0;
9283 	unsigned int n_varying  = 0;
9284 	unsigned int n_varyings = 0;
9285 
9286 	if (m_xfb_varyings != NULL)
9287 	{
9288 		releaseXFBVaryingNames();
9289 	}
9290 
9291 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9292 		 ++variables_iterator)
9293 	{
9294 		const _variable& variable = *variables_iterator;
9295 
9296 		n_varyings += variable.array_size;
9297 	}
9298 
9299 	m_xfb_varyings = new glw::GLchar*[n_varyings];
9300 
9301 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9302 		 ++variables_iterator, ++n_variable)
9303 	{
9304 		const _variable& variable = *variables_iterator;
9305 
9306 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9307 		{
9308 			std::stringstream varying_sstream;
9309 			size_t			  varying_length;
9310 
9311 			varying_sstream << "gs_variable" << n_variable;
9312 
9313 			if (variable.array_size > 1)
9314 			{
9315 				varying_sstream << "[" << array_index << "]";
9316 			}
9317 
9318 			/* Store the varying name */
9319 			varying_length			  = varying_sstream.str().length();
9320 			m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9321 
9322 			memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9323 			m_xfb_varyings[n_varying][varying_length] = 0;
9324 		} /* for (all array indices) */
9325 	}	 /* for (all varyings) */
9326 
9327 	m_n_xfb_varyings = n_varyings;
9328 }
9329 
9330 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9331  *  without using the "flat" keyword. (case c) )
9332  *
9333  *  @param input_variable_type Variable type to use for input variable declaration.
9334  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9335  *                             of the arrayed variable.
9336  *
9337  *  @return Requested string.
9338  **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9339 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9340 	Utils::_variable_type input_variable_type, unsigned int array_size)
9341 {
9342 	std::stringstream result_sstream;
9343 	std::stringstream array_index_stringstream;
9344 	std::stringstream array_size_stringstream;
9345 
9346 	if (array_size > 1)
9347 	{
9348 		array_index_stringstream << "[0]";
9349 		array_size_stringstream << "[" << array_size << "]";
9350 	}
9351 
9352 	if (Utils::isMatrixVariableType(input_variable_type))
9353 	{
9354 		array_index_stringstream << "[0].x";
9355 	}
9356 	else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9357 	{
9358 		array_index_stringstream << "[0]";
9359 	}
9360 
9361 	result_sstream << "#version 400\n"
9362 					  "\n"
9363 					  "in "
9364 				   << Utils::getVariableTypeString(input_variable_type) << " test_input"
9365 				   << array_size_stringstream.str() << ";\n"
9366 													   "\n"
9367 													   "out float test_output;\n"
9368 													   "\n"
9369 													   "void main()\n"
9370 													   "{\n"
9371 													   "    if (test_input"
9372 				   << array_index_stringstream.str() << " > 2.0)\n"
9373 														"    {\n"
9374 														"        test_output = 1.0;\n"
9375 														"    }\n"
9376 														"    else\n"
9377 														"    {\n"
9378 														"        test_output = 3.0;\n"
9379 														"    }\n"
9380 														"}\n";
9381 
9382 	return result_sstream.str();
9383 }
9384 
9385 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9386  *
9387  *  @param input_variable_type Variable type to use for input variable declaration.
9388  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9389  *                             of the arrayed variable.
9390  *
9391  *  @return Requested string.
9392  **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9393 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9394 	Utils::_variable_type output_variable_type, unsigned int array_size)
9395 {
9396 	std::stringstream array_index_sstream;
9397 	std::stringstream array_size_sstream;
9398 	std::stringstream result_sstream;
9399 	std::string		  output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9400 
9401 	if (array_size > 1)
9402 	{
9403 		array_index_sstream << "[0]";
9404 		array_size_sstream << "[" << array_size << "]";
9405 	}
9406 
9407 	result_sstream << "#version 400\n"
9408 					  "\n"
9409 					  "out "
9410 				   << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9411 																								   "\n"
9412 																								   "void main()\n"
9413 																								   "{\n"
9414 																								   "    test_output"
9415 				   << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9416 																						   "}\n";
9417 
9418 	return result_sstream.str();
9419 }
9420 
9421 /** Retrieves body of a fragment shader that uses user-specified set of variables
9422  *  to declare contents of input & output block.
9423  *
9424  *  @param variables As per description.
9425  *
9426  *  @return Requested string.
9427  **/
getFragmentShaderBody(const _variables & variables)9428 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9429 {
9430 	std::stringstream result_sstream;
9431 
9432 	/* Form the pre-amble */
9433 	result_sstream << "#version 400\n"
9434 					  "\n"
9435 
9436 				   /* Add input block */
9437 				   << "in GS_DATA\n"
9438 					  "{\n"
9439 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9440 																		  "\n"
9441 
9442 				   /* Add output variable */
9443 				   << "out vec4 result;\n"
9444 					  "\n"
9445 
9446 					  /* Add main() definition */
9447 					  "void main()\n"
9448 					  "{\n"
9449 					  "const double epsilon = 1e-5;\n"
9450 					  "\n"
9451 					  "result = vec4(1, 0, 0, 0);\n"
9452 					  "\n";
9453 
9454 	/* Determine expected values first */
9455 	unsigned int base_counter = 1;
9456 	const size_t n_variables  = variables.size();
9457 
9458 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9459 	{
9460 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9461 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9462 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9463 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9464 
9465 		std::stringstream array_size_sstream;
9466 
9467 		if (variable_array_size > 1)
9468 		{
9469 			array_size_sstream << "[" << variable_array_size << "]";
9470 		}
9471 
9472 		/* Local variable declaration */
9473 		result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9474 					   << ";\n"
9475 						  "\n";
9476 
9477 		/* Set expected values */
9478 		for (unsigned int index = 0; index < variable_array_size; ++index)
9479 		{
9480 			std::stringstream array_index_sstream;
9481 
9482 			if (variable_array_size > 1)
9483 			{
9484 				array_index_sstream << "[" << index << "]";
9485 			}
9486 
9487 			result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9488 						   << variable_type_string << "(";
9489 
9490 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9491 			{
9492 				unsigned int expected_value =
9493 					(base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9494 
9495 				if (m_are_double_inputs_supported)
9496 				{
9497 					/* VS input attributes */
9498 					//expected_value += (base_counter + 6);
9499 					expected_value -= 1;
9500 				}
9501 
9502 				result_sstream << expected_value;
9503 
9504 				if (n_component != (n_variable_type_components - 1))
9505 				{
9506 					result_sstream << ", ";
9507 				}
9508 
9509 				++base_counter;
9510 			} /* for (all components) */
9511 
9512 			result_sstream << ");\n";
9513 		} /* for (all array indices) */
9514 
9515 		result_sstream << "\n";
9516 	} /* for (all variable types) */
9517 
9518 	/* Now that we know the expected values, do a huge conditional check to verify if all
9519 	 * input variables carry correct information.
9520 	 */
9521 	result_sstream << "if (";
9522 
9523 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9524 	{
9525 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9526 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9527 		bool				  is_variable_type_matrix	= Utils::isMatrixVariableType(variable_type);
9528 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9529 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9530 
9531 		for (unsigned int index = 0; index < variable_array_size; ++index)
9532 		{
9533 			std::stringstream array_index_sstream;
9534 
9535 			if (variable_array_size > 1)
9536 			{
9537 				array_index_sstream << "[" << index << "]";
9538 			}
9539 
9540 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9541 			{
9542 				std::stringstream component_index_sstream;
9543 
9544 				if (n_variable_type_components > 1)
9545 				{
9546 					component_index_sstream << "[" << n_component << "]";
9547 				}
9548 
9549 				result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9550 
9551 				if (is_variable_type_matrix)
9552 				{
9553 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9554 					const unsigned int column	= n_component % n_columns;
9555 					const unsigned int row		 = n_component / n_columns;
9556 
9557 					result_sstream << "[" << column << "]"
9558 													   "."
9559 								   << Utils::getComponentAtIndex(row);
9560 				}
9561 				else
9562 				{
9563 					result_sstream << component_index_sstream.str();
9564 				}
9565 
9566 				result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9567 
9568 				if (is_variable_type_matrix)
9569 				{
9570 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9571 					const unsigned int column	= n_component % n_columns;
9572 					const unsigned int row		 = n_component / n_columns;
9573 
9574 					result_sstream << "[" << column << "]"
9575 													   "."
9576 								   << Utils::getComponentAtIndex(row);
9577 				}
9578 				else
9579 				{
9580 					result_sstream << component_index_sstream.str();
9581 				}
9582 
9583 				result_sstream << ") <= epsilon &&";
9584 			} /* for (all components) */
9585 		}	 /* for (all array indices) */
9586 	}		  /* for (all variable types) */
9587 
9588 	result_sstream << "true)\n"
9589 					  "{\n"
9590 					  "    result = vec4(0, 1, 0, 0);\n"
9591 					  "}\n"
9592 					  "}\n";
9593 
9594 	/* All done */
9595 	return result_sstream.str();
9596 }
9597 
9598 /** Retrieves body of a geometry shader that uses user-specified set of variables
9599  *  to declare contents of input & output block.
9600  *
9601  *  @param variables As per description.
9602  *
9603  *  @return Requested string.
9604  **/
getGeometryShaderBody(const _variables & variables)9605 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9606 {
9607 	std::stringstream result_sstream;
9608 
9609 	/* Form the pre-amble */
9610 	result_sstream << "#version 400\n"
9611 					  "\n"
9612 					  "layout(triangles)                      in;\n"
9613 					  "layout(triangle_strip, max_vertices=4) out;\n"
9614 					  "\n"
9615 
9616 					  /* Add the input block */
9617 					  "in TE_DATA\n"
9618 					  "{\n"
9619 				   << getVariableDeclarations("te", variables) << "} in_data[];\n"
9620 																  "\n"
9621 
9622 																  /* Add the output block */
9623 																  "out GS_DATA\n"
9624 																  "{\n"
9625 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9626 																		  "\n"
9627 
9628 																		  /* Declare main() function */
9629 																		  "void main()\n"
9630 																		  "{\n";
9631 
9632 	/* Take input variables, add a predefined value and forward them to output variables */
9633 	const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9634 									1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
9635 	const unsigned int n_quad_vertices =
9636 		sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9637 	const size_t n_variables = variables.size();
9638 
9639 	for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9640 	{
9641 		unsigned int counter			 = 4;
9642 		const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9643 
9644 		for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9645 		{
9646 			unsigned int		  variable_array_size = variables[n_variable].array_size;
9647 			Utils::_variable_type variable_type		  = variables[n_variable].type;
9648 			unsigned int n_variable_type_components   = Utils::getNumberOfComponentsForVariableType(variable_type);
9649 			std::string  variable_type_string		  = Utils::getVariableTypeString(variable_type);
9650 
9651 			for (unsigned int index = 0; index < variable_array_size; ++index)
9652 			{
9653 				std::stringstream array_index_sstream;
9654 
9655 				if (variable_array_size > 1)
9656 				{
9657 					array_index_sstream << "[" << index << "]";
9658 				}
9659 
9660 				result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9661 							   << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9662 							   << variable_type_string << "(";
9663 
9664 				for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9665 				{
9666 					result_sstream << (counter++);
9667 
9668 					if (n_component != (n_variable_type_components - 1))
9669 					{
9670 						result_sstream << ", ";
9671 					}
9672 				} /* for (all components) */
9673 
9674 				result_sstream << ");\n";
9675 			} /* for (all array indices) */
9676 		}	 /* for (all variable types) */
9677 
9678 		result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9679 					   << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9680 																					  "EmitVertex();\n";
9681 	} /* for (all emitted quad vertices) */
9682 
9683 	result_sstream << "EndPrimitive();\n"
9684 					  "}\n";
9685 
9686 	/* All done */
9687 	return result_sstream.str();
9688 }
9689 
9690 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9691  *  to declare contents of input & output block.
9692  *
9693  *  @param variables As per description.
9694  *
9695  *  @return Requested string.
9696  **/
getTessellationControlShaderBody(const _variables & variables)9697 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9698 {
9699 	std::stringstream result_sstream;
9700 
9701 	/* Form the pre-amble */
9702 	result_sstream << "#version 400\n"
9703 					  "\n"
9704 					  "layout (vertices=4) out;\n"
9705 
9706 					  /* Declare input block */
9707 					  "in VS_DATA\n"
9708 					  "{\n"
9709 				   << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9710 
9711 																  /* Declare output block */
9712 																  "out TC_DATA\n"
9713 																  "{\n"
9714 				   << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9715 																  "\n"
9716 
9717 																  /* Define main() */
9718 																  "void main()\n"
9719 																  "{\n"
9720 																  "    gl_TessLevelInner[0] = 1;\n"
9721 																  "    gl_TessLevelInner[1] = 1;\n"
9722 																  "    gl_TessLevelOuter[0] = 1;\n"
9723 																  "    gl_TessLevelOuter[1] = 1;\n"
9724 																  "    gl_TessLevelOuter[2] = 1;\n"
9725 																  "    gl_TessLevelOuter[3] = 1;\n"
9726 																  "\n";
9727 
9728 	/* Take input variables, add a predefined value and forward them to output variables */
9729 	const size_t n_variables = variables.size();
9730 	unsigned int counter	 = 2;
9731 
9732 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9733 	{
9734 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9735 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9736 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9737 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9738 
9739 		for (unsigned int index = 0; index < variable_array_size; ++index)
9740 		{
9741 			std::stringstream array_index_sstream;
9742 
9743 			if (variable_array_size > 1)
9744 			{
9745 				array_index_sstream << "[" << index << "]";
9746 			}
9747 
9748 			result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9749 						   << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9750 						   << variable_type_string << "(";
9751 
9752 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9753 			{
9754 				result_sstream << (counter++);
9755 
9756 				if (n_component != (n_variable_type_components - 1))
9757 				{
9758 					result_sstream << ", ";
9759 				}
9760 			}
9761 
9762 			result_sstream << ");\n";
9763 		} /* for (all array indices) */
9764 	}	 /* for (all variable types) */
9765 
9766 	result_sstream << "}\n";
9767 
9768 	/* We're done */
9769 	return result_sstream.str();
9770 }
9771 
9772 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9773  *  to declare contents of input & output block.
9774  *
9775  *  @param variables As per description.
9776  *
9777  *  @return Requested string.
9778  **/
getTessellationEvaluationShaderBody(const _variables & variables)9779 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9780 {
9781 	std::stringstream result_sstream;
9782 
9783 	/* Form the pre-amble */
9784 	result_sstream << "#version 400\n"
9785 					  "\n"
9786 					  "layout(quads) in;\n"
9787 					  "\n"
9788 
9789 					  /* Define input block */
9790 					  "in TC_DATA\n"
9791 					  "{\n"
9792 				   << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9793 																  "\n"
9794 
9795 																  /* Define output block */
9796 																  "out TE_DATA\n"
9797 																  "{\n"
9798 				   << getVariableDeclarations("te", variables) << "};\n"
9799 																  "\n"
9800 
9801 																  /* Define main() */
9802 																  "void main()\n"
9803 																  "{\n";
9804 
9805 	/* Take input variables, add a predefined value and forward them to output variables */
9806 	const size_t n_variables = variables.size();
9807 	unsigned int counter	 = 3;
9808 
9809 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9810 	{
9811 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9812 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9813 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9814 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9815 
9816 		for (unsigned int index = 0; index < variable_array_size; ++index)
9817 		{
9818 			std::stringstream array_index_sstream;
9819 
9820 			if (variable_array_size > 1)
9821 			{
9822 				array_index_sstream << "[" << index << "]";
9823 			}
9824 
9825 			result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9826 						   << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9827 
9828 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9829 			{
9830 				result_sstream << (counter++);
9831 
9832 				if (n_component != (n_variable_type_components - 1))
9833 				{
9834 					result_sstream << ", ";
9835 				}
9836 			} /* for (all components) */
9837 
9838 			result_sstream << ");\n";
9839 		} /* for (all array indices) */
9840 	}	 /* for (all variable types) */
9841 
9842 	result_sstream << "}\n";
9843 
9844 	/* All done */
9845 	return result_sstream.str();
9846 }
9847 
9848 /** Returns a string containing declarations of user-specified set of variables.
9849  *  Each declaration can optionally use a layot qualifier requested by the caller.
9850  *
9851  *  @param prefix             Prefix to use for variable names.
9852  *  @param variables          List of variables to declare in the result string.
9853  *  @param explicit_locations true if each declaration should explicitly define location
9854  *                            of the variable ( eg. (layout location=X) )
9855  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
9856  *                            be NULL.
9857  *
9858  *  @return Requested string.
9859  **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9860 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9861 														const char* layout_qualifier)
9862 {
9863 	std::stringstream result_sstream;
9864 
9865 	/* Define output variables */
9866 	const size_t n_variables = variables.size();
9867 
9868 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9869 	{
9870 		unsigned int		  variable_array_size  = variables[n_variable].array_size;
9871 		Utils::_variable_type variable_type		   = variables[n_variable].type;
9872 		std::string			  variable_type_string = Utils::getVariableTypeString(variable_type);
9873 
9874 		result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9875 
9876 		if (variable_array_size > 1)
9877 		{
9878 			result_sstream << "[" << variable_array_size << "]";
9879 		}
9880 
9881 		result_sstream << ";\n";
9882 	} /* for (all user-specified variable types) */
9883 
9884 	return result_sstream.str();
9885 }
9886 
9887 /** Retrieves body of a vertex shader that uses user-specified set of variables
9888  *  to declare contents of input & output block.
9889  *
9890  *  @param variables As per description.
9891  *
9892  *  @return Requested string.
9893  **/
getVertexShaderBody(const _variables & variables)9894 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9895 {
9896 	std::stringstream result_sstream;
9897 
9898 	/* Form pre-amble */
9899 	result_sstream << "#version 400\n"
9900 					  "\n";
9901 
9902 	/* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9903 	if (m_are_double_inputs_supported)
9904 	{
9905 		result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9906 					   << getVariableDeclarations("in_vs", variables, "in");
9907 	}
9908 
9909 	/* Define output variables */
9910 	result_sstream << "out VS_DATA\n"
9911 					  "{\n"
9912 				   << getVariableDeclarations("vs", variables);
9913 
9914 	/* Define main() */
9915 	result_sstream << "};\n"
9916 					  "\n"
9917 					  "void main()\n"
9918 					  "{\n";
9919 
9920 	/* Set output variable values */
9921 	unsigned int counter	 = 1;
9922 	const size_t n_variables = variables.size();
9923 
9924 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9925 	{
9926 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9927 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9928 		const unsigned int	n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9929 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9930 
9931 		for (unsigned int index = 0; index < variable_array_size; ++index)
9932 		{
9933 			if (variable_array_size == 1)
9934 			{
9935 				result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9936 			}
9937 			else
9938 			{
9939 				result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9940 							   << " = " << variable_type_string << "(";
9941 			}
9942 
9943 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9944 			{
9945 				result_sstream << (double)(counter++);
9946 
9947 				/* Use input attributes, if available */
9948 				if (m_are_double_inputs_supported)
9949 				{
9950 					result_sstream << " + in_vs_variable" << n_variable;
9951 
9952 					if (variable_array_size > 1)
9953 					{
9954 						result_sstream << "[" << index << "]";
9955 					}
9956 
9957 					if (Utils::isMatrixVariableType(variables[n_variable].type))
9958 					{
9959 						const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9960 						const unsigned int column	= n_component % n_columns;
9961 						const unsigned int row		 = n_component / n_columns;
9962 
9963 						result_sstream << "[" << (column) << "]"
9964 															 "."
9965 									   << Utils::getComponentAtIndex(row);
9966 					}
9967 					else if (n_variable_type_components > 1)
9968 					{
9969 						result_sstream << "[" << n_component << "]";
9970 					}
9971 				}
9972 
9973 				if (n_component != (n_variable_type_components - 1))
9974 				{
9975 					result_sstream << ", ";
9976 				}
9977 			} /* for (all components) */
9978 
9979 			result_sstream << ");\n";
9980 		}
9981 	} /* for (all variable types) */
9982 
9983 	/* We will be using geometry shader to lay out the actual vertices so
9984 	 * the only thing we need to make sure is that the vertex never gets
9985 	 * culled.
9986 	 */
9987 	result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9988 					  "}\n";
9989 
9990 	/* That's it */
9991 	return result_sstream.str();
9992 }
9993 
9994 /** Initializes shader objects required to run the test. */
initTest()9995 void GPUShaderFP64Test7::initTest()
9996 {
9997 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9998 
9999 	/* Are double-precision input variables supported? */
10000 	m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
10001 
10002 	/* Create a vertex array object */
10003 	gl.genVertexArrays(1, &m_vao_id);
10004 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
10005 
10006 	gl.bindVertexArray(m_vao_id);
10007 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
10008 
10009 	/* Create a texture object we will use as FBO's color attachment */
10010 	gl.genTextures(1, &m_to_id);
10011 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
10012 
10013 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
10014 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
10015 
10016 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
10017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
10018 
10019 	/* Allocate temporary buffer to hold the texture data we will be reading
10020 	 * from color attachment. */
10021 	m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
10022 
10023 	/* Create and set up a framebuffer object */
10024 	gl.genFramebuffers(1, &m_fbo_id);
10025 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
10026 
10027 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
10028 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
10029 
10030 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10031 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10032 
10033 	/* Create all shader objects */
10034 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10035 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10036 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10037 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10038 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10039 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10040 
10041 	/* Create test program object */
10042 	m_po_id = gl.createProgram();
10043 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10044 
10045 	/* Attach the shaders to the program object */
10046 	gl.attachShader(m_po_id, m_fs_id);
10047 	gl.attachShader(m_po_id, m_gs_id);
10048 	gl.attachShader(m_po_id, m_tc_id);
10049 	gl.attachShader(m_po_id, m_te_id);
10050 	gl.attachShader(m_po_id, m_vs_id);
10051 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10052 
10053 	/* The test passes double-precision values through the whole rendering pipeline.
10054 	 * This translates to a notable amount of components that we would need to transfer
10055 	 * all values in one fell swoop. The number is large enough to exceed minimum
10056 	 * capabilities as described for OpenGL 4.0 implementations.
10057 	 * For that reason, the test executes in turns. Each turn is allocated as many
10058 	 * double-precision scalar/matrix values as supported by the tested GL implementation.
10059 	 */
10060 	glw::GLint gl_max_fragment_input_components_value				  = 0;
10061 	glw::GLint gl_max_geometry_input_components_value				  = 0;
10062 	glw::GLint gl_max_geometry_output_components_value				  = 0;
10063 	glw::GLint gl_max_tess_control_input_components_value			  = 0;
10064 	glw::GLint gl_max_tess_control_output_components_value			  = 0;
10065 	glw::GLint gl_max_tess_evaluation_input_components_value		  = 0;
10066 	glw::GLint gl_max_tess_evaluation_output_components_value		  = 0;
10067 	glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10068 	glw::GLint gl_max_vertex_output_components_value				  = 0;
10069 
10070 	gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10071 	gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10072 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10073 	gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10074 	gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10075 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10076 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10077 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10078 				   &gl_max_transform_feedback_interleaved_components_value);
10079 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10080 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10081 
10082 	m_n_max_components_per_stage =
10083 		de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10084 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10085 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10086 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10087 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10088 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10089 	m_n_max_components_per_stage =
10090 		de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10091 	m_n_max_components_per_stage =
10092 		de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10093 
10094 	/* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10095 	 * the input patch */
10096 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
10097 
10098 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10099 
10100 	/* Initialize a BO we will use to hold XFB data */
10101 	gl.genBuffers(1, &m_xfb_bo_id);
10102 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10103 
10104 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10105 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10106 
10107 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10108 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10109 }
10110 
10111 /** Executes test iteration.
10112  *
10113  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10114  */
iterate()10115 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10116 {
10117 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10118 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10119 	{
10120 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10121 	}
10122 
10123 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10124 	{
10125 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10126 	}
10127 
10128 	/* Initialize GL objects required to run the test */
10129 	initTest();
10130 
10131 	/* Check the negative cases first */
10132 	const Utils::_variable_type double_variable_types[] = {
10133 		Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10134 		Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10135 		Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10136 		Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10137 		Utils::VARIABLE_TYPE_DMAT4X3,
10138 	};
10139 	const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10140 
10141 	for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10142 		 ++n_double_variable_type)
10143 	{
10144 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
10145 		{
10146 			Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10147 
10148 			if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10149 			{
10150 				m_testCtx.getLog() << tcu::TestLog::Message
10151 								   << "A fragment shader with double-precision output variable compiled successfully."
10152 								   << tcu::TestLog::EndMessage;
10153 
10154 				m_has_test_passed = false;
10155 			}
10156 
10157 			if (compileShader(m_fs_id,
10158 							  getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10159 			{
10160 				m_testCtx.getLog()
10161 					<< tcu::TestLog::Message
10162 					<< "A fragment shader with double-precision input variables lacking flat layout qualifier"
10163 					   " compiled successfully."
10164 					<< tcu::TestLog::EndMessage;
10165 
10166 				m_has_test_passed = false;
10167 			}
10168 		}
10169 	} /* for (all variable types) */
10170 
10171 	/* Execute functional test. Split the run into as many iterations as necessary
10172 	 * so that we do not exceed GL implementation's capabilities. */
10173 	unsigned int n_tested_variables = 0;
10174 	_variables   variables_to_test;
10175 
10176 	while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10177 	{
10178 		glw::GLint total_n_used_components = 0;
10179 
10180 		/* Use as many variables as possible for the iterations. Do not exceed maximum amount
10181 		 * of varying components that can be used for all shadr stages.
10182 		 */
10183 		while (total_n_used_components < m_n_max_components_per_stage &&
10184 			   n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10185 		{
10186 			_variable	new_variable;
10187 			unsigned int n_type_components = 0;
10188 			glw::GLint   n_used_components = 0;
10189 
10190 			new_variable.array_size =
10191 				((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10192 			new_variable.type = double_variable_types[n_tested_variables / 2];
10193 
10194 			/* Double-precision varyings can use twice as many components as single-precision FPs */
10195 			n_type_components = 4 /* components per location */ *
10196 								Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10197 			n_used_components = n_type_components * new_variable.array_size * 2;
10198 
10199 			/* Do we have enough space? */
10200 			if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10201 			{
10202 				if (n_used_components > m_n_max_components_per_stage)
10203 				{ //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10204 					n_tested_variables++;
10205 				}
10206 				break;
10207 			}
10208 
10209 			/* We can safely test the type in current iteration */
10210 			total_n_used_components += n_used_components;
10211 			n_tested_variables++;
10212 
10213 			variables_to_test.push_back(new_variable);
10214 		}
10215 
10216 		if (variables_to_test.size() > 0)
10217 		{
10218 			m_has_test_passed &= executeFunctionalTest(variables_to_test);
10219 
10220 			variables_to_test.clear();
10221 		}
10222 	}
10223 
10224 	/* We're done */
10225 	if (m_has_test_passed)
10226 	{
10227 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10228 	}
10229 	else
10230 	{
10231 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10232 	}
10233 
10234 	return STOP;
10235 }
10236 
10237 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10238 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10239 {
10240 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10241 	std::stringstream	 log_sstream;
10242 
10243 	log_sstream << "Test variable values as retrieved from geometry shader:\n";
10244 
10245 	/* Map the XFB BO contents into process space */
10246 	const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10247 
10248 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10249 
10250 	/* Read the variable contents. We only care about the set of varyings emitted
10251 	 * for first vertex in the geometry shader */
10252 	unsigned int		 n_varying	 = 0;
10253 	const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10254 
10255 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10256 		 ++variables_iterator, ++n_varying)
10257 	{
10258 		const _variable&			 variable			= *variables_iterator;
10259 		const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10260 		const unsigned int			 n_components		= Utils::getNumberOfComponentsForVariableType(variable.type);
10261 
10262 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10263 		{
10264 			log_sstream << "gs_variable" << n_varying;
10265 
10266 			if (variable.array_size > 1)
10267 			{
10268 				log_sstream << "[" << array_index << "]";
10269 			}
10270 
10271 			log_sstream << ": (";
10272 
10273 			for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10274 			{
10275 				log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10276 
10277 				if (n_component != (n_components - 1))
10278 				{
10279 					log_sstream << ", ";
10280 				}
10281 
10282 				traveller_ptr += sizeof(double);
10283 			}
10284 
10285 			log_sstream << ")\n";
10286 		} /* for (all array indices) */
10287 	}	 /* for (all variables) */
10288 
10289 	/* Unmap the BO */
10290 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10291 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10292 
10293 	/* Pass the logged stream into the framework */
10294 	m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10295 }
10296 
10297 /** De-allocates an arary holding strings representing names of varyings that
10298  *  should be used for transform feed-back.
10299  **/
releaseXFBVaryingNames()10300 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10301 {
10302 	for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10303 	{
10304 		delete[] m_xfb_varyings[n_varying];
10305 	}
10306 
10307 	delete m_xfb_varyings;
10308 	m_xfb_varyings = DE_NULL;
10309 
10310 	m_n_xfb_varyings = 0;
10311 }
10312 
10313 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10314  *  Takes a list of test variables used for current iteration and assigns increasing values
10315  *  to subsequent input attributes of the test program.
10316  *
10317  *  @param variables Test variables of the current iteration.
10318  */
setInputAttributeValues(const _variables & variables)10319 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10320 {
10321 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
10322 	unsigned int		  counter = 6;
10323 
10324 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10325 		 variable_iterator++)
10326 	{
10327 		const _variable&   variable			  = *variable_iterator;
10328 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
10329 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10330 		unsigned int	   n_components		  = 0;
10331 		unsigned int	   n_columns		  = 1;
10332 
10333 		if (is_matrix_type)
10334 		{
10335 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
10336 			n_components = n_total_components / n_columns;
10337 
10338 			DE_ASSERT(n_total_components % n_columns == 0);
10339 		}
10340 		else
10341 		{
10342 			n_components = n_total_components;
10343 		}
10344 
10345 		DE_ASSERT(n_components >= 1 && n_components <= 4);
10346 
10347 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10348 		{
10349 			const double data[] = { -1, -1, -1, -1 };
10350 
10351 			switch (n_components)
10352 			{
10353 			case 1:
10354 			{
10355 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
10356 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10357 
10358 				break;
10359 			}
10360 
10361 			case 2:
10362 			{
10363 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
10364 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10365 
10366 				break;
10367 			}
10368 
10369 			case 3:
10370 			{
10371 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
10372 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10373 
10374 				break;
10375 			}
10376 
10377 			case 4:
10378 			{
10379 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
10380 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10381 
10382 				break;
10383 			}
10384 
10385 			default:
10386 			{
10387 				TCU_FAIL("Unrecognized number of components");
10388 			}
10389 			} /* switch (n_components) */
10390 
10391 			/* Make sure VAAs are disabled */
10392 			gl.disableVertexAttribArray(variable.attribute_location + index);
10393 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10394 
10395 			counter += n_components;
10396 		} /* for (all array indices) */
10397 	}	 /* for (all variables) */
10398 }
10399 
10400 /** Constructor
10401  *
10402  *  @param context Rendering context.
10403  */
GPUShaderFP64Test8(deqp::Context & context)10404 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10405 	: TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10406 											  "are accepted during compilation stage")
10407 	, m_cs_id(0)
10408 	, m_fs_id(0)
10409 	, m_gs_id(0)
10410 	, m_tc_id(0)
10411 	, m_te_id(0)
10412 	, m_vs_id(0)
10413 	, m_has_test_passed(true)
10414 {
10415 }
10416 
10417 /** Deinitializes all buffers and GL objects that may have been generated
10418  *  during test execution.
10419  **/
deinit()10420 void GPUShaderFP64Test8::deinit()
10421 {
10422 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10423 
10424 	if (m_cs_id != 0)
10425 	{
10426 		gl.deleteShader(m_cs_id);
10427 
10428 		m_cs_id = 0;
10429 	}
10430 
10431 	if (m_fs_id != 0)
10432 	{
10433 		gl.deleteShader(m_fs_id);
10434 
10435 		m_fs_id = 0;
10436 	}
10437 
10438 	if (m_gs_id != 0)
10439 	{
10440 		gl.deleteShader(m_gs_id);
10441 
10442 		m_gs_id = 0;
10443 	}
10444 
10445 	if (m_tc_id != 0)
10446 	{
10447 		gl.deleteShader(m_tc_id);
10448 
10449 		m_tc_id = 0;
10450 	}
10451 
10452 	if (m_te_id != 0)
10453 	{
10454 		gl.deleteShader(m_te_id);
10455 
10456 		m_te_id = 0;
10457 	}
10458 
10459 	if (m_vs_id != 0)
10460 	{
10461 		gl.deleteShader(m_vs_id);
10462 
10463 		m_vs_id = 0;
10464 	}
10465 }
10466 
10467 /** Executes a single test case.
10468  *
10469  *  This function can throw TestError exceptions if GL implementation reports
10470  *  an error.
10471  *
10472  *  @param test_case Test case descriptor.
10473  *
10474  *  @return true if test case passed, false otherwise.
10475  **/
executeIteration(const _test_case & test_case)10476 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10477 {
10478 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10479 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10480 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
10481 	bool				  result	 = true;
10482 	const char*			  stage_body = NULL;
10483 	const char*			  stage_name = NULL;
10484 
10485 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10486 	{
10487 		const glw::GLuint so_id = so_ids[n_so_id];
10488 
10489 		/* Skip compute shader if it is not supported */
10490 		if (0 == so_id)
10491 		{
10492 			continue;
10493 		}
10494 
10495 		/* Compile the shader */
10496 		gl.compileShader(so_id);
10497 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10498 
10499 		/* Has the compilation succeeded as expected? */
10500 		glw::GLint compile_status = GL_FALSE;
10501 
10502 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10503 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10504 
10505 		if (compile_status == GL_FALSE)
10506 		{
10507 			/* What is the current stage's name? */
10508 			if (so_id == m_cs_id)
10509 			{
10510 				stage_body = test_case.cs_shader_body.c_str();
10511 				stage_name = "Compute shader";
10512 			}
10513 			else if (so_id == m_fs_id)
10514 			{
10515 				stage_body = test_case.fs_shader_body.c_str();
10516 				stage_name = "Fragment shader";
10517 			}
10518 			else if (so_id == m_gs_id)
10519 			{
10520 				stage_body = test_case.gs_shader_body.c_str();
10521 				stage_name = "Geometry shader";
10522 			}
10523 			else if (so_id == m_tc_id)
10524 			{
10525 				stage_body = test_case.tc_shader_body.c_str();
10526 				stage_name = "Tessellation control shader";
10527 			}
10528 			else if (so_id == m_te_id)
10529 			{
10530 				stage_body = test_case.te_shader_body.c_str();
10531 				stage_name = "Tessellation evaluation shader";
10532 			}
10533 			else if (so_id == m_vs_id)
10534 			{
10535 				stage_body = test_case.vs_shader_body.c_str();
10536 				stage_name = "Vertex shader";
10537 			}
10538 			else
10539 			{
10540 				/* Doesn't make much sense to throw exceptions here so.. */
10541 				stage_body = "";
10542 				stage_name = "[?]";
10543 			}
10544 
10545 			/* This shader should have never failed to compile! */
10546 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10547 							   << " has not compiled successfully, even though the shader is valid."
10548 								  " Following is shader's body:\n"
10549 							   << stage_body << tcu::TestLog::EndMessage;
10550 
10551 			result = false;
10552 		}
10553 	} /* for (all shader objects) */
10554 
10555 	return result;
10556 }
10557 
10558 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10559  *  type.
10560  *
10561  *  @param variable_type Variable type to return valid argument lists for.
10562  **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10563 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10564 	const Utils::_variable_type& variable_type)
10565 {
10566 	const Utils::_variable_type matrix_types[] = {
10567 		Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10568 		Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10569 		Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10570 	};
10571 	const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10572 												   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10573 	const unsigned int n_matrix_types	 = sizeof(matrix_types) / sizeof(matrix_types[0]);
10574 	const unsigned int n_scalar_types	 = sizeof(scalar_types) / sizeof(scalar_types[0]);
10575 	const int		   n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10576 
10577 	/* Construct the argument list tree root. Each node carries a counter that tells how many components
10578 	 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10579 	 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10580 	 * used to define a subsequent argument, and its counter is increased by the amount of components
10581 	 * described by the type.
10582 	 */
10583 	_argument_list_tree_node root;
10584 
10585 	root.n_components_used = 0;
10586 	root.parent			   = NULL;
10587 	root.type			   = variable_type;
10588 
10589 	/* Fill till all leaves use up all available components */
10590 	_argument_list_tree_node_queue nodes_queue;
10591 
10592 	nodes_queue.push(&root);
10593 
10594 	do
10595 	{
10596 		/* Pop the first item in the queue */
10597 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10598 		nodes_queue.pop();
10599 
10600 		/* Matrix variable types can be defined by a combination of non-matrix variable types OR
10601 		 * a single matrix variable type.
10602 		 *
10603 		 * Let's handle the latter case first.
10604 		 */
10605 		const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10606 
10607 		if (Utils::isMatrixVariableType(current_node_ptr->type))
10608 		{
10609 			/* Iterate through all known matrix types. All the types can be used
10610 			 * as a constructor, assuming only one value is used to define new matrix's
10611 			 * contents. */
10612 			for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10613 			{
10614 				Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10615 
10616 				/* Construct a new child node. Since GLSL spec clearly states we must not use more
10617 				 * than one constructor argument if the only argument is a matrix type, mark the node
10618 				 * as if it defined all available components.
10619 				 */
10620 				_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10621 
10622 				new_subnode->n_components_used = n_total_components;
10623 				new_subnode->parent			   = current_node_ptr;
10624 				new_subnode->type			   = new_argument_type;
10625 
10626 				/* Add the descriptor to node list but do not add it to the queue. This would be
10627 				 * a redundant operation, since no new children nodes would have been assigned to
10628 				 * this node anyway.
10629 				 */
10630 				current_node_ptr->children.push_back(new_subnode);
10631 			} /* for (all matrix types) */
10632 		}	 /* if (current node's type is a matrix) */
10633 
10634 		/* Now for a combination of non-matrix variable types.. */
10635 		if (!Utils::isMatrixVariableType(current_node_ptr->type))
10636 		{
10637 			/* Iterate through all known scalar types */
10638 			for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10639 			{
10640 				Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10641 				const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10642 
10643 				/* Only use the scalar type if we don't exceed the amount of components we can define
10644 				 * for requested type.
10645 				 */
10646 				if (n_new_argument_components <= n_components_remaining)
10647 				{
10648 					/* Form new node descriptor */
10649 					_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10650 
10651 					new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10652 					new_subnode->parent			   = current_node_ptr;
10653 					new_subnode->type			   = new_argument_type;
10654 
10655 					current_node_ptr->children.push_back(new_subnode);
10656 					nodes_queue.push(new_subnode);
10657 				}
10658 			} /* for (all scalar types) */
10659 		}	 /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10660 	} while (nodes_queue.size() > 0);
10661 
10662 	/* To construct the argument lists, traverse the tree. Each path from root to child
10663 	 * gives us a single argument list.
10664 	 *
10665 	 * First, identify leaf nodes.
10666 	 */
10667 	_argument_list_tree_nodes leaf_nodes;
10668 
10669 	nodes_queue.push(&root);
10670 
10671 	do
10672 	{
10673 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10674 		nodes_queue.pop();
10675 
10676 		if (current_node_ptr->children.size() == 0)
10677 		{
10678 			/* This is a leaf node !*/
10679 			leaf_nodes.push_back(current_node_ptr);
10680 		}
10681 		else
10682 		{
10683 			/* Throw all children nodes to the queue */
10684 			const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10685 
10686 			for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10687 			{
10688 				nodes_queue.push(current_node_ptr->children[n_children_node]);
10689 			} /* for (all children nodes) */
10690 		}
10691 	} while (nodes_queue.size() > 0);
10692 
10693 	/* For all leaf nodes, move up the tree and construct the argument lists. */
10694 	const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10695 	_argument_lists	result;
10696 
10697 	for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10698 	{
10699 		_argument_list			  argument_list;
10700 		_argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10701 
10702 		do
10703 		{
10704 			if (current_node_ptr != &root)
10705 			{
10706 				if (argument_list.size() == 0)
10707 				{
10708 					argument_list.push_back(current_node_ptr->type);
10709 				}
10710 				else
10711 				{
10712 					argument_list.insert(argument_list.begin(), current_node_ptr->type);
10713 				}
10714 			}
10715 
10716 			current_node_ptr = current_node_ptr->parent;
10717 		} while (current_node_ptr != NULL);
10718 
10719 		result.push_back(argument_list);
10720 	} /* for (all leaf nodes) */
10721 
10722 	return result;
10723 }
10724 
10725 /** Retrieves body of a compute shader that should be used for the purpose of
10726  *  user-specified test case.
10727  *
10728  *  @param test_case Test case descriptor to use.
10729  *
10730  *  @return Requested string.
10731  **/
getComputeShaderBody(const _test_case & test_case)10732 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10733 {
10734 	std::stringstream result_sstream;
10735 
10736 	/* Form the body */
10737 	result_sstream << "#version 420\n"
10738 					  "#extension GL_ARB_compute_shader          : require\n"
10739 					  "\n"
10740 					  "layout(local_size_x = 1) in;\n"
10741 					  "\n"
10742 					  "void main()\n"
10743 					  "{\n"
10744 				   << getGeneralBody(test_case) << "}\n";
10745 
10746 	/* Return the body */
10747 	return result_sstream.str();
10748 }
10749 
10750 /** Retrieves body of a fragment shader that should be used for the purpose of
10751  *  user-specified test case.
10752  *
10753  *  @param test_case Test case descriptor to use.
10754  *
10755  *  @return Requested string.
10756  **/
getFragmentShaderBody(const _test_case & test_case)10757 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10758 {
10759 	std::stringstream result_sstream;
10760 
10761 	/* Form the body */
10762 	result_sstream << "#version 420\n"
10763 					  "\n"
10764 					  "void main()\n"
10765 					  "{\n"
10766 				   << getGeneralBody(test_case) << "}\n"
10767 												   "\n";
10768 
10769 	/* Return the body */
10770 	return result_sstream.str();
10771 }
10772 
10773 /** Returns a GLSL line that defines and initializes a variable as described by
10774  *  user-specified test case descriptor.
10775  *
10776  *  @param test_case Test case descriptor to use for the query.
10777  *
10778  *  @return As per description
10779  **/
getGeneralBody(const _test_case & test_case)10780 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10781 {
10782 	std::stringstream result_sstream;
10783 
10784 	/* Form the body */
10785 	std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10786 
10787 	result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10788 
10789 	for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10790 		 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10791 	{
10792 		const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10793 		std::string		   argument_variable_type_string   = Utils::getVariableTypeString(argument_variable_type);
10794 		const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10795 
10796 		if (argument_list_iterator != test_case.argument_list.begin())
10797 		{
10798 			result_sstream << ", ";
10799 		}
10800 
10801 		result_sstream << argument_variable_type_string << "(";
10802 
10803 		for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10804 		{
10805 			result_sstream << (double)(n_component + 1);
10806 
10807 			if (n_component != (argument_n_components - 1))
10808 			{
10809 				result_sstream << ", ";
10810 			}
10811 		} /* for (all argument components) */
10812 
10813 		result_sstream << ")";
10814 	} /* for (all arguments) */
10815 
10816 	result_sstream << ");\n";
10817 
10818 	return result_sstream.str();
10819 }
10820 
10821 /** Retrieves body of a geometry shader that should be used for the purpose of
10822  *  user-specified test case.
10823  *
10824  *  @param test_case Test case descriptor to use.
10825  *
10826  *  @return Requested string.
10827  **/
getGeometryShaderBody(const _test_case & test_case)10828 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10829 {
10830 	std::stringstream result_sstream;
10831 
10832 	/* Form the body */
10833 	result_sstream << "#version 420\n"
10834 					  "\n"
10835 					  "layout(points)                 in;\n"
10836 					  "layout(max_vertices=1, points) out;\n"
10837 					  "\n"
10838 					  "void main()\n"
10839 					  "{\n"
10840 				   << getGeneralBody(test_case) << "}\n"
10841 												   "\n";
10842 
10843 	/* We're done! */
10844 	return result_sstream.str();
10845 }
10846 
10847 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10848  *  user-specified test case.
10849  *
10850  *  @param test_case Test case descriptor to use.
10851  *
10852  *  @return Requested string.
10853  **/
getTessellationControlShaderBody(const _test_case & test_case)10854 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10855 {
10856 	std::stringstream result_sstream;
10857 
10858 	/* Form the body */
10859 	result_sstream << "#version 420\n"
10860 					  "\n"
10861 					  "layout(vertices=4) out;\n"
10862 					  "\n"
10863 					  "void main()\n"
10864 					  "{\n"
10865 				   << getGeneralBody(test_case) << "}\n"
10866 												   "\n";
10867 
10868 	/* Return the body */
10869 	return result_sstream.str();
10870 }
10871 
10872 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10873  *  user-specified test case.
10874  *
10875  *  @param test_case Test case descriptor to use.
10876  *
10877  *  @return Requested string.
10878  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10879 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10880 {
10881 	std::stringstream result_sstream;
10882 
10883 	/* Form the body */
10884 	result_sstream << "#version 420\n"
10885 					  "\n"
10886 					  "layout(isolines) in;\n"
10887 					  "\n"
10888 					  "void main()\n"
10889 					  "{\n"
10890 				   << getGeneralBody(test_case) << "}\n"
10891 												   "\n";
10892 
10893 	/* Return the body */
10894 	return result_sstream.str();
10895 }
10896 
10897 /** Retrieves body of a vertex shader that should be used for the purpose of
10898  *  user-specified test case.
10899  *
10900  *  @param test_case Test case descriptor to use.
10901  *
10902  *  @return Requested string.
10903  **/
getVertexShaderBody(const _test_case & test_case)10904 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10905 {
10906 	std::stringstream result_sstream;
10907 
10908 	/* Form the body */
10909 	result_sstream << "#version 420\n"
10910 					  "\n"
10911 					  "void main()\n"
10912 					  "{\n"
10913 				   << getGeneralBody(test_case) << "}\n"
10914 												   "\n";
10915 
10916 	return result_sstream.str();
10917 }
10918 
10919 /** Initializes shader objects required to run the test. */
initTest()10920 void GPUShaderFP64Test8::initTest()
10921 {
10922 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10923 
10924 	/* Generate shader objects */
10925 
10926 	/* Compute shader support and GL 4.2 required */
10927 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10928 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10929 	{
10930 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10931 	}
10932 
10933 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10934 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10935 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10936 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10937 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10938 
10939 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10940 }
10941 
10942 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10943  *
10944  *  @param test_case Test case descriptor to generate the shader bodies for.
10945  **/
initIteration(_test_case & test_case)10946 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10947 {
10948 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10949 
10950 	test_case.cs_shader_body = getComputeShaderBody(test_case);
10951 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
10952 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
10953 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10954 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10955 	test_case.vs_shader_body = getVertexShaderBody(test_case);
10956 
10957 	/* Assign the bodies to relevant shaders */
10958 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10959 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10960 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10961 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10962 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10963 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10964 
10965 	/* m_cs_id is initialized only if compute_shader is supported */
10966 	if (0 != m_cs_id)
10967 	{
10968 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10969 	}
10970 
10971 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10972 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10973 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10974 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10975 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10976 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10977 }
10978 
10979 /** Executes test iteration.
10980  *
10981  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10982  */
iterate()10983 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10984 {
10985 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10986 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10987 	{
10988 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10989 	}
10990 
10991 	/* Initialize GL objects needed to run the tests */
10992 	initTest();
10993 
10994 	/* Build iteration array to run the tests in an automated manner */
10995 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
10996 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10997 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10998 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
10999 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11000 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11001 													 Utils::VARIABLE_TYPE_DVEC4 };
11002 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11003 
11004 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11005 	{
11006 		const Utils::_variable_type variable_type = variable_types[n_variable_type];
11007 
11008 		/* Construct a set of argument lists valid for the variable type considered */
11009 		_argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
11010 
11011 		for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
11012 			 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
11013 		{
11014 			/* Constructor thwe test case descriptor */
11015 			_test_case test_case;
11016 
11017 			test_case.argument_list = *argument_list_iterator;
11018 			test_case.type			= variable_type;
11019 
11020 			/* Initialize a program object we will use to perform the casting */
11021 			initIteration(test_case);
11022 
11023 			/* See if the shader compiles. */
11024 			m_has_test_passed &= executeIteration(test_case);
11025 		} /* for (all argument lists) */
11026 	}	 /* for (all variable types) */
11027 
11028 	/* We're done */
11029 	if (m_has_test_passed)
11030 	{
11031 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11032 	}
11033 	else
11034 	{
11035 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11036 	}
11037 
11038 	return STOP;
11039 }
11040 
11041 /** Constructor.
11042  *
11043  *  @param context Rendering context.
11044  *
11045  **/
GPUShaderFP64Test9(deqp::Context & context)11046 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11047 	: TestCase(context, "operators", "Verifies that general and relational operators work "
11048 									 "correctly when used against double-precision floating-"
11049 									 "point types.")
11050 	, m_has_test_passed(true)
11051 	, m_po_id(0)
11052 	, m_xfb_bo_id(0)
11053 	, m_vao_id(0)
11054 	, m_vs_id(0)
11055 {
11056 	/* Left blank intentionally */
11057 }
11058 
11059 /** Deinitializes all ES objects that may have been created during
11060  *  test execution.
11061  **/
deinit()11062 void GPUShaderFP64Test9::deinit()
11063 {
11064 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11065 
11066 	if (m_po_id != 0)
11067 	{
11068 		gl.deleteProgram(m_po_id);
11069 
11070 		m_po_id = 0;
11071 	}
11072 
11073 	if (m_xfb_bo_id != 0)
11074 	{
11075 		gl.deleteBuffers(1, &m_xfb_bo_id);
11076 
11077 		m_xfb_bo_id = 0;
11078 	}
11079 
11080 	if (m_vao_id != 0)
11081 	{
11082 		gl.deleteVertexArrays(1, &m_vao_id);
11083 
11084 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11085 	}
11086 
11087 	if (m_vs_id != 0)
11088 	{
11089 		gl.deleteShader(m_vs_id);
11090 
11091 		m_vs_id = 0;
11092 	}
11093 }
11094 
11095 /** Executes a single test iteration using user-specified test case properties.
11096  *
11097  *  @param test_case Test case descriptor.
11098  *
11099  *  @return true if the pass was successful, false if the test should fail.
11100  **/
executeTestIteration(const _test_case & test_case)11101 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11102 {
11103 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
11104 	bool				  result = true;
11105 
11106 	/* Activate the test program object */
11107 	gl.useProgram(m_po_id);
11108 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11109 
11110 	/* Draw a single point with XFB enabled */
11111 	gl.beginTransformFeedback(GL_POINTS);
11112 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11113 	{
11114 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11115 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11116 	}
11117 	gl.endTransformFeedback();
11118 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11119 
11120 	/* Map the XFB BO into process space */
11121 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11122 
11123 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11124 
11125 	result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11126 
11127 	/* Unmap the BO */
11128 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11129 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11130 
11131 	return result;
11132 }
11133 
11134 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11135  *  under user-specified location.
11136  *
11137  *  @param matrix_a_type  Type of the l-side matrix.
11138  *  @param matrix_a_data  Row-ordered data of l-side matrix.
11139  *  @param matrix_b_type  Type of the r-side matrix.
11140  *  @param matrix_b_data  Row-ordered data of r-side matrix.
11141  *  @param out_result_ptr Deref to be used to store the multiplication result.
11142  **/
getMatrixMultiplicationResult(const Utils::_variable_type & matrix_a_type,const std::vector<double> & matrix_a_data,const Utils::_variable_type & matrix_b_type,const std::vector<double> & matrix_b_data,double * out_result_ptr)11143 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11144 													   const std::vector<double>&   matrix_a_data,
11145 													   const Utils::_variable_type& matrix_b_type,
11146 													   const std::vector<double>& matrix_b_data, double* out_result_ptr)
11147 {
11148 	(void)matrix_b_type;
11149 	using namespace tcu;
11150 	/* To keep the code maintainable, we only consider cases relevant for this test */
11151 	switch (matrix_a_type)
11152 	{
11153 	case Utils::VARIABLE_TYPE_DMAT2:
11154 	{
11155 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11156 
11157 		tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11158 		tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11159 		tcu::Matrix2d result;
11160 
11161 		matrix_a = transpose(matrix_a);
11162 		matrix_b = transpose(matrix_b);
11163 		result   = matrix_a * matrix_b;
11164 
11165 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11166 		break;
11167 	}
11168 
11169 	case Utils::VARIABLE_TYPE_DMAT2X3:
11170 	{
11171 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11172 
11173 		tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11174 		tcu::Matrix<double, 3, 2> matrix_a_transposed;
11175 		tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11176 		tcu::Matrix<double, 2, 3> matrix_b_transposed;
11177 		tcu::Matrix<double, 3, 3> result;
11178 
11179 		matrix_a_transposed = transpose(matrix_a);
11180 		matrix_b_transposed = transpose(matrix_b);
11181 		result				= matrix_a_transposed * matrix_b_transposed;
11182 
11183 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11184 		break;
11185 	}
11186 
11187 	case Utils::VARIABLE_TYPE_DMAT2X4:
11188 	{
11189 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11190 
11191 		tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11192 		tcu::Matrix<double, 4, 2> matrix_a_transposed;
11193 		tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11194 		tcu::Matrix<double, 2, 4> matrix_b_transposed;
11195 		tcu::Matrix<double, 4, 4> result;
11196 
11197 		matrix_a_transposed = transpose(matrix_a);
11198 		matrix_b_transposed = transpose(matrix_b);
11199 		result				= matrix_a_transposed * matrix_b_transposed;
11200 
11201 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11202 		break;
11203 	}
11204 
11205 	case Utils::VARIABLE_TYPE_DMAT3:
11206 	{
11207 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11208 
11209 		tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11210 		tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11211 		tcu::Matrix<double, 3, 3> result;
11212 
11213 		matrix_a = transpose(matrix_a);
11214 		matrix_b = transpose(matrix_b);
11215 		result   = matrix_a * matrix_b;
11216 
11217 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11218 		break;
11219 	}
11220 
11221 	case Utils::VARIABLE_TYPE_DMAT3X2:
11222 	{
11223 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11224 
11225 		tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11226 		tcu::Matrix<double, 2, 3> matrix_a_transposed;
11227 		tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11228 		tcu::Matrix<double, 3, 2> matrix_b_transposed;
11229 		tcu::Matrix<double, 2, 2> result;
11230 
11231 		matrix_a_transposed = transpose(matrix_a);
11232 		matrix_b_transposed = transpose(matrix_b);
11233 		result				= matrix_a_transposed * matrix_b_transposed;
11234 
11235 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11236 		break;
11237 	}
11238 
11239 	case Utils::VARIABLE_TYPE_DMAT3X4:
11240 	{
11241 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11242 
11243 		tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11244 		tcu::Matrix<double, 4, 3> matrix_a_transposed;
11245 		tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11246 		tcu::Matrix<double, 3, 4> matrix_b_transposed;
11247 		tcu::Matrix<double, 4, 4> result;
11248 
11249 		matrix_a_transposed = transpose(matrix_a);
11250 		matrix_b_transposed = transpose(matrix_b);
11251 		result				= matrix_a_transposed * matrix_b_transposed;
11252 
11253 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11254 		break;
11255 	}
11256 
11257 	case Utils::VARIABLE_TYPE_DMAT4:
11258 	{
11259 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11260 
11261 		tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11262 		tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11263 		tcu::Matrix<double, 4, 4> result;
11264 
11265 		matrix_a = transpose(matrix_a);
11266 		matrix_b = transpose(matrix_b);
11267 		result   = matrix_a * matrix_b;
11268 
11269 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11270 		break;
11271 	}
11272 
11273 	case Utils::VARIABLE_TYPE_DMAT4X2:
11274 	{
11275 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11276 
11277 		tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11278 		tcu::Matrix<double, 2, 4> matrix_a_transposed;
11279 		tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11280 		tcu::Matrix<double, 4, 2> matrix_b_transposed;
11281 		tcu::Matrix<double, 2, 2> result;
11282 
11283 		matrix_a_transposed = transpose(matrix_a);
11284 		matrix_b_transposed = transpose(matrix_b);
11285 		result				= matrix_a_transposed * matrix_b_transposed;
11286 
11287 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11288 		break;
11289 	}
11290 
11291 	case Utils::VARIABLE_TYPE_DMAT4X3:
11292 	{
11293 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11294 
11295 		tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11296 		tcu::Matrix<double, 3, 4> matrix_a_transposed;
11297 		tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11298 		tcu::Matrix<double, 4, 3> matrix_b_transposed;
11299 		tcu::Matrix<double, 3, 3> result;
11300 
11301 		matrix_a_transposed = transpose(matrix_a);
11302 		matrix_b_transposed = transpose(matrix_b);
11303 		result				= matrix_a_transposed * matrix_b_transposed;
11304 
11305 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11306 		break;
11307 	}
11308 
11309 	default:
11310 	{
11311 		TCU_FAIL("Unrecognized matrix A type");
11312 	}
11313 	} /* switch (matrix_a_type) */
11314 }
11315 
11316 /** Returns GLSL operator representation of the user-specified operation.
11317  *
11318  *  @param operation_type Internal operation type to retrieve the operator for.
11319  *
11320  *  @return As per description.
11321  **/
getOperatorForOperationType(const _operation_type & operation_type)11322 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11323 {
11324 	const char* result = NULL;
11325 
11326 	switch (operation_type)
11327 	{
11328 	case OPERATION_TYPE_ADDITION:
11329 		result = "+";
11330 		break;
11331 	case OPERATION_TYPE_DIVISION:
11332 		result = "/";
11333 		break;
11334 	case OPERATION_TYPE_MULTIPLICATION:
11335 		result = "*";
11336 		break;
11337 	case OPERATION_TYPE_SUBTRACTION:
11338 		result = "-";
11339 		break;
11340 
11341 	case OPERATION_TYPE_PRE_DECREMENTATION:
11342 	case OPERATION_TYPE_POST_DECREMENTATION:
11343 	{
11344 		result = "--";
11345 
11346 		break;
11347 	}
11348 
11349 	case OPERATION_TYPE_PRE_INCREMENTATION:
11350 	case OPERATION_TYPE_POST_INCREMENTATION:
11351 	{
11352 		result = "++";
11353 
11354 		break;
11355 	}
11356 
11357 	default:
11358 	{
11359 		TCU_FAIL("Unrecognized operation type");
11360 	}
11361 	} /* switch(operation_type) */
11362 
11363 	return result;
11364 }
11365 
11366 /** Returns a string representing user-specified operation type.
11367  *
11368  *  @param operation_type Operation type to return the literal for.
11369  *
11370  *  @return Requested string.
11371  **/
getOperationTypeString(const _operation_type & operation_type)11372 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11373 {
11374 	std::string result = "[?]";
11375 
11376 	switch (operation_type)
11377 	{
11378 	case OPERATION_TYPE_ADDITION:
11379 		result = "addition";
11380 		break;
11381 	case OPERATION_TYPE_DIVISION:
11382 		result = "division";
11383 		break;
11384 	case OPERATION_TYPE_MULTIPLICATION:
11385 		result = "multiplication";
11386 		break;
11387 	case OPERATION_TYPE_SUBTRACTION:
11388 		result = "subtraction";
11389 		break;
11390 	case OPERATION_TYPE_PRE_DECREMENTATION:
11391 		result = "pre-decrementation";
11392 		break;
11393 	case OPERATION_TYPE_PRE_INCREMENTATION:
11394 		result = "pre-incrementation";
11395 		break;
11396 	case OPERATION_TYPE_POST_DECREMENTATION:
11397 		result = "post-decrementation";
11398 		break;
11399 	case OPERATION_TYPE_POST_INCREMENTATION:
11400 		result = "post-incrementation";
11401 		break;
11402 
11403 	default:
11404 	{
11405 		TCU_FAIL("Unrecognized operation type");
11406 	}
11407 	}
11408 
11409 	return result;
11410 }
11411 
11412 /** Returns body of a vertex shader that should be used for user-specified test case
11413  *  descriptor.
11414  *
11415  *  @param test_case Test case descriptor.
11416  *
11417  *  @return Requested GLSL shader body.
11418  **/
getVertexShaderBody(_test_case & test_case)11419 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11420 {
11421 	std::stringstream  result_sstream;
11422 	std::string		   result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11423 	std::string		   variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11424 	std::string		   variable_type_string	= Utils::getVariableTypeString(test_case.variable_type);
11425 	const unsigned int n_variable_components   = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11426 
11427 	/* If we are to multiply matrices, we will need to use a different type
11428 	 * for the result variable if either of the matrices is not square.
11429 	 */
11430 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11431 		Utils::isMatrixVariableType(test_case.variable_type))
11432 	{
11433 		Utils::_variable_type result_variable_type;
11434 		Utils::_variable_type transposed_matrix_variable_type =
11435 			Utils::getTransposedMatrixVariableType(test_case.variable_type);
11436 
11437 		result_variable_type =
11438 			Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11439 		result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11440 
11441 		test_case.result_variable_type = result_variable_type;
11442 	}
11443 
11444 	/* Form the pre-amble */
11445 	result_sstream << "#version 400\n"
11446 					  "\n"
11447 
11448 					  /* Add output variables */
11449 					  "out "
11450 				   << result_variable_type_string << " result;\n"
11451 													 "out ivec2 result_lt;\n"
11452 													 "out ivec2 result_lte;\n"
11453 													 "out ivec2 result_gt;\n"
11454 													 "out ivec2 result_gte;\n"
11455 													 "void main()\n"
11456 													 "{\n";
11457 
11458 	/* Form reference values */
11459 	result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11460 
11461 	for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11462 	{
11463 		result_sstream << (n_variable_component + 1);
11464 
11465 		if (n_variable_component != (n_variable_components - 1))
11466 		{
11467 			result_sstream << ", ";
11468 		}
11469 	} /* for (all variable components) */
11470 
11471 	result_sstream << ");\n";
11472 
11473 	for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11474 		 ++n_ref2_case)
11475 	{
11476 		Utils::_variable_type compatible_variable_type = test_case.variable_type;
11477 
11478 		if (Utils::isMatrixVariableType(compatible_variable_type) &&
11479 			test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11480 		{
11481 			compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11482 		}
11483 
11484 		std::string ref2_variable_type_fp_string =
11485 			Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11486 		std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11487 		std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11488 		std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11489 
11490 		result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11491 
11492 		for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11493 			 ++n_variable_component)
11494 		{
11495 			result_sstream << (n_variable_components - (n_variable_component + 1));
11496 
11497 			if (n_variable_component != (n_variable_components - 1))
11498 			{
11499 				result_sstream << ", ";
11500 			}
11501 		} /* for (all variable components) */
11502 
11503 		result_sstream << ");\n";
11504 	} /* for (both reference2 declarations) */
11505 
11506 	/* Add actual body */
11507 	result_sstream << "\n"
11508 					  "result = ";
11509 
11510 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11511 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11512 	{
11513 		result_sstream << getOperatorForOperationType(test_case.operation_type);
11514 	}
11515 
11516 	result_sstream << "reference1 ";
11517 
11518 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11519 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11520 		test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11521 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11522 	{
11523 		if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11524 			test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11525 		{
11526 			result_sstream << getOperatorForOperationType(test_case.operation_type);
11527 		}
11528 	}
11529 	else
11530 	{
11531 		result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11532 	}
11533 
11534 	result_sstream << ";\n";
11535 
11536 	if (Utils::isScalarVariableType(test_case.variable_type))
11537 	{
11538 		result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
11539 						  "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
11540 						  "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
11541 						  "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11542 						  "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
11543 						  "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
11544 						  "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
11545 						  "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11546 	}
11547 	else
11548 	{
11549 		result_sstream << "result_lt [0] = 1;\n"
11550 						  "result_lt [1] = 1;\n"
11551 						  "result_lte[0] = 1;\n"
11552 						  "result_lte[1] = 1;\n"
11553 						  "result_gt [0] = 1;\n"
11554 						  "result_gt [1] = 1;\n"
11555 						  "result_gte[0] = 1;\n"
11556 						  "result_gte[1] = 1;\n";
11557 	}
11558 
11559 	result_sstream << "}\n";
11560 
11561 	/* All done */
11562 	return result_sstream.str();
11563 }
11564 
11565 /** Initializes all GL objects required to run the test.
11566  *
11567  *  This function can throw a TestError exception if the implementation misbehaves.
11568  */
initTest()11569 void GPUShaderFP64Test9::initTest()
11570 {
11571 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11572 
11573 	/* Create program & vertex shader objects */
11574 	m_po_id = gl.createProgram();
11575 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11576 
11577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11578 
11579 	/* Attach the shader to the program */
11580 	gl.attachShader(m_po_id, m_vs_id);
11581 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11582 
11583 	/* Set up a buffer object */
11584 	gl.genBuffers(1, &m_xfb_bo_id);
11585 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11586 
11587 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11588 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11589 
11590 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11591 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11592 
11593 	/* Set up a vertex array object */
11594 	gl.genVertexArrays(1, &m_vao_id);
11595 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11596 
11597 	gl.bindVertexArray(m_vao_id);
11598 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11599 }
11600 
11601 /** Initializes all GL objects required to run an iteration described by
11602  *  user-specified test case descriptor.
11603  *
11604  *  @param test_case Test case descriptor to use for the initialization.
11605  **/
initTestIteration(_test_case & test_case)11606 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11607 {
11608 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
11609 	std::string			  vs_body		  = getVertexShaderBody(test_case);
11610 	const char*			  vs_body_raw_ptr = vs_body.c_str();
11611 
11612 	/* Store the shader's body */
11613 	test_case.vs_body = vs_body;
11614 
11615 	/* Try to compile the shader */
11616 	glw::GLint compile_status = GL_FALSE;
11617 
11618 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11619 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11620 
11621 	gl.compileShader(m_vs_id);
11622 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11623 
11624 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11625 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11626 
11627 	if (compile_status != GL_TRUE)
11628 	{
11629 		TCU_FAIL("Test shader compilation failed.");
11630 	}
11631 
11632 	/* Configure XFB */
11633 	const char*		   xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11634 	const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11635 
11636 	gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11637 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11638 
11639 	/* Try to link the program */
11640 	glw::GLint link_status = GL_FALSE;
11641 
11642 	gl.linkProgram(m_po_id);
11643 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11644 
11645 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11646 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11647 
11648 	if (link_status != GL_TRUE)
11649 	{
11650 		TCU_FAIL("Test program linking failure");
11651 	}
11652 
11653 	/* Set up XFB BO data storage */
11654 	const unsigned int result_variable_size = static_cast<unsigned int>(
11655 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11656 	const unsigned int xfb_bo_size = static_cast<unsigned int>(
11657 		result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11658 
11659 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11660 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11661 }
11662 
11663 /** Executes test iteration.
11664  *
11665  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11666  */
iterate()11667 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11668 {
11669 	/* Do not execute the test if GL_ARB_texture_view is not supported */
11670 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11671 	{
11672 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11673 	}
11674 
11675 	/* Initialize all ES objects required to run all the checks */
11676 	initTest();
11677 
11678 	/* Iterate through all variable types we want to test */
11679 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
11680 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11681 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11682 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
11683 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11684 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11685 													 Utils::VARIABLE_TYPE_DVEC4 };
11686 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11687 
11688 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11689 	{
11690 		/* Iterate through all operation types we want to check */
11691 		for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11692 		{
11693 			_operation_type				 operation_type = (_operation_type)n_operation_type;
11694 			const Utils::_variable_type& variable_type  = variable_types[n_variable_type];
11695 
11696 			/* Construct test case descriptor */
11697 			_test_case test_case;
11698 
11699 			test_case.operation_type	   = operation_type;
11700 			test_case.result_variable_type = variable_type;
11701 			test_case.variable_type		   = variable_type;
11702 
11703 			/* Run the iteration */
11704 			initTestIteration(test_case);
11705 
11706 			m_has_test_passed &= executeTestIteration(test_case);
11707 		} /* for (all operation types) */
11708 	}	 /* for (all variable types) */
11709 
11710 	/* All done. */
11711 	if (m_has_test_passed)
11712 	{
11713 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11714 	}
11715 	else
11716 	{
11717 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11718 	}
11719 
11720 	return STOP;
11721 }
11722 
11723 /** Verifies data XFBed out by the draw call for user-specified test case
11724  *  descriptor.
11725  *
11726  *  @param test_case Test case descriptor
11727  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
11728  *                   Must not be NULL.
11729  *
11730  *  @return true if the data was found to be correct, false otherwise.
11731  **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11732 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11733 {
11734 	const double	   epsilon = 1e-5;
11735 	const unsigned int n_result_components =
11736 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11737 	bool		  result			  = true;
11738 	const double* xfb_data_result	 = (const double*)xfb_data;
11739 	const int*	xfb_data_result_lt  = (const int*)(xfb_data_result + n_result_components);
11740 	const int*	xfb_data_result_lte = (const int*)xfb_data_result_lt + 2;  /* cast/non-cast cases */
11741 	const int*	xfb_data_result_gt  = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11742 	const int*	xfb_data_result_gte = (const int*)xfb_data_result_gt + 2;  /* cast/non-cast cases */
11743 
11744 	/* Prepare reference values */
11745 	int					modifier;
11746 	std::vector<double> reference1;
11747 	std::vector<double> reference2;
11748 
11749 	if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11750 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11751 	{
11752 		modifier = 1;
11753 	}
11754 	else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11755 			 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11756 	{
11757 		modifier = -1;
11758 	}
11759 	else
11760 	{
11761 		modifier = 0;
11762 	}
11763 
11764 	if (Utils::isMatrixVariableType(test_case.variable_type))
11765 	{
11766 		/* Matrices may be of different sizes so we need to compute the
11767 		 * reference values separately for each matrix
11768 		 */
11769 		const Utils::_variable_type matrix_a_type = test_case.variable_type;
11770 		const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11771 		const unsigned int			n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11772 		const unsigned int			n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11773 
11774 		for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11775 		{
11776 			reference1.push_back(modifier + n_component + 1);
11777 		}
11778 
11779 		for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11780 		{
11781 			reference2.push_back(n_matrix_b_components - (n_component + 1));
11782 		}
11783 	} /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11784 	else
11785 	{
11786 		/* Generate as many components as will be expected for the result variable */
11787 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11788 		{
11789 			reference1.push_back(modifier + n_result_component + 1);
11790 			reference2.push_back(n_result_components - (n_result_component + 1));
11791 		}
11792 	}
11793 
11794 	/* Verify the result value(s) */
11795 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11796 		Utils::isMatrixVariableType(test_case.variable_type))
11797 	{
11798 		/* Matrix multiplication */
11799 		double				  expected_result_data[4 * 4];
11800 		Utils::_variable_type matrix_a_type = test_case.variable_type;
11801 		Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11802 
11803 		getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11804 
11805 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11806 		{
11807 			if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11808 			{
11809 				std::stringstream log_sstream;
11810 
11811 				log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11812 							<< Utils::getVariableTypeString(matrix_b_type)
11813 							<< " matrix multiplication was incorrect; expected:(";
11814 
11815 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11816 					 ++n_logged_component)
11817 				{
11818 					log_sstream << expected_result_data[n_logged_component];
11819 
11820 					if (n_logged_component != (n_result_components - 1))
11821 					{
11822 						log_sstream << ", ";
11823 					}
11824 				} /* for (all components to be logged) */
11825 
11826 				log_sstream << "), retrieved:(";
11827 
11828 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11829 					 ++n_logged_component)
11830 				{
11831 					log_sstream << xfb_data_result[n_logged_component];
11832 
11833 					if (n_logged_component != (n_result_components - 1))
11834 					{
11835 						log_sstream << ", ";
11836 					}
11837 				} /* for (all components to be logged) */
11838 
11839 				log_sstream << ")";
11840 
11841 				m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11842 
11843 				result = false;
11844 				break;
11845 			}
11846 		} /* for (all result components) */
11847 	}	 /* if (dealing with matrix multiplication) */
11848 	else
11849 	{
11850 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11851 		{
11852 			double expected_value = reference1[n_component];
11853 
11854 			switch (test_case.operation_type)
11855 			{
11856 			case OPERATION_TYPE_ADDITION:
11857 				expected_value += reference2[n_component];
11858 				break;
11859 			case OPERATION_TYPE_DIVISION:
11860 				expected_value /= reference2[n_component];
11861 				break;
11862 			case OPERATION_TYPE_MULTIPLICATION:
11863 				expected_value *= reference2[n_component];
11864 				break;
11865 			case OPERATION_TYPE_SUBTRACTION:
11866 				expected_value -= reference2[n_component];
11867 				break;
11868 
11869 			case OPERATION_TYPE_PRE_DECREMENTATION:
11870 			case OPERATION_TYPE_PRE_INCREMENTATION:
11871 			{
11872 				/* Modifier already applied */
11873 				break;
11874 			}
11875 
11876 			case OPERATION_TYPE_POST_DECREMENTATION:
11877 			case OPERATION_TYPE_POST_INCREMENTATION:
11878 			{
11879 				/* Need to reverse the modification for the purpose of the following check */
11880 				expected_value -= modifier;
11881 
11882 				break;
11883 			}
11884 
11885 			default:
11886 			{
11887 				TCU_FAIL("Unrecognized operation type");
11888 			}
11889 			} /* switch (test_case.operation_type) */
11890 
11891 			if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11892 			{
11893 				std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11894 				std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11895 
11896 				m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11897 								   << variable_type_string << "]"
11898 															  " and operation type ["
11899 								   << operation_type_string << "]"
11900 															   " were found invalid."
11901 								   << tcu::TestLog::EndMessage;
11902 
11903 				result = false;
11904 				break;
11905 			} /* if (test case failed) */
11906 		}	 /* for (all components) */
11907 	}
11908 
11909 	/* Verify the comparison operation results */
11910 	if (Utils::isScalarVariableType(test_case.variable_type))
11911 	{
11912 		DE_ASSERT(n_result_components == 1);
11913 
11914 		const bool expected_result_lt[2]  = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11915 		const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11916 		const bool expected_result_gt[2]  = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11917 		const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11918 
11919 		if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11920 			(xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11921 		{
11922 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11923 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11924 
11925 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11926 														   "variable type ["
11927 							   << variable_type_string << "]"
11928 														  "and operation type ["
11929 							   << operation_type_string << "]"
11930 														   "was found invalid; expected:("
11931 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11932 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11933 							   << tcu::TestLog::EndMessage;
11934 
11935 			result = false;
11936 		}
11937 
11938 		if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11939 			(xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11940 		{
11941 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11942 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11943 
11944 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11945 														   "variable type ["
11946 							   << variable_type_string << "]"
11947 														  "and operation type ["
11948 							   << operation_type_string << "]"
11949 														   "was found invalid; expected:("
11950 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11951 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11952 							   << tcu::TestLog::EndMessage;
11953 
11954 			result = false;
11955 		}
11956 
11957 		if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11958 			(xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11959 		{
11960 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11961 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11962 
11963 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11964 														   "variable type ["
11965 							   << variable_type_string << "]"
11966 														  "and operation type ["
11967 							   << operation_type_string << "]"
11968 														   "was found invalid; expected:("
11969 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11970 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11971 							   << tcu::TestLog::EndMessage;
11972 
11973 			result = false;
11974 		}
11975 
11976 		if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11977 			(xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11978 		{
11979 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11980 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11981 
11982 			m_testCtx.getLog() << tcu::TestLog::Message
11983 							   << "Values reported for greater-than-or-equal operator used for "
11984 								  "variable type ["
11985 							   << variable_type_string << "]"
11986 														  "and operation type ["
11987 							   << operation_type_string << "]"
11988 														   "was found invalid; expected:("
11989 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11990 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11991 							   << tcu::TestLog::EndMessage;
11992 
11993 			result = false;
11994 		}
11995 	} /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11996 	else
11997 	{
11998 		if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11999 			xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
12000 			xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
12001 		{
12002 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12003 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12004 
12005 			m_testCtx.getLog() << tcu::TestLog::Message
12006 							   << "Invalid value was reported for matrix variable type, for which "
12007 								  " operator checks are not executed; variable type ["
12008 							   << variable_type_string << "]"
12009 														  "and operation type ["
12010 							   << operation_type_string << "]" << tcu::TestLog::EndMessage;
12011 
12012 			result = false;
12013 		}
12014 	}
12015 
12016 	return result;
12017 }
12018 
12019 namespace TypeHelpers
12020 {
12021 /** Get base type for reference types
12022  *
12023  * @tparam T type
12024  **/
12025 template <typename T>
12026 class referenceToType
12027 {
12028 public:
12029 	typedef T result;
12030 };
12031 
12032 template <typename T>
12033 class referenceToType<const T&>
12034 {
12035 public:
12036 	typedef T result;
12037 };
12038 
12039 /** Maps variable type with enumeration Utils::_variable_type
12040  *
12041  * @tparam T type
12042  **/
12043 template <typename T>
12044 class typeInfo;
12045 
12046 template <>
12047 class typeInfo<glw::GLboolean>
12048 {
12049 public:
12050 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12051 };
12052 
12053 template <>
12054 class typeInfo<glw::GLdouble>
12055 {
12056 public:
12057 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12058 };
12059 
12060 template <>
12061 class typeInfo<tcu::UVec2>
12062 {
12063 public:
12064 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12065 };
12066 
12067 template <>
12068 class typeInfo<tcu::UVec3>
12069 {
12070 public:
12071 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12072 };
12073 
12074 template <>
12075 class typeInfo<tcu::UVec4>
12076 {
12077 public:
12078 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12079 };
12080 
12081 template <>
12082 class typeInfo<tcu::DVec2>
12083 {
12084 public:
12085 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12086 };
12087 
12088 template <>
12089 class typeInfo<tcu::DVec3>
12090 {
12091 public:
12092 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12093 };
12094 
12095 template <>
12096 class typeInfo<tcu::DVec4>
12097 {
12098 public:
12099 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12100 };
12101 
12102 template <>
12103 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12104 {
12105 public:
12106 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12107 };
12108 
12109 template <>
12110 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12111 {
12112 public:
12113 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12114 };
12115 
12116 template <>
12117 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12118 {
12119 public:
12120 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12121 };
12122 
12123 template <>
12124 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12125 {
12126 public:
12127 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12128 };
12129 
12130 template <>
12131 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12132 {
12133 public:
12134 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12135 };
12136 
12137 template <>
12138 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12139 {
12140 public:
12141 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12142 };
12143 
12144 template <>
12145 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12146 {
12147 public:
12148 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12149 };
12150 
12151 template <>
12152 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12153 {
12154 public:
12155 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12156 };
12157 
12158 template <>
12159 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12160 {
12161 public:
12162 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12163 };
12164 } /* TypeHelpers */
12165 
12166 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12167  *
12168  **/
12169 namespace Math
12170 {
12171 template <typename T>
12172 static T clamp(T x, T minVal, T maxVal);
12173 
12174 template <int Size>
12175 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12176 
12177 template <int Size>
12178 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12179 
12180 template <typename T>
12181 static T determinant(T val);
12182 
12183 template <typename T>
12184 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12185 
12186 template <typename T>
12187 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12188 
12189 template <typename T>
12190 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12191 
12192 template <int Size>
12193 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12194 																glw::GLuint column, glw::GLuint row);
12195 
12196 template <int Size>
12197 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12198 											const tcu::Vector<glw::GLdouble, Size>& right);
12199 
12200 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12201 
12202 static glw::GLdouble fract(glw::GLdouble val);
12203 
12204 template <typename T>
12205 static T frexp(T val, glw::GLint& exp);
12206 
12207 template <int Size>
12208 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12209 												  const tcu::Vector<glw::GLdouble, Size>& right);
12210 
12211 template <int Size>
12212 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12213 													   const tcu::Vector<glw::GLdouble, Size>& right);
12214 
12215 template <int Size>
12216 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12217 
12218 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12219 
12220 static glw::GLuint isinf_impl(glw::GLdouble val);
12221 
12222 static glw::GLuint isnan_impl(glw::GLdouble val);
12223 
12224 template <typename T>
12225 static T ldexp(T val, glw::GLint exp);
12226 
12227 template <int Size>
12228 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12229 											   const tcu::Vector<glw::GLdouble, Size>& right);
12230 
12231 template <int Size>
12232 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12233 													const tcu::Vector<glw::GLdouble, Size>& right);
12234 
12235 template <typename T>
12236 static T max(T left, T right);
12237 
12238 template <typename T>
12239 static T min(T left, T right);
12240 
12241 template <int		 Size>
12242 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12243 								glw::GLuint row);
12244 
12245 template <typename T>
12246 static T mix(T left, T right, T weight);
12247 
12248 template <typename T>
12249 static T mod(T left, T right);
12250 
12251 template <typename T>
12252 static T modf(T val, T& integer);
12253 
12254 template <typename T>
12255 static T multiply(T left, T right);
12256 
12257 template <int Size>
12258 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12259 											   const tcu::Vector<glw::GLdouble, Size>& right);
12260 
12261 template <int Cols, int Rows>
12262 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12263 														   const tcu::Vector<glw::GLdouble, Cols>& right);
12264 
12265 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12266 
12267 template <typename T>
12268 static T round(T t);
12269 
12270 template <typename T>
12271 static T roundEven(T t);
12272 
12273 template <typename T>
12274 static T sign(T t);
12275 
12276 template <typename T>
12277 static T smoothStep(T e0, T e1, T val);
12278 
12279 template <typename T>
12280 static T step(T edge, T val);
12281 
12282 template <typename T, int Rows, int Cols>
12283 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12284 
12285 template <typename T>
12286 static T trunc(T t);
12287 
12288 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12289 
12290 template <typename T>
clamp(T x,T minVal,T maxVal)12291 static T clamp(T x, T minVal, T maxVal)
12292 {
12293 	return min(max(x, minVal), maxVal);
12294 }
12295 
12296 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12297 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12298 {
12299 	tcu::Matrix<glw::GLdouble, Size, Size> result;
12300 
12301 	for (glw::GLuint c = 0; c < Size; ++c)
12302 	{
12303 		for (glw::GLuint r = 0; r < Size; ++r)
12304 		{
12305 			const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12306 
12307 			result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12308 		}
12309 	}
12310 
12311 	return result;
12312 }
12313 
12314 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12315 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12316 {
12317 	tcu::Vector<glw::GLuint, Size> result;
12318 
12319 	for (glw::GLint i = 0; i < Size; ++i)
12320 	{
12321 		if (GL_FALSE != src[i])
12322 		{
12323 			result[i] = 1;
12324 		}
12325 		else
12326 		{
12327 			result[i] = 0;
12328 		}
12329 	}
12330 
12331 	return result;
12332 }
12333 
12334 template <typename T>
det2(T _00,T _10,T _01,T _11)12335 static T det2(T _00, T _10, T _01, T _11)
12336 {
12337 	return _00 * _11 - _01 * _10;
12338 }
12339 
12340 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12341 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12342 {
12343 	return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12344 }
12345 
12346 template <typename T>
det4(T _00,T _10,T _20,T _30,T _01,T _11,T _21,T _31,T _02,T _12,T _22,T _32,T _03,T _13,T _23,T _33)12347 static T det4(T _00, T _10, T _20, T _30, T _01, T _11, T _21, T _31, T _02, T _12, T _22, T _32, T _03, T _13, T _23,
12348 			  T _33)
12349 {
12350 	return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12351 		   _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12352 		   _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12353 		   _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12354 }
12355 
12356 template <typename T>
determinant(T val)12357 static T determinant(T val)
12358 {
12359 	return val;
12360 }
12361 
12362 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12363 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12364 {
12365 	return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12366 }
12367 
12368 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12369 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12370 {
12371 	return det3(mat(0, 0), mat(0, 1), mat(0, 2), mat(1, 0), mat(1, 1), mat(1, 2), mat(2, 0), mat(2, 1), mat(2, 2));
12372 }
12373 
12374 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12375 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12376 {
12377 	return det4(mat(0, 0), mat(0, 1), mat(0, 2), mat(0, 3), mat(1, 0), mat(1, 1), mat(1, 2), mat(1, 3), mat(2, 0),
12378 				mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12379 }
12380 
12381 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12382 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12383 																glw::GLuint column, glw::GLuint row)
12384 {
12385 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12386 
12387 	for (glw::GLuint c = 0; c < Size; ++c)
12388 	{
12389 		/* Skip eliminated column */
12390 		if (column == c)
12391 		{
12392 			continue;
12393 		}
12394 
12395 		for (glw::GLuint r = 0; r < Size; ++r)
12396 		{
12397 			/* Skip eliminated row */
12398 			if (row == r)
12399 			{
12400 				continue;
12401 			}
12402 
12403 			const glw::GLint r_offset = (r > row) ? -1 : 0;
12404 			const glw::GLint c_offset = (c > column) ? -1 : 0;
12405 
12406 			result(r + r_offset, c + c_offset) = matrix(r, c);
12407 		}
12408 	}
12409 
12410 	return result;
12411 }
12412 
12413 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12415 											const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 	return convertBvecToUvec(tcu::equal(left, right));
12418 }
12419 
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12420 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12421 {
12422 	return a * b + c;
12423 }
12424 
fract(glw::GLdouble val)12425 static glw::GLdouble fract(glw::GLdouble val)
12426 {
12427 	return val - floor(val);
12428 }
12429 
12430 template <typename T>
frexp(T val,glw::GLint & exp)12431 static T frexp(T val, glw::GLint& exp)
12432 {
12433 	return ::frexp(val, &exp);
12434 }
12435 
12436 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12437 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12438 												  const tcu::Vector<glw::GLdouble, Size>& right)
12439 {
12440 	return convertBvecToUvec(tcu::greaterThan(left, right));
12441 }
12442 
12443 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12444 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12445 													   const tcu::Vector<glw::GLdouble, Size>& right)
12446 {
12447 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12448 }
12449 
12450 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12451 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12452 {
12453 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
12454 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12455 	const glw::GLdouble det		= determinant(matrix);
12456 	const glw::GLdouble inv_det = 1.0 / det;
12457 
12458 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12459 
12460 	return result;
12461 }
12462 
inverseSqrt(glw::GLdouble val)12463 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12464 {
12465 	const glw::GLdouble root = sqrt(val);
12466 
12467 	return (1.0 / root);
12468 }
12469 
isinf_impl(glw::GLdouble val)12470 static glw::GLuint isinf_impl(glw::GLdouble val)
12471 {
12472 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12473 
12474 	return ((infinity == val) || (-infinity == val));
12475 }
12476 
isnan_impl(glw::GLdouble val)12477 static glw::GLuint isnan_impl(glw::GLdouble val)
12478 {
12479 	return val != val;
12480 }
12481 
12482 template <typename T>
ldexp(T val,glw::GLint exp)12483 static T ldexp(T val, glw::GLint exp)
12484 {
12485 	return ::ldexp(val, exp);
12486 }
12487 
12488 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12489 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12490 											   const tcu::Vector<glw::GLdouble, Size>& right)
12491 {
12492 	return convertBvecToUvec(tcu::lessThan(left, right));
12493 }
12494 
12495 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12496 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12497 													const tcu::Vector<glw::GLdouble, Size>& right)
12498 {
12499 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
12500 }
12501 
12502 template <typename T>
max(T left,T right)12503 static T max(T left, T right)
12504 {
12505 	return (left >= right) ? left : right;
12506 }
12507 
12508 template <typename T>
min(T left,T right)12509 static T min(T left, T right)
12510 {
12511 	return (left <= right) ? left : right;
12512 }
12513 
12514 template <int		 Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12515 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12516 								glw::GLuint row)
12517 {
12518 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12519 
12520 	return determinant(eliminated);
12521 }
12522 
12523 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12524 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12525 {
12526 	const glw::GLuint r = (0 == row) ? 1 : 0;
12527 	const glw::GLuint c = (0 == column) ? 1 : 0;
12528 
12529 	return matrix(r, c);
12530 }
12531 
12532 template <typename T>
mix(T left,T right,T weight)12533 static T mix(T left, T right, T weight)
12534 {
12535 	return left * (1 - weight) + right * (weight);
12536 }
12537 
12538 template <typename T>
mod(T left,T right)12539 static T mod(T left, T right)
12540 {
12541 	const T div_res = left / right;
12542 	const T floored = floor(div_res);
12543 
12544 	return left - right * floored;
12545 }
12546 
12547 template <typename T>
modf(T val,T & integer)12548 static T modf(T val, T& integer)
12549 {
12550 	return ::modf(val, &integer);
12551 }
12552 
12553 template <typename T>
multiply(T left,T right)12554 static T multiply(T left, T right)
12555 {
12556 	T result = left * right;
12557 
12558 	return result;
12559 }
12560 
12561 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12562 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12563 											   const tcu::Vector<glw::GLdouble, Size>& right)
12564 {
12565 	return convertBvecToUvec(tcu::notEqual(left, right));
12566 }
12567 
12568 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12569 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12570 														   const tcu::Vector<glw::GLdouble, Cols>& right)
12571 {
12572 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
12573 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
12574 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12575 
12576 	for (glw::GLuint i = 0; i < Rows; ++i)
12577 	{
12578 		left_mat(i, 0) = left[i];
12579 	}
12580 
12581 	for (glw::GLuint i = 0; i < Cols; ++i)
12582 	{
12583 		right_mat(0, i) = right[i];
12584 	}
12585 
12586 	result = left_mat * right_mat;
12587 
12588 	return result;
12589 }
12590 
packDouble2x32(const tcu::UVec2 & in)12591 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12592 {
12593 	const glw::GLuint buffer[2] = { in[0], in[1] };
12594 	glw::GLdouble	 result;
12595 	memcpy(&result, buffer, sizeof(result));
12596 	return result;
12597 }
12598 
12599 template <typename T>
round(T t)12600 static T round(T t)
12601 {
12602 	T frac = fract(t);
12603 	T res  = t - frac;
12604 
12605 	if (((T)0.5) < frac)
12606 	{
12607 		res += ((T)1.0);
12608 	}
12609 
12610 	return res;
12611 }
12612 
12613 template <typename T>
roundEven(T t)12614 static T roundEven(T t)
12615 {
12616 	T frac = fract(t);
12617 	T res  = t - frac;
12618 
12619 	if (((T)0.5) < frac)
12620 	{
12621 		res += ((T)1.0);
12622 	}
12623 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12624 	{
12625 		res += ((T)1.0);
12626 	}
12627 
12628 	return res;
12629 }
12630 
12631 template <typename T>
sign(T t)12632 static T sign(T t)
12633 {
12634 	if (0 > t)
12635 	{
12636 		return -1;
12637 	}
12638 	else if (0 == t)
12639 	{
12640 		return 0;
12641 	}
12642 	else
12643 	{
12644 		return 1;
12645 	}
12646 }
12647 
12648 template <typename T>
smoothStep(T e0,T e1,T val)12649 static T smoothStep(T e0, T e1, T val)
12650 {
12651 	if (e0 >= val)
12652 	{
12653 		return 0;
12654 	}
12655 
12656 	if (e1 <= val)
12657 	{
12658 		return 1;
12659 	}
12660 
12661 	T temp = (val - e0) / (e1 - e0);
12662 
12663 	T result = temp * temp * (3 - 2 * temp);
12664 
12665 	return result;
12666 }
12667 
12668 template <typename T>
step(T edge,T val)12669 static T step(T edge, T val)
12670 {
12671 	if (edge > val)
12672 	{
12673 		return 0;
12674 	}
12675 	else
12676 	{
12677 		return 1;
12678 	}
12679 }
12680 
12681 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12682 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12683 {
12684 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12685 
12686 	return result;
12687 }
12688 
12689 template <typename T>
trunc(T t)12690 static T trunc(T t)
12691 {
12692 	const T abs_value	= de::abs(t);
12693 	const T result_value = floor(abs_value);
12694 
12695 	const T result = sign(t) * result_value;
12696 
12697 	return result;
12698 }
12699 
unpackDouble2x32(const glw::GLdouble & val)12700 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12701 {
12702 	glw::GLuint* ptr = (glw::GLuint*)&val;
12703 	tcu::UVec2   result(ptr[0], ptr[1]);
12704 
12705 	return result;
12706 }
12707 } /* Math */
12708 
12709 /** Enumeration of tested functions
12710  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12711  * For example "max" can be called for (dvec3, double).
12712  **/
12713 enum FunctionEnum
12714 {
12715 	FUNCTION_ABS = 0,
12716 	FUNCTION_CEIL,
12717 	FUNCTION_CLAMP,
12718 	FUNCTION_CLAMP_AGAINST_SCALAR,
12719 	FUNCTION_CROSS,
12720 	FUNCTION_DETERMINANT,
12721 	FUNCTION_DISTANCE,
12722 	FUNCTION_DOT,
12723 	FUNCTION_EQUAL,
12724 	FUNCTION_FACEFORWARD,
12725 	FUNCTION_FLOOR,
12726 	FUNCTION_FMA,
12727 	FUNCTION_FRACT,
12728 	FUNCTION_FREXP,
12729 	FUNCTION_GREATERTHAN,
12730 	FUNCTION_GREATERTHANEQUAL,
12731 	FUNCTION_INVERSE,
12732 	FUNCTION_INVERSESQRT,
12733 	FUNCTION_LDEXP,
12734 	FUNCTION_LESSTHAN,
12735 	FUNCTION_LESSTHANEQUAL,
12736 	FUNCTION_LENGTH,
12737 	FUNCTION_MATRIXCOMPMULT,
12738 	FUNCTION_MAX,
12739 	FUNCTION_MAX_AGAINST_SCALAR,
12740 	FUNCTION_MIN,
12741 	FUNCTION_MIN_AGAINST_SCALAR,
12742 	FUNCTION_MIX,
12743 	FUNCTION_MOD,
12744 	FUNCTION_MOD_AGAINST_SCALAR,
12745 	FUNCTION_MODF,
12746 	FUNCTION_NORMALIZE,
12747 	FUNCTION_NOTEQUAL,
12748 	FUNCTION_OUTERPRODUCT,
12749 	FUNCTION_PACKDOUBLE2X32,
12750 	FUNCTION_REFLECT,
12751 	FUNCTION_REFRACT,
12752 	FUNCTION_ROUND,
12753 	FUNCTION_ROUNDEVEN,
12754 	FUNCTION_SIGN,
12755 	FUNCTION_SMOOTHSTEP,
12756 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12757 	FUNCTION_SQRT,
12758 	FUNCTION_STEP,
12759 	FUNCTION_STEP_AGAINST_SCALAR,
12760 	FUNCTION_TRANSPOSE,
12761 	FUNCTION_TRUNC,
12762 	FUNCTION_UNPACKDOUBLE2X32,
12763 	FUNCTION_ISNAN,
12764 	FUNCTION_ISINF,
12765 };
12766 
12767 struct TypeDefinition
12768 {
12769 	std::string name;
12770 	glw::GLuint n_columns;
12771 	glw::GLuint n_rows;
12772 };
12773 
12774 /** Implementation of BuiltinFunctionTest test, description follows:
12775  *
12776  *  Verify double-precision support in common functions works correctly.
12777  *  All double-precision types that apply for particular cases should
12778  *  be tested for the following functions:
12779  *
12780  *  - abs();
12781  *  - ceil();
12782  *  - clamp();
12783  *  - cross();
12784  *  - determinant();
12785  *  - distance();
12786  *  - dot();
12787  *  - equal();
12788  *  - faceforward();
12789  *  - floor();
12790  *  - fma();
12791  *  - fract();
12792  *  - frexp();
12793  *  - greaterThan();
12794  *  - greaterThanEqual();
12795  *  - inverse();
12796  *  - inversesqrt();
12797  *  - ldexp();
12798  *  - lessThan();
12799  *  - lessThanEqual();
12800  *  - length();
12801  *  - matrixCompMult();
12802  *  - max();
12803  *  - min();
12804  *  - mix();
12805  *  - mod();
12806  *  - modf();
12807  *  - normalize();
12808  *  - notEqual();
12809  *  - outerProduct();
12810  *  - packDouble2x32();
12811  *  - reflect();
12812  *  - refract();
12813  *  - round();
12814  *  - roundEven();
12815  *  - sign();
12816  *  - smoothstep();
12817  *  - sqrt();
12818  *  - step();
12819  *  - transpose();
12820  *  - trunc();
12821  *  - unpackDouble2x32();
12822  *  - isnan();
12823  *  - isinf();
12824  *
12825  *  The test should work by creating a program object (for each case
12826  *  considered), to which a vertex shader should be attached. The
12827  *  shader should define input variables that should be used as
12828  *  arguments for the function in question. The result of the
12829  *  operation should then be XFBed back to the test, where the
12830  *  value should be verified.
12831  *
12832  *  Reference function implementation from pre-DEQP CTS framework
12833  *  should be ported to C for verification purposes where available.
12834  *
12835  *  The test should use 1024 different scalar/vector/matrix argument
12836  *  combinations. It should pass if all functions are determined
12837  *  to work correctly for all argument combinations used.
12838  **/
12839 class BuiltinFunctionTest : public deqp::TestCase
12840 {
12841 public:
12842 	/* Public methods */
12843 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12844 						TypeDefinition typeDefinition);
12845 
12846 	virtual void						 deinit();
12847 	virtual tcu::TestNode::IterateResult iterate();
12848 
12849 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12850 	 *
12851 	 **/
12852 	class functionObject
12853 	{
12854 	public:
12855 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12856 					   Utils::_variable_type result_type);
12857 
~functionObject()12858 		virtual ~functionObject()
12859 		{
12860 		}
12861 
12862 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12863 
12864 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
12865 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12866 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12867 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12868 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12869 		glw::GLuint getArgumentStride() const;
12870 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
12871 		FunctionEnum	   getFunctionEnum() const;
12872 		const glw::GLchar* getName() const;
12873 		glw::GLuint getResultComponents(glw::GLuint result) const;
12874 		virtual glw::GLuint getResultCount() const;
12875 		glw::GLuint getResultOffset(glw::GLuint result) const;
12876 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12877 		glw::GLuint getResultStride(glw::GLuint result) const;
12878 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12879 		glw::GLuint getResultStride() const;
12880 
12881 	protected:
12882 		const FunctionEnum			m_function_enum;
12883 		const glw::GLchar*			m_function_name;
12884 		const glw::GLvoid*			m_p_function;
12885 		const Utils::_variable_type m_res_type;
12886 	};
12887 
12888 private:
12889 	/* Private types */
12890 	/** General type enumeration
12891 	 *
12892 	 **/
12893 	enum generalType
12894 	{
12895 		SCALAR = 0,
12896 		VECTOR,
12897 		MATRIX,
12898 	};
12899 
12900 	/** Details of variable type
12901 	 *
12902 	 **/
12903 	struct typeDetails
12904 	{
12905 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12906 
12907 		generalType m_general_type;
12908 		glw::GLuint m_n_columns;
12909 		glw::GLuint m_n_rows;
12910 		glw::GLenum m_type;
12911 		std::string m_type_name;
12912 	};
12913 
12914 	/* Typedefs for gl.uniform* function pointers */
12915 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12916 																	   const glw::GLdouble*);
12917 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12918 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12919 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12920 
12921 	/* Private methods */
12922 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12923 
12924 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12925 
12926 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
12927 														 const functionObject& function_object) const;
12928 
12929 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
12930 														 const functionObject& function_object) const;
12931 
12932 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
12933 														 const functionObject& function_object) const;
12934 
12935 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
12936 														 const functionObject& function_object) const;
12937 
12938 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
12939 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12940 
12941 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12942 
12943 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12944 
12945 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12946 
12947 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12948 						   glw::GLubyte* buffer);
12949 
12950 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12951 
12952 	void prepareTestData(const functionObject& function_object);
12953 	void prepareVertexShaderCode(const functionObject& function_object);
12954 
12955 	bool test(FunctionEnum function, const typeDetails& type);
12956 
12957 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12958 
12959 	void testInit();
12960 
12961 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12962 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12963 						  const glw::GLvoid* result_src);
12964 
12965 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12966 
12967 	/* Private constants */
12968 	static const glw::GLdouble m_epsilon;
12969 	static const glw::GLuint   m_n_veritces;
12970 
12971 	/* Private fields */
12972 	glw::GLuint m_transform_feedback_buffer_id;
12973 	glw::GLuint m_vertex_array_object_id;
12974 
12975 	std::vector<glw::GLubyte> m_expected_results_data;
12976 	FunctionEnum			  m_function;
12977 	TypeDefinition			  m_typeDefinition;
12978 	std::vector<glw::GLubyte> m_argument_data;
12979 	std::string				  m_vertex_shader_code;
12980 };
12981 
12982 /* Constants used by BuiltinFunctionTest */
12983 /** Khronos Bug #14010
12984  *  Using an epsilon value for comparing floating points is error prone.
12985  *  Rather than writing a new floating point comparison function, I am
12986  *  increasing the epsilon value to allow greater orders of magnitude
12987  *  of floating point values.
12988  **/
12989 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
12990 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12991 
12992 /** Implementations of function objects required by "BuiltinFunctionTest"
12993  *
12994  **/
12995 namespace FunctionObject
12996 {
12997 /** Maps variable type with enumeration Utils::_variable_type
12998  *
12999  * @tparam T type
13000  **/
13001 template <typename T>
13002 class typeInfo
13003 {
13004 public:
13005 	static const Utils::_variable_type variable_type =
13006 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
13007 };
13008 
13009 /** Place data from <in> into <buffer>
13010  *
13011  * @param buffer Buffer
13012  * @param in     Input data
13013  **/
13014 template <typename T>
13015 class pack
13016 {
13017 public:
set(glw::GLvoid * buffer,const T & in)13018 	static void set(glw::GLvoid* buffer, const T& in)
13019 	{
13020 		*(T*)buffer = in;
13021 	}
13022 };
13023 
13024 /** Place tcu::Matrix data from <in> into <buffer>
13025  *
13026  * @param buffer Buffer
13027  * @param in     Input data
13028  **/
13029 template <int Cols, int Rows>
13030 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13031 {
13032 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13033 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13034 	{
13035 		glw::GLdouble* data = (glw::GLdouble*)buffer;
13036 
13037 		for (glw::GLint column = 0; column < Cols; ++column)
13038 		{
13039 			for (glw::GLint row = 0; row < Rows; ++row)
13040 			{
13041 				glw::GLint index = column * Rows + row;
13042 
13043 				data[index] = in(row, column);
13044 			}
13045 		}
13046 	}
13047 };
13048 
13049 /** Get data of <out> from <buffer>
13050  *
13051  * @param buffer Buffer
13052  * @param out    Output data
13053  **/
13054 template <typename T>
13055 class unpack
13056 {
13057 public:
get(const glw::GLvoid * buffer,T & out)13058 	static void get(const glw::GLvoid* buffer, T& out)
13059 	{
13060 		out = *(T*)buffer;
13061 	}
13062 };
13063 
13064 /** Get tcu::Matrix data from <buffer>
13065  *
13066  * @param buffer Buffer
13067  * @param out    Output data
13068  **/
13069 template <int Cols, int Rows>
13070 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13071 {
13072 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13073 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13074 	{
13075 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
13076 
13077 		for (glw::GLint column = 0; column < Cols; ++column)
13078 		{
13079 			for (glw::GLint row = 0; row < Rows; ++row)
13080 			{
13081 				glw::GLint index = column * Rows + row;
13082 
13083 				out(row, column) = data[index];
13084 			}
13085 		}
13086 	}
13087 };
13088 
13089 /** Base of unary function classes
13090  *
13091  **/
13092 class unaryBase : public BuiltinFunctionTest::functionObject
13093 {
13094 public:
unaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13095 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13096 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13097 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13098 	{
13099 	}
13100 
getArgumentCount() const13101 	virtual glw::GLuint getArgumentCount() const
13102 	{
13103 		return 1;
13104 	}
13105 
getArgumentType(glw::GLuint) const13106 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13107 	{
13108 		return m_arg_type;
13109 	}
13110 
13111 protected:
13112 	const Utils::_variable_type m_arg_type;
13113 };
13114 
13115 /** Unary function class. It treats input argument as one variable.
13116  *
13117  * @tparam ResT Type of result
13118  * @tparam ArgT Type of argument
13119  **/
13120 template <typename ResT, typename ArgT>
13121 class unary : public unaryBase
13122 {
13123 public:
13124 	typedef ResT (*functionPointer)(const ArgT&);
13125 
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13126 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13127 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13128 					typeInfo<ArgT>::variable_type)
13129 	{
13130 	}
13131 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13132 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13133 	{
13134 		ResT result;
13135 		ArgT arg;
13136 
13137 		unpack<ArgT>::get(argument_src, arg);
13138 
13139 		functionPointer p_function = (functionPointer)m_p_function;
13140 
13141 		result = p_function(arg);
13142 
13143 		pack<ResT>::set(result_dst, result);
13144 	}
13145 };
13146 
13147 /** Unary function class. It treats input argument as separate components.
13148  *
13149  * @tparam ResT Type of result
13150  **/
13151 template <typename ResT>
13152 class unaryByComponent : public unaryBase
13153 {
13154 public:
13155 	typedef ResT (*functionPointer)(glw::GLdouble);
13156 
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13157 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13158 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13159 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13160 	{
13161 	}
13162 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13163 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13164 	{
13165 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13166 		ResT*		   p_result		= (ResT*)result_dst;
13167 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
13168 
13169 		functionPointer p_function = (functionPointer)m_p_function;
13170 
13171 		for (glw::GLuint component = 0; component < n_components; ++component)
13172 		{
13173 			p_result[component] = p_function(p_arg[component]);
13174 		}
13175 	}
13176 };
13177 
13178 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13179  *
13180  * @tparam ResT Type of result
13181  * @tparam ArgT Type of argument
13182  * @tparam OutT Type of output parameter
13183  **/
13184 template <typename ResT, typename ArgT, typename OutT>
13185 class unaryWithOutputByComponent : public unaryBase
13186 {
13187 public:
13188 	typedef ResT (*functionPointer)(ArgT, OutT&);
13189 
unaryWithOutputByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type,const Utils::_variable_type out_type)13190 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13191 							   functionPointer function_pointer, const Utils::_variable_type res_type,
13192 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13193 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13194 		, m_out_type(out_type)
13195 	{
13196 	}
13197 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13198 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13199 	{
13200 		ResT* p_result = (ResT*)result_dst;
13201 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13202 		ArgT* p_arg	= (ArgT*)argument_src;
13203 
13204 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13205 		const glw::GLuint n_components_1 = getResultComponents(1);
13206 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13207 
13208 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13209 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13210 
13211 		functionPointer p_function = (functionPointer)m_p_function;
13212 
13213 		for (glw::GLuint component = 0; component < n_components; ++component)
13214 		{
13215 			const ArgT first_arg  = p_arg[component * component_step_0];
13216 			OutT&	  second_arg = p_out[component * component_step_1];
13217 
13218 			p_result[component] = p_function(first_arg, second_arg);
13219 		}
13220 	}
13221 
getResultCount() const13222 	glw::GLuint getResultCount() const
13223 	{
13224 		return 2;
13225 	}
13226 
getResultType(glw::GLuint result) const13227 	Utils::_variable_type getResultType(glw::GLuint result) const
13228 	{
13229 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13230 
13231 		switch (result)
13232 		{
13233 		case 0:
13234 			type = m_res_type;
13235 			break;
13236 		case 1:
13237 			type = m_out_type;
13238 			break;
13239 		default:
13240 			TCU_FAIL("Not implemented");
13241 			break;
13242 		}
13243 
13244 		return type;
13245 	}
13246 
13247 protected:
13248 	const Utils::_variable_type m_out_type;
13249 };
13250 
13251 /** Base of binary function classes.
13252  *
13253  **/
13254 class binaryBase : public BuiltinFunctionTest::functionObject
13255 {
13256 public:
binaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type)13257 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13258 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13259 			   const Utils::_variable_type arg_2_type)
13260 		: functionObject(function_enum, function_name, function_pointer, res_type)
13261 		, m_arg_1_type(arg_1_type)
13262 		, m_arg_2_type(arg_2_type)
13263 	{
13264 	}
13265 
getArgumentCount() const13266 	virtual glw::GLuint getArgumentCount() const
13267 	{
13268 		return 2;
13269 	}
13270 
getArgumentType(glw::GLuint argument) const13271 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13272 	{
13273 		switch (argument)
13274 		{
13275 		case 0:
13276 			return m_arg_1_type;
13277 			break;
13278 		case 1:
13279 			return m_arg_2_type;
13280 			break;
13281 		default:
13282 			return Utils::VARIABLE_TYPE_UNKNOWN;
13283 			break;
13284 		}
13285 	}
13286 
13287 protected:
13288 	const Utils::_variable_type m_arg_1_type;
13289 	const Utils::_variable_type m_arg_2_type;
13290 };
13291 
13292 /** Binary function class. It treats input arguments as two variables.
13293  *
13294  * @param ResT  Type of result
13295  * @param Arg1T Type of first argument
13296  * @param Arg2T Type of second argument
13297  **/
13298 template <typename ResT, typename Arg1T, typename Arg2T>
13299 class binary : public binaryBase
13300 {
13301 public:
13302 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13303 
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13304 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13305 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13306 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13307 	{
13308 	}
13309 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13310 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13311 	{
13312 		const glw::GLuint argument_1_stride = getArgumentStride(0);
13313 
13314 		functionPointer p_function = (functionPointer)m_p_function;
13315 
13316 		Arg1T arg_1;
13317 		Arg2T arg_2;
13318 		ResT  result;
13319 
13320 		unpack<Arg1T>::get(argument_src, arg_1);
13321 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13322 
13323 		result = p_function(arg_1, arg_2);
13324 
13325 		pack<ResT>::set(result_dst, result);
13326 	}
13327 };
13328 
13329 /** Binary function class. It treats input arguments as separate components.
13330  *
13331  * @param ResT  Type of result
13332  * @param Arg1T Type of first argument
13333  * @param Arg2T Type of second argument
13334  **/
13335 template <typename ResT, typename Arg1T, typename Arg2T>
13336 class binaryByComponent : public binaryBase
13337 {
13338 public:
13339 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
13340 
binaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type)13341 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13342 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13343 					  const Utils::_variable_type arg_2_type)
13344 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13345 	{
13346 	}
13347 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13348 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13349 	{
13350 		ResT*  p_result = (ResT*)result_dst;
13351 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
13352 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13353 
13354 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13355 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13356 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13357 
13358 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13359 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13360 
13361 		functionPointer p_function = (functionPointer)m_p_function;
13362 
13363 		for (glw::GLuint component = 0; component < n_components; ++component)
13364 		{
13365 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
13366 			const Arg2T second_arg = p_arg_2[component * component_step_1];
13367 
13368 			p_result[component] = p_function(first_arg, second_arg);
13369 		}
13370 	}
13371 };
13372 
13373 /** Base of tenary function classes.
13374  *
13375  **/
13376 class tenaryBase : public BuiltinFunctionTest::functionObject
13377 {
13378 public:
tenaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type,const Utils::_variable_type arg_3_type)13379 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13380 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13381 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13382 		: functionObject(function_enum, function_name, function_pointer, res_type)
13383 		, m_arg_1_type(arg_1_type)
13384 		, m_arg_2_type(arg_2_type)
13385 		, m_arg_3_type(arg_3_type)
13386 	{
13387 	}
13388 
getArgumentCount() const13389 	virtual glw::GLuint getArgumentCount() const
13390 	{
13391 		return 3;
13392 	}
13393 
getArgumentType(glw::GLuint argument) const13394 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13395 	{
13396 		switch (argument)
13397 		{
13398 		case 0:
13399 			return m_arg_1_type;
13400 			break;
13401 		case 1:
13402 			return m_arg_2_type;
13403 			break;
13404 		case 2:
13405 			return m_arg_3_type;
13406 			break;
13407 		default:
13408 			return Utils::VARIABLE_TYPE_UNKNOWN;
13409 			break;
13410 		}
13411 	}
13412 
13413 protected:
13414 	const Utils::_variable_type m_arg_1_type;
13415 	const Utils::_variable_type m_arg_2_type;
13416 	const Utils::_variable_type m_arg_3_type;
13417 };
13418 
13419 /** Tenary function class. It treats input arguments as three variables.
13420  *
13421  * @param ResT  Type of result
13422  * @param Arg1T Type of first argument
13423  * @param Arg2T Type of second argument
13424  * @param Arg3T Type of third argument
13425  **/
13426 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13427 class tenary : public tenaryBase
13428 {
13429 public:
13430 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13431 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13432 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13433 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13434 
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13435 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13436 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13437 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13438 	{
13439 	}
13440 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13441 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13442 	{
13443 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
13444 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
13445 
13446 		functionPointer p_function = (functionPointer)m_p_function;
13447 
13448 		arg1T arg_1;
13449 		arg2T arg_2;
13450 		arg3T arg_3;
13451 		ResT  result;
13452 
13453 		unpack<arg1T>::get(argument_src, arg_1);
13454 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13455 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13456 
13457 		result = p_function(arg_1, arg_2, arg_3);
13458 
13459 		pack<ResT>::set(result_dst, result);
13460 	}
13461 };
13462 
13463 /** Tenary function class. It treats input arguments as separate components.
13464  *
13465 
13466  **/
13467 class tenaryByComponent : public tenaryBase
13468 {
13469 public:
13470 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13471 
tenaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type,const Utils::_variable_type arg_3_type)13472 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13473 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13474 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13475 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13476 					 arg_3_type)
13477 	{
13478 	}
13479 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13480 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13481 	{
13482 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
13483 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
13484 
13485 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13486 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13487 		const glw::GLuint n_components_2 = getArgumentComponents(2);
13488 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13489 
13490 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13491 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13492 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13493 
13494 		functionPointer p_function = (functionPointer)m_p_function;
13495 
13496 		for (glw::GLuint component = 0; component < n_components; ++component)
13497 		{
13498 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13499 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13500 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13501 
13502 			p_result[component] = p_function(first_arg, second_arg, third_arg);
13503 		}
13504 	}
13505 };
13506 } /* FunctionObject */
13507 
13508 /** Constructor.
13509  *
13510  *  @param context Rendering context.
13511  **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13512 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13513 										 TypeDefinition typeDefinition)
13514 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13515 	, m_transform_feedback_buffer_id(0)
13516 	, m_vertex_array_object_id(0)
13517 	, m_function(function)
13518 	, m_typeDefinition(typeDefinition)
13519 {
13520 	/* Nothing to be done here */
13521 }
13522 
13523 /** Deinitializes all GL objects that may have been created during test execution.
13524  *
13525  **/
deinit()13526 void BuiltinFunctionTest::deinit()
13527 {
13528 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13529 
13530 	/* Clean buffers */
13531 	if (0 != m_transform_feedback_buffer_id)
13532 	{
13533 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13534 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13535 		m_transform_feedback_buffer_id = 0;
13536 	}
13537 
13538 	/* Clean VAO */
13539 	if (0 != m_vertex_array_object_id)
13540 	{
13541 		gl.bindVertexArray(0);
13542 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13543 		m_vertex_array_object_id = 0;
13544 	}
13545 }
13546 
13547 /** Execute test
13548  *
13549  * @return tcu::TestNode::STOP
13550  **/
iterate()13551 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13552 {
13553 	/* Check if extension is supported */
13554 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13555 	{
13556 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13557 	}
13558 
13559 	testInit();
13560 
13561 	/* Verify result */
13562 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13563 	if (test(m_function, type))
13564 	{
13565 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13566 	}
13567 	else
13568 	{
13569 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13570 	}
13571 
13572 	/* Done */
13573 	return tcu::TestNode::STOP;
13574 }
13575 
13576 /** Constructor
13577  *
13578  * @param function_enum    Function enumeration
13579  * @param function_name    Function name
13580  * @param function_pointer Pointer to routine that wiil be executed
13581  * @param result_type      Type of result
13582  **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13583 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13584 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13585 	: m_function_enum(function_enum)
13586 	, m_function_name(function_name)
13587 	, m_p_function(function_pointer)
13588 	, m_res_type(result_type)
13589 {
13590 	/* Nothing to be done here */
13591 }
13592 
13593 /** Get number of components for <argument>
13594  *
13595  * @param argument Argument ordinal, starts with 0
13596  *
13597  * @return Number of components
13598  **/
getArgumentComponents(glw::GLuint argument) const13599 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13600 {
13601 	const Utils::_variable_type type		  = getArgumentType(argument);
13602 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13603 
13604 	return n_components;
13605 }
13606 
13607 /** Get size in bytes of single component of <argument>
13608  *
13609  * @param argument Argument ordinal, starts with 0
13610  *
13611  * @return Size of component
13612  **/
getArgumentComponentSize(glw::GLuint argument) const13613 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13614 {
13615 	const Utils::_variable_type type		   = getArgumentType(argument);
13616 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13617 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13618 
13619 	return base_type_size;
13620 }
13621 
13622 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13623  *
13624  * @param argument Argument ordinal, starts with 0
13625  *
13626  * @return Offset of arguemnt's data
13627  **/
getArgumentOffset(glw::GLuint argument) const13628 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13629 {
13630 	glw::GLuint result = 0;
13631 
13632 	for (glw::GLuint i = 0; i < argument; ++i)
13633 	{
13634 		result += getArgumentStride(i);
13635 	}
13636 
13637 	return result;
13638 }
13639 
13640 /** Get stride in bytes of all arguments
13641  *
13642  * @return Stride of all arguments
13643  **/
getArgumentStride() const13644 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13645 {
13646 	const glw::GLuint n_args = getArgumentCount();
13647 	glw::GLuint		  result = 0;
13648 
13649 	for (glw::GLuint i = 0; i < n_args; ++i)
13650 	{
13651 		result += getArgumentStride(i);
13652 	}
13653 
13654 	return result;
13655 }
13656 
13657 /** Get stride in bytes of <argument>
13658  *
13659  * @param argument Argument ordinal, starts with 0
13660  *
13661  * @return Stride of argument
13662  **/
getArgumentStride(glw::GLuint argument) const13663 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13664 {
13665 	const glw::GLuint component_size = getArgumentComponentSize(argument);
13666 	const glw::GLuint n_components   = getArgumentComponents(argument);
13667 
13668 	return n_components * component_size;
13669 }
13670 
13671 /** Get function enumeration
13672  *
13673  * @return Function enumeration
13674  **/
getFunctionEnum() const13675 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13676 {
13677 	return m_function_enum;
13678 }
13679 
13680 /** Get function name
13681  *
13682  * @return Function name
13683  **/
getName() const13684 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13685 {
13686 	return m_function_name;
13687 }
13688 
13689 /** Get number of components for <result>
13690  *
13691  * @param result Result ordinal, starts with 0
13692  *
13693  * @return Number of components
13694  **/
getResultComponents(glw::GLuint result) const13695 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13696 {
13697 	const Utils::_variable_type type		  = getResultType(result);
13698 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13699 
13700 	return n_components;
13701 }
13702 
13703 /** Get number of results
13704  *
13705  * @return Number of results
13706  **/
getResultCount() const13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13708 {
13709 	return 1;
13710 }
13711 
13712 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13713  *
13714  * @param result Result ordinal, starts with 0
13715  *
13716  * @return Offset
13717  **/
getResultOffset(glw::GLuint result) const13718 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13719 {
13720 	glw::GLuint offset = 0;
13721 
13722 	for (glw::GLuint i = 0; i < result; ++i)
13723 	{
13724 		offset += getResultStride(i);
13725 		offset = deAlign32(offset, getBaseTypeSize(i));
13726 	}
13727 
13728 	return offset;
13729 }
13730 
13731 /** Get stride in bytes of <result>.
13732  *
13733  * @param result Result ordinal, starts with 0
13734  *
13735  * @return Stride
13736  **/
getResultStride(glw::GLuint result) const13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13738 {
13739 	const Utils::_variable_type type		   = getResultType(result);
13740 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
13741 
13742 	return n_components * getBaseTypeSize(result);
13743 }
13744 
13745 /** Get size in bytes of <result> base component.
13746  *
13747  * @param result Result ordinal, starts with 0
13748  *
13749  * @return Alignment
13750  **/
getBaseTypeSize(glw::GLuint result) const13751 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13752 {
13753 	const Utils::_variable_type type		   = getResultType(result);
13754 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13755 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13756 
13757 	return base_type_size;
13758 }
13759 
13760 /** Get stride in bytes of all results.
13761  *
13762  * @return Stride
13763  **/
getResultStride() const13764 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13765 {
13766 	const glw::GLuint n_results	= getResultCount();
13767 	glw::GLuint		  stride	   = 0;
13768 	glw::GLuint		  maxAlignment = 0;
13769 
13770 	for (glw::GLuint i = 0; i < n_results; ++i)
13771 	{
13772 		const glw::GLuint alignment = getBaseTypeSize(i);
13773 		stride += getResultStride(i);
13774 		stride		 = deAlign32(stride, alignment);
13775 		maxAlignment = deMaxu32(maxAlignment, alignment);
13776 	}
13777 
13778 	// The stride of all results must also be aligned,
13779 	// so results for next vertex are aligned.
13780 	return deAlign32(stride, maxAlignment);
13781 }
13782 
13783 /** Get type of <result>.
13784  *
13785  * @param result Result ordinal, starts with 0
13786  *
13787  * @return Type
13788  **/
getResultType(glw::GLuint) const13789 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13790 {
13791 	return m_res_type;
13792 }
13793 
13794 /** Constructor
13795  *
13796  * @param n_columns Number of columns
13797  * @param n_rows    Number of rows
13798  **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13799 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13800 	: m_n_columns(n_columns), m_n_rows(n_rows)
13801 {
13802 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13803 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
13804 	m_type_name				   = Utils::getVariableTypeString(type);
13805 
13806 	if (1 == m_n_columns)
13807 	{
13808 		if (1 == m_n_rows)
13809 		{
13810 			m_general_type = SCALAR;
13811 		}
13812 		else
13813 		{
13814 			m_general_type = VECTOR;
13815 		}
13816 	}
13817 	else
13818 	{
13819 		m_general_type = MATRIX;
13820 	}
13821 }
13822 
13823 /** Compare two values
13824  *
13825  * @param type  Type of values
13826  * @param left  Pointer to left value
13827  * @param right Pointer to right value
13828  *
13829  * @return true if values are equal, false otherwise
13830  **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13831 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13832 {
13833 	bool result = true;
13834 
13835 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
13836 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
13837 
13838 	switch (base_type)
13839 	{
13840 	case Utils::VARIABLE_TYPE_DOUBLE:
13841 
13842 	{
13843 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13844 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
13845 
13846 		for (glw::GLuint component = 0; component < n_components; ++component)
13847 		{
13848 			const glw::GLdouble left_value  = left_values[component];
13849 			const glw::GLdouble right_value = right_values[component];
13850 
13851 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13852 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13853 			{
13854 				result = false;
13855 				break;
13856 			}
13857 		}
13858 	}
13859 
13860 	break;
13861 
13862 	case Utils::VARIABLE_TYPE_INT:
13863 
13864 	{
13865 		const glw::GLint* left_values  = (glw::GLint*)left;
13866 		const glw::GLint* right_values = (glw::GLint*)right;
13867 
13868 		for (glw::GLuint component = 0; component < n_components; ++component)
13869 		{
13870 			const glw::GLint left_value  = left_values[component];
13871 			const glw::GLint right_value = right_values[component];
13872 
13873 			if (left_value != right_value)
13874 			{
13875 				result = false;
13876 				break;
13877 			}
13878 		}
13879 	}
13880 
13881 	break;
13882 
13883 	case Utils::VARIABLE_TYPE_UINT:
13884 
13885 	{
13886 		const glw::GLuint* left_values  = (glw::GLuint*)left;
13887 		const glw::GLuint* right_values = (glw::GLuint*)right;
13888 
13889 		for (glw::GLuint component = 0; component < n_components; ++component)
13890 		{
13891 			const glw::GLuint left_value  = left_values[component];
13892 			const glw::GLuint right_value = right_values[component];
13893 
13894 			if (left_value != right_value)
13895 			{
13896 				result = false;
13897 				break;
13898 			}
13899 		}
13900 	}
13901 
13902 	break;
13903 
13904 	default:
13905 
13906 		TCU_FAIL("Not implemented");
13907 
13908 		break;
13909 	}
13910 
13911 	return result;
13912 }
13913 
13914 /** Create instance of function object for given function enumeration and type
13915  *
13916  * @param function Function enumeration
13917  * @param type     Type details
13918  *
13919  * @return Create object
13920  **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13921 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
13922 																			const typeDetails& type)
13923 {
13924 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13925 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13926 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13927 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13928 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13929 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13930 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13931 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13932 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13933 
13934 	const glw::GLuint			n_columns	 = type.m_n_columns;
13935 	const glw::GLuint			n_rows		  = type.m_n_rows;
13936 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13937 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13938 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
13939 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
13940 
13941 	switch (function)
13942 	{
13943 	case FUNCTION_ABS:
13944 
13945 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13946 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13947 
13948 		break;
13949 
13950 	case FUNCTION_CEIL:
13951 
13952 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13953 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13954 
13955 		break;
13956 
13957 	case FUNCTION_CLAMP:
13958 
13959 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13960 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
13961 													 variable_type /* arg3_type */);
13962 		break;
13963 
13964 	case FUNCTION_CLAMP_AGAINST_SCALAR:
13965 
13966 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13967 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13968 													 scalar_type /* arg3_type */);
13969 		break;
13970 
13971 	case FUNCTION_CROSS:
13972 
13973 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13974 			function, "cross", tcu::cross);
13975 
13976 		break;
13977 
13978 	case FUNCTION_DETERMINANT:
13979 
13980 		switch (variable_type)
13981 		{
13982 		case Utils::VARIABLE_TYPE_DMAT2:
13983 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13984 																						 Math::determinant);
13985 		case Utils::VARIABLE_TYPE_DMAT3:
13986 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13987 																						 Math::determinant);
13988 		case Utils::VARIABLE_TYPE_DMAT4:
13989 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13990 																						 Math::determinant);
13991 		default:
13992 			TCU_FAIL("Not implemented");
13993 			break;
13994 		}
13995 
13996 		break;
13997 
13998 	case FUNCTION_DISTANCE:
13999 
14000 		switch (variable_type)
14001 		{
14002 		case Utils::VARIABLE_TYPE_DVEC2:
14003 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14004 				function, "distance", tcu::distance);
14005 			break;
14006 		case Utils::VARIABLE_TYPE_DVEC3:
14007 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14008 				function, "distance", tcu::distance);
14009 			break;
14010 		case Utils::VARIABLE_TYPE_DVEC4:
14011 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14012 				function, "distance", tcu::distance);
14013 			break;
14014 		default:
14015 			break;
14016 		}
14017 
14018 		break;
14019 
14020 	case FUNCTION_DOT:
14021 
14022 		switch (variable_type)
14023 		{
14024 		case Utils::VARIABLE_TYPE_DVEC2:
14025 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14026 				function, "dot", tcu::dot);
14027 			break;
14028 		case Utils::VARIABLE_TYPE_DVEC3:
14029 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14030 				function, "dot", tcu::dot);
14031 			break;
14032 		case Utils::VARIABLE_TYPE_DVEC4:
14033 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14034 				function, "dot", tcu::dot);
14035 			break;
14036 		default:
14037 			break;
14038 		}
14039 
14040 		break;
14041 
14042 	case FUNCTION_EQUAL:
14043 
14044 		switch (variable_type)
14045 		{
14046 		case Utils::VARIABLE_TYPE_DVEC2:
14047 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14048 				function, "equal", Math::equal);
14049 			break;
14050 		case Utils::VARIABLE_TYPE_DVEC3:
14051 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14052 				function, "equal", Math::equal);
14053 			break;
14054 		case Utils::VARIABLE_TYPE_DVEC4:
14055 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14056 				function, "equal", Math::equal);
14057 			break;
14058 		default:
14059 			break;
14060 		}
14061 
14062 		break;
14063 
14064 	case FUNCTION_FACEFORWARD:
14065 
14066 		switch (variable_type)
14067 		{
14068 		case Utils::VARIABLE_TYPE_DVEC2:
14069 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14070 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14071 				function, "faceforward", tcu::faceForward);
14072 			break;
14073 		case Utils::VARIABLE_TYPE_DVEC3:
14074 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14075 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14076 				function, "faceforward", tcu::faceForward);
14077 			break;
14078 		case Utils::VARIABLE_TYPE_DVEC4:
14079 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14080 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14081 				function, "faceforward", tcu::faceForward);
14082 			break;
14083 		default:
14084 			break;
14085 		}
14086 
14087 		break;
14088 
14089 	case FUNCTION_FLOOR:
14090 
14091 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14092 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14093 
14094 		break;
14095 
14096 	case FUNCTION_FMA:
14097 
14098 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14099 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14100 													 variable_type /* arg3_type */);
14101 
14102 		break;
14103 
14104 	case FUNCTION_FRACT:
14105 
14106 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14107 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14108 
14109 		break;
14110 
14111 	case FUNCTION_FREXP:
14112 
14113 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14114 															  glw::GLint /* OutT */>(
14115 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14116 			int_type /* out_type */);
14117 
14118 		break;
14119 
14120 	case FUNCTION_GREATERTHAN:
14121 
14122 		switch (variable_type)
14123 		{
14124 		case Utils::VARIABLE_TYPE_DVEC2:
14125 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14126 				function, "greaterThan", Math::greaterThan);
14127 			break;
14128 		case Utils::VARIABLE_TYPE_DVEC3:
14129 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14130 				function, "greaterThan", Math::greaterThan);
14131 			break;
14132 		case Utils::VARIABLE_TYPE_DVEC4:
14133 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14134 				function, "greaterThan", Math::greaterThan);
14135 			break;
14136 		default:
14137 			break;
14138 		}
14139 
14140 		break;
14141 
14142 	case FUNCTION_GREATERTHANEQUAL:
14143 
14144 		switch (variable_type)
14145 		{
14146 		case Utils::VARIABLE_TYPE_DVEC2:
14147 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14148 				function, "greaterThanEqual", Math::greaterThanEqual);
14149 			break;
14150 		case Utils::VARIABLE_TYPE_DVEC3:
14151 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14152 				function, "greaterThanEqual", Math::greaterThanEqual);
14153 			break;
14154 		case Utils::VARIABLE_TYPE_DVEC4:
14155 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14156 				function, "greaterThanEqual", Math::greaterThanEqual);
14157 			break;
14158 		default:
14159 			break;
14160 		}
14161 
14162 		break;
14163 
14164 	case FUNCTION_INVERSE:
14165 
14166 		switch (variable_type)
14167 		{
14168 		case Utils::VARIABLE_TYPE_DMAT2:
14169 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14170 			break;
14171 		case Utils::VARIABLE_TYPE_DMAT3:
14172 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14173 			break;
14174 		case Utils::VARIABLE_TYPE_DMAT4:
14175 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14176 			break;
14177 		default:
14178 			break;
14179 		}
14180 
14181 		break;
14182 
14183 	case FUNCTION_INVERSESQRT:
14184 
14185 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14186 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14187 
14188 		break;
14189 
14190 	case FUNCTION_LDEXP:
14191 
14192 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14193 													 glw::GLint /* Arg2T */>(
14194 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14195 			int_type /* arg2_type */);
14196 
14197 		break;
14198 
14199 	case FUNCTION_LESSTHAN:
14200 
14201 		switch (variable_type)
14202 		{
14203 		case Utils::VARIABLE_TYPE_DVEC2:
14204 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14205 				function, "lessThan", Math::lessThan);
14206 			break;
14207 		case Utils::VARIABLE_TYPE_DVEC3:
14208 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14209 				function, "lessThan", Math::lessThan);
14210 			break;
14211 		case Utils::VARIABLE_TYPE_DVEC4:
14212 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14213 				function, "lessThan", Math::lessThan);
14214 			break;
14215 		default:
14216 			break;
14217 		}
14218 
14219 		break;
14220 
14221 	case FUNCTION_LESSTHANEQUAL:
14222 
14223 		switch (variable_type)
14224 		{
14225 		case Utils::VARIABLE_TYPE_DVEC2:
14226 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14227 				function, "lessThanEqual", Math::lessThanEqual);
14228 			break;
14229 		case Utils::VARIABLE_TYPE_DVEC3:
14230 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14231 				function, "lessThanEqual", Math::lessThanEqual);
14232 			break;
14233 		case Utils::VARIABLE_TYPE_DVEC4:
14234 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14235 				function, "lessThanEqual", Math::lessThanEqual);
14236 			break;
14237 		default:
14238 			break;
14239 		}
14240 
14241 		break;
14242 
14243 	case FUNCTION_LENGTH:
14244 
14245 		switch (variable_type)
14246 		{
14247 		case Utils::VARIABLE_TYPE_DVEC2:
14248 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14249 																							  tcu::length);
14250 			break;
14251 		case Utils::VARIABLE_TYPE_DVEC3:
14252 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14253 																							  tcu::length);
14254 			break;
14255 		case Utils::VARIABLE_TYPE_DVEC4:
14256 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14257 																							  tcu::length);
14258 			break;
14259 		default:
14260 			break;
14261 		}
14262 
14263 		break;
14264 
14265 	case FUNCTION_MATRIXCOMPMULT:
14266 
14267 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14268 													 glw::GLdouble /* Arg2T */>(
14269 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14270 			variable_type /* arg2_type */);
14271 
14272 		break;
14273 
14274 	case FUNCTION_MAX:
14275 
14276 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14277 													 glw::GLdouble /* Arg2T */>(
14278 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14279 			variable_type /* arg2_type */);
14280 
14281 		break;
14282 
14283 	case FUNCTION_MAX_AGAINST_SCALAR:
14284 
14285 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14286 													 glw::GLdouble /* Arg2T */>(
14287 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14288 			scalar_type /* arg2_type */);
14289 
14290 		break;
14291 
14292 	case FUNCTION_MIN:
14293 
14294 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14295 													 glw::GLdouble /* Arg2T */>(
14296 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14297 			variable_type /* arg2_type */);
14298 
14299 		break;
14300 
14301 	case FUNCTION_MIN_AGAINST_SCALAR:
14302 
14303 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14304 													 glw::GLdouble /* Arg2T */>(
14305 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14306 			scalar_type /* arg2_type */);
14307 
14308 		break;
14309 
14310 	case FUNCTION_MIX:
14311 
14312 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14313 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14314 													 variable_type /* arg3_type */);
14315 
14316 		break;
14317 
14318 	case FUNCTION_MOD:
14319 
14320 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14321 													 glw::GLdouble /* Arg2T */>(
14322 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14323 			variable_type /* arg2_type */);
14324 
14325 		break;
14326 
14327 	case FUNCTION_MOD_AGAINST_SCALAR:
14328 
14329 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14330 													 glw::GLdouble /* Arg2T */>(
14331 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14332 			scalar_type /* arg2_type */);
14333 
14334 		break;
14335 
14336 	case FUNCTION_MODF:
14337 
14338 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14339 															  glw::GLdouble /* OutT */>(
14340 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14341 			variable_type /* out_type */);
14342 
14343 		break;
14344 
14345 	case FUNCTION_NORMALIZE:
14346 
14347 		switch (variable_type)
14348 		{
14349 		case Utils::VARIABLE_TYPE_DVEC2:
14350 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14351 																						   tcu::normalize);
14352 			break;
14353 		case Utils::VARIABLE_TYPE_DVEC3:
14354 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14355 																						   tcu::normalize);
14356 			break;
14357 		case Utils::VARIABLE_TYPE_DVEC4:
14358 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14359 																						   tcu::normalize);
14360 			break;
14361 		default:
14362 			break;
14363 		}
14364 
14365 		break;
14366 
14367 	case FUNCTION_NOTEQUAL:
14368 
14369 		switch (variable_type)
14370 		{
14371 		case Utils::VARIABLE_TYPE_DVEC2:
14372 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14373 				function, "notEqual", Math::notEqual);
14374 			break;
14375 		case Utils::VARIABLE_TYPE_DVEC3:
14376 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14377 				function, "notEqual", Math::notEqual);
14378 			break;
14379 		case Utils::VARIABLE_TYPE_DVEC4:
14380 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14381 				function, "notEqual", Math::notEqual);
14382 			break;
14383 		default:
14384 			break;
14385 		}
14386 
14387 		break;
14388 
14389 	case FUNCTION_OUTERPRODUCT:
14390 
14391 		switch (variable_type)
14392 		{
14393 		case Utils::VARIABLE_TYPE_DMAT2:
14394 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14395 				function, "outerProduct", Math::outerProduct);
14396 			break;
14397 		case Utils::VARIABLE_TYPE_DMAT2X3:
14398 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14399 				function, "outerProduct", Math::outerProduct);
14400 			break;
14401 		case Utils::VARIABLE_TYPE_DMAT2X4:
14402 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14403 				function, "outerProduct", Math::outerProduct);
14404 			break;
14405 		case Utils::VARIABLE_TYPE_DMAT3:
14406 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14407 				function, "outerProduct", Math::outerProduct);
14408 			break;
14409 		case Utils::VARIABLE_TYPE_DMAT3X2:
14410 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14411 				function, "outerProduct", Math::outerProduct);
14412 			break;
14413 		case Utils::VARIABLE_TYPE_DMAT3X4:
14414 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14415 				function, "outerProduct", Math::outerProduct);
14416 			break;
14417 		case Utils::VARIABLE_TYPE_DMAT4:
14418 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14419 				function, "outerProduct", Math::outerProduct);
14420 			break;
14421 		case Utils::VARIABLE_TYPE_DMAT4X2:
14422 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14423 				function, "outerProduct", Math::outerProduct);
14424 			break;
14425 		case Utils::VARIABLE_TYPE_DMAT4X3:
14426 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14427 				function, "outerProduct", Math::outerProduct);
14428 			break;
14429 		default:
14430 			break;
14431 		}
14432 
14433 		break;
14434 
14435 	case FUNCTION_PACKDOUBLE2X32:
14436 
14437 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14438 																						  Math::packDouble2x32);
14439 
14440 		break;
14441 
14442 	case FUNCTION_REFLECT:
14443 
14444 		switch (variable_type)
14445 		{
14446 		case Utils::VARIABLE_TYPE_DVEC2:
14447 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14448 				function, "reflect", tcu::reflect);
14449 			break;
14450 		case Utils::VARIABLE_TYPE_DVEC3:
14451 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14452 				function, "reflect", tcu::reflect);
14453 			break;
14454 		case Utils::VARIABLE_TYPE_DVEC4:
14455 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14456 				function, "reflect", tcu::reflect);
14457 			break;
14458 		default:
14459 			break;
14460 		}
14461 
14462 		break;
14463 
14464 	case FUNCTION_REFRACT:
14465 
14466 		switch (variable_type)
14467 		{
14468 		case Utils::VARIABLE_TYPE_DVEC2:
14469 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14470 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14471 				function, "refract", tcu::refract);
14472 			break;
14473 		case Utils::VARIABLE_TYPE_DVEC3:
14474 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14475 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14476 				function, "refract", tcu::refract);
14477 			break;
14478 		case Utils::VARIABLE_TYPE_DVEC4:
14479 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14480 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14481 				function, "refract", tcu::refract);
14482 			break;
14483 		default:
14484 			break;
14485 		}
14486 
14487 		break;
14488 
14489 	case FUNCTION_ROUND:
14490 
14491 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14492 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14493 
14494 		break;
14495 
14496 	case FUNCTION_ROUNDEVEN:
14497 
14498 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14499 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14500 
14501 		break;
14502 
14503 	case FUNCTION_SIGN:
14504 
14505 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14506 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14507 
14508 		break;
14509 
14510 	case FUNCTION_SMOOTHSTEP:
14511 
14512 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14513 													 variable_type /* res_type  */, variable_type /* arg1_type */,
14514 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
14515 
14516 		break;
14517 
14518 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14519 
14520 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14521 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
14522 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14523 
14524 		break;
14525 
14526 	case FUNCTION_SQRT:
14527 
14528 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14529 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14530 
14531 		break;
14532 
14533 	case FUNCTION_STEP:
14534 
14535 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14536 													 glw::GLdouble /* Arg2T */>(
14537 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14538 			variable_type /* arg2_type */);
14539 
14540 		break;
14541 
14542 	case FUNCTION_STEP_AGAINST_SCALAR:
14543 
14544 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14545 													 glw::GLdouble /* Arg2T */>(
14546 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14547 			variable_type /* arg2_type */);
14548 
14549 		break;
14550 
14551 	case FUNCTION_TRANSPOSE:
14552 
14553 		switch (variable_type)
14554 		{
14555 		case Utils::VARIABLE_TYPE_DMAT2:
14556 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14557 																				 Math::transpose);
14558 			break;
14559 		case Utils::VARIABLE_TYPE_DMAT2X3:
14560 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14561 																					 Math::transpose);
14562 			break;
14563 		case Utils::VARIABLE_TYPE_DMAT2X4:
14564 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14565 																					 Math::transpose);
14566 			break;
14567 		case Utils::VARIABLE_TYPE_DMAT3:
14568 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14569 																				 Math::transpose);
14570 			break;
14571 		case Utils::VARIABLE_TYPE_DMAT3X2:
14572 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14573 																					 Math::transpose);
14574 			break;
14575 		case Utils::VARIABLE_TYPE_DMAT3X4:
14576 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14577 																					 Math::transpose);
14578 			break;
14579 		case Utils::VARIABLE_TYPE_DMAT4:
14580 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14581 																				 Math::transpose);
14582 			break;
14583 		case Utils::VARIABLE_TYPE_DMAT4X2:
14584 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14585 																					 Math::transpose);
14586 			break;
14587 		case Utils::VARIABLE_TYPE_DMAT4X3:
14588 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14589 																					 Math::transpose);
14590 			break;
14591 		default:
14592 			break;
14593 		}
14594 
14595 		break;
14596 
14597 	case FUNCTION_TRUNC:
14598 
14599 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14600 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14601 
14602 		break;
14603 
14604 	case FUNCTION_UNPACKDOUBLE2X32:
14605 
14606 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14607 																						  Math::unpackDouble2x32);
14608 
14609 		break;
14610 
14611 	case FUNCTION_ISNAN:
14612 
14613 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14614 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14615 
14616 		break;
14617 
14618 	case FUNCTION_ISINF:
14619 
14620 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14621 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14622 
14623 		break;
14624 
14625 	default:
14626 		TCU_FAIL("Not implemented");
14627 		return 0;
14628 		break;
14629 	}
14630 
14631 	TCU_FAIL("Not implemented");
14632 	return 0;
14633 }
14634 
14635 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14636  *
14637  * @param argument        Argument index
14638  * @param function_object Function object
14639  *
14640  * @return Function pointer
14641  **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14642 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14643 	glw::GLuint argument, const functionObject& function_object) const
14644 {
14645 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14646 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14647 
14648 	switch (argument_type)
14649 	{
14650 	case Utils::VARIABLE_TYPE_DMAT2:
14651 		return gl.uniformMatrix2dv;
14652 		break;
14653 	case Utils::VARIABLE_TYPE_DMAT2X3:
14654 		return gl.uniformMatrix2x3dv;
14655 		break;
14656 	case Utils::VARIABLE_TYPE_DMAT2X4:
14657 		return gl.uniformMatrix2x4dv;
14658 		break;
14659 	case Utils::VARIABLE_TYPE_DMAT3:
14660 		return gl.uniformMatrix3dv;
14661 		break;
14662 	case Utils::VARIABLE_TYPE_DMAT3X2:
14663 		return gl.uniformMatrix3x2dv;
14664 		break;
14665 	case Utils::VARIABLE_TYPE_DMAT3X4:
14666 		return gl.uniformMatrix3x4dv;
14667 		break;
14668 	case Utils::VARIABLE_TYPE_DMAT4:
14669 		return gl.uniformMatrix4dv;
14670 		break;
14671 	case Utils::VARIABLE_TYPE_DMAT4X2:
14672 		return gl.uniformMatrix4x2dv;
14673 		break;
14674 	case Utils::VARIABLE_TYPE_DMAT4X3:
14675 		return gl.uniformMatrix4x3dv;
14676 		break;
14677 	default:
14678 		break;
14679 	}
14680 
14681 	TCU_FAIL("Not implemented");
14682 	return 0;
14683 }
14684 
14685 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14686  *
14687  * @param argument        Argument index
14688  * @param function_object Function object
14689  *
14690  * @return Function pointer
14691  **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14692 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14693 	glw::GLuint argument, const functionObject& function_object) const
14694 {
14695 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14696 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14697 
14698 	switch (argument_type)
14699 	{
14700 	case Utils::VARIABLE_TYPE_DOUBLE:
14701 		return gl.uniform1dv;
14702 		break;
14703 	case Utils::VARIABLE_TYPE_DVEC2:
14704 		return gl.uniform2dv;
14705 		break;
14706 	case Utils::VARIABLE_TYPE_DVEC3:
14707 		return gl.uniform3dv;
14708 		break;
14709 	case Utils::VARIABLE_TYPE_DVEC4:
14710 		return gl.uniform4dv;
14711 		break;
14712 	default:
14713 		TCU_FAIL("Not implemented");
14714 		break;
14715 	}
14716 
14717 	return 0;
14718 }
14719 
14720 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14721  *
14722  * @param argument        Argument index
14723  * @param function_object Function object
14724  *
14725  * @return Function pointer
14726  **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14727 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14728 	glw::GLuint argument, const functionObject& function_object) const
14729 {
14730 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14731 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14732 
14733 	switch (argument_type)
14734 	{
14735 	case Utils::VARIABLE_TYPE_INT:
14736 		return gl.uniform1iv;
14737 		break;
14738 	case Utils::VARIABLE_TYPE_IVEC2:
14739 		return gl.uniform2iv;
14740 		break;
14741 	case Utils::VARIABLE_TYPE_IVEC3:
14742 		return gl.uniform3iv;
14743 		break;
14744 	case Utils::VARIABLE_TYPE_IVEC4:
14745 		return gl.uniform4iv;
14746 		break;
14747 	default:
14748 		TCU_FAIL("Not implemented");
14749 		break;
14750 	}
14751 
14752 	return 0;
14753 }
14754 
14755 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14756  *
14757  * @param argument        Argument index
14758  * @param function_object Function object
14759  *
14760  * @return Function pointer
14761  **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14762 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14763 	glw::GLuint argument, const functionObject& function_object) const
14764 {
14765 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14766 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14767 
14768 	switch (argument_type)
14769 	{
14770 	case Utils::VARIABLE_TYPE_UVEC2:
14771 		return gl.uniform2uiv;
14772 		break;
14773 	default:
14774 		TCU_FAIL("Not implemented");
14775 		break;
14776 	}
14777 
14778 	return 0;
14779 }
14780 
14781 /** Get name of uniform that will be used as <argument>.
14782  *
14783  * @param argument Argument index
14784  *
14785  * @return Name of uniform
14786  **/
getUniformName(glw::GLuint argument) const14787 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14788 {
14789 	switch (argument)
14790 	{
14791 	case 0:
14792 		return "uniform_0";
14793 		break;
14794 	case 1:
14795 		return "uniform_1";
14796 		break;
14797 	case 2:
14798 		return "uniform_2";
14799 		break;
14800 	default:
14801 		TCU_FAIL("Not implemented");
14802 		return 0;
14803 		break;
14804 	}
14805 }
14806 
14807 /** Get name of varying that will be used as <result>.
14808  *
14809  * @param result Result index
14810  *
14811  * @return Name of varying
14812  **/
getVaryingName(glw::GLuint result) const14813 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14814 {
14815 	switch (result)
14816 	{
14817 	case 0:
14818 		return "result_0";
14819 		break;
14820 	case 1:
14821 		return "result_1";
14822 		break;
14823 	case 2:
14824 		return "result_2";
14825 		break;
14826 	default:
14827 		TCU_FAIL("Not implemented");
14828 		return 0;
14829 		break;
14830 	}
14831 }
14832 
14833 /** Check if given combination of function and type is implemented
14834  *
14835  * @param function Function enumeration
14836  * @param type     Type details
14837  *
14838  * @return true if function is available for given type, false otherwise
14839  **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14840 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14841 {
14842 	static const bool look_up_table[][3] = {
14843 		/* SCALAR, VECTOR, MATRIX */
14844 		/* FUNCTION_ABS:                       */ { true, true, false },
14845 		/* FUNCTION_CEIL:                      */ { true, true, false },
14846 		/* FUNCTION_CLAMP:                     */ { true, true, false },
14847 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14848 		/* FUNCTION_CROSS:                     */ { false, true, false },
14849 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
14850 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
14851 		/* FUNCTION_DOT:                       */ { false, true, false },
14852 		/* FUNCTION_EQUAL:                     */ { false, true, false },
14853 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
14854 		/* FUNCTION_FLOOR:                     */ { true, true, false },
14855 		/* FUNCTION_FMA:                       */ { true, true, false },
14856 		/* FUNCTION_FRACT:                     */ { true, true, false },
14857 		/* FUNCTION_FREXP:                     */ { true, true, false },
14858 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
14859 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14860 		/* FUNCTION_INVERSE:                   */ { false, false, true },
14861 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
14862 		/* FUNCTION_LDEXP:                     */ { true, true, false },
14863 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
14864 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14865 		/* FUNCTION_LENGTH:                    */ { false, true, false },
14866 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14867 		/* FUNCTION_MAX:                       */ { true, true, false },
14868 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14869 		/* FUNCTION_MIN:                       */ { true, true, false },
14870 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14871 		/* FUNCTION_MIX:                       */ { true, true, false },
14872 		/* FUNCTION_MOD:                       */ { true, true, false },
14873 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14874 		/* FUNCTION_MODF:                      */ { true, true, false },
14875 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
14876 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14877 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14878 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14879 		/* FUNCTION_REFLECT:                   */ { false, true, false },
14880 		/* FUNCTION_REFRACT:                   */ { false, true, false },
14881 		/* FUNCTION_ROUND:                     */ { true, true, false },
14882 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14883 		/* FUNCTION_SIGN:                      */ { true, false, false },
14884 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14885 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14886 		/* FUNCTION_SQRT:                      */ { true, true, false },
14887 		/* FUNCTION_STEP:                      */ { true, true, false },
14888 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14889 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14890 		/* FUNCTION_TRUNC:                     */ { true, true, false },
14891 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14892 		/* FUNCTION_ISNAN:                     */ { true, true, false },
14893 		/* FUNCTION_ISINF:                     */ { true, true, false },
14894 	};
14895 
14896 	bool result = look_up_table[function][type.m_general_type];
14897 
14898 	if (true == result)
14899 	{
14900 		switch (function)
14901 		{
14902 		case FUNCTION_CROSS: /* Only 3 element vectors */
14903 			result = (3 == type.m_n_rows);
14904 			break;
14905 		case FUNCTION_DETERMINANT: /* Only square matrices */
14906 		case FUNCTION_INVERSE:
14907 			result = (type.m_n_columns == type.m_n_rows);
14908 			break;
14909 		default:
14910 			break;
14911 		}
14912 	}
14913 
14914 	return result;
14915 }
14916 
14917 /** Logs variable of given type: name (type) [values]
14918  *
14919  * @param buffer Source of data
14920  * @param name   Name of variable
14921  * @param type   Type of variable
14922  **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14923 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14924 										  Utils::_variable_type type) const
14925 {
14926 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
14927 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
14928 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14929 
14930 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14931 
14932 	for (glw::GLuint component = 0; component < n_components; ++component)
14933 	{
14934 		if (0 != component)
14935 		{
14936 			message << ", ";
14937 		}
14938 
14939 		switch (base_type)
14940 		{
14941 		case Utils::VARIABLE_TYPE_DOUBLE:
14942 			message << ((glw::GLdouble*)buffer)[component];
14943 			break;
14944 		case Utils::VARIABLE_TYPE_INT:
14945 			message << ((glw::GLint*)buffer)[component];
14946 			break;
14947 		case Utils::VARIABLE_TYPE_UINT:
14948 			message << ((glw::GLuint*)buffer)[component];
14949 			break;
14950 		default:
14951 			TCU_FAIL("Not implemented");
14952 		}
14953 	}
14954 
14955 	message << "]" << tcu::TestLog::EndMessage;
14956 }
14957 
14958 /** Prepare input arguments, data are stored in <buffer>
14959  *
14960  * @param function_object Function object
14961  * @param vertex          Vertex index
14962  * @param buffer          Buffer pointer
14963  **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14964 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14965 										  glw::GLubyte* buffer)
14966 {
14967 	const glw::GLuint n_arguments = function_object.getArgumentCount();
14968 
14969 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14970 	{
14971 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
14972 
14973 		prepareComponents(function_object, vertex, argument, buffer + offset);
14974 	}
14975 }
14976 
14977 /** Prepare components for given <function_object>, <vertex> and <argument>
14978  *
14979  * @param function_object Function object
14980  * @param vertex          Vertex index
14981  * @param argument        Argument index
14982  * @param buffer          Buffer pointer
14983  **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14984 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14985 											glw::GLuint argument, glw::GLubyte* buffer)
14986 {
14987 	glw::GLuint					argument_index[3]		 = { 0 };
14988 	glw::GLuint					argument_reset[3]		 = { 0 };
14989 	glw::GLuint					argument_step[3]		 = { 0 };
14990 	glw::GLdouble				double_argument_start[3] = { 0.0 };
14991 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14992 	glw::GLuint					int_argument_start  = -4;
14993 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
14994 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
14995 	glw::GLuint					uint_argument_start = 0;
14996 
14997 	switch (n_arguments)
14998 	{
14999 	case 1:
15000 		argument_step[0]		 = 1;
15001 		argument_reset[0]		 = 1024;
15002 		double_argument_start[0] = -511.5;
15003 		break;
15004 	case 2:
15005 		argument_step[0]		 = 32;
15006 		argument_step[1]		 = 1;
15007 		argument_reset[0]		 = 32;
15008 		argument_reset[1]		 = 32;
15009 		double_argument_start[0] = -15.5;
15010 		double_argument_start[1] = -15.5;
15011 		break;
15012 	case 3:
15013 		argument_step[0]		 = 64;
15014 		argument_step[1]		 = 8;
15015 		argument_step[2]		 = 1;
15016 		argument_reset[0]		 = 16;
15017 		argument_reset[1]		 = 8;
15018 		argument_reset[2]		 = 8;
15019 		double_argument_start[0] = -7.5;
15020 		double_argument_start[1] = -3.5;
15021 		double_argument_start[2] = -3.5;
15022 		break;
15023 	default:
15024 		TCU_FAIL("Not implemented");
15025 		return;
15026 		break;
15027 	};
15028 
15029 	switch (function_object.getFunctionEnum())
15030 	{
15031 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
15032 	case FUNCTION_CLAMP_AGAINST_SCALAR:
15033 		double_argument_start[2] = 4.5;
15034 		break;
15035 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
15036 		double_argument_start[0] = 16.5;
15037 		break;
15038 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
15039 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
15040 		argument_step[0]		 = 1;
15041 		argument_step[1]		 = 8;
15042 		argument_step[2]		 = 64;
15043 		argument_reset[0]		 = 8;
15044 		argument_reset[1]		 = 8;
15045 		argument_reset[2]		 = 16;
15046 		double_argument_start[0] = -3.5;
15047 		double_argument_start[1] = 4.5;
15048 		double_argument_start[2] = -7.5;
15049 		break;
15050 	default:
15051 		break;
15052 	}
15053 
15054 	for (glw::GLuint i = 0; i < n_arguments; ++i)
15055 	{
15056 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
15057 	}
15058 
15059 	switch (base_arg_type)
15060 	{
15061 	case Utils::VARIABLE_TYPE_DOUBLE:
15062 	{
15063 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
15064 
15065 		double_argument_start[argument] += argument_index[argument];
15066 
15067 		for (glw::GLuint component = 0; component < n_components; ++component)
15068 		{
15069 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
15070 
15071 			switch (function_object.getFunctionEnum())
15072 			{
15073 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
15074 				if (0.5 == Math::fract(value))
15075 				{
15076 					value += 0.01;
15077 				}
15078 				break;
15079 			default:
15080 				break;
15081 			}
15082 
15083 			argument_dst[component] = value;
15084 		}
15085 	}
15086 	break;
15087 	case Utils::VARIABLE_TYPE_INT:
15088 	{
15089 		glw::GLint* argument_dst = (glw::GLint*)buffer;
15090 
15091 		uint_argument_start += argument_index[argument];
15092 
15093 		for (glw::GLuint component = 0; component < n_components; ++component)
15094 		{
15095 			const glw::GLint value = int_argument_start + component;
15096 
15097 			argument_dst[component] = value;
15098 		}
15099 	}
15100 	break;
15101 	case Utils::VARIABLE_TYPE_UINT:
15102 	{
15103 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
15104 
15105 		uint_argument_start += argument_index[argument];
15106 
15107 		for (glw::GLuint component = 0; component < n_components; ++component)
15108 		{
15109 			const glw::GLuint value = uint_argument_start + component;
15110 
15111 			argument_dst[component] = value;
15112 		}
15113 	}
15114 	break;
15115 	default:
15116 		TCU_FAIL("Not implemented");
15117 		return;
15118 		break;
15119 	}
15120 }
15121 
15122 /** Prepare programInfo for given functionObject
15123  *
15124  * @param function_object  Function object
15125  * @param out_program_info Program info
15126  **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)15127 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
15128 {
15129 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
15130 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
15131 
15132 	prepareVertexShaderCode(function_object);
15133 
15134 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
15135 						   varying_names, n_varying_names);
15136 }
15137 
15138 /** Prepare input data and expected results for given function object
15139  *
15140  * @param function_object Function object
15141  **/
prepareTestData(const functionObject & function_object)15142 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
15143 {
15144 	const glw::GLuint result_stride		   = function_object.getResultStride();
15145 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
15146 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
15147 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
15148 
15149 	m_argument_data.clear();
15150 	m_expected_results_data.clear();
15151 
15152 	m_argument_data.resize(argument_buffer_size);
15153 	m_expected_results_data.resize(result_buffer_size);
15154 
15155 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15156 	{
15157 		const glw::GLuint result_offset   = vertex * result_stride;
15158 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
15159 		const glw::GLuint argument_offset = vertex * argument_stride;
15160 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
15161 
15162 		prepareArgument(function_object, vertex, argument_dst);
15163 		function_object.call(result_dst, argument_dst);
15164 	}
15165 }
15166 
15167 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
15168  *
15169  * @param function_object Function object
15170  **/
prepareVertexShaderCode(const functionObject & function_object)15171 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
15172 {
15173 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
15174 													 "\n"
15175 													 "precision highp float;\n"
15176 													 "\n"
15177 													 "ARGUMENT_DEFINITION"
15178 													 "\n"
15179 													 "RESULT_DEFINITION"
15180 													 "\n"
15181 													 "void main()\n"
15182 													 "{\n"
15183 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
15184 													 "}\n"
15185 													 "\n";
15186 
15187 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15188 	static const glw::GLchar* argument_token			= "ARGUMENT";
15189 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
15190 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15191 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
15192 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
15193 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
15194 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
15195 
15196 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15197 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
15198 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
15199 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15200 
15201 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15202 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
15203 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
15204 	const glw::GLuint n_results					 = function_object.getResultCount();
15205 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15206 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
15207 
15208 	size_t		search_position = 0;
15209 	std::string string			= shader_template_code;
15210 
15211 	/* Replace ARGUMENT_DEFINITION with definitions */
15212 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15213 	{
15214 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15215 		const glw::GLchar*	uniform_name  = getUniformName(argument);
15216 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
15217 
15218 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15219 
15220 		search_position -= argument_definition_length;
15221 
15222 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15223 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15224 	}
15225 
15226 	/* Remove ARGUMENT_DEFINITION */
15227 	Utils::replaceToken(argument_definition_token, search_position, "", string);
15228 
15229 	/* Replace RESULT_DEFINITION with definitions */
15230 	for (glw::GLuint result = 0; result < n_results; ++result)
15231 	{
15232 		Utils::_variable_type variable_type = function_object.getResultType(result);
15233 		const glw::GLchar*	varying_name  = getVaryingName(result);
15234 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
15235 
15236 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15237 
15238 		search_position -= result_definition_length;
15239 
15240 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15241 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
15242 	}
15243 
15244 	/* Remove RESULT_DEFINITION */
15245 	Utils::replaceToken(result_definition_token, search_position, "", string);
15246 
15247 	/* Replace RESULT_NAME */
15248 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15249 
15250 	/* Replace RESULT_TYPE */
15251 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15252 
15253 	/* Replace FUNCTION_NAME */
15254 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15255 
15256 	/* Replace ARGUMENT with list of arguments */
15257 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15258 	{
15259 		const glw::GLchar* uniform_name = getUniformName(argument);
15260 
15261 		if (0 == argument)
15262 		{
15263 			Utils::replaceToken(argument_token, search_position, first_argument, string);
15264 		}
15265 		else
15266 		{
15267 			Utils::replaceToken(argument_token, search_position, argument_str, string);
15268 		}
15269 
15270 		search_position -= first_argument_length;
15271 
15272 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15273 	}
15274 
15275 	for (glw::GLuint result = 1; result < n_results; ++result)
15276 	{
15277 		const glw::GLchar* varying_name = getVaryingName(result);
15278 
15279 		Utils::replaceToken(argument_token, search_position, argument_str, string);
15280 
15281 		search_position -= first_argument_length;
15282 
15283 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15284 	}
15285 
15286 	/* Remove ARGUMENT */
15287 	Utils::replaceToken(argument_token, search_position, "", string);
15288 
15289 	m_vertex_shader_code = string;
15290 }
15291 
15292 /** Test single function with one type
15293  *
15294  * param function Function enumeration
15295  * param type     Type details
15296  *
15297  * @return true if test pass (or function is not available for <type>), false otherwise
15298  **/
test(FunctionEnum function,const typeDetails & type)15299 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15300 {
15301 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15302 
15303 	/* Skip if function is not implemented for type */
15304 	if (false == isFunctionImplemented(function, type))
15305 	{
15306 		return true;
15307 	}
15308 
15309 	Utils::programInfo			  program(m_context);
15310 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15311 
15312 	prepareProgram(*function_object, program);
15313 	prepareTestData(*function_object);
15314 
15315 	/* Set up program */
15316 	gl.useProgram(program.m_program_object_id);
15317 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15318 
15319 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15320 	{
15321 		testBegin(*function_object, program.m_program_object_id, vertex);
15322 
15323 		gl.beginTransformFeedback(GL_POINTS);
15324 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15325 
15326 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15327 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15328 
15329 		gl.endTransformFeedback();
15330 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15331 
15332 		if (false == verifyResults(*function_object, vertex))
15333 		{
15334 			return false;
15335 		}
15336 	}
15337 
15338 	return true;
15339 }
15340 
15341 /** Update transform feedback buffer and uniforms
15342  *
15343  * @param function_object Function object
15344  * @param program_id      Program object id
15345  * @param vertex          Vertex index
15346  **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15347 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15348 {
15349 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
15350 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
15351 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
15352 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
15353 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
15354 
15355 	/* Update transform feedback buffer */
15356 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
15357 	transform_feedback_buffer_data.resize(result_buffer_size);
15358 
15359 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15360 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15361 
15362 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15363 				  GL_DYNAMIC_COPY);
15364 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15365 
15366 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15367 					   result_buffer_size);
15368 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15369 
15370 	/* Update VAO */
15371 	gl.bindVertexArray(m_vertex_array_object_id);
15372 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15373 
15374 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15375 	{
15376 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
15377 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
15378 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
15379 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
15380 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
15381 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15382 
15383 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15384 
15385 		if (-1 == uniform_location)
15386 		{
15387 			TCU_FAIL("Inactive uniform");
15388 		}
15389 
15390 		if (1 == n_columns)
15391 		{
15392 			switch (Utils::getBaseVariableType(argument_type))
15393 			{
15394 			case Utils::VARIABLE_TYPE_DOUBLE:
15395 			{
15396 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15397 
15398 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15399 			}
15400 			break;
15401 			case Utils::VARIABLE_TYPE_UINT:
15402 			{
15403 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15404 
15405 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15406 			}
15407 			break;
15408 			case Utils::VARIABLE_TYPE_INT:
15409 			{
15410 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15411 
15412 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15413 			}
15414 			break;
15415 			default:
15416 				TCU_FAIL("Not implemented");
15417 				break;
15418 			}
15419 		}
15420 		else
15421 		{
15422 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15423 
15424 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15425 		}
15426 	}
15427 }
15428 
15429 /** Init GL obejcts
15430  *
15431  **/
testInit()15432 void BuiltinFunctionTest::testInit()
15433 {
15434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15435 
15436 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
15437 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15438 
15439 	gl.genVertexArrays(1, &m_vertex_array_object_id);
15440 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15441 
15442 	gl.enable(GL_RASTERIZER_DISCARD);
15443 }
15444 
15445 /** Checks if function result is an acceptable edge case
15446  *
15447  * @param function_object Function object
15448  * @param vertex          Vertex index
15449  *
15450  * @return true if all results are as expected, false otherwise
15451  **/
isResultEdgeCase(const functionObject & function_object,glw::GLuint vertex,const Utils::_variable_type result_type,const glw::GLvoid * expected_result_src,const glw::GLvoid * result_src)15452 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15453 										   const Utils::_variable_type result_type,
15454 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15455 {
15456 	FunctionEnum function_type = function_object.getFunctionEnum();
15457 	switch (function_type)
15458 	{
15459 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15460 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15461 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15462 	case FUNCTION_MOD:
15463 	case FUNCTION_MOD_AGAINST_SCALAR:
15464 	{
15465 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
15466 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
15467 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
15468 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
15469 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
15470 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
15471 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
15472 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
15473 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15474 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15475 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15476 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
15477 		bool				 edge_case_present = false;
15478 		bool				 recheck		   = false;
15479 
15480 		// verify if there is a mod(a, a) case and prepare new expected result
15481 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15482 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15483 		for (glw::GLuint component = 0; component < n_components; ++component)
15484 		{
15485 			glw::GLdouble expected_result_component = expected_result[component];
15486 			glw::GLdouble actual_result_component   = actual_result[component];
15487 			glw::GLdouble argument_1_component		= argument_1[component];
15488 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15489 
15490 			// if coresponding components of arguments are equal and if component of first argument
15491 			// and component of result are equal then expected result must be corrected
15492 			edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) &&
15493 								(m_epsilon > de::abs(argument_1_component - actual_result_component));
15494 			recheck |= edge_case_present;
15495 			corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component;
15496 		}
15497 
15498 		// recheck test result with corrected expected result
15499 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15500 	}
15501 	default:
15502 		return false;
15503 	}
15504 }
15505 
15506 /** Compare contents of transform feedback buffer with expected results
15507  *
15508  * @param function_object Function object
15509  * @param vertex          Vertex index
15510  *
15511  * @return true if all results are as expected, false otherwise
15512  **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15513 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15514 {
15515 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
15516 	bool				  test_result	  = true;
15517 	const glw::GLuint	 n_results		   = function_object.getResultCount();
15518 	const glw::GLuint	 results_stride   = function_object.getResultStride();
15519 	const glw::GLuint	 results_offset   = vertex * results_stride;
15520 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15521 
15522 	/* Get transform feedback data */
15523 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15524 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15525 
15526 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15527 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15528 
15529 	for (glw::GLuint result = 0; result < n_results; ++result)
15530 	{
15531 		const Utils::_variable_type result_type   = function_object.getResultType(result);
15532 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
15533 
15534 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
15535 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
15536 
15537 		if (compare(result_type, expected_result_src, result_src))
15538 			continue;
15539 
15540 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15541 		{
15542 			test_result = false;
15543 			break;
15544 		}
15545 	}
15546 
15547 	/* Unmap transform feedback buffer */
15548 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15549 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15550 
15551 	if (false == test_result)
15552 	{
15553 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
15554 		const glw::GLuint arguments_offset = vertex * argument_stride;
15555 
15556 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15557 											<< tcu::TestLog::EndMessage;
15558 
15559 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15560 											<< tcu::TestLog::EndMessage;
15561 
15562 		for (glw::GLuint result = 0; result < n_results; ++result)
15563 		{
15564 			const Utils::_variable_type result_type   = function_object.getResultType(result);
15565 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
15566 
15567 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
15568 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
15569 
15570 			logVariableType(result_src, "Result", result_type);
15571 			logVariableType(expected_result_src, "Expected result", result_type);
15572 		}
15573 
15574 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15575 		{
15576 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15577 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
15578 
15579 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15580 		}
15581 
15582 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15583 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
15584 	}
15585 
15586 	return test_result;
15587 }
15588 
15589 /** Constructor.
15590  *
15591  *  @param context Rendering context.
15592  **/
GPUShaderFP64Tests(deqp::Context & context)15593 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15594 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15595 {
15596 	/* Left blank on purpose */
15597 }
15598 
15599 /** Initializes a texture_storage_multisample test group.
15600  *
15601  **/
init(void)15602 void GPUShaderFP64Tests::init(void)
15603 {
15604 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15605 	fp64->addChild(new GPUShaderFP64Test1(m_context));
15606 	fp64->addChild(new GPUShaderFP64Test2(m_context));
15607 	fp64->addChild(new GPUShaderFP64Test3(m_context));
15608 	fp64->addChild(new GPUShaderFP64Test4(m_context));
15609 	fp64->addChild(new GPUShaderFP64Test5(m_context));
15610 	fp64->addChild(new GPUShaderFP64Test6(m_context));
15611 	fp64->addChild(new GPUShaderFP64Test7(m_context));
15612 	fp64->addChild(new GPUShaderFP64Test8(m_context));
15613 	fp64->addChild(new GPUShaderFP64Test9(m_context));
15614 	addChild(fp64);
15615 
15616 	TypeDefinition typeDefinition[] =
15617 	{
15618 		{ "double",  1, 1 },
15619 		{ "dvec2",   1, 2 },
15620 		{ "dvec3",   1, 3 },
15621 		{ "dvec4",   1, 4 },
15622 		{ "dmat2",   2, 2 },
15623 		{ "dmat2x3", 2, 3 },
15624 		{ "dmat2x4", 2, 4 },
15625 		{ "dmat3x2", 3, 2 },
15626 		{ "dmat3",   3, 3 },
15627 		{ "dmat3x4", 3, 4 },
15628 		{ "dmat4x2", 4, 2 },
15629 		{ "dmat4x3", 4, 3 },
15630 		{ "dmat4",   4, 4 }
15631 	};
15632 
15633 	struct BuiltinFunctions
15634 	{
15635 		std::string  name;
15636 		FunctionEnum function;
15637 	} builtinFunctions[] = {
15638 		{ "abs",						FUNCTION_ABS },
15639 		{ "ceil",						FUNCTION_CEIL },
15640 		{ "clamp",						FUNCTION_CLAMP },
15641 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
15642 		{ "cross",						FUNCTION_CROSS },
15643 		{ "determinant",				FUNCTION_DETERMINANT },
15644 		{ "distance",					FUNCTION_DISTANCE },
15645 		{ "dot",						FUNCTION_DOT },
15646 		{ "equal",						FUNCTION_EQUAL },
15647 		{ "faceforward",				FUNCTION_FACEFORWARD },
15648 		{ "floor",						FUNCTION_FLOOR },
15649 		{ "fma",						FUNCTION_FMA },
15650 		{ "fract",						FUNCTION_FRACT },
15651 		{ "frexp",						FUNCTION_FREXP },
15652 		{ "greaterthan",				FUNCTION_GREATERTHAN },
15653 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
15654 		{ "inverse",					FUNCTION_INVERSE },
15655 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
15656 		{ "ldexp",						FUNCTION_LDEXP },
15657 		{ "lessthan",					FUNCTION_LESSTHAN },
15658 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
15659 		{ "length",						FUNCTION_LENGTH },
15660 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
15661 		{ "max",						FUNCTION_MAX },
15662 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
15663 		{ "min",						FUNCTION_MIN },
15664 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
15665 		{ "mix",						FUNCTION_MIX },
15666 		{ "mod",						FUNCTION_MOD },
15667 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
15668 		{ "modf",						FUNCTION_MODF },
15669 		{ "normalize",					FUNCTION_NORMALIZE },
15670 		{ "notequal",					FUNCTION_NOTEQUAL },
15671 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
15672 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
15673 		{ "reflect",					FUNCTION_REFLECT },
15674 		{ "refract",					FUNCTION_REFRACT },
15675 		{ "round",						FUNCTION_ROUND },
15676 		{ "roundeven",					FUNCTION_ROUNDEVEN },
15677 		{ "sign",						FUNCTION_SIGN },
15678 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
15679 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15680 		{ "sqrt",						FUNCTION_SQRT },
15681 		{ "step",						FUNCTION_STEP },
15682 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
15683 		{ "transpose",					FUNCTION_TRANSPOSE },
15684 		{ "trunc",						FUNCTION_TRUNC },
15685 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
15686 		{ "isnan",						FUNCTION_ISNAN },
15687 		{ "isinf",						FUNCTION_ISINF }
15688 	};
15689 
15690 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15691 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15692 	{
15693 		const BuiltinFunctions& bf = builtinFunctions[i];
15694 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15695 		{
15696 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
15697 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15698 		}
15699 	}
15700 	addChild(builin);
15701 }
15702 
15703 } /* glcts namespace */
15704