• 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 
3399 	default:
3400 		return GL_NONE;
3401 	}
3402 }
3403 
3404 /** Get primitive type drawn with DrawArrays
3405  *
3406  * @param shader_stage Tested shader stage id
3407  *
3408  * @return Primitive type
3409  **/
getDrawPrimitiveType(shaderStage shader_stage) const3410 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3411 {
3412 	switch (shader_stage)
3413 	{
3414 	case FRAGMENT_SHADER:
3415 		return GL_TRIANGLE_FAN;
3416 
3417 	case GEOMETRY_SHADER:
3418 	case VERTEX_SHADER:
3419 		return GL_POINTS;
3420 
3421 	case TESS_CTRL_SHADER:
3422 	case TESS_EVAL_SHADER:
3423 		return GL_PATCHES;
3424 
3425 	default:
3426 		return GL_NONE;
3427 	}
3428 }
3429 
3430 /** Get maximum allowed number of uniform components
3431  *
3432  * @param shader_stage Tested shader stage id
3433  *
3434  * @return Maxmimum uniform components
3435  **/
getMaxUniformComponents(shaderStage shader_stage) const3436 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3437 {
3438 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3439 	glw::GLint			  max_uniform_components = 0;
3440 	glw::GLenum			  pname					 = 0;
3441 
3442 	switch (shader_stage)
3443 	{
3444 	case COMPUTE_SHADER:
3445 		pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3446 		break;
3447 	case FRAGMENT_SHADER:
3448 		pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3449 		break;
3450 	case GEOMETRY_SHADER:
3451 		pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3452 		break;
3453 	case TESS_CTRL_SHADER:
3454 		pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3455 		break;
3456 	case TESS_EVAL_SHADER:
3457 		pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3458 		break;
3459 	case VERTEX_SHADER:
3460 		pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3461 		break;
3462 	}
3463 
3464 	gl.getIntegerv(pname, &max_uniform_components);
3465 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3466 
3467 	return max_uniform_components;
3468 }
3469 
3470 /** Get maximum size allowed for an uniform block
3471  *
3472  * @return Maxmimum uniform block size
3473  **/
getMaxUniformBlockSize() const3474 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3475 {
3476 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3477 	glw::GLint			  max_uniform_block_size = 0;
3478 
3479 	gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3480 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3481 
3482 	return max_uniform_block_size;
3483 }
3484 
3485 /** Get number of components required to store single uniform of given type
3486  *
3487  * @param uniform_type Tested uniform type
3488  *
3489  * @return Number of components
3490  **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3491 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3492 {
3493 	static const glw::GLuint type_size	 = 2; /* double takes 2 N */
3494 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3495 
3496 	if (1 == uniform_type.m_n_columns)
3497 	{
3498 		return type_size * column_length;
3499 	}
3500 	else
3501 	{
3502 		const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3503 
3504 		return alignment * uniform_type.m_n_columns;
3505 	}
3506 }
3507 
3508 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3509  *
3510  * @param uniform_type Tested uniform type
3511  *
3512  * @return Size of a single member
3513  **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3514 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3515 {
3516 	static const glw::GLuint vec4_size	 = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3517 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3518 
3519 	/** Size for a layout(std140, column_major) uniform_type uniform[] **/
3520 	return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3521 }
3522 
3523 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3524  *
3525  * @param shader_stage Tested shader stage id
3526  * @param uniform_type Tested uniform type
3527  *
3528  * @return Number of components
3529  **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3530 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage				shader_stage,
3531 												  const uniformTypeDetails& uniform_type) const
3532 {
3533 	const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
3534 	const glw::GLuint required_components	  = getRequiredComponentsNumber(uniform_type);
3535 	const glw::GLuint n_uniforms			   = max_uniform_components / required_components;
3536 	const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
3537 	const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3538 	const glw::GLuint max_uniforms			   = max_uniform_block_size / uniform_type_member_size;
3539 
3540 	return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3541 }
3542 
3543 /** Get name of shader stage
3544  *
3545  * @param shader_stage Tested shader stage id
3546  *
3547  * @return Name
3548  **/
getShaderStageName(shaderStage shader_stage) const3549 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3550 {
3551 	switch (shader_stage)
3552 	{
3553 	case COMPUTE_SHADER:
3554 		return "compute shader";
3555 	case FRAGMENT_SHADER:
3556 		return "fragment shader";
3557 	case GEOMETRY_SHADER:
3558 		return "geometry shader";
3559 	case TESS_CTRL_SHADER:
3560 		return "tesselation control shader";
3561 	case TESS_EVAL_SHADER:
3562 		return "tesselation evaluation shader";
3563 	case VERTEX_SHADER:
3564 		return "vertex shader";
3565 	}
3566 
3567 	return 0;
3568 }
3569 
3570 /** Inspect program to get: buffer_size, offset, strides and block index
3571  *
3572  * @param program_id          Program id
3573  * @param out_buffer_size     Size of uniform buffer
3574  * @param out_uniform_details Uniform offset and strides
3575  * @param uniform_block_index Uniform block index
3576  **/
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) const3577 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3578 										const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3579 										uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const
3580 {
3581 	glw::GLint				 array_stride = 0;
3582 	std::vector<glw::GLchar> extracted_uniform_name;
3583 	const glw::Functions&	gl			   = m_context.getRenderContext().getFunctions();
3584 	glw::GLuint				 index		   = 0;
3585 	glw::GLint				 matrix_stride = 0;
3586 	glw::GLint				 offset		   = 0;
3587 	glw::GLsizei			 size		   = 0;
3588 	glw::GLenum				 type		   = 0;
3589 	const glw::GLchar*		 uniform_name  = 0;
3590 	std::string				 uniform_name_str;
3591 	std::stringstream		 uniform_name_stream;
3592 
3593 	/* Get index of uniform block */
3594 	uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3595 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3596 
3597 	if (GL_INVALID_INDEX == uniform_block_index)
3598 	{
3599 		TCU_FAIL("Unifom block is inactive");
3600 	}
3601 
3602 	/* Get size of uniform block */
3603 	gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3604 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3605 
3606 	if (0 == out_buffer_size)
3607 	{
3608 		TCU_FAIL("Unifom block size is 0");
3609 	}
3610 
3611 	/* Prepare uniform name */
3612 	uniform_name_stream << "uniform_array";
3613 
3614 	uniform_name_str = uniform_name_stream.str();
3615 	uniform_name	 = uniform_name_str.c_str();
3616 
3617 	/* Get index of uniform */
3618 	gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3619 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3620 
3621 	if (GL_INVALID_INDEX == index)
3622 	{
3623 		TCU_FAIL("Unifom is inactive");
3624 	}
3625 
3626 	/* Verify getActiveUniform results */
3627 	extracted_uniform_name.resize(uniform_name_str.length() * 2);
3628 
3629 	gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3630 						&extracted_uniform_name[0]);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3632 
3633 	if ((n_uniforms != size) || (uniform_type.m_type != type))
3634 	{
3635 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3636 											<< " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3637 											<< " expected: " << uniform_type.m_type
3638 											<< ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3639 
3640 		TCU_FAIL("Invalid GetActiveUniform results");
3641 	}
3642 
3643 	/* Get offset of uniform */
3644 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3645 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3646 
3647 	if (-1 == offset)
3648 	{
3649 		TCU_FAIL("Unifom has invalid offset");
3650 	}
3651 
3652 	out_uniform_details.m_offset = offset;
3653 
3654 	/* Get matrix stride of uniform */
3655 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3656 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3657 
3658 	if (-1 == matrix_stride)
3659 	{
3660 		TCU_FAIL("Unifom has invalid matrix stride");
3661 	}
3662 
3663 	out_uniform_details.m_matrix_stride = matrix_stride;
3664 
3665 	/* Get array stride of uniform */
3666 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3667 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3668 
3669 	if (-1 == matrix_stride)
3670 	{
3671 		TCU_FAIL("Unifom has invalid matrix stride");
3672 	}
3673 
3674 	out_uniform_details.m_array_stride = array_stride;
3675 }
3676 
3677 /** Prepare source code for "boilerplate" shaders
3678  *
3679  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3680  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3681  * @param out_source_code          Source code
3682  **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3683 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3684 												  const glw::GLchar* stage_specific_main_body,
3685 												  std::string&		 out_source_code) const
3686 {
3687 	/* Shader template */
3688 	static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3689 																 "\n"
3690 																 "precision highp float;\n"
3691 																 "\n"
3692 																 "STAGE_SPECIFIC_LAYOUT"
3693 																 "void main()\n"
3694 																 "{\n"
3695 																 "STAGE_SPECIFIC_MAIN_BODY"
3696 																 "}\n"
3697 																 "\n";
3698 
3699 	std::string string = boilerplate_shader_template_code;
3700 
3701 	/* Tokens */
3702 	static const glw::GLchar* body_token   = "STAGE_SPECIFIC_MAIN_BODY";
3703 	static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3704 
3705 	size_t search_position = 0;
3706 
3707 	/* Replace tokens */
3708 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3709 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3710 
3711 	/* Store resuls */
3712 	out_source_code = string;
3713 }
3714 
3715 /** Prepare program for given combination of shader stage and uniform type
3716  *
3717  * @param shader_stage     Shader stage
3718  * @param uniform_type     Uniform type
3719  * @param out_program_info Instance of programInfo
3720  **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3721 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3722 										Utils::programInfo& out_program_info) const
3723 {
3724 	/* Stage specific layouts */
3725 	static const glw::GLchar* geometry_shader_layout_code = "layout(points)                   in;\n"
3726 															"layout(points, max_vertices = 1) out;\n"
3727 															"\n";
3728 
3729 	static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3730 															 "\n";
3731 
3732 	static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3733 															 "\n";
3734 
3735 	/* Stage specific main body */
3736 	static const glw::GLchar* boilerplate_fragment_shader_body_code = "    discard;\n";
3737 
3738 	static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
3739 																	   "    gl_TessLevelOuter[1] = 1.0;\n"
3740 																	   "    gl_TessLevelOuter[2] = 1.0;\n"
3741 																	   "    gl_TessLevelOuter[3] = 1.0;\n"
3742 																	   "    gl_TessLevelInner[0] = 1.0;\n"
3743 																	   "    gl_TessLevelInner[1] = 1.0;\n";
3744 
3745 	static const glw::GLchar* boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
3746 
3747 	static const glw::GLchar* corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
3748 															   "    {\n"
3749 															   "        gl_Position = vec4(-1, -1, 0, 1);\n"
3750 															   "    }\n"
3751 															   "    else if (1 == gl_VertexID)\n"
3752 															   "    {\n"
3753 															   "        gl_Position = vec4(-1, 1, 0, 1);\n"
3754 															   "    }\n"
3755 															   "    else if (2 == gl_VertexID)\n"
3756 															   "    {\n"
3757 															   "        gl_Position = vec4(1, 1, 0, 1);\n"
3758 															   "    }\n"
3759 															   "    else if (3 == gl_VertexID)\n"
3760 															   "    {\n"
3761 															   "        gl_Position = vec4(1, -1, 0, 1);\n"
3762 															   "    }\n";
3763 
3764 	static const glw::GLchar* passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
3765 
3766 	static const glw::GLchar* test_shader_body_code = "\n    result = verification_result;\n";
3767 
3768 	static const glw::GLchar* test_geometry_shader_body_code = "\n    result = verification_result;\n"
3769 															   "\n"
3770 															   "    EmitVertex();\n"
3771 															   "    EndPrimitive();\n";
3772 
3773 	static const glw::GLchar* test_tess_ctrl_shader_body_code =
3774 		"\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
3775 		"\n"
3776 		"    gl_TessLevelOuter[0] = 1.0;\n"
3777 		"    gl_TessLevelOuter[1] = 1.0;\n"
3778 		"    gl_TessLevelOuter[2] = 1.0;\n"
3779 		"    gl_TessLevelOuter[3] = 1.0;\n"
3780 		"    gl_TessLevelInner[0] = 1.0;\n"
3781 		"    gl_TessLevelInner[1] = 1.0;\n";
3782 
3783 	/* In variables */
3784 	static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
3785 
3786 	/* Out variables */
3787 	static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3788 
3789 	static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3790 
3791 	static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3792 
3793 	/* Varying name */
3794 	static const glw::GLchar* varying_name = "result";
3795 	glw::GLuint				  n_varyings   = 1;
3796 
3797 	/* Storage for ready shaders */
3798 	std::string compute_shader_code;
3799 	std::string fragment_shader_code;
3800 	std::string geometry_shader_code;
3801 	std::string tess_ctrl_shader_code;
3802 	std::string tess_eval_shader_code;
3803 	std::string vertex_shader_code;
3804 
3805 	/* Storage for uniform definition and verification code */
3806 	std::string uniform_definitions;
3807 	std::string uniform_verification;
3808 
3809 	/* Get uniform definition and verification code */
3810 	prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3811 	prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3812 
3813 	/* Prepare vertex shader */
3814 	switch (shader_stage)
3815 	{
3816 	case FRAGMENT_SHADER:
3817 
3818 		prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3819 
3820 		break;
3821 
3822 	case GEOMETRY_SHADER:
3823 	case TESS_CTRL_SHADER:
3824 	case TESS_EVAL_SHADER:
3825 
3826 		prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3827 
3828 		break;
3829 
3830 	case VERTEX_SHADER:
3831 
3832 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3833 						  test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3834 						  test_shader_body_code /* body */, vertex_shader_code);
3835 
3836 		break;
3837 
3838 	default:
3839 		break;
3840 	}
3841 
3842 	/* Prepare fragment shader */
3843 	switch (shader_stage)
3844 	{
3845 	case FRAGMENT_SHADER:
3846 
3847 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3848 						  test_fragment_shader_out_variable /* out var */,
3849 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3850 						  fragment_shader_code);
3851 
3852 		break;
3853 
3854 	case GEOMETRY_SHADER:
3855 	case TESS_CTRL_SHADER:
3856 	case TESS_EVAL_SHADER:
3857 	case VERTEX_SHADER:
3858 
3859 		prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3860 								 fragment_shader_code);
3861 
3862 		break;
3863 
3864 	default:
3865 		break;
3866 	}
3867 
3868 	/* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3869 	switch (shader_stage)
3870 	{
3871 	case COMPUTE_SHADER:
3872 
3873 		prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3874 
3875 		break;
3876 
3877 	case GEOMETRY_SHADER:
3878 
3879 		prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3880 						  "" /* in var */, test_shader_out_variable /* out var */,
3881 						  uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3882 						  geometry_shader_code);
3883 
3884 		break;
3885 
3886 	case TESS_CTRL_SHADER:
3887 
3888 		prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3889 						  "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3890 						  uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3891 						  tess_ctrl_shader_code);
3892 
3893 		prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3894 						  test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3895 						  "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3896 						  tess_eval_shader_code);
3897 
3898 		break;
3899 
3900 	case TESS_EVAL_SHADER:
3901 
3902 		prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3903 								 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3904 
3905 		prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3906 						  "" /* in var */, test_shader_out_variable /* out var */,
3907 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3908 						  tess_eval_shader_code);
3909 
3910 		break;
3911 
3912 	default:
3913 		break;
3914 	}
3915 
3916 	/* Select shaders that will be used by program */
3917 	const glw::GLchar* cs_c_str  = 0;
3918 	const glw::GLchar* fs_c_str  = 0;
3919 	const glw::GLchar* gs_c_str  = 0;
3920 	const glw::GLchar* tcs_c_str = 0;
3921 	const glw::GLchar* tes_c_str = 0;
3922 	const glw::GLchar* vs_c_str  = 0;
3923 
3924 	if (false == compute_shader_code.empty())
3925 	{
3926 		cs_c_str = compute_shader_code.c_str();
3927 	}
3928 
3929 	if (false == fragment_shader_code.empty())
3930 	{
3931 		fs_c_str = fragment_shader_code.c_str();
3932 	}
3933 
3934 	if (false == geometry_shader_code.empty())
3935 	{
3936 		gs_c_str = geometry_shader_code.c_str();
3937 	}
3938 
3939 	if (false == tess_ctrl_shader_code.empty())
3940 	{
3941 		tcs_c_str = tess_ctrl_shader_code.c_str();
3942 	}
3943 
3944 	if (false == tess_eval_shader_code.empty())
3945 	{
3946 		tes_c_str = tess_eval_shader_code.c_str();
3947 	}
3948 
3949 	if (false == vertex_shader_code.empty())
3950 	{
3951 		vs_c_str = vertex_shader_code.c_str();
3952 	}
3953 
3954 	/* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3955 	if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3956 	{
3957 		n_varyings = 0;
3958 	}
3959 
3960 	/* Build */
3961 	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);
3962 }
3963 
3964 /** Prepare collection of tested shader stages
3965  *
3966  */
prepareShaderStages()3967 void GPUShaderFP64Test2::prepareShaderStages()
3968 {
3969 	/* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3970 	if (0 != m_pDispatchCompute)
3971 	{
3972 		m_shader_stages.push_back(COMPUTE_SHADER);
3973 	}
3974 
3975 	m_shader_stages.push_back(FRAGMENT_SHADER);
3976 	m_shader_stages.push_back(GEOMETRY_SHADER);
3977 	m_shader_stages.push_back(TESS_CTRL_SHADER);
3978 	m_shader_stages.push_back(TESS_EVAL_SHADER);
3979 	m_shader_stages.push_back(VERTEX_SHADER);
3980 }
3981 
3982 /** Prepare source code for "tested" shader stage
3983  *
3984  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3985  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
3986  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
3987  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
3988  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
3989  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3990  * @param out_source_code          Shader source code
3991  **/
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) const3992 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
3993 										   const glw::GLchar* uniform_definitions,
3994 										   const glw::GLchar* in_variable_definitions,
3995 										   const glw::GLchar* out_variable_definitions,
3996 										   const glw::GLchar* uniform_verification,
3997 										   const glw::GLchar* stage_specific_main_body,
3998 										   std::string&		  out_source_code) const
3999 {
4000 	/* Shader template */
4001 	static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4002 														  "\n"
4003 														  "precision highp float;\n"
4004 														  "\n"
4005 														  "STAGE_SPECIFIC_LAYOUT"
4006 														  "UNIFORM_DEFINITIONS"
4007 														  "IN_VARIABLE_DEFINITION"
4008 														  "OUT_VARIABLE_DEFINITION"
4009 														  "\n"
4010 														  "void main()\n"
4011 														  "{\n"
4012 														  "UNIFORM_VERIFICATION"
4013 														  "STAGE_SPECIFIC_MAIN_BODY"
4014 														  "}\n"
4015 														  "\n";
4016 
4017 	std::string string = test_shader_template_code;
4018 
4019 	/* Tokens */
4020 	static const glw::GLchar* body_token	= "STAGE_SPECIFIC_MAIN_BODY";
4021 	static const glw::GLchar* in_var_token  = "IN_VARIABLE_DEFINITION";
4022 	static const glw::GLchar* layout_token  = "STAGE_SPECIFIC_LAYOUT";
4023 	static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4024 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4025 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4026 
4027 	size_t search_position = 0;
4028 
4029 	/* Replace tokens */
4030 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4031 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4032 	Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4033 	Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4034 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4035 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4036 
4037 	/* Store resuls */
4038 	out_source_code = string;
4039 }
4040 
4041 /** Prepare source code for "tested" compute shaders
4042  *
4043  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
4044  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4045  * @param out_source_code      Source code
4046  **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4047 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4048 												  const glw::GLchar* uniform_verification,
4049 												  std::string&		 out_source_code) const
4050 {
4051 	/* Shader template */
4052 	static const glw::GLchar* test_shader_template_code =
4053 		"#version 420 core\n"
4054 		"#extension GL_ARB_compute_shader          : require\n"
4055 		"#extension GL_ARB_shader_image_load_store : require\n"
4056 		"\n"
4057 		"precision highp float;\n"
4058 		"\n"
4059 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4060 		"\n"
4061 		"UNIFORM_DEFINITIONS"
4062 		"layout(r32i) writeonly uniform iimage2D result;\n"
4063 		"\n"
4064 		"void main()\n"
4065 		"{\n"
4066 		"UNIFORM_VERIFICATION"
4067 		"\n"
4068 		"    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4069 		"}\n"
4070 		"\n";
4071 
4072 	std::string string = test_shader_template_code;
4073 
4074 	/* Tokens */
4075 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4076 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4077 
4078 	size_t search_position = 0;
4079 
4080 	/* Replace tokens */
4081 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4082 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083 
4084 	/* Store resuls */
4085 	out_source_code = string;
4086 }
4087 
4088 /** Prepare source code which defines uniforms for tested shader stage
4089  *
4090  * @param shader_stage    Shader stage id
4091  * @param uniform_type    Details of uniform type
4092  * @param out_source_code Source code
4093  **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4094 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4095 												   std::string& out_source_code) const
4096 {
4097 	const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4098 	std::stringstream stream;
4099 
4100 	/*
4101 	 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4102 	 * {
4103 	 *     TYPE_NAME uniform_array[N_UNIFORMS];
4104 	 * };
4105 	 */
4106 	stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4107 																   "{\n";
4108 
4109 	stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4110 
4111 	stream << "};\n\n";
4112 
4113 	out_source_code = stream.str();
4114 }
4115 
4116 /** Prepare uniform buffer for test
4117  *
4118  * @param shader_stage Shader stage id
4119  * @param uniform_type Details of uniform type
4120  * @param program_info Program object info
4121  **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4122 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4123 										 const Utils::programInfo& program_info) const
4124 {
4125 	glw::GLint				  buffer_size	 = 0;
4126 	glw::GLuint				  element_ordinal = 1;
4127 	const glw::Functions&	 gl			  = m_context.getRenderContext().getFunctions();
4128 	const glw::GLuint		  n_columns		  = uniform_type.m_n_columns;
4129 	const glw::GLuint		  n_rows		  = uniform_type.m_n_rows;
4130 	const glw::GLuint		  n_elements	  = n_columns * n_rows;
4131 	uniformDetails			  uniform_details;
4132 	const glw::GLuint		  program_id = program_info.m_program_object_id;
4133 	const glw::GLint		  n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4134 	std::vector<glw::GLubyte> uniform_buffer_data;
4135 	glw::GLuint				  uniform_block_index = 0;
4136 
4137 	/* Get uniform details */
4138 	inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4139 
4140 	/* Uniform offset and strides */
4141 	const glw::GLuint array_stride   = uniform_details.m_array_stride;
4142 	const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
4143 	const glw::GLuint uniform_offset = uniform_details.m_offset;
4144 
4145 	/* Prepare storage for buffer data */
4146 	uniform_buffer_data.resize(buffer_size);
4147 
4148 	/* Prepare uniform data */
4149 	for (glw::GLint i = 0; i < n_uniforms; ++i)
4150 	{
4151 		const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4152 
4153 		for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4154 		{
4155 			const glw::GLuint   column		 = element / n_rows;
4156 			const glw::GLuint   column_elem  = element % n_rows;
4157 			const glw::GLdouble value		 = element_ordinal;
4158 			const glw::GLuint   value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4159 																	  column_elem * sizeof(glw::GLdouble));
4160 			glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4161 
4162 			*value_dst = value;
4163 		}
4164 	}
4165 
4166 	/* Update uniform buffer with new set of data */
4167 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4168 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4169 
4170 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4171 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4172 
4173 	/* Bind uniform block to uniform buffer */
4174 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4175 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4176 
4177 	gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4178 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4179 }
4180 
4181 /** Prepare collection of tested uniform types
4182  *
4183  **/
prepareUniformTypes()4184 void GPUShaderFP64Test2::prepareUniformTypes()
4185 {
4186 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4187 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4188 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4189 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4190 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4191 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4192 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4193 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4194 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4195 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4196 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4197 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4198 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4199 }
4200 
4201 /** Prepare source code that verifes uniform values
4202  *
4203  * @param shader_stage    Shader stage id
4204  * @param uniform_type    Details of uniform type
4205  * @param out_source_code Source code
4206  **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4207 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4208 													std::string& out_source_code) const
4209 {
4210 	glw::GLuint		  element_ordinal = 1;
4211 	const glw::GLuint n_columns		  = uniform_type.m_n_columns;
4212 	const glw::GLuint n_rows		  = uniform_type.m_n_rows;
4213 	const glw::GLuint n_elements	  = n_columns * n_rows;
4214 	const glw::GLuint n_uniforms	  = getAmountUniforms(shader_stage, uniform_type);
4215 	std::stringstream stream;
4216 
4217 	/*
4218 	 * int verification_result = M_RESULT_SUCCESS;
4219 	 *
4220 	 * for (int i = 0; i < N_UNIFORMS; ++i)
4221 	 * {
4222 	 *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4223 	 *     {
4224 	 *         verification_result = M_RESULT_FAILURE
4225 	 *     }
4226 	 * }
4227 	 */
4228 	stream << "    int verification_result = " << m_result_success << ";\n"
4229 																	  "\n"
4230 																	  "    for (int i = 0; i < "
4231 		   << n_uniforms << "; ++i)\n"
4232 							"    {\n"
4233 							"        if ("
4234 		   << uniform_type.m_type_name << "(";
4235 
4236 	for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4237 	{
4238 		stream << "i * (" << n_elements << ") + " << element + 1;
4239 
4240 		if (n_elements != element + 1)
4241 		{
4242 			stream << ", ";
4243 		}
4244 	}
4245 
4246 	stream << ") != uniform_array[i])\n"
4247 			  "        {\n"
4248 			  "           verification_result = "
4249 		   << m_result_failure << ";\n"
4250 								  "        }\n"
4251 								  "    }\n";
4252 
4253 	out_source_code = stream.str();
4254 }
4255 
4256 /** Execute test for given combination of "tested" shader stage and uniform type
4257  *
4258  * @param shader_stage Tested shader stage id
4259  * @param uniform_type Tested uniform type
4260  *
4261  * @return true if test passed, false otherwise
4262  **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4263 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4264 {
4265 	const glw::GLenum		draw_primitive = getDrawPrimitiveType(shader_stage);
4266 	static const glw::GLint first_vertex   = 0;
4267 	const glw::Functions&   gl			   = m_context.getRenderContext().getFunctions();
4268 	const glw::GLsizei		n_vertices	 = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4269 	Utils::programInfo		program_info(m_context);
4270 	bool					result = true;
4271 
4272 	/* Prepare program */
4273 	prepareProgram(shader_stage, uniform_type, program_info);
4274 
4275 	gl.useProgram(program_info.m_program_object_id);
4276 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4277 
4278 	/* Prepare uniform buffer and bind it with uniform block */
4279 	prepareUniforms(shader_stage, uniform_type, program_info);
4280 
4281 	/* Prepare storage for test results */
4282 	testBegin(program_info.m_program_object_id, shader_stage);
4283 
4284 	/* Execute */
4285 	if (COMPUTE_SHADER == shader_stage)
4286 	{
4287 		m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4288 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4289 	}
4290 	else
4291 	{
4292 		gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4293 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4294 	}
4295 
4296 	/* Clean after test */
4297 	testEnd(shader_stage);
4298 
4299 	/* Check results */
4300 	if (false == verifyResults(shader_stage))
4301 	{
4302 		m_context.getTestContext().getLog()
4303 			<< tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4304 			<< ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4305 
4306 		result = false;
4307 	}
4308 
4309 	return result;
4310 }
4311 
4312 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4313  *
4314  * @param program_id   Program object id
4315  * @param shader_stage Tested shader stage id
4316  **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4317 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4318 {
4319 	std::vector<glw::GLint> buffer_data;
4320 	const glw::GLenum		captured_primitive = getCapturedPrimitiveType(shader_stage);
4321 	const glw::Functions&   gl				   = m_context.getRenderContext().getFunctions();
4322 
4323 	/* Prepare buffer filled with m_result_failure */
4324 	buffer_data.resize(m_n_captured_results);
4325 	for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4326 	{
4327 		buffer_data[i] = m_result_failure;
4328 	}
4329 
4330 	/* Prepare buffer for test results */
4331 	switch (shader_stage)
4332 	{
4333 	case GEOMETRY_SHADER:
4334 	case TESS_CTRL_SHADER:
4335 	case TESS_EVAL_SHADER:
4336 	case VERTEX_SHADER:
4337 
4338 		/* Verify getTransformFeedbackVarying results */
4339 		{
4340 			glw::GLsizei size = 0;
4341 			glw::GLenum  type = 0;
4342 			glw::GLchar  name[16];
4343 
4344 			gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4345 										   name);
4346 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4347 
4348 			if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4349 			{
4350 				m_context.getTestContext().getLog()
4351 					<< tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4352 					<< " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4353 					<< ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4354 
4355 				TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4356 			}
4357 		}
4358 
4359 		/* Create/clean transform feedback buffer */
4360 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4361 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4362 
4363 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4364 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4365 
4366 		/* Set up transform feedback buffer */
4367 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4368 						   m_transform_feedback_buffer_size);
4369 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4370 
4371 		gl.beginTransformFeedback(captured_primitive);
4372 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4373 
4374 		break;
4375 
4376 	case FRAGMENT_SHADER:
4377 
4378 		/* Clean texture */
4379 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4380 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4381 
4382 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4383 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4385 
4386 		/* Set up texture as color attachment 0 */
4387 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4388 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4389 
4390 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4391 		GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4392 
4393 		gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4394 		GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4395 
4396 		break;
4397 
4398 	case COMPUTE_SHADER:
4399 
4400 		/* Clean texture */
4401 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4402 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4403 
4404 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4405 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4406 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4407 
4408 		glw::GLint location = gl.getUniformLocation(program_id, "result");
4409 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4410 
4411 		if (-1 == location)
4412 		{
4413 			TCU_FAIL("Inactive uniform \"result\"");
4414 		}
4415 
4416 		gl.uniform1i(location, 0 /* first image unit */);
4417 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4418 
4419 		/* Bind texture to first image unit */
4420 		gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4421 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4422 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4423 
4424 		break;
4425 	}
4426 }
4427 
4428 /** Unbind transform feedback buffer, framebuffer or image unit
4429  *
4430  * @param shader_stage Tested shader stage id
4431  **/
testEnd(shaderStage shader_stage) const4432 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4433 {
4434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4435 
4436 	switch (shader_stage)
4437 	{
4438 	case GEOMETRY_SHADER:
4439 	case TESS_CTRL_SHADER:
4440 	case TESS_EVAL_SHADER:
4441 	case VERTEX_SHADER:
4442 
4443 		gl.endTransformFeedback();
4444 
4445 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4446 
4447 		break;
4448 
4449 	case FRAGMENT_SHADER:
4450 
4451 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4452 								0 /* level */);
4453 
4454 		gl.bindTexture(GL_TEXTURE_2D, 0);
4455 
4456 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4457 
4458 		break;
4459 
4460 	case COMPUTE_SHADER:
4461 
4462 		gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4463 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4464 
4465 		break;
4466 	}
4467 }
4468 
4469 /** Initialize OpenGL objects for test
4470  *
4471  **/
testInit()4472 void GPUShaderFP64Test2::testInit()
4473 {
4474 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4475 
4476 	/* The test is in 4.0 group. However:
4477 	 * - compute_shader is core since 4.3
4478 	 * - compute_shader require at least version 4.2 of GL */
4479 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4480 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4481 	{
4482 		m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4483 	}
4484 
4485 	/* Tesselation patch set up */
4486 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
4487 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4488 
4489 	/* Generate FBO */
4490 	gl.genFramebuffers(1, &m_framebuffer_id);
4491 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4492 
4493 	/* Prepare texture */
4494 	gl.genTextures(1, &m_texture_id);
4495 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4496 
4497 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4498 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4499 
4500 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4501 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4502 
4503 	/* Prepare transform feedback buffer */
4504 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
4505 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4506 
4507 	/* Generate uniform buffer */
4508 	gl.genBuffers(1, &m_uniform_buffer_id);
4509 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4510 
4511 	/* Prepare VAO */
4512 	gl.genVertexArrays(1, &m_vertex_array_object_id);
4513 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4514 
4515 	gl.bindVertexArray(m_vertex_array_object_id);
4516 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4517 }
4518 
4519 /** Result verification, expected result is that whole buffer is filled with m_result_success
4520  *
4521  * @param shader_stage Tested shader stage id
4522  **/
verifyResults(shaderStage shader_stage) const4523 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4524 {
4525 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4526 
4527 	if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4528 	{
4529 		/* Verify contents of texture */
4530 
4531 		/* Prepare storage for testure data */
4532 		std::vector<glw::GLint> image_data;
4533 		image_data.resize(m_texture_width * m_texture_height);
4534 
4535 		/* Get texture contents */
4536 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4537 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4538 
4539 		gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4540 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4541 
4542 		for (glw::GLuint y = 0; y < m_texture_width; ++y)
4543 		{
4544 			for (glw::GLuint x = 0; x < m_texture_height; ++x)
4545 			{
4546 				const glw::GLuint offset = y * m_texture_width + x;
4547 				const glw::GLint  value  = image_data[offset];
4548 
4549 				if (m_result_success != value)
4550 				{
4551 					m_context.getTestContext().getLog()
4552 						<< tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4553 						<< tcu::TestLog::EndMessage;
4554 
4555 					return false;
4556 				}
4557 			}
4558 		}
4559 
4560 		return true;
4561 	}
4562 	else
4563 	{
4564 		/* Verify contents of transform feedback buffer */
4565 
4566 		bool result = true;
4567 
4568 		/* Get transform feedback data */
4569 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4570 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4571 
4572 		glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4573 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4574 
4575 		for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4576 		{
4577 			const glw::GLint value = feedback_data[i];
4578 
4579 			if (m_result_success != value)
4580 			{
4581 				m_context.getTestContext().getLog() << tcu::TestLog::Message
4582 													<< "Error. Transform feedback buffer contents are wrong at " << i
4583 													<< tcu::TestLog::EndMessage;
4584 
4585 				result = false;
4586 				break;
4587 			}
4588 		}
4589 
4590 		/* Unmap transform feedback buffer */
4591 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4592 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4593 
4594 		return result;
4595 	}
4596 }
4597 
4598 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4599 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4600 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4601 
4602 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name			 = "UniformBlock";
4603 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4604 
4605 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
4606 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result	= "gs_fs_gs_result";
4607 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
4608 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
4609 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result	= "gs_fs_vs_result";
4610 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4611 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
4612 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
4613 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
4614 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
4615 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
4616 
4617 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4618 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset			 = -1;
4619 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride	= -1;
4620 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4621 
4622 /** Constructor
4623  *
4624  * @param context Test context
4625  **/
GPUShaderFP64Test3(deqp::Context & context)4626 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4627 	: TestCase(context, "named_uniform_blocks",
4628 			   "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4629 {
4630 	/* Nothing to be done */
4631 }
4632 
4633 /** Deinitialize test
4634  *
4635  **/
deinit()4636 void GPUShaderFP64Test3::deinit()
4637 {
4638 	/* GL entry points */
4639 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4640 
4641 	/* Clean programs */
4642 	m_packed_program.deinit(m_context);
4643 	m_shared_program.deinit(m_context);
4644 	m_std140_program.deinit(m_context);
4645 
4646 	/* Clean frambuffer */
4647 	if (0 != m_framebuffer_id)
4648 	{
4649 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4650 		gl.deleteFramebuffers(1, &m_framebuffer_id);
4651 
4652 		m_framebuffer_id = 0;
4653 	}
4654 
4655 	/* Clean texture */
4656 	if (0 != m_color_texture_id)
4657 	{
4658 		gl.bindTexture(GL_TEXTURE_2D, 0);
4659 		gl.deleteTextures(1, &m_color_texture_id);
4660 
4661 		m_color_texture_id = 0;
4662 	}
4663 
4664 	/* Clean buffers */
4665 	if (0 != m_transform_feedback_buffer_id)
4666 	{
4667 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4668 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4669 
4670 		m_transform_feedback_buffer_id = 0;
4671 	}
4672 
4673 	if (0 != m_uniform_buffer_id)
4674 	{
4675 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4676 		gl.deleteBuffers(1, &m_uniform_buffer_id);
4677 
4678 		m_uniform_buffer_id = 0;
4679 	}
4680 
4681 	/* Clean VAO */
4682 	if (0 != m_vertex_array_object_id)
4683 	{
4684 		gl.bindVertexArray(0);
4685 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4686 
4687 		m_vertex_array_object_id = 0;
4688 	}
4689 }
4690 
4691 /** Execute test
4692  *
4693  * @return tcu::TestNode::STOP
4694  **/
iterate()4695 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4696 {
4697 	bool result = true;
4698 
4699 	/* Check if extension is supported */
4700 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4701 	{
4702 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4703 	}
4704 
4705 	/* Initialize test */
4706 	testInit();
4707 
4708 	/* Test "packed" uniform buffer layout */
4709 	if (false == test(PACKED))
4710 	{
4711 		result = false;
4712 	}
4713 
4714 	/* Test "shared" uniform buffer layout */
4715 	if (false == test(SHARED))
4716 	{
4717 		result = false;
4718 	}
4719 
4720 	/* Test "std140" uniform buffer layout */
4721 	if (false == test(STD140))
4722 	{
4723 		result = false;
4724 	}
4725 
4726 	/* Set result */
4727 	if (true == result)
4728 	{
4729 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4730 	}
4731 	else
4732 	{
4733 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4734 	}
4735 
4736 	/* Done */
4737 	return tcu::TestNode::STOP;
4738 }
4739 
4740 /** Constructor
4741  *
4742  **/
programInfo()4743 GPUShaderFP64Test3::programInfo::programInfo()
4744 	: m_fragment_shader_id(0)
4745 	, m_geometry_shader_id(0)
4746 	, m_program_object_id(0)
4747 	, m_tesselation_control_shader_id(0)
4748 	, m_tesselation_evaluation_shader_id(0)
4749 	, m_vertex_shader_id(0)
4750 	, m_buffer_size(0)
4751 	, m_uniform_block_index(0)
4752 {
4753 	/* Nothing to be done here */
4754 }
4755 
4756 /** Compile shader
4757  *
4758  * @param context     Test context
4759  * @param shader_id   Shader object id
4760  * @param shader_code Shader source code
4761  **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4762 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4763 											  const glw::GLchar* shader_code) const
4764 {
4765 	/* GL entry points */
4766 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4767 
4768 	/* Compilation status */
4769 	glw::GLint status = GL_FALSE;
4770 
4771 	/* Set source code */
4772 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4773 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4774 
4775 	/* Compile */
4776 	gl.compileShader(shader_id);
4777 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4778 
4779 	/* Get compilation status */
4780 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4781 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4782 
4783 	/* Log compilation error */
4784 	if (GL_TRUE != status)
4785 	{
4786 		glw::GLint				 length = 0;
4787 		std::vector<glw::GLchar> message;
4788 
4789 		/* Error log length */
4790 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4791 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4792 
4793 		/* Prepare storage */
4794 		message.resize(length);
4795 
4796 		/* Get error log */
4797 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4798 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4799 
4800 		/* Log */
4801 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4802 										  << &message[0] << "\nShader source\n"
4803 										  << shader_code << tcu::TestLog::EndMessage;
4804 
4805 		TCU_FAIL("Failed to compile shader");
4806 	}
4807 }
4808 
4809 /** Cleans program and attached shaders
4810  *
4811  * @param context Test context
4812  **/
deinit(deqp::Context & context)4813 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4814 {
4815 	/* GL entry points */
4816 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4817 
4818 	/* Restore default program */
4819 	gl.useProgram(0);
4820 
4821 	/* Clean program object */
4822 	if (0 != m_program_object_id)
4823 	{
4824 		gl.deleteProgram(m_program_object_id);
4825 		m_program_object_id = 0;
4826 	}
4827 
4828 	/* Clean shaders */
4829 	if (0 != m_fragment_shader_id)
4830 	{
4831 		gl.deleteShader(m_fragment_shader_id);
4832 		m_fragment_shader_id = 0;
4833 	}
4834 
4835 	if (0 != m_geometry_shader_id)
4836 	{
4837 		gl.deleteShader(m_geometry_shader_id);
4838 		m_geometry_shader_id = 0;
4839 	}
4840 
4841 	if (0 != m_tesselation_control_shader_id)
4842 	{
4843 		gl.deleteShader(m_tesselation_control_shader_id);
4844 		m_tesselation_control_shader_id = 0;
4845 	}
4846 
4847 	if (0 != m_tesselation_evaluation_shader_id)
4848 	{
4849 		gl.deleteShader(m_tesselation_evaluation_shader_id);
4850 		m_tesselation_evaluation_shader_id = 0;
4851 	}
4852 
4853 	if (0 != m_vertex_shader_id)
4854 	{
4855 		gl.deleteShader(m_vertex_shader_id);
4856 		m_vertex_shader_id = 0;
4857 	}
4858 }
4859 
4860 /** Build program and query for uniform layout
4861  *
4862  * @param context                            Test context
4863  * @param uniform_details                  Collection of uniform details
4864  * @param fragment_shader_code               Fragment shader source code
4865  * @param geometry_shader_code               Geometry shader source code
4866  * @param tesselation_control_shader_code    Tesselation control shader source code
4867  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4868  * @param vertex_shader_code                 Vertex shader source code
4869  **/
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)4870 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4871 										   const glw::GLchar* fragment_shader_code,
4872 										   const glw::GLchar* geometry_shader_code,
4873 										   const glw::GLchar* tesselation_control_shader_code,
4874 										   const glw::GLchar* tesselation_evaluation_shader_code,
4875 										   const glw::GLchar* vertex_shader_code)
4876 {
4877 	/* GL entry points */
4878 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4879 
4880 	/* Names of varyings to be captured with transform feedback */
4881 	static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4882 												  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4883 	static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4884 
4885 	/* Create shader objects */
4886 	m_fragment_shader_id			   = gl.createShader(GL_FRAGMENT_SHADER);
4887 	m_geometry_shader_id			   = gl.createShader(GL_GEOMETRY_SHADER);
4888 	m_tesselation_control_shader_id	= gl.createShader(GL_TESS_CONTROL_SHADER);
4889 	m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4890 	m_vertex_shader_id				   = gl.createShader(GL_VERTEX_SHADER);
4891 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4892 
4893 	/* Create program object */
4894 	m_program_object_id = gl.createProgram();
4895 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4896 
4897 	/* Set up names of varyings to be captured with transform feedback */
4898 	gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4899 	GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4900 
4901 	/* Compile shaders */
4902 	compile(context, m_fragment_shader_id, fragment_shader_code);
4903 	compile(context, m_geometry_shader_id, geometry_shader_code);
4904 	compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4905 	compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4906 	compile(context, m_vertex_shader_id, vertex_shader_code);
4907 
4908 	/* Link program */
4909 	link(context);
4910 
4911 	/* Inspect program object */
4912 	/* Get index of named uniform block */
4913 	m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4914 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4915 
4916 	if (GL_INVALID_INDEX == m_uniform_block_index)
4917 	{
4918 		TCU_FAIL("Unifom block is inactive");
4919 	}
4920 
4921 	/* Get size of named uniform block */
4922 	gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4923 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4924 
4925 	if (0 == m_buffer_size)
4926 	{
4927 		TCU_FAIL("Unifom block size is 0");
4928 	}
4929 
4930 	/* Get information about "double precision" uniforms */
4931 	for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4932 		 end != it; ++it)
4933 	{
4934 		const glw::GLchar* uniform_name = 0;
4935 		std::string		   uniform_name_str;
4936 		std::stringstream  uniform_name_stream;
4937 		glw::GLuint		   index		 = 0;
4938 		glw::GLint		   offset		 = 0;
4939 		glw::GLint		   matrix_stride = 0;
4940 
4941 		/* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4942 		uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4943 
4944 		uniform_name_str = uniform_name_stream.str();
4945 		uniform_name	 = uniform_name_str.c_str();
4946 
4947 		/* Get index of uniform */
4948 		gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4949 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4950 
4951 		if (GL_INVALID_INDEX == index)
4952 		{
4953 			TCU_FAIL("Unifom is inactive");
4954 		}
4955 
4956 		/* Get offset of uniform */
4957 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4958 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4959 
4960 		if (m_invalid_uniform_offset == offset)
4961 		{
4962 			TCU_FAIL("Unifom has invalid offset");
4963 		}
4964 
4965 		m_uniform_offsets.push_back(offset);
4966 
4967 		/* Get matrix stride of uniform */
4968 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4969 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4970 
4971 		if (m_invalid_uniform_matrix_stride == offset)
4972 		{
4973 			TCU_FAIL("Unifom has invalid matrix stride");
4974 		}
4975 
4976 		m_uniform_matrix_strides.push_back(matrix_stride);
4977 	}
4978 }
4979 
4980 /** Attach shaders and link program
4981  *
4982  * @param context Test context
4983  **/
link(deqp::Context & context) const4984 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4985 {
4986 	/* GL entry points */
4987 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4988 
4989 	/* Link status */
4990 	glw::GLint status = GL_FALSE;
4991 
4992 	/* Attach shaders */
4993 	gl.attachShader(m_program_object_id, m_fragment_shader_id);
4994 	gl.attachShader(m_program_object_id, m_geometry_shader_id);
4995 	gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
4996 	gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
4997 	gl.attachShader(m_program_object_id, m_vertex_shader_id);
4998 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
4999 
5000 	/* Link */
5001 	gl.linkProgram(m_program_object_id);
5002 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5003 
5004 	/* Get link status */
5005 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5006 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5007 
5008 	/* Log link error */
5009 	if (GL_TRUE != status)
5010 	{
5011 		glw::GLint				 length = 0;
5012 		std::vector<glw::GLchar> message;
5013 
5014 		/* Get error log length */
5015 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5016 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5017 
5018 		message.resize(length);
5019 
5020 		/* Get error log */
5021 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5022 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5023 
5024 		/* Log */
5025 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5026 										  << &message[0] << tcu::TestLog::EndMessage;
5027 
5028 		TCU_FAIL("Failed to link program");
5029 	}
5030 }
5031 
5032 /** Returns "predefined" values that will be used to fill uniform data
5033  *
5034  * @param type_ordinal Ordinal number of "double precision" uniform type
5035  * @param element      Index of element in uniform
5036  *
5037  * @return "Predefined" value
5038  **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5039 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5040 {
5041 	return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5042 		   ((m_base_element - (glw::GLdouble)element) / 4.0);
5043 }
5044 
5045 /** Returns a reference of programInfo instance specific for given buffer layout
5046  *
5047  * @param uniform_data_layout Buffer layout
5048  *
5049  * @return Reference to an instance of programInfo
5050  **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5051 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5052 {
5053 	const programInfo* program_info = 0;
5054 
5055 	switch (uniform_data_layout)
5056 	{
5057 	case PACKED:
5058 
5059 		program_info = &m_packed_program;
5060 
5061 		break;
5062 
5063 	case SHARED:
5064 
5065 		program_info = &m_shared_program;
5066 
5067 		break;
5068 
5069 	case STD140:
5070 
5071 		program_info = &m_std140_program;
5072 
5073 		break;
5074 	}
5075 
5076 	return *program_info;
5077 }
5078 
5079 /** Get "name" of buffer layout
5080  *
5081  * @param uniform_data_layout Buffer layout
5082  *
5083  * @return "Name" of layout
5084  **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5085 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5086 {
5087 	const glw::GLchar* layout = "";
5088 
5089 	switch (uniform_data_layout)
5090 	{
5091 	case PACKED:
5092 		layout = "packed";
5093 		break;
5094 	case SHARED:
5095 		layout = "shared";
5096 		break;
5097 	case STD140:
5098 		layout = "std140";
5099 		break;
5100 	}
5101 
5102 	return layout;
5103 }
5104 
5105 /** Prepare programInfo instance for specific buffer layout
5106  *
5107  * @param program_info        Instance of programInfo
5108  * @param uniform_data_layout Buffer layout
5109  **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5110 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5111 {
5112 	/* Storage for shader source code */
5113 	std::stringstream fragment_shader_code;
5114 	std::stringstream geometry_shader_code;
5115 	std::stringstream tess_control_shader_code;
5116 	std::stringstream tess_eval_shader_code;
5117 	std::stringstream vertex_shader_code;
5118 
5119 	/* Write preambles */
5120 	writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5121 	writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5122 	writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5123 	writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5124 	writePreamble(vertex_shader_code, VERTEX_SHADER);
5125 
5126 	/* Write definition of named uniform block */
5127 	writeUniformBlock(fragment_shader_code, uniform_data_layout);
5128 	writeUniformBlock(geometry_shader_code, uniform_data_layout);
5129 	writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5130 	writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5131 	writeUniformBlock(vertex_shader_code, uniform_data_layout);
5132 
5133 	/* Write definitions of varyings */
5134 	writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5135 	writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5136 	writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5137 	writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5138 	writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5139 
5140 	/* Write main routine */
5141 	writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5142 	writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5143 	writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5144 	writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5145 	writeMainBody(vertex_shader_code, VERTEX_SHADER);
5146 
5147 	/* Init programInfo instance */
5148 	program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5149 					  geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5150 					  tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5151 }
5152 
5153 /** Prepare uniform buffer
5154  *
5155  * @param program_info   Instance of programInfo
5156  * @param verify_offsets If uniform offsets should be verified against expected values
5157  *
5158  * @return false if uniform offsets verification result is failure, true otherwise
5159  **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5160 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5161 {
5162 	const glw::GLuint							buffer_size = program_info.m_buffer_size;
5163 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
5164 	bool										offset_verification_result = true;
5165 	glw::GLuint									type_ordinal			   = 1;
5166 	std::vector<uniformDetails>::const_iterator it_uniform_details		   = m_uniform_details.begin();
5167 	std::vector<glw::GLint>::const_iterator		it_uniform_offsets		   = program_info.m_uniform_offsets.begin();
5168 	std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5169 
5170 	/* Prepare storage for uniform buffer data */
5171 	std::vector<glw::GLubyte> buffer_data;
5172 	buffer_data.resize(buffer_size);
5173 
5174 	/* For each "double precision" uniform */
5175 	for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5176 		 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5177 	{
5178 		const glw::GLint  matrix_stride  = *it_uniform_matrix_strides;
5179 		const glw::GLuint n_columns		 = it_uniform_details->m_n_columns;
5180 		const glw::GLuint n_elements	 = it_uniform_details->m_n_elements;
5181 		const glw::GLuint column_length  = n_elements / n_columns;
5182 		const glw::GLint  uniform_offset = *it_uniform_offsets;
5183 
5184 		/* For each element of uniform */
5185 		for (glw::GLuint element = 0; element < n_elements; ++element)
5186 		{
5187 			const glw::GLuint   column		= element / column_length;
5188 			const glw::GLuint   column_elem = element % column_length;
5189 			const glw::GLdouble value		= getExpectedValue(type_ordinal, element);
5190 			const glw::GLuint   value_offset =
5191 				static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5192 
5193 			glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5194 
5195 			/* Store value */
5196 			*value_dst = value;
5197 		}
5198 
5199 		/* Uniform offset verification */
5200 		if (true == verify_offsets)
5201 		{
5202 			const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5203 
5204 			if (expected_offset != uniform_offset)
5205 			{
5206 				if (true == offset_verification_result)
5207 				{
5208 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5209 				}
5210 
5211 				m_context.getTestContext().getLog()
5212 					<< tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5213 					<< " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5214 					<< tcu::TestLog::EndMessage;
5215 
5216 				offset_verification_result = false;
5217 			}
5218 		}
5219 	}
5220 
5221 	/* Update uniform buffer with prepared data */
5222 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5223 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5224 
5225 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5226 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5227 
5228 	/* Bind uniform buffer as data source for named uniform block */
5229 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5230 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5231 
5232 	gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5233 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5234 
5235 	/* Done */
5236 	return offset_verification_result;
5237 }
5238 
5239 /** Prepare data, execute draw call and verify results
5240  *
5241  * @param uniform_data_layout
5242  *
5243  * @return true if test pass, false otherwise
5244  **/
test(uniformDataLayout uniform_data_layout) const5245 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5246 {
5247 	bool				  are_offsets_verified		 = (STD140 == uniform_data_layout);
5248 	const glw::Functions& gl						 = m_context.getRenderContext().getFunctions();
5249 	bool				  offset_verification_result = true;
5250 	const programInfo&	program_info				 = getProgramInfo(uniform_data_layout);
5251 	bool				  result					 = true;
5252 
5253 	/* Set up program */
5254 	gl.useProgram(program_info.m_program_object_id);
5255 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5256 
5257 	/* Prepare uniform buffer */
5258 	offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5259 
5260 	if (true == are_offsets_verified && false == offset_verification_result)
5261 	{
5262 		/* Offsets verification failure was already reported, add info about buffer layout */
5263 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5264 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5265 											<< tcu::TestLog::EndMessage;
5266 
5267 		result = false;
5268 	}
5269 
5270 	/* Set up transform feedback buffer */
5271 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5272 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5273 
5274 	/* Begin transform feedback */
5275 	gl.beginTransformFeedback(GL_POINTS);
5276 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5277 
5278 	/* Execute draw call for singe vertex */
5279 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5280 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5281 
5282 	/* Stop transform feedback */
5283 	gl.endTransformFeedback();
5284 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5285 
5286 	/* Verify results */
5287 	if (false == verifyResults())
5288 	{
5289 		/* Result verificatioon failure was already reported, add info about layout */
5290 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5291 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5292 											<< tcu::TestLog::EndMessage;
5293 
5294 		result = false;
5295 	}
5296 
5297 	/* Done */
5298 	return result;
5299 }
5300 
testInit()5301 void GPUShaderFP64Test3::testInit()
5302 {
5303 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5304 
5305 	/* Uniform block declaration with std140 offsets calculated
5306 	 *                       | align | loc_req | begins | ends | offset in bytes | imp |
5307 	 * ivec3   unused1[3]    |     4 |      12 |      0 |   12 |               0 |     |
5308 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5309 	 * bool    unused2       |     1 |       1 |     14 |   15 |              56 |     |
5310 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5311 	 * bvec3   unused3       |     4 |       4 |     20 |   24 |              80 |     |
5312 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5313 	 * int     unused4[3]    |     4 |      12 |     32 |   44 |             128 |     |
5314 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5315 	 * bool    unused5       |     1 |       1 |     56 |   57 |             224 |     |
5316 	 * bool    unused6[2]    |     4 |       8 |     60 |   68 |             240 |     |
5317 	 * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
5318 	 * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
5319 	 * bool    unused7       |     1 |       1 |    104 |  105 |             416 |     |
5320 	 * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
5321 	 * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
5322 	 * uvec3   unused8       |     4 |       4 |    160 |  164 |             640 |     |
5323 	 * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
5324 	 * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
5325 	 * bool    unused9       |     1 |       1 |    196 |  197 |             784 |     |
5326 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5327 	 * int     unused10      |     1 |       1 |    224 |  225 |             896 |     |
5328 	 * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
5329 	 * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
5330 	 */
5331 
5332 	/* Prepare "double precision" unfiorms' details */
5333 	m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5334 											   1 /* n_elements */, "double" /* type_name */));
5335 	m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5336 											   2 /* n_elements */, "dvec2" /* type_name */));
5337 	m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5338 											   3 /* n_elements */, "dvec3" /* type_name */));
5339 	m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5340 											   4 /* n_elements */, "dvec4" /* type_name */));
5341 	m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5342 											   4 /* n_elements */, "dmat2" /* type_name */));
5343 	m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5344 											   9 /* n_elements */, "dmat3" /* type_name */));
5345 	m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5346 											   16 /* n_elements */, "dmat4" /* type_name */));
5347 	m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5348 											   6 /* n_elements */, "dmat2x3" /* type_name */));
5349 	m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5350 											   8 /* n_elements */, "dmat2x4" /* type_name */));
5351 	m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5352 											   6 /* n_elements */, "dmat3x2" /* type_name */));
5353 	m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5354 											   12 /* n_elements */, "dmat3x4" /* type_name */));
5355 	m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5356 											   8 /* n_elements */, "dmat4x2" /* type_name */));
5357 	m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5358 											   12 /* n_elements */, "dmat4x3" /* type_name */));
5359 
5360 	/* Get random values for getExpectedValue */
5361 	m_base_element		= (glw::GLdouble)(rand() % 13);
5362 	m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5363 
5364 	/* Prepare programInfos for all buffer layouts */
5365 	prepareProgram(m_packed_program, PACKED);
5366 	prepareProgram(m_shared_program, SHARED);
5367 	prepareProgram(m_std140_program, STD140);
5368 
5369 	/* Generate buffers */
5370 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
5371 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5372 
5373 	gl.genBuffers(1, &m_uniform_buffer_id);
5374 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5375 
5376 	/* Prepare transform feedback buffer */
5377 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5378 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5379 
5380 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5381 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5382 
5383 	/* Prepare texture for color attachment 0 */
5384 	gl.genTextures(1, &m_color_texture_id);
5385 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5386 
5387 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5388 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5389 
5390 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5391 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5392 
5393 	/* Prepare FBO with color attachment 0 */
5394 	gl.genFramebuffers(1, &m_framebuffer_id);
5395 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5396 
5397 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5398 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5399 
5400 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5401 							0 /* level */);
5402 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5403 
5404 	gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5405 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5406 
5407 	/* Prepare VAO */
5408 	gl.genVertexArrays(1, &m_vertex_array_object_id);
5409 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5410 
5411 	gl.bindVertexArray(m_vertex_array_object_id);
5412 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5413 
5414 	/* Tesselation patch set up */
5415 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
5416 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5417 }
5418 
5419 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5420  *
5421  * @return true if all values are as expected, false otherwise
5422  **/
verifyResults() const5423 bool GPUShaderFP64Test3::verifyResults() const
5424 {
5425 	glw::GLint*			  feedback_data			  = 0;
5426 	bool				  fragment_shader_result  = false;
5427 	bool				  geometry_shader_result  = false;
5428 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
5429 	bool				  tess_ctrl_shader_result = false;
5430 	bool				  tess_eval_shader_result = false;
5431 	bool				  vertex_shader_result	= false;
5432 
5433 	/* Prepare storage for testure data */
5434 	std::vector<glw::GLint> image_data;
5435 	image_data.resize(1);
5436 
5437 	/* Get texture contents */
5438 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5439 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5440 
5441 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5442 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5443 
5444 	/* Get transform feedback data */
5445 	feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5446 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5447 
5448 	/* Verify results */
5449 	fragment_shader_result  = (m_result_success == image_data[0]);
5450 	geometry_shader_result  = (m_result_success == feedback_data[0]);
5451 	tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5452 	tess_eval_shader_result = (m_result_success == feedback_data[2]);
5453 	vertex_shader_result	= (m_result_success == feedback_data[3]);
5454 
5455 	/* Unmap transform feedback buffer */
5456 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5457 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5458 
5459 	/* Set result */
5460 	if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5461 				 tess_eval_shader_result && vertex_shader_result))
5462 	{
5463 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5464 
5465 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5466 											<< "Vertex shader stage result: " << vertex_shader_result
5467 											<< tcu::TestLog::EndMessage;
5468 
5469 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5470 											<< "Tesselation control shader stage result: " << tess_ctrl_shader_result
5471 											<< tcu::TestLog::EndMessage;
5472 
5473 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5474 											<< "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5475 											<< tcu::TestLog::EndMessage;
5476 
5477 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 											<< "Geometry shader stage result: " << geometry_shader_result
5479 											<< tcu::TestLog::EndMessage;
5480 
5481 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 											<< "Fragment shader stage result: " << fragment_shader_result
5483 											<< tcu::TestLog::EndMessage;
5484 
5485 		return false;
5486 	}
5487 	else
5488 	{
5489 		return true;
5490 	}
5491 }
5492 
5493 /** Write main routine of <shader_stage> shader to stream
5494  *
5495  * @param stream       Output stream with source code of shader
5496  * @param shader_stage Shader stage
5497  **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5498 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5499 {
5500 	glw::GLuint		   type_ordinal = 1;
5501 	const glw::GLchar* varying_name = "";
5502 
5503 	/* Select name for varying that will hold result of "that" shader_stage */
5504 	switch (shader_stage)
5505 	{
5506 	case FRAGMENT_SHADER:
5507 		varying_name = m_varying_name_fs_out_fs_result;
5508 		break;
5509 	case GEOMETRY_SHADER:
5510 		varying_name = m_varying_name_gs_fs_gs_result;
5511 		break;
5512 	case TESS_CONTROL_SHADER:
5513 		varying_name = m_varying_name_tcs_tes_tcs_result;
5514 		break;
5515 	case TESS_EVAL_SHADER:
5516 		varying_name = m_varying_name_tes_gs_tes_result;
5517 		break;
5518 	case VERTEX_SHADER:
5519 		varying_name = m_varying_name_vs_tcs_vs_result;
5520 		break;
5521 	}
5522 
5523 	/* void main() */
5524 	stream << "void main()\n"
5525 			  "{\n";
5526 
5527 	/* Tesselation levels output */
5528 	if (TESS_CONTROL_SHADER == shader_stage)
5529 	{
5530 		stream << "gl_TessLevelOuter[0] = 1.0;\n"
5531 				  "gl_TessLevelOuter[1] = 1.0;\n"
5532 				  "gl_TessLevelOuter[2] = 1.0;\n"
5533 				  "gl_TessLevelOuter[3] = 1.0;\n"
5534 				  "gl_TessLevelInner[0] = 1.0;\n"
5535 				  "gl_TessLevelInner[1] = 1.0;\n"
5536 				  "\n";
5537 	}
5538 
5539 	/* For each "double precision" uniform
5540 	 *
5541 	 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5542 	 * {
5543 	 *     VARYING_NAME = m_result_failure;
5544 	 * }
5545 	 */
5546 	for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5547 		 end != it; ++it, ++type_ordinal)
5548 	{
5549 		stream << "    ";
5550 
5551 		/* First comparison is done with if, next with else if */
5552 		if (1 != type_ordinal)
5553 		{
5554 			stream << "else ";
5555 		}
5556 
5557 		/* if (TYPE_NAME( */
5558 		stream << "if (" << it->m_type_name << "(";
5559 
5560 		/* PREDIFINED_VALUES */
5561 		for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5562 		{
5563 			stream << getExpectedValue(type_ordinal, element);
5564 
5565 			/* Separate with comma */
5566 			if (it->m_n_elements != element + 1)
5567 			{
5568 				stream << ", ";
5569 			}
5570 		}
5571 
5572 		/*
5573 		 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5574 		 * {
5575 		 *     VARYING_NAME
5576 		 */
5577 		stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5578 																				   "    {\n"
5579 																				   "        "
5580 			   << varying_name;
5581 
5582 		/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5583 		if (TESS_CONTROL_SHADER == shader_stage)
5584 		{
5585 			stream << "[gl_InvocationID]";
5586 		}
5587 
5588 		/*
5589 		 * = m_result_failure;
5590 		 * }
5591 		 */
5592 		stream << " = " << m_result_failure << ";\n"
5593 			   << "    }\n";
5594 	}
5595 
5596 	/* If all comparisons are ok
5597 	 *
5598 	 *     else
5599 	 *     {
5600 	 *         VARYING_NAME = m_result_success;
5601 	 *     }
5602 	 */
5603 
5604 	/*
5605 	 * else
5606 	 * {
5607 	 *     VARYING_NAME
5608 	 */
5609 	stream << "    else\n"
5610 			  "    {\n"
5611 			  "        "
5612 		   << varying_name;
5613 
5614 	/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5615 	if (TESS_CONTROL_SHADER == shader_stage)
5616 	{
5617 		stream << "[gl_InvocationID]";
5618 	}
5619 
5620 	/*
5621 	 * = m_result_success;
5622 	 * }
5623 	 *
5624 	 */
5625 	stream << " = " << m_result_success << ";\n"
5626 		   << "    }\n"
5627 		   << "\n";
5628 
5629 	/* For each pair of "input/output" varyings
5630 	 *
5631 	 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5632 	 **/
5633 	writeVaryingPassthrough(stream, shader_stage);
5634 
5635 	/* Geometry shader have to emit vertex */
5636 	if (GEOMETRY_SHADER == shader_stage)
5637 	{
5638 		stream << "\n"
5639 				  "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5640 				  "EmitVertex();\n"
5641 				  "EndPrimitive();\n";
5642 	}
5643 
5644 	/* Close scope of main */
5645 	stream << "}\n\n";
5646 }
5647 
5648 /** Write shader preamble to stream
5649  *
5650  * @param stream       Output stream with source code of shader
5651  * @param shader_stage Shader stage
5652  **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5653 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5654 {
5655 	stream << "#version 400 core\n"
5656 			  "\n"
5657 			  "precision highp float;\n"
5658 			  "\n";
5659 
5660 	switch (shader_stage)
5661 	{
5662 	case FRAGMENT_SHADER:
5663 		break;
5664 	case GEOMETRY_SHADER:
5665 		stream << "layout(points)                   in;\n"
5666 				  "layout(points, max_vertices = 1) out;\n"
5667 				  "\n";
5668 		break;
5669 	case TESS_CONTROL_SHADER:
5670 		stream << "layout(vertices = 1) out;\n"
5671 				  "\n";
5672 		break;
5673 	case TESS_EVAL_SHADER:
5674 		stream << "layout(isolines, point_mode) in;\n"
5675 				  "\n";
5676 		break;
5677 	case VERTEX_SHADER:
5678 		break;
5679 	}
5680 }
5681 
5682 /** Write name uniform blcok definition with specific layout to stream
5683  *
5684  * @param stream              Output stream with source code of shader
5685  * @param uniform_data_layout Buffer layout
5686  **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5687 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5688 {
5689 	const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5690 
5691 	stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5692 																			 "{\n"
5693 																			 "    ivec3   unused1[3];\n"
5694 																			 "    double  double_value;\n"
5695 																			 "    bool    unused2;\n"
5696 																			 "    dvec2   dvec2_value;\n"
5697 																			 "    bvec3   unused3;\n"
5698 																			 "    dvec3   dvec3_value;\n"
5699 																			 "    int     unused4[3];\n"
5700 																			 "    dvec4   dvec4_value;\n"
5701 																			 "    bool    unused5;\n"
5702 																			 "    bool    unused6[2];\n"
5703 																			 "    dmat2   dmat2_value;\n"
5704 																			 "    dmat3   dmat3_value;\n"
5705 																			 "    bool    unused7;\n"
5706 																			 "    dmat4   dmat4_value;\n"
5707 																			 "    dmat2x3 dmat2x3_value;\n"
5708 																			 "    uvec3   unused8;\n"
5709 																			 "    dmat2x4 dmat2x4_value;\n"
5710 																			 "    dmat3x2 dmat3x2_value;\n"
5711 																			 "    bool    unused9;\n"
5712 																			 "    dmat3x4 dmat3x4_value;\n"
5713 																			 "    int     unused10;\n"
5714 																			 "    dmat4x2 dmat4x2_value;\n"
5715 																			 "    dmat4x3 dmat4x3_value;\n"
5716 																			 "} "
5717 		   << m_uniform_block_instance_name << ";\n";
5718 
5719 	stream << "\n";
5720 }
5721 
5722 /** Write definitions of varyings specific for given <shader_stage> to stream
5723  *
5724  * @param stream       Output stream with source code of shader
5725  * @param shader_stage Shader stage
5726  **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5727 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5728 {
5729 	static const glw::GLchar* const varying_type = "int";
5730 
5731 	switch (shader_stage)
5732 	{
5733 	case FRAGMENT_SHADER:
5734 
5735 		/* In */
5736 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5737 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5738 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5739 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5740 
5741 		stream << "\n";
5742 
5743 		/* Out */
5744 		stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5745 
5746 		break;
5747 
5748 	case GEOMETRY_SHADER:
5749 
5750 		/* In */
5751 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5752 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5753 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5754 
5755 		stream << "\n";
5756 
5757 		/* Out */
5758 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5759 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5760 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5761 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5762 
5763 		break;
5764 
5765 	case TESS_CONTROL_SHADER:
5766 
5767 		/* In */
5768 		stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5769 
5770 		stream << "\n";
5771 
5772 		/* Out */
5773 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5774 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5775 
5776 		break;
5777 
5778 	case TESS_EVAL_SHADER:
5779 
5780 		/* In */
5781 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5782 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5783 
5784 		stream << "\n";
5785 
5786 		/* Out */
5787 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5788 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5789 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5790 
5791 		break;
5792 
5793 	case VERTEX_SHADER:
5794 
5795 		/* Out */
5796 		stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5797 
5798 		break;
5799 	}
5800 
5801 	stream << "\n";
5802 }
5803 
5804 /** Write passthrough code of "input/output" varying pairs to stream
5805  *
5806  * @param stream       Output stream with source code of shader
5807  * @param shader_stage Shader stage
5808  **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5809 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5810 {
5811 	switch (shader_stage)
5812 	{
5813 	case FRAGMENT_SHADER:
5814 		break;
5815 
5816 	case GEOMETRY_SHADER:
5817 
5818 		stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5819 		stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5820 		stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5821 
5822 		break;
5823 
5824 	case TESS_CONTROL_SHADER:
5825 
5826 		stream << "    " << m_varying_name_tcs_tes_vs_result
5827 			   << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5828 
5829 		break;
5830 
5831 	case TESS_EVAL_SHADER:
5832 
5833 		stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5834 		stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5835 
5836 		break;
5837 
5838 	case VERTEX_SHADER:
5839 
5840 		break;
5841 	}
5842 }
5843 
5844 /** Constructor. Sets all uniform locations to -1 and sets all
5845  *  values to 0.
5846  */
_data()5847 GPUShaderFP64Test4::_data::_data()
5848 {
5849 	memset(&uniform_double, 0, sizeof(uniform_double));
5850 	memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5851 	memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5852 	memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5853 	memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5854 	memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5855 	memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5856 
5857 	uniform_location_double		   = -1;
5858 	uniform_location_double_arr[0] = -1;
5859 	uniform_location_double_arr[1] = -1;
5860 	uniform_location_dvec2		   = -1;
5861 	uniform_location_dvec2_arr[0]  = -1;
5862 	uniform_location_dvec2_arr[1]  = -1;
5863 	uniform_location_dvec3		   = -1;
5864 	uniform_location_dvec3_arr[0]  = -1;
5865 	uniform_location_dvec3_arr[1]  = -1;
5866 	uniform_location_dvec4		   = -1;
5867 	uniform_location_dvec4_arr[0]  = -1;
5868 	uniform_location_dvec4_arr[1]  = -1;
5869 }
5870 
5871 /** Constructor
5872  *
5873  *  @param context Rendering context.
5874  */
GPUShaderFP64Test4(deqp::Context & context)5875 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5876 	: TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5877 									   " report correct properties of & values assigned to double-precision uniforms.")
5878 	, m_has_test_passed(true)
5879 	, m_uniform_name_buffer(0)
5880 	, m_cs_id(0)
5881 	, m_fs_id(0)
5882 	, m_gs_id(0)
5883 	, m_po_cs_id(0)
5884 	, m_po_noncs_id(0)
5885 	, m_tc_id(0)
5886 	, m_te_id(0)
5887 	, m_vs_id(0)
5888 {
5889 	/* Left blank intentionally */
5890 }
5891 
5892 /** Deinitializes all GL objects, as well as releases all bufers, that may
5893  *  have beenallocated or  created during test execution.
5894  **/
deinit()5895 void GPUShaderFP64Test4::deinit()
5896 {
5897 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5898 
5899 	if (m_cs_id != 0)
5900 	{
5901 		gl.deleteShader(m_cs_id);
5902 
5903 		m_cs_id = 0;
5904 	}
5905 
5906 	if (m_fs_id != 0)
5907 	{
5908 		gl.deleteShader(m_fs_id);
5909 
5910 		m_fs_id = 0;
5911 	}
5912 
5913 	if (m_gs_id != 0)
5914 	{
5915 		gl.deleteShader(m_gs_id);
5916 
5917 		m_gs_id = 0;
5918 	}
5919 
5920 	if (m_po_cs_id != 0)
5921 	{
5922 		gl.deleteProgram(m_po_cs_id);
5923 
5924 		m_po_cs_id = 0;
5925 	}
5926 
5927 	if (m_po_noncs_id != 0)
5928 	{
5929 		gl.deleteProgram(m_po_noncs_id);
5930 
5931 		m_po_noncs_id = 0;
5932 	}
5933 
5934 	if (m_tc_id != 0)
5935 	{
5936 		gl.deleteShader(m_tc_id);
5937 
5938 		m_tc_id = 0;
5939 	}
5940 
5941 	if (m_te_id != 0)
5942 	{
5943 		gl.deleteShader(m_te_id);
5944 
5945 		m_te_id = 0;
5946 	}
5947 
5948 	if (m_uniform_name_buffer != DE_NULL)
5949 	{
5950 		delete[] m_uniform_name_buffer;
5951 
5952 		m_uniform_name_buffer = DE_NULL;
5953 	}
5954 
5955 	if (m_vs_id != 0)
5956 	{
5957 		gl.deleteShader(m_vs_id);
5958 
5959 		m_vs_id = 0;
5960 	}
5961 }
5962 
5963 /** Generates double-precision values for all uniforms defined for all program objects
5964  *  used by the test.
5965  *
5966  *  This function DOES NOT use any GL API. It only calculates & stores the values
5967  *  in internal storage for further usage.
5968  */
generateUniformValues()5969 void GPUShaderFP64Test4::generateUniformValues()
5970 {
5971 	_stage_data*	   stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5972 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5973 
5974 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5975 	{
5976 		_stage_data* stage_ptr = stages[n_stage];
5977 
5978 		/* Iterate through all uniform components and assign them double values */
5979 		double* double_ptrs[] = {
5980 			&stage_ptr->uniform_structure_arrays[0].uniform_double,
5981 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5982 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5983 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5984 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5985 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
5986 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
5987 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
5988 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
5989 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
5990 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
5991 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
5992 			&stage_ptr->uniform_structure_arrays[1].uniform_double,
5993 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
5994 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
5995 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
5996 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
5997 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
5998 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
5999 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6000 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6001 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6002 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6003 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6004 			&stage_ptr->uniforms.uniform_double,
6005 			stage_ptr->uniforms.uniform_double_arr + 0,
6006 			stage_ptr->uniforms.uniform_double_arr + 1,
6007 			stage_ptr->uniforms.uniform_dvec2 + 0,
6008 			stage_ptr->uniforms.uniform_dvec2 + 1,
6009 			stage_ptr->uniforms.uniform_dvec2_arr + 0,
6010 			stage_ptr->uniforms.uniform_dvec2_arr + 1,
6011 			stage_ptr->uniforms.uniform_dvec2_arr + 2,
6012 			stage_ptr->uniforms.uniform_dvec2_arr + 3,
6013 			stage_ptr->uniforms.uniform_dvec3 + 0,
6014 			stage_ptr->uniforms.uniform_dvec3 + 1,
6015 			stage_ptr->uniforms.uniform_dvec3 + 2,
6016 			stage_ptr->uniforms.uniform_dvec3_arr + 0,
6017 			stage_ptr->uniforms.uniform_dvec3_arr + 1,
6018 			stage_ptr->uniforms.uniform_dvec3_arr + 2,
6019 			stage_ptr->uniforms.uniform_dvec3_arr + 3,
6020 			stage_ptr->uniforms.uniform_dvec3_arr + 4,
6021 			stage_ptr->uniforms.uniform_dvec3_arr + 5,
6022 			stage_ptr->uniforms.uniform_dvec4 + 0,
6023 			stage_ptr->uniforms.uniform_dvec4 + 1,
6024 			stage_ptr->uniforms.uniform_dvec4 + 2,
6025 			stage_ptr->uniforms.uniform_dvec4 + 3,
6026 			stage_ptr->uniforms.uniform_dvec4_arr + 0,
6027 			stage_ptr->uniforms.uniform_dvec4_arr + 1,
6028 			stage_ptr->uniforms.uniform_dvec4_arr + 2,
6029 			stage_ptr->uniforms.uniform_dvec4_arr + 3,
6030 			stage_ptr->uniforms.uniform_dvec4_arr + 4,
6031 			stage_ptr->uniforms.uniform_dvec4_arr + 5,
6032 			stage_ptr->uniforms.uniform_dvec4_arr + 6,
6033 			stage_ptr->uniforms.uniform_dvec4_arr + 7,
6034 		};
6035 		const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6036 
6037 		for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6038 		{
6039 			double* double_ptr = double_ptrs[n_double_ptr];
6040 
6041 			/* Generate the value. Use magic numbers to generate a set of double-precision
6042 			 * floating-point numbers.
6043 			 */
6044 			static int seed = 16762362;
6045 
6046 			*double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6047 
6048 			seed += 751;
6049 		} /* for (all pointers to double variables) */
6050 	}	 /* for (all stages) */
6051 }
6052 
6053 /** Initializes all program & shader objects required to run the test. The function also
6054  *  retrieves locations of all uniforms defined by both program objects.
6055  **/
initProgramObjects()6056 void GPUShaderFP64Test4::initProgramObjects()
6057 {
6058 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6059 
6060 	/* Create program & shader objects */
6061 
6062 	/* Compute shader support and GL 4.2 required */
6063 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6064 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6065 	{
6066 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6067 	}
6068 
6069 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6070 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6071 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6072 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6073 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6074 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6075 
6076 	/* m_cs_id is initialized only if compute shaders are supported */
6077 	if (0 != m_cs_id)
6078 	{
6079 		m_po_cs_id = gl.createProgram();
6080 	}
6081 
6082 	m_po_noncs_id = gl.createProgram();
6083 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6084 
6085 	/* Configure compute shader body */
6086 	const char* cs_body = "#version 420\n"
6087 						  "#extension GL_ARB_compute_shader          : require\n"
6088 						  "\n"
6089 						  "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6090 						  "\n"
6091 						  "layout(rgba32f) uniform image2D testImage;\n"
6092 						  "\n"
6093 						  "uniform double cs_double;\n"
6094 						  "uniform dvec2  cs_dvec2;\n"
6095 						  "uniform dvec3  cs_dvec3;\n"
6096 						  "uniform dvec4  cs_dvec4;\n"
6097 						  "uniform double cs_double_arr[2];\n"
6098 						  "uniform dvec2  cs_dvec2_arr [2];\n"
6099 						  "uniform dvec3  cs_dvec3_arr [2];\n"
6100 						  "uniform dvec4  cs_dvec4_arr [2];\n"
6101 						  "\n"
6102 						  "uniform struct cs_struct\n"
6103 						  "{\n"
6104 						  "    double struct_double;\n"
6105 						  "    dvec2  struct_dvec2;\n"
6106 						  "    dvec3  struct_dvec3;\n"
6107 						  "    dvec4  struct_dvec4;\n"
6108 						  "} cs_array[2];\n"
6109 						  "\n"
6110 						  "void main()\n"
6111 						  "{\n"
6112 						  "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
6113 						  "          * cs_dvec4.z                 *\n"
6114 						  "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
6115 						  "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
6116 						  "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
6117 						  "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
6118 						  "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
6119 						  "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6120 						  "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
6121 						  "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6122 						  "\n"
6123 						  "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6124 						  "}\n";
6125 
6126 	/* m_cs_id is initialized only if compute shaders are supported */
6127 	if (0 != m_cs_id)
6128 	{
6129 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6130 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6131 	}
6132 
6133 	/* Configure vertex shader body */
6134 	const char* vs_body = "#version 400\n"
6135 						  "\n"
6136 						  "uniform double vs_double;\n"
6137 						  "uniform dvec2  vs_dvec2;\n"
6138 						  "uniform dvec3  vs_dvec3;\n"
6139 						  "uniform dvec4  vs_dvec4;\n"
6140 						  "uniform double vs_double_arr[2];\n"
6141 						  "uniform dvec2  vs_dvec2_arr [2];\n"
6142 						  "uniform dvec3  vs_dvec3_arr [2];\n"
6143 						  "uniform dvec4  vs_dvec4_arr [2];\n"
6144 						  "\n"
6145 						  "uniform struct vs_struct\n"
6146 						  "{\n"
6147 						  "    double struct_double;\n"
6148 						  "    dvec2  struct_dvec2;\n"
6149 						  "    dvec3  struct_dvec3;\n"
6150 						  "    dvec4  struct_dvec4;\n"
6151 						  "} vs_array[2];\n"
6152 						  "\n"
6153 						  "void main()\n"
6154 						  "{\n"
6155 						  "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
6156 						  "* vs_dvec4.x                 *\n"
6157 						  "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
6158 						  "* vs_dvec4_arr[0].x          *\n"
6159 						  "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
6160 						  "* vs_dvec4_arr[1].x          *\n"
6161 						  "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6162 						  "* vs_array[0].struct_dvec4.x *\n"
6163 						  "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6164 						  "* vs_array[1].struct_dvec4.x > 1.0)\n"
6165 						  "    {\n"
6166 						  "        gl_Position = vec4(0);\n"
6167 						  "    }\n"
6168 						  "    else\n"
6169 						  "    {\n"
6170 						  "        gl_Position = vec4(1);\n"
6171 						  "    }\n"
6172 						  "}\n";
6173 
6174 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6176 
6177 	/* Configure tessellation control shader body */
6178 	const char* tc_body = "#version 400\n"
6179 						  "\n"
6180 						  "uniform double tc_double;\n"
6181 						  "uniform dvec2  tc_dvec2;\n"
6182 						  "uniform dvec3  tc_dvec3;\n"
6183 						  "uniform dvec4  tc_dvec4;\n"
6184 						  "uniform double tc_double_arr[2];\n"
6185 						  "uniform dvec2  tc_dvec2_arr [2];\n"
6186 						  "uniform dvec3  tc_dvec3_arr [2];\n"
6187 						  "uniform dvec4  tc_dvec4_arr [2];\n"
6188 						  "\n"
6189 						  "uniform struct tc_struct\n"
6190 						  "{\n"
6191 						  "    double struct_double;\n"
6192 						  "    dvec2  struct_dvec2;\n"
6193 						  "    dvec3  struct_dvec3;\n"
6194 						  "    dvec4  struct_dvec4;\n"
6195 						  "} tc_array[2];\n"
6196 						  "\n"
6197 						  "layout(vertices = 4) out;\n"
6198 						  "\n"
6199 						  "void main()\n"
6200 						  "{\n"
6201 						  "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
6202 						  "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
6203 						  "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
6204 						  "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
6205 						  "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6206 						  "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6207 						  "\n"
6208 						  "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
6209 						  "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
6210 						  "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
6211 						  "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
6212 						  "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6213 						  "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
6214 						  "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6215 						  "    {\n"
6216 						  "        gl_TessLevelInner[1] = 3.0;\n"
6217 						  "    }\n"
6218 						  "}\n";
6219 
6220 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6221 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6222 
6223 	/* Configure tessellation evaluation shader body */
6224 	const char* te_body = "#version 400\n"
6225 						  "\n"
6226 						  "uniform double te_double;\n"
6227 						  "uniform dvec2  te_dvec2;\n"
6228 						  "uniform dvec3  te_dvec3;\n"
6229 						  "uniform dvec4  te_dvec4;\n"
6230 						  "uniform double te_double_arr[2];\n"
6231 						  "uniform dvec2  te_dvec2_arr [2];\n"
6232 						  "uniform dvec3  te_dvec3_arr [2];\n"
6233 						  "uniform dvec4  te_dvec4_arr [2];\n"
6234 						  "\n"
6235 						  "uniform struct te_struct\n"
6236 						  "{\n"
6237 						  "    double struct_double;\n"
6238 						  "    dvec2  struct_dvec2;\n"
6239 						  "    dvec3  struct_dvec3;\n"
6240 						  "    dvec4  struct_dvec4;\n"
6241 						  "} te_array[2];\n"
6242 						  "\n"
6243 						  "layout(triangles) in;\n"
6244 						  "\n"
6245 						  "void main()\n"
6246 						  "{\n"
6247 						  "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
6248 						  "* te_dvec4.x                 *\n"
6249 						  "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
6250 						  "* te_dvec4_arr[0].x          *\n"
6251 						  "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
6252 						  "* te_dvec4_arr[1].x          *\n"
6253 						  "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6254 						  "* te_array[0].struct_dvec4.x *\n"
6255 						  "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6256 						  "* te_array[1].struct_dvec4.x > 1.0)\n"
6257 						  "    {\n"
6258 						  "        gl_Position = gl_in[0].gl_Position;\n"
6259 						  "    }\n"
6260 						  "    else\n"
6261 						  "    {\n"
6262 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6263 						  "    }\n"
6264 						  "}\n";
6265 
6266 	gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6267 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6268 
6269 	/* Configure geometry shader body */
6270 	const char* gs_body = "#version 400\n"
6271 						  "\n"
6272 						  "uniform double gs_double;\n"
6273 						  "uniform dvec2  gs_dvec2;\n"
6274 						  "uniform dvec3  gs_dvec3;\n"
6275 						  "uniform dvec4  gs_dvec4;\n"
6276 						  "uniform double gs_double_arr[2];\n"
6277 						  "uniform dvec2  gs_dvec2_arr [2];\n"
6278 						  "uniform dvec3  gs_dvec3_arr [2];\n"
6279 						  "uniform dvec4  gs_dvec4_arr [2];\n"
6280 						  "\n"
6281 						  "uniform struct gs_struct\n"
6282 						  "{\n"
6283 						  "    double struct_double;\n"
6284 						  "    dvec2  struct_dvec2;\n"
6285 						  "    dvec3  struct_dvec3;\n"
6286 						  "    dvec4  struct_dvec4;\n"
6287 						  "} gs_array[2];\n"
6288 						  "\n"
6289 						  "layout (points)                   in;\n"
6290 						  "layout (points, max_vertices = 1) out;\n"
6291 						  "\n"
6292 						  "void main()\n"
6293 						  "{\n"
6294 						  "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
6295 						  "* gs_dvec4.x        *\n"
6296 						  "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
6297 						  "* gs_dvec4_arr[0].x *\n"
6298 						  "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
6299 						  "* gs_dvec4_arr[1].x *\n"
6300 						  "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6301 						  "* gs_array[0].struct_dvec4.x *\n"
6302 						  "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6303 						  "* gs_array[1].struct_dvec4.x > 1.0)\n"
6304 						  "    {\n"
6305 						  "        gl_Position = gl_in[0].gl_Position;\n"
6306 						  "    }\n"
6307 						  "    else\n"
6308 						  "    {\n"
6309 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6310 						  "    }\n"
6311 						  "\n"
6312 						  "    EmitVertex();\n"
6313 						  "}\n";
6314 
6315 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6316 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6317 
6318 	/* Configure fragment shader body */
6319 	const char* fs_body = "#version 400\n"
6320 						  "\n"
6321 						  "uniform double fs_double;\n"
6322 						  "uniform dvec2  fs_dvec2;\n"
6323 						  "uniform dvec3  fs_dvec3;\n"
6324 						  "uniform dvec4  fs_dvec4;\n"
6325 						  "uniform double fs_double_arr[2];\n"
6326 						  "uniform dvec2  fs_dvec2_arr [2];\n"
6327 						  "uniform dvec3  fs_dvec3_arr [2];\n"
6328 						  "uniform dvec4  fs_dvec4_arr [2];\n"
6329 						  "\n"
6330 						  "uniform struct fs_struct\n"
6331 						  "{\n"
6332 						  "    double struct_double;\n"
6333 						  "    dvec2  struct_dvec2;\n"
6334 						  "    dvec3  struct_dvec3;\n"
6335 						  "    dvec4  struct_dvec4;\n"
6336 						  "} fs_array[2];\n"
6337 						  "\n"
6338 						  "out vec4 result;\n"
6339 						  "\n"
6340 						  "void main()\n"
6341 						  "{\n"
6342 						  "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
6343 						  "* fs_dvec4.x        *\n"
6344 						  "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
6345 						  "* fs_dvec4_arr[0].x *\n"
6346 						  "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
6347 						  "* fs_dvec4_arr[1].x *\n"
6348 						  "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6349 						  "* fs_array[0].struct_dvec4.x *\n"
6350 						  "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6351 						  "* fs_array[1].struct_dvec4.x > 1.0)\n"
6352 						  "    {\n"
6353 						  "        result = vec4(0.0);\n"
6354 						  "    }\n"
6355 						  "    else\n"
6356 						  "    {\n"
6357 						  "        result = vec4(1.0);\n"
6358 						  "    }\n"
6359 						  "}\n";
6360 
6361 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6362 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6363 
6364 	/* Compile the shaders */
6365 	const glw::GLuint  shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6366 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6367 
6368 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6369 	{
6370 		glw::GLint  compile_status = GL_FALSE;
6371 		glw::GLuint so_id		   = shaders[n_shader];
6372 
6373 		/* Skip compute shader if not supported */
6374 		if (0 == so_id)
6375 		{
6376 			continue;
6377 		}
6378 
6379 		gl.compileShader(so_id);
6380 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6381 
6382 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6383 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6384 
6385 		if (compile_status != GL_TRUE)
6386 		{
6387 			TCU_FAIL("Shader compilation failed");
6388 		}
6389 
6390 		if (so_id == m_cs_id)
6391 		{
6392 			gl.attachShader(m_po_cs_id, so_id);
6393 		}
6394 		else
6395 		{
6396 			gl.attachShader(m_po_noncs_id, so_id);
6397 		}
6398 
6399 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6400 	} /* for (all shaders) */
6401 
6402 	/* Link the program */
6403 	const glw::GLuint  programs[]  = { m_po_cs_id, m_po_noncs_id };
6404 	const unsigned int n_programs  = sizeof(programs) / sizeof(programs[0]);
6405 	glw::GLint		   link_status = GL_FALSE;
6406 
6407 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6408 	{
6409 		glw::GLuint po_id = programs[n_program];
6410 
6411 		/* Skip compute shader program if not supported */
6412 		if (0 == po_id)
6413 		{
6414 			continue;
6415 		}
6416 
6417 		gl.linkProgram(po_id);
6418 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6419 
6420 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6421 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6422 
6423 		if (link_status != GL_TRUE)
6424 		{
6425 			TCU_FAIL("Program linking failed");
6426 		}
6427 	} /* for (both program objects) */
6428 
6429 	/* Retrieve uniform locations */
6430 	_stage_data*			  cs_stage_data[]		= { &m_data_cs };
6431 	static const char*		  cs_uniform_prefixes[] = { "cs_" };
6432 	static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6433 
6434 	_stage_data*			  noncs_stage_data[]	   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6435 	static const char*		  noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6436 	static const unsigned int n_noncs_uniform_prefixes =
6437 		sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6438 
6439 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6440 	{
6441 		unsigned int  n_uniform_prefixes = DE_NULL;
6442 		glw::GLuint   po_id				 = programs[n_program];
6443 		_stage_data** stages_data		 = DE_NULL;
6444 		const char**  uniform_prefixes   = DE_NULL;
6445 
6446 		if (n_program == 0)
6447 		{
6448 			stages_data		   = cs_stage_data;
6449 			uniform_prefixes   = cs_uniform_prefixes;
6450 			n_uniform_prefixes = n_cs_uniform_prefixes;
6451 		}
6452 		else
6453 		{
6454 			stages_data		   = noncs_stage_data;
6455 			uniform_prefixes   = noncs_uniform_prefixes;
6456 			n_uniform_prefixes = n_noncs_uniform_prefixes;
6457 		}
6458 
6459 		/* Skip compute shader program if not supported */
6460 		if (0 == po_id)
6461 		{
6462 			continue;
6463 		}
6464 
6465 		/* Uniform names used by the test program consist of a prefix (different for each
6466 		 * shader stage) and a common part.
6467 		 */
6468 		for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6469 		{
6470 			_stage_data* stage_data				  = stages_data[n_uniform_prefix];
6471 			std::string  uniform_prefix			  = std::string(uniform_prefixes[n_uniform_prefix]);
6472 			std::string  uniform_double_name	  = uniform_prefix + "double";
6473 			std::string  uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6474 			std::string  uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6475 			std::string  uniform_dvec2_name		  = uniform_prefix + "dvec2";
6476 			std::string  uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
6477 			std::string  uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
6478 			std::string  uniform_dvec3_name		  = uniform_prefix + "dvec3";
6479 			std::string  uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
6480 			std::string  uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
6481 			std::string  uniform_dvec4_name		  = uniform_prefix + "dvec4";
6482 			std::string  uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
6483 			std::string  uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
6484 			std::string  uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6485 			std::string  uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
6486 			std::string  uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
6487 			std::string  uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
6488 			std::string  uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6489 			std::string  uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
6490 			std::string  uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
6491 			std::string  uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
6492 
6493 			/* Retrieve uniform locations */
6494 			stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6495 			stage_data->uniforms.uniform_location_double_arr[0] =
6496 				gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6497 			stage_data->uniforms.uniform_location_double_arr[1] =
6498 				gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6499 			stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6500 			stage_data->uniforms.uniform_location_dvec2_arr[0] =
6501 				gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6502 			stage_data->uniforms.uniform_location_dvec2_arr[1] =
6503 				gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6504 			stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6505 			stage_data->uniforms.uniform_location_dvec3_arr[0] =
6506 				gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6507 			stage_data->uniforms.uniform_location_dvec3_arr[1] =
6508 				gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6509 			stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6510 			stage_data->uniforms.uniform_location_dvec4_arr[0] =
6511 				gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6512 			stage_data->uniforms.uniform_location_dvec4_arr[1] =
6513 				gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6514 			stage_data->uniform_structure_arrays[0].uniform_location_double =
6515 				gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6516 			stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6517 				gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6518 			stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6519 				gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6520 			stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6521 				gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6522 			stage_data->uniform_structure_arrays[1].uniform_location_double =
6523 				gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6524 			stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6525 				gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6526 			stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6527 				gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6528 			stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6529 				gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6530 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6531 
6532 			if (stage_data->uniforms.uniform_location_double == -1 ||
6533 				stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6534 				stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6535 				stage_data->uniforms.uniform_location_dvec2 == -1 ||
6536 				stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6537 				stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6538 				stage_data->uniforms.uniform_location_dvec3 == -1 ||
6539 				stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6540 				stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6541 				stage_data->uniforms.uniform_location_dvec4 == -1 ||
6542 				stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6543 				stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6544 				stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6545 				stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6546 				stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6547 				stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6548 				stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6549 				stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6550 				stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6551 				stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6552 			{
6553 				TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6554 			}
6555 
6556 			/* Make sure locations of subsequent items in array uniforms are correct */
6557 			if (stage_data->uniforms.uniform_location_double_arr[1] !=
6558 					(stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6559 				stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6560 					(stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6561 				stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6562 					(stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6563 				stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6564 					(stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6565 			{
6566 				m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6567 															   " double_arr[0]:"
6568 								   << stage_data->uniforms.uniform_location_double_arr[0]
6569 								   << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6570 								   << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6571 								   << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6572 								   << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6573 								   << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6574 								   << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6575 								   << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6576 								   << tcu::TestLog::EndMessage;
6577 
6578 				TCU_FAIL("Double-precision uniform array item locations are invalid.");
6579 			}
6580 		} /* for (all uniform prefixes) */
6581 	}	 /* for (both program objects) */
6582 }
6583 
6584 /** Initializes all objects required to run the test. */
initTest()6585 void GPUShaderFP64Test4::initTest()
6586 {
6587 	initProgramObjects();
6588 
6589 	generateUniformValues();
6590 	initUniformValues();
6591 }
6592 
6593 /** Assigns values generated by generateUniformValues() to uniforms defined by
6594  *  both program objects.
6595  **/
initUniformValues()6596 void GPUShaderFP64Test4::initUniformValues()
6597 {
6598 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6599 
6600 	/* Iterate through all programs */
6601 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6602 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6603 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6604 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6605 
6606 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6607 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6608 
6609 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6610 	{
6611 		glw::GLuint   po_id		 = programs[n_program];
6612 		unsigned int  n_stages   = 0;
6613 		_stage_data** stage_data = DE_NULL;
6614 
6615 		if (po_id == m_po_cs_id)
6616 		{
6617 			n_stages   = n_cs_stages;
6618 			stage_data = cs_stages;
6619 		}
6620 		else
6621 		{
6622 			n_stages   = n_noncs_stages;
6623 			stage_data = noncs_stages;
6624 		}
6625 
6626 		/* Skip compute shader program if not supported */
6627 		if (0 == po_id)
6628 		{
6629 			continue;
6630 		}
6631 
6632 		gl.useProgram(po_id);
6633 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6634 
6635 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6636 		{
6637 			/* Iterate through all uniforms */
6638 			_stage_data* stage_ptr = stage_data[n_stage];
6639 
6640 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6641 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6642 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6643 			gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6644 						 stage_ptr->uniform_structure_arrays[0].uniform_double);
6645 			gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6646 						 stage_ptr->uniform_structure_arrays[1].uniform_double);
6647 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6648 
6649 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6650 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6651 						  stage_ptr->uniforms.uniform_dvec2_arr + 0);
6652 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6653 						  stage_ptr->uniforms.uniform_dvec2_arr + 2);
6654 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6655 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6656 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6657 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6658 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6659 
6660 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6661 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6662 						  stage_ptr->uniforms.uniform_dvec3_arr + 0);
6663 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6664 						  stage_ptr->uniforms.uniform_dvec3_arr + 3);
6665 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6666 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6667 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6668 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6669 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6670 
6671 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6672 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6673 						  stage_ptr->uniforms.uniform_dvec4_arr + 0);
6674 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6675 						  stage_ptr->uniforms.uniform_dvec4_arr + 4);
6676 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6677 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6678 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6679 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6680 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6681 		} /* for (all shader stages) */
6682 	}	 /* for (both program objects) */
6683 }
6684 
6685 /** Executes test iteration.
6686  *
6687  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6688  */
iterate()6689 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6690 {
6691 	/* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6692 
6693 	/* Initialize all objects required to run the test */
6694 	initTest();
6695 
6696 	/* Verify the implementation reports correct values for all stages we've configured */
6697 	m_has_test_passed &= verifyUniformValues();
6698 
6699 	/* Is this also the case when "program interface query" mechanism is used? */
6700 	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6701 	{
6702 		m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6703 	}
6704 
6705 	/* We're done */
6706 	if (m_has_test_passed)
6707 	{
6708 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6709 	}
6710 	else
6711 	{
6712 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6713 	}
6714 
6715 	return STOP;
6716 }
6717 
6718 /** Verifies that:
6719  *
6720  *  a) glGetProgramResourceIndex()
6721  *  b) glGetProgramResourceiv()
6722  *  c) glGetProgramResourceName()
6723  *
6724  *  functions return correct values for double-precision uniforms.
6725  *
6726  *  @return true if the verification was passed, false otherwise.
6727  */
verifyProgramInterfaceQuerySupport()6728 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6729 {
6730 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6731 	bool				  result = true;
6732 
6733 	/* Iterate through all programs */
6734 	const char*		   cs_prefixes[]	= { "cs_" };
6735 	_stage_data*	   cs_stages[]		= { &m_data_cs };
6736 	const char*		   noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6737 	_stage_data*	   noncs_stages[]   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6738 	const unsigned int n_cs_stages		= sizeof(cs_stages) / sizeof(cs_stages[0]);
6739 	const unsigned int n_noncs_stages   = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6740 
6741 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6742 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6743 
6744 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6745 	{
6746 		glw::GLuint   po_id			 = programs[n_program];
6747 		unsigned int  n_stages		 = 0;
6748 		const char**  stage_prefixes = DE_NULL;
6749 		_stage_data** stage_data	 = DE_NULL;
6750 
6751 		if (po_id == m_po_cs_id)
6752 		{
6753 			n_stages	   = n_cs_stages;
6754 			stage_data	 = cs_stages;
6755 			stage_prefixes = cs_prefixes;
6756 		}
6757 		else
6758 		{
6759 			n_stages	   = n_noncs_stages;
6760 			stage_data	 = noncs_stages;
6761 			stage_prefixes = noncs_prefixes;
6762 		}
6763 
6764 		/* Skip compute shader program if not supported */
6765 		if (0 == po_id)
6766 		{
6767 			continue;
6768 		}
6769 
6770 		/* Determine maximum uniform name length */
6771 		glw::GLint max_uniform_name_length = 0;
6772 
6773 		gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6774 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6775 
6776 		/* Allocate a buffer we will use to hold uniform names */
6777 		m_uniform_name_buffer = new char[max_uniform_name_length];
6778 
6779 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6780 		{
6781 			/* Iterate through all uniforms */
6782 			_stage_data* stage_ptr	= stage_data[n_stage];
6783 			const char*  stage_prefix = stage_prefixes[n_stage];
6784 
6785 			/* Construct an array that will be used to run the test in an automated manner */
6786 			_program_interface_query_test_item uniforms[] = {
6787 				/* array size */ /* name */ /* type */ /* location */
6788 				{ 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6789 				{ 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6790 				{ 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6791 				{ 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6792 				{ 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6793 				{ 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6794 				{ 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6795 				{ 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6796 				{ 1, "array[0].struct_double", GL_DOUBLE,
6797 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6798 				{ 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6799 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6800 				{ 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6801 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6802 				{ 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6803 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6804 				{ 1, "array[1].struct_double", GL_DOUBLE,
6805 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6806 				{ 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6807 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6808 				{ 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6809 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6810 				{ 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6811 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6812 			};
6813 			const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6814 
6815 			/* Prefix the names with stage-specific string */
6816 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6817 			{
6818 				_program_interface_query_test_item& current_item = uniforms[n_uniform];
6819 
6820 				current_item.name = std::string(stage_prefix) + current_item.name;
6821 			} /* for (all uniform descriptors) */
6822 
6823 			const glw::GLenum  properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6824 			const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6825 
6826 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6827 			{
6828 				_program_interface_query_test_item& current_item		  = uniforms[n_uniform];
6829 				glw::GLint							n_written_items		  = 0;
6830 				glw::GLint							retrieved_array_size  = 0;
6831 				glw::GLint							retrieved_name_length = 0;
6832 				glw::GLenum							retrieved_type		  = GL_NONE;
6833 				glw::GLint							temp_buffer[2]		  = { 0, GL_NONE };
6834 
6835 				/* Retrieve index of the iteration-specific uniform */
6836 				glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6837 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6838 
6839 				/* Make sure glGetProgramResourceName() returns correct values */
6840 				memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6841 
6842 				gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6843 										  resource_index, max_uniform_name_length, &retrieved_name_length,
6844 										  m_uniform_name_buffer);
6845 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6846 
6847 				if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6848 					memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6849 				{
6850 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6851 									   << resource_index << "]"
6852 															": expected:["
6853 									   << current_item.name << "]"
6854 															   ", reported:["
6855 									   << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6856 
6857 					result = false;
6858 					continue;
6859 				}
6860 
6861 				/* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6862 				gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6863 										resource_index, n_properties, properties,
6864 										sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6865 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6866 
6867 				if (n_written_items != n_properties)
6868 				{
6869 					TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6870 				}
6871 
6872 				/* For clarity, copy the retrieved values to separate variables */
6873 				retrieved_array_size = temp_buffer[0];
6874 				retrieved_type		 = temp_buffer[1];
6875 
6876 				/* Verify the values */
6877 				if (retrieved_array_size != current_item.expected_array_size)
6878 				{
6879 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6880 									   << current_item.name << "]"
6881 									   << ": expected:[" << current_item.expected_array_size << "]"
6882 																								", reported:["
6883 									   << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6884 
6885 					result = false;
6886 				}
6887 
6888 				if (retrieved_type != current_item.expected_type)
6889 				{
6890 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6891 									   << current_item.name << "]"
6892 									   << ": expected:[" << current_item.expected_type << "]"
6893 																						  ", reported:["
6894 									   << retrieved_type << "]" << tcu::TestLog::EndMessage;
6895 
6896 					result = false;
6897 				}
6898 			} /* for (all uniforms) */
6899 		}	 /* for (all shader stages) */
6900 
6901 		/* We're now OK to release the buffer we used to hold uniform names for
6902 		 * the program */
6903 		if (m_uniform_name_buffer != DE_NULL)
6904 		{
6905 			delete[] m_uniform_name_buffer;
6906 
6907 			m_uniform_name_buffer = DE_NULL;
6908 		}
6909 	} /* for (both program objects) */
6910 
6911 	return result;
6912 }
6913 
6914 /** Verifies glGetUniform*() calls return correct values assigned to
6915  *  double-precision uniforms.
6916  *
6917  *  @return true if all values reported by OpenGL were found to be correct,
6918  *          false otherwise.
6919  **/
verifyUniformValues()6920 bool GPUShaderFP64Test4::verifyUniformValues()
6921 {
6922 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6923 	bool				  result = true;
6924 
6925 	/* Iterate through all programs */
6926 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6927 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6928 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6929 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6930 
6931 	const glw::GLuint programs[] = {
6932 		m_po_noncs_id, m_po_cs_id,
6933 	};
6934 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6935 
6936 	/* Set up rounding for the tests */
6937 	deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
6938 
6939 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6940 	{
6941 		glw::GLuint   po_id		 = programs[n_program];
6942 		unsigned int  n_stages   = 0;
6943 		_stage_data** stage_data = DE_NULL;
6944 
6945 		if (po_id == m_po_cs_id)
6946 		{
6947 			n_stages   = n_cs_stages;
6948 			stage_data = cs_stages;
6949 		}
6950 		else
6951 		{
6952 			n_stages   = n_noncs_stages;
6953 			stage_data = noncs_stages;
6954 		}
6955 
6956 		/* Skip compute shader program if not supported */
6957 		if (0 == po_id)
6958 		{
6959 			continue;
6960 		}
6961 
6962 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6963 		{
6964 			/* Iterate through all uniforms */
6965 			_stage_data* stage_ptr = stage_data[n_stage];
6966 
6967 			/* Set up arrays that we will guide the automated testing */
6968 			const uniform_value_pair double_uniforms[] = {
6969 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6970 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6971 								   stage_ptr->uniforms.uniform_double_arr + 0),
6972 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6973 								   stage_ptr->uniforms.uniform_double_arr + 1),
6974 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6975 								   &stage_ptr->uniform_structure_arrays[0].uniform_double),
6976 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6977 								   &stage_ptr->uniform_structure_arrays[1].uniform_double)
6978 			};
6979 			const uniform_value_pair dvec2_uniforms[] = {
6980 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6981 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6982 								   stage_ptr->uniforms.uniform_dvec2_arr + 0),
6983 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6984 								   stage_ptr->uniforms.uniform_dvec2_arr + 2),
6985 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6986 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6987 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6988 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6989 			};
6990 			const uniform_value_pair dvec3_uniforms[] = {
6991 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6992 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6993 								   stage_ptr->uniforms.uniform_dvec3_arr + 0),
6994 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6995 								   stage_ptr->uniforms.uniform_dvec3_arr + 3),
6996 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
6997 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
6998 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
6999 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7000 			};
7001 			const uniform_value_pair dvec4_uniforms[] = {
7002 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7003 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7004 								   stage_ptr->uniforms.uniform_dvec4_arr + 0),
7005 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7006 								   stage_ptr->uniforms.uniform_dvec4_arr + 4),
7007 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7008 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7009 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7010 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7011 			};
7012 
7013 			/* Iterate over all uniforms and verify the values reported by the API */
7014 			double		 returned_double_data[4];
7015 			float		 returned_float_data[4];
7016 			int			 returned_int_data[4];
7017 			unsigned int returned_uint_data[4];
7018 
7019 			for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7020 			{
7021 				const uniform_value_pair* current_uv_pairs  = NULL;
7022 				const unsigned int		  n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7023 				unsigned int			  n_pairs			= 0;
7024 
7025 				switch (n_type)
7026 				{
7027 				case 0: /* double */
7028 				{
7029 					current_uv_pairs = double_uniforms;
7030 					n_pairs			 = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7031 
7032 					break;
7033 				}
7034 
7035 				case 1: /* dvec2 */
7036 				{
7037 					current_uv_pairs = dvec2_uniforms;
7038 					n_pairs			 = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7039 
7040 					break;
7041 				}
7042 
7043 				case 2: /* dvec3 */
7044 				{
7045 					current_uv_pairs = dvec3_uniforms;
7046 					n_pairs			 = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7047 
7048 					break;
7049 				}
7050 
7051 				case 3: /* dvec4 */
7052 				{
7053 					current_uv_pairs = dvec4_uniforms;
7054 					n_pairs			 = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7055 
7056 					break;
7057 				}
7058 
7059 				default:
7060 				{
7061 					TCU_FAIL("Invalid type index requested");
7062 				}
7063 				} /* switch (n_type) */
7064 
7065 				for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7066 				{
7067 					const uniform_value_pair& current_uv_pair  = current_uv_pairs[n_pair];
7068 					glw::GLint				  uniform_location = current_uv_pair.first;
7069 					const double*			  uniform_value	= current_uv_pair.second;
7070 
7071 					/* Retrieve the values from the GL implementation*/
7072 					gl.getUniformdv(po_id, uniform_location, returned_double_data);
7073 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7074 
7075 					gl.getUniformfv(po_id, uniform_location, returned_float_data);
7076 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7077 
7078 					gl.getUniformiv(po_id, uniform_location, returned_int_data);
7079 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7080 
7081 					gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7082 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7083 
7084 					/* Make sure the values reported match the reference values */
7085 					bool		can_continue = true;
7086 					const float epsilon		 = 1e-5f;
7087 
7088 					for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7089 					{
7090 						if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7091 						{
7092 							m_testCtx.getLog()
7093 								<< tcu::TestLog::Message
7094 								<< "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7095 								<< uniform_location << "]"
7096 													   " and component ["
7097 								<< n_component << "]"
7098 												  ": retrieved:["
7099 								<< returned_double_data[n_component] << "]"
7100 																		", expected:["
7101 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7102 
7103 							result = false;
7104 						}
7105 
7106 						if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7107 						{
7108 							m_testCtx.getLog()
7109 								<< tcu::TestLog::Message
7110 								<< "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7111 								<< uniform_location << "]"
7112 													   " and component ["
7113 								<< n_component << "]"
7114 												  ": retrieved:["
7115 								<< returned_float_data[n_component] << "]"
7116 																	   ", expected:["
7117 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7118 
7119 							result = false;
7120 						}
7121 
7122 						/* ints */
7123 						int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7124 						unsigned int rounded_uniform_value_uint =
7125 							(unsigned int)(uniform_value[n_component] > 0.0) ?
7126 								((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7127 								0;
7128 
7129 						if (returned_int_data[n_component] != rounded_uniform_value_sint)
7130 						{
7131 							m_testCtx.getLog()
7132 								<< tcu::TestLog::Message
7133 								<< "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7134 								<< uniform_location << "]"
7135 													   " and component ["
7136 								<< n_component << "]"
7137 												  ": retrieved:["
7138 								<< returned_int_data[n_component] << "]"
7139 																	 ", expected:["
7140 								<< rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7141 
7142 							result = false;
7143 						}
7144 
7145 						if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7146 						{
7147 							m_testCtx.getLog()
7148 								<< tcu::TestLog::Message
7149 								<< "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7150 								<< uniform_location << "]"
7151 													   " and component ["
7152 								<< n_component << "]"
7153 												  ": retrieved:["
7154 								<< returned_uint_data[n_component] << "]"
7155 																	  ", expected:["
7156 								<< rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7157 
7158 							result = false;
7159 						}
7160 					} /* for (all components) */
7161 				}	 /* for (all uniform+value pairs) */
7162 			}		  /* for (all 4 uniform types) */
7163 		}			  /* for (all shader stages) */
7164 	}				  /* for (both program objects) */
7165 
7166 	/* All done! */
7167 	return result;
7168 }
7169 
7170 /** Constructor
7171  *
7172  *  @param context Rendering context.
7173  */
GPUShaderFP64Test5(deqp::Context & context)7174 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7175 	: TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7176 									   " floating-point variables work correctly")
7177 	, m_base_value_bo_data(DE_NULL)
7178 	, m_base_value_bo_id(0)
7179 	, m_has_test_passed(true)
7180 	, m_po_base_value_attribute_location(-1)
7181 	, m_po_id(0)
7182 	, m_vao_id(0)
7183 	, m_vs_id(0)
7184 	, m_xfb_bo_id(0)
7185 	, m_xfb_bo_size(0)
7186 {
7187 	/* Set up base value array (as per test spec) */
7188 	m_base_values[0] = -25.12065f;
7189 	m_base_values[1] = 0.0f;
7190 	m_base_values[2] = 0.001f;
7191 	m_base_values[3] = 1.0f;
7192 	m_base_values[4] = 256.78901f;
7193 
7194 	/* Set up swizzle matrix */
7195 	m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7196 	m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7197 	m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7198 	m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7199 	m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7200 	m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7201 	m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7202 	m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7203 	m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7204 	m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7205 	m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7206 	m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7207 	m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7208 	m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7209 	m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7210 	m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7211 }
7212 
deinit()7213 void GPUShaderFP64Test5::deinit()
7214 {
7215 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7216 
7217 	if (m_base_value_bo_data != DE_NULL)
7218 	{
7219 		delete[] m_base_value_bo_data;
7220 
7221 		m_base_value_bo_data = DE_NULL;
7222 	}
7223 
7224 	if (m_base_value_bo_id != 0)
7225 	{
7226 		gl.deleteBuffers(1, &m_base_value_bo_id);
7227 
7228 		m_base_value_bo_id = 0;
7229 	}
7230 
7231 	if (m_vao_id != 0)
7232 	{
7233 		gl.deleteVertexArrays(1, &m_vao_id);
7234 
7235 		m_vao_id = 0;
7236 	}
7237 
7238 	if (m_xfb_bo_id != 0)
7239 	{
7240 		gl.deleteBuffers(1, &m_xfb_bo_id);
7241 
7242 		m_xfb_bo_id = 0;
7243 	}
7244 
7245 	/* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7246 	 * take care of it here
7247 	 */
7248 	deinitInteration();
7249 }
7250 
7251 /** Deinitializes all buffers and GL objects that may have been generated
7252  *  during test execution.
7253  **/
deinitInteration()7254 void GPUShaderFP64Test5::deinitInteration()
7255 {
7256 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7257 
7258 	if (m_po_id != 0)
7259 	{
7260 		gl.deleteProgram(m_po_id);
7261 
7262 		m_po_id = 0;
7263 	}
7264 
7265 	if (m_vs_id != 0)
7266 	{
7267 		gl.deleteShader(m_vs_id);
7268 
7269 		m_vs_id = 0;
7270 	}
7271 }
7272 
7273 /** Executes a single test case iteration using user-provided test case descriptor.
7274  *
7275  *  This function may throw a TestError exception if GL implementation misbehaves.
7276  *
7277  *  @param test_case Test case descriptor to use.
7278  *
7279  *  @return true if the values returned by GL implementation were found to be valid,
7280  *          false otherwise.
7281  **/
executeIteration(const _test_case & test_case)7282 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7283 {
7284 	bool result = true;
7285 
7286 	/* Convert the base values array to the type of input attribute we'll be using
7287 	 * for the iteration.
7288 	 */
7289 	Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7290 
7291 	if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7292 	{
7293 		/* bools are actually represented by ints, since bool varyings are not allowed */
7294 		base_value_type = Utils::VARIABLE_TYPE_INT;
7295 	}
7296 
7297 	const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7298 	const unsigned int n_base_values			 = sizeof(m_base_values) / sizeof(m_base_values[0]);
7299 
7300 	m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7301 
7302 	unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7303 
7304 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7305 	{
7306 		switch (base_value_type)
7307 		{
7308 		case Utils::VARIABLE_TYPE_DOUBLE:
7309 			*((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7310 			break;
7311 		case Utils::VARIABLE_TYPE_FLOAT:
7312 			*((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7313 			break;
7314 		case Utils::VARIABLE_TYPE_INT:
7315 			*((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7316 			break;
7317 		case Utils::VARIABLE_TYPE_UINT:
7318 			*((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7319 			break;
7320 
7321 		default:
7322 		{
7323 			TCU_FAIL("Unrecognized base value type");
7324 		}
7325 		}
7326 
7327 		base_value_traveller_ptr += base_value_component_size;
7328 	} /* for (all base values) */
7329 
7330 	/* Update buffer object storage with the data we've just finished preparing. */
7331 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7332 
7333 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7334 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7335 
7336 	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7337 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7338 
7339 	/* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7340 	 * new data is interpreted correctly.
7341 	 */
7342 	if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7343 	{
7344 		gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,							  /* size */
7345 							   Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7346 							   0,																  /* stride */
7347 							   DE_NULL);														  /* pointer */
7348 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7349 	}
7350 	else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7351 	{
7352 		gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,						/* size */
7353 								Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7354 								DE_NULL);													/* pointer */
7355 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7356 	}
7357 	else
7358 	{
7359 		DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7360 
7361 		gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7362 								GL_DOUBLE, 0,						   /* stride */
7363 								DE_NULL);							   /* pointer */
7364 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7365 	}
7366 
7367 	gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7368 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7369 
7370 	/* Execute the draw call */
7371 	gl.useProgram(m_po_id);
7372 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7373 
7374 	gl.beginTransformFeedback(GL_POINTS);
7375 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7376 	{
7377 		gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7378 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7379 	}
7380 	gl.endTransformFeedback();
7381 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7382 
7383 	/* Map the XFB buffer object into process space */
7384 	void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7385 
7386 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7387 	DE_ASSERT(xfb_data_ptr != NULL);
7388 
7389 	/* Verify the data */
7390 	result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7391 
7392 	/* Unmap the XFB BO */
7393 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7394 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7395 
7396 	/** Good to release the data buffer at this point */
7397 	if (m_base_value_bo_data != DE_NULL)
7398 	{
7399 		delete[] m_base_value_bo_data;
7400 
7401 		m_base_value_bo_data = DE_NULL;
7402 	}
7403 
7404 	/* All done */
7405 	return result;
7406 }
7407 
7408 /** Returns properties of a swizzle operator described by @param type swizzle type.
7409  *
7410  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
7411  *                             corresponding to the specific swizzle operator.
7412  *                             Must not be NULL.
7413  *  @param out_n_components    Deref will be used to store the amount of components
7414  *                             used by the operator. Must not be NULL.
7415  *  @param out_component_order Deref will be used to store up to 4 integer values,
7416  *                             corresponding to component indices described by the
7417  *                             operator for a particular position.  Must not be NULL.
7418  **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7419 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7420 												  unsigned int* out_n_components, unsigned int* out_component_order)
7421 {
7422 	unsigned int result_component_order[4] = { 0 };
7423 	unsigned int result_n_components	   = 0;
7424 	std::string  result_swizzle_string;
7425 
7426 	switch (type)
7427 	{
7428 	case SWIZZLE_TYPE_NONE:
7429 	{
7430 		result_swizzle_string = "";
7431 		result_n_components   = 0;
7432 
7433 		break;
7434 	}
7435 
7436 	case SWIZZLE_TYPE_XWZY:
7437 	{
7438 		result_swizzle_string	 = "xwzy";
7439 		result_n_components		  = 4;
7440 		result_component_order[0] = 0;
7441 		result_component_order[1] = 3;
7442 		result_component_order[2] = 2;
7443 		result_component_order[3] = 1;
7444 
7445 		break;
7446 	}
7447 
7448 	case SWIZZLE_TYPE_XZXY:
7449 	{
7450 		result_swizzle_string	 = "xzxy";
7451 		result_n_components		  = 4;
7452 		result_component_order[0] = 0;
7453 		result_component_order[1] = 2;
7454 		result_component_order[2] = 0;
7455 		result_component_order[3] = 1;
7456 
7457 		break;
7458 	}
7459 
7460 	case SWIZZLE_TYPE_XZY:
7461 	{
7462 		result_swizzle_string	 = "xzy";
7463 		result_n_components		  = 3;
7464 		result_component_order[0] = 0;
7465 		result_component_order[1] = 2;
7466 		result_component_order[2] = 1;
7467 
7468 		break;
7469 	}
7470 
7471 	case SWIZZLE_TYPE_XZYW:
7472 	{
7473 		result_swizzle_string	 = "xzyw";
7474 		result_n_components		  = 4;
7475 		result_component_order[0] = 0;
7476 		result_component_order[1] = 2;
7477 		result_component_order[2] = 1;
7478 		result_component_order[3] = 3;
7479 
7480 		break;
7481 	}
7482 
7483 	case SWIZZLE_TYPE_Y:
7484 	{
7485 		result_swizzle_string	 = "y";
7486 		result_n_components		  = 1;
7487 		result_component_order[0] = 1;
7488 
7489 		break;
7490 	}
7491 
7492 	case SWIZZLE_TYPE_YX:
7493 	{
7494 		result_swizzle_string	 = "yx";
7495 		result_n_components		  = 2;
7496 		result_component_order[0] = 1;
7497 		result_component_order[1] = 0;
7498 
7499 		break;
7500 	}
7501 
7502 	case SWIZZLE_TYPE_YXX:
7503 	{
7504 		result_swizzle_string	 = "yxx";
7505 		result_n_components		  = 3;
7506 		result_component_order[0] = 1;
7507 		result_component_order[1] = 0;
7508 		result_component_order[2] = 0;
7509 
7510 		break;
7511 	}
7512 
7513 	case SWIZZLE_TYPE_YXXY:
7514 	{
7515 		result_swizzle_string	 = "yxxy";
7516 		result_n_components		  = 4;
7517 		result_component_order[0] = 1;
7518 		result_component_order[1] = 0;
7519 		result_component_order[2] = 0;
7520 		result_component_order[3] = 1;
7521 
7522 		break;
7523 	}
7524 
7525 	case SWIZZLE_TYPE_Z:
7526 	{
7527 		result_swizzle_string	 = "z";
7528 		result_n_components		  = 1;
7529 		result_component_order[0] = 2;
7530 
7531 		break;
7532 	}
7533 
7534 	case SWIZZLE_TYPE_ZY:
7535 	{
7536 		result_swizzle_string	 = "zy";
7537 		result_n_components		  = 2;
7538 		result_component_order[0] = 2;
7539 		result_component_order[1] = 1;
7540 
7541 		break;
7542 	}
7543 
7544 	case SWIZZLE_TYPE_W:
7545 	{
7546 		result_swizzle_string	 = "w";
7547 		result_n_components		  = 1;
7548 		result_component_order[0] = 3;
7549 
7550 		break;
7551 	}
7552 
7553 	case SWIZZLE_TYPE_WX:
7554 	{
7555 		result_swizzle_string	 = "wx";
7556 		result_n_components		  = 2;
7557 		result_component_order[0] = 3;
7558 		result_component_order[1] = 0;
7559 
7560 		break;
7561 	}
7562 
7563 	default:
7564 	{
7565 		TCU_FAIL("Unrecognized swizzle type");
7566 	}
7567 	} /* switch (type) */
7568 
7569 	if (out_swizzle_string != DE_NULL)
7570 	{
7571 		*out_swizzle_string = result_swizzle_string;
7572 	}
7573 
7574 	if (out_n_components != DE_NULL)
7575 	{
7576 		*out_n_components = result_n_components;
7577 	}
7578 
7579 	if (out_component_order != DE_NULL)
7580 	{
7581 		memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7582 	}
7583 }
7584 
7585 /** Returns body of a vertex shader that should be used for particular test case,
7586  *  given user-specified test case descriptor.
7587  *
7588  *  @param test_case Descriptor to use for the query.
7589  *
7590  *  @return Requested data.
7591  **/
getVertexShaderBody(const _test_case & test_case)7592 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7593 {
7594 	std::stringstream  result;
7595 	const std::string  base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7596 	const std::string  dst_type_string  = Utils::getVariableTypeString(test_case.dst_type);
7597 	const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7598 	const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7599 	const std::string  src_type_string  = Utils::getVariableTypeString(test_case.src_type);
7600 
7601 	/* Add version preamble */
7602 	result << "#version 420\n"
7603 			  "\n";
7604 
7605 	/* Declare output variables. Note that boolean output variables are not supported, so we need
7606 	 * to handle that special case correctly */
7607 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7608 	{
7609 		result << "out int result;\n";
7610 	}
7611 	else
7612 	{
7613 		result << "out " << dst_type_string << " result;\n";
7614 	}
7615 
7616 	/* Declare input variables. Handle the bool case exclusively. */
7617 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7618 	{
7619 		/* Use ints for bools. We will cast them to bool in the code later. */
7620 		result << "in int base_value;\n";
7621 	}
7622 	else
7623 	{
7624 		result << "in " << base_type_string << " base_value;\n";
7625 	}
7626 
7627 	/* Declare main() and construct the value we will be casting from.
7628 	 *
7629 	 * Note: Addition operations on bool values cause an implicit conversion to int
7630 	 *       which is not allowed. Hence, we skip these operations for this special
7631 	 *       case.
7632 	 */
7633 	result << "void main()\n"
7634 			  "{\n"
7635 		   << src_type_string << " lside_value = ";
7636 
7637 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7638 	{
7639 		result << src_type_string << "(0 != ";
7640 	}
7641 	else
7642 	{
7643 		result << src_type_string << "(";
7644 	}
7645 
7646 	if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7647 	{
7648 		for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7649 		{
7650 			result << "base_value + " << n_component;
7651 
7652 			if (n_component != (n_src_components - 1))
7653 			{
7654 				result << ", ";
7655 			}
7656 		} /* for (all components) */
7657 	}
7658 	else
7659 	{
7660 		DE_ASSERT(n_src_components == 1);
7661 
7662 		result << "base_value";
7663 	}
7664 
7665 	result << ");\n";
7666 
7667 	/* Perform the casting operation. Add swizzle operator if possible. */
7668 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7669 	{
7670 		/* Handle the bool case exclusively */
7671 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7672 		{
7673 			result << "result = (bool(lside_value) == false) ? 0 : 1";
7674 		}
7675 		else
7676 		{
7677 			result << "result = (lside_value == false) ? 0 : 1";
7678 		}
7679 	}
7680 	else
7681 	{
7682 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7683 		{
7684 			result << "result = " << dst_type_string << "(lside_value)";
7685 		}
7686 		else
7687 		{
7688 			result << "result = lside_value";
7689 		}
7690 	}
7691 
7692 	if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7693 	{
7694 		/* Add a swizzle operator  */
7695 		DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7696 		DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7697 
7698 		unsigned int  swizzle_component_order[4] = { 0 };
7699 		unsigned int  swizzle_n_components		 = 0;
7700 		_swizzle_type swizzle_operator			 = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7701 		std::string   swizzle_string;
7702 
7703 		getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7704 
7705 		if (swizzle_n_components > 0)
7706 		{
7707 			result << "." << swizzle_string;
7708 		}
7709 	}
7710 
7711 	/* Close the shader implementation. */
7712 	result << ";\n"
7713 			  "}\n";
7714 
7715 	return result.str();
7716 }
7717 
7718 /** Initializes program & shader objects needed to run the iteration, given
7719  *  user-specified test case descriptor.
7720  *
7721  *  This function can throw a TestError exception if a GL error is detected
7722  *  during execution.
7723  *
7724  *  @param test_case Descriptor to use for the iteration.
7725  **/
initIteration(_test_case & test_case)7726 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7727 {
7728 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7729 
7730 	/* Create program & shader objects */
7731 	m_po_id = gl.createProgram();
7732 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7733 
7734 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7735 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7736 
7737 	/* Configure shader body */
7738 	std::string body		 = getVertexShaderBody(test_case);
7739 	const char* body_raw_ptr = body.c_str();
7740 
7741 	gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7742 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7743 
7744 	/* Store it in the test case descriptor for logging purposes */
7745 	test_case.shader_body = body;
7746 
7747 	/* Compile the shader */
7748 	glw::GLint compile_status = GL_FALSE;
7749 
7750 	gl.compileShader(m_vs_id);
7751 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7752 
7753 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7754 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7755 
7756 	if (compile_status != GL_TRUE)
7757 	{
7758 		TCU_FAIL("Shader compilation failed");
7759 	}
7760 
7761 	/* Attach the shader to the program obejct */
7762 	gl.attachShader(m_po_id, m_vs_id);
7763 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7764 
7765 	/* Configure XFB for the program object */
7766 	const char* xfb_varying_name = "result";
7767 
7768 	gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7769 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7770 
7771 	/* Link the program object */
7772 	glw::GLint link_status = GL_FALSE;
7773 
7774 	gl.linkProgram(m_po_id);
7775 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7776 
7777 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7778 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7779 
7780 	if (link_status != GL_TRUE)
7781 	{
7782 		TCU_FAIL("Program linking failed");
7783 	}
7784 
7785 	/* Retrieve attribute locations */
7786 	m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7787 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7788 
7789 	if (m_po_base_value_attribute_location == -1)
7790 	{
7791 		TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7792 	}
7793 }
7794 
7795 /** Initializes GL objects used by all test cases.
7796  *
7797  *  This function may throw a TestError exception if GL implementation reports
7798  *  an error at any point.
7799  **/
initTest()7800 void GPUShaderFP64Test5::initTest()
7801 {
7802 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7803 
7804 	/* Generate buffer object IDs */
7805 	gl.genBuffers(1, &m_base_value_bo_id);
7806 	gl.genBuffers(1, &m_xfb_bo_id);
7807 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7808 
7809 	/* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7810 	 * will never eat up more than 1 double (as per test spec) and we will be drawing
7811 	 * as many points in a single draw call as there are defined in m_base_values array.
7812 	 */
7813 	const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7814 
7815 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7816 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7817 
7818 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7820 
7821 	/* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7822 	 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7823 	 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7824 	 */
7825 	const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7826 
7827 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7828 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7829 
7830 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7831 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7832 
7833 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7834 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7835 
7836 	/* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7837 	m_xfb_bo_size = xfb_bo_size;
7838 
7839 	/* Generate a vertex array object we will need to use for the draw calls */
7840 	gl.genVertexArrays(1, &m_vao_id);
7841 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7842 
7843 	gl.bindVertexArray(m_vao_id);
7844 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7845 }
7846 
7847 /** Executes test iteration.
7848  *
7849  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7850  */
iterate()7851 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7852 {
7853 	/* Do not execute the test if GL_ARB_texture_view is not supported */
7854 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7855 	{
7856 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7857 	}
7858 
7859 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7860 	{
7861 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7862 	}
7863 
7864 	/* Initialize GL objects needed to run the tests */
7865 	initTest();
7866 
7867 	/* Build iteration array to run the tests in an automated manner */
7868 	_test_case test_cases[] = {
7869 		/* test case type */ /* source type */ /* destination type */
7870 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7871 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7872 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7873 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7874 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7875 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7876 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7877 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7878 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7879 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7880 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7881 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7882 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7883 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7884 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7885 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7886 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7887 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7888 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7889 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7890 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7891 
7892 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7893 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7894 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7895 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7896 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7897 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7898 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7899 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7900 	};
7901 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7902 
7903 	/* Execute all iterations */
7904 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7905 	{
7906 		_test_case& test_case = test_cases[n_test_case];
7907 
7908 		/* Initialize a program object we will use to perform the casting */
7909 		initIteration(test_case);
7910 
7911 		/* Use the program object to XFB the results */
7912 		m_has_test_passed &= executeIteration(test_case);
7913 
7914 		/* Release the GL Resource for this sub test */
7915 		deinitInteration();
7916 
7917 	} /* for (all test cases) */
7918 	/* We're done */
7919 	if (m_has_test_passed)
7920 	{
7921 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7922 	}
7923 	else
7924 	{
7925 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7926 	}
7927 
7928 	return STOP;
7929 }
7930 
7931 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7932  *  for which the data have been generated.
7933  *
7934  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
7935  *  @param test_case Descriptor of the test case, for which the vertex shader was
7936  *                   generated.
7937  *
7938  *  @return true if the data were found to be valid, false otherwise.
7939  **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7940 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7941 {
7942 	const Utils::_variable_type base_dst_type		= Utils::getBaseVariableType(test_case.dst_type);
7943 	const Utils::_variable_type base_src_type		= Utils::getBaseVariableType(test_case.src_type);
7944 	const float					epsilon				= 1e-5f;
7945 	const unsigned int			n_base_values		= sizeof(m_base_values) / sizeof(m_base_values[0]);
7946 	const unsigned int			n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7947 	const unsigned int			n_src_components	= Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7948 	bool						result				= true;
7949 	_swizzle_type				swizzle_operator	= SWIZZLE_TYPE_NONE;
7950 	unsigned int				swizzle_order[4]	= { 0 };
7951 	const unsigned char*		traveller_ptr		= data_ptr;
7952 
7953 	if (!Utils::isMatrixVariableType(test_case.src_type))
7954 	{
7955 		DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7956 		DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7957 
7958 		swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7959 
7960 		getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7961 								 DE_NULL,					/* out_n_components */
7962 								 swizzle_order);
7963 	}
7964 
7965 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7966 	{
7967 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7968 		{
7969 			unsigned int n_swizzled_component = n_result_component;
7970 
7971 			if (swizzle_operator != SWIZZLE_TYPE_NONE)
7972 			{
7973 				n_swizzled_component =
7974 					(n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7975 			}
7976 
7977 			switch (base_dst_type)
7978 			{
7979 			case Utils::VARIABLE_TYPE_BOOL:
7980 			case Utils::VARIABLE_TYPE_INT:
7981 			{
7982 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7983 				double expected_value	 = ref_expected_value;
7984 				int	result_value		  = *((int*)traveller_ptr);
7985 
7986 				if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7987 				{
7988 					if (expected_value != 0.0)
7989 					{
7990 						expected_value = 1.0;
7991 					}
7992 				}
7993 
7994 				if (result_value != (int)expected_value)
7995 				{
7996 					m_testCtx.getLog() << tcu::TestLog::Message
7997 									   << "Invalid boolean/integer value obtained when doing an "
7998 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
7999 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8000 									   << "]"
8001 										  ", component index: ["
8002 									   << n_swizzled_component << "]"
8003 																  ", value: ["
8004 									   << ref_expected_value << "]"
8005 																" to GLSL type ["
8006 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8007 																							  ", retrieved value: ["
8008 									   << result_value << "]"
8009 														  ", expected value: ["
8010 									   << (int)expected_value << "]"
8011 																 ", shader used:\n"
8012 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8013 
8014 					result = false;
8015 				}
8016 
8017 				traveller_ptr += sizeof(int);
8018 				break;
8019 			} /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8020 
8021 			case Utils::VARIABLE_TYPE_DOUBLE:
8022 			{
8023 				double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8024 				double expected_value	 = ref_expected_value;
8025 				double result_value		  = *((double*)traveller_ptr);
8026 
8027 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8028 				{
8029 					expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8030 				}
8031 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8032 				{
8033 					expected_value = (int)expected_value;
8034 				}
8035 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8036 				{
8037 					// Negative values in base values array when converted to unsigned int will be ZERO
8038 					// Addition operations done inside the shader in such cases will operate on ZERO rather
8039 					// than the negative value being passed.
8040 					// Replicate the sequence of conversion and addition operations done on the
8041 					// shader input, to calculate the expected values in XFB data in the
8042 					// problematic cases.
8043 					if (expected_value < 0)
8044 					{
8045 						expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8046 					}
8047 					expected_value = (unsigned int)expected_value;
8048 				}
8049 
8050 				traveller_ptr += sizeof(double);
8051 				if (de::abs(result_value - expected_value) > epsilon)
8052 				{
8053 					m_testCtx.getLog() << tcu::TestLog::Message
8054 									   << "Invalid double-precision floating-point value obtained when doing an "
8055 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8056 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8057 									   << "]"
8058 										  ", component index: ["
8059 									   << n_swizzled_component << "]"
8060 																  ", value: ["
8061 									   << ref_expected_value << "]"
8062 																" to GLSL type ["
8063 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8064 																							  ", retrieved value: ["
8065 									   << std::setprecision(16) << result_value << "]"
8066 																				   ", expected value: ["
8067 									   << std::setprecision(16) << expected_value << "]"
8068 																					 ", shader used:\n"
8069 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8070 
8071 					result = false;
8072 				}
8073 
8074 				break;
8075 			} /* VARIABLE_TYPE_DOUBLE case */
8076 
8077 			case Utils::VARIABLE_TYPE_FLOAT:
8078 			{
8079 				float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8080 				float expected_value	 = ref_expected_value;
8081 				float result_value		 = *((float*)traveller_ptr);
8082 
8083 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8084 				{
8085 					expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8086 				}
8087 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8088 				{
8089 					expected_value = (float)((int)expected_value);
8090 				}
8091 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8092 				{
8093 					expected_value = (float)((unsigned int)expected_value);
8094 				}
8095 
8096 				traveller_ptr += sizeof(float);
8097 				if (de::abs(result_value - expected_value) > epsilon)
8098 				{
8099 					m_testCtx.getLog() << tcu::TestLog::Message
8100 									   << "Invalid single-precision floating-point value obtained when doing an "
8101 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8102 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8103 									   << "]"
8104 										  ", component index: ["
8105 									   << n_swizzled_component << "]"
8106 																  ", value: ["
8107 									   << ref_expected_value << "]"
8108 																" to GLSL type ["
8109 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8110 																							  ", retrieved value: ["
8111 									   << std::setprecision(16) << result_value << "]"
8112 																				   ", expected value: ["
8113 									   << std::setprecision(16) << expected_value << "]"
8114 																					 ", shader used:\n"
8115 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8116 
8117 					result = false;
8118 				}
8119 
8120 				break;
8121 			} /* VARIABLE_TYPE_FLOAT case */
8122 
8123 			case Utils::VARIABLE_TYPE_UINT:
8124 			{
8125 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8126 				double expected_value	 = ref_expected_value;
8127 				unsigned int result_value = *((unsigned int*)traveller_ptr);
8128 
8129 				traveller_ptr += sizeof(unsigned int);
8130 				if (result_value != (unsigned int)expected_value)
8131 				{
8132 					if (expected_value < 0.0)
8133 					{
8134 						// It is undefined to convert a negative floating-point value to an uint.
8135 						break;
8136 					}
8137 
8138 					m_testCtx.getLog() << tcu::TestLog::Message
8139 									   << "Invalid unsigned integer value obtained when doing an "
8140 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8141 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8142 									   << "]"
8143 										  ", component index: ["
8144 									   << n_swizzled_component << "]"
8145 																  ", value: ["
8146 									   << ref_expected_value << "]"
8147 																" to GLSL type ["
8148 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8149 																							  ", retrieved value: ["
8150 									   << result_value << "]"
8151 														  ", expected value: ["
8152 									   << (unsigned int)expected_value << "]"
8153 																		  ", shader used:\n"
8154 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8155 
8156 					result = false;
8157 				}
8158 
8159 				break;
8160 			} /* VARIABLE_TYPE_UINT case */
8161 
8162 			default:
8163 			{
8164 				TCU_FAIL("Unrecognized variable type");
8165 			}
8166 			} /* switch (test_case.dst_type) */
8167 		}	 /* for (all result components) */
8168 	}		  /* for (all base values) */
8169 
8170 	return result;
8171 }
8172 
8173 /** Constructor
8174  *
8175  *  @param context Rendering context.
8176  */
GPUShaderFP64Test6(deqp::Context & context)8177 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8178 	: TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8179 											   "during compilation time.")
8180 	, m_cs_id(0)
8181 	, m_fs_id(0)
8182 	, m_gs_id(0)
8183 	, m_tc_id(0)
8184 	, m_te_id(0)
8185 	, m_vs_id(0)
8186 	, m_has_test_passed(true)
8187 {
8188 }
8189 
8190 /** Deinitializes all buffers and GL objects that may have been generated
8191  *  during test execution.
8192  **/
deinit()8193 void GPUShaderFP64Test6::deinit()
8194 {
8195 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8196 
8197 	if (m_cs_id != 0)
8198 	{
8199 		gl.deleteShader(m_cs_id);
8200 
8201 		m_cs_id = 0;
8202 	}
8203 
8204 	if (m_fs_id != 0)
8205 	{
8206 		gl.deleteShader(m_fs_id);
8207 
8208 		m_fs_id = 0;
8209 	}
8210 
8211 	if (m_gs_id != 0)
8212 	{
8213 		gl.deleteShader(m_gs_id);
8214 
8215 		m_gs_id = 0;
8216 	}
8217 
8218 	if (m_tc_id != 0)
8219 	{
8220 		gl.deleteShader(m_tc_id);
8221 
8222 		m_tc_id = 0;
8223 	}
8224 
8225 	if (m_te_id != 0)
8226 	{
8227 		gl.deleteShader(m_te_id);
8228 
8229 		m_te_id = 0;
8230 	}
8231 
8232 	if (m_vs_id != 0)
8233 	{
8234 		gl.deleteShader(m_vs_id);
8235 
8236 		m_vs_id = 0;
8237 	}
8238 }
8239 
8240 /** Executes a single test case.
8241  *
8242  *  This function can throw TestError exceptions if GL implementation reports
8243  *  an error.
8244  *
8245  *  @param test_case Test case descriptor.
8246  *
8247  *  @return true if test case passed, false otherwise.
8248  **/
executeIteration(const _test_case & test_case)8249 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8250 {
8251 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
8252 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8253 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
8254 	bool				  result	 = true;
8255 	const char*			  stage_body = NULL;
8256 	const char*			  stage_name = NULL;
8257 
8258 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8259 	{
8260 		const glw::GLuint so_id = so_ids[n_so_id];
8261 
8262 		/* Skip compute shader if it is not supported */
8263 		if (0 == so_id)
8264 		{
8265 			continue;
8266 		}
8267 
8268 		/* Compile the shader */
8269 		gl.compileShader(so_id);
8270 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8271 
8272 		/* Has the compilation failed as expected? */
8273 		glw::GLint compile_status = GL_TRUE;
8274 
8275 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8276 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8277 
8278 		if (compile_status == GL_TRUE)
8279 		{
8280 			/* What is the current stage's name? */
8281 			if (so_id == m_cs_id)
8282 			{
8283 				stage_body = test_case.cs_shader_body.c_str();
8284 				stage_name = "Compute shader";
8285 			}
8286 			else if (so_id == m_fs_id)
8287 			{
8288 				stage_body = test_case.fs_shader_body.c_str();
8289 				stage_name = "Fragment shader";
8290 			}
8291 			else if (so_id == m_gs_id)
8292 			{
8293 				stage_body = test_case.gs_shader_body.c_str();
8294 				stage_name = "Geometry shader";
8295 			}
8296 			else if (so_id == m_tc_id)
8297 			{
8298 				stage_body = test_case.tc_shader_body.c_str();
8299 				stage_name = "Tessellation control shader";
8300 			}
8301 			else if (so_id == m_te_id)
8302 			{
8303 				stage_body = test_case.te_shader_body.c_str();
8304 				stage_name = "Tessellation evaluation shader";
8305 			}
8306 			else if (so_id == m_vs_id)
8307 			{
8308 				stage_body = test_case.vs_shader_body.c_str();
8309 				stage_name = "Vertex shader";
8310 			}
8311 			else
8312 			{
8313 				/* Doesn't make much sense to throw exceptions here so.. */
8314 				stage_body = "";
8315 				stage_name = "[?]";
8316 			}
8317 
8318 			/* This shader should have never compiled successfully! */
8319 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8320 							   << " has been compiled successfully, even though the shader was malformed."
8321 								  " Following is shader body:\n"
8322 							   << stage_body << tcu::TestLog::EndMessage;
8323 
8324 			result = false;
8325 		}
8326 	} /* for (all shader objects) */
8327 
8328 	return result;
8329 }
8330 
8331 /** Retrieves body of a compute shader that should be used for the purpose of
8332  *  user-specified test case.
8333  *
8334  *  @param test_case Test case descriptor to use.
8335  *
8336  *  @return Requested string.
8337  **/
getComputeShaderBody(const _test_case & test_case)8338 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8339 {
8340 	std::stringstream result_sstream;
8341 
8342 	/* Add pre-amble */
8343 	result_sstream << "#version 420\n"
8344 					  "#extension GL_ARB_compute_shader          : require\n"
8345 					  "\n"
8346 					  "layout(local_size_x = 6) in;\n"
8347 					  "\n"
8348 					  "void main()\n"
8349 					  "{\n";
8350 
8351 	/* Add local variable declarations */
8352 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8353 
8354 	if (test_case.src_array_size > 1)
8355 	{
8356 		result_sstream << "[" << test_case.src_array_size << "]";
8357 	}
8358 
8359 	result_sstream << ";\n";
8360 
8361 	if (test_case.wrap_dst_type_in_structure)
8362 	{
8363 		result_sstream << "struct\n"
8364 						  "{\n"
8365 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8366 	}
8367 	else
8368 	{
8369 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8370 	}
8371 
8372 	result_sstream << ";\n";
8373 
8374 	if (test_case.wrap_dst_type_in_structure)
8375 	{
8376 		result_sstream << "\n} dst;\n";
8377 	}
8378 
8379 	/* Add actual body */
8380 	result_sstream << "dst = src;\n"
8381 					  "}\n";
8382 
8383 	/* Return the body */
8384 	return result_sstream.str();
8385 }
8386 
8387 /** Retrieves body of a fragment shader that should be used for the purpose of
8388  *  user-specified test case.
8389  *
8390  *  @param test_case Test case descriptor to use.
8391  *
8392  *  @return Requested string.
8393  **/
getFragmentShaderBody(const _test_case & test_case)8394 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8395 {
8396 	std::stringstream result_sstream;
8397 
8398 	/* Add pre-amble */
8399 	result_sstream << "#version 420\n"
8400 					  "\n"
8401 					  "void main()\n"
8402 					  "{\n";
8403 
8404 	/* Add local variable declarations */
8405 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8406 
8407 	if (test_case.src_array_size > 1)
8408 	{
8409 		result_sstream << "[" << test_case.src_array_size << "]";
8410 	}
8411 
8412 	result_sstream << ";\n";
8413 
8414 	if (test_case.wrap_dst_type_in_structure)
8415 	{
8416 		result_sstream << "struct\n"
8417 						  "{\n"
8418 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8419 	}
8420 	else
8421 	{
8422 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8423 	}
8424 
8425 	result_sstream << ";\n";
8426 
8427 	if (test_case.wrap_dst_type_in_structure)
8428 	{
8429 		result_sstream << "\n} dst;\n";
8430 	}
8431 
8432 	/* Add actual body */
8433 	result_sstream << "dst = src;\n"
8434 					  "}\n";
8435 
8436 	/* Return the body */
8437 	return result_sstream.str();
8438 }
8439 
8440 /** Retrieves body of a geometry shader that should be used for the purpose of
8441  *  user-specified test case.
8442  *
8443  *  @param test_case Test case descriptor to use.
8444  *
8445  *  @return Requested string.
8446  **/
getGeometryShaderBody(const _test_case & test_case)8447 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8448 {
8449 	std::stringstream result_sstream;
8450 
8451 	/* Add preamble */
8452 	result_sstream << "#version 420\n"
8453 					  "\n"
8454 					  "layout(points)                 in;\n"
8455 					  "layout(max_vertices=1, points) out;\n"
8456 					  "\n"
8457 					  "void main()\n"
8458 					  "{\n";
8459 
8460 	/* Add local variable declarations */
8461 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8462 
8463 	if (test_case.src_array_size > 1)
8464 	{
8465 		result_sstream << "[" << test_case.src_array_size << "]";
8466 	}
8467 
8468 	result_sstream << ";\n";
8469 
8470 	if (test_case.wrap_dst_type_in_structure)
8471 	{
8472 		result_sstream << "struct\n"
8473 						  "{\n"
8474 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8475 	}
8476 	else
8477 	{
8478 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8479 	}
8480 
8481 	result_sstream << ";\n"
8482 					  "\n";
8483 
8484 	if (test_case.wrap_dst_type_in_structure)
8485 	{
8486 		result_sstream << "} dst;\n";
8487 	}
8488 
8489 	/* Add actual body */
8490 	result_sstream << "dst = src;\n"
8491 					  "}\n";
8492 
8493 	/* We're done! */
8494 	return result_sstream.str();
8495 }
8496 
8497 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8498  *  user-specified test case.
8499  *
8500  *  @param test_case Test case descriptor to use.
8501  *
8502  *  @return Requested string.
8503  **/
getTessellationControlShaderBody(const _test_case & test_case)8504 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8505 {
8506 	std::stringstream result_sstream;
8507 
8508 	/* Add preamble */
8509 	result_sstream << "#version 420\n"
8510 					  "\n"
8511 					  "layout(vertices=4) out;\n"
8512 					  "\n"
8513 					  "void main()\n"
8514 					  "{\n";
8515 
8516 	/* Add local variable declarations. */
8517 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8518 
8519 	if (test_case.src_array_size > 1)
8520 	{
8521 		result_sstream << "[" << test_case.src_array_size << "]";
8522 	}
8523 
8524 	result_sstream << ";\n";
8525 
8526 	if (test_case.wrap_dst_type_in_structure)
8527 	{
8528 		result_sstream << "struct\n"
8529 						  "{\n"
8530 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8531 	}
8532 	else
8533 	{
8534 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8535 	}
8536 
8537 	if (test_case.wrap_dst_type_in_structure)
8538 	{
8539 		result_sstream << ";\n"
8540 						  "} dst;\n";
8541 	}
8542 	else
8543 	{
8544 		result_sstream << ";\n";
8545 	}
8546 
8547 	/* Continue with the actual body. */
8548 	result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8549 					  "gl_TessLevelOuter[1] = 1.0;\n"
8550 					  "dst                  = src;\n"
8551 					  "}\n";
8552 
8553 	/* Return the body */
8554 	return result_sstream.str();
8555 }
8556 
8557 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8558  *  user-specified test case.
8559  *
8560  *  @param test_case Test case descriptor to use.
8561  *
8562  *  @return Requested string.
8563  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8564 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8565 {
8566 	std::stringstream result_sstream;
8567 
8568 	/* Add preamble */
8569 	result_sstream << "#version 420\n"
8570 					  "\n"
8571 					  "layout(isolines) in;\n"
8572 					  "\n"
8573 					  "void main()\n"
8574 					  "{\n";
8575 
8576 	/* Add local variable declarations */
8577 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8578 
8579 	if (test_case.src_array_size > 1)
8580 	{
8581 		result_sstream << "[" << test_case.src_array_size << "]";
8582 	}
8583 
8584 	result_sstream << ";\n";
8585 
8586 	if (test_case.wrap_dst_type_in_structure)
8587 	{
8588 		result_sstream << "struct\n"
8589 						  "{\n"
8590 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8591 	}
8592 	else
8593 	{
8594 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8595 	}
8596 
8597 	if (test_case.wrap_dst_type_in_structure)
8598 	{
8599 		result_sstream << ";\n"
8600 						  "} dst;\n";
8601 	}
8602 	else
8603 	{
8604 		result_sstream << ";\n";
8605 	}
8606 
8607 	/* Continue with the actual body. */
8608 	result_sstream << "dst = src;\n";
8609 
8610 	/* Complete the body */
8611 	result_sstream << "}\n";
8612 
8613 	/* Return the body */
8614 	return result_sstream.str();
8615 }
8616 
8617 /** Retrieves body of a vertex shader that should be used for the purpose of
8618  *  user-specified test case.
8619  *
8620  *  @param test_case Test case descriptor to use.
8621  *
8622  *  @return Requested string.
8623  **/
getVertexShaderBody(const _test_case & test_case)8624 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8625 {
8626 	std::stringstream result_sstream;
8627 
8628 	/* Add preamble */
8629 	result_sstream << "#version 420\n"
8630 					  "\n"
8631 					  "void main()\n"
8632 					  "{\n";
8633 
8634 	/* Add local variables */
8635 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8636 
8637 	if (test_case.src_array_size > 1)
8638 	{
8639 		result_sstream << "[" << test_case.src_array_size << "]";
8640 	}
8641 
8642 	result_sstream << ";\n";
8643 
8644 	if (test_case.wrap_dst_type_in_structure)
8645 	{
8646 		result_sstream << "struct\n"
8647 						  "{\n"
8648 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8649 	}
8650 	else
8651 	{
8652 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8653 	}
8654 
8655 	if (test_case.wrap_dst_type_in_structure)
8656 	{
8657 		result_sstream << ";\n"
8658 						  "} dst;\n";
8659 	}
8660 	else
8661 	{
8662 		result_sstream << ";\n";
8663 	}
8664 
8665 	/* Start actual body */
8666 	result_sstream << "dst         = src;\n"
8667 					  "gl_Position = vec4(1.0);\n"
8668 					  "}";
8669 
8670 	return result_sstream.str();
8671 }
8672 
8673 /** Initializes shader objects required to run the test. */
initTest()8674 void GPUShaderFP64Test6::initTest()
8675 {
8676 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8677 
8678 	/* Generate shader objects */
8679 
8680 	/* Compute shader support and GL 4.2 required */
8681 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8682 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8683 	{
8684 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8685 	}
8686 
8687 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8688 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8689 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8690 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8691 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8692 
8693 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8694 }
8695 
8696 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8697  *
8698  *  @param test_case Test case descriptor to generate the shader bodies for.
8699  **/
initIteration(_test_case & test_case)8700 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8701 {
8702 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8703 
8704 	test_case.cs_shader_body = getComputeShaderBody(test_case);
8705 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
8706 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
8707 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8708 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8709 	test_case.vs_shader_body = getVertexShaderBody(test_case);
8710 
8711 	/* Assign the bodies to relevant shaders */
8712 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8713 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8714 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8715 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8716 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8717 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8718 
8719 	/* m_cs_id is initialized only if compute_shader is supported */
8720 	if (0 != m_cs_id)
8721 	{
8722 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8723 	}
8724 
8725 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8726 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8727 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8728 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8729 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8730 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8731 }
8732 
8733 /** Executes test iteration.
8734  *
8735  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8736  */
iterate()8737 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8738 {
8739 	/* Do not execute the test if GL_ARB_texture_view is not supported */
8740 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8741 	{
8742 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8743 	}
8744 
8745 	/* Initialize GL objects needed to run the tests */
8746 	initTest();
8747 
8748 	/* Build iteration array to run the tests in an automated manner */
8749 	_test_case test_cases[] = {
8750 		/* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8751 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8752 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8753 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8754 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8755 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8756 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8757 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8758 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8759 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8760 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8761 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8762 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8763 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8764 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8765 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8766 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8767 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8768 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8769 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8770 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8771 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8772 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8773 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8774 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8775 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8776 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8777 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8778 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8779 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8780 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8781 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8782 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8783 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8784 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8785 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8786 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8787 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8788 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8789 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8790 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8791 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8792 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8793 	};
8794 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8795 
8796 	/* Execute all iterations */
8797 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8798 	{
8799 		_test_case& test_case = test_cases[n_test_case];
8800 
8801 		/* Initialize a program object we will use to perform the casting */
8802 		initIteration(test_case);
8803 
8804 		/* Use the program object to XFB the results */
8805 		m_has_test_passed &= executeIteration(test_case);
8806 
8807 	} /* for (all test cases) */
8808 
8809 	/* We're done */
8810 	if (m_has_test_passed)
8811 	{
8812 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8813 	}
8814 	else
8815 	{
8816 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8817 	}
8818 
8819 	return STOP;
8820 }
8821 
8822 /** Constructor
8823  *
8824  *  @param context Rendering context.
8825  */
GPUShaderFP64Test7(deqp::Context & context)8826 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8827 	: TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8828 									"in all shader stages.")
8829 	, m_are_double_inputs_supported(false)
8830 	, m_fbo_id(0)
8831 	, m_fs_id(0)
8832 	, m_gs_id(0)
8833 	, m_has_test_passed(true)
8834 	, m_n_max_components_per_stage(0)
8835 	, m_n_xfb_varyings(0)
8836 	, m_po_id(0)
8837 	, m_tc_id(0)
8838 	, m_te_id(0)
8839 	, m_to_id(0)
8840 	, m_to_data(NULL)
8841 	, m_to_height(4)
8842 	, m_to_width(4)
8843 	, m_xfb_bo_id(0)
8844 	, m_xfb_varyings(NULL)
8845 	, m_vao_id(0)
8846 	, m_vs_id(0)
8847 {
8848 }
8849 
8850 /** Compiles all shaders attached to test program object and links it.
8851  *
8852  *  @param variables
8853  *
8854  *  @return true if the process was executed successfully, false otherwise.
8855  */
buildTestProgram(_variables & variables)8856 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8857 {
8858 	std::string			  fs_body = getFragmentShaderBody(variables);
8859 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
8860 	std::string			  gs_body = getGeometryShaderBody(variables);
8861 	std::string			  tc_body = getTessellationControlShaderBody(variables);
8862 	std::string			  te_body = getTessellationEvaluationShaderBody(variables);
8863 	std::string			  vs_body = getVertexShaderBody(variables);
8864 	bool				  result  = false;
8865 
8866 	/* Try to link the program object */
8867 	glw::GLint link_status = GL_FALSE;
8868 
8869 	/* Compile the shaders */
8870 	if (!compileShader(m_fs_id, fs_body))
8871 	{
8872 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8873 
8874 		goto end;
8875 	}
8876 
8877 	if (!compileShader(m_gs_id, gs_body))
8878 	{
8879 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8880 
8881 		goto end;
8882 	}
8883 
8884 	if (!compileShader(m_tc_id, tc_body))
8885 	{
8886 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8887 						   << tcu::TestLog::EndMessage;
8888 
8889 		goto end;
8890 	}
8891 
8892 	if (!compileShader(m_te_id, te_body))
8893 	{
8894 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8895 						   << tcu::TestLog::EndMessage;
8896 
8897 		goto end;
8898 	}
8899 
8900 	if (!compileShader(m_vs_id, vs_body))
8901 	{
8902 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8903 
8904 		goto end;
8905 	}
8906 
8907 	/* Configure XFB */
8908 	releaseXFBVaryingNames();
8909 	generateXFBVaryingNames(variables);
8910 
8911 	gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8912 
8913 	gl.linkProgram(m_po_id);
8914 
8915 	/* Have we succeeded? */
8916 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8917 
8918 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8919 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8920 
8921 	if (link_status != GL_TRUE)
8922 	{
8923 		m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8924 						   << tcu::TestLog::EndMessage;
8925 
8926 		goto end;
8927 	}
8928 
8929 	/* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8930 	if (m_are_double_inputs_supported)
8931 	{
8932 		const size_t n_variables = variables.size();
8933 
8934 		for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8935 		{
8936 			_variable&		  current_variable = variables[n_variable];
8937 			std::stringstream attribute_name_sstream;
8938 
8939 			attribute_name_sstream << "in_vs_variable" << n_variable;
8940 
8941 			if (current_variable.array_size > 1)
8942 			{
8943 				attribute_name_sstream << "[0]";
8944 			}
8945 
8946 			current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8947 
8948 			if (current_variable.attribute_location == -1)
8949 			{
8950 				m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8951 								   << attribute_name_sstream.str().c_str()
8952 								   << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8953 
8954 				m_has_test_passed = false;
8955 				goto end;
8956 			}
8957 		} /* for (all test variables) */
8958 	}	 /* if (m_are_double_inputs_supported) */
8959 
8960 	m_current_fs_body = fs_body;
8961 	m_current_gs_body = gs_body;
8962 	m_current_tc_body = tc_body;
8963 	m_current_te_body = te_body;
8964 	m_current_vs_body = vs_body;
8965 
8966 	result = true;
8967 
8968 end:
8969 	return result;
8970 }
8971 
8972 /** Updates shader object's body and then compiles the shader.
8973  *
8974  *  @param body Body to use for the shader.
8975  *
8976  *  @return true if the shader compiled successfully, false otherwise.
8977  **/
compileShader(glw::GLint shader_id,const std::string & body)8978 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8979 {
8980 	const char*			  body_raw_ptr   = body.c_str();
8981 	glw::GLint			  compile_status = GL_FALSE;
8982 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
8983 
8984 	gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8985 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8986 
8987 	gl.compileShader(shader_id);
8988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8989 
8990 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8991 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8992 
8993 	return (compile_status == GL_TRUE);
8994 }
8995 
8996 /** Configure storage of a buffer object used for capturing XFB data.
8997  *
8998  *  @param variables Holds descriptor for all variables used for the iteration the
8999  *                   BO is being configured for. Storage size will be directly related
9000  *                   to the number of the variables and their type.
9001  */
configureXFBBuffer(const _variables & variables)9002 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9003 {
9004 	DE_ASSERT(m_n_xfb_varyings != 0);
9005 
9006 	/* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9007 	 * The test only draws a single patch, and triangles are caught by transform feed-back.
9008 	 * Let's initialize the storage, according to the list of variables that will be used
9009 	 * for the test run.
9010 	 */
9011 	unsigned int bo_size = 0;
9012 
9013 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9014 		 variables_iterator++)
9015 	{
9016 		const _variable& variable		= *variables_iterator;
9017 		unsigned int	 n_bytes_needed = static_cast<unsigned int>(
9018 			Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9019 
9020 		bo_size += n_bytes_needed;
9021 	} /* for (all variables) */
9022 
9023 	bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9024 
9025 	/* Set up the BO storage */
9026 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9027 
9028 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9029 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9030 }
9031 
9032 /** Deinitializes all buffers and GL objects that may have been generated
9033  *  during test execution.
9034  **/
deinit()9035 void GPUShaderFP64Test7::deinit()
9036 {
9037 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9038 
9039 	if (m_fbo_id != 0)
9040 	{
9041 		gl.deleteFramebuffers(1, &m_fbo_id);
9042 
9043 		m_fbo_id = 0;
9044 	}
9045 
9046 	if (m_fs_id != 0)
9047 	{
9048 		gl.deleteShader(m_fs_id);
9049 
9050 		m_fs_id = 0;
9051 	}
9052 
9053 	if (m_gs_id != 0)
9054 	{
9055 		gl.deleteShader(m_gs_id);
9056 
9057 		m_gs_id = 0;
9058 	}
9059 
9060 	if (m_po_id != 0)
9061 	{
9062 		gl.deleteProgram(m_po_id);
9063 
9064 		m_po_id = 0;
9065 	}
9066 
9067 	if (m_tc_id != 0)
9068 	{
9069 		gl.deleteShader(m_tc_id);
9070 
9071 		m_tc_id = 0;
9072 	}
9073 
9074 	if (m_te_id != 0)
9075 	{
9076 		gl.deleteShader(m_te_id);
9077 
9078 		m_te_id = 0;
9079 	}
9080 
9081 	if (m_to_data != NULL)
9082 	{
9083 		delete[] m_to_data;
9084 
9085 		m_to_data = NULL;
9086 	}
9087 
9088 	if (m_to_id != 0)
9089 	{
9090 		gl.deleteTextures(1, &m_to_id);
9091 
9092 		m_to_id = 0;
9093 	}
9094 
9095 	if (m_xfb_bo_id != 0)
9096 	{
9097 		gl.deleteBuffers(1, &m_xfb_bo_id);
9098 
9099 		m_xfb_bo_id = 0;
9100 	}
9101 
9102 	if (m_xfb_varyings != DE_NULL)
9103 	{
9104 		releaseXFBVaryingNames();
9105 	}
9106 
9107 	if (m_vao_id != 0)
9108 	{
9109 		gl.deleteVertexArrays(1, &m_vao_id);
9110 
9111 		m_vao_id = 0;
9112 	}
9113 
9114 	if (m_vs_id != 0)
9115 	{
9116 		gl.deleteShader(m_vs_id);
9117 
9118 		m_vs_id = 0;
9119 	}
9120 }
9121 
9122 /** Executes the functional part of the test (case a) from the test spec)
9123  *
9124  *  @param variables Vector of variable descriptors defining properties of
9125  *                   variables that should be used for the iteration.
9126  *
9127  *  @return true if the test passed, false otherwise.
9128  **/
executeFunctionalTest(_variables & variables)9129 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9130 {
9131 	bool result = true;
9132 
9133 	/* Build the test program */
9134 	if (!buildTestProgram(variables))
9135 	{
9136 		return false;
9137 	}
9138 
9139 	/* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9140 	if (m_are_double_inputs_supported)
9141 	{
9142 		setInputAttributeValues(variables);
9143 	}
9144 
9145 	/* Set up buffer object to hold XFB data. The data will be used for logging purposes
9146 	 * only, if a data mismatch is detected.
9147 	 */
9148 	configureXFBBuffer(variables);
9149 
9150 	/* Issue a draw call using the test program */
9151 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9152 
9153 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9154 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9155 
9156 	gl.clear(GL_COLOR_BUFFER_BIT);
9157 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9158 
9159 	gl.useProgram(m_po_id);
9160 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9161 
9162 	gl.viewport(0, /* x */
9163 				0, /* y */
9164 				m_to_width, m_to_height);
9165 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9166 
9167 	gl.beginTransformFeedback(GL_TRIANGLES);
9168 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9169 	{
9170 		gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9171 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9172 	}
9173 	gl.endTransformFeedback();
9174 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9175 
9176 	/* Verify color attachment contents */
9177 	const float epsilon = 1.0f / 255.0f;
9178 
9179 	gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9180 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9181 
9182 	for (unsigned int y = 0; y < m_to_height; ++y)
9183 	{
9184 		const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9185 
9186 		for (unsigned int x = 0; x < m_to_width; ++x)
9187 		{
9188 			const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9189 
9190 			if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9191 				de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9192 			{
9193 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9194 								   << ")"
9195 									  "; expected:(0, 255, 0, 0), found: ("
9196 								   << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9197 								   << ", " << (int)pixel_ptr[3]
9198 								   << "), with the following variable types used as varyings:"
9199 								   << tcu::TestLog::EndMessage;
9200 
9201 				/* List the variable types that failed the test */
9202 				const size_t n_variables = variables.size();
9203 
9204 				for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9205 				{
9206 					m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9207 									   << Utils::getVariableTypeString(variables[n_variable].type)
9208 									   << " (array size:" << variables[n_variable].array_size << ")"
9209 									   << tcu::TestLog::EndMessage;
9210 				} /* for (all variable types) */
9211 
9212 				/* Log the variable contents */
9213 				logVariableContents(variables);
9214 
9215 				/* Log shaders used for the iteration */
9216 				m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9217 															   "\n"
9218 															   "(VS):\n"
9219 								   << m_current_vs_body.c_str() << "\n"
9220 								   << "(TC):\n"
9221 									  "\n"
9222 								   << m_current_tc_body.c_str() << "\n"
9223 																   "(TE):\n"
9224 																   "\n"
9225 								   << m_current_te_body.c_str() << "\n"
9226 																   "(GS):\n"
9227 								   << m_current_gs_body.c_str() << "\n"
9228 																   "(FS):\n"
9229 																   "\n"
9230 								   << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9231 
9232 				result = false;
9233 
9234 				goto end;
9235 			}
9236 		} /* for (all columns) */
9237 	}	 /* for (all rows) */
9238 
9239 /* All done! */
9240 end:
9241 	return result;
9242 }
9243 
9244 /** Takes user-input vector of test variables and allocates & fills an array of strings
9245  *  holding names of geometry shader stage varyings that should be captured during
9246  *  transform feedback operation. The array will be stored in m_xfb_varyings.
9247  *
9248  *  @param variables Holds all test variable descriptors to be used for the iteration.
9249  */
generateXFBVaryingNames(const _variables & variables)9250 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9251 {
9252 	unsigned int n_variable = 0;
9253 	unsigned int n_varying  = 0;
9254 	unsigned int n_varyings = 0;
9255 
9256 	if (m_xfb_varyings != NULL)
9257 	{
9258 		releaseXFBVaryingNames();
9259 	}
9260 
9261 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9262 		 ++variables_iterator)
9263 	{
9264 		const _variable& variable = *variables_iterator;
9265 
9266 		n_varyings += variable.array_size;
9267 	}
9268 
9269 	m_xfb_varyings = new glw::GLchar*[n_varyings];
9270 
9271 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9272 		 ++variables_iterator, ++n_variable)
9273 	{
9274 		const _variable& variable = *variables_iterator;
9275 
9276 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9277 		{
9278 			std::stringstream varying_sstream;
9279 			size_t			  varying_length;
9280 
9281 			varying_sstream << "gs_variable" << n_variable;
9282 
9283 			if (variable.array_size > 1)
9284 			{
9285 				varying_sstream << "[" << array_index << "]";
9286 			}
9287 
9288 			/* Store the varying name */
9289 			varying_length			  = varying_sstream.str().length();
9290 			m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9291 
9292 			memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9293 			m_xfb_varyings[n_varying][varying_length] = 0;
9294 		} /* for (all array indices) */
9295 	}	 /* for (all varyings) */
9296 
9297 	m_n_xfb_varyings = n_varyings;
9298 }
9299 
9300 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9301  *  without using the "flat" keyword. (case c) )
9302  *
9303  *  @param input_variable_type Variable type to use for input variable declaration.
9304  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9305  *                             of the arrayed variable.
9306  *
9307  *  @return Requested string.
9308  **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9309 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9310 	Utils::_variable_type input_variable_type, unsigned int array_size)
9311 {
9312 	std::stringstream result_sstream;
9313 	std::stringstream array_index_stringstream;
9314 	std::stringstream array_size_stringstream;
9315 
9316 	if (array_size > 1)
9317 	{
9318 		array_index_stringstream << "[0]";
9319 		array_size_stringstream << "[" << array_size << "]";
9320 	}
9321 
9322 	if (Utils::isMatrixVariableType(input_variable_type))
9323 	{
9324 		array_index_stringstream << "[0].x";
9325 	}
9326 	else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9327 	{
9328 		array_index_stringstream << "[0]";
9329 	}
9330 
9331 	result_sstream << "#version 400\n"
9332 					  "\n"
9333 					  "in "
9334 				   << Utils::getVariableTypeString(input_variable_type) << " test_input"
9335 				   << array_size_stringstream.str() << ";\n"
9336 													   "\n"
9337 													   "out float test_output;\n"
9338 													   "\n"
9339 													   "void main()\n"
9340 													   "{\n"
9341 													   "    if (test_input"
9342 				   << array_index_stringstream.str() << " > 2.0)\n"
9343 														"    {\n"
9344 														"        test_output = 1.0;\n"
9345 														"    }\n"
9346 														"    else\n"
9347 														"    {\n"
9348 														"        test_output = 3.0;\n"
9349 														"    }\n"
9350 														"}\n";
9351 
9352 	return result_sstream.str();
9353 }
9354 
9355 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9356  *
9357  *  @param input_variable_type Variable type to use for input variable declaration.
9358  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9359  *                             of the arrayed variable.
9360  *
9361  *  @return Requested string.
9362  **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9363 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9364 	Utils::_variable_type output_variable_type, unsigned int array_size)
9365 {
9366 	std::stringstream array_index_sstream;
9367 	std::stringstream array_size_sstream;
9368 	std::stringstream result_sstream;
9369 	std::string		  output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9370 
9371 	if (array_size > 1)
9372 	{
9373 		array_index_sstream << "[0]";
9374 		array_size_sstream << "[" << array_size << "]";
9375 	}
9376 
9377 	result_sstream << "#version 400\n"
9378 					  "\n"
9379 					  "out "
9380 				   << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9381 																								   "\n"
9382 																								   "void main()\n"
9383 																								   "{\n"
9384 																								   "    test_output"
9385 				   << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9386 																						   "}\n";
9387 
9388 	return result_sstream.str();
9389 }
9390 
9391 /** Retrieves body of a fragment shader that uses user-specified set of variables
9392  *  to declare contents of input & output block.
9393  *
9394  *  @param variables As per description.
9395  *
9396  *  @return Requested string.
9397  **/
getFragmentShaderBody(const _variables & variables)9398 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9399 {
9400 	std::stringstream result_sstream;
9401 
9402 	/* Form the pre-amble */
9403 	result_sstream << "#version 400\n"
9404 					  "\n"
9405 
9406 				   /* Add input block */
9407 				   << "in GS_DATA\n"
9408 					  "{\n"
9409 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9410 																		  "\n"
9411 
9412 				   /* Add output variable */
9413 				   << "out vec4 result;\n"
9414 					  "\n"
9415 
9416 					  /* Add main() definition */
9417 					  "void main()\n"
9418 					  "{\n"
9419 					  "const double epsilon = 1e-5;\n"
9420 					  "\n"
9421 					  "result = vec4(1, 0, 0, 0);\n"
9422 					  "\n";
9423 
9424 	/* Determine expected values first */
9425 	unsigned int base_counter = 1;
9426 	const size_t n_variables  = variables.size();
9427 
9428 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9429 	{
9430 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9431 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9432 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9433 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9434 
9435 		std::stringstream array_size_sstream;
9436 
9437 		if (variable_array_size > 1)
9438 		{
9439 			array_size_sstream << "[" << variable_array_size << "]";
9440 		}
9441 
9442 		/* Local variable declaration */
9443 		result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9444 					   << ";\n"
9445 						  "\n";
9446 
9447 		/* Set expected values */
9448 		for (unsigned int index = 0; index < variable_array_size; ++index)
9449 		{
9450 			std::stringstream array_index_sstream;
9451 
9452 			if (variable_array_size > 1)
9453 			{
9454 				array_index_sstream << "[" << index << "]";
9455 			}
9456 
9457 			result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9458 						   << variable_type_string << "(";
9459 
9460 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9461 			{
9462 				unsigned int expected_value =
9463 					(base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9464 
9465 				if (m_are_double_inputs_supported)
9466 				{
9467 					/* VS input attributes */
9468 					//expected_value += (base_counter + 6);
9469 					expected_value -= 1;
9470 				}
9471 
9472 				result_sstream << expected_value;
9473 
9474 				if (n_component != (n_variable_type_components - 1))
9475 				{
9476 					result_sstream << ", ";
9477 				}
9478 
9479 				++base_counter;
9480 			} /* for (all components) */
9481 
9482 			result_sstream << ");\n";
9483 		} /* for (all array indices) */
9484 
9485 		result_sstream << "\n";
9486 	} /* for (all variable types) */
9487 
9488 	/* Now that we know the expected values, do a huge conditional check to verify if all
9489 	 * input variables carry correct information.
9490 	 */
9491 	result_sstream << "if (";
9492 
9493 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9494 	{
9495 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9496 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9497 		bool				  is_variable_type_matrix	= Utils::isMatrixVariableType(variable_type);
9498 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9499 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9500 
9501 		for (unsigned int index = 0; index < variable_array_size; ++index)
9502 		{
9503 			std::stringstream array_index_sstream;
9504 
9505 			if (variable_array_size > 1)
9506 			{
9507 				array_index_sstream << "[" << index << "]";
9508 			}
9509 
9510 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9511 			{
9512 				std::stringstream component_index_sstream;
9513 
9514 				if (n_variable_type_components > 1)
9515 				{
9516 					component_index_sstream << "[" << n_component << "]";
9517 				}
9518 
9519 				result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9520 
9521 				if (is_variable_type_matrix)
9522 				{
9523 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9524 					const unsigned int column	= n_component % n_columns;
9525 					const unsigned int row		 = n_component / n_columns;
9526 
9527 					result_sstream << "[" << column << "]"
9528 													   "."
9529 								   << Utils::getComponentAtIndex(row);
9530 				}
9531 				else
9532 				{
9533 					result_sstream << component_index_sstream.str();
9534 				}
9535 
9536 				result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9537 
9538 				if (is_variable_type_matrix)
9539 				{
9540 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9541 					const unsigned int column	= n_component % n_columns;
9542 					const unsigned int row		 = n_component / n_columns;
9543 
9544 					result_sstream << "[" << column << "]"
9545 													   "."
9546 								   << Utils::getComponentAtIndex(row);
9547 				}
9548 				else
9549 				{
9550 					result_sstream << component_index_sstream.str();
9551 				}
9552 
9553 				result_sstream << ") <= epsilon &&";
9554 			} /* for (all components) */
9555 		}	 /* for (all array indices) */
9556 	}		  /* for (all variable types) */
9557 
9558 	result_sstream << "true)\n"
9559 					  "{\n"
9560 					  "    result = vec4(0, 1, 0, 0);\n"
9561 					  "}\n"
9562 					  "}\n";
9563 
9564 	/* All done */
9565 	return result_sstream.str();
9566 }
9567 
9568 /** Retrieves body of a geometry shader that uses user-specified set of variables
9569  *  to declare contents of input & output block.
9570  *
9571  *  @param variables As per description.
9572  *
9573  *  @return Requested string.
9574  **/
getGeometryShaderBody(const _variables & variables)9575 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9576 {
9577 	std::stringstream result_sstream;
9578 
9579 	/* Form the pre-amble */
9580 	result_sstream << "#version 400\n"
9581 					  "\n"
9582 					  "layout(triangles)                      in;\n"
9583 					  "layout(triangle_strip, max_vertices=4) out;\n"
9584 					  "\n"
9585 
9586 					  /* Add the input block */
9587 					  "in TE_DATA\n"
9588 					  "{\n"
9589 				   << getVariableDeclarations("te", variables) << "} in_data[];\n"
9590 																  "\n"
9591 
9592 																  /* Add the output block */
9593 																  "out GS_DATA\n"
9594 																  "{\n"
9595 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9596 																		  "\n"
9597 
9598 																		  /* Declare main() function */
9599 																		  "void main()\n"
9600 																		  "{\n";
9601 
9602 	/* Take input variables, add a predefined value and forward them to output variables */
9603 	const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9604 									1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
9605 	const unsigned int n_quad_vertices =
9606 		sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9607 	const size_t n_variables = variables.size();
9608 
9609 	for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9610 	{
9611 		unsigned int counter			 = 4;
9612 		const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9613 
9614 		for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9615 		{
9616 			unsigned int		  variable_array_size = variables[n_variable].array_size;
9617 			Utils::_variable_type variable_type		  = variables[n_variable].type;
9618 			unsigned int n_variable_type_components   = Utils::getNumberOfComponentsForVariableType(variable_type);
9619 			std::string  variable_type_string		  = Utils::getVariableTypeString(variable_type);
9620 
9621 			for (unsigned int index = 0; index < variable_array_size; ++index)
9622 			{
9623 				std::stringstream array_index_sstream;
9624 
9625 				if (variable_array_size > 1)
9626 				{
9627 					array_index_sstream << "[" << index << "]";
9628 				}
9629 
9630 				result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9631 							   << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9632 							   << variable_type_string << "(";
9633 
9634 				for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9635 				{
9636 					result_sstream << (counter++);
9637 
9638 					if (n_component != (n_variable_type_components - 1))
9639 					{
9640 						result_sstream << ", ";
9641 					}
9642 				} /* for (all components) */
9643 
9644 				result_sstream << ");\n";
9645 			} /* for (all array indices) */
9646 		}	 /* for (all variable types) */
9647 
9648 		result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9649 					   << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9650 																					  "EmitVertex();\n";
9651 	} /* for (all emitted quad vertices) */
9652 
9653 	result_sstream << "EndPrimitive();\n"
9654 					  "}\n";
9655 
9656 	/* All done */
9657 	return result_sstream.str();
9658 }
9659 
9660 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9661  *  to declare contents of input & output block.
9662  *
9663  *  @param variables As per description.
9664  *
9665  *  @return Requested string.
9666  **/
getTessellationControlShaderBody(const _variables & variables)9667 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9668 {
9669 	std::stringstream result_sstream;
9670 
9671 	/* Form the pre-amble */
9672 	result_sstream << "#version 400\n"
9673 					  "\n"
9674 					  "layout (vertices=4) out;\n"
9675 
9676 					  /* Declare input block */
9677 					  "in VS_DATA\n"
9678 					  "{\n"
9679 				   << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9680 
9681 																  /* Declare output block */
9682 																  "out TC_DATA\n"
9683 																  "{\n"
9684 				   << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9685 																  "\n"
9686 
9687 																  /* Define main() */
9688 																  "void main()\n"
9689 																  "{\n"
9690 																  "    gl_TessLevelInner[0] = 1;\n"
9691 																  "    gl_TessLevelInner[1] = 1;\n"
9692 																  "    gl_TessLevelOuter[0] = 1;\n"
9693 																  "    gl_TessLevelOuter[1] = 1;\n"
9694 																  "    gl_TessLevelOuter[2] = 1;\n"
9695 																  "    gl_TessLevelOuter[3] = 1;\n"
9696 																  "\n";
9697 
9698 	/* Take input variables, add a predefined value and forward them to output variables */
9699 	const size_t n_variables = variables.size();
9700 	unsigned int counter	 = 2;
9701 
9702 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9703 	{
9704 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9705 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9706 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9707 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9708 
9709 		for (unsigned int index = 0; index < variable_array_size; ++index)
9710 		{
9711 			std::stringstream array_index_sstream;
9712 
9713 			if (variable_array_size > 1)
9714 			{
9715 				array_index_sstream << "[" << index << "]";
9716 			}
9717 
9718 			result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9719 						   << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9720 						   << variable_type_string << "(";
9721 
9722 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9723 			{
9724 				result_sstream << (counter++);
9725 
9726 				if (n_component != (n_variable_type_components - 1))
9727 				{
9728 					result_sstream << ", ";
9729 				}
9730 			}
9731 
9732 			result_sstream << ");\n";
9733 		} /* for (all array indices) */
9734 	}	 /* for (all variable types) */
9735 
9736 	result_sstream << "}\n";
9737 
9738 	/* We're done */
9739 	return result_sstream.str();
9740 }
9741 
9742 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9743  *  to declare contents of input & output block.
9744  *
9745  *  @param variables As per description.
9746  *
9747  *  @return Requested string.
9748  **/
getTessellationEvaluationShaderBody(const _variables & variables)9749 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9750 {
9751 	std::stringstream result_sstream;
9752 
9753 	/* Form the pre-amble */
9754 	result_sstream << "#version 400\n"
9755 					  "\n"
9756 					  "layout(quads) in;\n"
9757 					  "\n"
9758 
9759 					  /* Define input block */
9760 					  "in TC_DATA\n"
9761 					  "{\n"
9762 				   << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9763 																  "\n"
9764 
9765 																  /* Define output block */
9766 																  "out TE_DATA\n"
9767 																  "{\n"
9768 				   << getVariableDeclarations("te", variables) << "};\n"
9769 																  "\n"
9770 
9771 																  /* Define main() */
9772 																  "void main()\n"
9773 																  "{\n";
9774 
9775 	/* Take input variables, add a predefined value and forward them to output variables */
9776 	const size_t n_variables = variables.size();
9777 	unsigned int counter	 = 3;
9778 
9779 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9780 	{
9781 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9782 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9783 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9784 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9785 
9786 		for (unsigned int index = 0; index < variable_array_size; ++index)
9787 		{
9788 			std::stringstream array_index_sstream;
9789 
9790 			if (variable_array_size > 1)
9791 			{
9792 				array_index_sstream << "[" << index << "]";
9793 			}
9794 
9795 			result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9796 						   << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9797 
9798 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9799 			{
9800 				result_sstream << (counter++);
9801 
9802 				if (n_component != (n_variable_type_components - 1))
9803 				{
9804 					result_sstream << ", ";
9805 				}
9806 			} /* for (all components) */
9807 
9808 			result_sstream << ");\n";
9809 		} /* for (all array indices) */
9810 	}	 /* for (all variable types) */
9811 
9812 	result_sstream << "}\n";
9813 
9814 	/* All done */
9815 	return result_sstream.str();
9816 }
9817 
9818 /** Returns a string containing declarations of user-specified set of variables.
9819  *  Each declaration can optionally use a layot qualifier requested by the caller.
9820  *
9821  *  @param prefix             Prefix to use for variable names.
9822  *  @param variables          List of variables to declare in the result string.
9823  *  @param explicit_locations true if each declaration should explicitly define location
9824  *                            of the variable ( eg. (layout location=X) )
9825  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
9826  *                            be NULL.
9827  *
9828  *  @return Requested string.
9829  **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9830 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9831 														const char* layout_qualifier)
9832 {
9833 	std::stringstream result_sstream;
9834 
9835 	/* Define output variables */
9836 	const size_t n_variables = variables.size();
9837 
9838 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9839 	{
9840 		unsigned int		  variable_array_size  = variables[n_variable].array_size;
9841 		Utils::_variable_type variable_type		   = variables[n_variable].type;
9842 		std::string			  variable_type_string = Utils::getVariableTypeString(variable_type);
9843 
9844 		result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9845 
9846 		if (variable_array_size > 1)
9847 		{
9848 			result_sstream << "[" << variable_array_size << "]";
9849 		}
9850 
9851 		result_sstream << ";\n";
9852 	} /* for (all user-specified variable types) */
9853 
9854 	return result_sstream.str();
9855 }
9856 
9857 /** Retrieves body of a vertex shader that uses user-specified set of variables
9858  *  to declare contents of input & output block.
9859  *
9860  *  @param variables As per description.
9861  *
9862  *  @return Requested string.
9863  **/
getVertexShaderBody(const _variables & variables)9864 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9865 {
9866 	std::stringstream result_sstream;
9867 
9868 	/* Form pre-amble */
9869 	result_sstream << "#version 400\n"
9870 					  "\n";
9871 
9872 	/* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9873 	if (m_are_double_inputs_supported)
9874 	{
9875 		result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9876 					   << getVariableDeclarations("in_vs", variables, "in");
9877 	}
9878 
9879 	/* Define output variables */
9880 	result_sstream << "out VS_DATA\n"
9881 					  "{\n"
9882 				   << getVariableDeclarations("vs", variables);
9883 
9884 	/* Define main() */
9885 	result_sstream << "};\n"
9886 					  "\n"
9887 					  "void main()\n"
9888 					  "{\n";
9889 
9890 	/* Set output variable values */
9891 	unsigned int counter	 = 1;
9892 	const size_t n_variables = variables.size();
9893 
9894 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9895 	{
9896 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9897 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9898 		const unsigned int	n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9899 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9900 
9901 		for (unsigned int index = 0; index < variable_array_size; ++index)
9902 		{
9903 			if (variable_array_size == 1)
9904 			{
9905 				result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9906 			}
9907 			else
9908 			{
9909 				result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9910 							   << " = " << variable_type_string << "(";
9911 			}
9912 
9913 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9914 			{
9915 				result_sstream << (double)(counter++);
9916 
9917 				/* Use input attributes, if available */
9918 				if (m_are_double_inputs_supported)
9919 				{
9920 					result_sstream << " + in_vs_variable" << n_variable;
9921 
9922 					if (variable_array_size > 1)
9923 					{
9924 						result_sstream << "[" << index << "]";
9925 					}
9926 
9927 					if (Utils::isMatrixVariableType(variables[n_variable].type))
9928 					{
9929 						const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9930 						const unsigned int column	= n_component % n_columns;
9931 						const unsigned int row		 = n_component / n_columns;
9932 
9933 						result_sstream << "[" << (column) << "]"
9934 															 "."
9935 									   << Utils::getComponentAtIndex(row);
9936 					}
9937 					else if (n_variable_type_components > 1)
9938 					{
9939 						result_sstream << "[" << n_component << "]";
9940 					}
9941 				}
9942 
9943 				if (n_component != (n_variable_type_components - 1))
9944 				{
9945 					result_sstream << ", ";
9946 				}
9947 			} /* for (all components) */
9948 
9949 			result_sstream << ");\n";
9950 		}
9951 	} /* for (all variable types) */
9952 
9953 	/* We will be using geometry shader to lay out the actual vertices so
9954 	 * the only thing we need to make sure is that the vertex never gets
9955 	 * culled.
9956 	 */
9957 	result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9958 					  "}\n";
9959 
9960 	/* That's it */
9961 	return result_sstream.str();
9962 }
9963 
9964 /** Initializes shader objects required to run the test. */
initTest()9965 void GPUShaderFP64Test7::initTest()
9966 {
9967 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9968 
9969 	/* Are double-precision input variables supported? */
9970 	m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9971 
9972 	/* Create a vertex array object */
9973 	gl.genVertexArrays(1, &m_vao_id);
9974 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9975 
9976 	gl.bindVertexArray(m_vao_id);
9977 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9978 
9979 	/* Create a texture object we will use as FBO's color attachment */
9980 	gl.genTextures(1, &m_to_id);
9981 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9982 
9983 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9984 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9985 
9986 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9987 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9988 
9989 	/* Allocate temporary buffer to hold the texture data we will be reading
9990 	 * from color attachment. */
9991 	m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9992 
9993 	/* Create and set up a framebuffer object */
9994 	gl.genFramebuffers(1, &m_fbo_id);
9995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9996 
9997 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
9999 
10000 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10001 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10002 
10003 	/* Create all shader objects */
10004 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10005 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10006 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10007 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10008 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10009 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10010 
10011 	/* Create test program object */
10012 	m_po_id = gl.createProgram();
10013 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10014 
10015 	/* Attach the shaders to the program object */
10016 	gl.attachShader(m_po_id, m_fs_id);
10017 	gl.attachShader(m_po_id, m_gs_id);
10018 	gl.attachShader(m_po_id, m_tc_id);
10019 	gl.attachShader(m_po_id, m_te_id);
10020 	gl.attachShader(m_po_id, m_vs_id);
10021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10022 
10023 	/* The test passes double-precision values through the whole rendering pipeline.
10024 	 * This translates to a notable amount of components that we would need to transfer
10025 	 * all values in one fell swoop. The number is large enough to exceed minimum
10026 	 * capabilities as described for OpenGL 4.0 implementations.
10027 	 * For that reason, the test executes in turns. Each turn is allocated as many
10028 	 * double-precision scalar/matrix values as supported by the tested GL implementation.
10029 	 */
10030 	glw::GLint gl_max_fragment_input_components_value				  = 0;
10031 	glw::GLint gl_max_geometry_input_components_value				  = 0;
10032 	glw::GLint gl_max_geometry_output_components_value				  = 0;
10033 	glw::GLint gl_max_tess_control_input_components_value			  = 0;
10034 	glw::GLint gl_max_tess_control_output_components_value			  = 0;
10035 	glw::GLint gl_max_tess_evaluation_input_components_value		  = 0;
10036 	glw::GLint gl_max_tess_evaluation_output_components_value		  = 0;
10037 	glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10038 	glw::GLint gl_max_vertex_output_components_value				  = 0;
10039 
10040 	gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10041 	gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10042 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10043 	gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10044 	gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10045 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10046 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10047 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10048 				   &gl_max_transform_feedback_interleaved_components_value);
10049 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10050 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10051 
10052 	m_n_max_components_per_stage =
10053 		de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10054 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10055 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10056 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10057 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10058 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10059 	m_n_max_components_per_stage =
10060 		de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10061 	m_n_max_components_per_stage =
10062 		de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10063 
10064 	/* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10065 	 * the input patch */
10066 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
10067 
10068 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10069 
10070 	/* Initialize a BO we will use to hold XFB data */
10071 	gl.genBuffers(1, &m_xfb_bo_id);
10072 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10073 
10074 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10076 
10077 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10079 }
10080 
10081 /** Executes test iteration.
10082  *
10083  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10084  */
iterate()10085 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10086 {
10087 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10088 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10089 	{
10090 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10091 	}
10092 
10093 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10094 	{
10095 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10096 	}
10097 
10098 	/* Initialize GL objects required to run the test */
10099 	initTest();
10100 
10101 	/* Check the negative cases first */
10102 	const Utils::_variable_type double_variable_types[] = {
10103 		Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10104 		Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10105 		Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10106 		Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10107 		Utils::VARIABLE_TYPE_DMAT4X3,
10108 	};
10109 	const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10110 
10111 	for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10112 		 ++n_double_variable_type)
10113 	{
10114 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
10115 		{
10116 			Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10117 
10118 			if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10119 			{
10120 				m_testCtx.getLog() << tcu::TestLog::Message
10121 								   << "A fragment shader with double-precision output variable compiled successfully."
10122 								   << tcu::TestLog::EndMessage;
10123 
10124 				m_has_test_passed = false;
10125 			}
10126 
10127 			if (compileShader(m_fs_id,
10128 							  getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10129 			{
10130 				m_testCtx.getLog()
10131 					<< tcu::TestLog::Message
10132 					<< "A fragment shader with double-precision input variables lacking flat layout qualifier"
10133 					   " compiled successfully."
10134 					<< tcu::TestLog::EndMessage;
10135 
10136 				m_has_test_passed = false;
10137 			}
10138 		}
10139 	} /* for (all variable types) */
10140 
10141 	/* Execute functional test. Split the run into as many iterations as necessary
10142 	 * so that we do not exceed GL implementation's capabilities. */
10143 	unsigned int n_tested_variables = 0;
10144 	_variables   variables_to_test;
10145 
10146 	while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10147 	{
10148 		glw::GLint total_n_used_components = 0;
10149 
10150 		/* Use as many variables as possible for the iterations. Do not exceed maximum amount
10151 		 * of varying components that can be used for all shadr stages.
10152 		 */
10153 		while (total_n_used_components < m_n_max_components_per_stage &&
10154 			   n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10155 		{
10156 			_variable	new_variable;
10157 			unsigned int n_type_components = 0;
10158 			glw::GLint   n_used_components = 0;
10159 
10160 			new_variable.array_size =
10161 				((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10162 			new_variable.type = double_variable_types[n_tested_variables / 2];
10163 
10164 			/* Double-precision varyings can use twice as many components as single-precision FPs */
10165 			n_type_components = 4 /* components per location */ *
10166 								Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10167 			n_used_components = n_type_components * new_variable.array_size * 2;
10168 
10169 			/* Do we have enough space? */
10170 			if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10171 			{
10172 				if (n_used_components > m_n_max_components_per_stage)
10173 				{ //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10174 					n_tested_variables++;
10175 				}
10176 				break;
10177 			}
10178 
10179 			/* We can safely test the type in current iteration */
10180 			total_n_used_components += n_used_components;
10181 			n_tested_variables++;
10182 
10183 			variables_to_test.push_back(new_variable);
10184 		}
10185 
10186 		if (variables_to_test.size() > 0)
10187 		{
10188 			m_has_test_passed &= executeFunctionalTest(variables_to_test);
10189 
10190 			variables_to_test.clear();
10191 		}
10192 	}
10193 
10194 	/* We're done */
10195 	if (m_has_test_passed)
10196 	{
10197 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10198 	}
10199 	else
10200 	{
10201 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10202 	}
10203 
10204 	return STOP;
10205 }
10206 
10207 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10208 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10209 {
10210 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10211 	std::stringstream	 log_sstream;
10212 
10213 	log_sstream << "Test variable values as retrieved from geometry shader:\n";
10214 
10215 	/* Map the XFB BO contents into process space */
10216 	const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10217 
10218 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10219 
10220 	/* Read the variable contents. We only care about the set of varyings emitted
10221 	 * for first vertex in the geometry shader */
10222 	unsigned int		 n_varying	 = 0;
10223 	const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10224 
10225 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10226 		 ++variables_iterator, ++n_varying)
10227 	{
10228 		const _variable&			 variable			= *variables_iterator;
10229 		const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10230 		const unsigned int			 n_components		= Utils::getNumberOfComponentsForVariableType(variable.type);
10231 
10232 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10233 		{
10234 			log_sstream << "gs_variable" << n_varying;
10235 
10236 			if (variable.array_size > 1)
10237 			{
10238 				log_sstream << "[" << array_index << "]";
10239 			}
10240 
10241 			log_sstream << ": (";
10242 
10243 			for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10244 			{
10245 				log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10246 
10247 				if (n_component != (n_components - 1))
10248 				{
10249 					log_sstream << ", ";
10250 				}
10251 
10252 				traveller_ptr += sizeof(double);
10253 			}
10254 
10255 			log_sstream << ")\n";
10256 		} /* for (all array indices) */
10257 	}	 /* for (all variables) */
10258 
10259 	/* Unmap the BO */
10260 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10261 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10262 
10263 	/* Pass the logged stream into the framework */
10264 	m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10265 }
10266 
10267 /** De-allocates an arary holding strings representing names of varyings that
10268  *  should be used for transform feed-back.
10269  **/
releaseXFBVaryingNames()10270 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10271 {
10272 	for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10273 	{
10274 		delete[] m_xfb_varyings[n_varying];
10275 	}
10276 
10277 	delete[] m_xfb_varyings;
10278 	m_xfb_varyings = DE_NULL;
10279 
10280 	m_n_xfb_varyings = 0;
10281 }
10282 
10283 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10284  *  Takes a list of test variables used for current iteration and assigns increasing values
10285  *  to subsequent input attributes of the test program.
10286  *
10287  *  @param variables Test variables of the current iteration.
10288  */
setInputAttributeValues(const _variables & variables)10289 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10290 {
10291 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
10292 
10293 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10294 		 variable_iterator++)
10295 	{
10296 		const _variable&   variable			  = *variable_iterator;
10297 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
10298 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10299 		unsigned int	   n_components		  = 0;
10300 		unsigned int	   n_columns		  = 1;
10301 
10302 		if (is_matrix_type)
10303 		{
10304 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
10305 			n_components = n_total_components / n_columns;
10306 
10307 			DE_ASSERT(n_total_components % n_columns == 0);
10308 		}
10309 		else
10310 		{
10311 			n_components = n_total_components;
10312 		}
10313 
10314 		DE_ASSERT(n_components >= 1 && n_components <= 4);
10315 
10316 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10317 		{
10318 			const double data[] = { -1, -1, -1, -1 };
10319 
10320 			switch (n_components)
10321 			{
10322 			case 1:
10323 			{
10324 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
10325 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10326 
10327 				break;
10328 			}
10329 
10330 			case 2:
10331 			{
10332 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
10333 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10334 
10335 				break;
10336 			}
10337 
10338 			case 3:
10339 			{
10340 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
10341 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10342 
10343 				break;
10344 			}
10345 
10346 			case 4:
10347 			{
10348 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
10349 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10350 
10351 				break;
10352 			}
10353 
10354 			default:
10355 			{
10356 				TCU_FAIL("Unrecognized number of components");
10357 			}
10358 			} /* switch (n_components) */
10359 
10360 			/* Make sure VAAs are disabled */
10361 			gl.disableVertexAttribArray(variable.attribute_location + index);
10362 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10363 		} /* for (all array indices) */
10364 	}	 /* for (all variables) */
10365 }
10366 
10367 /** Constructor
10368  *
10369  *  @param context Rendering context.
10370  */
GPUShaderFP64Test8(deqp::Context & context)10371 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10372 	: TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10373 											  "are accepted during compilation stage")
10374 	, m_cs_id(0)
10375 	, m_fs_id(0)
10376 	, m_gs_id(0)
10377 	, m_tc_id(0)
10378 	, m_te_id(0)
10379 	, m_vs_id(0)
10380 	, m_has_test_passed(true)
10381 {
10382 }
10383 
10384 /** Deinitializes all buffers and GL objects that may have been generated
10385  *  during test execution.
10386  **/
deinit()10387 void GPUShaderFP64Test8::deinit()
10388 {
10389 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10390 
10391 	if (m_cs_id != 0)
10392 	{
10393 		gl.deleteShader(m_cs_id);
10394 
10395 		m_cs_id = 0;
10396 	}
10397 
10398 	if (m_fs_id != 0)
10399 	{
10400 		gl.deleteShader(m_fs_id);
10401 
10402 		m_fs_id = 0;
10403 	}
10404 
10405 	if (m_gs_id != 0)
10406 	{
10407 		gl.deleteShader(m_gs_id);
10408 
10409 		m_gs_id = 0;
10410 	}
10411 
10412 	if (m_tc_id != 0)
10413 	{
10414 		gl.deleteShader(m_tc_id);
10415 
10416 		m_tc_id = 0;
10417 	}
10418 
10419 	if (m_te_id != 0)
10420 	{
10421 		gl.deleteShader(m_te_id);
10422 
10423 		m_te_id = 0;
10424 	}
10425 
10426 	if (m_vs_id != 0)
10427 	{
10428 		gl.deleteShader(m_vs_id);
10429 
10430 		m_vs_id = 0;
10431 	}
10432 }
10433 
10434 /** Executes a single test case.
10435  *
10436  *  This function can throw TestError exceptions if GL implementation reports
10437  *  an error.
10438  *
10439  *  @param test_case Test case descriptor.
10440  *
10441  *  @return true if test case passed, false otherwise.
10442  **/
executeIteration(const _test_case & test_case)10443 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10444 {
10445 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10446 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10447 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
10448 	bool				  result	 = true;
10449 	const char*			  stage_body = NULL;
10450 	const char*			  stage_name = NULL;
10451 
10452 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10453 	{
10454 		const glw::GLuint so_id = so_ids[n_so_id];
10455 
10456 		/* Skip compute shader if it is not supported */
10457 		if (0 == so_id)
10458 		{
10459 			continue;
10460 		}
10461 
10462 		/* Compile the shader */
10463 		gl.compileShader(so_id);
10464 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10465 
10466 		/* Has the compilation succeeded as expected? */
10467 		glw::GLint compile_status = GL_FALSE;
10468 
10469 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10470 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10471 
10472 		if (compile_status == GL_FALSE)
10473 		{
10474 			/* What is the current stage's name? */
10475 			if (so_id == m_cs_id)
10476 			{
10477 				stage_body = test_case.cs_shader_body.c_str();
10478 				stage_name = "Compute shader";
10479 			}
10480 			else if (so_id == m_fs_id)
10481 			{
10482 				stage_body = test_case.fs_shader_body.c_str();
10483 				stage_name = "Fragment shader";
10484 			}
10485 			else if (so_id == m_gs_id)
10486 			{
10487 				stage_body = test_case.gs_shader_body.c_str();
10488 				stage_name = "Geometry shader";
10489 			}
10490 			else if (so_id == m_tc_id)
10491 			{
10492 				stage_body = test_case.tc_shader_body.c_str();
10493 				stage_name = "Tessellation control shader";
10494 			}
10495 			else if (so_id == m_te_id)
10496 			{
10497 				stage_body = test_case.te_shader_body.c_str();
10498 				stage_name = "Tessellation evaluation shader";
10499 			}
10500 			else if (so_id == m_vs_id)
10501 			{
10502 				stage_body = test_case.vs_shader_body.c_str();
10503 				stage_name = "Vertex shader";
10504 			}
10505 			else
10506 			{
10507 				/* Doesn't make much sense to throw exceptions here so.. */
10508 				stage_body = "";
10509 				stage_name = "[?]";
10510 			}
10511 
10512 			/* This shader should have never failed to compile! */
10513 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10514 							   << " has not compiled successfully, even though the shader is valid."
10515 								  " Following is shader's body:\n"
10516 							   << stage_body << tcu::TestLog::EndMessage;
10517 
10518 			result = false;
10519 		}
10520 	} /* for (all shader objects) */
10521 
10522 	return result;
10523 }
10524 
10525 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10526  *  type.
10527  *
10528  *  @param variable_type Variable type to return valid argument lists for.
10529  **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10530 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10531 	const Utils::_variable_type& variable_type)
10532 {
10533 	const Utils::_variable_type matrix_types[] = {
10534 		Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10535 		Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10536 		Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10537 	};
10538 	const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10539 												   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10540 	const unsigned int n_matrix_types	 = sizeof(matrix_types) / sizeof(matrix_types[0]);
10541 	const unsigned int n_scalar_types	 = sizeof(scalar_types) / sizeof(scalar_types[0]);
10542 	const int		   n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10543 
10544 	/* Construct the argument list tree root. Each node carries a counter that tells how many components
10545 	 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10546 	 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10547 	 * used to define a subsequent argument, and its counter is increased by the amount of components
10548 	 * described by the type.
10549 	 */
10550 	_argument_list_tree_node root;
10551 
10552 	root.n_components_used = 0;
10553 	root.parent			   = NULL;
10554 	root.type			   = variable_type;
10555 
10556 	/* Fill till all leaves use up all available components */
10557 	_argument_list_tree_node_queue nodes_queue;
10558 
10559 	nodes_queue.push(&root);
10560 
10561 	do
10562 	{
10563 		/* Pop the first item in the queue */
10564 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10565 		nodes_queue.pop();
10566 
10567 		/* Matrix variable types can be defined by a combination of non-matrix variable types OR
10568 		 * a single matrix variable type.
10569 		 *
10570 		 * Let's handle the latter case first.
10571 		 */
10572 		const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10573 
10574 		if (Utils::isMatrixVariableType(current_node_ptr->type))
10575 		{
10576 			/* Iterate through all known matrix types. All the types can be used
10577 			 * as a constructor, assuming only one value is used to define new matrix's
10578 			 * contents. */
10579 			for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10580 			{
10581 				Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10582 
10583 				/* Construct a new child node. Since GLSL spec clearly states we must not use more
10584 				 * than one constructor argument if the only argument is a matrix type, mark the node
10585 				 * as if it defined all available components.
10586 				 */
10587 				_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10588 
10589 				new_subnode->n_components_used = n_total_components;
10590 				new_subnode->parent			   = current_node_ptr;
10591 				new_subnode->type			   = new_argument_type;
10592 
10593 				/* Add the descriptor to node list but do not add it to the queue. This would be
10594 				 * a redundant operation, since no new children nodes would have been assigned to
10595 				 * this node anyway.
10596 				 */
10597 				current_node_ptr->children.push_back(new_subnode);
10598 			} /* for (all matrix types) */
10599 		}	 /* if (current node's type is a matrix) */
10600 
10601 		/* Now for a combination of non-matrix variable types.. */
10602 		if (!Utils::isMatrixVariableType(current_node_ptr->type))
10603 		{
10604 			/* Iterate through all known scalar types */
10605 			for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10606 			{
10607 				Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10608 				const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10609 
10610 				/* Only use the scalar type if we don't exceed the amount of components we can define
10611 				 * for requested type.
10612 				 */
10613 				if (n_new_argument_components <= n_components_remaining)
10614 				{
10615 					/* Form new node descriptor */
10616 					_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10617 
10618 					new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10619 					new_subnode->parent			   = current_node_ptr;
10620 					new_subnode->type			   = new_argument_type;
10621 
10622 					current_node_ptr->children.push_back(new_subnode);
10623 					nodes_queue.push(new_subnode);
10624 				}
10625 			} /* for (all scalar types) */
10626 		}	 /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10627 	} while (nodes_queue.size() > 0);
10628 
10629 	/* To construct the argument lists, traverse the tree. Each path from root to child
10630 	 * gives us a single argument list.
10631 	 *
10632 	 * First, identify leaf nodes.
10633 	 */
10634 	_argument_list_tree_nodes leaf_nodes;
10635 
10636 	nodes_queue.push(&root);
10637 
10638 	do
10639 	{
10640 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10641 		nodes_queue.pop();
10642 
10643 		if (current_node_ptr->children.size() == 0)
10644 		{
10645 			/* This is a leaf node !*/
10646 			leaf_nodes.push_back(current_node_ptr);
10647 		}
10648 		else
10649 		{
10650 			/* Throw all children nodes to the queue */
10651 			const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10652 
10653 			for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10654 			{
10655 				nodes_queue.push(current_node_ptr->children[n_children_node]);
10656 			} /* for (all children nodes) */
10657 		}
10658 	} while (nodes_queue.size() > 0);
10659 
10660 	/* For all leaf nodes, move up the tree and construct the argument lists. */
10661 	const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10662 	_argument_lists	result;
10663 
10664 	for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10665 	{
10666 		_argument_list			  argument_list;
10667 		_argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10668 
10669 		do
10670 		{
10671 			if (current_node_ptr != &root)
10672 			{
10673 				if (argument_list.size() == 0)
10674 				{
10675 					argument_list.push_back(current_node_ptr->type);
10676 				}
10677 				else
10678 				{
10679 					argument_list.insert(argument_list.begin(), current_node_ptr->type);
10680 				}
10681 			}
10682 
10683 			current_node_ptr = current_node_ptr->parent;
10684 		} while (current_node_ptr != NULL);
10685 
10686 		result.push_back(argument_list);
10687 	} /* for (all leaf nodes) */
10688 
10689 	return result;
10690 }
10691 
10692 /** Retrieves body of a compute shader that should be used for the purpose of
10693  *  user-specified test case.
10694  *
10695  *  @param test_case Test case descriptor to use.
10696  *
10697  *  @return Requested string.
10698  **/
getComputeShaderBody(const _test_case & test_case)10699 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10700 {
10701 	std::stringstream result_sstream;
10702 
10703 	/* Form the body */
10704 	result_sstream << "#version 420\n"
10705 					  "#extension GL_ARB_compute_shader          : require\n"
10706 					  "\n"
10707 					  "layout(local_size_x = 1) in;\n"
10708 					  "\n"
10709 					  "void main()\n"
10710 					  "{\n"
10711 				   << getGeneralBody(test_case) << "}\n";
10712 
10713 	/* Return the body */
10714 	return result_sstream.str();
10715 }
10716 
10717 /** Retrieves body of a fragment shader that should be used for the purpose of
10718  *  user-specified test case.
10719  *
10720  *  @param test_case Test case descriptor to use.
10721  *
10722  *  @return Requested string.
10723  **/
getFragmentShaderBody(const _test_case & test_case)10724 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10725 {
10726 	std::stringstream result_sstream;
10727 
10728 	/* Form the body */
10729 	result_sstream << "#version 420\n"
10730 					  "\n"
10731 					  "void main()\n"
10732 					  "{\n"
10733 				   << getGeneralBody(test_case) << "}\n"
10734 												   "\n";
10735 
10736 	/* Return the body */
10737 	return result_sstream.str();
10738 }
10739 
10740 /** Returns a GLSL line that defines and initializes a variable as described by
10741  *  user-specified test case descriptor.
10742  *
10743  *  @param test_case Test case descriptor to use for the query.
10744  *
10745  *  @return As per description
10746  **/
getGeneralBody(const _test_case & test_case)10747 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10748 {
10749 	std::stringstream result_sstream;
10750 
10751 	/* Form the body */
10752 	std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10753 
10754 	result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10755 
10756 	for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10757 		 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10758 	{
10759 		const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10760 		std::string		   argument_variable_type_string   = Utils::getVariableTypeString(argument_variable_type);
10761 		const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10762 
10763 		if (argument_list_iterator != test_case.argument_list.begin())
10764 		{
10765 			result_sstream << ", ";
10766 		}
10767 
10768 		result_sstream << argument_variable_type_string << "(";
10769 
10770 		for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10771 		{
10772 			result_sstream << (double)(n_component + 1);
10773 
10774 			if (n_component != (argument_n_components - 1))
10775 			{
10776 				result_sstream << ", ";
10777 			}
10778 		} /* for (all argument components) */
10779 
10780 		result_sstream << ")";
10781 	} /* for (all arguments) */
10782 
10783 	result_sstream << ");\n";
10784 
10785 	return result_sstream.str();
10786 }
10787 
10788 /** Retrieves body of a geometry shader that should be used for the purpose of
10789  *  user-specified test case.
10790  *
10791  *  @param test_case Test case descriptor to use.
10792  *
10793  *  @return Requested string.
10794  **/
getGeometryShaderBody(const _test_case & test_case)10795 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10796 {
10797 	std::stringstream result_sstream;
10798 
10799 	/* Form the body */
10800 	result_sstream << "#version 420\n"
10801 					  "\n"
10802 					  "layout(points)                 in;\n"
10803 					  "layout(max_vertices=1, points) out;\n"
10804 					  "\n"
10805 					  "void main()\n"
10806 					  "{\n"
10807 				   << getGeneralBody(test_case) << "}\n"
10808 												   "\n";
10809 
10810 	/* We're done! */
10811 	return result_sstream.str();
10812 }
10813 
10814 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10815  *  user-specified test case.
10816  *
10817  *  @param test_case Test case descriptor to use.
10818  *
10819  *  @return Requested string.
10820  **/
getTessellationControlShaderBody(const _test_case & test_case)10821 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10822 {
10823 	std::stringstream result_sstream;
10824 
10825 	/* Form the body */
10826 	result_sstream << "#version 420\n"
10827 					  "\n"
10828 					  "layout(vertices=4) out;\n"
10829 					  "\n"
10830 					  "void main()\n"
10831 					  "{\n"
10832 				   << getGeneralBody(test_case) << "}\n"
10833 												   "\n";
10834 
10835 	/* Return the body */
10836 	return result_sstream.str();
10837 }
10838 
10839 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10840  *  user-specified test case.
10841  *
10842  *  @param test_case Test case descriptor to use.
10843  *
10844  *  @return Requested string.
10845  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10846 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10847 {
10848 	std::stringstream result_sstream;
10849 
10850 	/* Form the body */
10851 	result_sstream << "#version 420\n"
10852 					  "\n"
10853 					  "layout(isolines) in;\n"
10854 					  "\n"
10855 					  "void main()\n"
10856 					  "{\n"
10857 				   << getGeneralBody(test_case) << "}\n"
10858 												   "\n";
10859 
10860 	/* Return the body */
10861 	return result_sstream.str();
10862 }
10863 
10864 /** Retrieves body of a vertex shader that should be used for the purpose of
10865  *  user-specified test case.
10866  *
10867  *  @param test_case Test case descriptor to use.
10868  *
10869  *  @return Requested string.
10870  **/
getVertexShaderBody(const _test_case & test_case)10871 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10872 {
10873 	std::stringstream result_sstream;
10874 
10875 	/* Form the body */
10876 	result_sstream << "#version 420\n"
10877 					  "\n"
10878 					  "void main()\n"
10879 					  "{\n"
10880 				   << getGeneralBody(test_case) << "}\n"
10881 												   "\n";
10882 
10883 	return result_sstream.str();
10884 }
10885 
10886 /** Initializes shader objects required to run the test. */
initTest()10887 void GPUShaderFP64Test8::initTest()
10888 {
10889 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10890 
10891 	/* Generate shader objects */
10892 
10893 	/* Compute shader support and GL 4.2 required */
10894 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10895 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10896 	{
10897 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10898 	}
10899 
10900 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10901 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10902 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10903 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10904 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10905 
10906 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10907 }
10908 
10909 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10910  *
10911  *  @param test_case Test case descriptor to generate the shader bodies for.
10912  **/
initIteration(_test_case & test_case)10913 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10914 {
10915 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10916 
10917 	test_case.cs_shader_body = getComputeShaderBody(test_case);
10918 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
10919 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
10920 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10921 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10922 	test_case.vs_shader_body = getVertexShaderBody(test_case);
10923 
10924 	/* Assign the bodies to relevant shaders */
10925 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10926 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10927 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10928 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10929 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10930 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10931 
10932 	/* m_cs_id is initialized only if compute_shader is supported */
10933 	if (0 != m_cs_id)
10934 	{
10935 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10936 	}
10937 
10938 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10939 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10940 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10941 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10942 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10943 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10944 }
10945 
10946 /** Executes test iteration.
10947  *
10948  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10949  */
iterate()10950 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10951 {
10952 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10953 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10954 	{
10955 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10956 	}
10957 
10958 	/* Initialize GL objects needed to run the tests */
10959 	initTest();
10960 
10961 	/* Build iteration array to run the tests in an automated manner */
10962 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
10963 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10964 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10965 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
10966 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10967 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
10968 													 Utils::VARIABLE_TYPE_DVEC4 };
10969 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10970 
10971 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10972 	{
10973 		const Utils::_variable_type variable_type = variable_types[n_variable_type];
10974 
10975 		/* Construct a set of argument lists valid for the variable type considered */
10976 		_argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10977 
10978 		for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10979 			 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10980 		{
10981 			/* Constructor thwe test case descriptor */
10982 			_test_case test_case;
10983 
10984 			test_case.argument_list = *argument_list_iterator;
10985 			test_case.type			= variable_type;
10986 
10987 			/* Initialize a program object we will use to perform the casting */
10988 			initIteration(test_case);
10989 
10990 			/* See if the shader compiles. */
10991 			m_has_test_passed &= executeIteration(test_case);
10992 		} /* for (all argument lists) */
10993 	}	 /* for (all variable types) */
10994 
10995 	/* We're done */
10996 	if (m_has_test_passed)
10997 	{
10998 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10999 	}
11000 	else
11001 	{
11002 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11003 	}
11004 
11005 	return STOP;
11006 }
11007 
11008 /** Constructor.
11009  *
11010  *  @param context Rendering context.
11011  *
11012  **/
GPUShaderFP64Test9(deqp::Context & context)11013 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11014 	: TestCase(context, "operators", "Verifies that general and relational operators work "
11015 									 "correctly when used against double-precision floating-"
11016 									 "point types.")
11017 	, m_has_test_passed(true)
11018 	, m_po_id(0)
11019 	, m_xfb_bo_id(0)
11020 	, m_vao_id(0)
11021 	, m_vs_id(0)
11022 {
11023 	/* Left blank intentionally */
11024 }
11025 
11026 /** Deinitializes all ES objects that may have been created during
11027  *  test execution.
11028  **/
deinit()11029 void GPUShaderFP64Test9::deinit()
11030 {
11031 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11032 
11033 	if (m_po_id != 0)
11034 	{
11035 		gl.deleteProgram(m_po_id);
11036 
11037 		m_po_id = 0;
11038 	}
11039 
11040 	if (m_xfb_bo_id != 0)
11041 	{
11042 		gl.deleteBuffers(1, &m_xfb_bo_id);
11043 
11044 		m_xfb_bo_id = 0;
11045 	}
11046 
11047 	if (m_vao_id != 0)
11048 	{
11049 		gl.deleteVertexArrays(1, &m_vao_id);
11050 
11051 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11052 	}
11053 
11054 	if (m_vs_id != 0)
11055 	{
11056 		gl.deleteShader(m_vs_id);
11057 
11058 		m_vs_id = 0;
11059 	}
11060 }
11061 
11062 /** Executes a single test iteration using user-specified test case properties.
11063  *
11064  *  @param test_case Test case descriptor.
11065  *
11066  *  @return true if the pass was successful, false if the test should fail.
11067  **/
executeTestIteration(const _test_case & test_case)11068 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11069 {
11070 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
11071 	bool				  result = true;
11072 
11073 	/* Activate the test program object */
11074 	gl.useProgram(m_po_id);
11075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11076 
11077 	/* Draw a single point with XFB enabled */
11078 	gl.beginTransformFeedback(GL_POINTS);
11079 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11080 	{
11081 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11082 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11083 	}
11084 	gl.endTransformFeedback();
11085 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11086 
11087 	/* Map the XFB BO into process space */
11088 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11089 
11090 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11091 
11092 	result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11093 
11094 	/* Unmap the BO */
11095 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11096 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11097 
11098 	return result;
11099 }
11100 
11101 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11102  *  under user-specified location.
11103  *
11104  *  @param matrix_a_type  Type of the l-side matrix.
11105  *  @param matrix_a_data  Row-ordered data of l-side matrix.
11106  *  @param matrix_b_type  Type of the r-side matrix.
11107  *  @param matrix_b_data  Row-ordered data of r-side matrix.
11108  *  @param out_result_ptr Deref to be used to store the multiplication result.
11109  **/
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)11110 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11111 													   const std::vector<double>&   matrix_a_data,
11112 													   const Utils::_variable_type& matrix_b_type,
11113 													   const std::vector<double>& matrix_b_data, double* out_result_ptr)
11114 {
11115 	(void)matrix_b_type;
11116 	using namespace tcu;
11117 	/* To keep the code maintainable, we only consider cases relevant for this test */
11118 	switch (matrix_a_type)
11119 	{
11120 	case Utils::VARIABLE_TYPE_DMAT2:
11121 	{
11122 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11123 
11124 		tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11125 		tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11126 		tcu::Matrix2d result;
11127 
11128 		matrix_a = transpose(matrix_a);
11129 		matrix_b = transpose(matrix_b);
11130 		result   = matrix_a * matrix_b;
11131 
11132 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11133 		break;
11134 	}
11135 
11136 	case Utils::VARIABLE_TYPE_DMAT2X3:
11137 	{
11138 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11139 
11140 		tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11141 		tcu::Matrix<double, 3, 2> matrix_a_transposed;
11142 		tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11143 		tcu::Matrix<double, 2, 3> matrix_b_transposed;
11144 		tcu::Matrix<double, 3, 3> result;
11145 
11146 		matrix_a_transposed = transpose(matrix_a);
11147 		matrix_b_transposed = transpose(matrix_b);
11148 		result				= matrix_a_transposed * matrix_b_transposed;
11149 
11150 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11151 		break;
11152 	}
11153 
11154 	case Utils::VARIABLE_TYPE_DMAT2X4:
11155 	{
11156 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11157 
11158 		tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11159 		tcu::Matrix<double, 4, 2> matrix_a_transposed;
11160 		tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11161 		tcu::Matrix<double, 2, 4> matrix_b_transposed;
11162 		tcu::Matrix<double, 4, 4> result;
11163 
11164 		matrix_a_transposed = transpose(matrix_a);
11165 		matrix_b_transposed = transpose(matrix_b);
11166 		result				= matrix_a_transposed * matrix_b_transposed;
11167 
11168 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11169 		break;
11170 	}
11171 
11172 	case Utils::VARIABLE_TYPE_DMAT3:
11173 	{
11174 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11175 
11176 		tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11177 		tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11178 		tcu::Matrix<double, 3, 3> result;
11179 
11180 		matrix_a = transpose(matrix_a);
11181 		matrix_b = transpose(matrix_b);
11182 		result   = matrix_a * matrix_b;
11183 
11184 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11185 		break;
11186 	}
11187 
11188 	case Utils::VARIABLE_TYPE_DMAT3X2:
11189 	{
11190 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11191 
11192 		tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11193 		tcu::Matrix<double, 2, 3> matrix_a_transposed;
11194 		tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11195 		tcu::Matrix<double, 3, 2> matrix_b_transposed;
11196 		tcu::Matrix<double, 2, 2> result;
11197 
11198 		matrix_a_transposed = transpose(matrix_a);
11199 		matrix_b_transposed = transpose(matrix_b);
11200 		result				= matrix_a_transposed * matrix_b_transposed;
11201 
11202 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11203 		break;
11204 	}
11205 
11206 	case Utils::VARIABLE_TYPE_DMAT3X4:
11207 	{
11208 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11209 
11210 		tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11211 		tcu::Matrix<double, 4, 3> matrix_a_transposed;
11212 		tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11213 		tcu::Matrix<double, 3, 4> matrix_b_transposed;
11214 		tcu::Matrix<double, 4, 4> result;
11215 
11216 		matrix_a_transposed = transpose(matrix_a);
11217 		matrix_b_transposed = transpose(matrix_b);
11218 		result				= matrix_a_transposed * matrix_b_transposed;
11219 
11220 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11221 		break;
11222 	}
11223 
11224 	case Utils::VARIABLE_TYPE_DMAT4:
11225 	{
11226 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11227 
11228 		tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11229 		tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11230 		tcu::Matrix<double, 4, 4> result;
11231 
11232 		matrix_a = transpose(matrix_a);
11233 		matrix_b = transpose(matrix_b);
11234 		result   = matrix_a * matrix_b;
11235 
11236 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11237 		break;
11238 	}
11239 
11240 	case Utils::VARIABLE_TYPE_DMAT4X2:
11241 	{
11242 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11243 
11244 		tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11245 		tcu::Matrix<double, 2, 4> matrix_a_transposed;
11246 		tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11247 		tcu::Matrix<double, 4, 2> matrix_b_transposed;
11248 		tcu::Matrix<double, 2, 2> result;
11249 
11250 		matrix_a_transposed = transpose(matrix_a);
11251 		matrix_b_transposed = transpose(matrix_b);
11252 		result				= matrix_a_transposed * matrix_b_transposed;
11253 
11254 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11255 		break;
11256 	}
11257 
11258 	case Utils::VARIABLE_TYPE_DMAT4X3:
11259 	{
11260 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11261 
11262 		tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11263 		tcu::Matrix<double, 3, 4> matrix_a_transposed;
11264 		tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11265 		tcu::Matrix<double, 4, 3> matrix_b_transposed;
11266 		tcu::Matrix<double, 3, 3> result;
11267 
11268 		matrix_a_transposed = transpose(matrix_a);
11269 		matrix_b_transposed = transpose(matrix_b);
11270 		result				= matrix_a_transposed * matrix_b_transposed;
11271 
11272 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11273 		break;
11274 	}
11275 
11276 	default:
11277 	{
11278 		TCU_FAIL("Unrecognized matrix A type");
11279 	}
11280 	} /* switch (matrix_a_type) */
11281 }
11282 
11283 /** Returns GLSL operator representation of the user-specified operation.
11284  *
11285  *  @param operation_type Internal operation type to retrieve the operator for.
11286  *
11287  *  @return As per description.
11288  **/
getOperatorForOperationType(const _operation_type & operation_type)11289 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11290 {
11291 	const char* result = NULL;
11292 
11293 	switch (operation_type)
11294 	{
11295 	case OPERATION_TYPE_ADDITION:
11296 		result = "+";
11297 		break;
11298 	case OPERATION_TYPE_DIVISION:
11299 		result = "/";
11300 		break;
11301 	case OPERATION_TYPE_MULTIPLICATION:
11302 		result = "*";
11303 		break;
11304 	case OPERATION_TYPE_SUBTRACTION:
11305 		result = "-";
11306 		break;
11307 
11308 	case OPERATION_TYPE_PRE_DECREMENTATION:
11309 	case OPERATION_TYPE_POST_DECREMENTATION:
11310 	{
11311 		result = "--";
11312 
11313 		break;
11314 	}
11315 
11316 	case OPERATION_TYPE_PRE_INCREMENTATION:
11317 	case OPERATION_TYPE_POST_INCREMENTATION:
11318 	{
11319 		result = "++";
11320 
11321 		break;
11322 	}
11323 
11324 	default:
11325 	{
11326 		TCU_FAIL("Unrecognized operation type");
11327 	}
11328 	} /* switch(operation_type) */
11329 
11330 	return result;
11331 }
11332 
11333 /** Returns a string representing user-specified operation type.
11334  *
11335  *  @param operation_type Operation type to return the literal for.
11336  *
11337  *  @return Requested string.
11338  **/
getOperationTypeString(const _operation_type & operation_type)11339 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11340 {
11341 	std::string result = "[?]";
11342 
11343 	switch (operation_type)
11344 	{
11345 	case OPERATION_TYPE_ADDITION:
11346 		result = "addition";
11347 		break;
11348 	case OPERATION_TYPE_DIVISION:
11349 		result = "division";
11350 		break;
11351 	case OPERATION_TYPE_MULTIPLICATION:
11352 		result = "multiplication";
11353 		break;
11354 	case OPERATION_TYPE_SUBTRACTION:
11355 		result = "subtraction";
11356 		break;
11357 	case OPERATION_TYPE_PRE_DECREMENTATION:
11358 		result = "pre-decrementation";
11359 		break;
11360 	case OPERATION_TYPE_PRE_INCREMENTATION:
11361 		result = "pre-incrementation";
11362 		break;
11363 	case OPERATION_TYPE_POST_DECREMENTATION:
11364 		result = "post-decrementation";
11365 		break;
11366 	case OPERATION_TYPE_POST_INCREMENTATION:
11367 		result = "post-incrementation";
11368 		break;
11369 
11370 	default:
11371 	{
11372 		TCU_FAIL("Unrecognized operation type");
11373 	}
11374 	}
11375 
11376 	return result;
11377 }
11378 
11379 /** Returns body of a vertex shader that should be used for user-specified test case
11380  *  descriptor.
11381  *
11382  *  @param test_case Test case descriptor.
11383  *
11384  *  @return Requested GLSL shader body.
11385  **/
getVertexShaderBody(_test_case & test_case)11386 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11387 {
11388 	std::stringstream  result_sstream;
11389 	std::string		   result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11390 	std::string		   variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11391 	std::string		   variable_type_string	= Utils::getVariableTypeString(test_case.variable_type);
11392 	const unsigned int n_variable_components   = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11393 
11394 	/* If we are to multiply matrices, we will need to use a different type
11395 	 * for the result variable if either of the matrices is not square.
11396 	 */
11397 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11398 		Utils::isMatrixVariableType(test_case.variable_type))
11399 	{
11400 		Utils::_variable_type result_variable_type;
11401 		Utils::_variable_type transposed_matrix_variable_type =
11402 			Utils::getTransposedMatrixVariableType(test_case.variable_type);
11403 
11404 		result_variable_type =
11405 			Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11406 		result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11407 
11408 		test_case.result_variable_type = result_variable_type;
11409 	}
11410 
11411 	/* Form the pre-amble */
11412 	result_sstream << "#version 400\n"
11413 					  "\n"
11414 
11415 					  /* Add output variables */
11416 					  "out "
11417 				   << result_variable_type_string << " result;\n"
11418 													 "out ivec2 result_lt;\n"
11419 													 "out ivec2 result_lte;\n"
11420 													 "out ivec2 result_gt;\n"
11421 													 "out ivec2 result_gte;\n"
11422 													 "void main()\n"
11423 													 "{\n";
11424 
11425 	/* Form reference values */
11426 	result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11427 
11428 	for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11429 	{
11430 		result_sstream << (n_variable_component + 1);
11431 
11432 		if (n_variable_component != (n_variable_components - 1))
11433 		{
11434 			result_sstream << ", ";
11435 		}
11436 	} /* for (all variable components) */
11437 
11438 	result_sstream << ");\n";
11439 
11440 	for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11441 		 ++n_ref2_case)
11442 	{
11443 		Utils::_variable_type compatible_variable_type = test_case.variable_type;
11444 
11445 		if (Utils::isMatrixVariableType(compatible_variable_type) &&
11446 			test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11447 		{
11448 			compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11449 		}
11450 
11451 		std::string ref2_variable_type_fp_string =
11452 			Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11453 		std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11454 		std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11455 		std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11456 
11457 		result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11458 
11459 		for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11460 			 ++n_variable_component)
11461 		{
11462 			result_sstream << (n_variable_components - (n_variable_component + 1));
11463 
11464 			if (n_variable_component != (n_variable_components - 1))
11465 			{
11466 				result_sstream << ", ";
11467 			}
11468 		} /* for (all variable components) */
11469 
11470 		result_sstream << ");\n";
11471 	} /* for (both reference2 declarations) */
11472 
11473 	/* Add actual body */
11474 	result_sstream << "\n"
11475 					  "result = ";
11476 
11477 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11478 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11479 	{
11480 		result_sstream << getOperatorForOperationType(test_case.operation_type);
11481 	}
11482 
11483 	result_sstream << "reference1 ";
11484 
11485 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11486 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11487 		test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11488 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11489 	{
11490 		if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11491 			test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11492 		{
11493 			result_sstream << getOperatorForOperationType(test_case.operation_type);
11494 		}
11495 	}
11496 	else
11497 	{
11498 		result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11499 	}
11500 
11501 	result_sstream << ";\n";
11502 
11503 	if (Utils::isScalarVariableType(test_case.variable_type))
11504 	{
11505 		result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
11506 						  "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
11507 						  "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
11508 						  "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11509 						  "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
11510 						  "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
11511 						  "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
11512 						  "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11513 	}
11514 	else
11515 	{
11516 		result_sstream << "result_lt [0] = 1;\n"
11517 						  "result_lt [1] = 1;\n"
11518 						  "result_lte[0] = 1;\n"
11519 						  "result_lte[1] = 1;\n"
11520 						  "result_gt [0] = 1;\n"
11521 						  "result_gt [1] = 1;\n"
11522 						  "result_gte[0] = 1;\n"
11523 						  "result_gte[1] = 1;\n";
11524 	}
11525 
11526 	result_sstream << "}\n";
11527 
11528 	/* All done */
11529 	return result_sstream.str();
11530 }
11531 
11532 /** Initializes all GL objects required to run the test.
11533  *
11534  *  This function can throw a TestError exception if the implementation misbehaves.
11535  */
initTest()11536 void GPUShaderFP64Test9::initTest()
11537 {
11538 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11539 
11540 	/* Create program & vertex shader objects */
11541 	m_po_id = gl.createProgram();
11542 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11543 
11544 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11545 
11546 	/* Attach the shader to the program */
11547 	gl.attachShader(m_po_id, m_vs_id);
11548 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11549 
11550 	/* Set up a buffer object */
11551 	gl.genBuffers(1, &m_xfb_bo_id);
11552 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11553 
11554 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11555 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11556 
11557 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11558 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11559 
11560 	/* Set up a vertex array object */
11561 	gl.genVertexArrays(1, &m_vao_id);
11562 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11563 
11564 	gl.bindVertexArray(m_vao_id);
11565 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11566 }
11567 
11568 /** Initializes all GL objects required to run an iteration described by
11569  *  user-specified test case descriptor.
11570  *
11571  *  @param test_case Test case descriptor to use for the initialization.
11572  **/
initTestIteration(_test_case & test_case)11573 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11574 {
11575 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
11576 	std::string			  vs_body		  = getVertexShaderBody(test_case);
11577 	const char*			  vs_body_raw_ptr = vs_body.c_str();
11578 
11579 	/* Store the shader's body */
11580 	test_case.vs_body = vs_body;
11581 
11582 	/* Try to compile the shader */
11583 	glw::GLint compile_status = GL_FALSE;
11584 
11585 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11586 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11587 
11588 	gl.compileShader(m_vs_id);
11589 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11590 
11591 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11592 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11593 
11594 	if (compile_status != GL_TRUE)
11595 	{
11596 		TCU_FAIL("Test shader compilation failed.");
11597 	}
11598 
11599 	/* Configure XFB */
11600 	const char*		   xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11601 	const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11602 
11603 	gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11604 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11605 
11606 	/* Try to link the program */
11607 	glw::GLint link_status = GL_FALSE;
11608 
11609 	gl.linkProgram(m_po_id);
11610 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11611 
11612 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11613 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11614 
11615 	if (link_status != GL_TRUE)
11616 	{
11617 		TCU_FAIL("Test program linking failure");
11618 	}
11619 
11620 	/* Set up XFB BO data storage */
11621 	const unsigned int result_variable_size = static_cast<unsigned int>(
11622 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11623 	const unsigned int xfb_bo_size = static_cast<unsigned int>(
11624 		result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11625 
11626 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11627 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11628 }
11629 
11630 /** Executes test iteration.
11631  *
11632  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11633  */
iterate()11634 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11635 {
11636 	/* Do not execute the test if GL_ARB_texture_view is not supported */
11637 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11638 	{
11639 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11640 	}
11641 
11642 	/* Initialize all ES objects required to run all the checks */
11643 	initTest();
11644 
11645 	/* Iterate through all variable types we want to test */
11646 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
11647 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11648 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11649 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
11650 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11651 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11652 													 Utils::VARIABLE_TYPE_DVEC4 };
11653 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11654 
11655 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11656 	{
11657 		/* Iterate through all operation types we want to check */
11658 		for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11659 		{
11660 			_operation_type				 operation_type = (_operation_type)n_operation_type;
11661 			const Utils::_variable_type& variable_type  = variable_types[n_variable_type];
11662 
11663 			/* Construct test case descriptor */
11664 			_test_case test_case;
11665 
11666 			test_case.operation_type	   = operation_type;
11667 			test_case.result_variable_type = variable_type;
11668 			test_case.variable_type		   = variable_type;
11669 
11670 			/* Run the iteration */
11671 			initTestIteration(test_case);
11672 
11673 			m_has_test_passed &= executeTestIteration(test_case);
11674 		} /* for (all operation types) */
11675 	}	 /* for (all variable types) */
11676 
11677 	/* All done. */
11678 	if (m_has_test_passed)
11679 	{
11680 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11681 	}
11682 	else
11683 	{
11684 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11685 	}
11686 
11687 	return STOP;
11688 }
11689 
11690 /** Verifies data XFBed out by the draw call for user-specified test case
11691  *  descriptor.
11692  *
11693  *  @param test_case Test case descriptor
11694  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
11695  *                   Must not be NULL.
11696  *
11697  *  @return true if the data was found to be correct, false otherwise.
11698  **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11699 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11700 {
11701 	const double	   epsilon = 1e-5;
11702 	const unsigned int n_result_components =
11703 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11704 	bool		  result			  = true;
11705 	const double* xfb_data_result	 = (const double*)xfb_data;
11706 	const int*	xfb_data_result_lt  = (const int*)(xfb_data_result + n_result_components);
11707 	const int*	xfb_data_result_lte = (const int*)xfb_data_result_lt + 2;  /* cast/non-cast cases */
11708 	const int*	xfb_data_result_gt  = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11709 	const int*	xfb_data_result_gte = (const int*)xfb_data_result_gt + 2;  /* cast/non-cast cases */
11710 
11711 	/* Prepare reference values */
11712 	int					modifier;
11713 	std::vector<double> reference1;
11714 	std::vector<double> reference2;
11715 
11716 	if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11717 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11718 	{
11719 		modifier = 1;
11720 	}
11721 	else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11722 			 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11723 	{
11724 		modifier = -1;
11725 	}
11726 	else
11727 	{
11728 		modifier = 0;
11729 	}
11730 
11731 	if (Utils::isMatrixVariableType(test_case.variable_type))
11732 	{
11733 		/* Matrices may be of different sizes so we need to compute the
11734 		 * reference values separately for each matrix
11735 		 */
11736 		const Utils::_variable_type matrix_a_type = test_case.variable_type;
11737 		const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11738 		const unsigned int			n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11739 		const unsigned int			n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11740 
11741 		for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11742 		{
11743 			reference1.push_back(modifier + n_component + 1);
11744 		}
11745 
11746 		for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11747 		{
11748 			reference2.push_back(n_matrix_b_components - (n_component + 1));
11749 		}
11750 	} /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11751 	else
11752 	{
11753 		/* Generate as many components as will be expected for the result variable */
11754 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11755 		{
11756 			reference1.push_back(modifier + n_result_component + 1);
11757 			reference2.push_back(n_result_components - (n_result_component + 1));
11758 		}
11759 	}
11760 
11761 	/* Verify the result value(s) */
11762 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11763 		Utils::isMatrixVariableType(test_case.variable_type))
11764 	{
11765 		/* Matrix multiplication */
11766 		double				  expected_result_data[4 * 4];
11767 		Utils::_variable_type matrix_a_type = test_case.variable_type;
11768 		Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11769 
11770 		getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11771 
11772 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11773 		{
11774 			if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11775 			{
11776 				std::stringstream log_sstream;
11777 
11778 				log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11779 							<< Utils::getVariableTypeString(matrix_b_type)
11780 							<< " matrix multiplication was incorrect; expected:(";
11781 
11782 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11783 					 ++n_logged_component)
11784 				{
11785 					log_sstream << expected_result_data[n_logged_component];
11786 
11787 					if (n_logged_component != (n_result_components - 1))
11788 					{
11789 						log_sstream << ", ";
11790 					}
11791 				} /* for (all components to be logged) */
11792 
11793 				log_sstream << "), retrieved:(";
11794 
11795 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11796 					 ++n_logged_component)
11797 				{
11798 					log_sstream << xfb_data_result[n_logged_component];
11799 
11800 					if (n_logged_component != (n_result_components - 1))
11801 					{
11802 						log_sstream << ", ";
11803 					}
11804 				} /* for (all components to be logged) */
11805 
11806 				log_sstream << ")";
11807 
11808 				m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11809 
11810 				result = false;
11811 				break;
11812 			}
11813 		} /* for (all result components) */
11814 	}	 /* if (dealing with matrix multiplication) */
11815 	else
11816 	{
11817 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11818 		{
11819 			double expected_value = reference1[n_component];
11820 
11821 			switch (test_case.operation_type)
11822 			{
11823 			case OPERATION_TYPE_ADDITION:
11824 				expected_value += reference2[n_component];
11825 				break;
11826 			case OPERATION_TYPE_DIVISION:
11827 				expected_value /= reference2[n_component];
11828 				break;
11829 			case OPERATION_TYPE_MULTIPLICATION:
11830 				expected_value *= reference2[n_component];
11831 				break;
11832 			case OPERATION_TYPE_SUBTRACTION:
11833 				expected_value -= reference2[n_component];
11834 				break;
11835 
11836 			case OPERATION_TYPE_PRE_DECREMENTATION:
11837 			case OPERATION_TYPE_PRE_INCREMENTATION:
11838 			{
11839 				/* Modifier already applied */
11840 				break;
11841 			}
11842 
11843 			case OPERATION_TYPE_POST_DECREMENTATION:
11844 			case OPERATION_TYPE_POST_INCREMENTATION:
11845 			{
11846 				/* Need to reverse the modification for the purpose of the following check */
11847 				expected_value -= modifier;
11848 
11849 				break;
11850 			}
11851 
11852 			default:
11853 			{
11854 				TCU_FAIL("Unrecognized operation type");
11855 			}
11856 			} /* switch (test_case.operation_type) */
11857 
11858 			if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11859 			{
11860 				std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11861 				std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11862 
11863 				m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11864 								   << variable_type_string << "]"
11865 															  " and operation type ["
11866 								   << operation_type_string << "]"
11867 															   " were found invalid."
11868 								   << tcu::TestLog::EndMessage;
11869 
11870 				result = false;
11871 				break;
11872 			} /* if (test case failed) */
11873 		}	 /* for (all components) */
11874 	}
11875 
11876 	/* Verify the comparison operation results */
11877 	if (Utils::isScalarVariableType(test_case.variable_type))
11878 	{
11879 		DE_ASSERT(n_result_components == 1);
11880 
11881 		const bool expected_result_lt[2]  = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11882 		const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11883 		const bool expected_result_gt[2]  = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11884 		const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11885 
11886 		if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11887 			(xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11888 		{
11889 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11890 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11891 
11892 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11893 														   "variable type ["
11894 							   << variable_type_string << "]"
11895 														  "and operation type ["
11896 							   << operation_type_string << "]"
11897 														   "was found invalid; expected:("
11898 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11899 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11900 							   << tcu::TestLog::EndMessage;
11901 
11902 			result = false;
11903 		}
11904 
11905 		if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11906 			(xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11907 		{
11908 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11909 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11910 
11911 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11912 														   "variable type ["
11913 							   << variable_type_string << "]"
11914 														  "and operation type ["
11915 							   << operation_type_string << "]"
11916 														   "was found invalid; expected:("
11917 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11918 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11919 							   << tcu::TestLog::EndMessage;
11920 
11921 			result = false;
11922 		}
11923 
11924 		if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11925 			(xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11926 		{
11927 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11928 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11929 
11930 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11931 														   "variable type ["
11932 							   << variable_type_string << "]"
11933 														  "and operation type ["
11934 							   << operation_type_string << "]"
11935 														   "was found invalid; expected:("
11936 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11937 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11938 							   << tcu::TestLog::EndMessage;
11939 
11940 			result = false;
11941 		}
11942 
11943 		if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11944 			(xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11945 		{
11946 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11947 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11948 
11949 			m_testCtx.getLog() << tcu::TestLog::Message
11950 							   << "Values reported for greater-than-or-equal operator used for "
11951 								  "variable type ["
11952 							   << variable_type_string << "]"
11953 														  "and operation type ["
11954 							   << operation_type_string << "]"
11955 														   "was found invalid; expected:("
11956 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11957 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11958 							   << tcu::TestLog::EndMessage;
11959 
11960 			result = false;
11961 		}
11962 	} /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11963 	else
11964 	{
11965 		if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11966 			xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11967 			xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11968 		{
11969 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11970 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11971 
11972 			m_testCtx.getLog() << tcu::TestLog::Message
11973 							   << "Invalid value was reported for matrix variable type, for which "
11974 								  " operator checks are not executed; variable type ["
11975 							   << variable_type_string << "]"
11976 														  "and operation type ["
11977 							   << operation_type_string << "]" << tcu::TestLog::EndMessage;
11978 
11979 			result = false;
11980 		}
11981 	}
11982 
11983 	return result;
11984 }
11985 
11986 namespace TypeHelpers
11987 {
11988 /** Get base type for reference types
11989  *
11990  * @tparam T type
11991  **/
11992 template <typename T>
11993 class referenceToType
11994 {
11995 public:
11996 	typedef T result;
11997 };
11998 
11999 template <typename T>
12000 class referenceToType<const T&>
12001 {
12002 public:
12003 	typedef T result;
12004 };
12005 
12006 /** Maps variable type with enumeration Utils::_variable_type
12007  *
12008  * @tparam T type
12009  **/
12010 template <typename T>
12011 class typeInfo;
12012 
12013 template <>
12014 class typeInfo<glw::GLboolean>
12015 {
12016 public:
12017 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12018 };
12019 
12020 template <>
12021 class typeInfo<glw::GLdouble>
12022 {
12023 public:
12024 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12025 };
12026 
12027 template <>
12028 class typeInfo<tcu::UVec2>
12029 {
12030 public:
12031 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12032 };
12033 
12034 template <>
12035 class typeInfo<tcu::UVec3>
12036 {
12037 public:
12038 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12039 };
12040 
12041 template <>
12042 class typeInfo<tcu::UVec4>
12043 {
12044 public:
12045 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12046 };
12047 
12048 template <>
12049 class typeInfo<tcu::DVec2>
12050 {
12051 public:
12052 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12053 };
12054 
12055 template <>
12056 class typeInfo<tcu::DVec3>
12057 {
12058 public:
12059 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12060 };
12061 
12062 template <>
12063 class typeInfo<tcu::DVec4>
12064 {
12065 public:
12066 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12067 };
12068 
12069 template <>
12070 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12071 {
12072 public:
12073 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12074 };
12075 
12076 template <>
12077 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12078 {
12079 public:
12080 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12081 };
12082 
12083 template <>
12084 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12085 {
12086 public:
12087 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12088 };
12089 
12090 template <>
12091 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12092 {
12093 public:
12094 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12095 };
12096 
12097 template <>
12098 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12099 {
12100 public:
12101 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12102 };
12103 
12104 template <>
12105 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12106 {
12107 public:
12108 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12109 };
12110 
12111 template <>
12112 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12113 {
12114 public:
12115 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12116 };
12117 
12118 template <>
12119 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12120 {
12121 public:
12122 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12123 };
12124 
12125 template <>
12126 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12127 {
12128 public:
12129 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12130 };
12131 } /* TypeHelpers */
12132 
12133 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12134  *
12135  **/
12136 namespace Math
12137 {
12138 template <typename T>
12139 static T clamp(T x, T minVal, T maxVal);
12140 
12141 template <int Size>
12142 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12143 
12144 template <int Size>
12145 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12146 
12147 template <typename T>
12148 static T determinant(T val);
12149 
12150 template <typename T>
12151 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12152 
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12155 
12156 template <typename T>
12157 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12158 
12159 template <int Size>
12160 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12161 																glw::GLuint column, glw::GLuint row);
12162 
12163 template <int Size>
12164 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12165 											const tcu::Vector<glw::GLdouble, Size>& right);
12166 
12167 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12168 
12169 static glw::GLdouble fract(glw::GLdouble val);
12170 
12171 template <typename T>
12172 static T frexp(T val, glw::GLint& exp);
12173 
12174 template <int Size>
12175 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12176 												  const tcu::Vector<glw::GLdouble, Size>& right);
12177 
12178 template <int Size>
12179 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12180 													   const tcu::Vector<glw::GLdouble, Size>& right);
12181 
12182 template <int Size>
12183 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12184 
12185 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12186 
12187 static glw::GLuint isinf_impl(glw::GLdouble val);
12188 
12189 static glw::GLuint isnan_impl(glw::GLdouble val);
12190 
12191 template <typename T>
12192 static T ldexp(T val, glw::GLint exp);
12193 
12194 template <int Size>
12195 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12196 											   const tcu::Vector<glw::GLdouble, Size>& right);
12197 
12198 template <int Size>
12199 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12200 													const tcu::Vector<glw::GLdouble, Size>& right);
12201 
12202 template <typename T>
12203 static T max(T left, T right);
12204 
12205 template <typename T>
12206 static T min(T left, T right);
12207 
12208 template <int		 Size>
12209 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12210 								glw::GLuint row);
12211 
12212 template <typename T>
12213 static T mix(T left, T right, T weight);
12214 
12215 template <typename T>
12216 static T mod(T left, T right);
12217 
12218 template <typename T>
12219 static T modf(T val, T& integer);
12220 
12221 template <typename T>
12222 static T multiply(T left, T right);
12223 
12224 template <int Size>
12225 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12226 											   const tcu::Vector<glw::GLdouble, Size>& right);
12227 
12228 template <int Cols, int Rows>
12229 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12230 														   const tcu::Vector<glw::GLdouble, Cols>& right);
12231 
12232 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12233 
12234 template <typename T>
12235 static T round(T t);
12236 
12237 template <typename T>
12238 static T roundEven(T t);
12239 
12240 template <typename T>
12241 static T sign(T t);
12242 
12243 template <typename T>
12244 static T smoothStep(T e0, T e1, T val);
12245 
12246 template <typename T>
12247 static T step(T edge, T val);
12248 
12249 template <typename T, int Rows, int Cols>
12250 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12251 
12252 template <typename T>
12253 static T trunc(T t);
12254 
12255 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12256 
12257 template <typename T>
clamp(T x,T minVal,T maxVal)12258 static T clamp(T x, T minVal, T maxVal)
12259 {
12260 	return min(max(x, minVal), maxVal);
12261 }
12262 
12263 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12264 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12265 {
12266 	tcu::Matrix<glw::GLdouble, Size, Size> result;
12267 
12268 	for (glw::GLuint c = 0; c < Size; ++c)
12269 	{
12270 		for (glw::GLuint r = 0; r < Size; ++r)
12271 		{
12272 			const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12273 
12274 			result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12275 		}
12276 	}
12277 
12278 	return result;
12279 }
12280 
12281 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12282 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12283 {
12284 	tcu::Vector<glw::GLuint, Size> result;
12285 
12286 	for (glw::GLint i = 0; i < Size; ++i)
12287 	{
12288 		if (GL_FALSE != src[i])
12289 		{
12290 			result[i] = 1;
12291 		}
12292 		else
12293 		{
12294 			result[i] = 0;
12295 		}
12296 	}
12297 
12298 	return result;
12299 }
12300 
12301 template <typename T>
det2(T _00,T _10,T _01,T _11)12302 static T det2(T _00, T _10, T _01, T _11)
12303 {
12304 	return _00 * _11 - _01 * _10;
12305 }
12306 
12307 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12308 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12309 {
12310 	return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12311 }
12312 
12313 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)12314 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,
12315 			  T _33)
12316 {
12317 	return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12318 		   _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12319 		   _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12320 		   _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12321 }
12322 
12323 template <typename T>
determinant(T val)12324 static T determinant(T val)
12325 {
12326 	return val;
12327 }
12328 
12329 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12330 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12331 {
12332 	return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12333 }
12334 
12335 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12336 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12337 {
12338 	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));
12339 }
12340 
12341 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12342 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12343 {
12344 	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),
12345 				mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12346 }
12347 
12348 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12349 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12350 																glw::GLuint column, glw::GLuint row)
12351 {
12352 	// GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12353 #if (DE_COMPILER == DE_COMPILER_GCC)
12354 #	pragma GCC diagnostic push
12355 #	pragma GCC diagnostic ignored "-Warray-bounds"
12356 #endif
12357 
12358 	const glw::GLint eCol = static_cast<glw::GLint>(column);
12359 	const glw::GLint eRow = static_cast<glw::GLint>(row);
12360 
12361 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12362 
12363 	for (glw::GLint c = 0; c < Size; ++c)
12364 	{
12365 		/* Skip eliminated column */
12366 		if (eCol == c)
12367 		{
12368 			continue;
12369 		}
12370 
12371 		for (glw::GLint r = 0; r < Size; ++r)
12372 		{
12373 			/* Skip eliminated row */
12374 			if (eRow == r)
12375 			{
12376 				continue;
12377 			}
12378 
12379 			const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12380 			const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12381 
12382 			result(r + r_offset, c + c_offset) = matrix(r, c);
12383 		}
12384 	}
12385 
12386 	return result;
12387 
12388 #if (DE_COMPILER == DE_COMPILER_GCC)
12389 #	pragma GCC diagnostic pop
12390 #endif
12391 }
12392 
12393 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12394 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12395 											const tcu::Vector<glw::GLdouble, Size>& right)
12396 {
12397 	return convertBvecToUvec(tcu::equal(left, right));
12398 }
12399 
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12400 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12401 {
12402 	return a * b + c;
12403 }
12404 
fract(glw::GLdouble val)12405 static glw::GLdouble fract(glw::GLdouble val)
12406 {
12407 	return val - floor(val);
12408 }
12409 
12410 template <typename T>
frexp(T val,glw::GLint & exp)12411 static T frexp(T val, glw::GLint& exp)
12412 {
12413 	return ::frexp(val, &exp);
12414 }
12415 
12416 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12417 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12418 												  const tcu::Vector<glw::GLdouble, Size>& right)
12419 {
12420 	return convertBvecToUvec(tcu::greaterThan(left, right));
12421 }
12422 
12423 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12424 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12425 													   const tcu::Vector<glw::GLdouble, Size>& right)
12426 {
12427 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12428 }
12429 
12430 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12431 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12432 {
12433 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
12434 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12435 	const glw::GLdouble det		= determinant(matrix);
12436 	const glw::GLdouble inv_det = 1.0 / det;
12437 
12438 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12439 
12440 	return result;
12441 }
12442 
inverseSqrt(glw::GLdouble val)12443 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12444 {
12445 	const glw::GLdouble root = sqrt(val);
12446 
12447 	return (1.0 / root);
12448 }
12449 
isinf_impl(glw::GLdouble val)12450 static glw::GLuint isinf_impl(glw::GLdouble val)
12451 {
12452 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12453 
12454 	return ((infinity == val) || (-infinity == val));
12455 }
12456 
isnan_impl(glw::GLdouble val)12457 static glw::GLuint isnan_impl(glw::GLdouble val)
12458 {
12459 	return val != val;
12460 }
12461 
12462 template <typename T>
ldexp(T val,glw::GLint exp)12463 static T ldexp(T val, glw::GLint exp)
12464 {
12465 	return ::ldexp(val, exp);
12466 }
12467 
12468 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12469 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12470 											   const tcu::Vector<glw::GLdouble, Size>& right)
12471 {
12472 	return convertBvecToUvec(tcu::lessThan(left, right));
12473 }
12474 
12475 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12476 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12477 													const tcu::Vector<glw::GLdouble, Size>& right)
12478 {
12479 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
12480 }
12481 
12482 template <typename T>
max(T left,T right)12483 static T max(T left, T right)
12484 {
12485 	return (left >= right) ? left : right;
12486 }
12487 
12488 template <typename T>
min(T left,T right)12489 static T min(T left, T right)
12490 {
12491 	return (left <= right) ? left : right;
12492 }
12493 
12494 template <int		 Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12495 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12496 								glw::GLuint row)
12497 {
12498 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12499 
12500 	return determinant(eliminated);
12501 }
12502 
12503 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12504 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12505 {
12506 	const glw::GLuint r = (0 == row) ? 1 : 0;
12507 	const glw::GLuint c = (0 == column) ? 1 : 0;
12508 
12509 	return matrix(r, c);
12510 }
12511 
12512 template <typename T>
mix(T left,T right,T weight)12513 static T mix(T left, T right, T weight)
12514 {
12515 	return left * (1 - weight) + right * (weight);
12516 }
12517 
12518 template <typename T>
mod(T left,T right)12519 static T mod(T left, T right)
12520 {
12521 	const T div_res = left / right;
12522 	const T floored = floor(div_res);
12523 
12524 	return left - right * floored;
12525 }
12526 
12527 template <typename T>
modf(T val,T & integer)12528 static T modf(T val, T& integer)
12529 {
12530 	return ::modf(val, &integer);
12531 }
12532 
12533 template <typename T>
multiply(T left,T right)12534 static T multiply(T left, T right)
12535 {
12536 	T result = left * right;
12537 
12538 	return result;
12539 }
12540 
12541 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12542 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12543 											   const tcu::Vector<glw::GLdouble, Size>& right)
12544 {
12545 	return convertBvecToUvec(tcu::notEqual(left, right));
12546 }
12547 
12548 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12549 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12550 														   const tcu::Vector<glw::GLdouble, Cols>& right)
12551 {
12552 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
12553 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
12554 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12555 
12556 	for (glw::GLuint i = 0; i < Rows; ++i)
12557 	{
12558 		left_mat(i, 0) = left[i];
12559 	}
12560 
12561 	for (glw::GLuint i = 0; i < Cols; ++i)
12562 	{
12563 		right_mat(0, i) = right[i];
12564 	}
12565 
12566 	result = left_mat * right_mat;
12567 
12568 	return result;
12569 }
12570 
packDouble2x32(const tcu::UVec2 & in)12571 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12572 {
12573 	const glw::GLuint buffer[2] = { in[0], in[1] };
12574 	glw::GLdouble	 result;
12575 	memcpy(&result, buffer, sizeof(result));
12576 	return result;
12577 }
12578 
12579 template <typename T>
round(T t)12580 static T round(T t)
12581 {
12582 	T frac = fract(t);
12583 	T res  = t - frac;
12584 
12585 	if (((T)0.5) < frac)
12586 	{
12587 		res += ((T)1.0);
12588 	}
12589 
12590 	return res;
12591 }
12592 
12593 template <typename T>
roundEven(T t)12594 static T roundEven(T t)
12595 {
12596 	T frac = fract(t);
12597 	T res  = t - frac;
12598 
12599 	if (((T)0.5) < frac)
12600 	{
12601 		res += ((T)1.0);
12602 	}
12603 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12604 	{
12605 		res += ((T)1.0);
12606 	}
12607 
12608 	return res;
12609 }
12610 
12611 template <typename T>
sign(T t)12612 static T sign(T t)
12613 {
12614 	if (0 > t)
12615 	{
12616 		return -1;
12617 	}
12618 	else if (0 == t)
12619 	{
12620 		return 0;
12621 	}
12622 	else
12623 	{
12624 		return 1;
12625 	}
12626 }
12627 
12628 template <typename T>
smoothStep(T e0,T e1,T val)12629 static T smoothStep(T e0, T e1, T val)
12630 {
12631 	if (e0 >= val)
12632 	{
12633 		return 0;
12634 	}
12635 
12636 	if (e1 <= val)
12637 	{
12638 		return 1;
12639 	}
12640 
12641 	T temp = (val - e0) / (e1 - e0);
12642 
12643 	T result = temp * temp * (3 - 2 * temp);
12644 
12645 	return result;
12646 }
12647 
12648 template <typename T>
step(T edge,T val)12649 static T step(T edge, T val)
12650 {
12651 	if (edge > val)
12652 	{
12653 		return 0;
12654 	}
12655 	else
12656 	{
12657 		return 1;
12658 	}
12659 }
12660 
12661 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12662 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12663 {
12664 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12665 
12666 	return result;
12667 }
12668 
12669 template <typename T>
trunc(T t)12670 static T trunc(T t)
12671 {
12672 	const T abs_value	= de::abs(t);
12673 	const T result_value = floor(abs_value);
12674 
12675 	const T result = sign(t) * result_value;
12676 
12677 	return result;
12678 }
12679 
unpackDouble2x32(const glw::GLdouble & val)12680 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12681 {
12682 	glw::GLuint* ptr = (glw::GLuint*)&val;
12683 	tcu::UVec2   result(ptr[0], ptr[1]);
12684 
12685 	return result;
12686 }
12687 } /* Math */
12688 
12689 /** Enumeration of tested functions
12690  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12691  * For example "max" can be called for (dvec3, double).
12692  **/
12693 enum FunctionEnum
12694 {
12695 	FUNCTION_ABS = 0,
12696 	FUNCTION_CEIL,
12697 	FUNCTION_CLAMP,
12698 	FUNCTION_CLAMP_AGAINST_SCALAR,
12699 	FUNCTION_CROSS,
12700 	FUNCTION_DETERMINANT,
12701 	FUNCTION_DISTANCE,
12702 	FUNCTION_DOT,
12703 	FUNCTION_EQUAL,
12704 	FUNCTION_FACEFORWARD,
12705 	FUNCTION_FLOOR,
12706 	FUNCTION_FMA,
12707 	FUNCTION_FRACT,
12708 	FUNCTION_FREXP,
12709 	FUNCTION_GREATERTHAN,
12710 	FUNCTION_GREATERTHANEQUAL,
12711 	FUNCTION_INVERSE,
12712 	FUNCTION_INVERSESQRT,
12713 	FUNCTION_LDEXP,
12714 	FUNCTION_LESSTHAN,
12715 	FUNCTION_LESSTHANEQUAL,
12716 	FUNCTION_LENGTH,
12717 	FUNCTION_MATRIXCOMPMULT,
12718 	FUNCTION_MAX,
12719 	FUNCTION_MAX_AGAINST_SCALAR,
12720 	FUNCTION_MIN,
12721 	FUNCTION_MIN_AGAINST_SCALAR,
12722 	FUNCTION_MIX,
12723 	FUNCTION_MOD,
12724 	FUNCTION_MOD_AGAINST_SCALAR,
12725 	FUNCTION_MODF,
12726 	FUNCTION_NORMALIZE,
12727 	FUNCTION_NOTEQUAL,
12728 	FUNCTION_OUTERPRODUCT,
12729 	FUNCTION_PACKDOUBLE2X32,
12730 	FUNCTION_REFLECT,
12731 	FUNCTION_REFRACT,
12732 	FUNCTION_ROUND,
12733 	FUNCTION_ROUNDEVEN,
12734 	FUNCTION_SIGN,
12735 	FUNCTION_SMOOTHSTEP,
12736 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12737 	FUNCTION_SQRT,
12738 	FUNCTION_STEP,
12739 	FUNCTION_STEP_AGAINST_SCALAR,
12740 	FUNCTION_TRANSPOSE,
12741 	FUNCTION_TRUNC,
12742 	FUNCTION_UNPACKDOUBLE2X32,
12743 	FUNCTION_ISNAN,
12744 	FUNCTION_ISINF,
12745 };
12746 
12747 struct TypeDefinition
12748 {
12749 	std::string name;
12750 	glw::GLuint n_columns;
12751 	glw::GLuint n_rows;
12752 };
12753 
12754 /** Implementation of BuiltinFunctionTest test, description follows:
12755  *
12756  *  Verify double-precision support in common functions works correctly.
12757  *  All double-precision types that apply for particular cases should
12758  *  be tested for the following functions:
12759  *
12760  *  - abs();
12761  *  - ceil();
12762  *  - clamp();
12763  *  - cross();
12764  *  - determinant();
12765  *  - distance();
12766  *  - dot();
12767  *  - equal();
12768  *  - faceforward();
12769  *  - floor();
12770  *  - fma();
12771  *  - fract();
12772  *  - frexp();
12773  *  - greaterThan();
12774  *  - greaterThanEqual();
12775  *  - inverse();
12776  *  - inversesqrt();
12777  *  - ldexp();
12778  *  - lessThan();
12779  *  - lessThanEqual();
12780  *  - length();
12781  *  - matrixCompMult();
12782  *  - max();
12783  *  - min();
12784  *  - mix();
12785  *  - mod();
12786  *  - modf();
12787  *  - normalize();
12788  *  - notEqual();
12789  *  - outerProduct();
12790  *  - packDouble2x32();
12791  *  - reflect();
12792  *  - refract();
12793  *  - round();
12794  *  - roundEven();
12795  *  - sign();
12796  *  - smoothstep();
12797  *  - sqrt();
12798  *  - step();
12799  *  - transpose();
12800  *  - trunc();
12801  *  - unpackDouble2x32();
12802  *  - isnan();
12803  *  - isinf();
12804  *
12805  *  The test should work by creating a program object (for each case
12806  *  considered), to which a vertex shader should be attached. The
12807  *  shader should define input variables that should be used as
12808  *  arguments for the function in question. The result of the
12809  *  operation should then be XFBed back to the test, where the
12810  *  value should be verified.
12811  *
12812  *  Reference function implementation from pre-DEQP CTS framework
12813  *  should be ported to C for verification purposes where available.
12814  *
12815  *  The test should use 1024 different scalar/vector/matrix argument
12816  *  combinations. It should pass if all functions are determined
12817  *  to work correctly for all argument combinations used.
12818  **/
12819 class BuiltinFunctionTest : public deqp::TestCase
12820 {
12821 public:
12822 	/* Public methods */
12823 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12824 						TypeDefinition typeDefinition);
12825 
12826 	virtual void						 deinit();
12827 	virtual tcu::TestNode::IterateResult iterate();
12828 
12829 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12830 	 *
12831 	 **/
12832 	class functionObject
12833 	{
12834 	public:
12835 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12836 					   Utils::_variable_type result_type);
12837 
~functionObject()12838 		virtual ~functionObject()
12839 		{
12840 		}
12841 
12842 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12843 
12844 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
12845 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12846 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12847 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12848 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12849 		glw::GLuint getArgumentStride() const;
12850 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
12851 		FunctionEnum	   getFunctionEnum() const;
12852 		const glw::GLchar* getName() const;
12853 		glw::GLuint getResultComponents(glw::GLuint result) const;
12854 		virtual glw::GLuint getResultCount() const;
12855 		glw::GLuint getResultOffset(glw::GLuint result) const;
12856 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12857 		glw::GLuint getResultStride(glw::GLuint result) const;
12858 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12859 		glw::GLuint getResultStride() const;
12860 
12861 	protected:
12862 		const FunctionEnum			m_function_enum;
12863 		const glw::GLchar*			m_function_name;
12864 		const glw::GLvoid*			m_p_function;
12865 		const Utils::_variable_type m_res_type;
12866 	};
12867 
12868 private:
12869 	/* Private types */
12870 	/** General type enumeration
12871 	 *
12872 	 **/
12873 	enum generalType
12874 	{
12875 		SCALAR = 0,
12876 		VECTOR,
12877 		MATRIX,
12878 	};
12879 
12880 	/** Details of variable type
12881 	 *
12882 	 **/
12883 	struct typeDetails
12884 	{
12885 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12886 
12887 		generalType m_general_type;
12888 		glw::GLuint m_n_columns;
12889 		glw::GLuint m_n_rows;
12890 		glw::GLenum m_type;
12891 		std::string m_type_name;
12892 	};
12893 
12894 	/* Typedefs for gl.uniform* function pointers */
12895 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12896 																	   const glw::GLdouble*);
12897 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12898 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12899 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12900 
12901 	/* Private methods */
12902 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12903 
12904 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12905 
12906 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
12907 														 const functionObject& function_object) const;
12908 
12909 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
12910 														 const functionObject& function_object) const;
12911 
12912 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
12913 														 const functionObject& function_object) const;
12914 
12915 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
12916 														 const functionObject& function_object) const;
12917 
12918 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
12919 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12920 
12921 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12922 
12923 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12924 
12925 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12926 
12927 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12928 						   glw::GLubyte* buffer);
12929 
12930 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12931 
12932 	void prepareTestData(const functionObject& function_object);
12933 	void prepareVertexShaderCode(const functionObject& function_object);
12934 
12935 	bool test(FunctionEnum function, const typeDetails& type);
12936 
12937 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12938 
12939 	void testInit();
12940 
12941 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12942 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12943 						  const glw::GLvoid* result_src);
12944 
12945 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12946 
12947 	/* Private constants */
12948 	static const glw::GLdouble m_epsilon;
12949 	static const glw::GLuint   m_n_veritces;
12950 
12951 	/* Private fields */
12952 	glw::GLuint m_transform_feedback_buffer_id;
12953 	glw::GLuint m_vertex_array_object_id;
12954 
12955 	std::vector<glw::GLubyte> m_expected_results_data;
12956 	FunctionEnum			  m_function;
12957 	TypeDefinition			  m_typeDefinition;
12958 	std::vector<glw::GLubyte> m_argument_data;
12959 	std::string				  m_vertex_shader_code;
12960 };
12961 
12962 /* Constants used by BuiltinFunctionTest */
12963 /** Khronos Bug #14010
12964  *  Using an epsilon value for comparing floating points is error prone.
12965  *  Rather than writing a new floating point comparison function, I am
12966  *  increasing the epsilon value to allow greater orders of magnitude
12967  *  of floating point values.
12968  **/
12969 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
12970 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12971 
12972 /** Implementations of function objects required by "BuiltinFunctionTest"
12973  *
12974  **/
12975 namespace FunctionObject
12976 {
12977 /** Maps variable type with enumeration Utils::_variable_type
12978  *
12979  * @tparam T type
12980  **/
12981 template <typename T>
12982 class typeInfo
12983 {
12984 public:
12985 	static const Utils::_variable_type variable_type =
12986 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12987 };
12988 
12989 /** Place data from <in> into <buffer>
12990  *
12991  * @param buffer Buffer
12992  * @param in     Input data
12993  **/
12994 template <typename T>
12995 class pack
12996 {
12997 public:
set(glw::GLvoid * buffer,const T & in)12998 	static void set(glw::GLvoid* buffer, const T& in)
12999 	{
13000 		*(T*)buffer = in;
13001 	}
13002 };
13003 
13004 /** Place tcu::Matrix data from <in> into <buffer>
13005  *
13006  * @param buffer Buffer
13007  * @param in     Input data
13008  **/
13009 template <int Cols, int Rows>
13010 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13011 {
13012 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13013 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13014 	{
13015 		glw::GLdouble* data = (glw::GLdouble*)buffer;
13016 
13017 		for (glw::GLint column = 0; column < Cols; ++column)
13018 		{
13019 			for (glw::GLint row = 0; row < Rows; ++row)
13020 			{
13021 				glw::GLint index = column * Rows + row;
13022 
13023 				data[index] = in(row, column);
13024 			}
13025 		}
13026 	}
13027 };
13028 
13029 /** Get data of <out> from <buffer>
13030  *
13031  * @param buffer Buffer
13032  * @param out    Output data
13033  **/
13034 template <typename T>
13035 class unpack
13036 {
13037 public:
get(const glw::GLvoid * buffer,T & out)13038 	static void get(const glw::GLvoid* buffer, T& out)
13039 	{
13040 		out = *(T*)buffer;
13041 	}
13042 };
13043 
13044 /** Get tcu::Matrix data from <buffer>
13045  *
13046  * @param buffer Buffer
13047  * @param out    Output data
13048  **/
13049 template <int Cols, int Rows>
13050 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13051 {
13052 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13053 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13054 	{
13055 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
13056 
13057 		for (glw::GLint column = 0; column < Cols; ++column)
13058 		{
13059 			for (glw::GLint row = 0; row < Rows; ++row)
13060 			{
13061 				glw::GLint index = column * Rows + row;
13062 
13063 				out(row, column) = data[index];
13064 			}
13065 		}
13066 	}
13067 };
13068 
13069 /** Base of unary function classes
13070  *
13071  **/
13072 class unaryBase : public BuiltinFunctionTest::functionObject
13073 {
13074 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)13075 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13076 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13077 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13078 	{
13079 	}
13080 
getArgumentCount() const13081 	virtual glw::GLuint getArgumentCount() const
13082 	{
13083 		return 1;
13084 	}
13085 
getArgumentType(glw::GLuint) const13086 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13087 	{
13088 		return m_arg_type;
13089 	}
13090 
13091 protected:
13092 	const Utils::_variable_type m_arg_type;
13093 };
13094 
13095 /** Unary function class. It treats input argument as one variable.
13096  *
13097  * @tparam ResT Type of result
13098  * @tparam ArgT Type of argument
13099  **/
13100 template <typename ResT, typename ArgT>
13101 class unary : public unaryBase
13102 {
13103 public:
13104 	typedef ResT (*functionPointer)(const ArgT&);
13105 
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13106 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13107 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13108 					typeInfo<ArgT>::variable_type)
13109 	{
13110 	}
13111 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13112 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13113 	{
13114 		ResT result;
13115 		ArgT arg;
13116 
13117 		unpack<ArgT>::get(argument_src, arg);
13118 
13119 		functionPointer p_function = (functionPointer)m_p_function;
13120 
13121 		result = p_function(arg);
13122 
13123 		pack<ResT>::set(result_dst, result);
13124 	}
13125 };
13126 
13127 /** Unary function class. It treats input argument as separate components.
13128  *
13129  * @tparam ResT Type of result
13130  **/
13131 template <typename ResT>
13132 class unaryByComponent : public unaryBase
13133 {
13134 public:
13135 	typedef ResT (*functionPointer)(glw::GLdouble);
13136 
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13137 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13138 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13139 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13140 	{
13141 	}
13142 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13143 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13144 	{
13145 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13146 		ResT*		   p_result		= (ResT*)result_dst;
13147 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
13148 
13149 		functionPointer p_function = (functionPointer)m_p_function;
13150 
13151 		for (glw::GLuint component = 0; component < n_components; ++component)
13152 		{
13153 			p_result[component] = p_function(p_arg[component]);
13154 		}
13155 	}
13156 };
13157 
13158 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13159  *
13160  * @tparam ResT Type of result
13161  * @tparam ArgT Type of argument
13162  * @tparam OutT Type of output parameter
13163  **/
13164 template <typename ResT, typename ArgT, typename OutT>
13165 class unaryWithOutputByComponent : public unaryBase
13166 {
13167 public:
13168 	typedef ResT (*functionPointer)(ArgT, OutT&);
13169 
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)13170 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13171 							   functionPointer function_pointer, const Utils::_variable_type res_type,
13172 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13173 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13174 		, m_out_type(out_type)
13175 	{
13176 	}
13177 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13178 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13179 	{
13180 		ResT* p_result = (ResT*)result_dst;
13181 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13182 		ArgT* p_arg	= (ArgT*)argument_src;
13183 
13184 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13185 		const glw::GLuint n_components_1 = getResultComponents(1);
13186 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13187 
13188 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13189 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13190 
13191 		functionPointer p_function = (functionPointer)m_p_function;
13192 
13193 		for (glw::GLuint component = 0; component < n_components; ++component)
13194 		{
13195 			const ArgT first_arg  = p_arg[component * component_step_0];
13196 			OutT&	  second_arg = p_out[component * component_step_1];
13197 
13198 			p_result[component] = p_function(first_arg, second_arg);
13199 		}
13200 	}
13201 
getResultCount() const13202 	glw::GLuint getResultCount() const
13203 	{
13204 		return 2;
13205 	}
13206 
getResultType(glw::GLuint result) const13207 	Utils::_variable_type getResultType(glw::GLuint result) const
13208 	{
13209 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13210 
13211 		switch (result)
13212 		{
13213 		case 0:
13214 			type = m_res_type;
13215 			break;
13216 		case 1:
13217 			type = m_out_type;
13218 			break;
13219 		default:
13220 			TCU_FAIL("Not implemented");
13221 			break;
13222 		}
13223 
13224 		return type;
13225 	}
13226 
13227 protected:
13228 	const Utils::_variable_type m_out_type;
13229 };
13230 
13231 /** Base of binary function classes.
13232  *
13233  **/
13234 class binaryBase : public BuiltinFunctionTest::functionObject
13235 {
13236 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)13237 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13238 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13239 			   const Utils::_variable_type arg_2_type)
13240 		: functionObject(function_enum, function_name, function_pointer, res_type)
13241 		, m_arg_1_type(arg_1_type)
13242 		, m_arg_2_type(arg_2_type)
13243 	{
13244 	}
13245 
getArgumentCount() const13246 	virtual glw::GLuint getArgumentCount() const
13247 	{
13248 		return 2;
13249 	}
13250 
getArgumentType(glw::GLuint argument) const13251 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13252 	{
13253 		switch (argument)
13254 		{
13255 		case 0:
13256 			return m_arg_1_type;
13257 		case 1:
13258 			return m_arg_2_type;
13259 		default:
13260 			return Utils::VARIABLE_TYPE_UNKNOWN;
13261 		}
13262 	}
13263 
13264 protected:
13265 	const Utils::_variable_type m_arg_1_type;
13266 	const Utils::_variable_type m_arg_2_type;
13267 };
13268 
13269 /** Binary function class. It treats input arguments as two variables.
13270  *
13271  * @param ResT  Type of result
13272  * @param Arg1T Type of first argument
13273  * @param Arg2T Type of second argument
13274  **/
13275 template <typename ResT, typename Arg1T, typename Arg2T>
13276 class binary : public binaryBase
13277 {
13278 public:
13279 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13280 
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13281 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13282 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13283 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13284 	{
13285 	}
13286 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13287 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13288 	{
13289 		const glw::GLuint argument_1_stride = getArgumentStride(0);
13290 
13291 		functionPointer p_function = (functionPointer)m_p_function;
13292 
13293 		Arg1T arg_1;
13294 		Arg2T arg_2;
13295 		ResT  result;
13296 
13297 		unpack<Arg1T>::get(argument_src, arg_1);
13298 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13299 
13300 		result = p_function(arg_1, arg_2);
13301 
13302 		pack<ResT>::set(result_dst, result);
13303 	}
13304 };
13305 
13306 /** Binary function class. It treats input arguments as separate components.
13307  *
13308  * @param ResT  Type of result
13309  * @param Arg1T Type of first argument
13310  * @param Arg2T Type of second argument
13311  **/
13312 template <typename ResT, typename Arg1T, typename Arg2T>
13313 class binaryByComponent : public binaryBase
13314 {
13315 public:
13316 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
13317 
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)13318 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13319 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13320 					  const Utils::_variable_type arg_2_type)
13321 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13322 	{
13323 	}
13324 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13325 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13326 	{
13327 		ResT*  p_result = (ResT*)result_dst;
13328 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
13329 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13330 
13331 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13332 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13333 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13334 
13335 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13336 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13337 
13338 		functionPointer p_function = (functionPointer)m_p_function;
13339 
13340 		for (glw::GLuint component = 0; component < n_components; ++component)
13341 		{
13342 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
13343 			const Arg2T second_arg = p_arg_2[component * component_step_1];
13344 
13345 			p_result[component] = p_function(first_arg, second_arg);
13346 		}
13347 	}
13348 };
13349 
13350 /** Base of tenary function classes.
13351  *
13352  **/
13353 class tenaryBase : public BuiltinFunctionTest::functionObject
13354 {
13355 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)13356 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13357 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13358 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13359 		: functionObject(function_enum, function_name, function_pointer, res_type)
13360 		, m_arg_1_type(arg_1_type)
13361 		, m_arg_2_type(arg_2_type)
13362 		, m_arg_3_type(arg_3_type)
13363 	{
13364 	}
13365 
getArgumentCount() const13366 	virtual glw::GLuint getArgumentCount() const
13367 	{
13368 		return 3;
13369 	}
13370 
getArgumentType(glw::GLuint argument) const13371 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13372 	{
13373 		switch (argument)
13374 		{
13375 		case 0:
13376 			return m_arg_1_type;
13377 		case 1:
13378 			return m_arg_2_type;
13379 		case 2:
13380 			return m_arg_3_type;
13381 		default:
13382 			return Utils::VARIABLE_TYPE_UNKNOWN;
13383 		}
13384 	}
13385 
13386 protected:
13387 	const Utils::_variable_type m_arg_1_type;
13388 	const Utils::_variable_type m_arg_2_type;
13389 	const Utils::_variable_type m_arg_3_type;
13390 };
13391 
13392 /** Tenary function class. It treats input arguments as three variables.
13393  *
13394  * @param ResT  Type of result
13395  * @param Arg1T Type of first argument
13396  * @param Arg2T Type of second argument
13397  * @param Arg3T Type of third argument
13398  **/
13399 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13400 class tenary : public tenaryBase
13401 {
13402 public:
13403 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13404 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13405 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13406 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13407 
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13408 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13409 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13410 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13411 	{
13412 	}
13413 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13414 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13415 	{
13416 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
13417 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
13418 
13419 		functionPointer p_function = (functionPointer)m_p_function;
13420 
13421 		arg1T arg_1;
13422 		arg2T arg_2;
13423 		arg3T arg_3;
13424 		ResT  result;
13425 
13426 		unpack<arg1T>::get(argument_src, arg_1);
13427 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13428 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13429 
13430 		result = p_function(arg_1, arg_2, arg_3);
13431 
13432 		pack<ResT>::set(result_dst, result);
13433 	}
13434 };
13435 
13436 /** Tenary function class. It treats input arguments as separate components.
13437  *
13438 
13439  **/
13440 class tenaryByComponent : public tenaryBase
13441 {
13442 public:
13443 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13444 
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)13445 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13446 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13447 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13448 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13449 					 arg_3_type)
13450 	{
13451 	}
13452 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13453 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13454 	{
13455 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
13456 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
13457 
13458 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13459 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13460 		const glw::GLuint n_components_2 = getArgumentComponents(2);
13461 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13462 
13463 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13464 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13465 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13466 
13467 		functionPointer p_function = (functionPointer)m_p_function;
13468 
13469 		for (glw::GLuint component = 0; component < n_components; ++component)
13470 		{
13471 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13472 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13473 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13474 
13475 			p_result[component] = p_function(first_arg, second_arg, third_arg);
13476 		}
13477 	}
13478 };
13479 } /* FunctionObject */
13480 
13481 /** Constructor.
13482  *
13483  *  @param context Rendering context.
13484  **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13485 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13486 										 TypeDefinition typeDefinition)
13487 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13488 	, m_transform_feedback_buffer_id(0)
13489 	, m_vertex_array_object_id(0)
13490 	, m_function(function)
13491 	, m_typeDefinition(typeDefinition)
13492 {
13493 	/* Nothing to be done here */
13494 }
13495 
13496 /** Deinitializes all GL objects that may have been created during test execution.
13497  *
13498  **/
deinit()13499 void BuiltinFunctionTest::deinit()
13500 {
13501 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13502 
13503 	/* Clean buffers */
13504 	if (0 != m_transform_feedback_buffer_id)
13505 	{
13506 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13507 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13508 		m_transform_feedback_buffer_id = 0;
13509 	}
13510 
13511 	/* Clean VAO */
13512 	if (0 != m_vertex_array_object_id)
13513 	{
13514 		gl.bindVertexArray(0);
13515 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13516 		m_vertex_array_object_id = 0;
13517 	}
13518 }
13519 
13520 /** Execute test
13521  *
13522  * @return tcu::TestNode::STOP
13523  **/
iterate()13524 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13525 {
13526 	/* Check if extension is supported */
13527 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13528 	{
13529 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13530 	}
13531 
13532 	testInit();
13533 
13534 	/* Verify result */
13535 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13536 	if (test(m_function, type))
13537 	{
13538 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13539 	}
13540 	else
13541 	{
13542 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13543 	}
13544 
13545 	/* Done */
13546 	return tcu::TestNode::STOP;
13547 }
13548 
13549 /** Constructor
13550  *
13551  * @param function_enum    Function enumeration
13552  * @param function_name    Function name
13553  * @param function_pointer Pointer to routine that wiil be executed
13554  * @param result_type      Type of result
13555  **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13556 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13557 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13558 	: m_function_enum(function_enum)
13559 	, m_function_name(function_name)
13560 	, m_p_function(function_pointer)
13561 	, m_res_type(result_type)
13562 {
13563 	/* Nothing to be done here */
13564 }
13565 
13566 /** Get number of components for <argument>
13567  *
13568  * @param argument Argument ordinal, starts with 0
13569  *
13570  * @return Number of components
13571  **/
getArgumentComponents(glw::GLuint argument) const13572 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13573 {
13574 	const Utils::_variable_type type		  = getArgumentType(argument);
13575 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13576 
13577 	return n_components;
13578 }
13579 
13580 /** Get size in bytes of single component of <argument>
13581  *
13582  * @param argument Argument ordinal, starts with 0
13583  *
13584  * @return Size of component
13585  **/
getArgumentComponentSize(glw::GLuint argument) const13586 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13587 {
13588 	const Utils::_variable_type type		   = getArgumentType(argument);
13589 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13590 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13591 
13592 	return base_type_size;
13593 }
13594 
13595 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13596  *
13597  * @param argument Argument ordinal, starts with 0
13598  *
13599  * @return Offset of arguemnt's data
13600  **/
getArgumentOffset(glw::GLuint argument) const13601 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13602 {
13603 	glw::GLuint result = 0;
13604 
13605 	for (glw::GLuint i = 0; i < argument; ++i)
13606 	{
13607 		result += getArgumentStride(i);
13608 	}
13609 
13610 	return result;
13611 }
13612 
13613 /** Get stride in bytes of all arguments
13614  *
13615  * @return Stride of all arguments
13616  **/
getArgumentStride() const13617 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13618 {
13619 	const glw::GLuint n_args = getArgumentCount();
13620 	glw::GLuint		  result = 0;
13621 
13622 	for (glw::GLuint i = 0; i < n_args; ++i)
13623 	{
13624 		result += getArgumentStride(i);
13625 	}
13626 
13627 	return result;
13628 }
13629 
13630 /** Get stride in bytes of <argument>
13631  *
13632  * @param argument Argument ordinal, starts with 0
13633  *
13634  * @return Stride of argument
13635  **/
getArgumentStride(glw::GLuint argument) const13636 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13637 {
13638 	const glw::GLuint component_size = getArgumentComponentSize(argument);
13639 	const glw::GLuint n_components   = getArgumentComponents(argument);
13640 
13641 	return n_components * component_size;
13642 }
13643 
13644 /** Get function enumeration
13645  *
13646  * @return Function enumeration
13647  **/
getFunctionEnum() const13648 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13649 {
13650 	return m_function_enum;
13651 }
13652 
13653 /** Get function name
13654  *
13655  * @return Function name
13656  **/
getName() const13657 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13658 {
13659 	return m_function_name;
13660 }
13661 
13662 /** Get number of components for <result>
13663  *
13664  * @param result Result ordinal, starts with 0
13665  *
13666  * @return Number of components
13667  **/
getResultComponents(glw::GLuint result) const13668 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13669 {
13670 	const Utils::_variable_type type		  = getResultType(result);
13671 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13672 
13673 	return n_components;
13674 }
13675 
13676 /** Get number of results
13677  *
13678  * @return Number of results
13679  **/
getResultCount() const13680 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13681 {
13682 	return 1;
13683 }
13684 
13685 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13686  *
13687  * @param result Result ordinal, starts with 0
13688  *
13689  * @return Offset
13690  **/
getResultOffset(glw::GLuint result) const13691 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13692 {
13693 	glw::GLuint offset = 0;
13694 
13695 	for (glw::GLuint i = 0; i < result; ++i)
13696 	{
13697 		offset += getResultStride(i);
13698 		offset = deAlign32(offset, getBaseTypeSize(i));
13699 	}
13700 
13701 	return offset;
13702 }
13703 
13704 /** Get stride in bytes of <result>.
13705  *
13706  * @param result Result ordinal, starts with 0
13707  *
13708  * @return Stride
13709  **/
getResultStride(glw::GLuint result) const13710 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13711 {
13712 	const Utils::_variable_type type		   = getResultType(result);
13713 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
13714 
13715 	return n_components * getBaseTypeSize(result);
13716 }
13717 
13718 /** Get size in bytes of <result> base component.
13719  *
13720  * @param result Result ordinal, starts with 0
13721  *
13722  * @return Alignment
13723  **/
getBaseTypeSize(glw::GLuint result) const13724 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13725 {
13726 	const Utils::_variable_type type		   = getResultType(result);
13727 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13728 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13729 
13730 	return base_type_size;
13731 }
13732 
13733 /** Get stride in bytes of all results.
13734  *
13735  * @return Stride
13736  **/
getResultStride() const13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13738 {
13739 	const glw::GLuint n_results	= getResultCount();
13740 	glw::GLuint		  stride	   = 0;
13741 	glw::GLuint		  maxAlignment = 0;
13742 
13743 	for (glw::GLuint i = 0; i < n_results; ++i)
13744 	{
13745 		const glw::GLuint alignment = getBaseTypeSize(i);
13746 		stride += getResultStride(i);
13747 		stride		 = deAlign32(stride, alignment);
13748 		maxAlignment = deMaxu32(maxAlignment, alignment);
13749 	}
13750 
13751 	// The stride of all results must also be aligned,
13752 	// so results for next vertex are aligned.
13753 	return deAlign32(stride, maxAlignment);
13754 }
13755 
13756 /** Get type of <result>.
13757  *
13758  * @param result Result ordinal, starts with 0
13759  *
13760  * @return Type
13761  **/
getResultType(glw::GLuint) const13762 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13763 {
13764 	return m_res_type;
13765 }
13766 
13767 /** Constructor
13768  *
13769  * @param n_columns Number of columns
13770  * @param n_rows    Number of rows
13771  **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13772 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13773 	: m_n_columns(n_columns), m_n_rows(n_rows)
13774 {
13775 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13776 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
13777 	m_type_name				   = Utils::getVariableTypeString(type);
13778 
13779 	if (1 == m_n_columns)
13780 	{
13781 		if (1 == m_n_rows)
13782 		{
13783 			m_general_type = SCALAR;
13784 		}
13785 		else
13786 		{
13787 			m_general_type = VECTOR;
13788 		}
13789 	}
13790 	else
13791 	{
13792 		m_general_type = MATRIX;
13793 	}
13794 }
13795 
13796 /** Compare two values
13797  *
13798  * @param type  Type of values
13799  * @param left  Pointer to left value
13800  * @param right Pointer to right value
13801  *
13802  * @return true if values are equal, false otherwise
13803  **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13804 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13805 {
13806 	bool result = true;
13807 
13808 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
13809 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
13810 
13811 	switch (base_type)
13812 	{
13813 	case Utils::VARIABLE_TYPE_DOUBLE:
13814 
13815 	{
13816 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13817 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
13818 
13819 		for (glw::GLuint component = 0; component < n_components; ++component)
13820 		{
13821 			const glw::GLdouble left_value  = left_values[component];
13822 			const glw::GLdouble right_value = right_values[component];
13823 
13824 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13825 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13826 			{
13827 				result = false;
13828 				break;
13829 			}
13830 		}
13831 	}
13832 
13833 	break;
13834 
13835 	case Utils::VARIABLE_TYPE_INT:
13836 
13837 	{
13838 		const glw::GLint* left_values  = (glw::GLint*)left;
13839 		const glw::GLint* right_values = (glw::GLint*)right;
13840 
13841 		for (glw::GLuint component = 0; component < n_components; ++component)
13842 		{
13843 			const glw::GLint left_value  = left_values[component];
13844 			const glw::GLint right_value = right_values[component];
13845 
13846 			if (left_value != right_value)
13847 			{
13848 				result = false;
13849 				break;
13850 			}
13851 		}
13852 	}
13853 
13854 	break;
13855 
13856 	case Utils::VARIABLE_TYPE_UINT:
13857 
13858 	{
13859 		const glw::GLuint* left_values  = (glw::GLuint*)left;
13860 		const glw::GLuint* right_values = (glw::GLuint*)right;
13861 
13862 		for (glw::GLuint component = 0; component < n_components; ++component)
13863 		{
13864 			const glw::GLuint left_value  = left_values[component];
13865 			const glw::GLuint right_value = right_values[component];
13866 
13867 			if (left_value != right_value)
13868 			{
13869 				result = false;
13870 				break;
13871 			}
13872 		}
13873 	}
13874 
13875 	break;
13876 
13877 	default:
13878 
13879 		TCU_FAIL("Not implemented");
13880 	}
13881 
13882 	return result;
13883 }
13884 
13885 /** Create instance of function object for given function enumeration and type
13886  *
13887  * @param function Function enumeration
13888  * @param type     Type details
13889  *
13890  * @return Create object
13891  **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13892 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
13893 																			const typeDetails& type)
13894 {
13895 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13896 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13897 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13898 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13899 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13900 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13901 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13902 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13903 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13904 
13905 	const glw::GLuint			n_columns	 = type.m_n_columns;
13906 	const glw::GLuint			n_rows		  = type.m_n_rows;
13907 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13908 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13909 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
13910 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
13911 
13912 	switch (function)
13913 	{
13914 	case FUNCTION_ABS:
13915 
13916 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13917 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13918 
13919 	case FUNCTION_CEIL:
13920 
13921 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13922 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13923 
13924 	case FUNCTION_CLAMP:
13925 
13926 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13927 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
13928 													 variable_type /* arg3_type */);
13929 
13930 	case FUNCTION_CLAMP_AGAINST_SCALAR:
13931 
13932 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13933 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13934 													 scalar_type /* arg3_type */);
13935 
13936 	case FUNCTION_CROSS:
13937 
13938 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13939 			function, "cross", tcu::cross);
13940 
13941 	case FUNCTION_DETERMINANT:
13942 
13943 		switch (variable_type)
13944 		{
13945 		case Utils::VARIABLE_TYPE_DMAT2:
13946 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13947 																						 Math::determinant);
13948 		case Utils::VARIABLE_TYPE_DMAT3:
13949 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13950 																						 Math::determinant);
13951 		case Utils::VARIABLE_TYPE_DMAT4:
13952 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13953 																						 Math::determinant);
13954 		default:
13955 			TCU_FAIL("Not implemented");
13956 		}
13957 
13958 	case FUNCTION_DISTANCE:
13959 
13960 		switch (variable_type)
13961 		{
13962 		case Utils::VARIABLE_TYPE_DVEC2:
13963 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13964 				function, "distance", tcu::distance);
13965 		case Utils::VARIABLE_TYPE_DVEC3:
13966 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13967 				function, "distance", tcu::distance);
13968 		case Utils::VARIABLE_TYPE_DVEC4:
13969 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13970 				function, "distance", tcu::distance);
13971 		default:
13972 			break;
13973 		}
13974 
13975 		break;
13976 
13977 	case FUNCTION_DOT:
13978 
13979 		switch (variable_type)
13980 		{
13981 		case Utils::VARIABLE_TYPE_DVEC2:
13982 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13983 				function, "dot", tcu::dot);
13984 		case Utils::VARIABLE_TYPE_DVEC3:
13985 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13986 				function, "dot", tcu::dot);
13987 		case Utils::VARIABLE_TYPE_DVEC4:
13988 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13989 				function, "dot", tcu::dot);
13990 		default:
13991 			break;
13992 		}
13993 
13994 		break;
13995 
13996 	case FUNCTION_EQUAL:
13997 
13998 		switch (variable_type)
13999 		{
14000 		case Utils::VARIABLE_TYPE_DVEC2:
14001 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14002 				function, "equal", Math::equal);
14003 		case Utils::VARIABLE_TYPE_DVEC3:
14004 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14005 				function, "equal", Math::equal);
14006 		case Utils::VARIABLE_TYPE_DVEC4:
14007 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14008 				function, "equal", Math::equal);
14009 		default:
14010 			break;
14011 		}
14012 
14013 		break;
14014 
14015 	case FUNCTION_FACEFORWARD:
14016 
14017 		switch (variable_type)
14018 		{
14019 		case Utils::VARIABLE_TYPE_DVEC2:
14020 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14021 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14022 				function, "faceforward", tcu::faceForward);
14023 		case Utils::VARIABLE_TYPE_DVEC3:
14024 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14025 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14026 				function, "faceforward", tcu::faceForward);
14027 		case Utils::VARIABLE_TYPE_DVEC4:
14028 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14029 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14030 				function, "faceforward", tcu::faceForward);
14031 		default:
14032 			break;
14033 		}
14034 
14035 		break;
14036 
14037 	case FUNCTION_FLOOR:
14038 
14039 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14040 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14041 
14042 	case FUNCTION_FMA:
14043 
14044 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14045 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14046 													 variable_type /* arg3_type */);
14047 
14048 	case FUNCTION_FRACT:
14049 
14050 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14051 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14052 
14053 	case FUNCTION_FREXP:
14054 
14055 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14056 															  glw::GLint /* OutT */>(
14057 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14058 			int_type /* out_type */);
14059 
14060 	case FUNCTION_GREATERTHAN:
14061 
14062 		switch (variable_type)
14063 		{
14064 		case Utils::VARIABLE_TYPE_DVEC2:
14065 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14066 				function, "greaterThan", Math::greaterThan);
14067 		case Utils::VARIABLE_TYPE_DVEC3:
14068 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14069 				function, "greaterThan", Math::greaterThan);
14070 		case Utils::VARIABLE_TYPE_DVEC4:
14071 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14072 				function, "greaterThan", Math::greaterThan);
14073 		default:
14074 			break;
14075 		}
14076 
14077 		break;
14078 
14079 	case FUNCTION_GREATERTHANEQUAL:
14080 
14081 		switch (variable_type)
14082 		{
14083 		case Utils::VARIABLE_TYPE_DVEC2:
14084 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14085 				function, "greaterThanEqual", Math::greaterThanEqual);
14086 		case Utils::VARIABLE_TYPE_DVEC3:
14087 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14088 				function, "greaterThanEqual", Math::greaterThanEqual);
14089 		case Utils::VARIABLE_TYPE_DVEC4:
14090 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14091 				function, "greaterThanEqual", Math::greaterThanEqual);
14092 		default:
14093 			break;
14094 		}
14095 
14096 		break;
14097 
14098 	case FUNCTION_INVERSE:
14099 
14100 		switch (variable_type)
14101 		{
14102 		case Utils::VARIABLE_TYPE_DMAT2:
14103 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14104 		case Utils::VARIABLE_TYPE_DMAT3:
14105 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14106 		case Utils::VARIABLE_TYPE_DMAT4:
14107 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14108 		default:
14109 			break;
14110 		}
14111 
14112 		break;
14113 
14114 	case FUNCTION_INVERSESQRT:
14115 
14116 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14117 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14118 
14119 	case FUNCTION_LDEXP:
14120 
14121 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14122 													 glw::GLint /* Arg2T */>(
14123 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14124 			int_type /* arg2_type */);
14125 
14126 	case FUNCTION_LESSTHAN:
14127 
14128 		switch (variable_type)
14129 		{
14130 		case Utils::VARIABLE_TYPE_DVEC2:
14131 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14132 				function, "lessThan", Math::lessThan);
14133 		case Utils::VARIABLE_TYPE_DVEC3:
14134 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14135 				function, "lessThan", Math::lessThan);
14136 		case Utils::VARIABLE_TYPE_DVEC4:
14137 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14138 				function, "lessThan", Math::lessThan);
14139 		default:
14140 			break;
14141 		}
14142 
14143 		break;
14144 
14145 	case FUNCTION_LESSTHANEQUAL:
14146 
14147 		switch (variable_type)
14148 		{
14149 		case Utils::VARIABLE_TYPE_DVEC2:
14150 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14151 				function, "lessThanEqual", Math::lessThanEqual);
14152 		case Utils::VARIABLE_TYPE_DVEC3:
14153 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14154 				function, "lessThanEqual", Math::lessThanEqual);
14155 		case Utils::VARIABLE_TYPE_DVEC4:
14156 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14157 				function, "lessThanEqual", Math::lessThanEqual);
14158 		default:
14159 			break;
14160 		}
14161 
14162 		break;
14163 
14164 	case FUNCTION_LENGTH:
14165 
14166 		switch (variable_type)
14167 		{
14168 		case Utils::VARIABLE_TYPE_DVEC2:
14169 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14170 																							  tcu::length);
14171 		case Utils::VARIABLE_TYPE_DVEC3:
14172 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14173 																							  tcu::length);
14174 		case Utils::VARIABLE_TYPE_DVEC4:
14175 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14176 																							  tcu::length);
14177 		default:
14178 			break;
14179 		}
14180 
14181 		break;
14182 
14183 	case FUNCTION_MATRIXCOMPMULT:
14184 
14185 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14186 													 glw::GLdouble /* Arg2T */>(
14187 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14188 			variable_type /* arg2_type */);
14189 
14190 	case FUNCTION_MAX:
14191 
14192 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14193 													 glw::GLdouble /* Arg2T */>(
14194 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14195 			variable_type /* arg2_type */);
14196 
14197 	case FUNCTION_MAX_AGAINST_SCALAR:
14198 
14199 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14200 													 glw::GLdouble /* Arg2T */>(
14201 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14202 			scalar_type /* arg2_type */);
14203 
14204 	case FUNCTION_MIN:
14205 
14206 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14207 													 glw::GLdouble /* Arg2T */>(
14208 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14209 			variable_type /* arg2_type */);
14210 
14211 	case FUNCTION_MIN_AGAINST_SCALAR:
14212 
14213 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14214 													 glw::GLdouble /* Arg2T */>(
14215 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14216 			scalar_type /* arg2_type */);
14217 
14218 	case FUNCTION_MIX:
14219 
14220 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14221 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14222 													 variable_type /* arg3_type */);
14223 
14224 	case FUNCTION_MOD:
14225 
14226 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14227 													 glw::GLdouble /* Arg2T */>(
14228 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14229 			variable_type /* arg2_type */);
14230 
14231 	case FUNCTION_MOD_AGAINST_SCALAR:
14232 
14233 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14234 													 glw::GLdouble /* Arg2T */>(
14235 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14236 			scalar_type /* arg2_type */);
14237 
14238 	case FUNCTION_MODF:
14239 
14240 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14241 															  glw::GLdouble /* OutT */>(
14242 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14243 			variable_type /* out_type */);
14244 
14245 	case FUNCTION_NORMALIZE:
14246 
14247 		switch (variable_type)
14248 		{
14249 		case Utils::VARIABLE_TYPE_DVEC2:
14250 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14251 																						   tcu::normalize);
14252 		case Utils::VARIABLE_TYPE_DVEC3:
14253 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14254 																						   tcu::normalize);
14255 		case Utils::VARIABLE_TYPE_DVEC4:
14256 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14257 																						   tcu::normalize);
14258 		default:
14259 			break;
14260 		}
14261 
14262 		break;
14263 
14264 	case FUNCTION_NOTEQUAL:
14265 
14266 		switch (variable_type)
14267 		{
14268 		case Utils::VARIABLE_TYPE_DVEC2:
14269 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14270 				function, "notEqual", Math::notEqual);
14271 		case Utils::VARIABLE_TYPE_DVEC3:
14272 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14273 				function, "notEqual", Math::notEqual);
14274 		case Utils::VARIABLE_TYPE_DVEC4:
14275 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14276 				function, "notEqual", Math::notEqual);
14277 		default:
14278 			break;
14279 		}
14280 
14281 		break;
14282 
14283 	case FUNCTION_OUTERPRODUCT:
14284 
14285 		switch (variable_type)
14286 		{
14287 		case Utils::VARIABLE_TYPE_DMAT2:
14288 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14289 				function, "outerProduct", Math::outerProduct);
14290 		case Utils::VARIABLE_TYPE_DMAT2X3:
14291 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 				function, "outerProduct", Math::outerProduct);
14293 		case Utils::VARIABLE_TYPE_DMAT2X4:
14294 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14295 				function, "outerProduct", Math::outerProduct);
14296 		case Utils::VARIABLE_TYPE_DMAT3:
14297 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14298 				function, "outerProduct", Math::outerProduct);
14299 		case Utils::VARIABLE_TYPE_DMAT3X2:
14300 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 				function, "outerProduct", Math::outerProduct);
14302 		case Utils::VARIABLE_TYPE_DMAT3X4:
14303 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14304 				function, "outerProduct", Math::outerProduct);
14305 		case Utils::VARIABLE_TYPE_DMAT4:
14306 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14307 				function, "outerProduct", Math::outerProduct);
14308 		case Utils::VARIABLE_TYPE_DMAT4X2:
14309 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 				function, "outerProduct", Math::outerProduct);
14311 		case Utils::VARIABLE_TYPE_DMAT4X3:
14312 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14313 				function, "outerProduct", Math::outerProduct);
14314 		default:
14315 			break;
14316 		}
14317 
14318 		break;
14319 
14320 	case FUNCTION_PACKDOUBLE2X32:
14321 
14322 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14323 																						  Math::packDouble2x32);
14324 
14325 	case FUNCTION_REFLECT:
14326 
14327 		switch (variable_type)
14328 		{
14329 		case Utils::VARIABLE_TYPE_DVEC2:
14330 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14331 				function, "reflect", tcu::reflect);
14332 		case Utils::VARIABLE_TYPE_DVEC3:
14333 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14334 				function, "reflect", tcu::reflect);
14335 		case Utils::VARIABLE_TYPE_DVEC4:
14336 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14337 				function, "reflect", tcu::reflect);
14338 		default:
14339 			break;
14340 		}
14341 
14342 		break;
14343 
14344 	case FUNCTION_REFRACT:
14345 
14346 		switch (variable_type)
14347 		{
14348 		case Utils::VARIABLE_TYPE_DVEC2:
14349 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14350 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14351 				function, "refract", tcu::refract);
14352 		case Utils::VARIABLE_TYPE_DVEC3:
14353 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14354 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14355 				function, "refract", tcu::refract);
14356 		case Utils::VARIABLE_TYPE_DVEC4:
14357 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14358 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14359 				function, "refract", tcu::refract);
14360 		default:
14361 			break;
14362 		}
14363 
14364 		break;
14365 
14366 	case FUNCTION_ROUND:
14367 
14368 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14369 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14370 
14371 	case FUNCTION_ROUNDEVEN:
14372 
14373 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14374 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14375 
14376 	case FUNCTION_SIGN:
14377 
14378 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14379 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14380 
14381 	case FUNCTION_SMOOTHSTEP:
14382 
14383 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14384 													 variable_type /* res_type  */, variable_type /* arg1_type */,
14385 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
14386 
14387 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14388 
14389 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14390 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
14391 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14392 
14393 	case FUNCTION_SQRT:
14394 
14395 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14396 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14397 
14398 	case FUNCTION_STEP:
14399 
14400 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14401 													 glw::GLdouble /* Arg2T */>(
14402 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14403 			variable_type /* arg2_type */);
14404 
14405 	case FUNCTION_STEP_AGAINST_SCALAR:
14406 
14407 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14408 													 glw::GLdouble /* Arg2T */>(
14409 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14410 			variable_type /* arg2_type */);
14411 
14412 	case FUNCTION_TRANSPOSE:
14413 
14414 		switch (variable_type)
14415 		{
14416 		case Utils::VARIABLE_TYPE_DMAT2:
14417 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14418 																				 Math::transpose);
14419 		case Utils::VARIABLE_TYPE_DMAT2X3:
14420 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14421 																					 Math::transpose);
14422 		case Utils::VARIABLE_TYPE_DMAT2X4:
14423 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14424 																					 Math::transpose);
14425 		case Utils::VARIABLE_TYPE_DMAT3:
14426 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14427 																				 Math::transpose);
14428 		case Utils::VARIABLE_TYPE_DMAT3X2:
14429 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14430 																					 Math::transpose);
14431 		case Utils::VARIABLE_TYPE_DMAT3X4:
14432 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14433 																					 Math::transpose);
14434 		case Utils::VARIABLE_TYPE_DMAT4:
14435 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14436 																				 Math::transpose);
14437 		case Utils::VARIABLE_TYPE_DMAT4X2:
14438 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14439 																					 Math::transpose);
14440 		case Utils::VARIABLE_TYPE_DMAT4X3:
14441 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14442 																					 Math::transpose);
14443 		default:
14444 			break;
14445 		}
14446 
14447 		break;
14448 
14449 	case FUNCTION_TRUNC:
14450 
14451 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14452 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14453 
14454 	case FUNCTION_UNPACKDOUBLE2X32:
14455 
14456 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14457 																						  Math::unpackDouble2x32);
14458 
14459 	case FUNCTION_ISNAN:
14460 
14461 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14462 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14463 
14464 	case FUNCTION_ISINF:
14465 
14466 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14467 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14468 
14469 	default:
14470 		TCU_FAIL("Not implemented");
14471 		return 0;
14472 	}
14473 
14474 	TCU_FAIL("Not implemented");
14475 	return 0;
14476 }
14477 
14478 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14479  *
14480  * @param argument        Argument index
14481  * @param function_object Function object
14482  *
14483  * @return Function pointer
14484  **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14485 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14486 	glw::GLuint argument, const functionObject& function_object) const
14487 {
14488 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14489 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14490 
14491 	switch (argument_type)
14492 	{
14493 	case Utils::VARIABLE_TYPE_DMAT2:
14494 		return gl.uniformMatrix2dv;
14495 	case Utils::VARIABLE_TYPE_DMAT2X3:
14496 		return gl.uniformMatrix2x3dv;
14497 	case Utils::VARIABLE_TYPE_DMAT2X4:
14498 		return gl.uniformMatrix2x4dv;
14499 	case Utils::VARIABLE_TYPE_DMAT3:
14500 		return gl.uniformMatrix3dv;
14501 	case Utils::VARIABLE_TYPE_DMAT3X2:
14502 		return gl.uniformMatrix3x2dv;
14503 	case Utils::VARIABLE_TYPE_DMAT3X4:
14504 		return gl.uniformMatrix3x4dv;
14505 	case Utils::VARIABLE_TYPE_DMAT4:
14506 		return gl.uniformMatrix4dv;
14507 	case Utils::VARIABLE_TYPE_DMAT4X2:
14508 		return gl.uniformMatrix4x2dv;
14509 	case Utils::VARIABLE_TYPE_DMAT4X3:
14510 		return gl.uniformMatrix4x3dv;
14511 	default:
14512 		break;
14513 	}
14514 
14515 	TCU_FAIL("Not implemented");
14516 	return 0;
14517 }
14518 
14519 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14520  *
14521  * @param argument        Argument index
14522  * @param function_object Function object
14523  *
14524  * @return Function pointer
14525  **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14526 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14527 	glw::GLuint argument, const functionObject& function_object) const
14528 {
14529 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14530 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14531 
14532 	switch (argument_type)
14533 	{
14534 	case Utils::VARIABLE_TYPE_DOUBLE:
14535 		return gl.uniform1dv;
14536 	case Utils::VARIABLE_TYPE_DVEC2:
14537 		return gl.uniform2dv;
14538 	case Utils::VARIABLE_TYPE_DVEC3:
14539 		return gl.uniform3dv;
14540 	case Utils::VARIABLE_TYPE_DVEC4:
14541 		return gl.uniform4dv;
14542 	default:
14543 		TCU_FAIL("Not implemented");
14544 	}
14545 
14546 	return 0;
14547 }
14548 
14549 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14550  *
14551  * @param argument        Argument index
14552  * @param function_object Function object
14553  *
14554  * @return Function pointer
14555  **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14556 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14557 	glw::GLuint argument, const functionObject& function_object) const
14558 {
14559 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14560 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14561 
14562 	switch (argument_type)
14563 	{
14564 	case Utils::VARIABLE_TYPE_INT:
14565 		return gl.uniform1iv;
14566 	case Utils::VARIABLE_TYPE_IVEC2:
14567 		return gl.uniform2iv;
14568 	case Utils::VARIABLE_TYPE_IVEC3:
14569 		return gl.uniform3iv;
14570 	case Utils::VARIABLE_TYPE_IVEC4:
14571 		return gl.uniform4iv;
14572 	default:
14573 		TCU_FAIL("Not implemented");
14574 	}
14575 
14576 	return 0;
14577 }
14578 
14579 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14580  *
14581  * @param argument        Argument index
14582  * @param function_object Function object
14583  *
14584  * @return Function pointer
14585  **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14586 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14587 	glw::GLuint argument, const functionObject& function_object) const
14588 {
14589 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14590 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14591 
14592 	switch (argument_type)
14593 	{
14594 	case Utils::VARIABLE_TYPE_UVEC2:
14595 		return gl.uniform2uiv;
14596 	default:
14597 		TCU_FAIL("Not implemented");
14598 	}
14599 
14600 	return 0;
14601 }
14602 
14603 /** Get name of uniform that will be used as <argument>.
14604  *
14605  * @param argument Argument index
14606  *
14607  * @return Name of uniform
14608  **/
getUniformName(glw::GLuint argument) const14609 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14610 {
14611 	switch (argument)
14612 	{
14613 	case 0:
14614 		return "uniform_0";
14615 	case 1:
14616 		return "uniform_1";
14617 	case 2:
14618 		return "uniform_2";
14619 	default:
14620 		TCU_FAIL("Not implemented");
14621 		return 0;
14622 	}
14623 }
14624 
14625 /** Get name of varying that will be used as <result>.
14626  *
14627  * @param result Result index
14628  *
14629  * @return Name of varying
14630  **/
getVaryingName(glw::GLuint result) const14631 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14632 {
14633 	switch (result)
14634 	{
14635 	case 0:
14636 		return "result_0";
14637 	case 1:
14638 		return "result_1";
14639 	case 2:
14640 		return "result_2";
14641 	default:
14642 		TCU_FAIL("Not implemented");
14643 		return 0;
14644 	}
14645 }
14646 
14647 /** Check if given combination of function and type is implemented
14648  *
14649  * @param function Function enumeration
14650  * @param type     Type details
14651  *
14652  * @return true if function is available for given type, false otherwise
14653  **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14654 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14655 {
14656 	static const bool look_up_table[][3] = {
14657 		/* SCALAR, VECTOR, MATRIX */
14658 		/* FUNCTION_ABS:                       */ { true, true, false },
14659 		/* FUNCTION_CEIL:                      */ { true, true, false },
14660 		/* FUNCTION_CLAMP:                     */ { true, true, false },
14661 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14662 		/* FUNCTION_CROSS:                     */ { false, true, false },
14663 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
14664 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
14665 		/* FUNCTION_DOT:                       */ { false, true, false },
14666 		/* FUNCTION_EQUAL:                     */ { false, true, false },
14667 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
14668 		/* FUNCTION_FLOOR:                     */ { true, true, false },
14669 		/* FUNCTION_FMA:                       */ { true, true, false },
14670 		/* FUNCTION_FRACT:                     */ { true, true, false },
14671 		/* FUNCTION_FREXP:                     */ { true, true, false },
14672 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
14673 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14674 		/* FUNCTION_INVERSE:                   */ { false, false, true },
14675 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
14676 		/* FUNCTION_LDEXP:                     */ { true, true, false },
14677 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
14678 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14679 		/* FUNCTION_LENGTH:                    */ { false, true, false },
14680 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14681 		/* FUNCTION_MAX:                       */ { true, true, false },
14682 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14683 		/* FUNCTION_MIN:                       */ { true, true, false },
14684 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14685 		/* FUNCTION_MIX:                       */ { true, true, false },
14686 		/* FUNCTION_MOD:                       */ { true, true, false },
14687 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14688 		/* FUNCTION_MODF:                      */ { true, true, false },
14689 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
14690 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14691 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14692 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14693 		/* FUNCTION_REFLECT:                   */ { false, true, false },
14694 		/* FUNCTION_REFRACT:                   */ { false, true, false },
14695 		/* FUNCTION_ROUND:                     */ { true, true, false },
14696 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14697 		/* FUNCTION_SIGN:                      */ { true, false, false },
14698 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14699 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14700 		/* FUNCTION_SQRT:                      */ { true, true, false },
14701 		/* FUNCTION_STEP:                      */ { true, true, false },
14702 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14703 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14704 		/* FUNCTION_TRUNC:                     */ { true, true, false },
14705 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14706 		/* FUNCTION_ISNAN:                     */ { true, true, false },
14707 		/* FUNCTION_ISINF:                     */ { true, true, false },
14708 	};
14709 
14710 	bool result = look_up_table[function][type.m_general_type];
14711 
14712 	if (true == result)
14713 	{
14714 		switch (function)
14715 		{
14716 		case FUNCTION_CROSS: /* Only 3 element vectors */
14717 			result = (3 == type.m_n_rows);
14718 			break;
14719 		case FUNCTION_DETERMINANT: /* Only square matrices */
14720 		case FUNCTION_INVERSE:
14721 			result = (type.m_n_columns == type.m_n_rows);
14722 			break;
14723 		default:
14724 			break;
14725 		}
14726 	}
14727 
14728 	return result;
14729 }
14730 
14731 /** Logs variable of given type: name (type) [values]
14732  *
14733  * @param buffer Source of data
14734  * @param name   Name of variable
14735  * @param type   Type of variable
14736  **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14737 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14738 										  Utils::_variable_type type) const
14739 {
14740 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
14741 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
14742 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14743 
14744 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14745 
14746 	for (glw::GLuint component = 0; component < n_components; ++component)
14747 	{
14748 		if (0 != component)
14749 		{
14750 			message << ", ";
14751 		}
14752 
14753 		switch (base_type)
14754 		{
14755 		case Utils::VARIABLE_TYPE_DOUBLE:
14756 			message << ((glw::GLdouble*)buffer)[component];
14757 			break;
14758 		case Utils::VARIABLE_TYPE_INT:
14759 			message << ((glw::GLint*)buffer)[component];
14760 			break;
14761 		case Utils::VARIABLE_TYPE_UINT:
14762 			message << ((glw::GLuint*)buffer)[component];
14763 			break;
14764 		default:
14765 			TCU_FAIL("Not implemented");
14766 		}
14767 	}
14768 
14769 	message << "]" << tcu::TestLog::EndMessage;
14770 }
14771 
14772 /** Prepare input arguments, data are stored in <buffer>
14773  *
14774  * @param function_object Function object
14775  * @param vertex          Vertex index
14776  * @param buffer          Buffer pointer
14777  **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14778 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14779 										  glw::GLubyte* buffer)
14780 {
14781 	const glw::GLuint n_arguments = function_object.getArgumentCount();
14782 
14783 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14784 	{
14785 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
14786 
14787 		prepareComponents(function_object, vertex, argument, buffer + offset);
14788 	}
14789 }
14790 
14791 /** Prepare components for given <function_object>, <vertex> and <argument>
14792  *
14793  * @param function_object Function object
14794  * @param vertex          Vertex index
14795  * @param argument        Argument index
14796  * @param buffer          Buffer pointer
14797  **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14798 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14799 											glw::GLuint argument, glw::GLubyte* buffer)
14800 {
14801 	glw::GLuint					argument_index[3]		 = { 0 };
14802 	glw::GLuint					argument_reset[3]		 = { 0 };
14803 	glw::GLuint					argument_step[3]		 = { 0 };
14804 	glw::GLdouble				double_argument_start[3] = { 0.0 };
14805 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14806 	glw::GLuint					int_argument_start  = -4;
14807 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
14808 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
14809 	glw::GLuint					uint_argument_start = 0;
14810 
14811 	switch (n_arguments)
14812 	{
14813 	case 1:
14814 		argument_step[0]		 = 1;
14815 		argument_reset[0]		 = 1024;
14816 		double_argument_start[0] = -511.5;
14817 		break;
14818 	case 2:
14819 		argument_step[0]		 = 32;
14820 		argument_step[1]		 = 1;
14821 		argument_reset[0]		 = 32;
14822 		argument_reset[1]		 = 32;
14823 		double_argument_start[0] = -15.5;
14824 		double_argument_start[1] = -15.5;
14825 		break;
14826 	case 3:
14827 		argument_step[0]		 = 64;
14828 		argument_step[1]		 = 8;
14829 		argument_step[2]		 = 1;
14830 		argument_reset[0]		 = 16;
14831 		argument_reset[1]		 = 8;
14832 		argument_reset[2]		 = 8;
14833 		double_argument_start[0] = -7.5;
14834 		double_argument_start[1] = -3.5;
14835 		double_argument_start[2] = -3.5;
14836 		break;
14837 	default:
14838 		TCU_FAIL("Not implemented");
14839 		return;
14840 	}
14841 
14842 	switch (function_object.getFunctionEnum())
14843 	{
14844 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14845 	case FUNCTION_CLAMP_AGAINST_SCALAR:
14846 		double_argument_start[2] = 4.5;
14847 		break;
14848 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14849 		double_argument_start[0] = 16.5;
14850 		break;
14851 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14852 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14853 		argument_step[0]		 = 1;
14854 		argument_step[1]		 = 8;
14855 		argument_step[2]		 = 64;
14856 		argument_reset[0]		 = 8;
14857 		argument_reset[1]		 = 8;
14858 		argument_reset[2]		 = 16;
14859 		double_argument_start[0] = -3.5;
14860 		double_argument_start[1] = 4.5;
14861 		double_argument_start[2] = -7.5;
14862 		break;
14863 	default:
14864 		break;
14865 	}
14866 
14867 	for (glw::GLuint i = 0; i < n_arguments; ++i)
14868 	{
14869 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14870 	}
14871 
14872 	switch (base_arg_type)
14873 	{
14874 	case Utils::VARIABLE_TYPE_DOUBLE:
14875 	{
14876 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14877 
14878 		double_argument_start[argument] += argument_index[argument];
14879 
14880 		for (glw::GLuint component = 0; component < n_components; ++component)
14881 		{
14882 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14883 
14884 			switch (function_object.getFunctionEnum())
14885 			{
14886 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14887 				if (0.5 == Math::fract(value))
14888 				{
14889 					value += 0.01;
14890 				}
14891 				break;
14892 			default:
14893 				break;
14894 			}
14895 
14896 			argument_dst[component] = value;
14897 		}
14898 	}
14899 	break;
14900 	case Utils::VARIABLE_TYPE_INT:
14901 	{
14902 		glw::GLint* argument_dst = (glw::GLint*)buffer;
14903 
14904 		uint_argument_start += argument_index[argument];
14905 
14906 		for (glw::GLuint component = 0; component < n_components; ++component)
14907 		{
14908 			const glw::GLint value = int_argument_start + component;
14909 
14910 			argument_dst[component] = value;
14911 		}
14912 	}
14913 	break;
14914 	case Utils::VARIABLE_TYPE_UINT:
14915 	{
14916 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14917 
14918 		uint_argument_start += argument_index[argument];
14919 
14920 		for (glw::GLuint component = 0; component < n_components; ++component)
14921 		{
14922 			const glw::GLuint value = uint_argument_start + component;
14923 
14924 			argument_dst[component] = value;
14925 		}
14926 	}
14927 	break;
14928 	default:
14929 		TCU_FAIL("Not implemented");
14930 		return;
14931 	}
14932 }
14933 
14934 /** Prepare programInfo for given functionObject
14935  *
14936  * @param function_object  Function object
14937  * @param out_program_info Program info
14938  **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14939 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14940 {
14941 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
14942 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14943 
14944 	prepareVertexShaderCode(function_object);
14945 
14946 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14947 						   varying_names, n_varying_names);
14948 }
14949 
14950 /** Prepare input data and expected results for given function object
14951  *
14952  * @param function_object Function object
14953  **/
prepareTestData(const functionObject & function_object)14954 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14955 {
14956 	const glw::GLuint result_stride		   = function_object.getResultStride();
14957 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
14958 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
14959 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14960 
14961 	m_argument_data.clear();
14962 	m_expected_results_data.clear();
14963 
14964 	m_argument_data.resize(argument_buffer_size);
14965 	m_expected_results_data.resize(result_buffer_size);
14966 
14967 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14968 	{
14969 		const glw::GLuint result_offset   = vertex * result_stride;
14970 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
14971 		const glw::GLuint argument_offset = vertex * argument_stride;
14972 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
14973 
14974 		prepareArgument(function_object, vertex, argument_dst);
14975 		function_object.call(result_dst, argument_dst);
14976 	}
14977 }
14978 
14979 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14980  *
14981  * @param function_object Function object
14982  **/
prepareVertexShaderCode(const functionObject & function_object)14983 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14984 {
14985 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
14986 													 "\n"
14987 													 "precision highp float;\n"
14988 													 "\n"
14989 													 "ARGUMENT_DEFINITION"
14990 													 "\n"
14991 													 "RESULT_DEFINITION"
14992 													 "\n"
14993 													 "void main()\n"
14994 													 "{\n"
14995 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14996 													 "}\n"
14997 													 "\n";
14998 
14999 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15000 	static const glw::GLchar* argument_token			= "ARGUMENT";
15001 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
15002 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15003 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
15004 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
15005 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
15006 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
15007 
15008 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15009 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
15010 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
15011 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15012 
15013 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15014 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
15015 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
15016 	const glw::GLuint n_results					 = function_object.getResultCount();
15017 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15018 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
15019 
15020 	size_t		search_position = 0;
15021 	std::string string			= shader_template_code;
15022 
15023 	/* Replace ARGUMENT_DEFINITION with definitions */
15024 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15025 	{
15026 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15027 		const glw::GLchar*	uniform_name  = getUniformName(argument);
15028 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
15029 
15030 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15031 
15032 		search_position -= argument_definition_length;
15033 
15034 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15035 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15036 	}
15037 
15038 	/* Remove ARGUMENT_DEFINITION */
15039 	Utils::replaceToken(argument_definition_token, search_position, "", string);
15040 
15041 	/* Replace RESULT_DEFINITION with definitions */
15042 	for (glw::GLuint result = 0; result < n_results; ++result)
15043 	{
15044 		Utils::_variable_type variable_type = function_object.getResultType(result);
15045 		const glw::GLchar*	varying_name  = getVaryingName(result);
15046 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
15047 
15048 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15049 
15050 		search_position -= result_definition_length;
15051 
15052 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15053 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
15054 	}
15055 
15056 	/* Remove RESULT_DEFINITION */
15057 	Utils::replaceToken(result_definition_token, search_position, "", string);
15058 
15059 	/* Replace RESULT_NAME */
15060 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15061 
15062 	/* Replace RESULT_TYPE */
15063 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15064 
15065 	/* Replace FUNCTION_NAME */
15066 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15067 
15068 	/* Replace ARGUMENT with list of arguments */
15069 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15070 	{
15071 		const glw::GLchar* uniform_name = getUniformName(argument);
15072 
15073 		if (0 == argument)
15074 		{
15075 			Utils::replaceToken(argument_token, search_position, first_argument, string);
15076 		}
15077 		else
15078 		{
15079 			Utils::replaceToken(argument_token, search_position, argument_str, string);
15080 		}
15081 
15082 		search_position -= first_argument_length;
15083 
15084 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15085 	}
15086 
15087 	for (glw::GLuint result = 1; result < n_results; ++result)
15088 	{
15089 		const glw::GLchar* varying_name = getVaryingName(result);
15090 
15091 		Utils::replaceToken(argument_token, search_position, argument_str, string);
15092 
15093 		search_position -= first_argument_length;
15094 
15095 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15096 	}
15097 
15098 	/* Remove ARGUMENT */
15099 	Utils::replaceToken(argument_token, search_position, "", string);
15100 
15101 	m_vertex_shader_code = string;
15102 }
15103 
15104 /** Test single function with one type
15105  *
15106  * param function Function enumeration
15107  * param type     Type details
15108  *
15109  * @return true if test pass (or function is not available for <type>), false otherwise
15110  **/
test(FunctionEnum function,const typeDetails & type)15111 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15112 {
15113 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15114 
15115 	/* Skip if function is not implemented for type */
15116 	if (false == isFunctionImplemented(function, type))
15117 	{
15118 		return true;
15119 	}
15120 
15121 	Utils::programInfo			  program(m_context);
15122 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15123 
15124 	prepareProgram(*function_object, program);
15125 	prepareTestData(*function_object);
15126 
15127 	/* Set up program */
15128 	gl.useProgram(program.m_program_object_id);
15129 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15130 
15131 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15132 	{
15133 		testBegin(*function_object, program.m_program_object_id, vertex);
15134 
15135 		gl.beginTransformFeedback(GL_POINTS);
15136 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15137 
15138 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15139 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15140 
15141 		gl.endTransformFeedback();
15142 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15143 
15144 		if (false == verifyResults(*function_object, vertex))
15145 		{
15146 			return false;
15147 		}
15148 	}
15149 
15150 	return true;
15151 }
15152 
15153 /** Update transform feedback buffer and uniforms
15154  *
15155  * @param function_object Function object
15156  * @param program_id      Program object id
15157  * @param vertex          Vertex index
15158  **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15159 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15160 {
15161 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
15162 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
15163 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
15164 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
15165 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
15166 
15167 	/* Update transform feedback buffer */
15168 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
15169 	transform_feedback_buffer_data.resize(result_buffer_size);
15170 
15171 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15172 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15173 
15174 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15175 				  GL_DYNAMIC_COPY);
15176 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15177 
15178 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15179 					   result_buffer_size);
15180 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15181 
15182 	/* Update VAO */
15183 	gl.bindVertexArray(m_vertex_array_object_id);
15184 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15185 
15186 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15187 	{
15188 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
15189 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
15190 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
15191 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
15192 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
15193 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15194 
15195 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15196 
15197 		if (-1 == uniform_location)
15198 		{
15199 			TCU_FAIL("Inactive uniform");
15200 		}
15201 
15202 		if (1 == n_columns)
15203 		{
15204 			switch (Utils::getBaseVariableType(argument_type))
15205 			{
15206 			case Utils::VARIABLE_TYPE_DOUBLE:
15207 			{
15208 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15209 
15210 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15211 			}
15212 			break;
15213 			case Utils::VARIABLE_TYPE_UINT:
15214 			{
15215 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15216 
15217 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15218 			}
15219 			break;
15220 			case Utils::VARIABLE_TYPE_INT:
15221 			{
15222 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15223 
15224 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15225 			}
15226 			break;
15227 			default:
15228 				TCU_FAIL("Not implemented");
15229 			}
15230 		}
15231 		else
15232 		{
15233 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15234 
15235 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15236 		}
15237 	}
15238 }
15239 
15240 /** Init GL obejcts
15241  *
15242  **/
testInit()15243 void BuiltinFunctionTest::testInit()
15244 {
15245 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15246 
15247 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
15248 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15249 
15250 	gl.genVertexArrays(1, &m_vertex_array_object_id);
15251 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15252 
15253 	gl.enable(GL_RASTERIZER_DISCARD);
15254 }
15255 
15256 /** Checks if function result is an acceptable edge case
15257  *
15258  * @param function_object Function object
15259  * @param vertex          Vertex index
15260  *
15261  * @return true if all results are as expected, false otherwise
15262  **/
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)15263 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15264 										   const Utils::_variable_type result_type,
15265 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15266 {
15267 	FunctionEnum function_type = function_object.getFunctionEnum();
15268 	switch (function_type)
15269 	{
15270 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15271 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15272 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15273 	case FUNCTION_MOD:
15274 	case FUNCTION_MOD_AGAINST_SCALAR:
15275 	{
15276 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
15277 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
15278 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
15279 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
15280 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
15281 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
15282 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
15283 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
15284 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15285 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15286 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15287 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
15288 		bool				 edge_case_present = false;
15289 		bool				 recheck		   = false;
15290 
15291 		// verify if there is a mod(a, a) case and prepare new expected result
15292 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15293 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15294 		for (glw::GLuint component = 0; component < n_components; ++component)
15295 		{
15296 			glw::GLdouble expected_result_component = expected_result[component];
15297 			glw::GLdouble actual_result_component   = actual_result[component];
15298 			glw::GLdouble argument_1_component		= argument_1[component];
15299 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15300 
15301 			// if coresponding components of arguments are equal and if component of first argument
15302 			// and component of result are equal then expected result must be corrected
15303                         bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15304                                                                       round(argument_1_component / argument_2_component));
15305                         edge_case_present = possible_edge_case &&
15306                                             (m_epsilon > de::abs(argument_2_component - actual_result_component));
15307 			recheck |= edge_case_present;
15308                         corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15309 		}
15310 
15311 		// recheck test result with corrected expected result
15312 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15313 	}
15314 	default:
15315 		return false;
15316 	}
15317 }
15318 
15319 /** Compare contents of transform feedback buffer with expected results
15320  *
15321  * @param function_object Function object
15322  * @param vertex          Vertex index
15323  *
15324  * @return true if all results are as expected, false otherwise
15325  **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15326 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15327 {
15328 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
15329 	bool				  test_result	  = true;
15330 	const glw::GLuint	 n_results		   = function_object.getResultCount();
15331 	const glw::GLuint	 results_stride   = function_object.getResultStride();
15332 	const glw::GLuint	 results_offset   = vertex * results_stride;
15333 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15334 
15335 	/* Get transform feedback data */
15336 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15337 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15338 
15339 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15340 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15341 
15342 	for (glw::GLuint result = 0; result < n_results; ++result)
15343 	{
15344 		const Utils::_variable_type result_type   = function_object.getResultType(result);
15345 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
15346 
15347 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
15348 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
15349 
15350 		if (compare(result_type, expected_result_src, result_src))
15351 			continue;
15352 
15353 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15354 		{
15355 			test_result = false;
15356 			break;
15357 		}
15358 	}
15359 
15360 	/* Unmap transform feedback buffer */
15361 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15362 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15363 
15364 	if (false == test_result)
15365 	{
15366 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
15367 		const glw::GLuint arguments_offset = vertex * argument_stride;
15368 
15369 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15370 											<< tcu::TestLog::EndMessage;
15371 
15372 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15373 											<< tcu::TestLog::EndMessage;
15374 
15375 		for (glw::GLuint result = 0; result < n_results; ++result)
15376 		{
15377 			const Utils::_variable_type result_type   = function_object.getResultType(result);
15378 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
15379 
15380 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
15381 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
15382 
15383 			logVariableType(result_src, "Result", result_type);
15384 			logVariableType(expected_result_src, "Expected result", result_type);
15385 		}
15386 
15387 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15388 		{
15389 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15390 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
15391 
15392 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15393 		}
15394 
15395 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15396 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
15397 	}
15398 
15399 	return test_result;
15400 }
15401 
15402 /** Constructor.
15403  *
15404  *  @param context Rendering context.
15405  **/
GPUShaderFP64Tests(deqp::Context & context)15406 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15407 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15408 {
15409 	/* Left blank on purpose */
15410 }
15411 
15412 /** Initializes a texture_storage_multisample test group.
15413  *
15414  **/
init(void)15415 void GPUShaderFP64Tests::init(void)
15416 {
15417 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15418 	fp64->addChild(new GPUShaderFP64Test1(m_context));
15419 	fp64->addChild(new GPUShaderFP64Test2(m_context));
15420 	fp64->addChild(new GPUShaderFP64Test3(m_context));
15421 	fp64->addChild(new GPUShaderFP64Test4(m_context));
15422 	fp64->addChild(new GPUShaderFP64Test5(m_context));
15423 	fp64->addChild(new GPUShaderFP64Test6(m_context));
15424 	fp64->addChild(new GPUShaderFP64Test7(m_context));
15425 	fp64->addChild(new GPUShaderFP64Test8(m_context));
15426 	fp64->addChild(new GPUShaderFP64Test9(m_context));
15427 	addChild(fp64);
15428 
15429 	TypeDefinition typeDefinition[] =
15430 	{
15431 		{ "double",  1, 1 },
15432 		{ "dvec2",   1, 2 },
15433 		{ "dvec3",   1, 3 },
15434 		{ "dvec4",   1, 4 },
15435 		{ "dmat2",   2, 2 },
15436 		{ "dmat2x3", 2, 3 },
15437 		{ "dmat2x4", 2, 4 },
15438 		{ "dmat3x2", 3, 2 },
15439 		{ "dmat3",   3, 3 },
15440 		{ "dmat3x4", 3, 4 },
15441 		{ "dmat4x2", 4, 2 },
15442 		{ "dmat4x3", 4, 3 },
15443 		{ "dmat4",   4, 4 }
15444 	};
15445 
15446 	struct BuiltinFunctions
15447 	{
15448 		std::string  name;
15449 		FunctionEnum function;
15450 	} builtinFunctions[] = {
15451 		{ "abs",						FUNCTION_ABS },
15452 		{ "ceil",						FUNCTION_CEIL },
15453 		{ "clamp",						FUNCTION_CLAMP },
15454 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
15455 		{ "cross",						FUNCTION_CROSS },
15456 		{ "determinant",				FUNCTION_DETERMINANT },
15457 		{ "distance",					FUNCTION_DISTANCE },
15458 		{ "dot",						FUNCTION_DOT },
15459 		{ "equal",						FUNCTION_EQUAL },
15460 		{ "faceforward",				FUNCTION_FACEFORWARD },
15461 		{ "floor",						FUNCTION_FLOOR },
15462 		{ "fma",						FUNCTION_FMA },
15463 		{ "fract",						FUNCTION_FRACT },
15464 		{ "frexp",						FUNCTION_FREXP },
15465 		{ "greaterthan",				FUNCTION_GREATERTHAN },
15466 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
15467 		{ "inverse",					FUNCTION_INVERSE },
15468 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
15469 		{ "ldexp",						FUNCTION_LDEXP },
15470 		{ "lessthan",					FUNCTION_LESSTHAN },
15471 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
15472 		{ "length",						FUNCTION_LENGTH },
15473 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
15474 		{ "max",						FUNCTION_MAX },
15475 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
15476 		{ "min",						FUNCTION_MIN },
15477 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
15478 		{ "mix",						FUNCTION_MIX },
15479 		{ "mod",						FUNCTION_MOD },
15480 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
15481 		{ "modf",						FUNCTION_MODF },
15482 		{ "normalize",					FUNCTION_NORMALIZE },
15483 		{ "notequal",					FUNCTION_NOTEQUAL },
15484 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
15485 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
15486 		{ "reflect",					FUNCTION_REFLECT },
15487 		{ "refract",					FUNCTION_REFRACT },
15488 		{ "round",						FUNCTION_ROUND },
15489 		{ "roundeven",					FUNCTION_ROUNDEVEN },
15490 		{ "sign",						FUNCTION_SIGN },
15491 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
15492 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15493 		{ "sqrt",						FUNCTION_SQRT },
15494 		{ "step",						FUNCTION_STEP },
15495 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
15496 		{ "transpose",					FUNCTION_TRANSPOSE },
15497 		{ "trunc",						FUNCTION_TRUNC },
15498 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
15499 		{ "isnan",						FUNCTION_ISNAN },
15500 		{ "isinf",						FUNCTION_ISINF }
15501 	};
15502 
15503 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15504 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15505 	{
15506 		const BuiltinFunctions& bf = builtinFunctions[i];
15507 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15508 		{
15509 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
15510 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15511 		}
15512 	}
15513 	addChild(builin);
15514 }
15515 
15516 } /* glcts namespace */
15517