• 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   dummy1[3]     |     4 |      12 |      0 |   12 |               0 |     |
5308 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5309 	 * bool    dummy2        |     1 |       1 |     14 |   15 |              56 |     |
5310 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5311 	 * bvec3   dummy3        |     4 |       4 |     20 |   24 |              80 |     |
5312 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5313 	 * int     dummy4[3]     |     4 |      12 |     32 |   44 |             128 |     |
5314 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5315 	 * bool    dummy5        |     1 |       1 |     56 |   57 |             224 |     |
5316 	 * bool    dummy6[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    dummy7        |     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   dummy8        |     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    dummy9        |     1 |       1 |    196 |  197 |             784 |     |
5326 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5327 	 * int     dummy10       |     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   dummy1[3];\n"
5694 																			 "    double  double_value;\n"
5695 																			 "    bool    dummy2;\n"
5696 																			 "    dvec2   dvec2_value;\n"
5697 																			 "    bvec3   dummy3;\n"
5698 																			 "    dvec3   dvec3_value;\n"
5699 																			 "    int     dummy4[3];\n"
5700 																			 "    dvec4   dvec4_value;\n"
5701 																			 "    bool    dummy5;\n"
5702 																			 "    bool    dummy6[2];\n"
5703 																			 "    dmat2   dmat2_value;\n"
5704 																			 "    dmat3   dmat3_value;\n"
5705 																			 "    bool    dummy7;\n"
5706 																			 "    dmat4   dmat4_value;\n"
5707 																			 "    dmat2x3 dmat2x3_value;\n"
5708 																			 "    uvec3   dummy8;\n"
5709 																			 "    dmat2x4 dmat2x4_value;\n"
5710 																			 "    dmat3x2 dmat3x2_value;\n"
5711 																			 "    bool    dummy9;\n"
5712 																			 "    dmat3x4 dmat3x4_value;\n"
5713 																			 "    int     dummy10;\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 	unsigned int		  counter = 6;
10293 
10294 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10295 		 variable_iterator++)
10296 	{
10297 		const _variable&   variable			  = *variable_iterator;
10298 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
10299 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10300 		unsigned int	   n_components		  = 0;
10301 		unsigned int	   n_columns		  = 1;
10302 
10303 		if (is_matrix_type)
10304 		{
10305 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
10306 			n_components = n_total_components / n_columns;
10307 
10308 			DE_ASSERT(n_total_components % n_columns == 0);
10309 		}
10310 		else
10311 		{
10312 			n_components = n_total_components;
10313 		}
10314 
10315 		DE_ASSERT(n_components >= 1 && n_components <= 4);
10316 
10317 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10318 		{
10319 			const double data[] = { -1, -1, -1, -1 };
10320 
10321 			switch (n_components)
10322 			{
10323 			case 1:
10324 			{
10325 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
10326 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10327 
10328 				break;
10329 			}
10330 
10331 			case 2:
10332 			{
10333 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
10334 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10335 
10336 				break;
10337 			}
10338 
10339 			case 3:
10340 			{
10341 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
10342 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10343 
10344 				break;
10345 			}
10346 
10347 			case 4:
10348 			{
10349 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
10350 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10351 
10352 				break;
10353 			}
10354 
10355 			default:
10356 			{
10357 				TCU_FAIL("Unrecognized number of components");
10358 			}
10359 			} /* switch (n_components) */
10360 
10361 			/* Make sure VAAs are disabled */
10362 			gl.disableVertexAttribArray(variable.attribute_location + index);
10363 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10364 
10365 			counter += n_components;
10366 		} /* for (all array indices) */
10367 	}	 /* for (all variables) */
10368 }
10369 
10370 /** Constructor
10371  *
10372  *  @param context Rendering context.
10373  */
GPUShaderFP64Test8(deqp::Context & context)10374 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10375 	: TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10376 											  "are accepted during compilation stage")
10377 	, m_cs_id(0)
10378 	, m_fs_id(0)
10379 	, m_gs_id(0)
10380 	, m_tc_id(0)
10381 	, m_te_id(0)
10382 	, m_vs_id(0)
10383 	, m_has_test_passed(true)
10384 {
10385 }
10386 
10387 /** Deinitializes all buffers and GL objects that may have been generated
10388  *  during test execution.
10389  **/
deinit()10390 void GPUShaderFP64Test8::deinit()
10391 {
10392 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10393 
10394 	if (m_cs_id != 0)
10395 	{
10396 		gl.deleteShader(m_cs_id);
10397 
10398 		m_cs_id = 0;
10399 	}
10400 
10401 	if (m_fs_id != 0)
10402 	{
10403 		gl.deleteShader(m_fs_id);
10404 
10405 		m_fs_id = 0;
10406 	}
10407 
10408 	if (m_gs_id != 0)
10409 	{
10410 		gl.deleteShader(m_gs_id);
10411 
10412 		m_gs_id = 0;
10413 	}
10414 
10415 	if (m_tc_id != 0)
10416 	{
10417 		gl.deleteShader(m_tc_id);
10418 
10419 		m_tc_id = 0;
10420 	}
10421 
10422 	if (m_te_id != 0)
10423 	{
10424 		gl.deleteShader(m_te_id);
10425 
10426 		m_te_id = 0;
10427 	}
10428 
10429 	if (m_vs_id != 0)
10430 	{
10431 		gl.deleteShader(m_vs_id);
10432 
10433 		m_vs_id = 0;
10434 	}
10435 }
10436 
10437 /** Executes a single test case.
10438  *
10439  *  This function can throw TestError exceptions if GL implementation reports
10440  *  an error.
10441  *
10442  *  @param test_case Test case descriptor.
10443  *
10444  *  @return true if test case passed, false otherwise.
10445  **/
executeIteration(const _test_case & test_case)10446 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10447 {
10448 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10449 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10450 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
10451 	bool				  result	 = true;
10452 	const char*			  stage_body = NULL;
10453 	const char*			  stage_name = NULL;
10454 
10455 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10456 	{
10457 		const glw::GLuint so_id = so_ids[n_so_id];
10458 
10459 		/* Skip compute shader if it is not supported */
10460 		if (0 == so_id)
10461 		{
10462 			continue;
10463 		}
10464 
10465 		/* Compile the shader */
10466 		gl.compileShader(so_id);
10467 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10468 
10469 		/* Has the compilation succeeded as expected? */
10470 		glw::GLint compile_status = GL_FALSE;
10471 
10472 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10473 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10474 
10475 		if (compile_status == GL_FALSE)
10476 		{
10477 			/* What is the current stage's name? */
10478 			if (so_id == m_cs_id)
10479 			{
10480 				stage_body = test_case.cs_shader_body.c_str();
10481 				stage_name = "Compute shader";
10482 			}
10483 			else if (so_id == m_fs_id)
10484 			{
10485 				stage_body = test_case.fs_shader_body.c_str();
10486 				stage_name = "Fragment shader";
10487 			}
10488 			else if (so_id == m_gs_id)
10489 			{
10490 				stage_body = test_case.gs_shader_body.c_str();
10491 				stage_name = "Geometry shader";
10492 			}
10493 			else if (so_id == m_tc_id)
10494 			{
10495 				stage_body = test_case.tc_shader_body.c_str();
10496 				stage_name = "Tessellation control shader";
10497 			}
10498 			else if (so_id == m_te_id)
10499 			{
10500 				stage_body = test_case.te_shader_body.c_str();
10501 				stage_name = "Tessellation evaluation shader";
10502 			}
10503 			else if (so_id == m_vs_id)
10504 			{
10505 				stage_body = test_case.vs_shader_body.c_str();
10506 				stage_name = "Vertex shader";
10507 			}
10508 			else
10509 			{
10510 				/* Doesn't make much sense to throw exceptions here so.. */
10511 				stage_body = "";
10512 				stage_name = "[?]";
10513 			}
10514 
10515 			/* This shader should have never failed to compile! */
10516 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10517 							   << " has not compiled successfully, even though the shader is valid."
10518 								  " Following is shader's body:\n"
10519 							   << stage_body << tcu::TestLog::EndMessage;
10520 
10521 			result = false;
10522 		}
10523 	} /* for (all shader objects) */
10524 
10525 	return result;
10526 }
10527 
10528 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10529  *  type.
10530  *
10531  *  @param variable_type Variable type to return valid argument lists for.
10532  **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10533 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10534 	const Utils::_variable_type& variable_type)
10535 {
10536 	const Utils::_variable_type matrix_types[] = {
10537 		Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10538 		Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10539 		Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10540 	};
10541 	const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10542 												   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10543 	const unsigned int n_matrix_types	 = sizeof(matrix_types) / sizeof(matrix_types[0]);
10544 	const unsigned int n_scalar_types	 = sizeof(scalar_types) / sizeof(scalar_types[0]);
10545 	const int		   n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10546 
10547 	/* Construct the argument list tree root. Each node carries a counter that tells how many components
10548 	 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10549 	 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10550 	 * used to define a subsequent argument, and its counter is increased by the amount of components
10551 	 * described by the type.
10552 	 */
10553 	_argument_list_tree_node root;
10554 
10555 	root.n_components_used = 0;
10556 	root.parent			   = NULL;
10557 	root.type			   = variable_type;
10558 
10559 	/* Fill till all leaves use up all available components */
10560 	_argument_list_tree_node_queue nodes_queue;
10561 
10562 	nodes_queue.push(&root);
10563 
10564 	do
10565 	{
10566 		/* Pop the first item in the queue */
10567 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10568 		nodes_queue.pop();
10569 
10570 		/* Matrix variable types can be defined by a combination of non-matrix variable types OR
10571 		 * a single matrix variable type.
10572 		 *
10573 		 * Let's handle the latter case first.
10574 		 */
10575 		const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10576 
10577 		if (Utils::isMatrixVariableType(current_node_ptr->type))
10578 		{
10579 			/* Iterate through all known matrix types. All the types can be used
10580 			 * as a constructor, assuming only one value is used to define new matrix's
10581 			 * contents. */
10582 			for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10583 			{
10584 				Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10585 
10586 				/* Construct a new child node. Since GLSL spec clearly states we must not use more
10587 				 * than one constructor argument if the only argument is a matrix type, mark the node
10588 				 * as if it defined all available components.
10589 				 */
10590 				_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10591 
10592 				new_subnode->n_components_used = n_total_components;
10593 				new_subnode->parent			   = current_node_ptr;
10594 				new_subnode->type			   = new_argument_type;
10595 
10596 				/* Add the descriptor to node list but do not add it to the queue. This would be
10597 				 * a redundant operation, since no new children nodes would have been assigned to
10598 				 * this node anyway.
10599 				 */
10600 				current_node_ptr->children.push_back(new_subnode);
10601 			} /* for (all matrix types) */
10602 		}	 /* if (current node's type is a matrix) */
10603 
10604 		/* Now for a combination of non-matrix variable types.. */
10605 		if (!Utils::isMatrixVariableType(current_node_ptr->type))
10606 		{
10607 			/* Iterate through all known scalar types */
10608 			for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10609 			{
10610 				Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10611 				const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10612 
10613 				/* Only use the scalar type if we don't exceed the amount of components we can define
10614 				 * for requested type.
10615 				 */
10616 				if (n_new_argument_components <= n_components_remaining)
10617 				{
10618 					/* Form new node descriptor */
10619 					_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10620 
10621 					new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10622 					new_subnode->parent			   = current_node_ptr;
10623 					new_subnode->type			   = new_argument_type;
10624 
10625 					current_node_ptr->children.push_back(new_subnode);
10626 					nodes_queue.push(new_subnode);
10627 				}
10628 			} /* for (all scalar types) */
10629 		}	 /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10630 	} while (nodes_queue.size() > 0);
10631 
10632 	/* To construct the argument lists, traverse the tree. Each path from root to child
10633 	 * gives us a single argument list.
10634 	 *
10635 	 * First, identify leaf nodes.
10636 	 */
10637 	_argument_list_tree_nodes leaf_nodes;
10638 
10639 	nodes_queue.push(&root);
10640 
10641 	do
10642 	{
10643 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10644 		nodes_queue.pop();
10645 
10646 		if (current_node_ptr->children.size() == 0)
10647 		{
10648 			/* This is a leaf node !*/
10649 			leaf_nodes.push_back(current_node_ptr);
10650 		}
10651 		else
10652 		{
10653 			/* Throw all children nodes to the queue */
10654 			const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10655 
10656 			for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10657 			{
10658 				nodes_queue.push(current_node_ptr->children[n_children_node]);
10659 			} /* for (all children nodes) */
10660 		}
10661 	} while (nodes_queue.size() > 0);
10662 
10663 	/* For all leaf nodes, move up the tree and construct the argument lists. */
10664 	const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10665 	_argument_lists	result;
10666 
10667 	for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10668 	{
10669 		_argument_list			  argument_list;
10670 		_argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10671 
10672 		do
10673 		{
10674 			if (current_node_ptr != &root)
10675 			{
10676 				if (argument_list.size() == 0)
10677 				{
10678 					argument_list.push_back(current_node_ptr->type);
10679 				}
10680 				else
10681 				{
10682 					argument_list.insert(argument_list.begin(), current_node_ptr->type);
10683 				}
10684 			}
10685 
10686 			current_node_ptr = current_node_ptr->parent;
10687 		} while (current_node_ptr != NULL);
10688 
10689 		result.push_back(argument_list);
10690 	} /* for (all leaf nodes) */
10691 
10692 	return result;
10693 }
10694 
10695 /** Retrieves body of a compute shader that should be used for the purpose of
10696  *  user-specified test case.
10697  *
10698  *  @param test_case Test case descriptor to use.
10699  *
10700  *  @return Requested string.
10701  **/
getComputeShaderBody(const _test_case & test_case)10702 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10703 {
10704 	std::stringstream result_sstream;
10705 
10706 	/* Form the body */
10707 	result_sstream << "#version 420\n"
10708 					  "#extension GL_ARB_compute_shader          : require\n"
10709 					  "\n"
10710 					  "layout(local_size_x = 1) in;\n"
10711 					  "\n"
10712 					  "void main()\n"
10713 					  "{\n"
10714 				   << getGeneralBody(test_case) << "}\n";
10715 
10716 	/* Return the body */
10717 	return result_sstream.str();
10718 }
10719 
10720 /** Retrieves body of a fragment shader that should be used for the purpose of
10721  *  user-specified test case.
10722  *
10723  *  @param test_case Test case descriptor to use.
10724  *
10725  *  @return Requested string.
10726  **/
getFragmentShaderBody(const _test_case & test_case)10727 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10728 {
10729 	std::stringstream result_sstream;
10730 
10731 	/* Form the body */
10732 	result_sstream << "#version 420\n"
10733 					  "\n"
10734 					  "void main()\n"
10735 					  "{\n"
10736 				   << getGeneralBody(test_case) << "}\n"
10737 												   "\n";
10738 
10739 	/* Return the body */
10740 	return result_sstream.str();
10741 }
10742 
10743 /** Returns a GLSL line that defines and initializes a variable as described by
10744  *  user-specified test case descriptor.
10745  *
10746  *  @param test_case Test case descriptor to use for the query.
10747  *
10748  *  @return As per description
10749  **/
getGeneralBody(const _test_case & test_case)10750 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10751 {
10752 	std::stringstream result_sstream;
10753 
10754 	/* Form the body */
10755 	std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10756 
10757 	result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10758 
10759 	for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10760 		 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10761 	{
10762 		const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10763 		std::string		   argument_variable_type_string   = Utils::getVariableTypeString(argument_variable_type);
10764 		const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10765 
10766 		if (argument_list_iterator != test_case.argument_list.begin())
10767 		{
10768 			result_sstream << ", ";
10769 		}
10770 
10771 		result_sstream << argument_variable_type_string << "(";
10772 
10773 		for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10774 		{
10775 			result_sstream << (double)(n_component + 1);
10776 
10777 			if (n_component != (argument_n_components - 1))
10778 			{
10779 				result_sstream << ", ";
10780 			}
10781 		} /* for (all argument components) */
10782 
10783 		result_sstream << ")";
10784 	} /* for (all arguments) */
10785 
10786 	result_sstream << ");\n";
10787 
10788 	return result_sstream.str();
10789 }
10790 
10791 /** Retrieves body of a geometry shader that should be used for the purpose of
10792  *  user-specified test case.
10793  *
10794  *  @param test_case Test case descriptor to use.
10795  *
10796  *  @return Requested string.
10797  **/
getGeometryShaderBody(const _test_case & test_case)10798 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10799 {
10800 	std::stringstream result_sstream;
10801 
10802 	/* Form the body */
10803 	result_sstream << "#version 420\n"
10804 					  "\n"
10805 					  "layout(points)                 in;\n"
10806 					  "layout(max_vertices=1, points) out;\n"
10807 					  "\n"
10808 					  "void main()\n"
10809 					  "{\n"
10810 				   << getGeneralBody(test_case) << "}\n"
10811 												   "\n";
10812 
10813 	/* We're done! */
10814 	return result_sstream.str();
10815 }
10816 
10817 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10818  *  user-specified test case.
10819  *
10820  *  @param test_case Test case descriptor to use.
10821  *
10822  *  @return Requested string.
10823  **/
getTessellationControlShaderBody(const _test_case & test_case)10824 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10825 {
10826 	std::stringstream result_sstream;
10827 
10828 	/* Form the body */
10829 	result_sstream << "#version 420\n"
10830 					  "\n"
10831 					  "layout(vertices=4) out;\n"
10832 					  "\n"
10833 					  "void main()\n"
10834 					  "{\n"
10835 				   << getGeneralBody(test_case) << "}\n"
10836 												   "\n";
10837 
10838 	/* Return the body */
10839 	return result_sstream.str();
10840 }
10841 
10842 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10843  *  user-specified test case.
10844  *
10845  *  @param test_case Test case descriptor to use.
10846  *
10847  *  @return Requested string.
10848  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10849 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10850 {
10851 	std::stringstream result_sstream;
10852 
10853 	/* Form the body */
10854 	result_sstream << "#version 420\n"
10855 					  "\n"
10856 					  "layout(isolines) in;\n"
10857 					  "\n"
10858 					  "void main()\n"
10859 					  "{\n"
10860 				   << getGeneralBody(test_case) << "}\n"
10861 												   "\n";
10862 
10863 	/* Return the body */
10864 	return result_sstream.str();
10865 }
10866 
10867 /** Retrieves body of a vertex shader that should be used for the purpose of
10868  *  user-specified test case.
10869  *
10870  *  @param test_case Test case descriptor to use.
10871  *
10872  *  @return Requested string.
10873  **/
getVertexShaderBody(const _test_case & test_case)10874 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10875 {
10876 	std::stringstream result_sstream;
10877 
10878 	/* Form the body */
10879 	result_sstream << "#version 420\n"
10880 					  "\n"
10881 					  "void main()\n"
10882 					  "{\n"
10883 				   << getGeneralBody(test_case) << "}\n"
10884 												   "\n";
10885 
10886 	return result_sstream.str();
10887 }
10888 
10889 /** Initializes shader objects required to run the test. */
initTest()10890 void GPUShaderFP64Test8::initTest()
10891 {
10892 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10893 
10894 	/* Generate shader objects */
10895 
10896 	/* Compute shader support and GL 4.2 required */
10897 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10898 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10899 	{
10900 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10901 	}
10902 
10903 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10904 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10905 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10906 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10907 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10908 
10909 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10910 }
10911 
10912 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10913  *
10914  *  @param test_case Test case descriptor to generate the shader bodies for.
10915  **/
initIteration(_test_case & test_case)10916 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10917 {
10918 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10919 
10920 	test_case.cs_shader_body = getComputeShaderBody(test_case);
10921 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
10922 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
10923 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10924 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10925 	test_case.vs_shader_body = getVertexShaderBody(test_case);
10926 
10927 	/* Assign the bodies to relevant shaders */
10928 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10929 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10930 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10931 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10932 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10933 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10934 
10935 	/* m_cs_id is initialized only if compute_shader is supported */
10936 	if (0 != m_cs_id)
10937 	{
10938 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10939 	}
10940 
10941 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10942 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10943 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10944 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10945 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10946 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10947 }
10948 
10949 /** Executes test iteration.
10950  *
10951  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10952  */
iterate()10953 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10954 {
10955 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10956 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10957 	{
10958 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10959 	}
10960 
10961 	/* Initialize GL objects needed to run the tests */
10962 	initTest();
10963 
10964 	/* Build iteration array to run the tests in an automated manner */
10965 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
10966 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10967 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10968 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
10969 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10970 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
10971 													 Utils::VARIABLE_TYPE_DVEC4 };
10972 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10973 
10974 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10975 	{
10976 		const Utils::_variable_type variable_type = variable_types[n_variable_type];
10977 
10978 		/* Construct a set of argument lists valid for the variable type considered */
10979 		_argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10980 
10981 		for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10982 			 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10983 		{
10984 			/* Constructor thwe test case descriptor */
10985 			_test_case test_case;
10986 
10987 			test_case.argument_list = *argument_list_iterator;
10988 			test_case.type			= variable_type;
10989 
10990 			/* Initialize a program object we will use to perform the casting */
10991 			initIteration(test_case);
10992 
10993 			/* See if the shader compiles. */
10994 			m_has_test_passed &= executeIteration(test_case);
10995 		} /* for (all argument lists) */
10996 	}	 /* for (all variable types) */
10997 
10998 	/* We're done */
10999 	if (m_has_test_passed)
11000 	{
11001 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11002 	}
11003 	else
11004 	{
11005 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11006 	}
11007 
11008 	return STOP;
11009 }
11010 
11011 /** Constructor.
11012  *
11013  *  @param context Rendering context.
11014  *
11015  **/
GPUShaderFP64Test9(deqp::Context & context)11016 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11017 	: TestCase(context, "operators", "Verifies that general and relational operators work "
11018 									 "correctly when used against double-precision floating-"
11019 									 "point types.")
11020 	, m_has_test_passed(true)
11021 	, m_po_id(0)
11022 	, m_xfb_bo_id(0)
11023 	, m_vao_id(0)
11024 	, m_vs_id(0)
11025 {
11026 	/* Left blank intentionally */
11027 }
11028 
11029 /** Deinitializes all ES objects that may have been created during
11030  *  test execution.
11031  **/
deinit()11032 void GPUShaderFP64Test9::deinit()
11033 {
11034 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11035 
11036 	if (m_po_id != 0)
11037 	{
11038 		gl.deleteProgram(m_po_id);
11039 
11040 		m_po_id = 0;
11041 	}
11042 
11043 	if (m_xfb_bo_id != 0)
11044 	{
11045 		gl.deleteBuffers(1, &m_xfb_bo_id);
11046 
11047 		m_xfb_bo_id = 0;
11048 	}
11049 
11050 	if (m_vao_id != 0)
11051 	{
11052 		gl.deleteVertexArrays(1, &m_vao_id);
11053 
11054 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11055 	}
11056 
11057 	if (m_vs_id != 0)
11058 	{
11059 		gl.deleteShader(m_vs_id);
11060 
11061 		m_vs_id = 0;
11062 	}
11063 }
11064 
11065 /** Executes a single test iteration using user-specified test case properties.
11066  *
11067  *  @param test_case Test case descriptor.
11068  *
11069  *  @return true if the pass was successful, false if the test should fail.
11070  **/
executeTestIteration(const _test_case & test_case)11071 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11072 {
11073 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
11074 	bool				  result = true;
11075 
11076 	/* Activate the test program object */
11077 	gl.useProgram(m_po_id);
11078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11079 
11080 	/* Draw a single point with XFB enabled */
11081 	gl.beginTransformFeedback(GL_POINTS);
11082 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11083 	{
11084 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11085 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11086 	}
11087 	gl.endTransformFeedback();
11088 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11089 
11090 	/* Map the XFB BO into process space */
11091 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11092 
11093 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11094 
11095 	result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11096 
11097 	/* Unmap the BO */
11098 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11099 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11100 
11101 	return result;
11102 }
11103 
11104 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11105  *  under user-specified location.
11106  *
11107  *  @param matrix_a_type  Type of the l-side matrix.
11108  *  @param matrix_a_data  Row-ordered data of l-side matrix.
11109  *  @param matrix_b_type  Type of the r-side matrix.
11110  *  @param matrix_b_data  Row-ordered data of r-side matrix.
11111  *  @param out_result_ptr Deref to be used to store the multiplication result.
11112  **/
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)11113 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11114 													   const std::vector<double>&   matrix_a_data,
11115 													   const Utils::_variable_type& matrix_b_type,
11116 													   const std::vector<double>& matrix_b_data, double* out_result_ptr)
11117 {
11118 	(void)matrix_b_type;
11119 	using namespace tcu;
11120 	/* To keep the code maintainable, we only consider cases relevant for this test */
11121 	switch (matrix_a_type)
11122 	{
11123 	case Utils::VARIABLE_TYPE_DMAT2:
11124 	{
11125 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11126 
11127 		tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11128 		tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11129 		tcu::Matrix2d result;
11130 
11131 		matrix_a = transpose(matrix_a);
11132 		matrix_b = transpose(matrix_b);
11133 		result   = matrix_a * matrix_b;
11134 
11135 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11136 		break;
11137 	}
11138 
11139 	case Utils::VARIABLE_TYPE_DMAT2X3:
11140 	{
11141 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11142 
11143 		tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11144 		tcu::Matrix<double, 3, 2> matrix_a_transposed;
11145 		tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11146 		tcu::Matrix<double, 2, 3> matrix_b_transposed;
11147 		tcu::Matrix<double, 3, 3> result;
11148 
11149 		matrix_a_transposed = transpose(matrix_a);
11150 		matrix_b_transposed = transpose(matrix_b);
11151 		result				= matrix_a_transposed * matrix_b_transposed;
11152 
11153 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11154 		break;
11155 	}
11156 
11157 	case Utils::VARIABLE_TYPE_DMAT2X4:
11158 	{
11159 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11160 
11161 		tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11162 		tcu::Matrix<double, 4, 2> matrix_a_transposed;
11163 		tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11164 		tcu::Matrix<double, 2, 4> matrix_b_transposed;
11165 		tcu::Matrix<double, 4, 4> result;
11166 
11167 		matrix_a_transposed = transpose(matrix_a);
11168 		matrix_b_transposed = transpose(matrix_b);
11169 		result				= matrix_a_transposed * matrix_b_transposed;
11170 
11171 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11172 		break;
11173 	}
11174 
11175 	case Utils::VARIABLE_TYPE_DMAT3:
11176 	{
11177 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11178 
11179 		tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11180 		tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11181 		tcu::Matrix<double, 3, 3> result;
11182 
11183 		matrix_a = transpose(matrix_a);
11184 		matrix_b = transpose(matrix_b);
11185 		result   = matrix_a * matrix_b;
11186 
11187 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11188 		break;
11189 	}
11190 
11191 	case Utils::VARIABLE_TYPE_DMAT3X2:
11192 	{
11193 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11194 
11195 		tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11196 		tcu::Matrix<double, 2, 3> matrix_a_transposed;
11197 		tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11198 		tcu::Matrix<double, 3, 2> matrix_b_transposed;
11199 		tcu::Matrix<double, 2, 2> result;
11200 
11201 		matrix_a_transposed = transpose(matrix_a);
11202 		matrix_b_transposed = transpose(matrix_b);
11203 		result				= matrix_a_transposed * matrix_b_transposed;
11204 
11205 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11206 		break;
11207 	}
11208 
11209 	case Utils::VARIABLE_TYPE_DMAT3X4:
11210 	{
11211 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11212 
11213 		tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11214 		tcu::Matrix<double, 4, 3> matrix_a_transposed;
11215 		tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11216 		tcu::Matrix<double, 3, 4> matrix_b_transposed;
11217 		tcu::Matrix<double, 4, 4> result;
11218 
11219 		matrix_a_transposed = transpose(matrix_a);
11220 		matrix_b_transposed = transpose(matrix_b);
11221 		result				= matrix_a_transposed * matrix_b_transposed;
11222 
11223 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11224 		break;
11225 	}
11226 
11227 	case Utils::VARIABLE_TYPE_DMAT4:
11228 	{
11229 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11230 
11231 		tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11232 		tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11233 		tcu::Matrix<double, 4, 4> result;
11234 
11235 		matrix_a = transpose(matrix_a);
11236 		matrix_b = transpose(matrix_b);
11237 		result   = matrix_a * matrix_b;
11238 
11239 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11240 		break;
11241 	}
11242 
11243 	case Utils::VARIABLE_TYPE_DMAT4X2:
11244 	{
11245 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11246 
11247 		tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11248 		tcu::Matrix<double, 2, 4> matrix_a_transposed;
11249 		tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11250 		tcu::Matrix<double, 4, 2> matrix_b_transposed;
11251 		tcu::Matrix<double, 2, 2> result;
11252 
11253 		matrix_a_transposed = transpose(matrix_a);
11254 		matrix_b_transposed = transpose(matrix_b);
11255 		result				= matrix_a_transposed * matrix_b_transposed;
11256 
11257 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11258 		break;
11259 	}
11260 
11261 	case Utils::VARIABLE_TYPE_DMAT4X3:
11262 	{
11263 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11264 
11265 		tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11266 		tcu::Matrix<double, 3, 4> matrix_a_transposed;
11267 		tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11268 		tcu::Matrix<double, 4, 3> matrix_b_transposed;
11269 		tcu::Matrix<double, 3, 3> result;
11270 
11271 		matrix_a_transposed = transpose(matrix_a);
11272 		matrix_b_transposed = transpose(matrix_b);
11273 		result				= matrix_a_transposed * matrix_b_transposed;
11274 
11275 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11276 		break;
11277 	}
11278 
11279 	default:
11280 	{
11281 		TCU_FAIL("Unrecognized matrix A type");
11282 	}
11283 	} /* switch (matrix_a_type) */
11284 }
11285 
11286 /** Returns GLSL operator representation of the user-specified operation.
11287  *
11288  *  @param operation_type Internal operation type to retrieve the operator for.
11289  *
11290  *  @return As per description.
11291  **/
getOperatorForOperationType(const _operation_type & operation_type)11292 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11293 {
11294 	const char* result = NULL;
11295 
11296 	switch (operation_type)
11297 	{
11298 	case OPERATION_TYPE_ADDITION:
11299 		result = "+";
11300 		break;
11301 	case OPERATION_TYPE_DIVISION:
11302 		result = "/";
11303 		break;
11304 	case OPERATION_TYPE_MULTIPLICATION:
11305 		result = "*";
11306 		break;
11307 	case OPERATION_TYPE_SUBTRACTION:
11308 		result = "-";
11309 		break;
11310 
11311 	case OPERATION_TYPE_PRE_DECREMENTATION:
11312 	case OPERATION_TYPE_POST_DECREMENTATION:
11313 	{
11314 		result = "--";
11315 
11316 		break;
11317 	}
11318 
11319 	case OPERATION_TYPE_PRE_INCREMENTATION:
11320 	case OPERATION_TYPE_POST_INCREMENTATION:
11321 	{
11322 		result = "++";
11323 
11324 		break;
11325 	}
11326 
11327 	default:
11328 	{
11329 		TCU_FAIL("Unrecognized operation type");
11330 	}
11331 	} /* switch(operation_type) */
11332 
11333 	return result;
11334 }
11335 
11336 /** Returns a string representing user-specified operation type.
11337  *
11338  *  @param operation_type Operation type to return the literal for.
11339  *
11340  *  @return Requested string.
11341  **/
getOperationTypeString(const _operation_type & operation_type)11342 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11343 {
11344 	std::string result = "[?]";
11345 
11346 	switch (operation_type)
11347 	{
11348 	case OPERATION_TYPE_ADDITION:
11349 		result = "addition";
11350 		break;
11351 	case OPERATION_TYPE_DIVISION:
11352 		result = "division";
11353 		break;
11354 	case OPERATION_TYPE_MULTIPLICATION:
11355 		result = "multiplication";
11356 		break;
11357 	case OPERATION_TYPE_SUBTRACTION:
11358 		result = "subtraction";
11359 		break;
11360 	case OPERATION_TYPE_PRE_DECREMENTATION:
11361 		result = "pre-decrementation";
11362 		break;
11363 	case OPERATION_TYPE_PRE_INCREMENTATION:
11364 		result = "pre-incrementation";
11365 		break;
11366 	case OPERATION_TYPE_POST_DECREMENTATION:
11367 		result = "post-decrementation";
11368 		break;
11369 	case OPERATION_TYPE_POST_INCREMENTATION:
11370 		result = "post-incrementation";
11371 		break;
11372 
11373 	default:
11374 	{
11375 		TCU_FAIL("Unrecognized operation type");
11376 	}
11377 	}
11378 
11379 	return result;
11380 }
11381 
11382 /** Returns body of a vertex shader that should be used for user-specified test case
11383  *  descriptor.
11384  *
11385  *  @param test_case Test case descriptor.
11386  *
11387  *  @return Requested GLSL shader body.
11388  **/
getVertexShaderBody(_test_case & test_case)11389 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11390 {
11391 	std::stringstream  result_sstream;
11392 	std::string		   result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11393 	std::string		   variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11394 	std::string		   variable_type_string	= Utils::getVariableTypeString(test_case.variable_type);
11395 	const unsigned int n_variable_components   = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11396 
11397 	/* If we are to multiply matrices, we will need to use a different type
11398 	 * for the result variable if either of the matrices is not square.
11399 	 */
11400 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11401 		Utils::isMatrixVariableType(test_case.variable_type))
11402 	{
11403 		Utils::_variable_type result_variable_type;
11404 		Utils::_variable_type transposed_matrix_variable_type =
11405 			Utils::getTransposedMatrixVariableType(test_case.variable_type);
11406 
11407 		result_variable_type =
11408 			Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11409 		result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11410 
11411 		test_case.result_variable_type = result_variable_type;
11412 	}
11413 
11414 	/* Form the pre-amble */
11415 	result_sstream << "#version 400\n"
11416 					  "\n"
11417 
11418 					  /* Add output variables */
11419 					  "out "
11420 				   << result_variable_type_string << " result;\n"
11421 													 "out ivec2 result_lt;\n"
11422 													 "out ivec2 result_lte;\n"
11423 													 "out ivec2 result_gt;\n"
11424 													 "out ivec2 result_gte;\n"
11425 													 "void main()\n"
11426 													 "{\n";
11427 
11428 	/* Form reference values */
11429 	result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11430 
11431 	for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11432 	{
11433 		result_sstream << (n_variable_component + 1);
11434 
11435 		if (n_variable_component != (n_variable_components - 1))
11436 		{
11437 			result_sstream << ", ";
11438 		}
11439 	} /* for (all variable components) */
11440 
11441 	result_sstream << ");\n";
11442 
11443 	for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11444 		 ++n_ref2_case)
11445 	{
11446 		Utils::_variable_type compatible_variable_type = test_case.variable_type;
11447 
11448 		if (Utils::isMatrixVariableType(compatible_variable_type) &&
11449 			test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11450 		{
11451 			compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11452 		}
11453 
11454 		std::string ref2_variable_type_fp_string =
11455 			Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11456 		std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11457 		std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11458 		std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11459 
11460 		result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11461 
11462 		for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11463 			 ++n_variable_component)
11464 		{
11465 			result_sstream << (n_variable_components - (n_variable_component + 1));
11466 
11467 			if (n_variable_component != (n_variable_components - 1))
11468 			{
11469 				result_sstream << ", ";
11470 			}
11471 		} /* for (all variable components) */
11472 
11473 		result_sstream << ");\n";
11474 	} /* for (both reference2 declarations) */
11475 
11476 	/* Add actual body */
11477 	result_sstream << "\n"
11478 					  "result = ";
11479 
11480 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11481 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11482 	{
11483 		result_sstream << getOperatorForOperationType(test_case.operation_type);
11484 	}
11485 
11486 	result_sstream << "reference1 ";
11487 
11488 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11489 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11490 		test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11491 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11492 	{
11493 		if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11494 			test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11495 		{
11496 			result_sstream << getOperatorForOperationType(test_case.operation_type);
11497 		}
11498 	}
11499 	else
11500 	{
11501 		result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11502 	}
11503 
11504 	result_sstream << ";\n";
11505 
11506 	if (Utils::isScalarVariableType(test_case.variable_type))
11507 	{
11508 		result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
11509 						  "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
11510 						  "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
11511 						  "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11512 						  "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
11513 						  "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
11514 						  "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
11515 						  "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11516 	}
11517 	else
11518 	{
11519 		result_sstream << "result_lt [0] = 1;\n"
11520 						  "result_lt [1] = 1;\n"
11521 						  "result_lte[0] = 1;\n"
11522 						  "result_lte[1] = 1;\n"
11523 						  "result_gt [0] = 1;\n"
11524 						  "result_gt [1] = 1;\n"
11525 						  "result_gte[0] = 1;\n"
11526 						  "result_gte[1] = 1;\n";
11527 	}
11528 
11529 	result_sstream << "}\n";
11530 
11531 	/* All done */
11532 	return result_sstream.str();
11533 }
11534 
11535 /** Initializes all GL objects required to run the test.
11536  *
11537  *  This function can throw a TestError exception if the implementation misbehaves.
11538  */
initTest()11539 void GPUShaderFP64Test9::initTest()
11540 {
11541 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11542 
11543 	/* Create program & vertex shader objects */
11544 	m_po_id = gl.createProgram();
11545 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11546 
11547 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11548 
11549 	/* Attach the shader to the program */
11550 	gl.attachShader(m_po_id, m_vs_id);
11551 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11552 
11553 	/* Set up a buffer object */
11554 	gl.genBuffers(1, &m_xfb_bo_id);
11555 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11556 
11557 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11558 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11559 
11560 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11561 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11562 
11563 	/* Set up a vertex array object */
11564 	gl.genVertexArrays(1, &m_vao_id);
11565 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11566 
11567 	gl.bindVertexArray(m_vao_id);
11568 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11569 }
11570 
11571 /** Initializes all GL objects required to run an iteration described by
11572  *  user-specified test case descriptor.
11573  *
11574  *  @param test_case Test case descriptor to use for the initialization.
11575  **/
initTestIteration(_test_case & test_case)11576 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11577 {
11578 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
11579 	std::string			  vs_body		  = getVertexShaderBody(test_case);
11580 	const char*			  vs_body_raw_ptr = vs_body.c_str();
11581 
11582 	/* Store the shader's body */
11583 	test_case.vs_body = vs_body;
11584 
11585 	/* Try to compile the shader */
11586 	glw::GLint compile_status = GL_FALSE;
11587 
11588 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11589 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11590 
11591 	gl.compileShader(m_vs_id);
11592 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11593 
11594 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11595 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11596 
11597 	if (compile_status != GL_TRUE)
11598 	{
11599 		TCU_FAIL("Test shader compilation failed.");
11600 	}
11601 
11602 	/* Configure XFB */
11603 	const char*		   xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11604 	const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11605 
11606 	gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11607 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11608 
11609 	/* Try to link the program */
11610 	glw::GLint link_status = GL_FALSE;
11611 
11612 	gl.linkProgram(m_po_id);
11613 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11614 
11615 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11616 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11617 
11618 	if (link_status != GL_TRUE)
11619 	{
11620 		TCU_FAIL("Test program linking failure");
11621 	}
11622 
11623 	/* Set up XFB BO data storage */
11624 	const unsigned int result_variable_size = static_cast<unsigned int>(
11625 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11626 	const unsigned int xfb_bo_size = static_cast<unsigned int>(
11627 		result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11628 
11629 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11630 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11631 }
11632 
11633 /** Executes test iteration.
11634  *
11635  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11636  */
iterate()11637 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11638 {
11639 	/* Do not execute the test if GL_ARB_texture_view is not supported */
11640 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11641 	{
11642 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11643 	}
11644 
11645 	/* Initialize all ES objects required to run all the checks */
11646 	initTest();
11647 
11648 	/* Iterate through all variable types we want to test */
11649 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
11650 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11651 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11652 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
11653 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11654 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11655 													 Utils::VARIABLE_TYPE_DVEC4 };
11656 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11657 
11658 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11659 	{
11660 		/* Iterate through all operation types we want to check */
11661 		for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11662 		{
11663 			_operation_type				 operation_type = (_operation_type)n_operation_type;
11664 			const Utils::_variable_type& variable_type  = variable_types[n_variable_type];
11665 
11666 			/* Construct test case descriptor */
11667 			_test_case test_case;
11668 
11669 			test_case.operation_type	   = operation_type;
11670 			test_case.result_variable_type = variable_type;
11671 			test_case.variable_type		   = variable_type;
11672 
11673 			/* Run the iteration */
11674 			initTestIteration(test_case);
11675 
11676 			m_has_test_passed &= executeTestIteration(test_case);
11677 		} /* for (all operation types) */
11678 	}	 /* for (all variable types) */
11679 
11680 	/* All done. */
11681 	if (m_has_test_passed)
11682 	{
11683 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11684 	}
11685 	else
11686 	{
11687 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11688 	}
11689 
11690 	return STOP;
11691 }
11692 
11693 /** Verifies data XFBed out by the draw call for user-specified test case
11694  *  descriptor.
11695  *
11696  *  @param test_case Test case descriptor
11697  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
11698  *                   Must not be NULL.
11699  *
11700  *  @return true if the data was found to be correct, false otherwise.
11701  **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11702 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11703 {
11704 	const double	   epsilon = 1e-5;
11705 	const unsigned int n_result_components =
11706 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11707 	bool		  result			  = true;
11708 	const double* xfb_data_result	 = (const double*)xfb_data;
11709 	const int*	xfb_data_result_lt  = (const int*)(xfb_data_result + n_result_components);
11710 	const int*	xfb_data_result_lte = (const int*)xfb_data_result_lt + 2;  /* cast/non-cast cases */
11711 	const int*	xfb_data_result_gt  = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11712 	const int*	xfb_data_result_gte = (const int*)xfb_data_result_gt + 2;  /* cast/non-cast cases */
11713 
11714 	/* Prepare reference values */
11715 	int					modifier;
11716 	std::vector<double> reference1;
11717 	std::vector<double> reference2;
11718 
11719 	if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11720 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11721 	{
11722 		modifier = 1;
11723 	}
11724 	else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11725 			 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11726 	{
11727 		modifier = -1;
11728 	}
11729 	else
11730 	{
11731 		modifier = 0;
11732 	}
11733 
11734 	if (Utils::isMatrixVariableType(test_case.variable_type))
11735 	{
11736 		/* Matrices may be of different sizes so we need to compute the
11737 		 * reference values separately for each matrix
11738 		 */
11739 		const Utils::_variable_type matrix_a_type = test_case.variable_type;
11740 		const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11741 		const unsigned int			n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11742 		const unsigned int			n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11743 
11744 		for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11745 		{
11746 			reference1.push_back(modifier + n_component + 1);
11747 		}
11748 
11749 		for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11750 		{
11751 			reference2.push_back(n_matrix_b_components - (n_component + 1));
11752 		}
11753 	} /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11754 	else
11755 	{
11756 		/* Generate as many components as will be expected for the result variable */
11757 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11758 		{
11759 			reference1.push_back(modifier + n_result_component + 1);
11760 			reference2.push_back(n_result_components - (n_result_component + 1));
11761 		}
11762 	}
11763 
11764 	/* Verify the result value(s) */
11765 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11766 		Utils::isMatrixVariableType(test_case.variable_type))
11767 	{
11768 		/* Matrix multiplication */
11769 		double				  expected_result_data[4 * 4];
11770 		Utils::_variable_type matrix_a_type = test_case.variable_type;
11771 		Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11772 
11773 		getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11774 
11775 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11776 		{
11777 			if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11778 			{
11779 				std::stringstream log_sstream;
11780 
11781 				log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11782 							<< Utils::getVariableTypeString(matrix_b_type)
11783 							<< " matrix multiplication was incorrect; expected:(";
11784 
11785 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11786 					 ++n_logged_component)
11787 				{
11788 					log_sstream << expected_result_data[n_logged_component];
11789 
11790 					if (n_logged_component != (n_result_components - 1))
11791 					{
11792 						log_sstream << ", ";
11793 					}
11794 				} /* for (all components to be logged) */
11795 
11796 				log_sstream << "), retrieved:(";
11797 
11798 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11799 					 ++n_logged_component)
11800 				{
11801 					log_sstream << xfb_data_result[n_logged_component];
11802 
11803 					if (n_logged_component != (n_result_components - 1))
11804 					{
11805 						log_sstream << ", ";
11806 					}
11807 				} /* for (all components to be logged) */
11808 
11809 				log_sstream << ")";
11810 
11811 				m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11812 
11813 				result = false;
11814 				break;
11815 			}
11816 		} /* for (all result components) */
11817 	}	 /* if (dealing with matrix multiplication) */
11818 	else
11819 	{
11820 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11821 		{
11822 			double expected_value = reference1[n_component];
11823 
11824 			switch (test_case.operation_type)
11825 			{
11826 			case OPERATION_TYPE_ADDITION:
11827 				expected_value += reference2[n_component];
11828 				break;
11829 			case OPERATION_TYPE_DIVISION:
11830 				expected_value /= reference2[n_component];
11831 				break;
11832 			case OPERATION_TYPE_MULTIPLICATION:
11833 				expected_value *= reference2[n_component];
11834 				break;
11835 			case OPERATION_TYPE_SUBTRACTION:
11836 				expected_value -= reference2[n_component];
11837 				break;
11838 
11839 			case OPERATION_TYPE_PRE_DECREMENTATION:
11840 			case OPERATION_TYPE_PRE_INCREMENTATION:
11841 			{
11842 				/* Modifier already applied */
11843 				break;
11844 			}
11845 
11846 			case OPERATION_TYPE_POST_DECREMENTATION:
11847 			case OPERATION_TYPE_POST_INCREMENTATION:
11848 			{
11849 				/* Need to reverse the modification for the purpose of the following check */
11850 				expected_value -= modifier;
11851 
11852 				break;
11853 			}
11854 
11855 			default:
11856 			{
11857 				TCU_FAIL("Unrecognized operation type");
11858 			}
11859 			} /* switch (test_case.operation_type) */
11860 
11861 			if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11862 			{
11863 				std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11864 				std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11865 
11866 				m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11867 								   << variable_type_string << "]"
11868 															  " and operation type ["
11869 								   << operation_type_string << "]"
11870 															   " were found invalid."
11871 								   << tcu::TestLog::EndMessage;
11872 
11873 				result = false;
11874 				break;
11875 			} /* if (test case failed) */
11876 		}	 /* for (all components) */
11877 	}
11878 
11879 	/* Verify the comparison operation results */
11880 	if (Utils::isScalarVariableType(test_case.variable_type))
11881 	{
11882 		DE_ASSERT(n_result_components == 1);
11883 
11884 		const bool expected_result_lt[2]  = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11885 		const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11886 		const bool expected_result_gt[2]  = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11887 		const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11888 
11889 		if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11890 			(xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11891 		{
11892 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11893 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11894 
11895 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11896 														   "variable type ["
11897 							   << variable_type_string << "]"
11898 														  "and operation type ["
11899 							   << operation_type_string << "]"
11900 														   "was found invalid; expected:("
11901 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11902 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11903 							   << tcu::TestLog::EndMessage;
11904 
11905 			result = false;
11906 		}
11907 
11908 		if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11909 			(xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11910 		{
11911 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11912 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11913 
11914 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11915 														   "variable type ["
11916 							   << variable_type_string << "]"
11917 														  "and operation type ["
11918 							   << operation_type_string << "]"
11919 														   "was found invalid; expected:("
11920 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11921 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11922 							   << tcu::TestLog::EndMessage;
11923 
11924 			result = false;
11925 		}
11926 
11927 		if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11928 			(xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11929 		{
11930 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11931 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11932 
11933 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11934 														   "variable type ["
11935 							   << variable_type_string << "]"
11936 														  "and operation type ["
11937 							   << operation_type_string << "]"
11938 														   "was found invalid; expected:("
11939 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11940 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11941 							   << tcu::TestLog::EndMessage;
11942 
11943 			result = false;
11944 		}
11945 
11946 		if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11947 			(xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11948 		{
11949 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11950 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11951 
11952 			m_testCtx.getLog() << tcu::TestLog::Message
11953 							   << "Values reported for greater-than-or-equal operator used for "
11954 								  "variable type ["
11955 							   << variable_type_string << "]"
11956 														  "and operation type ["
11957 							   << operation_type_string << "]"
11958 														   "was found invalid; expected:("
11959 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11960 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11961 							   << tcu::TestLog::EndMessage;
11962 
11963 			result = false;
11964 		}
11965 	} /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11966 	else
11967 	{
11968 		if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11969 			xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11970 			xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11971 		{
11972 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11973 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11974 
11975 			m_testCtx.getLog() << tcu::TestLog::Message
11976 							   << "Invalid value was reported for matrix variable type, for which "
11977 								  " operator checks are not executed; variable type ["
11978 							   << variable_type_string << "]"
11979 														  "and operation type ["
11980 							   << operation_type_string << "]" << tcu::TestLog::EndMessage;
11981 
11982 			result = false;
11983 		}
11984 	}
11985 
11986 	return result;
11987 }
11988 
11989 namespace TypeHelpers
11990 {
11991 /** Get base type for reference types
11992  *
11993  * @tparam T type
11994  **/
11995 template <typename T>
11996 class referenceToType
11997 {
11998 public:
11999 	typedef T result;
12000 };
12001 
12002 template <typename T>
12003 class referenceToType<const T&>
12004 {
12005 public:
12006 	typedef T result;
12007 };
12008 
12009 /** Maps variable type with enumeration Utils::_variable_type
12010  *
12011  * @tparam T type
12012  **/
12013 template <typename T>
12014 class typeInfo;
12015 
12016 template <>
12017 class typeInfo<glw::GLboolean>
12018 {
12019 public:
12020 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12021 };
12022 
12023 template <>
12024 class typeInfo<glw::GLdouble>
12025 {
12026 public:
12027 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12028 };
12029 
12030 template <>
12031 class typeInfo<tcu::UVec2>
12032 {
12033 public:
12034 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12035 };
12036 
12037 template <>
12038 class typeInfo<tcu::UVec3>
12039 {
12040 public:
12041 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12042 };
12043 
12044 template <>
12045 class typeInfo<tcu::UVec4>
12046 {
12047 public:
12048 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12049 };
12050 
12051 template <>
12052 class typeInfo<tcu::DVec2>
12053 {
12054 public:
12055 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12056 };
12057 
12058 template <>
12059 class typeInfo<tcu::DVec3>
12060 {
12061 public:
12062 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12063 };
12064 
12065 template <>
12066 class typeInfo<tcu::DVec4>
12067 {
12068 public:
12069 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12070 };
12071 
12072 template <>
12073 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12074 {
12075 public:
12076 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12077 };
12078 
12079 template <>
12080 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12081 {
12082 public:
12083 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12084 };
12085 
12086 template <>
12087 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12088 {
12089 public:
12090 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12091 };
12092 
12093 template <>
12094 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12095 {
12096 public:
12097 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12098 };
12099 
12100 template <>
12101 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12102 {
12103 public:
12104 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12105 };
12106 
12107 template <>
12108 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12109 {
12110 public:
12111 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12112 };
12113 
12114 template <>
12115 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12116 {
12117 public:
12118 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12119 };
12120 
12121 template <>
12122 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12123 {
12124 public:
12125 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12126 };
12127 
12128 template <>
12129 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12130 {
12131 public:
12132 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12133 };
12134 } /* TypeHelpers */
12135 
12136 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12137  *
12138  **/
12139 namespace Math
12140 {
12141 template <typename T>
12142 static T clamp(T x, T minVal, T maxVal);
12143 
12144 template <int Size>
12145 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12146 
12147 template <int Size>
12148 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12149 
12150 template <typename T>
12151 static T determinant(T val);
12152 
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12155 
12156 template <typename T>
12157 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12158 
12159 template <typename T>
12160 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12161 
12162 template <int Size>
12163 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12164 																glw::GLuint column, glw::GLuint row);
12165 
12166 template <int Size>
12167 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12168 											const tcu::Vector<glw::GLdouble, Size>& right);
12169 
12170 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12171 
12172 static glw::GLdouble fract(glw::GLdouble val);
12173 
12174 template <typename T>
12175 static T frexp(T val, glw::GLint& exp);
12176 
12177 template <int Size>
12178 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12179 												  const tcu::Vector<glw::GLdouble, Size>& right);
12180 
12181 template <int Size>
12182 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12183 													   const tcu::Vector<glw::GLdouble, Size>& right);
12184 
12185 template <int Size>
12186 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12187 
12188 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12189 
12190 static glw::GLuint isinf_impl(glw::GLdouble val);
12191 
12192 static glw::GLuint isnan_impl(glw::GLdouble val);
12193 
12194 template <typename T>
12195 static T ldexp(T val, glw::GLint exp);
12196 
12197 template <int Size>
12198 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12199 											   const tcu::Vector<glw::GLdouble, Size>& right);
12200 
12201 template <int Size>
12202 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12203 													const tcu::Vector<glw::GLdouble, Size>& right);
12204 
12205 template <typename T>
12206 static T max(T left, T right);
12207 
12208 template <typename T>
12209 static T min(T left, T right);
12210 
12211 template <int		 Size>
12212 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12213 								glw::GLuint row);
12214 
12215 template <typename T>
12216 static T mix(T left, T right, T weight);
12217 
12218 template <typename T>
12219 static T mod(T left, T right);
12220 
12221 template <typename T>
12222 static T modf(T val, T& integer);
12223 
12224 template <typename T>
12225 static T multiply(T left, T right);
12226 
12227 template <int Size>
12228 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12229 											   const tcu::Vector<glw::GLdouble, Size>& right);
12230 
12231 template <int Cols, int Rows>
12232 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12233 														   const tcu::Vector<glw::GLdouble, Cols>& right);
12234 
12235 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12236 
12237 template <typename T>
12238 static T round(T t);
12239 
12240 template <typename T>
12241 static T roundEven(T t);
12242 
12243 template <typename T>
12244 static T sign(T t);
12245 
12246 template <typename T>
12247 static T smoothStep(T e0, T e1, T val);
12248 
12249 template <typename T>
12250 static T step(T edge, T val);
12251 
12252 template <typename T, int Rows, int Cols>
12253 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12254 
12255 template <typename T>
12256 static T trunc(T t);
12257 
12258 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12259 
12260 template <typename T>
clamp(T x,T minVal,T maxVal)12261 static T clamp(T x, T minVal, T maxVal)
12262 {
12263 	return min(max(x, minVal), maxVal);
12264 }
12265 
12266 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12267 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12268 {
12269 	tcu::Matrix<glw::GLdouble, Size, Size> result;
12270 
12271 	for (glw::GLuint c = 0; c < Size; ++c)
12272 	{
12273 		for (glw::GLuint r = 0; r < Size; ++r)
12274 		{
12275 			const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12276 
12277 			result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12278 		}
12279 	}
12280 
12281 	return result;
12282 }
12283 
12284 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12285 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12286 {
12287 	tcu::Vector<glw::GLuint, Size> result;
12288 
12289 	for (glw::GLint i = 0; i < Size; ++i)
12290 	{
12291 		if (GL_FALSE != src[i])
12292 		{
12293 			result[i] = 1;
12294 		}
12295 		else
12296 		{
12297 			result[i] = 0;
12298 		}
12299 	}
12300 
12301 	return result;
12302 }
12303 
12304 template <typename T>
det2(T _00,T _10,T _01,T _11)12305 static T det2(T _00, T _10, T _01, T _11)
12306 {
12307 	return _00 * _11 - _01 * _10;
12308 }
12309 
12310 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12311 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12312 {
12313 	return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12314 }
12315 
12316 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)12317 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,
12318 			  T _33)
12319 {
12320 	return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12321 		   _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12322 		   _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12323 		   _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12324 }
12325 
12326 template <typename T>
determinant(T val)12327 static T determinant(T val)
12328 {
12329 	return val;
12330 }
12331 
12332 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12333 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12334 {
12335 	return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12336 }
12337 
12338 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12339 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12340 {
12341 	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));
12342 }
12343 
12344 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12345 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12346 {
12347 	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),
12348 				mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12349 }
12350 
12351 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12352 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12353 																glw::GLuint column, glw::GLuint row)
12354 {
12355 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12356 
12357 	for (glw::GLuint c = 0; c < Size; ++c)
12358 	{
12359 		/* Skip eliminated column */
12360 		if (column == c)
12361 		{
12362 			continue;
12363 		}
12364 
12365 		for (glw::GLuint r = 0; r < Size; ++r)
12366 		{
12367 			/* Skip eliminated row */
12368 			if (row == r)
12369 			{
12370 				continue;
12371 			}
12372 
12373 			const glw::GLint r_offset = (r > row) ? -1 : 0;
12374 			const glw::GLint c_offset = (c > column) ? -1 : 0;
12375 
12376 			result(r + r_offset, c + c_offset) = matrix(r, c);
12377 		}
12378 	}
12379 
12380 	return result;
12381 }
12382 
12383 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12384 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12385 											const tcu::Vector<glw::GLdouble, Size>& right)
12386 {
12387 	return convertBvecToUvec(tcu::equal(left, right));
12388 }
12389 
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12390 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12391 {
12392 	return a * b + c;
12393 }
12394 
fract(glw::GLdouble val)12395 static glw::GLdouble fract(glw::GLdouble val)
12396 {
12397 	return val - floor(val);
12398 }
12399 
12400 template <typename T>
frexp(T val,glw::GLint & exp)12401 static T frexp(T val, glw::GLint& exp)
12402 {
12403 	return ::frexp(val, &exp);
12404 }
12405 
12406 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12407 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12408 												  const tcu::Vector<glw::GLdouble, Size>& right)
12409 {
12410 	return convertBvecToUvec(tcu::greaterThan(left, right));
12411 }
12412 
12413 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12415 													   const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12418 }
12419 
12420 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12421 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12422 {
12423 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
12424 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12425 	const glw::GLdouble det		= determinant(matrix);
12426 	const glw::GLdouble inv_det = 1.0 / det;
12427 
12428 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12429 
12430 	return result;
12431 }
12432 
inverseSqrt(glw::GLdouble val)12433 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12434 {
12435 	const glw::GLdouble root = sqrt(val);
12436 
12437 	return (1.0 / root);
12438 }
12439 
isinf_impl(glw::GLdouble val)12440 static glw::GLuint isinf_impl(glw::GLdouble val)
12441 {
12442 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12443 
12444 	return ((infinity == val) || (-infinity == val));
12445 }
12446 
isnan_impl(glw::GLdouble val)12447 static glw::GLuint isnan_impl(glw::GLdouble val)
12448 {
12449 	return val != val;
12450 }
12451 
12452 template <typename T>
ldexp(T val,glw::GLint exp)12453 static T ldexp(T val, glw::GLint exp)
12454 {
12455 	return ::ldexp(val, exp);
12456 }
12457 
12458 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12459 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12460 											   const tcu::Vector<glw::GLdouble, Size>& right)
12461 {
12462 	return convertBvecToUvec(tcu::lessThan(left, right));
12463 }
12464 
12465 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12466 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12467 													const tcu::Vector<glw::GLdouble, Size>& right)
12468 {
12469 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
12470 }
12471 
12472 template <typename T>
max(T left,T right)12473 static T max(T left, T right)
12474 {
12475 	return (left >= right) ? left : right;
12476 }
12477 
12478 template <typename T>
min(T left,T right)12479 static T min(T left, T right)
12480 {
12481 	return (left <= right) ? left : right;
12482 }
12483 
12484 template <int		 Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12485 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12486 								glw::GLuint row)
12487 {
12488 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12489 
12490 	return determinant(eliminated);
12491 }
12492 
12493 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12494 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12495 {
12496 	const glw::GLuint r = (0 == row) ? 1 : 0;
12497 	const glw::GLuint c = (0 == column) ? 1 : 0;
12498 
12499 	return matrix(r, c);
12500 }
12501 
12502 template <typename T>
mix(T left,T right,T weight)12503 static T mix(T left, T right, T weight)
12504 {
12505 	return left * (1 - weight) + right * (weight);
12506 }
12507 
12508 template <typename T>
mod(T left,T right)12509 static T mod(T left, T right)
12510 {
12511 	const T div_res = left / right;
12512 	const T floored = floor(div_res);
12513 
12514 	return left - right * floored;
12515 }
12516 
12517 template <typename T>
modf(T val,T & integer)12518 static T modf(T val, T& integer)
12519 {
12520 	return ::modf(val, &integer);
12521 }
12522 
12523 template <typename T>
multiply(T left,T right)12524 static T multiply(T left, T right)
12525 {
12526 	T result = left * right;
12527 
12528 	return result;
12529 }
12530 
12531 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12532 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12533 											   const tcu::Vector<glw::GLdouble, Size>& right)
12534 {
12535 	return convertBvecToUvec(tcu::notEqual(left, right));
12536 }
12537 
12538 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12539 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12540 														   const tcu::Vector<glw::GLdouble, Cols>& right)
12541 {
12542 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
12543 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
12544 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12545 
12546 	for (glw::GLuint i = 0; i < Rows; ++i)
12547 	{
12548 		left_mat(i, 0) = left[i];
12549 	}
12550 
12551 	for (glw::GLuint i = 0; i < Cols; ++i)
12552 	{
12553 		right_mat(0, i) = right[i];
12554 	}
12555 
12556 	result = left_mat * right_mat;
12557 
12558 	return result;
12559 }
12560 
packDouble2x32(const tcu::UVec2 & in)12561 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12562 {
12563 	const glw::GLuint buffer[2] = { in[0], in[1] };
12564 	glw::GLdouble	 result;
12565 	memcpy(&result, buffer, sizeof(result));
12566 	return result;
12567 }
12568 
12569 template <typename T>
round(T t)12570 static T round(T t)
12571 {
12572 	T frac = fract(t);
12573 	T res  = t - frac;
12574 
12575 	if (((T)0.5) < frac)
12576 	{
12577 		res += ((T)1.0);
12578 	}
12579 
12580 	return res;
12581 }
12582 
12583 template <typename T>
roundEven(T t)12584 static T roundEven(T t)
12585 {
12586 	T frac = fract(t);
12587 	T res  = t - frac;
12588 
12589 	if (((T)0.5) < frac)
12590 	{
12591 		res += ((T)1.0);
12592 	}
12593 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12594 	{
12595 		res += ((T)1.0);
12596 	}
12597 
12598 	return res;
12599 }
12600 
12601 template <typename T>
sign(T t)12602 static T sign(T t)
12603 {
12604 	if (0 > t)
12605 	{
12606 		return -1;
12607 	}
12608 	else if (0 == t)
12609 	{
12610 		return 0;
12611 	}
12612 	else
12613 	{
12614 		return 1;
12615 	}
12616 }
12617 
12618 template <typename T>
smoothStep(T e0,T e1,T val)12619 static T smoothStep(T e0, T e1, T val)
12620 {
12621 	if (e0 >= val)
12622 	{
12623 		return 0;
12624 	}
12625 
12626 	if (e1 <= val)
12627 	{
12628 		return 1;
12629 	}
12630 
12631 	T temp = (val - e0) / (e1 - e0);
12632 
12633 	T result = temp * temp * (3 - 2 * temp);
12634 
12635 	return result;
12636 }
12637 
12638 template <typename T>
step(T edge,T val)12639 static T step(T edge, T val)
12640 {
12641 	if (edge > val)
12642 	{
12643 		return 0;
12644 	}
12645 	else
12646 	{
12647 		return 1;
12648 	}
12649 }
12650 
12651 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12652 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12653 {
12654 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12655 
12656 	return result;
12657 }
12658 
12659 template <typename T>
trunc(T t)12660 static T trunc(T t)
12661 {
12662 	const T abs_value	= de::abs(t);
12663 	const T result_value = floor(abs_value);
12664 
12665 	const T result = sign(t) * result_value;
12666 
12667 	return result;
12668 }
12669 
unpackDouble2x32(const glw::GLdouble & val)12670 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12671 {
12672 	glw::GLuint* ptr = (glw::GLuint*)&val;
12673 	tcu::UVec2   result(ptr[0], ptr[1]);
12674 
12675 	return result;
12676 }
12677 } /* Math */
12678 
12679 /** Enumeration of tested functions
12680  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12681  * For example "max" can be called for (dvec3, double).
12682  **/
12683 enum FunctionEnum
12684 {
12685 	FUNCTION_ABS = 0,
12686 	FUNCTION_CEIL,
12687 	FUNCTION_CLAMP,
12688 	FUNCTION_CLAMP_AGAINST_SCALAR,
12689 	FUNCTION_CROSS,
12690 	FUNCTION_DETERMINANT,
12691 	FUNCTION_DISTANCE,
12692 	FUNCTION_DOT,
12693 	FUNCTION_EQUAL,
12694 	FUNCTION_FACEFORWARD,
12695 	FUNCTION_FLOOR,
12696 	FUNCTION_FMA,
12697 	FUNCTION_FRACT,
12698 	FUNCTION_FREXP,
12699 	FUNCTION_GREATERTHAN,
12700 	FUNCTION_GREATERTHANEQUAL,
12701 	FUNCTION_INVERSE,
12702 	FUNCTION_INVERSESQRT,
12703 	FUNCTION_LDEXP,
12704 	FUNCTION_LESSTHAN,
12705 	FUNCTION_LESSTHANEQUAL,
12706 	FUNCTION_LENGTH,
12707 	FUNCTION_MATRIXCOMPMULT,
12708 	FUNCTION_MAX,
12709 	FUNCTION_MAX_AGAINST_SCALAR,
12710 	FUNCTION_MIN,
12711 	FUNCTION_MIN_AGAINST_SCALAR,
12712 	FUNCTION_MIX,
12713 	FUNCTION_MOD,
12714 	FUNCTION_MOD_AGAINST_SCALAR,
12715 	FUNCTION_MODF,
12716 	FUNCTION_NORMALIZE,
12717 	FUNCTION_NOTEQUAL,
12718 	FUNCTION_OUTERPRODUCT,
12719 	FUNCTION_PACKDOUBLE2X32,
12720 	FUNCTION_REFLECT,
12721 	FUNCTION_REFRACT,
12722 	FUNCTION_ROUND,
12723 	FUNCTION_ROUNDEVEN,
12724 	FUNCTION_SIGN,
12725 	FUNCTION_SMOOTHSTEP,
12726 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12727 	FUNCTION_SQRT,
12728 	FUNCTION_STEP,
12729 	FUNCTION_STEP_AGAINST_SCALAR,
12730 	FUNCTION_TRANSPOSE,
12731 	FUNCTION_TRUNC,
12732 	FUNCTION_UNPACKDOUBLE2X32,
12733 	FUNCTION_ISNAN,
12734 	FUNCTION_ISINF,
12735 };
12736 
12737 struct TypeDefinition
12738 {
12739 	std::string name;
12740 	glw::GLuint n_columns;
12741 	glw::GLuint n_rows;
12742 };
12743 
12744 /** Implementation of BuiltinFunctionTest test, description follows:
12745  *
12746  *  Verify double-precision support in common functions works correctly.
12747  *  All double-precision types that apply for particular cases should
12748  *  be tested for the following functions:
12749  *
12750  *  - abs();
12751  *  - ceil();
12752  *  - clamp();
12753  *  - cross();
12754  *  - determinant();
12755  *  - distance();
12756  *  - dot();
12757  *  - equal();
12758  *  - faceforward();
12759  *  - floor();
12760  *  - fma();
12761  *  - fract();
12762  *  - frexp();
12763  *  - greaterThan();
12764  *  - greaterThanEqual();
12765  *  - inverse();
12766  *  - inversesqrt();
12767  *  - ldexp();
12768  *  - lessThan();
12769  *  - lessThanEqual();
12770  *  - length();
12771  *  - matrixCompMult();
12772  *  - max();
12773  *  - min();
12774  *  - mix();
12775  *  - mod();
12776  *  - modf();
12777  *  - normalize();
12778  *  - notEqual();
12779  *  - outerProduct();
12780  *  - packDouble2x32();
12781  *  - reflect();
12782  *  - refract();
12783  *  - round();
12784  *  - roundEven();
12785  *  - sign();
12786  *  - smoothstep();
12787  *  - sqrt();
12788  *  - step();
12789  *  - transpose();
12790  *  - trunc();
12791  *  - unpackDouble2x32();
12792  *  - isnan();
12793  *  - isinf();
12794  *
12795  *  The test should work by creating a program object (for each case
12796  *  considered), to which a vertex shader should be attached. The
12797  *  shader should define input variables that should be used as
12798  *  arguments for the function in question. The result of the
12799  *  operation should then be XFBed back to the test, where the
12800  *  value should be verified.
12801  *
12802  *  Reference function implementation from pre-DEQP CTS framework
12803  *  should be ported to C for verification purposes where available.
12804  *
12805  *  The test should use 1024 different scalar/vector/matrix argument
12806  *  combinations. It should pass if all functions are determined
12807  *  to work correctly for all argument combinations used.
12808  **/
12809 class BuiltinFunctionTest : public deqp::TestCase
12810 {
12811 public:
12812 	/* Public methods */
12813 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12814 						TypeDefinition typeDefinition);
12815 
12816 	virtual void						 deinit();
12817 	virtual tcu::TestNode::IterateResult iterate();
12818 
12819 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12820 	 *
12821 	 **/
12822 	class functionObject
12823 	{
12824 	public:
12825 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12826 					   Utils::_variable_type result_type);
12827 
~functionObject()12828 		virtual ~functionObject()
12829 		{
12830 		}
12831 
12832 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12833 
12834 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
12835 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12836 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12837 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12838 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12839 		glw::GLuint getArgumentStride() const;
12840 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
12841 		FunctionEnum	   getFunctionEnum() const;
12842 		const glw::GLchar* getName() const;
12843 		glw::GLuint getResultComponents(glw::GLuint result) const;
12844 		virtual glw::GLuint getResultCount() const;
12845 		glw::GLuint getResultOffset(glw::GLuint result) const;
12846 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12847 		glw::GLuint getResultStride(glw::GLuint result) const;
12848 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12849 		glw::GLuint getResultStride() const;
12850 
12851 	protected:
12852 		const FunctionEnum			m_function_enum;
12853 		const glw::GLchar*			m_function_name;
12854 		const glw::GLvoid*			m_p_function;
12855 		const Utils::_variable_type m_res_type;
12856 	};
12857 
12858 private:
12859 	/* Private types */
12860 	/** General type enumeration
12861 	 *
12862 	 **/
12863 	enum generalType
12864 	{
12865 		SCALAR = 0,
12866 		VECTOR,
12867 		MATRIX,
12868 	};
12869 
12870 	/** Details of variable type
12871 	 *
12872 	 **/
12873 	struct typeDetails
12874 	{
12875 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12876 
12877 		generalType m_general_type;
12878 		glw::GLuint m_n_columns;
12879 		glw::GLuint m_n_rows;
12880 		glw::GLenum m_type;
12881 		std::string m_type_name;
12882 	};
12883 
12884 	/* Typedefs for gl.uniform* function pointers */
12885 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12886 																	   const glw::GLdouble*);
12887 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12888 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12889 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12890 
12891 	/* Private methods */
12892 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12893 
12894 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12895 
12896 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
12897 														 const functionObject& function_object) const;
12898 
12899 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
12900 														 const functionObject& function_object) const;
12901 
12902 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
12903 														 const functionObject& function_object) const;
12904 
12905 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
12906 														 const functionObject& function_object) const;
12907 
12908 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
12909 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12910 
12911 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12912 
12913 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12914 
12915 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12916 
12917 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12918 						   glw::GLubyte* buffer);
12919 
12920 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12921 
12922 	void prepareTestData(const functionObject& function_object);
12923 	void prepareVertexShaderCode(const functionObject& function_object);
12924 
12925 	bool test(FunctionEnum function, const typeDetails& type);
12926 
12927 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12928 
12929 	void testInit();
12930 
12931 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12932 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12933 						  const glw::GLvoid* result_src);
12934 
12935 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12936 
12937 	/* Private constants */
12938 	static const glw::GLdouble m_epsilon;
12939 	static const glw::GLuint   m_n_veritces;
12940 
12941 	/* Private fields */
12942 	glw::GLuint m_transform_feedback_buffer_id;
12943 	glw::GLuint m_vertex_array_object_id;
12944 
12945 	std::vector<glw::GLubyte> m_expected_results_data;
12946 	FunctionEnum			  m_function;
12947 	TypeDefinition			  m_typeDefinition;
12948 	std::vector<glw::GLubyte> m_argument_data;
12949 	std::string				  m_vertex_shader_code;
12950 };
12951 
12952 /* Constants used by BuiltinFunctionTest */
12953 /** Khronos Bug #14010
12954  *  Using an epsilon value for comparing floating points is error prone.
12955  *  Rather than writing a new floating point comparison function, I am
12956  *  increasing the epsilon value to allow greater orders of magnitude
12957  *  of floating point values.
12958  **/
12959 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
12960 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12961 
12962 /** Implementations of function objects required by "BuiltinFunctionTest"
12963  *
12964  **/
12965 namespace FunctionObject
12966 {
12967 /** Maps variable type with enumeration Utils::_variable_type
12968  *
12969  * @tparam T type
12970  **/
12971 template <typename T>
12972 class typeInfo
12973 {
12974 public:
12975 	static const Utils::_variable_type variable_type =
12976 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12977 };
12978 
12979 /** Place data from <in> into <buffer>
12980  *
12981  * @param buffer Buffer
12982  * @param in     Input data
12983  **/
12984 template <typename T>
12985 class pack
12986 {
12987 public:
set(glw::GLvoid * buffer,const T & in)12988 	static void set(glw::GLvoid* buffer, const T& in)
12989 	{
12990 		*(T*)buffer = in;
12991 	}
12992 };
12993 
12994 /** Place tcu::Matrix data from <in> into <buffer>
12995  *
12996  * @param buffer Buffer
12997  * @param in     Input data
12998  **/
12999 template <int Cols, int Rows>
13000 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13001 {
13002 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13003 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13004 	{
13005 		glw::GLdouble* data = (glw::GLdouble*)buffer;
13006 
13007 		for (glw::GLint column = 0; column < Cols; ++column)
13008 		{
13009 			for (glw::GLint row = 0; row < Rows; ++row)
13010 			{
13011 				glw::GLint index = column * Rows + row;
13012 
13013 				data[index] = in(row, column);
13014 			}
13015 		}
13016 	}
13017 };
13018 
13019 /** Get data of <out> from <buffer>
13020  *
13021  * @param buffer Buffer
13022  * @param out    Output data
13023  **/
13024 template <typename T>
13025 class unpack
13026 {
13027 public:
get(const glw::GLvoid * buffer,T & out)13028 	static void get(const glw::GLvoid* buffer, T& out)
13029 	{
13030 		out = *(T*)buffer;
13031 	}
13032 };
13033 
13034 /** Get tcu::Matrix data from <buffer>
13035  *
13036  * @param buffer Buffer
13037  * @param out    Output data
13038  **/
13039 template <int Cols, int Rows>
13040 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13041 {
13042 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13043 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13044 	{
13045 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
13046 
13047 		for (glw::GLint column = 0; column < Cols; ++column)
13048 		{
13049 			for (glw::GLint row = 0; row < Rows; ++row)
13050 			{
13051 				glw::GLint index = column * Rows + row;
13052 
13053 				out(row, column) = data[index];
13054 			}
13055 		}
13056 	}
13057 };
13058 
13059 /** Base of unary function classes
13060  *
13061  **/
13062 class unaryBase : public BuiltinFunctionTest::functionObject
13063 {
13064 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)13065 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13066 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13067 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13068 	{
13069 	}
13070 
getArgumentCount() const13071 	virtual glw::GLuint getArgumentCount() const
13072 	{
13073 		return 1;
13074 	}
13075 
getArgumentType(glw::GLuint) const13076 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13077 	{
13078 		return m_arg_type;
13079 	}
13080 
13081 protected:
13082 	const Utils::_variable_type m_arg_type;
13083 };
13084 
13085 /** Unary function class. It treats input argument as one variable.
13086  *
13087  * @tparam ResT Type of result
13088  * @tparam ArgT Type of argument
13089  **/
13090 template <typename ResT, typename ArgT>
13091 class unary : public unaryBase
13092 {
13093 public:
13094 	typedef ResT (*functionPointer)(const ArgT&);
13095 
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13096 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13097 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13098 					typeInfo<ArgT>::variable_type)
13099 	{
13100 	}
13101 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13102 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13103 	{
13104 		ResT result;
13105 		ArgT arg;
13106 
13107 		unpack<ArgT>::get(argument_src, arg);
13108 
13109 		functionPointer p_function = (functionPointer)m_p_function;
13110 
13111 		result = p_function(arg);
13112 
13113 		pack<ResT>::set(result_dst, result);
13114 	}
13115 };
13116 
13117 /** Unary function class. It treats input argument as separate components.
13118  *
13119  * @tparam ResT Type of result
13120  **/
13121 template <typename ResT>
13122 class unaryByComponent : public unaryBase
13123 {
13124 public:
13125 	typedef ResT (*functionPointer)(glw::GLdouble);
13126 
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13127 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13128 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13129 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13130 	{
13131 	}
13132 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13133 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13134 	{
13135 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13136 		ResT*		   p_result		= (ResT*)result_dst;
13137 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
13138 
13139 		functionPointer p_function = (functionPointer)m_p_function;
13140 
13141 		for (glw::GLuint component = 0; component < n_components; ++component)
13142 		{
13143 			p_result[component] = p_function(p_arg[component]);
13144 		}
13145 	}
13146 };
13147 
13148 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13149  *
13150  * @tparam ResT Type of result
13151  * @tparam ArgT Type of argument
13152  * @tparam OutT Type of output parameter
13153  **/
13154 template <typename ResT, typename ArgT, typename OutT>
13155 class unaryWithOutputByComponent : public unaryBase
13156 {
13157 public:
13158 	typedef ResT (*functionPointer)(ArgT, OutT&);
13159 
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)13160 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13161 							   functionPointer function_pointer, const Utils::_variable_type res_type,
13162 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13163 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13164 		, m_out_type(out_type)
13165 	{
13166 	}
13167 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13168 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13169 	{
13170 		ResT* p_result = (ResT*)result_dst;
13171 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13172 		ArgT* p_arg	= (ArgT*)argument_src;
13173 
13174 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13175 		const glw::GLuint n_components_1 = getResultComponents(1);
13176 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13177 
13178 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13179 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13180 
13181 		functionPointer p_function = (functionPointer)m_p_function;
13182 
13183 		for (glw::GLuint component = 0; component < n_components; ++component)
13184 		{
13185 			const ArgT first_arg  = p_arg[component * component_step_0];
13186 			OutT&	  second_arg = p_out[component * component_step_1];
13187 
13188 			p_result[component] = p_function(first_arg, second_arg);
13189 		}
13190 	}
13191 
getResultCount() const13192 	glw::GLuint getResultCount() const
13193 	{
13194 		return 2;
13195 	}
13196 
getResultType(glw::GLuint result) const13197 	Utils::_variable_type getResultType(glw::GLuint result) const
13198 	{
13199 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13200 
13201 		switch (result)
13202 		{
13203 		case 0:
13204 			type = m_res_type;
13205 			break;
13206 		case 1:
13207 			type = m_out_type;
13208 			break;
13209 		default:
13210 			TCU_FAIL("Not implemented");
13211 			break;
13212 		}
13213 
13214 		return type;
13215 	}
13216 
13217 protected:
13218 	const Utils::_variable_type m_out_type;
13219 };
13220 
13221 /** Base of binary function classes.
13222  *
13223  **/
13224 class binaryBase : public BuiltinFunctionTest::functionObject
13225 {
13226 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)13227 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13228 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13229 			   const Utils::_variable_type arg_2_type)
13230 		: functionObject(function_enum, function_name, function_pointer, res_type)
13231 		, m_arg_1_type(arg_1_type)
13232 		, m_arg_2_type(arg_2_type)
13233 	{
13234 	}
13235 
getArgumentCount() const13236 	virtual glw::GLuint getArgumentCount() const
13237 	{
13238 		return 2;
13239 	}
13240 
getArgumentType(glw::GLuint argument) const13241 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13242 	{
13243 		switch (argument)
13244 		{
13245 		case 0:
13246 			return m_arg_1_type;
13247 		case 1:
13248 			return m_arg_2_type;
13249 		default:
13250 			return Utils::VARIABLE_TYPE_UNKNOWN;
13251 		}
13252 	}
13253 
13254 protected:
13255 	const Utils::_variable_type m_arg_1_type;
13256 	const Utils::_variable_type m_arg_2_type;
13257 };
13258 
13259 /** Binary function class. It treats input arguments as two variables.
13260  *
13261  * @param ResT  Type of result
13262  * @param Arg1T Type of first argument
13263  * @param Arg2T Type of second argument
13264  **/
13265 template <typename ResT, typename Arg1T, typename Arg2T>
13266 class binary : public binaryBase
13267 {
13268 public:
13269 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13270 
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13271 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13272 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13273 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13274 	{
13275 	}
13276 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13277 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13278 	{
13279 		const glw::GLuint argument_1_stride = getArgumentStride(0);
13280 
13281 		functionPointer p_function = (functionPointer)m_p_function;
13282 
13283 		Arg1T arg_1;
13284 		Arg2T arg_2;
13285 		ResT  result;
13286 
13287 		unpack<Arg1T>::get(argument_src, arg_1);
13288 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13289 
13290 		result = p_function(arg_1, arg_2);
13291 
13292 		pack<ResT>::set(result_dst, result);
13293 	}
13294 };
13295 
13296 /** Binary function class. It treats input arguments as separate components.
13297  *
13298  * @param ResT  Type of result
13299  * @param Arg1T Type of first argument
13300  * @param Arg2T Type of second argument
13301  **/
13302 template <typename ResT, typename Arg1T, typename Arg2T>
13303 class binaryByComponent : public binaryBase
13304 {
13305 public:
13306 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
13307 
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)13308 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13309 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13310 					  const Utils::_variable_type arg_2_type)
13311 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13312 	{
13313 	}
13314 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13315 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13316 	{
13317 		ResT*  p_result = (ResT*)result_dst;
13318 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
13319 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13320 
13321 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13322 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13323 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13324 
13325 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13326 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13327 
13328 		functionPointer p_function = (functionPointer)m_p_function;
13329 
13330 		for (glw::GLuint component = 0; component < n_components; ++component)
13331 		{
13332 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
13333 			const Arg2T second_arg = p_arg_2[component * component_step_1];
13334 
13335 			p_result[component] = p_function(first_arg, second_arg);
13336 		}
13337 	}
13338 };
13339 
13340 /** Base of tenary function classes.
13341  *
13342  **/
13343 class tenaryBase : public BuiltinFunctionTest::functionObject
13344 {
13345 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)13346 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13347 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13348 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13349 		: functionObject(function_enum, function_name, function_pointer, res_type)
13350 		, m_arg_1_type(arg_1_type)
13351 		, m_arg_2_type(arg_2_type)
13352 		, m_arg_3_type(arg_3_type)
13353 	{
13354 	}
13355 
getArgumentCount() const13356 	virtual glw::GLuint getArgumentCount() const
13357 	{
13358 		return 3;
13359 	}
13360 
getArgumentType(glw::GLuint argument) const13361 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13362 	{
13363 		switch (argument)
13364 		{
13365 		case 0:
13366 			return m_arg_1_type;
13367 		case 1:
13368 			return m_arg_2_type;
13369 		case 2:
13370 			return m_arg_3_type;
13371 		default:
13372 			return Utils::VARIABLE_TYPE_UNKNOWN;
13373 		}
13374 	}
13375 
13376 protected:
13377 	const Utils::_variable_type m_arg_1_type;
13378 	const Utils::_variable_type m_arg_2_type;
13379 	const Utils::_variable_type m_arg_3_type;
13380 };
13381 
13382 /** Tenary function class. It treats input arguments as three variables.
13383  *
13384  * @param ResT  Type of result
13385  * @param Arg1T Type of first argument
13386  * @param Arg2T Type of second argument
13387  * @param Arg3T Type of third argument
13388  **/
13389 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13390 class tenary : public tenaryBase
13391 {
13392 public:
13393 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13394 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13395 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13396 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13397 
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13398 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13399 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13400 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13401 	{
13402 	}
13403 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13404 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13405 	{
13406 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
13407 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
13408 
13409 		functionPointer p_function = (functionPointer)m_p_function;
13410 
13411 		arg1T arg_1;
13412 		arg2T arg_2;
13413 		arg3T arg_3;
13414 		ResT  result;
13415 
13416 		unpack<arg1T>::get(argument_src, arg_1);
13417 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13418 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13419 
13420 		result = p_function(arg_1, arg_2, arg_3);
13421 
13422 		pack<ResT>::set(result_dst, result);
13423 	}
13424 };
13425 
13426 /** Tenary function class. It treats input arguments as separate components.
13427  *
13428 
13429  **/
13430 class tenaryByComponent : public tenaryBase
13431 {
13432 public:
13433 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13434 
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)13435 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13436 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13437 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13438 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13439 					 arg_3_type)
13440 	{
13441 	}
13442 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13443 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13444 	{
13445 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
13446 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
13447 
13448 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13449 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13450 		const glw::GLuint n_components_2 = getArgumentComponents(2);
13451 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13452 
13453 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13454 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13455 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13456 
13457 		functionPointer p_function = (functionPointer)m_p_function;
13458 
13459 		for (glw::GLuint component = 0; component < n_components; ++component)
13460 		{
13461 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13462 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13463 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13464 
13465 			p_result[component] = p_function(first_arg, second_arg, third_arg);
13466 		}
13467 	}
13468 };
13469 } /* FunctionObject */
13470 
13471 /** Constructor.
13472  *
13473  *  @param context Rendering context.
13474  **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13475 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13476 										 TypeDefinition typeDefinition)
13477 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13478 	, m_transform_feedback_buffer_id(0)
13479 	, m_vertex_array_object_id(0)
13480 	, m_function(function)
13481 	, m_typeDefinition(typeDefinition)
13482 {
13483 	/* Nothing to be done here */
13484 }
13485 
13486 /** Deinitializes all GL objects that may have been created during test execution.
13487  *
13488  **/
deinit()13489 void BuiltinFunctionTest::deinit()
13490 {
13491 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13492 
13493 	/* Clean buffers */
13494 	if (0 != m_transform_feedback_buffer_id)
13495 	{
13496 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13497 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13498 		m_transform_feedback_buffer_id = 0;
13499 	}
13500 
13501 	/* Clean VAO */
13502 	if (0 != m_vertex_array_object_id)
13503 	{
13504 		gl.bindVertexArray(0);
13505 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13506 		m_vertex_array_object_id = 0;
13507 	}
13508 }
13509 
13510 /** Execute test
13511  *
13512  * @return tcu::TestNode::STOP
13513  **/
iterate()13514 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13515 {
13516 	/* Check if extension is supported */
13517 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13518 	{
13519 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13520 	}
13521 
13522 	testInit();
13523 
13524 	/* Verify result */
13525 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13526 	if (test(m_function, type))
13527 	{
13528 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13529 	}
13530 	else
13531 	{
13532 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13533 	}
13534 
13535 	/* Done */
13536 	return tcu::TestNode::STOP;
13537 }
13538 
13539 /** Constructor
13540  *
13541  * @param function_enum    Function enumeration
13542  * @param function_name    Function name
13543  * @param function_pointer Pointer to routine that wiil be executed
13544  * @param result_type      Type of result
13545  **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13546 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13547 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13548 	: m_function_enum(function_enum)
13549 	, m_function_name(function_name)
13550 	, m_p_function(function_pointer)
13551 	, m_res_type(result_type)
13552 {
13553 	/* Nothing to be done here */
13554 }
13555 
13556 /** Get number of components for <argument>
13557  *
13558  * @param argument Argument ordinal, starts with 0
13559  *
13560  * @return Number of components
13561  **/
getArgumentComponents(glw::GLuint argument) const13562 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13563 {
13564 	const Utils::_variable_type type		  = getArgumentType(argument);
13565 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13566 
13567 	return n_components;
13568 }
13569 
13570 /** Get size in bytes of single component of <argument>
13571  *
13572  * @param argument Argument ordinal, starts with 0
13573  *
13574  * @return Size of component
13575  **/
getArgumentComponentSize(glw::GLuint argument) const13576 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13577 {
13578 	const Utils::_variable_type type		   = getArgumentType(argument);
13579 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13580 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13581 
13582 	return base_type_size;
13583 }
13584 
13585 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13586  *
13587  * @param argument Argument ordinal, starts with 0
13588  *
13589  * @return Offset of arguemnt's data
13590  **/
getArgumentOffset(glw::GLuint argument) const13591 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13592 {
13593 	glw::GLuint result = 0;
13594 
13595 	for (glw::GLuint i = 0; i < argument; ++i)
13596 	{
13597 		result += getArgumentStride(i);
13598 	}
13599 
13600 	return result;
13601 }
13602 
13603 /** Get stride in bytes of all arguments
13604  *
13605  * @return Stride of all arguments
13606  **/
getArgumentStride() const13607 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13608 {
13609 	const glw::GLuint n_args = getArgumentCount();
13610 	glw::GLuint		  result = 0;
13611 
13612 	for (glw::GLuint i = 0; i < n_args; ++i)
13613 	{
13614 		result += getArgumentStride(i);
13615 	}
13616 
13617 	return result;
13618 }
13619 
13620 /** Get stride in bytes of <argument>
13621  *
13622  * @param argument Argument ordinal, starts with 0
13623  *
13624  * @return Stride of argument
13625  **/
getArgumentStride(glw::GLuint argument) const13626 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13627 {
13628 	const glw::GLuint component_size = getArgumentComponentSize(argument);
13629 	const glw::GLuint n_components   = getArgumentComponents(argument);
13630 
13631 	return n_components * component_size;
13632 }
13633 
13634 /** Get function enumeration
13635  *
13636  * @return Function enumeration
13637  **/
getFunctionEnum() const13638 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13639 {
13640 	return m_function_enum;
13641 }
13642 
13643 /** Get function name
13644  *
13645  * @return Function name
13646  **/
getName() const13647 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13648 {
13649 	return m_function_name;
13650 }
13651 
13652 /** Get number of components for <result>
13653  *
13654  * @param result Result ordinal, starts with 0
13655  *
13656  * @return Number of components
13657  **/
getResultComponents(glw::GLuint result) const13658 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13659 {
13660 	const Utils::_variable_type type		  = getResultType(result);
13661 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13662 
13663 	return n_components;
13664 }
13665 
13666 /** Get number of results
13667  *
13668  * @return Number of results
13669  **/
getResultCount() const13670 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13671 {
13672 	return 1;
13673 }
13674 
13675 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13676  *
13677  * @param result Result ordinal, starts with 0
13678  *
13679  * @return Offset
13680  **/
getResultOffset(glw::GLuint result) const13681 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13682 {
13683 	glw::GLuint offset = 0;
13684 
13685 	for (glw::GLuint i = 0; i < result; ++i)
13686 	{
13687 		offset += getResultStride(i);
13688 		offset = deAlign32(offset, getBaseTypeSize(i));
13689 	}
13690 
13691 	return offset;
13692 }
13693 
13694 /** Get stride in bytes of <result>.
13695  *
13696  * @param result Result ordinal, starts with 0
13697  *
13698  * @return Stride
13699  **/
getResultStride(glw::GLuint result) const13700 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13701 {
13702 	const Utils::_variable_type type		   = getResultType(result);
13703 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
13704 
13705 	return n_components * getBaseTypeSize(result);
13706 }
13707 
13708 /** Get size in bytes of <result> base component.
13709  *
13710  * @param result Result ordinal, starts with 0
13711  *
13712  * @return Alignment
13713  **/
getBaseTypeSize(glw::GLuint result) const13714 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13715 {
13716 	const Utils::_variable_type type		   = getResultType(result);
13717 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13718 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13719 
13720 	return base_type_size;
13721 }
13722 
13723 /** Get stride in bytes of all results.
13724  *
13725  * @return Stride
13726  **/
getResultStride() const13727 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13728 {
13729 	const glw::GLuint n_results	= getResultCount();
13730 	glw::GLuint		  stride	   = 0;
13731 	glw::GLuint		  maxAlignment = 0;
13732 
13733 	for (glw::GLuint i = 0; i < n_results; ++i)
13734 	{
13735 		const glw::GLuint alignment = getBaseTypeSize(i);
13736 		stride += getResultStride(i);
13737 		stride		 = deAlign32(stride, alignment);
13738 		maxAlignment = deMaxu32(maxAlignment, alignment);
13739 	}
13740 
13741 	// The stride of all results must also be aligned,
13742 	// so results for next vertex are aligned.
13743 	return deAlign32(stride, maxAlignment);
13744 }
13745 
13746 /** Get type of <result>.
13747  *
13748  * @param result Result ordinal, starts with 0
13749  *
13750  * @return Type
13751  **/
getResultType(glw::GLuint) const13752 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13753 {
13754 	return m_res_type;
13755 }
13756 
13757 /** Constructor
13758  *
13759  * @param n_columns Number of columns
13760  * @param n_rows    Number of rows
13761  **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13762 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13763 	: m_n_columns(n_columns), m_n_rows(n_rows)
13764 {
13765 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13766 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
13767 	m_type_name				   = Utils::getVariableTypeString(type);
13768 
13769 	if (1 == m_n_columns)
13770 	{
13771 		if (1 == m_n_rows)
13772 		{
13773 			m_general_type = SCALAR;
13774 		}
13775 		else
13776 		{
13777 			m_general_type = VECTOR;
13778 		}
13779 	}
13780 	else
13781 	{
13782 		m_general_type = MATRIX;
13783 	}
13784 }
13785 
13786 /** Compare two values
13787  *
13788  * @param type  Type of values
13789  * @param left  Pointer to left value
13790  * @param right Pointer to right value
13791  *
13792  * @return true if values are equal, false otherwise
13793  **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13794 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13795 {
13796 	bool result = true;
13797 
13798 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
13799 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
13800 
13801 	switch (base_type)
13802 	{
13803 	case Utils::VARIABLE_TYPE_DOUBLE:
13804 
13805 	{
13806 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13807 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
13808 
13809 		for (glw::GLuint component = 0; component < n_components; ++component)
13810 		{
13811 			const glw::GLdouble left_value  = left_values[component];
13812 			const glw::GLdouble right_value = right_values[component];
13813 
13814 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13815 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13816 			{
13817 				result = false;
13818 				break;
13819 			}
13820 		}
13821 	}
13822 
13823 	break;
13824 
13825 	case Utils::VARIABLE_TYPE_INT:
13826 
13827 	{
13828 		const glw::GLint* left_values  = (glw::GLint*)left;
13829 		const glw::GLint* right_values = (glw::GLint*)right;
13830 
13831 		for (glw::GLuint component = 0; component < n_components; ++component)
13832 		{
13833 			const glw::GLint left_value  = left_values[component];
13834 			const glw::GLint right_value = right_values[component];
13835 
13836 			if (left_value != right_value)
13837 			{
13838 				result = false;
13839 				break;
13840 			}
13841 		}
13842 	}
13843 
13844 	break;
13845 
13846 	case Utils::VARIABLE_TYPE_UINT:
13847 
13848 	{
13849 		const glw::GLuint* left_values  = (glw::GLuint*)left;
13850 		const glw::GLuint* right_values = (glw::GLuint*)right;
13851 
13852 		for (glw::GLuint component = 0; component < n_components; ++component)
13853 		{
13854 			const glw::GLuint left_value  = left_values[component];
13855 			const glw::GLuint right_value = right_values[component];
13856 
13857 			if (left_value != right_value)
13858 			{
13859 				result = false;
13860 				break;
13861 			}
13862 		}
13863 	}
13864 
13865 	break;
13866 
13867 	default:
13868 
13869 		TCU_FAIL("Not implemented");
13870 	}
13871 
13872 	return result;
13873 }
13874 
13875 /** Create instance of function object for given function enumeration and type
13876  *
13877  * @param function Function enumeration
13878  * @param type     Type details
13879  *
13880  * @return Create object
13881  **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13882 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
13883 																			const typeDetails& type)
13884 {
13885 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13886 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13887 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13888 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13889 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13890 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13891 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13892 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13893 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13894 
13895 	const glw::GLuint			n_columns	 = type.m_n_columns;
13896 	const glw::GLuint			n_rows		  = type.m_n_rows;
13897 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13898 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13899 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
13900 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
13901 
13902 	switch (function)
13903 	{
13904 	case FUNCTION_ABS:
13905 
13906 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13907 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13908 
13909 	case FUNCTION_CEIL:
13910 
13911 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13912 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13913 
13914 	case FUNCTION_CLAMP:
13915 
13916 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13917 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
13918 													 variable_type /* arg3_type */);
13919 
13920 	case FUNCTION_CLAMP_AGAINST_SCALAR:
13921 
13922 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13923 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13924 													 scalar_type /* arg3_type */);
13925 
13926 	case FUNCTION_CROSS:
13927 
13928 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13929 			function, "cross", tcu::cross);
13930 
13931 	case FUNCTION_DETERMINANT:
13932 
13933 		switch (variable_type)
13934 		{
13935 		case Utils::VARIABLE_TYPE_DMAT2:
13936 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13937 																						 Math::determinant);
13938 		case Utils::VARIABLE_TYPE_DMAT3:
13939 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13940 																						 Math::determinant);
13941 		case Utils::VARIABLE_TYPE_DMAT4:
13942 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13943 																						 Math::determinant);
13944 		default:
13945 			TCU_FAIL("Not implemented");
13946 		}
13947 
13948 	case FUNCTION_DISTANCE:
13949 
13950 		switch (variable_type)
13951 		{
13952 		case Utils::VARIABLE_TYPE_DVEC2:
13953 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13954 				function, "distance", tcu::distance);
13955 		case Utils::VARIABLE_TYPE_DVEC3:
13956 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13957 				function, "distance", tcu::distance);
13958 		case Utils::VARIABLE_TYPE_DVEC4:
13959 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13960 				function, "distance", tcu::distance);
13961 		default:
13962 			break;
13963 		}
13964 
13965 		break;
13966 
13967 	case FUNCTION_DOT:
13968 
13969 		switch (variable_type)
13970 		{
13971 		case Utils::VARIABLE_TYPE_DVEC2:
13972 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13973 				function, "dot", tcu::dot);
13974 		case Utils::VARIABLE_TYPE_DVEC3:
13975 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13976 				function, "dot", tcu::dot);
13977 		case Utils::VARIABLE_TYPE_DVEC4:
13978 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13979 				function, "dot", tcu::dot);
13980 		default:
13981 			break;
13982 		}
13983 
13984 		break;
13985 
13986 	case FUNCTION_EQUAL:
13987 
13988 		switch (variable_type)
13989 		{
13990 		case Utils::VARIABLE_TYPE_DVEC2:
13991 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13992 				function, "equal", Math::equal);
13993 		case Utils::VARIABLE_TYPE_DVEC3:
13994 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13995 				function, "equal", Math::equal);
13996 		case Utils::VARIABLE_TYPE_DVEC4:
13997 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13998 				function, "equal", Math::equal);
13999 		default:
14000 			break;
14001 		}
14002 
14003 		break;
14004 
14005 	case FUNCTION_FACEFORWARD:
14006 
14007 		switch (variable_type)
14008 		{
14009 		case Utils::VARIABLE_TYPE_DVEC2:
14010 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14011 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14012 				function, "faceforward", tcu::faceForward);
14013 		case Utils::VARIABLE_TYPE_DVEC3:
14014 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14015 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14016 				function, "faceforward", tcu::faceForward);
14017 		case Utils::VARIABLE_TYPE_DVEC4:
14018 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14019 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14020 				function, "faceforward", tcu::faceForward);
14021 		default:
14022 			break;
14023 		}
14024 
14025 		break;
14026 
14027 	case FUNCTION_FLOOR:
14028 
14029 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14030 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14031 
14032 	case FUNCTION_FMA:
14033 
14034 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14035 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14036 													 variable_type /* arg3_type */);
14037 
14038 	case FUNCTION_FRACT:
14039 
14040 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14041 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14042 
14043 	case FUNCTION_FREXP:
14044 
14045 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14046 															  glw::GLint /* OutT */>(
14047 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14048 			int_type /* out_type */);
14049 
14050 	case FUNCTION_GREATERTHAN:
14051 
14052 		switch (variable_type)
14053 		{
14054 		case Utils::VARIABLE_TYPE_DVEC2:
14055 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14056 				function, "greaterThan", Math::greaterThan);
14057 		case Utils::VARIABLE_TYPE_DVEC3:
14058 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14059 				function, "greaterThan", Math::greaterThan);
14060 		case Utils::VARIABLE_TYPE_DVEC4:
14061 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14062 				function, "greaterThan", Math::greaterThan);
14063 		default:
14064 			break;
14065 		}
14066 
14067 		break;
14068 
14069 	case FUNCTION_GREATERTHANEQUAL:
14070 
14071 		switch (variable_type)
14072 		{
14073 		case Utils::VARIABLE_TYPE_DVEC2:
14074 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14075 				function, "greaterThanEqual", Math::greaterThanEqual);
14076 		case Utils::VARIABLE_TYPE_DVEC3:
14077 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14078 				function, "greaterThanEqual", Math::greaterThanEqual);
14079 		case Utils::VARIABLE_TYPE_DVEC4:
14080 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14081 				function, "greaterThanEqual", Math::greaterThanEqual);
14082 		default:
14083 			break;
14084 		}
14085 
14086 		break;
14087 
14088 	case FUNCTION_INVERSE:
14089 
14090 		switch (variable_type)
14091 		{
14092 		case Utils::VARIABLE_TYPE_DMAT2:
14093 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14094 		case Utils::VARIABLE_TYPE_DMAT3:
14095 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14096 		case Utils::VARIABLE_TYPE_DMAT4:
14097 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14098 		default:
14099 			break;
14100 		}
14101 
14102 		break;
14103 
14104 	case FUNCTION_INVERSESQRT:
14105 
14106 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14107 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14108 
14109 	case FUNCTION_LDEXP:
14110 
14111 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14112 													 glw::GLint /* Arg2T */>(
14113 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14114 			int_type /* arg2_type */);
14115 
14116 	case FUNCTION_LESSTHAN:
14117 
14118 		switch (variable_type)
14119 		{
14120 		case Utils::VARIABLE_TYPE_DVEC2:
14121 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14122 				function, "lessThan", Math::lessThan);
14123 		case Utils::VARIABLE_TYPE_DVEC3:
14124 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14125 				function, "lessThan", Math::lessThan);
14126 		case Utils::VARIABLE_TYPE_DVEC4:
14127 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14128 				function, "lessThan", Math::lessThan);
14129 		default:
14130 			break;
14131 		}
14132 
14133 		break;
14134 
14135 	case FUNCTION_LESSTHANEQUAL:
14136 
14137 		switch (variable_type)
14138 		{
14139 		case Utils::VARIABLE_TYPE_DVEC2:
14140 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14141 				function, "lessThanEqual", Math::lessThanEqual);
14142 		case Utils::VARIABLE_TYPE_DVEC3:
14143 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14144 				function, "lessThanEqual", Math::lessThanEqual);
14145 		case Utils::VARIABLE_TYPE_DVEC4:
14146 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14147 				function, "lessThanEqual", Math::lessThanEqual);
14148 		default:
14149 			break;
14150 		}
14151 
14152 		break;
14153 
14154 	case FUNCTION_LENGTH:
14155 
14156 		switch (variable_type)
14157 		{
14158 		case Utils::VARIABLE_TYPE_DVEC2:
14159 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14160 																							  tcu::length);
14161 		case Utils::VARIABLE_TYPE_DVEC3:
14162 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14163 																							  tcu::length);
14164 		case Utils::VARIABLE_TYPE_DVEC4:
14165 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14166 																							  tcu::length);
14167 		default:
14168 			break;
14169 		}
14170 
14171 		break;
14172 
14173 	case FUNCTION_MATRIXCOMPMULT:
14174 
14175 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14176 													 glw::GLdouble /* Arg2T */>(
14177 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14178 			variable_type /* arg2_type */);
14179 
14180 	case FUNCTION_MAX:
14181 
14182 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14183 													 glw::GLdouble /* Arg2T */>(
14184 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14185 			variable_type /* arg2_type */);
14186 
14187 	case FUNCTION_MAX_AGAINST_SCALAR:
14188 
14189 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14190 													 glw::GLdouble /* Arg2T */>(
14191 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14192 			scalar_type /* arg2_type */);
14193 
14194 	case FUNCTION_MIN:
14195 
14196 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14197 													 glw::GLdouble /* Arg2T */>(
14198 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14199 			variable_type /* arg2_type */);
14200 
14201 	case FUNCTION_MIN_AGAINST_SCALAR:
14202 
14203 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14204 													 glw::GLdouble /* Arg2T */>(
14205 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14206 			scalar_type /* arg2_type */);
14207 
14208 	case FUNCTION_MIX:
14209 
14210 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14211 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14212 													 variable_type /* arg3_type */);
14213 
14214 	case FUNCTION_MOD:
14215 
14216 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14217 													 glw::GLdouble /* Arg2T */>(
14218 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14219 			variable_type /* arg2_type */);
14220 
14221 	case FUNCTION_MOD_AGAINST_SCALAR:
14222 
14223 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14224 													 glw::GLdouble /* Arg2T */>(
14225 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14226 			scalar_type /* arg2_type */);
14227 
14228 	case FUNCTION_MODF:
14229 
14230 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14231 															  glw::GLdouble /* OutT */>(
14232 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14233 			variable_type /* out_type */);
14234 
14235 	case FUNCTION_NORMALIZE:
14236 
14237 		switch (variable_type)
14238 		{
14239 		case Utils::VARIABLE_TYPE_DVEC2:
14240 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14241 																						   tcu::normalize);
14242 		case Utils::VARIABLE_TYPE_DVEC3:
14243 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14244 																						   tcu::normalize);
14245 		case Utils::VARIABLE_TYPE_DVEC4:
14246 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14247 																						   tcu::normalize);
14248 		default:
14249 			break;
14250 		}
14251 
14252 		break;
14253 
14254 	case FUNCTION_NOTEQUAL:
14255 
14256 		switch (variable_type)
14257 		{
14258 		case Utils::VARIABLE_TYPE_DVEC2:
14259 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14260 				function, "notEqual", Math::notEqual);
14261 		case Utils::VARIABLE_TYPE_DVEC3:
14262 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14263 				function, "notEqual", Math::notEqual);
14264 		case Utils::VARIABLE_TYPE_DVEC4:
14265 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14266 				function, "notEqual", Math::notEqual);
14267 		default:
14268 			break;
14269 		}
14270 
14271 		break;
14272 
14273 	case FUNCTION_OUTERPRODUCT:
14274 
14275 		switch (variable_type)
14276 		{
14277 		case Utils::VARIABLE_TYPE_DMAT2:
14278 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14279 				function, "outerProduct", Math::outerProduct);
14280 		case Utils::VARIABLE_TYPE_DMAT2X3:
14281 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14282 				function, "outerProduct", Math::outerProduct);
14283 		case Utils::VARIABLE_TYPE_DMAT2X4:
14284 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14285 				function, "outerProduct", Math::outerProduct);
14286 		case Utils::VARIABLE_TYPE_DMAT3:
14287 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14288 				function, "outerProduct", Math::outerProduct);
14289 		case Utils::VARIABLE_TYPE_DMAT3X2:
14290 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14291 				function, "outerProduct", Math::outerProduct);
14292 		case Utils::VARIABLE_TYPE_DMAT3X4:
14293 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14294 				function, "outerProduct", Math::outerProduct);
14295 		case Utils::VARIABLE_TYPE_DMAT4:
14296 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14297 				function, "outerProduct", Math::outerProduct);
14298 		case Utils::VARIABLE_TYPE_DMAT4X2:
14299 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14300 				function, "outerProduct", Math::outerProduct);
14301 		case Utils::VARIABLE_TYPE_DMAT4X3:
14302 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14303 				function, "outerProduct", Math::outerProduct);
14304 		default:
14305 			break;
14306 		}
14307 
14308 		break;
14309 
14310 	case FUNCTION_PACKDOUBLE2X32:
14311 
14312 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14313 																						  Math::packDouble2x32);
14314 
14315 	case FUNCTION_REFLECT:
14316 
14317 		switch (variable_type)
14318 		{
14319 		case Utils::VARIABLE_TYPE_DVEC2:
14320 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14321 				function, "reflect", tcu::reflect);
14322 		case Utils::VARIABLE_TYPE_DVEC3:
14323 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14324 				function, "reflect", tcu::reflect);
14325 		case Utils::VARIABLE_TYPE_DVEC4:
14326 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14327 				function, "reflect", tcu::reflect);
14328 		default:
14329 			break;
14330 		}
14331 
14332 		break;
14333 
14334 	case FUNCTION_REFRACT:
14335 
14336 		switch (variable_type)
14337 		{
14338 		case Utils::VARIABLE_TYPE_DVEC2:
14339 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14340 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14341 				function, "refract", tcu::refract);
14342 		case Utils::VARIABLE_TYPE_DVEC3:
14343 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14344 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14345 				function, "refract", tcu::refract);
14346 		case Utils::VARIABLE_TYPE_DVEC4:
14347 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14348 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14349 				function, "refract", tcu::refract);
14350 		default:
14351 			break;
14352 		}
14353 
14354 		break;
14355 
14356 	case FUNCTION_ROUND:
14357 
14358 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14359 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14360 
14361 	case FUNCTION_ROUNDEVEN:
14362 
14363 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14364 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14365 
14366 	case FUNCTION_SIGN:
14367 
14368 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14369 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14370 
14371 	case FUNCTION_SMOOTHSTEP:
14372 
14373 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14374 													 variable_type /* res_type  */, variable_type /* arg1_type */,
14375 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
14376 
14377 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14378 
14379 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14380 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
14381 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14382 
14383 	case FUNCTION_SQRT:
14384 
14385 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14386 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14387 
14388 	case FUNCTION_STEP:
14389 
14390 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14391 													 glw::GLdouble /* Arg2T */>(
14392 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14393 			variable_type /* arg2_type */);
14394 
14395 	case FUNCTION_STEP_AGAINST_SCALAR:
14396 
14397 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14398 													 glw::GLdouble /* Arg2T */>(
14399 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14400 			variable_type /* arg2_type */);
14401 
14402 	case FUNCTION_TRANSPOSE:
14403 
14404 		switch (variable_type)
14405 		{
14406 		case Utils::VARIABLE_TYPE_DMAT2:
14407 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14408 																				 Math::transpose);
14409 		case Utils::VARIABLE_TYPE_DMAT2X3:
14410 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14411 																					 Math::transpose);
14412 		case Utils::VARIABLE_TYPE_DMAT2X4:
14413 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14414 																					 Math::transpose);
14415 		case Utils::VARIABLE_TYPE_DMAT3:
14416 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14417 																				 Math::transpose);
14418 		case Utils::VARIABLE_TYPE_DMAT3X2:
14419 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14420 																					 Math::transpose);
14421 		case Utils::VARIABLE_TYPE_DMAT3X4:
14422 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14423 																					 Math::transpose);
14424 		case Utils::VARIABLE_TYPE_DMAT4:
14425 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14426 																				 Math::transpose);
14427 		case Utils::VARIABLE_TYPE_DMAT4X2:
14428 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14429 																					 Math::transpose);
14430 		case Utils::VARIABLE_TYPE_DMAT4X3:
14431 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14432 																					 Math::transpose);
14433 		default:
14434 			break;
14435 		}
14436 
14437 		break;
14438 
14439 	case FUNCTION_TRUNC:
14440 
14441 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14442 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14443 
14444 	case FUNCTION_UNPACKDOUBLE2X32:
14445 
14446 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14447 																						  Math::unpackDouble2x32);
14448 
14449 	case FUNCTION_ISNAN:
14450 
14451 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14452 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14453 
14454 	case FUNCTION_ISINF:
14455 
14456 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14457 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14458 
14459 	default:
14460 		TCU_FAIL("Not implemented");
14461 		return 0;
14462 	}
14463 
14464 	TCU_FAIL("Not implemented");
14465 	return 0;
14466 }
14467 
14468 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14469  *
14470  * @param argument        Argument index
14471  * @param function_object Function object
14472  *
14473  * @return Function pointer
14474  **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14475 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14476 	glw::GLuint argument, const functionObject& function_object) const
14477 {
14478 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14479 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14480 
14481 	switch (argument_type)
14482 	{
14483 	case Utils::VARIABLE_TYPE_DMAT2:
14484 		return gl.uniformMatrix2dv;
14485 	case Utils::VARIABLE_TYPE_DMAT2X3:
14486 		return gl.uniformMatrix2x3dv;
14487 	case Utils::VARIABLE_TYPE_DMAT2X4:
14488 		return gl.uniformMatrix2x4dv;
14489 	case Utils::VARIABLE_TYPE_DMAT3:
14490 		return gl.uniformMatrix3dv;
14491 	case Utils::VARIABLE_TYPE_DMAT3X2:
14492 		return gl.uniformMatrix3x2dv;
14493 	case Utils::VARIABLE_TYPE_DMAT3X4:
14494 		return gl.uniformMatrix3x4dv;
14495 	case Utils::VARIABLE_TYPE_DMAT4:
14496 		return gl.uniformMatrix4dv;
14497 	case Utils::VARIABLE_TYPE_DMAT4X2:
14498 		return gl.uniformMatrix4x2dv;
14499 	case Utils::VARIABLE_TYPE_DMAT4X3:
14500 		return gl.uniformMatrix4x3dv;
14501 	default:
14502 		break;
14503 	}
14504 
14505 	TCU_FAIL("Not implemented");
14506 	return 0;
14507 }
14508 
14509 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14510  *
14511  * @param argument        Argument index
14512  * @param function_object Function object
14513  *
14514  * @return Function pointer
14515  **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14516 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14517 	glw::GLuint argument, const functionObject& function_object) const
14518 {
14519 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14520 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14521 
14522 	switch (argument_type)
14523 	{
14524 	case Utils::VARIABLE_TYPE_DOUBLE:
14525 		return gl.uniform1dv;
14526 	case Utils::VARIABLE_TYPE_DVEC2:
14527 		return gl.uniform2dv;
14528 	case Utils::VARIABLE_TYPE_DVEC3:
14529 		return gl.uniform3dv;
14530 	case Utils::VARIABLE_TYPE_DVEC4:
14531 		return gl.uniform4dv;
14532 	default:
14533 		TCU_FAIL("Not implemented");
14534 	}
14535 
14536 	return 0;
14537 }
14538 
14539 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14540  *
14541  * @param argument        Argument index
14542  * @param function_object Function object
14543  *
14544  * @return Function pointer
14545  **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14546 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14547 	glw::GLuint argument, const functionObject& function_object) const
14548 {
14549 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14550 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14551 
14552 	switch (argument_type)
14553 	{
14554 	case Utils::VARIABLE_TYPE_INT:
14555 		return gl.uniform1iv;
14556 	case Utils::VARIABLE_TYPE_IVEC2:
14557 		return gl.uniform2iv;
14558 	case Utils::VARIABLE_TYPE_IVEC3:
14559 		return gl.uniform3iv;
14560 	case Utils::VARIABLE_TYPE_IVEC4:
14561 		return gl.uniform4iv;
14562 	default:
14563 		TCU_FAIL("Not implemented");
14564 	}
14565 
14566 	return 0;
14567 }
14568 
14569 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14570  *
14571  * @param argument        Argument index
14572  * @param function_object Function object
14573  *
14574  * @return Function pointer
14575  **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14576 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14577 	glw::GLuint argument, const functionObject& function_object) const
14578 {
14579 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14580 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14581 
14582 	switch (argument_type)
14583 	{
14584 	case Utils::VARIABLE_TYPE_UVEC2:
14585 		return gl.uniform2uiv;
14586 	default:
14587 		TCU_FAIL("Not implemented");
14588 	}
14589 
14590 	return 0;
14591 }
14592 
14593 /** Get name of uniform that will be used as <argument>.
14594  *
14595  * @param argument Argument index
14596  *
14597  * @return Name of uniform
14598  **/
getUniformName(glw::GLuint argument) const14599 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14600 {
14601 	switch (argument)
14602 	{
14603 	case 0:
14604 		return "uniform_0";
14605 	case 1:
14606 		return "uniform_1";
14607 	case 2:
14608 		return "uniform_2";
14609 	default:
14610 		TCU_FAIL("Not implemented");
14611 		return 0;
14612 	}
14613 }
14614 
14615 /** Get name of varying that will be used as <result>.
14616  *
14617  * @param result Result index
14618  *
14619  * @return Name of varying
14620  **/
getVaryingName(glw::GLuint result) const14621 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14622 {
14623 	switch (result)
14624 	{
14625 	case 0:
14626 		return "result_0";
14627 	case 1:
14628 		return "result_1";
14629 	case 2:
14630 		return "result_2";
14631 	default:
14632 		TCU_FAIL("Not implemented");
14633 		return 0;
14634 	}
14635 }
14636 
14637 /** Check if given combination of function and type is implemented
14638  *
14639  * @param function Function enumeration
14640  * @param type     Type details
14641  *
14642  * @return true if function is available for given type, false otherwise
14643  **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14644 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14645 {
14646 	static const bool look_up_table[][3] = {
14647 		/* SCALAR, VECTOR, MATRIX */
14648 		/* FUNCTION_ABS:                       */ { true, true, false },
14649 		/* FUNCTION_CEIL:                      */ { true, true, false },
14650 		/* FUNCTION_CLAMP:                     */ { true, true, false },
14651 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14652 		/* FUNCTION_CROSS:                     */ { false, true, false },
14653 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
14654 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
14655 		/* FUNCTION_DOT:                       */ { false, true, false },
14656 		/* FUNCTION_EQUAL:                     */ { false, true, false },
14657 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
14658 		/* FUNCTION_FLOOR:                     */ { true, true, false },
14659 		/* FUNCTION_FMA:                       */ { true, true, false },
14660 		/* FUNCTION_FRACT:                     */ { true, true, false },
14661 		/* FUNCTION_FREXP:                     */ { true, true, false },
14662 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
14663 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14664 		/* FUNCTION_INVERSE:                   */ { false, false, true },
14665 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
14666 		/* FUNCTION_LDEXP:                     */ { true, true, false },
14667 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
14668 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14669 		/* FUNCTION_LENGTH:                    */ { false, true, false },
14670 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14671 		/* FUNCTION_MAX:                       */ { true, true, false },
14672 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14673 		/* FUNCTION_MIN:                       */ { true, true, false },
14674 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14675 		/* FUNCTION_MIX:                       */ { true, true, false },
14676 		/* FUNCTION_MOD:                       */ { true, true, false },
14677 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14678 		/* FUNCTION_MODF:                      */ { true, true, false },
14679 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
14680 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14681 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14682 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14683 		/* FUNCTION_REFLECT:                   */ { false, true, false },
14684 		/* FUNCTION_REFRACT:                   */ { false, true, false },
14685 		/* FUNCTION_ROUND:                     */ { true, true, false },
14686 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14687 		/* FUNCTION_SIGN:                      */ { true, false, false },
14688 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14689 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14690 		/* FUNCTION_SQRT:                      */ { true, true, false },
14691 		/* FUNCTION_STEP:                      */ { true, true, false },
14692 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14693 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14694 		/* FUNCTION_TRUNC:                     */ { true, true, false },
14695 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14696 		/* FUNCTION_ISNAN:                     */ { true, true, false },
14697 		/* FUNCTION_ISINF:                     */ { true, true, false },
14698 	};
14699 
14700 	bool result = look_up_table[function][type.m_general_type];
14701 
14702 	if (true == result)
14703 	{
14704 		switch (function)
14705 		{
14706 		case FUNCTION_CROSS: /* Only 3 element vectors */
14707 			result = (3 == type.m_n_rows);
14708 			break;
14709 		case FUNCTION_DETERMINANT: /* Only square matrices */
14710 		case FUNCTION_INVERSE:
14711 			result = (type.m_n_columns == type.m_n_rows);
14712 			break;
14713 		default:
14714 			break;
14715 		}
14716 	}
14717 
14718 	return result;
14719 }
14720 
14721 /** Logs variable of given type: name (type) [values]
14722  *
14723  * @param buffer Source of data
14724  * @param name   Name of variable
14725  * @param type   Type of variable
14726  **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14727 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14728 										  Utils::_variable_type type) const
14729 {
14730 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
14731 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
14732 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14733 
14734 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14735 
14736 	for (glw::GLuint component = 0; component < n_components; ++component)
14737 	{
14738 		if (0 != component)
14739 		{
14740 			message << ", ";
14741 		}
14742 
14743 		switch (base_type)
14744 		{
14745 		case Utils::VARIABLE_TYPE_DOUBLE:
14746 			message << ((glw::GLdouble*)buffer)[component];
14747 			break;
14748 		case Utils::VARIABLE_TYPE_INT:
14749 			message << ((glw::GLint*)buffer)[component];
14750 			break;
14751 		case Utils::VARIABLE_TYPE_UINT:
14752 			message << ((glw::GLuint*)buffer)[component];
14753 			break;
14754 		default:
14755 			TCU_FAIL("Not implemented");
14756 		}
14757 	}
14758 
14759 	message << "]" << tcu::TestLog::EndMessage;
14760 }
14761 
14762 /** Prepare input arguments, data are stored in <buffer>
14763  *
14764  * @param function_object Function object
14765  * @param vertex          Vertex index
14766  * @param buffer          Buffer pointer
14767  **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14768 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14769 										  glw::GLubyte* buffer)
14770 {
14771 	const glw::GLuint n_arguments = function_object.getArgumentCount();
14772 
14773 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14774 	{
14775 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
14776 
14777 		prepareComponents(function_object, vertex, argument, buffer + offset);
14778 	}
14779 }
14780 
14781 /** Prepare components for given <function_object>, <vertex> and <argument>
14782  *
14783  * @param function_object Function object
14784  * @param vertex          Vertex index
14785  * @param argument        Argument index
14786  * @param buffer          Buffer pointer
14787  **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14788 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14789 											glw::GLuint argument, glw::GLubyte* buffer)
14790 {
14791 	glw::GLuint					argument_index[3]		 = { 0 };
14792 	glw::GLuint					argument_reset[3]		 = { 0 };
14793 	glw::GLuint					argument_step[3]		 = { 0 };
14794 	glw::GLdouble				double_argument_start[3] = { 0.0 };
14795 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14796 	glw::GLuint					int_argument_start  = -4;
14797 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
14798 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
14799 	glw::GLuint					uint_argument_start = 0;
14800 
14801 	switch (n_arguments)
14802 	{
14803 	case 1:
14804 		argument_step[0]		 = 1;
14805 		argument_reset[0]		 = 1024;
14806 		double_argument_start[0] = -511.5;
14807 		break;
14808 	case 2:
14809 		argument_step[0]		 = 32;
14810 		argument_step[1]		 = 1;
14811 		argument_reset[0]		 = 32;
14812 		argument_reset[1]		 = 32;
14813 		double_argument_start[0] = -15.5;
14814 		double_argument_start[1] = -15.5;
14815 		break;
14816 	case 3:
14817 		argument_step[0]		 = 64;
14818 		argument_step[1]		 = 8;
14819 		argument_step[2]		 = 1;
14820 		argument_reset[0]		 = 16;
14821 		argument_reset[1]		 = 8;
14822 		argument_reset[2]		 = 8;
14823 		double_argument_start[0] = -7.5;
14824 		double_argument_start[1] = -3.5;
14825 		double_argument_start[2] = -3.5;
14826 		break;
14827 	default:
14828 		TCU_FAIL("Not implemented");
14829 		return;
14830 	}
14831 
14832 	switch (function_object.getFunctionEnum())
14833 	{
14834 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14835 	case FUNCTION_CLAMP_AGAINST_SCALAR:
14836 		double_argument_start[2] = 4.5;
14837 		break;
14838 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14839 		double_argument_start[0] = 16.5;
14840 		break;
14841 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14842 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14843 		argument_step[0]		 = 1;
14844 		argument_step[1]		 = 8;
14845 		argument_step[2]		 = 64;
14846 		argument_reset[0]		 = 8;
14847 		argument_reset[1]		 = 8;
14848 		argument_reset[2]		 = 16;
14849 		double_argument_start[0] = -3.5;
14850 		double_argument_start[1] = 4.5;
14851 		double_argument_start[2] = -7.5;
14852 		break;
14853 	default:
14854 		break;
14855 	}
14856 
14857 	for (glw::GLuint i = 0; i < n_arguments; ++i)
14858 	{
14859 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14860 	}
14861 
14862 	switch (base_arg_type)
14863 	{
14864 	case Utils::VARIABLE_TYPE_DOUBLE:
14865 	{
14866 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14867 
14868 		double_argument_start[argument] += argument_index[argument];
14869 
14870 		for (glw::GLuint component = 0; component < n_components; ++component)
14871 		{
14872 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14873 
14874 			switch (function_object.getFunctionEnum())
14875 			{
14876 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14877 				if (0.5 == Math::fract(value))
14878 				{
14879 					value += 0.01;
14880 				}
14881 				break;
14882 			default:
14883 				break;
14884 			}
14885 
14886 			argument_dst[component] = value;
14887 		}
14888 	}
14889 	break;
14890 	case Utils::VARIABLE_TYPE_INT:
14891 	{
14892 		glw::GLint* argument_dst = (glw::GLint*)buffer;
14893 
14894 		uint_argument_start += argument_index[argument];
14895 
14896 		for (glw::GLuint component = 0; component < n_components; ++component)
14897 		{
14898 			const glw::GLint value = int_argument_start + component;
14899 
14900 			argument_dst[component] = value;
14901 		}
14902 	}
14903 	break;
14904 	case Utils::VARIABLE_TYPE_UINT:
14905 	{
14906 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14907 
14908 		uint_argument_start += argument_index[argument];
14909 
14910 		for (glw::GLuint component = 0; component < n_components; ++component)
14911 		{
14912 			const glw::GLuint value = uint_argument_start + component;
14913 
14914 			argument_dst[component] = value;
14915 		}
14916 	}
14917 	break;
14918 	default:
14919 		TCU_FAIL("Not implemented");
14920 		return;
14921 	}
14922 }
14923 
14924 /** Prepare programInfo for given functionObject
14925  *
14926  * @param function_object  Function object
14927  * @param out_program_info Program info
14928  **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14929 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14930 {
14931 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
14932 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14933 
14934 	prepareVertexShaderCode(function_object);
14935 
14936 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14937 						   varying_names, n_varying_names);
14938 }
14939 
14940 /** Prepare input data and expected results for given function object
14941  *
14942  * @param function_object Function object
14943  **/
prepareTestData(const functionObject & function_object)14944 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14945 {
14946 	const glw::GLuint result_stride		   = function_object.getResultStride();
14947 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
14948 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
14949 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14950 
14951 	m_argument_data.clear();
14952 	m_expected_results_data.clear();
14953 
14954 	m_argument_data.resize(argument_buffer_size);
14955 	m_expected_results_data.resize(result_buffer_size);
14956 
14957 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14958 	{
14959 		const glw::GLuint result_offset   = vertex * result_stride;
14960 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
14961 		const glw::GLuint argument_offset = vertex * argument_stride;
14962 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
14963 
14964 		prepareArgument(function_object, vertex, argument_dst);
14965 		function_object.call(result_dst, argument_dst);
14966 	}
14967 }
14968 
14969 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14970  *
14971  * @param function_object Function object
14972  **/
prepareVertexShaderCode(const functionObject & function_object)14973 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14974 {
14975 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
14976 													 "\n"
14977 													 "precision highp float;\n"
14978 													 "\n"
14979 													 "ARGUMENT_DEFINITION"
14980 													 "\n"
14981 													 "RESULT_DEFINITION"
14982 													 "\n"
14983 													 "void main()\n"
14984 													 "{\n"
14985 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14986 													 "}\n"
14987 													 "\n";
14988 
14989 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
14990 	static const glw::GLchar* argument_token			= "ARGUMENT";
14991 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
14992 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
14993 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
14994 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
14995 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
14996 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
14997 
14998 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
14999 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
15000 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
15001 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15002 
15003 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15004 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
15005 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
15006 	const glw::GLuint n_results					 = function_object.getResultCount();
15007 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15008 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
15009 
15010 	size_t		search_position = 0;
15011 	std::string string			= shader_template_code;
15012 
15013 	/* Replace ARGUMENT_DEFINITION with definitions */
15014 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15015 	{
15016 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15017 		const glw::GLchar*	uniform_name  = getUniformName(argument);
15018 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
15019 
15020 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15021 
15022 		search_position -= argument_definition_length;
15023 
15024 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15025 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15026 	}
15027 
15028 	/* Remove ARGUMENT_DEFINITION */
15029 	Utils::replaceToken(argument_definition_token, search_position, "", string);
15030 
15031 	/* Replace RESULT_DEFINITION with definitions */
15032 	for (glw::GLuint result = 0; result < n_results; ++result)
15033 	{
15034 		Utils::_variable_type variable_type = function_object.getResultType(result);
15035 		const glw::GLchar*	varying_name  = getVaryingName(result);
15036 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
15037 
15038 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15039 
15040 		search_position -= result_definition_length;
15041 
15042 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15043 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
15044 	}
15045 
15046 	/* Remove RESULT_DEFINITION */
15047 	Utils::replaceToken(result_definition_token, search_position, "", string);
15048 
15049 	/* Replace RESULT_NAME */
15050 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15051 
15052 	/* Replace RESULT_TYPE */
15053 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15054 
15055 	/* Replace FUNCTION_NAME */
15056 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15057 
15058 	/* Replace ARGUMENT with list of arguments */
15059 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15060 	{
15061 		const glw::GLchar* uniform_name = getUniformName(argument);
15062 
15063 		if (0 == argument)
15064 		{
15065 			Utils::replaceToken(argument_token, search_position, first_argument, string);
15066 		}
15067 		else
15068 		{
15069 			Utils::replaceToken(argument_token, search_position, argument_str, string);
15070 		}
15071 
15072 		search_position -= first_argument_length;
15073 
15074 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15075 	}
15076 
15077 	for (glw::GLuint result = 1; result < n_results; ++result)
15078 	{
15079 		const glw::GLchar* varying_name = getVaryingName(result);
15080 
15081 		Utils::replaceToken(argument_token, search_position, argument_str, string);
15082 
15083 		search_position -= first_argument_length;
15084 
15085 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15086 	}
15087 
15088 	/* Remove ARGUMENT */
15089 	Utils::replaceToken(argument_token, search_position, "", string);
15090 
15091 	m_vertex_shader_code = string;
15092 }
15093 
15094 /** Test single function with one type
15095  *
15096  * param function Function enumeration
15097  * param type     Type details
15098  *
15099  * @return true if test pass (or function is not available for <type>), false otherwise
15100  **/
test(FunctionEnum function,const typeDetails & type)15101 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15102 {
15103 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15104 
15105 	/* Skip if function is not implemented for type */
15106 	if (false == isFunctionImplemented(function, type))
15107 	{
15108 		return true;
15109 	}
15110 
15111 	Utils::programInfo			  program(m_context);
15112 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15113 
15114 	prepareProgram(*function_object, program);
15115 	prepareTestData(*function_object);
15116 
15117 	/* Set up program */
15118 	gl.useProgram(program.m_program_object_id);
15119 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15120 
15121 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15122 	{
15123 		testBegin(*function_object, program.m_program_object_id, vertex);
15124 
15125 		gl.beginTransformFeedback(GL_POINTS);
15126 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15127 
15128 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15129 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15130 
15131 		gl.endTransformFeedback();
15132 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15133 
15134 		if (false == verifyResults(*function_object, vertex))
15135 		{
15136 			return false;
15137 		}
15138 	}
15139 
15140 	return true;
15141 }
15142 
15143 /** Update transform feedback buffer and uniforms
15144  *
15145  * @param function_object Function object
15146  * @param program_id      Program object id
15147  * @param vertex          Vertex index
15148  **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15149 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15150 {
15151 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
15152 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
15153 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
15154 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
15155 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
15156 
15157 	/* Update transform feedback buffer */
15158 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
15159 	transform_feedback_buffer_data.resize(result_buffer_size);
15160 
15161 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15162 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15163 
15164 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15165 				  GL_DYNAMIC_COPY);
15166 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15167 
15168 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15169 					   result_buffer_size);
15170 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15171 
15172 	/* Update VAO */
15173 	gl.bindVertexArray(m_vertex_array_object_id);
15174 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15175 
15176 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15177 	{
15178 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
15179 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
15180 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
15181 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
15182 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
15183 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15184 
15185 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15186 
15187 		if (-1 == uniform_location)
15188 		{
15189 			TCU_FAIL("Inactive uniform");
15190 		}
15191 
15192 		if (1 == n_columns)
15193 		{
15194 			switch (Utils::getBaseVariableType(argument_type))
15195 			{
15196 			case Utils::VARIABLE_TYPE_DOUBLE:
15197 			{
15198 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15199 
15200 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15201 			}
15202 			break;
15203 			case Utils::VARIABLE_TYPE_UINT:
15204 			{
15205 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15206 
15207 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15208 			}
15209 			break;
15210 			case Utils::VARIABLE_TYPE_INT:
15211 			{
15212 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15213 
15214 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15215 			}
15216 			break;
15217 			default:
15218 				TCU_FAIL("Not implemented");
15219 			}
15220 		}
15221 		else
15222 		{
15223 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15224 
15225 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15226 		}
15227 	}
15228 }
15229 
15230 /** Init GL obejcts
15231  *
15232  **/
testInit()15233 void BuiltinFunctionTest::testInit()
15234 {
15235 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15236 
15237 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
15238 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15239 
15240 	gl.genVertexArrays(1, &m_vertex_array_object_id);
15241 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15242 
15243 	gl.enable(GL_RASTERIZER_DISCARD);
15244 }
15245 
15246 /** Checks if function result is an acceptable edge case
15247  *
15248  * @param function_object Function object
15249  * @param vertex          Vertex index
15250  *
15251  * @return true if all results are as expected, false otherwise
15252  **/
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)15253 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15254 										   const Utils::_variable_type result_type,
15255 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15256 {
15257 	FunctionEnum function_type = function_object.getFunctionEnum();
15258 	switch (function_type)
15259 	{
15260 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15261 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15262 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15263 	case FUNCTION_MOD:
15264 	case FUNCTION_MOD_AGAINST_SCALAR:
15265 	{
15266 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
15267 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
15268 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
15269 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
15270 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
15271 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
15272 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
15273 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
15274 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15275 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15276 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15277 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
15278 		bool				 edge_case_present = false;
15279 		bool				 recheck		   = false;
15280 
15281 		// verify if there is a mod(a, a) case and prepare new expected result
15282 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15283 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15284 		for (glw::GLuint component = 0; component < n_components; ++component)
15285 		{
15286 			glw::GLdouble expected_result_component = expected_result[component];
15287 			glw::GLdouble actual_result_component   = actual_result[component];
15288 			glw::GLdouble argument_1_component		= argument_1[component];
15289 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15290 
15291 			// if coresponding components of arguments are equal and if component of first argument
15292 			// and component of result are equal then expected result must be corrected
15293 			edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) &&
15294 								(m_epsilon > de::abs(argument_1_component - actual_result_component));
15295 			recheck |= edge_case_present;
15296 			corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component;
15297 		}
15298 
15299 		// recheck test result with corrected expected result
15300 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15301 	}
15302 	default:
15303 		return false;
15304 	}
15305 }
15306 
15307 /** Compare contents of transform feedback buffer with expected results
15308  *
15309  * @param function_object Function object
15310  * @param vertex          Vertex index
15311  *
15312  * @return true if all results are as expected, false otherwise
15313  **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15314 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15315 {
15316 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
15317 	bool				  test_result	  = true;
15318 	const glw::GLuint	 n_results		   = function_object.getResultCount();
15319 	const glw::GLuint	 results_stride   = function_object.getResultStride();
15320 	const glw::GLuint	 results_offset   = vertex * results_stride;
15321 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15322 
15323 	/* Get transform feedback data */
15324 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15325 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15326 
15327 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15328 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15329 
15330 	for (glw::GLuint result = 0; result < n_results; ++result)
15331 	{
15332 		const Utils::_variable_type result_type   = function_object.getResultType(result);
15333 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
15334 
15335 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
15336 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
15337 
15338 		if (compare(result_type, expected_result_src, result_src))
15339 			continue;
15340 
15341 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15342 		{
15343 			test_result = false;
15344 			break;
15345 		}
15346 	}
15347 
15348 	/* Unmap transform feedback buffer */
15349 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15350 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15351 
15352 	if (false == test_result)
15353 	{
15354 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
15355 		const glw::GLuint arguments_offset = vertex * argument_stride;
15356 
15357 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15358 											<< tcu::TestLog::EndMessage;
15359 
15360 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15361 											<< tcu::TestLog::EndMessage;
15362 
15363 		for (glw::GLuint result = 0; result < n_results; ++result)
15364 		{
15365 			const Utils::_variable_type result_type   = function_object.getResultType(result);
15366 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
15367 
15368 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
15369 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
15370 
15371 			logVariableType(result_src, "Result", result_type);
15372 			logVariableType(expected_result_src, "Expected result", result_type);
15373 		}
15374 
15375 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15376 		{
15377 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15378 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
15379 
15380 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15381 		}
15382 
15383 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15384 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
15385 	}
15386 
15387 	return test_result;
15388 }
15389 
15390 /** Constructor.
15391  *
15392  *  @param context Rendering context.
15393  **/
GPUShaderFP64Tests(deqp::Context & context)15394 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15395 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15396 {
15397 	/* Left blank on purpose */
15398 }
15399 
15400 /** Initializes a texture_storage_multisample test group.
15401  *
15402  **/
init(void)15403 void GPUShaderFP64Tests::init(void)
15404 {
15405 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15406 	fp64->addChild(new GPUShaderFP64Test1(m_context));
15407 	fp64->addChild(new GPUShaderFP64Test2(m_context));
15408 	fp64->addChild(new GPUShaderFP64Test3(m_context));
15409 	fp64->addChild(new GPUShaderFP64Test4(m_context));
15410 	fp64->addChild(new GPUShaderFP64Test5(m_context));
15411 	fp64->addChild(new GPUShaderFP64Test6(m_context));
15412 	fp64->addChild(new GPUShaderFP64Test7(m_context));
15413 	fp64->addChild(new GPUShaderFP64Test8(m_context));
15414 	fp64->addChild(new GPUShaderFP64Test9(m_context));
15415 	addChild(fp64);
15416 
15417 	TypeDefinition typeDefinition[] =
15418 	{
15419 		{ "double",  1, 1 },
15420 		{ "dvec2",   1, 2 },
15421 		{ "dvec3",   1, 3 },
15422 		{ "dvec4",   1, 4 },
15423 		{ "dmat2",   2, 2 },
15424 		{ "dmat2x3", 2, 3 },
15425 		{ "dmat2x4", 2, 4 },
15426 		{ "dmat3x2", 3, 2 },
15427 		{ "dmat3",   3, 3 },
15428 		{ "dmat3x4", 3, 4 },
15429 		{ "dmat4x2", 4, 2 },
15430 		{ "dmat4x3", 4, 3 },
15431 		{ "dmat4",   4, 4 }
15432 	};
15433 
15434 	struct BuiltinFunctions
15435 	{
15436 		std::string  name;
15437 		FunctionEnum function;
15438 	} builtinFunctions[] = {
15439 		{ "abs",						FUNCTION_ABS },
15440 		{ "ceil",						FUNCTION_CEIL },
15441 		{ "clamp",						FUNCTION_CLAMP },
15442 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
15443 		{ "cross",						FUNCTION_CROSS },
15444 		{ "determinant",				FUNCTION_DETERMINANT },
15445 		{ "distance",					FUNCTION_DISTANCE },
15446 		{ "dot",						FUNCTION_DOT },
15447 		{ "equal",						FUNCTION_EQUAL },
15448 		{ "faceforward",				FUNCTION_FACEFORWARD },
15449 		{ "floor",						FUNCTION_FLOOR },
15450 		{ "fma",						FUNCTION_FMA },
15451 		{ "fract",						FUNCTION_FRACT },
15452 		{ "frexp",						FUNCTION_FREXP },
15453 		{ "greaterthan",				FUNCTION_GREATERTHAN },
15454 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
15455 		{ "inverse",					FUNCTION_INVERSE },
15456 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
15457 		{ "ldexp",						FUNCTION_LDEXP },
15458 		{ "lessthan",					FUNCTION_LESSTHAN },
15459 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
15460 		{ "length",						FUNCTION_LENGTH },
15461 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
15462 		{ "max",						FUNCTION_MAX },
15463 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
15464 		{ "min",						FUNCTION_MIN },
15465 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
15466 		{ "mix",						FUNCTION_MIX },
15467 		{ "mod",						FUNCTION_MOD },
15468 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
15469 		{ "modf",						FUNCTION_MODF },
15470 		{ "normalize",					FUNCTION_NORMALIZE },
15471 		{ "notequal",					FUNCTION_NOTEQUAL },
15472 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
15473 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
15474 		{ "reflect",					FUNCTION_REFLECT },
15475 		{ "refract",					FUNCTION_REFRACT },
15476 		{ "round",						FUNCTION_ROUND },
15477 		{ "roundeven",					FUNCTION_ROUNDEVEN },
15478 		{ "sign",						FUNCTION_SIGN },
15479 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
15480 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15481 		{ "sqrt",						FUNCTION_SQRT },
15482 		{ "step",						FUNCTION_STEP },
15483 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
15484 		{ "transpose",					FUNCTION_TRANSPOSE },
15485 		{ "trunc",						FUNCTION_TRUNC },
15486 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
15487 		{ "isnan",						FUNCTION_ISNAN },
15488 		{ "isinf",						FUNCTION_ISINF }
15489 	};
15490 
15491 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15492 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15493 	{
15494 		const BuiltinFunctions& bf = builtinFunctions[i];
15495 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15496 		{
15497 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
15498 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15499 		}
15500 	}
15501 	addChild(builin);
15502 }
15503 
15504 } /* glcts namespace */
15505