1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  * \file  gl4GPUShaderFP64Tests.cpp
26  * \brief Implements conformance tests for "GPU Shader FP64" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cGPUShaderFP64Tests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuTestLog.hpp"
34 
35 #include <iomanip>
36 
37 #include "deMath.h"
38 #include "deUniquePtr.hpp"
39 #include "tcuMatrixUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 
42 #include <cstdlib>
43 #include <cstring>
44 #include <limits>
45 #include <memory>
46 
47 namespace gl4cts
48 {
49 
50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9;
51 
52 /** Constructor
53  *
54  * @param context Test context
55  **/
programInfo(deqp::Context& context)56 Utils::programInfo::programInfo(deqp::Context& context)
57 	: m_context(context)
58 	, m_compute_shader_id(0)
59 	, m_fragment_shader_id(0)
60 	, m_geometry_shader_id(0)
61 	, m_program_object_id(0)
62 	, m_tesselation_control_shader_id(0)
63 	, m_tesselation_evaluation_shader_id(0)
64 	, m_vertex_shader_id(0)
65 {
66 	/* Nothing to be done here */
67 }
68 
69 /** Destructor
70  *
71  **/
~programInfo()72 Utils::programInfo::~programInfo()
73 {
74 	/* GL entry points */
75 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
76 
77 	/* Make sure program object is no longer used by GL */
78 	gl.useProgram(0);
79 
80 	/* Clean program object */
81 	if (0 != m_program_object_id)
82 	{
83 		gl.deleteProgram(m_program_object_id);
84 		m_program_object_id = 0;
85 	}
86 
87 	/* Clean shaders */
88 	if (0 != m_compute_shader_id)
89 	{
90 		gl.deleteShader(m_compute_shader_id);
91 		m_compute_shader_id = 0;
92 	}
93 
94 	if (0 != m_fragment_shader_id)
95 	{
96 		gl.deleteShader(m_fragment_shader_id);
97 		m_fragment_shader_id = 0;
98 	}
99 
100 	if (0 != m_geometry_shader_id)
101 	{
102 		gl.deleteShader(m_geometry_shader_id);
103 		m_geometry_shader_id = 0;
104 	}
105 
106 	if (0 != m_tesselation_control_shader_id)
107 	{
108 		gl.deleteShader(m_tesselation_control_shader_id);
109 		m_tesselation_control_shader_id = 0;
110 	}
111 
112 	if (0 != m_tesselation_evaluation_shader_id)
113 	{
114 		gl.deleteShader(m_tesselation_evaluation_shader_id);
115 		m_tesselation_evaluation_shader_id = 0;
116 	}
117 
118 	if (0 != m_vertex_shader_id)
119 	{
120 		gl.deleteShader(m_vertex_shader_id);
121 		m_vertex_shader_id = 0;
122 	}
123 }
124 
125 /** Build program
126  *
127  * @param compute_shader_code                Compute shader source code
128  * @param fragment_shader_code               Fragment shader source code
129  * @param geometry_shader_code               Geometry shader source code
130  * @param tesselation_control_shader_code    Tesselation control shader source code
131  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
132  * @param vertex_shader_code                 Vertex shader source code
133  * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
134  * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
135  **/
build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code, const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code, const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names, glw::GLuint n_varying_names)136 void Utils::programInfo::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
137 							   const glw::GLchar* geometry_shader_code,
138 							   const glw::GLchar* tesselation_control_shader_code,
139 							   const glw::GLchar* tesselation_evaluation_shader_code,
140 							   const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names,
141 							   glw::GLuint n_varying_names)
142 {
143 	/* GL entry points */
144 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
145 
146 	/* Create shader objects and compile */
147 	if (0 != compute_shader_code)
148 	{
149 		m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
150 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
151 
152 		compile(m_compute_shader_id, compute_shader_code);
153 	}
154 
155 	if (0 != fragment_shader_code)
156 	{
157 		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
158 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
159 
160 		compile(m_fragment_shader_id, fragment_shader_code);
161 	}
162 
163 	if (0 != geometry_shader_code)
164 	{
165 		m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
166 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
167 
168 		compile(m_geometry_shader_id, geometry_shader_code);
169 	}
170 
171 	if (0 != tesselation_control_shader_code)
172 	{
173 		m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
174 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
175 
176 		compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
177 	}
178 
179 	if (0 != tesselation_evaluation_shader_code)
180 	{
181 		m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
182 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
183 
184 		compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
185 	}
186 
187 	if (0 != vertex_shader_code)
188 	{
189 		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
190 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
191 
192 		compile(m_vertex_shader_id, vertex_shader_code);
193 	}
194 
195 	/* Create program object */
196 	m_program_object_id = gl.createProgram();
197 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
198 
199 	/* Set up captyured varyings' names */
200 	if (0 != n_varying_names)
201 	{
202 		gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
203 		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
204 	}
205 
206 	/* Link program */
207 	link();
208 }
209 
210 /** Compile shader
211  *
212  * @param shader_id   Shader object id
213  * @param shader_code Shader source code
214  **/
compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
216 {
217 	/* GL entry points */
218 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
219 
220 	/* Compilation status */
221 	glw::GLint status = GL_FALSE;
222 
223 	/* Set source code */
224 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
225 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
226 
227 	/* Compile */
228 	gl.compileShader(shader_id);
229 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
230 
231 	/* Get compilation status */
232 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
233 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
234 
235 	/* Log compilation error */
236 	if (GL_TRUE != status)
237 	{
238 		glw::GLint				 length = 0;
239 		std::vector<glw::GLchar> message;
240 
241 		/* Error log length */
242 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
243 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
244 
245 		/* Prepare storage */
246 		message.resize(length);
247 
248 		/* Get error log */
249 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
250 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
251 
252 		/* Log */
253 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
254 											<< &message[0] << "\nShader source\n"
255 											<< shader_code << tcu::TestLog::EndMessage;
256 
257 		TCU_FAIL("Failed to compile shader");
258 	}
259 }
260 
261 /** Attach shaders and link program
262  *
263  **/
link() const264 void Utils::programInfo::link() const
265 {
266 	/* GL entry points */
267 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
268 
269 	/* Link status */
270 	glw::GLint status = GL_FALSE;
271 
272 	/* Attach shaders */
273 	if (0 != m_compute_shader_id)
274 	{
275 		gl.attachShader(m_program_object_id, m_compute_shader_id);
276 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
277 	}
278 
279 	if (0 != m_fragment_shader_id)
280 	{
281 		gl.attachShader(m_program_object_id, m_fragment_shader_id);
282 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
283 	}
284 
285 	if (0 != m_geometry_shader_id)
286 	{
287 		gl.attachShader(m_program_object_id, m_geometry_shader_id);
288 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
289 	}
290 
291 	if (0 != m_tesselation_control_shader_id)
292 	{
293 		gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
294 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
295 	}
296 
297 	if (0 != m_tesselation_evaluation_shader_id)
298 	{
299 		gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
300 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
301 	}
302 
303 	if (0 != m_vertex_shader_id)
304 	{
305 		gl.attachShader(m_program_object_id, m_vertex_shader_id);
306 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
307 	}
308 
309 	/* Link */
310 	gl.linkProgram(m_program_object_id);
311 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
312 
313 	/* Get link status */
314 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
315 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
316 
317 	/* Log link error */
318 	if (GL_TRUE != status)
319 	{
320 		glw::GLint				 length = 0;
321 		std::vector<glw::GLchar> message;
322 
323 		/* Get error log length */
324 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
325 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
326 
327 		message.resize(length);
328 
329 		/* Get error log */
330 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
331 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
332 
333 		/* Log */
334 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
335 											<< &message[0] << tcu::TestLog::EndMessage;
336 
337 		TCU_FAIL("Failed to link program");
338 	}
339 }
340 
341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision
342  *  matrix types.
343  *
344  *  @param type Variable type to return base type for.
345  *
346  *  @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized.
347  **/
getBaseVariableType(_variable_type type)348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type)
349 {
350 	_variable_type result = VARIABLE_TYPE_UNKNOWN;
351 
352 	switch (type)
353 	{
354 	case VARIABLE_TYPE_BOOL:
355 	{
356 		result = VARIABLE_TYPE_BOOL;
357 
358 		break;
359 	}
360 
361 	case VARIABLE_TYPE_DOUBLE:
362 	case VARIABLE_TYPE_DMAT2:
363 	case VARIABLE_TYPE_DMAT2X3:
364 	case VARIABLE_TYPE_DMAT2X4:
365 	case VARIABLE_TYPE_DMAT3:
366 	case VARIABLE_TYPE_DMAT3X2:
367 	case VARIABLE_TYPE_DMAT3X4:
368 	case VARIABLE_TYPE_DMAT4:
369 	case VARIABLE_TYPE_DMAT4X2:
370 	case VARIABLE_TYPE_DMAT4X3:
371 	case VARIABLE_TYPE_DVEC2:
372 	case VARIABLE_TYPE_DVEC3:
373 	case VARIABLE_TYPE_DVEC4:
374 	{
375 		result = VARIABLE_TYPE_DOUBLE;
376 
377 		break;
378 	}
379 
380 	case VARIABLE_TYPE_INT:
381 	case VARIABLE_TYPE_IVEC2:
382 	case VARIABLE_TYPE_IVEC3:
383 	case VARIABLE_TYPE_IVEC4:
384 	{
385 		result = VARIABLE_TYPE_INT;
386 
387 		break;
388 	}
389 
390 	case VARIABLE_TYPE_UINT:
391 	case VARIABLE_TYPE_UVEC2:
392 	case VARIABLE_TYPE_UVEC3:
393 	case VARIABLE_TYPE_UVEC4:
394 	{
395 		result = VARIABLE_TYPE_UINT;
396 
397 		break;
398 	}
399 
400 	case VARIABLE_TYPE_FLOAT:
401 	case VARIABLE_TYPE_MAT2:
402 	case VARIABLE_TYPE_MAT2X3:
403 	case VARIABLE_TYPE_MAT2X4:
404 	case VARIABLE_TYPE_MAT3:
405 	case VARIABLE_TYPE_MAT3X2:
406 	case VARIABLE_TYPE_MAT3X4:
407 	case VARIABLE_TYPE_MAT4:
408 	case VARIABLE_TYPE_MAT4X2:
409 	case VARIABLE_TYPE_MAT4X3:
410 	case VARIABLE_TYPE_VEC2:
411 	case VARIABLE_TYPE_VEC3:
412 	case VARIABLE_TYPE_VEC4:
413 	{
414 		result = VARIABLE_TYPE_FLOAT;
415 
416 		break;
417 	}
418 
419 	default:
420 	{
421 		TCU_FAIL("Unrecognized variable type");
422 	}
423 	} /* switch (type) */
424 
425 	return result;
426 }
427 
428 /** Returns size (in bytes) of a single component of a base variable type.
429  *
430  *  @param type Base variable type to use for the query.
431  *
432  *  @return Requested value or 0 if @param type was not recognized.
433  **/
getBaseVariableTypeComponentSize(_variable_type type)434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type)
435 {
436 	unsigned int result = 0;
437 
438 	switch (type)
439 	{
440 	case VARIABLE_TYPE_BOOL:
441 		result = sizeof(bool);
442 		break;
443 	case VARIABLE_TYPE_DOUBLE:
444 		result = sizeof(double);
445 		break;
446 	case VARIABLE_TYPE_FLOAT:
447 		result = sizeof(float);
448 		break;
449 	case VARIABLE_TYPE_INT:
450 		result = sizeof(int);
451 		break;
452 	case VARIABLE_TYPE_UINT:
453 		result = sizeof(unsigned int);
454 		break;
455 
456 	default:
457 	{
458 		TCU_FAIL("Unrecognized variable type");
459 	}
460 	} /* switch (type) */
461 
462 	return result;
463 }
464 
465 /** Returns component, corresponding to user-specified index
466  *  (eg. index:0 corresponds to 'x', index:1 corresponds to 'y',
467  *  and so on.
468  *
469  *  @param index Component index.
470  *
471  *  @return As per description.
472  **/
getComponentAtIndex(unsigned int index)473 unsigned char Utils::getComponentAtIndex(unsigned int index)
474 {
475 	unsigned char result = '?';
476 
477 	switch (index)
478 	{
479 	case 0:
480 		result = 'x';
481 		break;
482 	case 1:
483 		result = 'y';
484 		break;
485 	case 2:
486 		result = 'z';
487 		break;
488 	case 3:
489 		result = 'w';
490 		break;
491 
492 	default:
493 	{
494 		TCU_FAIL("Unrecognized component index");
495 	}
496 	}
497 
498 	return result;
499 }
500 
501 /** Get _variable_type representing double-precision type with given dimmensions
502  *
503  * @param n_columns Number of columns
504  * @param n_row     Number of rows
505  *
506  * @return Corresponding _variable_type
507  **/
getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
509 {
510 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
511 
512 	static const _variable_type types[4][4] = {
513 		{ VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 },
514 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 },
515 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 },
516 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 }
517 	};
518 
519 	type = types[n_columns - 1][n_rows - 1];
520 
521 	return type;
522 }
523 
524 /** Returns a single-precision equivalent of a double-precision floating-point variable
525  *  type.
526  *
527  *  @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
528  *              are accepted.
529  *
530  *  @return Requested GLSL type.
531  **/
getFPVariableTypeStringForVariableType(_variable_type type)532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
533 {
534 	std::string result = "[?]";
535 
536 	switch (type)
537 	{
538 	case VARIABLE_TYPE_DOUBLE:
539 		result = "float";
540 		break;
541 	case VARIABLE_TYPE_DMAT2:
542 		result = "mat2";
543 		break;
544 	case VARIABLE_TYPE_DMAT2X3:
545 		result = "mat2x3";
546 		break;
547 	case VARIABLE_TYPE_DMAT2X4:
548 		result = "mat2x4";
549 		break;
550 	case VARIABLE_TYPE_DMAT3:
551 		result = "mat3";
552 		break;
553 	case VARIABLE_TYPE_DMAT3X2:
554 		result = "mat3x2";
555 		break;
556 	case VARIABLE_TYPE_DMAT3X4:
557 		result = "mat3x4";
558 		break;
559 	case VARIABLE_TYPE_DMAT4:
560 		result = "mat4";
561 		break;
562 	case VARIABLE_TYPE_DMAT4X2:
563 		result = "mat4x2";
564 		break;
565 	case VARIABLE_TYPE_DMAT4X3:
566 		result = "mat4x3";
567 		break;
568 	case VARIABLE_TYPE_DVEC2:
569 		result = "vec2";
570 		break;
571 	case VARIABLE_TYPE_DVEC3:
572 		result = "vec3";
573 		break;
574 	case VARIABLE_TYPE_DVEC4:
575 		result = "vec4";
576 		break;
577 
578 	default:
579 	{
580 		TCU_FAIL("Unrecognized variable type");
581 	}
582 	} /* switch (type) */
583 
584 	return result;
585 }
586 
587 /** Returns GL data type enum corresponding to user-provided base variable type.
588  *
589  *  @param type Base variable type to return corresponding GLenum value for.
590  *
591  *  @return Corresponding GLenum value or GL_NONE if the input value was not
592  *          recognized.
593  **/
getGLDataTypeOfBaseVariableType(_variable_type type)594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
595 {
596 	glw::GLenum result = GL_NONE;
597 
598 	switch (type)
599 	{
600 	case VARIABLE_TYPE_BOOL:
601 		result = GL_BOOL;
602 		break;
603 	case VARIABLE_TYPE_DOUBLE:
604 		result = GL_DOUBLE;
605 		break;
606 	case VARIABLE_TYPE_FLOAT:
607 		result = GL_FLOAT;
608 		break;
609 	case VARIABLE_TYPE_INT:
610 		result = GL_INT;
611 		break;
612 	case VARIABLE_TYPE_UINT:
613 		result = GL_UNSIGNED_INT;
614 		break;
615 
616 	default:
617 	{
618 		TCU_FAIL("Unrecognized variable type");
619 	}
620 	}
621 
622 	return result;
623 }
624 
625 /** Return GLenum representing given <type>
626  *
627  * @param type Type of variable
628  *
629  * @return GL enumeration
630  **/
getGLDataTypeOfVariableType(_variable_type type)631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
632 {
633 	glw::GLenum result = GL_NONE;
634 
635 	switch (type)
636 	{
637 	case VARIABLE_TYPE_BOOL:
638 		result = GL_BOOL;
639 		break;
640 	case VARIABLE_TYPE_DOUBLE:
641 		result = GL_DOUBLE;
642 		break;
643 	case VARIABLE_TYPE_DMAT2:
644 		result = GL_DOUBLE_MAT2;
645 		break;
646 	case VARIABLE_TYPE_DMAT2X3:
647 		result = GL_DOUBLE_MAT2x3;
648 		break;
649 	case VARIABLE_TYPE_DMAT2X4:
650 		result = GL_DOUBLE_MAT2x4;
651 		break;
652 	case VARIABLE_TYPE_DMAT3:
653 		result = GL_DOUBLE_MAT3;
654 		break;
655 	case VARIABLE_TYPE_DMAT3X2:
656 		result = GL_DOUBLE_MAT3x2;
657 		break;
658 	case VARIABLE_TYPE_DMAT3X4:
659 		result = GL_DOUBLE_MAT3x4;
660 		break;
661 	case VARIABLE_TYPE_DMAT4:
662 		result = GL_DOUBLE_MAT4;
663 		break;
664 	case VARIABLE_TYPE_DMAT4X2:
665 		result = GL_DOUBLE_MAT4x2;
666 		break;
667 	case VARIABLE_TYPE_DMAT4X3:
668 		result = GL_DOUBLE_MAT4x3;
669 		break;
670 	case VARIABLE_TYPE_DVEC2:
671 		result = GL_DOUBLE_VEC2;
672 		break;
673 	case VARIABLE_TYPE_DVEC3:
674 		result = GL_DOUBLE_VEC3;
675 		break;
676 	case VARIABLE_TYPE_DVEC4:
677 		result = GL_DOUBLE_VEC4;
678 		break;
679 	case VARIABLE_TYPE_FLOAT:
680 		result = GL_FLOAT;
681 		break;
682 	case VARIABLE_TYPE_INT:
683 		result = GL_INT;
684 		break;
685 	case VARIABLE_TYPE_IVEC2:
686 		result = GL_INT_VEC2;
687 		break;
688 	case VARIABLE_TYPE_IVEC3:
689 		result = GL_INT_VEC3;
690 		break;
691 	case VARIABLE_TYPE_IVEC4:
692 		result = GL_INT_VEC4;
693 		break;
694 	case VARIABLE_TYPE_MAT2:
695 		result = GL_FLOAT_MAT2;
696 		break;
697 	case VARIABLE_TYPE_MAT2X3:
698 		result = GL_FLOAT_MAT2x3;
699 		break;
700 	case VARIABLE_TYPE_MAT2X4:
701 		result = GL_FLOAT_MAT2x4;
702 		break;
703 	case VARIABLE_TYPE_MAT3:
704 		result = GL_FLOAT_MAT3;
705 		break;
706 	case VARIABLE_TYPE_MAT3X2:
707 		result = GL_FLOAT_MAT3x2;
708 		break;
709 	case VARIABLE_TYPE_MAT3X4:
710 		result = GL_FLOAT_MAT3x4;
711 		break;
712 	case VARIABLE_TYPE_MAT4:
713 		result = GL_FLOAT_MAT4;
714 		break;
715 	case VARIABLE_TYPE_MAT4X2:
716 		result = GL_FLOAT_MAT4x2;
717 		break;
718 	case VARIABLE_TYPE_MAT4X3:
719 		result = GL_FLOAT_MAT4x3;
720 		break;
721 	case VARIABLE_TYPE_UINT:
722 		result = GL_UNSIGNED_INT;
723 		break;
724 	case VARIABLE_TYPE_UVEC2:
725 		result = GL_UNSIGNED_INT_VEC2;
726 		break;
727 	case VARIABLE_TYPE_UVEC3:
728 		result = GL_UNSIGNED_INT_VEC3;
729 		break;
730 	case VARIABLE_TYPE_UVEC4:
731 		result = GL_UNSIGNED_INT_VEC4;
732 		break;
733 	case VARIABLE_TYPE_VEC2:
734 		result = GL_FLOAT_VEC2;
735 		break;
736 	case VARIABLE_TYPE_VEC3:
737 		result = GL_FLOAT_VEC3;
738 		break;
739 	case VARIABLE_TYPE_VEC4:
740 		result = GL_FLOAT_VEC4;
741 		break;
742 
743 	default:
744 	{
745 		TCU_FAIL("Unrecognized variable type");
746 	}
747 	}
748 
749 	return result;
750 }
751 
752 /** Get _variable_type representing integer type with given dimmensions
753  *
754  * @param n_columns Number of columns
755  * @param n_row     Number of rows
756  *
757  * @return Corresponding _variable_type
758  **/
getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
760 {
761 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
762 
763 	static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
764 											 VARIABLE_TYPE_IVEC4 };
765 
766 	if (1 != n_columns)
767 	{
768 		TCU_FAIL("Not implemented");
769 	}
770 	else
771 	{
772 		type = types[n_rows - 1];
773 	}
774 
775 	return type;
776 }
777 
778 /** Returns te number of components that variables defined with user-specified type
779  *  support. For matrix types, total amount of values accessible for the type will be
780  *  returned.
781  *
782  *  @param type Variable type to return the described vale for.
783  *
784  *  @return As per description or 0 if @param type was not recognized.
785  */
getNumberOfComponentsForVariableType(_variable_type type)786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
787 {
788 	unsigned int result = 0;
789 
790 	switch (type)
791 	{
792 	case VARIABLE_TYPE_BOOL:
793 	case VARIABLE_TYPE_DOUBLE:
794 	case VARIABLE_TYPE_FLOAT:
795 	case VARIABLE_TYPE_INT:
796 	case VARIABLE_TYPE_UINT:
797 	{
798 		result = 1;
799 
800 		break;
801 	}
802 
803 	case VARIABLE_TYPE_DVEC2:
804 	case VARIABLE_TYPE_IVEC2:
805 	case VARIABLE_TYPE_UVEC2:
806 	case VARIABLE_TYPE_VEC2:
807 	{
808 		result = 2;
809 
810 		break;
811 	}
812 
813 	case VARIABLE_TYPE_DVEC3:
814 	case VARIABLE_TYPE_IVEC3:
815 	case VARIABLE_TYPE_UVEC3:
816 	case VARIABLE_TYPE_VEC3:
817 	{
818 		result = 3;
819 
820 		break;
821 	}
822 
823 	case VARIABLE_TYPE_DVEC4:
824 	case VARIABLE_TYPE_IVEC4:
825 	case VARIABLE_TYPE_UVEC4:
826 	case VARIABLE_TYPE_VEC4:
827 	{
828 		result = 4;
829 
830 		break;
831 	}
832 
833 	case VARIABLE_TYPE_DMAT2:
834 	case VARIABLE_TYPE_MAT2:
835 	{
836 		result = 2 * 2;
837 
838 		break;
839 	}
840 
841 	case VARIABLE_TYPE_DMAT2X3:
842 	case VARIABLE_TYPE_DMAT3X2:
843 	case VARIABLE_TYPE_MAT2X3:
844 	case VARIABLE_TYPE_MAT3X2:
845 	{
846 		result = 2 * 3;
847 
848 		break;
849 	}
850 
851 	case VARIABLE_TYPE_DMAT2X4:
852 	case VARIABLE_TYPE_DMAT4X2:
853 	case VARIABLE_TYPE_MAT2X4:
854 	case VARIABLE_TYPE_MAT4X2:
855 	{
856 		result = 2 * 4;
857 
858 		break;
859 	}
860 
861 	case VARIABLE_TYPE_DMAT3:
862 	case VARIABLE_TYPE_MAT3:
863 	{
864 		result = 3 * 3;
865 
866 		break;
867 	}
868 
869 	case VARIABLE_TYPE_DMAT3X4:
870 	case VARIABLE_TYPE_DMAT4X3:
871 	case VARIABLE_TYPE_MAT3X4:
872 	case VARIABLE_TYPE_MAT4X3:
873 	{
874 		result = 3 * 4;
875 
876 		break;
877 	}
878 
879 	case VARIABLE_TYPE_DMAT4:
880 	case VARIABLE_TYPE_MAT4:
881 	{
882 		result = 4 * 4;
883 
884 		break;
885 	}
886 
887 	default:
888 	{
889 		TCU_FAIL("Unrecognized type");
890 	}
891 	} /* switch (type) */
892 
893 	return result;
894 }
895 
896 /** Returns number of columns user-specified matrix variable type describes.
897  *
898  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
899  *              values are valid.
900  *
901  *  @return As per description.
902  **/
getNumberOfColumnsForVariableType(_variable_type type)903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
904 {
905 	unsigned int result = 0;
906 
907 	switch (type)
908 	{
909 	case VARIABLE_TYPE_BOOL:
910 	case VARIABLE_TYPE_DOUBLE:
911 	case VARIABLE_TYPE_FLOAT:
912 	case VARIABLE_TYPE_INT:
913 	case VARIABLE_TYPE_UINT:
914 	case VARIABLE_TYPE_DVEC2:
915 	case VARIABLE_TYPE_IVEC2:
916 	case VARIABLE_TYPE_UVEC2:
917 	case VARIABLE_TYPE_VEC2:
918 	case VARIABLE_TYPE_DVEC3:
919 	case VARIABLE_TYPE_IVEC3:
920 	case VARIABLE_TYPE_UVEC3:
921 	case VARIABLE_TYPE_VEC3:
922 	case VARIABLE_TYPE_DVEC4:
923 	case VARIABLE_TYPE_IVEC4:
924 	case VARIABLE_TYPE_UVEC4:
925 	case VARIABLE_TYPE_VEC4:
926 	{
927 		result = 1;
928 
929 		break;
930 	}
931 
932 	case VARIABLE_TYPE_DMAT2:
933 	case VARIABLE_TYPE_DMAT2X3:
934 	case VARIABLE_TYPE_DMAT2X4:
935 	case VARIABLE_TYPE_MAT2:
936 	case VARIABLE_TYPE_MAT2X3:
937 	case VARIABLE_TYPE_MAT2X4:
938 	{
939 		result = 2;
940 
941 		break;
942 	}
943 
944 	case VARIABLE_TYPE_DMAT3:
945 	case VARIABLE_TYPE_DMAT3X2:
946 	case VARIABLE_TYPE_DMAT3X4:
947 	case VARIABLE_TYPE_MAT3:
948 	case VARIABLE_TYPE_MAT3X2:
949 	case VARIABLE_TYPE_MAT3X4:
950 	{
951 		result = 3;
952 
953 		break;
954 	}
955 
956 	case VARIABLE_TYPE_DMAT4:
957 	case VARIABLE_TYPE_DMAT4X2:
958 	case VARIABLE_TYPE_DMAT4X3:
959 	case VARIABLE_TYPE_MAT4:
960 	case VARIABLE_TYPE_MAT4X2:
961 	case VARIABLE_TYPE_MAT4X3:
962 	{
963 		result = 4;
964 
965 		break;
966 	}
967 
968 	default:
969 	{
970 		TCU_FAIL("Unrecognized type");
971 	}
972 	} /* switch (type) */
973 
974 	return result;
975 }
976 
977 /** Returns maximum number of uniform locations taken by user-specified double-precision
978  *  variable type.
979  *
980  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
981  *
982  *  @return As per description.
983  **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
985 {
986 	unsigned int result = 0;
987 
988 	switch (type)
989 	{
990 	case VARIABLE_TYPE_DOUBLE:
991 		result = 1;
992 		break;
993 	case VARIABLE_TYPE_DVEC2:
994 		result = 1;
995 		break;
996 	case VARIABLE_TYPE_DVEC3:
997 		result = 2;
998 		break;
999 	case VARIABLE_TYPE_DVEC4:
1000 		result = 2;
1001 		break;
1002 	case VARIABLE_TYPE_DMAT2:
1003 		result = 2;
1004 		break;
1005 	case VARIABLE_TYPE_DMAT2X3:
1006 		result = 6;
1007 		break;
1008 	case VARIABLE_TYPE_DMAT2X4:
1009 		result = 8;
1010 		break;
1011 	case VARIABLE_TYPE_DMAT3:
1012 		result = 6;
1013 		break;
1014 	case VARIABLE_TYPE_DMAT3X2:
1015 		result = 4;
1016 		break;
1017 	case VARIABLE_TYPE_DMAT3X4:
1018 		result = 8;
1019 		break;
1020 	case VARIABLE_TYPE_DMAT4:
1021 		result = 8;
1022 		break;
1023 	case VARIABLE_TYPE_DMAT4X2:
1024 		result = 4;
1025 		break;
1026 	case VARIABLE_TYPE_DMAT4X3:
1027 		result = 6;
1028 		break;
1029 
1030 	default:
1031 	{
1032 		TCU_FAIL("Unrecognized type");
1033 	}
1034 	} /* switch (type) */
1035 
1036 	return result;
1037 }
1038 
1039 /** Get number of rows for given variable type
1040  *
1041  * @param type Type of variable
1042  *
1043  * @return Number of rows
1044  **/
getNumberOfRowsForVariableType(_variable_type type)1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1046 {
1047 	unsigned int result = 0;
1048 
1049 	switch (type)
1050 	{
1051 	case VARIABLE_TYPE_BOOL:
1052 	case VARIABLE_TYPE_DOUBLE:
1053 	case VARIABLE_TYPE_FLOAT:
1054 	case VARIABLE_TYPE_INT:
1055 	case VARIABLE_TYPE_UINT:
1056 	{
1057 		result = 1;
1058 
1059 		break;
1060 	}
1061 
1062 	case VARIABLE_TYPE_DVEC2:
1063 	case VARIABLE_TYPE_IVEC2:
1064 	case VARIABLE_TYPE_UVEC2:
1065 	case VARIABLE_TYPE_VEC2:
1066 	case VARIABLE_TYPE_DMAT2:
1067 	case VARIABLE_TYPE_DMAT3X2:
1068 	case VARIABLE_TYPE_DMAT4X2:
1069 	case VARIABLE_TYPE_MAT2:
1070 	case VARIABLE_TYPE_MAT3X2:
1071 	case VARIABLE_TYPE_MAT4X2:
1072 	{
1073 		result = 2;
1074 
1075 		break;
1076 	}
1077 
1078 	case VARIABLE_TYPE_DVEC3:
1079 	case VARIABLE_TYPE_IVEC3:
1080 	case VARIABLE_TYPE_UVEC3:
1081 	case VARIABLE_TYPE_VEC3:
1082 	case VARIABLE_TYPE_DMAT2X3:
1083 	case VARIABLE_TYPE_DMAT3:
1084 	case VARIABLE_TYPE_DMAT4X3:
1085 	case VARIABLE_TYPE_MAT2X3:
1086 	case VARIABLE_TYPE_MAT3:
1087 	case VARIABLE_TYPE_MAT4X3:
1088 	{
1089 		result = 3;
1090 
1091 		break;
1092 	}
1093 
1094 	case VARIABLE_TYPE_DVEC4:
1095 	case VARIABLE_TYPE_IVEC4:
1096 	case VARIABLE_TYPE_UVEC4:
1097 	case VARIABLE_TYPE_VEC4:
1098 	case VARIABLE_TYPE_DMAT2X4:
1099 	case VARIABLE_TYPE_DMAT3X4:
1100 	case VARIABLE_TYPE_DMAT4:
1101 	case VARIABLE_TYPE_MAT2X4:
1102 	case VARIABLE_TYPE_MAT3X4:
1103 	case VARIABLE_TYPE_MAT4:
1104 	{
1105 		result = 4;
1106 
1107 		break;
1108 	}
1109 
1110 	default:
1111 	{
1112 		TCU_FAIL("Unrecognized type");
1113 	}
1114 	} /* switch (type) */
1115 
1116 	return result;
1117 }
1118 
1119 /** Returns variable type of a matrix constructed by multiplying two matrices.
1120  *
1121  *  @param type_matrix_a L-side matrix type.
1122  *  @param type_matrix_b R-side matrix type.
1123  *
1124  *  @return As per description.
1125  **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a, _variable_type type_matrix_b)1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1127 																	 _variable_type type_matrix_b)
1128 {
1129 	const unsigned int	n_a_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1130 	const unsigned int	n_a_components   = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1131 	const unsigned int	n_a_rows		   = n_a_components / n_a_columns;
1132 	const unsigned int	n_b_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1133 	const unsigned int	n_result_columns = n_b_columns;
1134 	const unsigned int	n_result_rows	= n_a_rows;
1135 	Utils::_variable_type result;
1136 
1137 	switch (n_result_columns)
1138 	{
1139 	case 2:
1140 	{
1141 		switch (n_result_rows)
1142 		{
1143 		case 2:
1144 			result = VARIABLE_TYPE_DMAT2;
1145 			break;
1146 		case 3:
1147 			result = VARIABLE_TYPE_DMAT2X3;
1148 			break;
1149 		case 4:
1150 			result = VARIABLE_TYPE_DMAT2X4;
1151 			break;
1152 
1153 		default:
1154 		{
1155 			TCU_FAIL("Unrecognized amount of rows in result variable");
1156 		}
1157 		} /* switch (n_result_rows) */
1158 
1159 		break;
1160 	} /* case 2: */
1161 
1162 	case 3:
1163 	{
1164 		switch (n_result_rows)
1165 		{
1166 		case 2:
1167 			result = VARIABLE_TYPE_DMAT3X2;
1168 			break;
1169 		case 3:
1170 			result = VARIABLE_TYPE_DMAT3;
1171 			break;
1172 		case 4:
1173 			result = VARIABLE_TYPE_DMAT3X4;
1174 			break;
1175 
1176 		default:
1177 		{
1178 			TCU_FAIL("Unrecognized amount of rows in result variable");
1179 		}
1180 		} /* switch (n_result_rows) */
1181 
1182 		break;
1183 	} /* case 3: */
1184 
1185 	case 4:
1186 	{
1187 		switch (n_result_rows)
1188 		{
1189 		case 2:
1190 			result = VARIABLE_TYPE_DMAT4X2;
1191 			break;
1192 		case 3:
1193 			result = VARIABLE_TYPE_DMAT4X3;
1194 			break;
1195 		case 4:
1196 			result = VARIABLE_TYPE_DMAT4;
1197 			break;
1198 
1199 		default:
1200 		{
1201 			TCU_FAIL("Unrecognized amount of rows in result variable");
1202 		}
1203 		} /* switch (n_result_rows) */
1204 
1205 		break;
1206 	} /* case 4: */
1207 
1208 	default:
1209 	{
1210 		TCU_FAIL("Unrecognized amount of columns in result variable");
1211 	}
1212 	} /* switch (n_result_columns) */
1213 
1214 	/* Done */
1215 	return result;
1216 }
1217 
1218 /** Returns a string holding the value represented by user-provided variable, for which
1219  *  the data are represented in @param type variable type.
1220  *
1221  *  @return As per description.
1222  **/
getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)
1224 {
1225 	std::stringstream result_sstream;
1226 
1227 	switch (type)
1228 	{
1229 	case VARIABLE_TYPE_BOOL:
1230 		result_sstream << *((bool*)data_ptr);
1231 		break;
1232 	case VARIABLE_TYPE_DOUBLE:
1233 		result_sstream << *((double*)data_ptr);
1234 		break;
1235 	case VARIABLE_TYPE_FLOAT:
1236 		result_sstream << *((float*)data_ptr);
1237 		break;
1238 	case VARIABLE_TYPE_INT:
1239 		result_sstream << *((int*)data_ptr);
1240 		break;
1241 	case VARIABLE_TYPE_UINT:
1242 		result_sstream << *((unsigned int*)data_ptr);
1243 		break;
1244 
1245 	default:
1246 	{
1247 		TCU_FAIL("Unrecognized variable type requested");
1248 	}
1249 	} /* switch (type) */
1250 
1251 	return result_sstream.str();
1252 }
1253 
1254 /** Returns variable type of a transposed matrix of user-specified variable type.
1255  *
1256  *  @param type Variable type of the matrix to be transposed.
1257  *
1258  *  @return Transposed matrix variable type.
1259  **/
getTransposedMatrixVariableType(Utils::_variable_type type)1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1261 {
1262 	Utils::_variable_type result;
1263 
1264 	switch (type)
1265 	{
1266 	case VARIABLE_TYPE_DMAT2:
1267 		result = VARIABLE_TYPE_DMAT2;
1268 		break;
1269 	case VARIABLE_TYPE_DMAT2X3:
1270 		result = VARIABLE_TYPE_DMAT3X2;
1271 		break;
1272 	case VARIABLE_TYPE_DMAT2X4:
1273 		result = VARIABLE_TYPE_DMAT4X2;
1274 		break;
1275 	case VARIABLE_TYPE_DMAT3:
1276 		result = VARIABLE_TYPE_DMAT3;
1277 		break;
1278 	case VARIABLE_TYPE_DMAT3X2:
1279 		result = VARIABLE_TYPE_DMAT2X3;
1280 		break;
1281 	case VARIABLE_TYPE_DMAT3X4:
1282 		result = VARIABLE_TYPE_DMAT4X3;
1283 		break;
1284 	case VARIABLE_TYPE_DMAT4:
1285 		result = VARIABLE_TYPE_DMAT4;
1286 		break;
1287 	case VARIABLE_TYPE_DMAT4X2:
1288 		result = VARIABLE_TYPE_DMAT2X4;
1289 		break;
1290 	case VARIABLE_TYPE_DMAT4X3:
1291 		result = VARIABLE_TYPE_DMAT3X4;
1292 		break;
1293 
1294 	default:
1295 	{
1296 		TCU_FAIL("Unrecognized double-precision matrix variable type.");
1297 	}
1298 	} /* switch (type) */
1299 
1300 	return result;
1301 }
1302 
1303 /** Get _variable_type representing unsigned integer type with given dimmensions
1304  *
1305  * @param n_columns Number of columns
1306  * @param n_row     Number of rows
1307  *
1308  * @return Corresponding _variable_type
1309  **/
getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1311 {
1312 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1313 
1314 	static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1315 											 VARIABLE_TYPE_UVEC4 };
1316 
1317 	if (1 != n_columns)
1318 	{
1319 		TCU_FAIL("Not implemented");
1320 	}
1321 	else
1322 	{
1323 		type = types[n_rows - 1];
1324 	}
1325 
1326 	return type;
1327 }
1328 
1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1330  *  variable type.
1331  *
1332  *  @param type Variable type to use for the query.
1333  *
1334  *  @return Requested GLSL keyword or [?] if @param type was not recognized.
1335  **/
getVariableTypeString(_variable_type type)1336 std::string Utils::getVariableTypeString(_variable_type type)
1337 {
1338 	std::string result = "[?]";
1339 
1340 	switch (type)
1341 	{
1342 	case VARIABLE_TYPE_BOOL:
1343 		result = "bool";
1344 		break;
1345 	case VARIABLE_TYPE_BVEC2:
1346 		result = "bvec2";
1347 		break;
1348 	case VARIABLE_TYPE_BVEC3:
1349 		result = "bvec3";
1350 		break;
1351 	case VARIABLE_TYPE_BVEC4:
1352 		result = "bvec4";
1353 		break;
1354 	case VARIABLE_TYPE_DOUBLE:
1355 		result = "double";
1356 		break;
1357 	case VARIABLE_TYPE_DMAT2:
1358 		result = "dmat2";
1359 		break;
1360 	case VARIABLE_TYPE_DMAT2X3:
1361 		result = "dmat2x3";
1362 		break;
1363 	case VARIABLE_TYPE_DMAT2X4:
1364 		result = "dmat2x4";
1365 		break;
1366 	case VARIABLE_TYPE_DMAT3:
1367 		result = "dmat3";
1368 		break;
1369 	case VARIABLE_TYPE_DMAT3X2:
1370 		result = "dmat3x2";
1371 		break;
1372 	case VARIABLE_TYPE_DMAT3X4:
1373 		result = "dmat3x4";
1374 		break;
1375 	case VARIABLE_TYPE_DMAT4:
1376 		result = "dmat4";
1377 		break;
1378 	case VARIABLE_TYPE_DMAT4X2:
1379 		result = "dmat4x2";
1380 		break;
1381 	case VARIABLE_TYPE_DMAT4X3:
1382 		result = "dmat4x3";
1383 		break;
1384 	case VARIABLE_TYPE_DVEC2:
1385 		result = "dvec2";
1386 		break;
1387 	case VARIABLE_TYPE_DVEC3:
1388 		result = "dvec3";
1389 		break;
1390 	case VARIABLE_TYPE_DVEC4:
1391 		result = "dvec4";
1392 		break;
1393 	case VARIABLE_TYPE_FLOAT:
1394 		result = "float";
1395 		break;
1396 	case VARIABLE_TYPE_INT:
1397 		result = "int";
1398 		break;
1399 	case VARIABLE_TYPE_IVEC2:
1400 		result = "ivec2";
1401 		break;
1402 	case VARIABLE_TYPE_IVEC3:
1403 		result = "ivec3";
1404 		break;
1405 	case VARIABLE_TYPE_IVEC4:
1406 		result = "ivec4";
1407 		break;
1408 	case VARIABLE_TYPE_MAT2:
1409 		result = "mat2";
1410 		break;
1411 	case VARIABLE_TYPE_MAT2X3:
1412 		result = "mat2x3";
1413 		break;
1414 	case VARIABLE_TYPE_MAT2X4:
1415 		result = "mat2x4";
1416 		break;
1417 	case VARIABLE_TYPE_MAT3:
1418 		result = "mat3";
1419 		break;
1420 	case VARIABLE_TYPE_MAT3X2:
1421 		result = "mat3x2";
1422 		break;
1423 	case VARIABLE_TYPE_MAT3X4:
1424 		result = "mat3x4";
1425 		break;
1426 	case VARIABLE_TYPE_MAT4:
1427 		result = "mat4";
1428 		break;
1429 	case VARIABLE_TYPE_MAT4X2:
1430 		result = "mat4x2";
1431 		break;
1432 	case VARIABLE_TYPE_MAT4X3:
1433 		result = "mat4x3";
1434 		break;
1435 	case VARIABLE_TYPE_UINT:
1436 		result = "uint";
1437 		break;
1438 	case VARIABLE_TYPE_UVEC2:
1439 		result = "uvec2";
1440 		break;
1441 	case VARIABLE_TYPE_UVEC3:
1442 		result = "uvec3";
1443 		break;
1444 	case VARIABLE_TYPE_UVEC4:
1445 		result = "uvec4";
1446 		break;
1447 	case VARIABLE_TYPE_VEC2:
1448 		result = "vec2";
1449 		break;
1450 	case VARIABLE_TYPE_VEC3:
1451 		result = "vec3";
1452 		break;
1453 	case VARIABLE_TYPE_VEC4:
1454 		result = "vec4";
1455 		break;
1456 
1457 	default:
1458 	{
1459 		TCU_FAIL("Unrecognized variable type");
1460 	}
1461 	} /* switch (type) */
1462 
1463 	return result;
1464 }
1465 
1466 /** Check if GL context meets version requirements
1467  *
1468  * @param gl             Functions
1469  * @param required_major Minimum required MAJOR_VERSION
1470  * @param required_minor Minimum required MINOR_VERSION
1471  *
1472  * @return true if GL context version is at least as requested, false otherwise
1473  **/
isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
1475 {
1476 	glw::GLint major = 0;
1477 	glw::GLint minor = 0;
1478 
1479 	gl.getIntegerv(GL_MAJOR_VERSION, &major);
1480 	gl.getIntegerv(GL_MINOR_VERSION, &minor);
1481 
1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483 
1484 	if (major > required_major)
1485 	{
1486 		/* Major is higher than required one */
1487 		return true;
1488 	}
1489 	else if (major == required_major)
1490 	{
1491 		if (minor >= required_minor)
1492 		{
1493 			/* Major is equal to required one */
1494 			/* Minor is higher than or equal to required one */
1495 			return true;
1496 		}
1497 		else
1498 		{
1499 			/* Major is equal to required one */
1500 			/* Minor is lower than required one */
1501 			return false;
1502 		}
1503 	}
1504 	else
1505 	{
1506 		/* Major is lower than required one */
1507 		return false;
1508 	}
1509 }
1510 
1511 /** Tells whether user-specified variable type corresponds to a matrix type.
1512  *
1513  *  @param type Variable type to use for the query.
1514  *
1515  *  @return true if the variable type describes a matrix, false otherwise.
1516  **/
isMatrixVariableType(_variable_type type)1517 bool Utils::isMatrixVariableType(_variable_type type)
1518 {
1519 	return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1520 			type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1521 			type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1522 			type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1523 			type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1524 			type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1525 }
1526 
1527 /** Tells whether user-specified variable type is scalar.
1528  *
1529  *  @return true if @param type is a scalar variable type, false otherwise.
1530  **/
isScalarVariableType(_variable_type type)1531 bool Utils::isScalarVariableType(_variable_type type)
1532 {
1533 	bool result = false;
1534 
1535 	switch (type)
1536 	{
1537 	case VARIABLE_TYPE_BOOL:
1538 		result = true;
1539 		break;
1540 	case VARIABLE_TYPE_DOUBLE:
1541 		result = true;
1542 		break;
1543 	case VARIABLE_TYPE_FLOAT:
1544 		result = true;
1545 		break;
1546 	case VARIABLE_TYPE_INT:
1547 		result = true;
1548 		break;
1549 	case VARIABLE_TYPE_UINT:
1550 		result = true;
1551 		break;
1552 	default:
1553 		break;
1554 	} /* switch (type) */
1555 
1556 	return result;
1557 }
1558 
1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1560  *
1561  * @param token           Token string
1562  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1563  * @param text            String that will be used as replacement for <token>
1564  * @param string          String to work on
1565  **/
replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text, std::string& string)1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
1567 						 std::string& string)
1568 {
1569 	const size_t text_length	= strlen(text);
1570 	const size_t token_length   = strlen(token);
1571 	const size_t token_position = string.find(token, search_position);
1572 
1573 	string.replace(token_position, token_length, text, text_length);
1574 
1575 	search_position = token_position + text_length;
1576 }
1577 
1578 /** Constructor.
1579  *
1580  *  @param context Rendering context.
1581  *
1582  **/
GPUShaderFP64Test1(deqp::Context& context)1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context)
1584 	: TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision "
1585 								  "float uniform support & glUniform*() / glUniformMatrix*() API "
1586 								  " are reported correctly.")
1587 	, m_has_test_passed(true)
1588 	, m_po_bool_arr_uniform_location(0)
1589 	, m_po_bool_uniform_location(0)
1590 	, m_po_bvec2_arr_uniform_location(0)
1591 	, m_po_bvec2_uniform_location(0)
1592 	, m_po_bvec3_arr_uniform_location(0)
1593 	, m_po_bvec3_uniform_location(0)
1594 	, m_po_bvec4_arr_uniform_location(0)
1595 	, m_po_bvec4_uniform_location(0)
1596 	, m_po_dmat2_arr_uniform_location(0)
1597 	, m_po_dmat2_uniform_location(0)
1598 	, m_po_dmat2x3_arr_uniform_location(0)
1599 	, m_po_dmat2x3_uniform_location(0)
1600 	, m_po_dmat2x4_arr_uniform_location(0)
1601 	, m_po_dmat2x4_uniform_location(0)
1602 	, m_po_dmat3_arr_uniform_location(0)
1603 	, m_po_dmat3_uniform_location(0)
1604 	, m_po_dmat3x2_arr_uniform_location(0)
1605 	, m_po_dmat3x2_uniform_location(0)
1606 	, m_po_dmat3x4_arr_uniform_location(0)
1607 	, m_po_dmat3x4_uniform_location(0)
1608 	, m_po_dmat4_arr_uniform_location(0)
1609 	, m_po_dmat4_uniform_location(0)
1610 	, m_po_dmat4x2_arr_uniform_location(0)
1611 	, m_po_dmat4x2_uniform_location(0)
1612 	, m_po_dmat4x3_arr_uniform_location(0)
1613 	, m_po_dmat4x3_uniform_location(0)
1614 	, m_po_double_arr_uniform_location(0)
1615 	, m_po_double_uniform_location(0)
1616 	, m_po_dvec2_arr_uniform_location(0)
1617 	, m_po_dvec2_uniform_location(0)
1618 	, m_po_dvec3_arr_uniform_location(0)
1619 	, m_po_dvec3_uniform_location(0)
1620 	, m_po_dvec4_arr_uniform_location(0)
1621 	, m_po_dvec4_uniform_location(0)
1622 	, m_po_float_arr_uniform_location(0)
1623 	, m_po_float_uniform_location(0)
1624 	, m_po_int_arr_uniform_location(0)
1625 	, m_po_int_uniform_location(0)
1626 	, m_po_ivec2_arr_uniform_location(0)
1627 	, m_po_ivec2_uniform_location(0)
1628 	, m_po_ivec3_arr_uniform_location(0)
1629 	, m_po_ivec3_uniform_location(0)
1630 	, m_po_ivec4_arr_uniform_location(0)
1631 	, m_po_ivec4_uniform_location(0)
1632 	, m_po_sampler_uniform_location(0)
1633 	, m_po_uint_arr_uniform_location(0)
1634 	, m_po_uint_uniform_location(0)
1635 	, m_po_uvec2_arr_uniform_location(0)
1636 	, m_po_uvec2_uniform_location(0)
1637 	, m_po_uvec3_arr_uniform_location(0)
1638 	, m_po_uvec3_uniform_location(0)
1639 	, m_po_uvec4_arr_uniform_location(0)
1640 	, m_po_uvec4_uniform_location(0)
1641 	, m_po_vec2_arr_uniform_location(0)
1642 	, m_po_vec2_uniform_location(0)
1643 	, m_po_vec3_arr_uniform_location(0)
1644 	, m_po_vec3_uniform_location(0)
1645 	, m_po_vec4_arr_uniform_location(0)
1646 	, m_po_vec4_uniform_location(0)
1647 	, m_po_id(0)
1648 	, m_vs_id(0)
1649 {
1650 	/* Left blank intentionally */
1651 }
1652 
1653 /** Deinitializes all GL objects that may have been created during
1654  *  test execution.
1655  **/
deinit()1656 void GPUShaderFP64Test1::deinit()
1657 {
1658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1659 
1660 	if (m_po_id != 0)
1661 	{
1662 		gl.deleteProgram(m_po_id);
1663 
1664 		m_po_id = 0;
1665 	}
1666 
1667 	if (m_vs_id != 0)
1668 	{
1669 		gl.deleteShader(m_vs_id);
1670 
1671 		m_vs_id = 0;
1672 	}
1673 }
1674 
1675 /** Returns a string describing GL API function represented by user-provided enum.
1676  *
1677  *  @param func Uniform function to return the string for.
1678  *
1679  *  @return As per description. [?] will be returned if the function was not recognized.
1680  **/
getUniformFunctionString(_uniform_function func)1681 const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func)
1682 {
1683 	const char* result = "[?]";
1684 
1685 	switch (func)
1686 	{
1687 	case UNIFORM_FUNCTION_1D:
1688 		result = "glUniform1d";
1689 		break;
1690 	case UNIFORM_FUNCTION_1DV:
1691 		result = "glUniform1dv";
1692 		break;
1693 	case UNIFORM_FUNCTION_2D:
1694 		result = "glUniform2d";
1695 		break;
1696 	case UNIFORM_FUNCTION_2DV:
1697 		result = "glUniform2dv";
1698 		break;
1699 	case UNIFORM_FUNCTION_3D:
1700 		result = "glUniform3d";
1701 		break;
1702 	case UNIFORM_FUNCTION_3DV:
1703 		result = "glUniform3dv";
1704 		break;
1705 	case UNIFORM_FUNCTION_4D:
1706 		result = "glUniform4d";
1707 		break;
1708 	case UNIFORM_FUNCTION_4DV:
1709 		result = "glUniform4dv";
1710 		break;
1711 	case UNIFORM_FUNCTION_MATRIX2DV:
1712 		result = "glUniformMatrix2dv";
1713 		break;
1714 	case UNIFORM_FUNCTION_MATRIX2X3DV:
1715 		result = "glUniformMatrix2x3dv";
1716 		break;
1717 	case UNIFORM_FUNCTION_MATRIX2X4DV:
1718 		result = "glUniformMatrix2x4dv";
1719 		break;
1720 	case UNIFORM_FUNCTION_MATRIX3DV:
1721 		result = "glUniformMatrix3dv";
1722 		break;
1723 	case UNIFORM_FUNCTION_MATRIX3X2DV:
1724 		result = "glUniformMatrix3x2dv";
1725 		break;
1726 	case UNIFORM_FUNCTION_MATRIX3X4DV:
1727 		result = "glUniformMatrix3x4dv";
1728 		break;
1729 	case UNIFORM_FUNCTION_MATRIX4DV:
1730 		result = "glUniformMatrix4dv";
1731 		break;
1732 	case UNIFORM_FUNCTION_MATRIX4X2DV:
1733 		result = "glUniformMatrix4x2dv";
1734 		break;
1735 	case UNIFORM_FUNCTION_MATRIX4X3DV:
1736 		result = "glUniformMatrix4x3dv";
1737 		break;
1738 	default:
1739 		break;
1740 	}
1741 
1742 	return result;
1743 }
1744 
1745 /** Returns name of an uniform bound to user-provided location.
1746  *
1747  *  @param location Location of the uniform to return the name for.
1748  *
1749  *  @return As per description. [?] will be returned if the location was not
1750  *          recognized.
1751  **/
getUniformNameForLocation(glw::GLint location)1752 const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location)
1753 {
1754 	const char* result = "[?]";
1755 
1756 	if (location == m_po_bool_arr_uniform_location)
1757 		result = "uniform_bool_arr";
1758 	else if (location == m_po_bool_uniform_location)
1759 		result = "uniform_bool";
1760 	else if (location == m_po_bvec2_arr_uniform_location)
1761 		result = "uniform_bvec2_arr";
1762 	else if (location == m_po_bvec2_uniform_location)
1763 		result = "uniform_bvec2";
1764 	else if (location == m_po_bvec3_arr_uniform_location)
1765 		result = "uniform_bvec3_arr";
1766 	else if (location == m_po_bvec3_uniform_location)
1767 		result = "uniform_bvec3";
1768 	else if (location == m_po_bvec4_arr_uniform_location)
1769 		result = "uniform_bvec4_arr";
1770 	else if (location == m_po_bvec4_uniform_location)
1771 		result = "uniform_bvec4";
1772 	else if (location == m_po_dmat2_arr_uniform_location)
1773 		result = "uniform_dmat2_arr";
1774 	else if (location == m_po_dmat2_uniform_location)
1775 		result = "uniform_dmat2";
1776 	else if (location == m_po_dmat2x3_arr_uniform_location)
1777 		result = "uniform_dmat2x3_arr";
1778 	else if (location == m_po_dmat2x3_uniform_location)
1779 		result = "uniform_dmat2x3";
1780 	else if (location == m_po_dmat2x4_arr_uniform_location)
1781 		result = "uniform_dmat2x4_arr";
1782 	else if (location == m_po_dmat2x4_uniform_location)
1783 		result = "uniform_dmat2x4";
1784 	else if (location == m_po_dmat3_arr_uniform_location)
1785 		result = "uniform_dmat3_arr";
1786 	else if (location == m_po_dmat3_uniform_location)
1787 		result = "uniform_dmat3";
1788 	else if (location == m_po_dmat3x2_arr_uniform_location)
1789 		result = "uniform_dmat3x2_arr";
1790 	else if (location == m_po_dmat3x2_uniform_location)
1791 		result = "uniform_dmat3x2";
1792 	else if (location == m_po_dmat3x4_arr_uniform_location)
1793 		result = "uniform_dmat3x4_arr";
1794 	else if (location == m_po_dmat3x4_uniform_location)
1795 		result = "uniform_dmat3x4";
1796 	else if (location == m_po_dmat4_arr_uniform_location)
1797 		result = "uniform_dmat4_arr";
1798 	else if (location == m_po_dmat4_uniform_location)
1799 		result = "uniform_dmat4";
1800 	else if (location == m_po_dmat4x2_arr_uniform_location)
1801 		result = "uniform_dmat4x2_arr";
1802 	else if (location == m_po_dmat4x2_uniform_location)
1803 		result = "uniform_dmat4x2";
1804 	else if (location == m_po_dmat4x3_arr_uniform_location)
1805 		result = "uniform_dmat4x3_arr";
1806 	else if (location == m_po_dmat4x3_uniform_location)
1807 		result = "uniform_dmat4x3";
1808 	else if (location == m_po_double_arr_uniform_location)
1809 		result = "uniform_double_arr";
1810 	else if (location == m_po_double_uniform_location)
1811 		result = "uniform_double";
1812 	else if (location == m_po_dvec2_arr_uniform_location)
1813 		result = "uniform_dvec2_arr";
1814 	else if (location == m_po_dvec2_uniform_location)
1815 		result = "uniform_dvec2";
1816 	else if (location == m_po_dvec3_arr_uniform_location)
1817 		result = "uniform_dvec3_arr";
1818 	else if (location == m_po_dvec3_uniform_location)
1819 		result = "uniform_dvec3";
1820 	else if (location == m_po_dvec4_arr_uniform_location)
1821 		result = "uniform_dvec4_arr";
1822 	else if (location == m_po_dvec4_uniform_location)
1823 		result = "uniform_dvec4";
1824 	else if (location == m_po_float_arr_uniform_location)
1825 		result = "uniform_float_arr";
1826 	else if (location == m_po_float_uniform_location)
1827 		result = "uniform_float";
1828 	else if (location == m_po_int_arr_uniform_location)
1829 		result = "uniform_int_arr";
1830 	else if (location == m_po_int_uniform_location)
1831 		result = "uniform_int";
1832 	else if (location == m_po_ivec2_arr_uniform_location)
1833 		result = "uniform_ivec2_arr";
1834 	else if (location == m_po_ivec2_uniform_location)
1835 		result = "uniform_ivec2";
1836 	else if (location == m_po_ivec3_arr_uniform_location)
1837 		result = "uniform_ivec3_arr";
1838 	else if (location == m_po_ivec3_uniform_location)
1839 		result = "uniform_ivec3";
1840 	else if (location == m_po_ivec4_arr_uniform_location)
1841 		result = "uniform_ivec4_arr";
1842 	else if (location == m_po_ivec4_uniform_location)
1843 		result = "uniform_ivec4";
1844 	else if (location == m_po_uint_arr_uniform_location)
1845 		result = "uniform_uint_arr";
1846 	else if (location == m_po_uint_uniform_location)
1847 		result = "uniform_uint";
1848 	else if (location == m_po_uvec2_arr_uniform_location)
1849 		result = "uniform_uvec2_arr";
1850 	else if (location == m_po_uvec2_uniform_location)
1851 		result = "uniform_uvec2";
1852 	else if (location == m_po_uvec3_arr_uniform_location)
1853 		result = "uniform_uvec3_arr";
1854 	else if (location == m_po_uvec3_uniform_location)
1855 		result = "uniform_uvec3";
1856 	else if (location == m_po_uvec4_arr_uniform_location)
1857 		result = "uniform_uvec4_arr";
1858 	else if (location == m_po_uvec4_uniform_location)
1859 		result = "uniform_uvec4";
1860 	else if (location == m_po_vec2_arr_uniform_location)
1861 		result = "uniform_vec2_arr";
1862 	else if (location == m_po_vec2_uniform_location)
1863 		result = "uniform_vec2";
1864 	else if (location == m_po_vec3_arr_uniform_location)
1865 		result = "uniform_vec3_arr";
1866 	else if (location == m_po_vec3_uniform_location)
1867 		result = "uniform_vec3";
1868 	else if (location == m_po_vec4_arr_uniform_location)
1869 		result = "uniform_vec4_arr";
1870 	else if (location == m_po_vec4_uniform_location)
1871 		result = "uniform_vec4";
1872 
1873 	return result;
1874 }
1875 
1876 /** Initializes all GL objects required to run the test. Also extracts locations of all
1877  *  uniforms used by the test.
1878  *
1879  *  This function can throw a TestError exception if the implementation misbehaves.
1880  */
initTest()1881 void GPUShaderFP64Test1::initTest()
1882 {
1883 	glw::GLint			  compile_status = GL_FALSE;
1884 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
1885 	glw::GLint			  link_status	= GL_FALSE;
1886 
1887 	/* Set up a program object using all new double-precision types */
1888 	const char* vs_body =
1889 		"#version 400\n"
1890 		"\n"
1891 		"uniform bool      uniform_bool;\n"
1892 		"uniform bvec2     uniform_bvec2;\n"
1893 		"uniform bvec3     uniform_bvec3;\n"
1894 		"uniform bvec4     uniform_bvec4;\n"
1895 		"uniform dmat2     uniform_dmat2;\n"
1896 		"uniform dmat2x3   uniform_dmat2x3;\n"
1897 		"uniform dmat2x4   uniform_dmat2x4;\n"
1898 		"uniform dmat3     uniform_dmat3;\n"
1899 		"uniform dmat3x2   uniform_dmat3x2;\n"
1900 		"uniform dmat3x4   uniform_dmat3x4;\n"
1901 		"uniform dmat4     uniform_dmat4;\n"
1902 		"uniform dmat4x2   uniform_dmat4x2;\n"
1903 		"uniform dmat4x3   uniform_dmat4x3;\n"
1904 		"uniform double    uniform_double;\n"
1905 		"uniform dvec2     uniform_dvec2;\n"
1906 		"uniform dvec3     uniform_dvec3;\n"
1907 		"uniform dvec4     uniform_dvec4;\n"
1908 		"uniform float     uniform_float;\n"
1909 		"uniform int       uniform_int;\n"
1910 		"uniform ivec2     uniform_ivec2;\n"
1911 		"uniform ivec3     uniform_ivec3;\n"
1912 		"uniform ivec4     uniform_ivec4;\n"
1913 		"uniform sampler2D uniform_sampler;\n"
1914 		"uniform uint      uniform_uint;\n"
1915 		"uniform uvec2     uniform_uvec2;\n"
1916 		"uniform uvec3     uniform_uvec3;\n"
1917 		"uniform uvec4     uniform_uvec4;\n"
1918 		"uniform vec2      uniform_vec2;\n"
1919 		"uniform vec3      uniform_vec3;\n"
1920 		"uniform vec4      uniform_vec4;\n"
1921 		"uniform bool      uniform_bool_arr   [2];\n"
1922 		"uniform bvec2     uniform_bvec2_arr  [2];\n"
1923 		"uniform bvec3     uniform_bvec3_arr  [2];\n"
1924 		"uniform bvec4     uniform_bvec4_arr  [2];\n"
1925 		"uniform dmat2     uniform_dmat2_arr  [2];\n"
1926 		"uniform dmat2x3   uniform_dmat2x3_arr[2];\n"
1927 		"uniform dmat2x4   uniform_dmat2x4_arr[2];\n"
1928 		"uniform dmat3     uniform_dmat3_arr  [2];\n"
1929 		"uniform dmat3x2   uniform_dmat3x2_arr[2];\n"
1930 		"uniform dmat3x4   uniform_dmat3x4_arr[2];\n"
1931 		"uniform dmat4     uniform_dmat4_arr  [2];\n"
1932 		"uniform dmat4x2   uniform_dmat4x2_arr[2];\n"
1933 		"uniform dmat4x3   uniform_dmat4x3_arr[2];\n"
1934 		"uniform double    uniform_double_arr [2];\n"
1935 		"uniform dvec2     uniform_dvec2_arr  [2];\n"
1936 		"uniform dvec3     uniform_dvec3_arr  [2];\n"
1937 		"uniform dvec4     uniform_dvec4_arr  [2];\n"
1938 		"uniform float     uniform_float_arr  [2];\n"
1939 		"uniform int       uniform_int_arr    [2];\n"
1940 		"uniform ivec2     uniform_ivec2_arr  [2];\n"
1941 		"uniform ivec3     uniform_ivec3_arr  [2];\n"
1942 		"uniform ivec4     uniform_ivec4_arr  [2];\n"
1943 		"uniform uint      uniform_uint_arr   [2];\n"
1944 		"uniform uvec2     uniform_uvec2_arr  [2];\n"
1945 		"uniform uvec3     uniform_uvec3_arr  [2];\n"
1946 		"uniform uvec4     uniform_uvec4_arr  [2];\n"
1947 		"uniform vec2      uniform_vec2_arr   [2];\n"
1948 		"uniform vec3      uniform_vec3_arr   [2];\n"
1949 		"uniform vec4      uniform_vec4_arr   [2];\n"
1950 		"\n"
1951 		"void main()\n"
1952 		"{\n"
1953 		"    gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n"
1954 		"\n"
1955 		"    if (uniform_bool        && uniform_bvec2.y        && uniform_bvec3.z        && uniform_bvec4.w        &&\n"
1956 		"        uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n"
1957 		"    {\n"
1958 		"        double sum = uniform_dmat2       [0].x + uniform_dmat2x3       [0].x + uniform_dmat2x4       [0].x +\n"
1959 		"                     uniform_dmat3       [0].x + uniform_dmat3x2       [0].x + uniform_dmat3x4       [0].x +\n"
1960 		"                     uniform_dmat4       [0].x + uniform_dmat4x2       [0].x + uniform_dmat4x3       [0].x +\n"
1961 		"                     uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n"
1962 		"                     uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n"
1963 		"                     uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n"
1964 		"                     uniform_double            + uniform_double_arr [0]      +\n"
1965 		"                     uniform_dvec2.x           + uniform_dvec3.x             + uniform_dvec4.x        +\n"
1966 		"                     uniform_dvec2_arr[0].x    + uniform_dvec3_arr[0].x      + uniform_dvec4_arr[0].x;\n"
1967 		"        int   sum2 = uniform_int               + uniform_ivec2.x             + uniform_ivec3.x        +\n"
1968 		"                     uniform_ivec4.x           + uniform_ivec2_arr[0].x      + uniform_ivec3_arr[0].x +\n"
1969 		"                     uniform_ivec4_arr[0].x    + uniform_int_arr[0];\n"
1970 		"        uint  sum3 = uniform_uint              + uniform_uvec2.x             + uniform_uvec3.x        +\n"
1971 		"                     uniform_uvec4.x           + uniform_uint_arr[0]         + uniform_uvec2_arr[0].x +\n"
1972 		"                     uniform_uvec3_arr[0].x    + uniform_uvec4_arr[0].x;\n"
1973 		"        float sum4 = uniform_float             + uniform_float_arr[0]  + \n"
1974 		"                     uniform_vec2.x            + uniform_vec2_arr[0].x + \n"
1975 		"                     uniform_vec3.x            + uniform_vec3_arr[0].x + \n"
1976 		"                     uniform_vec4.x            + uniform_vec4_arr[0].x;\n"
1977 		"\n"
1978 		"        if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n"
1979 		"        {\n"
1980 		"            gl_Position = vec4(1);\n"
1981 		"        }\n"
1982 		"    }\n"
1983 		"}\n";
1984 
1985 	m_po_id = gl.createProgram();
1986 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1987 
1988 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1989 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
1990 
1991 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
1992 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1993 
1994 	gl.compileShader(m_vs_id);
1995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1996 
1997 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1999 
2000 	if (compile_status != GL_TRUE)
2001 	{
2002 		TCU_FAIL("Shader compilation failed.");
2003 	}
2004 
2005 	gl.attachShader(m_po_id, m_vs_id);
2006 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
2007 
2008 	gl.linkProgram(m_po_id);
2009 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2010 
2011 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
2012 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2013 
2014 	if (link_status != GL_TRUE)
2015 	{
2016 		TCU_FAIL("Program linking failed.");
2017 	}
2018 
2019 	m_po_bool_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]");
2020 	m_po_bool_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bool");
2021 	m_po_bvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]");
2022 	m_po_bvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec2");
2023 	m_po_bvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]");
2024 	m_po_bvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec3");
2025 	m_po_bvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]");
2026 	m_po_bvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec4");
2027 	m_po_dmat2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]");
2028 	m_po_dmat2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat2");
2029 	m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]");
2030 	m_po_dmat2x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x3");
2031 	m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]");
2032 	m_po_dmat2x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x4");
2033 	m_po_dmat3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]");
2034 	m_po_dmat3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat3");
2035 	m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]");
2036 	m_po_dmat3x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x2");
2037 	m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]");
2038 	m_po_dmat3x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x4");
2039 	m_po_dmat4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]");
2040 	m_po_dmat4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat4");
2041 	m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]");
2042 	m_po_dmat4x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x2");
2043 	m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]");
2044 	m_po_dmat4x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x3");
2045 	m_po_double_arr_uniform_location  = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]");
2046 	m_po_double_uniform_location	  = gl.getUniformLocation(m_po_id, "uniform_double");
2047 	m_po_dvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]");
2048 	m_po_dvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec2");
2049 	m_po_dvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]");
2050 	m_po_dvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec3");
2051 	m_po_dvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]");
2052 	m_po_dvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec4");
2053 	m_po_float_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]");
2054 	m_po_float_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_float");
2055 	m_po_int_arr_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]");
2056 	m_po_int_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_int");
2057 	m_po_ivec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]");
2058 	m_po_ivec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec2");
2059 	m_po_ivec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]");
2060 	m_po_ivec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec3");
2061 	m_po_ivec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]");
2062 	m_po_ivec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec4");
2063 	m_po_sampler_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_sampler");
2064 	m_po_uint_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]");
2065 	m_po_uint_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uint");
2066 	m_po_uvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]");
2067 	m_po_uvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec2");
2068 	m_po_uvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]");
2069 	m_po_uvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec3");
2070 	m_po_uvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]");
2071 	m_po_uvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec4");
2072 	m_po_vec2_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]");
2073 	m_po_vec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec2");
2074 	m_po_vec3_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]");
2075 	m_po_vec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec3");
2076 	m_po_vec4_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]");
2077 	m_po_vec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec4");
2078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
2079 
2080 	if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 ||
2081 		m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 ||
2082 		m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 ||
2083 		m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 ||
2084 		m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 ||
2085 		m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 ||
2086 		m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 ||
2087 		m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 ||
2088 		m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 ||
2089 		m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 ||
2090 		m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 ||
2091 		m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 ||
2092 		m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 ||
2093 		m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 ||
2094 		m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 ||
2095 		m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 ||
2096 		m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 ||
2097 		m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 ||
2098 		m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 ||
2099 		m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 ||
2100 		m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 ||
2101 		m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 ||
2102 		m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 ||
2103 		m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 ||
2104 		m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 ||
2105 		m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 ||
2106 		m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 ||
2107 		m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 ||
2108 		m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1)
2109 	{
2110 		TCU_FAIL("At last one of the required uniforms is considered inactive.");
2111 	}
2112 }
2113 
2114 /** Tells wheter uniform at user-specified location represents a double-precision
2115  *  matrix uniform.
2116  *
2117  *  @param uniform_location Location of the uniform to use for the query.
2118  *
2119  *  @return Requested information.
2120  **/
isMatrixUniform(glw::GLint uniform_location)2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location)
2122 {
2123 	return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location ||
2124 			uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location ||
2125 			uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location ||
2126 			uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location ||
2127 			uniform_location == m_po_dmat4x3_uniform_location);
2128 }
2129 
2130 /** Tells whether user-specified uniform function corresponds to one of the
2131  *  functions in glUniformMatrix*() class.
2132  *
2133  *  @param func Uniform function enum to use for the query.
2134  *
2135  *  @return true if the specified enum represents one of the glUniformMatrix*() functions,
2136  *          false otherwise.
2137  **/
isMatrixUniformFunction(_uniform_function func)2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func)
2139 {
2140 	return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV ||
2141 			func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV ||
2142 			func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV ||
2143 			func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV ||
2144 			func == UNIFORM_FUNCTION_MATRIX4X3DV);
2145 }
2146 
2147 /** Executes test iteration.
2148  *
2149  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2150  */
iterate()2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate()
2152 {
2153 	/* Do not execute the test if GL_ARB_texture_view is not supported */
2154 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
2155 	{
2156 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
2157 	}
2158 
2159 	/* Initialize all ES objects required to run all the checks */
2160 	initTest();
2161 
2162 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() and
2163 	 * glUniformMatrix*() functions if there is no current program object.
2164 	 */
2165 	m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO();
2166 
2167 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() if
2168 	 * the size of the uniform variable declared in the shader does not
2169 	 * match the size indicated by the command.
2170 	 */
2171 	m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions();
2172 
2173 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2174 	 * glUniformMatrix*() are used to load a uniform variable of type
2175 	 * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4,
2176 	 * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array
2177 	 * of these.
2178 	 */
2179 	m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions();
2180 
2181 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2182 	 * glUniformMatrix*() are used to load incompatible double-typed
2183 	 * uniforms, as presented below:
2184 	 *
2185 	 * I.    double-typed uniform configured by glUniform2d();
2186 	 * II.   double-typed uniform configured by glUniform3d();
2187 	 * III.  double-typed uniform configured by glUniform4d();
2188 	 * IV.   double-typed uniform configured by glUniformMatrix*();
2189 	 * V.    dvec2-typed  uniform configured by glUniform1d();
2190 	 * VI.   dvec2-typed  uniform configured by glUniform3d();
2191 	 * VII.  dvec2-typed  uniform configured by glUniform4d();
2192 	 * VIII. dvec2-typed  uniform configured by glUniformMatrix*();
2193 	 *
2194 	 *                          (etc.)
2195 	 *
2196 	 */
2197 	m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions();
2198 
2199 	/* Make sure GL_INVALID_OPERATION is generated if <location> of
2200 	 * glUniform*() and glUniformMatrix*() is an invalid uniform
2201 	 * location for the current program object and location is not
2202 	 * equal to -1.
2203 	 */
2204 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation();
2205 
2206 	/* Make sure GL_INVALID_VALUE is generated if <count> of
2207 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2208 	 * negative.
2209 	 */
2210 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount();
2211 
2212 	/* Make sure GL_INVALID_OPERATION is generated if <count> of
2213 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2214 	 * greater than 1 and the indicated uniform variable is not an
2215 	 * array variable.
2216 	 */
2217 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount();
2218 
2219 	/* Make sure GL_INVALID_OPERATION is generated if a sampler is
2220 	 * loaded by glUniform*() and glUniformMatrix*().
2221 	 */
2222 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers();
2223 
2224 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2225 	 * glUniformMatrix*() is used to load values for uniforms of
2226 	 * boolean types.
2227 	 */
2228 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans();
2229 
2230 	if (m_has_test_passed)
2231 	{
2232 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2233 	}
2234 	else
2235 	{
2236 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2237 	}
2238 
2239 	return STOP;
2240 }
2241 
2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2243  *  glUniformMatrix*dv() functions is used to load a boolean uniform.
2244  *
2245  *  @return true if the implementation was found to behave as expected, false otherwise.
2246  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()
2248 {
2249 	const double double_data[] = {
2250 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2251 	};
2252 	const glw::Functions& gl				  = m_context.getRenderContext().getFunctions();
2253 	bool				  result			  = true;
2254 	glw::GLint			  uniform_locations[] = { m_po_bool_arr_uniform_location,  m_po_bool_uniform_location,
2255 									   m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2256 									   m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2257 									   m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location };
2258 	const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2259 
2260 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2261 		 ++n_uniform_function)
2262 	{
2263 		const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2264 
2265 		for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2266 		{
2267 			const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2268 
2269 			switch (uniform_function)
2270 			{
2271 			case UNIFORM_FUNCTION_1D:
2272 				gl.uniform1d(uniform_location, 0.0);
2273 				break;
2274 			case UNIFORM_FUNCTION_2D:
2275 				gl.uniform2d(uniform_location, 0.0, 1.0);
2276 				break;
2277 			case UNIFORM_FUNCTION_3D:
2278 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2279 				break;
2280 			case UNIFORM_FUNCTION_4D:
2281 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2282 				break;
2283 
2284 			case UNIFORM_FUNCTION_1DV:
2285 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2286 				break;
2287 			case UNIFORM_FUNCTION_2DV:
2288 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2289 				break;
2290 			case UNIFORM_FUNCTION_3DV:
2291 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2292 				break;
2293 			case UNIFORM_FUNCTION_4DV:
2294 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2295 				break;
2296 
2297 			case UNIFORM_FUNCTION_MATRIX2DV:
2298 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2299 				break;
2300 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2301 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2302 				break;
2303 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2304 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2305 				break;
2306 			case UNIFORM_FUNCTION_MATRIX3DV:
2307 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2308 				break;
2309 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2310 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2311 				break;
2312 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2313 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2314 				break;
2315 			case UNIFORM_FUNCTION_MATRIX4DV:
2316 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2317 				break;
2318 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2319 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2320 				break;
2321 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2322 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2323 				break;
2324 
2325 			default:
2326 			{
2327 				TCU_FAIL("Unrecognized uniform function");
2328 			}
2329 			}
2330 
2331 			/* Make sure GL_INVALID_OPERATION was generated by the call */
2332 			const glw::GLenum error_code = gl.getError();
2333 
2334 			if (error_code != GL_INVALID_OPERATION)
2335 			{
2336 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2337 								   << "() did not generate an error"
2338 									  " when applied against a boolean uniform."
2339 								   << tcu::TestLog::EndMessage;
2340 
2341 				result = false;
2342 			}
2343 		} /* for (all bool uniforms) */
2344 	}	 /* for (all uniform functions) */
2345 
2346 	return result;
2347 }
2348 
2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2350  *  glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2351  *
2352  *  @return true if the implementation was found to behave as expected, false otherwise.
2353  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2355 {
2356 	const double double_data[] = {
2357 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2358 	};
2359 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2360 	bool				  result = true;
2361 
2362 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2363 		 ++n_uniform_function)
2364 	{
2365 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2366 
2367 		switch (uniform_function)
2368 		{
2369 		case UNIFORM_FUNCTION_1D:
2370 			gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2371 			break;
2372 		case UNIFORM_FUNCTION_2D:
2373 			gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2374 			break;
2375 		case UNIFORM_FUNCTION_3D:
2376 			gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2377 			break;
2378 		case UNIFORM_FUNCTION_4D:
2379 			gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2380 			break;
2381 
2382 		case UNIFORM_FUNCTION_1DV:
2383 			gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2384 			break;
2385 		case UNIFORM_FUNCTION_2DV:
2386 			gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2387 			break;
2388 		case UNIFORM_FUNCTION_3DV:
2389 			gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2390 			break;
2391 		case UNIFORM_FUNCTION_4DV:
2392 			gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2393 			break;
2394 
2395 		case UNIFORM_FUNCTION_MATRIX2DV:
2396 			gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2397 			break;
2398 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2399 			gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2400 			break;
2401 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2402 			gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2403 			break;
2404 		case UNIFORM_FUNCTION_MATRIX3DV:
2405 			gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2406 			break;
2407 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2408 			gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2409 			break;
2410 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2411 			gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2412 			break;
2413 		case UNIFORM_FUNCTION_MATRIX4DV:
2414 			gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2415 			break;
2416 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2417 			gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2418 			break;
2419 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2420 			gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2421 			break;
2422 
2423 		default:
2424 		{
2425 			TCU_FAIL("Unrecognized uniform function");
2426 		}
2427 		}
2428 
2429 		/* Make sure GL_INVALID_OPERATION was generated by the call */
2430 		const glw::GLenum error_code = gl.getError();
2431 
2432 		if (error_code != GL_INVALID_OPERATION)
2433 		{
2434 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2435 							   << "() did not generate an error"
2436 								  " when applied against a sampler uniform."
2437 							   << tcu::TestLog::EndMessage;
2438 
2439 			result = false;
2440 		}
2441 	} /* for (all uniform functions) */
2442 
2443 	return result;
2444 }
2445 
2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2447  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2448  *  invalid <count> argument.
2449  *
2450  *  @return true if the implementation was found to behave as expected, false otherwise.
2451  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2453 {
2454 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2455 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2456 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2457 	bool					result				= true;
2458 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2459 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2460 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2461 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2462 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2463 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2464 													UNIFORM_FUNCTION_MATRIX4X3DV };
2465 	const glw::GLint uniforms[] = {
2466 		m_po_bool_uniform_location,	m_po_bvec2_uniform_location,  m_po_bvec3_uniform_location,
2467 		m_po_bvec4_uniform_location,   m_po_dmat2_uniform_location,  m_po_dmat2x3_uniform_location,
2468 		m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,  m_po_dmat3x2_uniform_location,
2469 		m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location,  m_po_dmat4x2_uniform_location,
2470 		m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2471 		m_po_dvec3_uniform_location,   m_po_dvec4_uniform_location,  m_po_float_uniform_location,
2472 		m_po_int_uniform_location,	 m_po_ivec2_uniform_location,  m_po_ivec3_uniform_location,
2473 		m_po_ivec4_uniform_location,   m_po_uint_uniform_location,   m_po_uvec2_uniform_location,
2474 		m_po_uvec3_uniform_location,   m_po_uvec4_uniform_location,  m_po_vec2_uniform_location,
2475 		m_po_vec3_uniform_location,	m_po_vec4_uniform_location
2476 	};
2477 
2478 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2479 	const unsigned int n_uniforms		   = sizeof(uniforms) / sizeof(uniforms[0]);
2480 
2481 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2482 	{
2483 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2484 
2485 		for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2486 		{
2487 			glw::GLint uniform_location = uniforms[n_uniform];
2488 
2489 			/* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2490 			 * and glUniform*() functions with vector uniforms.
2491 			 */
2492 			bool is_matrix_uniform = isMatrixUniform(uniform_location);
2493 
2494 			if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2495 				((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2496 			{
2497 				continue;
2498 			}
2499 
2500 			/* Issue the call with an invalid <count> argument */
2501 			switch (uniform_function)
2502 			{
2503 			case UNIFORM_FUNCTION_1DV:
2504 				gl.uniform1dv(uniform_location, 2, double_values);
2505 				break;
2506 			case UNIFORM_FUNCTION_2DV:
2507 				gl.uniform2dv(uniform_location, 2, double_values);
2508 				break;
2509 			case UNIFORM_FUNCTION_3DV:
2510 				gl.uniform3dv(uniform_location, 2, double_values);
2511 				break;
2512 			case UNIFORM_FUNCTION_4DV:
2513 				gl.uniform4dv(uniform_location, 2, double_values);
2514 				break;
2515 			case UNIFORM_FUNCTION_MATRIX2DV:
2516 				gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2517 				break;
2518 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2519 				gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2520 				break;
2521 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2522 				gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2523 				break;
2524 			case UNIFORM_FUNCTION_MATRIX3DV:
2525 				gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2526 				break;
2527 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2528 				gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2529 				break;
2530 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2531 				gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2532 				break;
2533 			case UNIFORM_FUNCTION_MATRIX4DV:
2534 				gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2535 				break;
2536 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2537 				gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2538 				break;
2539 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2540 				gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2541 				break;
2542 
2543 			default:
2544 			{
2545 				TCU_FAIL("Unrecognized uniform function");
2546 			}
2547 			} /* switch (uniform_function) */
2548 
2549 			/* Make sure GL_INVALID_VALUE was generated */
2550 			glw::GLenum error_code = gl.getError();
2551 
2552 			if (error_code != GL_INVALID_OPERATION)
2553 			{
2554 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2555 								   << "() "
2556 									  "was called with an invalid count argument but did not generate a "
2557 									  "GL_INVALID_OPERATION error"
2558 								   << tcu::TestLog::EndMessage;
2559 
2560 				result = false;
2561 			}
2562 		} /* for (all non-arrayed uniforms) */
2563 	}	 /* for (all uniform functions) */
2564 
2565 	return result;
2566 }
2567 
2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2569  *  glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2570  *
2571  *  @return true if the implementation was found to behave as expected, false otherwise.
2572  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2574 {
2575 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2576 	bool				  result = true;
2577 
2578 	/* Find the largest valid uniform location */
2579 	const glw::GLint uniform_locations[] = {
2580 		m_po_bool_arr_uniform_location,	m_po_bool_uniform_location,		  m_po_bvec2_arr_uniform_location,
2581 		m_po_bvec2_uniform_location,	   m_po_bvec3_arr_uniform_location,   m_po_bvec3_uniform_location,
2582 		m_po_bvec4_arr_uniform_location,   m_po_bvec4_uniform_location,		  m_po_dmat2_arr_uniform_location,
2583 		m_po_dmat2_uniform_location,	   m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2584 		m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location,	 m_po_dmat3_arr_uniform_location,
2585 		m_po_dmat3_uniform_location,	   m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2586 		m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location,	 m_po_dmat4_arr_uniform_location,
2587 		m_po_dmat4_uniform_location,	   m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2588 		m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location,	 m_po_double_arr_uniform_location,
2589 		m_po_double_uniform_location,	  m_po_dvec2_arr_uniform_location,   m_po_dvec2_uniform_location,
2590 		m_po_dvec3_arr_uniform_location,   m_po_dvec3_uniform_location,		  m_po_dvec4_arr_uniform_location,
2591 		m_po_dvec4_uniform_location,	   m_po_float_arr_uniform_location,   m_po_float_uniform_location,
2592 		m_po_int_arr_uniform_location,	 m_po_int_uniform_location,		  m_po_ivec2_arr_uniform_location,
2593 		m_po_ivec2_uniform_location,	   m_po_ivec3_arr_uniform_location,   m_po_ivec3_uniform_location,
2594 		m_po_ivec4_arr_uniform_location,   m_po_ivec4_uniform_location,		  m_po_uint_arr_uniform_location,
2595 		m_po_uint_uniform_location,		   m_po_uvec2_arr_uniform_location,   m_po_uvec2_uniform_location,
2596 		m_po_uvec3_arr_uniform_location,   m_po_uvec3_uniform_location,		  m_po_uvec4_arr_uniform_location,
2597 		m_po_uvec4_uniform_location,	   m_po_vec2_arr_uniform_location,	m_po_vec2_uniform_location,
2598 		m_po_vec3_arr_uniform_location,	m_po_vec3_uniform_location,		  m_po_vec4_arr_uniform_location,
2599 		m_po_vec4_uniform_location
2600 	};
2601 	const unsigned int n_uniform_locations	= sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2602 	glw::GLint		   valid_uniform_location = -1;
2603 
2604 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2605 	{
2606 		glw::GLint uniform_location = uniform_locations[n_uniform_location];
2607 
2608 		if (uniform_location > valid_uniform_location)
2609 		{
2610 			valid_uniform_location = uniform_location;
2611 		}
2612 	} /* for (all  uniform locations) */
2613 
2614 	/* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2615 	 * for invalid uniform location that is != -1
2616 	 */
2617 	const double double_data[] = {
2618 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2619 	};
2620 	const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2621 
2622 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2623 		 ++n_uniform_function)
2624 	{
2625 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2626 
2627 		switch (uniform_function)
2628 		{
2629 		case UNIFORM_FUNCTION_1D:
2630 			gl.uniform1d(invalid_uniform_location, 0.0);
2631 			break;
2632 		case UNIFORM_FUNCTION_2D:
2633 			gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2634 			break;
2635 		case UNIFORM_FUNCTION_3D:
2636 			gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2637 			break;
2638 		case UNIFORM_FUNCTION_4D:
2639 			gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2640 			break;
2641 
2642 		case UNIFORM_FUNCTION_1DV:
2643 			gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2644 			break;
2645 		case UNIFORM_FUNCTION_2DV:
2646 			gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2647 			break;
2648 		case UNIFORM_FUNCTION_3DV:
2649 			gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2650 			break;
2651 		case UNIFORM_FUNCTION_4DV:
2652 			gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2653 			break;
2654 
2655 		case UNIFORM_FUNCTION_MATRIX2DV:
2656 			gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657 			break;
2658 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2659 			gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660 			break;
2661 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2662 			gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663 			break;
2664 		case UNIFORM_FUNCTION_MATRIX3DV:
2665 			gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666 			break;
2667 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2668 			gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669 			break;
2670 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2671 			gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672 			break;
2673 		case UNIFORM_FUNCTION_MATRIX4DV:
2674 			gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675 			break;
2676 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2677 			gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2678 			break;
2679 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2680 			gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2681 			break;
2682 
2683 		default:
2684 		{
2685 			TCU_FAIL("Unrecognized uniform function");
2686 		}
2687 		}
2688 
2689 		const glw::GLenum error_code = gl.getError();
2690 
2691 		if (error_code != GL_INVALID_OPERATION)
2692 		{
2693 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2694 							   << "() did not generate an error"
2695 								  " when passed an invalid uniform location different from -1."
2696 							   << tcu::TestLog::EndMessage;
2697 
2698 			result = false;
2699 		}
2700 	} /* for (all uniform functions) */
2701 
2702 	return result;
2703 }
2704 
2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2706  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2707  *  invalid <count> argument of -1.
2708  *
2709  *  @return true if the implementation was found to behave as expected, false otherwise.
2710  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2712 {
2713 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2714 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2715 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2716 	bool					result				= true;
2717 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2718 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2719 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2720 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2721 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2722 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2723 													UNIFORM_FUNCTION_MATRIX4X3DV };
2724 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2725 
2726 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2727 	{
2728 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2729 
2730 		switch (uniform_function)
2731 		{
2732 		case UNIFORM_FUNCTION_1DV:
2733 			gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2734 			break;
2735 		case UNIFORM_FUNCTION_2DV:
2736 			gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2737 			break;
2738 		case UNIFORM_FUNCTION_3DV:
2739 			gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2740 			break;
2741 		case UNIFORM_FUNCTION_4DV:
2742 			gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2743 			break;
2744 		case UNIFORM_FUNCTION_MATRIX2DV:
2745 			gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2746 			break;
2747 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2748 			gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2749 			break;
2750 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2751 			gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2752 			break;
2753 		case UNIFORM_FUNCTION_MATRIX3DV:
2754 			gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2755 			break;
2756 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2757 			gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2758 			break;
2759 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2760 			gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2761 			break;
2762 		case UNIFORM_FUNCTION_MATRIX4DV:
2763 			gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2764 			break;
2765 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2766 			gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2767 			break;
2768 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2769 			gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2770 			break;
2771 
2772 		default:
2773 		{
2774 			TCU_FAIL("Unrecognized uniform function");
2775 		}
2776 		} /* switch (uniform_function) */
2777 
2778 		/* Make sure GL_INVALID_VALUE was generated */
2779 		glw::GLenum error_code = gl.getError();
2780 
2781 		if (error_code != GL_INVALID_VALUE)
2782 		{
2783 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2784 							   << "() "
2785 								  "was called with a negative count argument but did not generate a "
2786 								  "GL_INVALID_VALUE error"
2787 							   << tcu::TestLog::EndMessage;
2788 
2789 			result = false;
2790 		}
2791 	} /* for (all uniform functions) */
2792 
2793 	return result;
2794 }
2795 
2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2797  *  glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2798  *  function (as per spec).
2799  *
2800  *  @return true if the implementation was found to behave as expected, false otherwise.
2801  **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2803 {
2804 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2805 	glw::GLenum			  error_code	= GL_NO_ERROR;
2806 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2807 	bool				  result		= true;
2808 
2809 	const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location,   m_po_dmat2x3_uniform_location,
2810 													m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,
2811 													m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2812 													m_po_dmat4_uniform_location,   m_po_dmat4x2_uniform_location,
2813 													m_po_dmat4x3_uniform_location, m_po_double_uniform_location,
2814 													m_po_dvec2_uniform_location,   m_po_dvec3_uniform_location,
2815 													m_po_dvec4_uniform_location };
2816 	const unsigned int n_double_uniform_locations =
2817 		sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2818 
2819 	gl.useProgram(m_po_id);
2820 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2821 
2822 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2823 	{
2824 		glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2825 
2826 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2827 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2828 		{
2829 			_uniform_function e_function = static_cast<_uniform_function>(function);
2830 			/* Exclude valid combinations */
2831 			if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2832 				((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2833 				((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2834 				((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2835 				((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2836 				((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2837 				((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2838 				((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2839 				((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2840 				((uniform_location == m_po_double_uniform_location) &&
2841 				 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2842 				((uniform_location == m_po_dvec2_uniform_location) &&
2843 				 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2844 				((uniform_location == m_po_dvec3_uniform_location) &&
2845 				 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2846 				((uniform_location == m_po_dvec4_uniform_location) &&
2847 				 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2848 			{
2849 				continue;
2850 			}
2851 
2852 			switch (e_function)
2853 			{
2854 			case UNIFORM_FUNCTION_1D:
2855 			{
2856 				gl.uniform1d(uniform_location, double_data[0]);
2857 
2858 				break;
2859 			}
2860 
2861 			case UNIFORM_FUNCTION_2D:
2862 			{
2863 				gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2864 
2865 				break;
2866 			}
2867 
2868 			case UNIFORM_FUNCTION_3D:
2869 			{
2870 				gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2871 
2872 				break;
2873 			}
2874 
2875 			case UNIFORM_FUNCTION_4D:
2876 			{
2877 				gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2878 
2879 				break;
2880 			}
2881 
2882 			case UNIFORM_FUNCTION_1DV:
2883 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2884 				break;
2885 			case UNIFORM_FUNCTION_2DV:
2886 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2887 				break;
2888 			case UNIFORM_FUNCTION_3DV:
2889 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2890 				break;
2891 			case UNIFORM_FUNCTION_4DV:
2892 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2893 				break;
2894 			case UNIFORM_FUNCTION_MATRIX2DV:
2895 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2896 				break;
2897 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2898 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2899 				break;
2900 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2901 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2902 				break;
2903 			case UNIFORM_FUNCTION_MATRIX3DV:
2904 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2905 				break;
2906 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2907 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2908 				break;
2909 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2910 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2911 				break;
2912 			case UNIFORM_FUNCTION_MATRIX4DV:
2913 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2914 				break;
2915 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2916 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2917 				break;
2918 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2919 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2920 				break;
2921 
2922 			default:
2923 			{
2924 				TCU_FAIL("Unrecognized function");
2925 			}
2926 			} /* switch (function) */
2927 
2928 			/* Make sure GL_INVALID_OPERATION error was generated */
2929 			error_code = gl.getError();
2930 
2931 			if (error_code != GL_INVALID_OPERATION)
2932 			{
2933 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2934 								   << "] was generated when a mismatched "
2935 									  "double-precision uniform function "
2936 								   << getUniformFunctionString(e_function) << "() was used to configure uniform "
2937 								   << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2938 
2939 				result = false;
2940 			}
2941 		} /* for (all uniform functions) */
2942 	}	 /* for (all uniform locations) */
2943 
2944 	return result;
2945 }
2946 
2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2948  *  glUniform*dv() functions is used to load an uniform, size of which is incompatible
2949  *  with the function.
2950  *
2951  *  @return true if the implementation was found to behave as expected, false otherwise.
2952  **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2954 {
2955 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2956 	glw::GLenum			  error_code	= GL_NO_ERROR;
2957 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2958 	bool				  result		= true;
2959 
2960 	const int data[] = {
2961 		/* API function */ /* Uniform location */ /* Count (dv functions only) */
2962 		(int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV,
2963 		m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0,
2964 		(int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2965 		m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2,
2966 		(int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2967 		m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0,
2968 		(int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2969 		m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2,
2970 		(int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2971 		m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0,
2972 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2973 		m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2,
2974 		(int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2975 		m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0,
2976 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D,
2977 		m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2,
2978 	};
2979 	const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
2980 
2981 	gl.useProgram(m_po_id);
2982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2983 
2984 	for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
2985 	{
2986 		_uniform_function function		   = (_uniform_function)data[n_check * 3 + 0];
2987 		int				  uniform_location = data[n_check * 3 + 1];
2988 		int				  uniform_count	= data[n_check * 3 + 2];
2989 
2990 		switch (function)
2991 		{
2992 		case UNIFORM_FUNCTION_1D:
2993 			gl.uniform1d(uniform_location, 0.0);
2994 			break;
2995 		case UNIFORM_FUNCTION_1DV:
2996 			gl.uniform1dv(uniform_location, uniform_count, double_data);
2997 			break;
2998 		case UNIFORM_FUNCTION_2D:
2999 			gl.uniform2d(uniform_location, 0.0, 1.0);
3000 			break;
3001 		case UNIFORM_FUNCTION_2DV:
3002 			gl.uniform2dv(uniform_location, uniform_count, double_data);
3003 			break;
3004 		case UNIFORM_FUNCTION_3D:
3005 			gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3006 			break;
3007 		case UNIFORM_FUNCTION_3DV:
3008 			gl.uniform3dv(uniform_location, uniform_count, double_data);
3009 			break;
3010 		case UNIFORM_FUNCTION_4D:
3011 			gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3012 			break;
3013 		case UNIFORM_FUNCTION_4DV:
3014 			gl.uniform4dv(uniform_location, uniform_count, double_data);
3015 			break;
3016 
3017 		default:
3018 		{
3019 			DE_ASSERT(false);
3020 		}
3021 		} /* switch (function) */
3022 
3023 		error_code = gl.getError();
3024 		if (error_code != GL_INVALID_OPERATION)
3025 		{
3026 			m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3027 							   << "() function did not generate GL_INVALID_OPERATION error when called for"
3028 								  " a uniform of incompatible size. (check index: "
3029 							   << n_check << ")" << tcu::TestLog::EndMessage;
3030 
3031 			result = false;
3032 		}
3033 	} /* for (all checks) */
3034 
3035 	return result;
3036 }
3037 
3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3039  *  glUniform*dv() functions is used to load an uniform, type of which is incompatible
3040  *  with the function.
3041  *
3042  *  @return true if the implementation was found to behave as expected, false otherwise.
3043  **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3045 {
3046 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
3047 	glw::GLenum			  error_code	= GL_NO_ERROR;
3048 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
3049 	bool				  result		= true;
3050 
3051 	const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location,  m_po_bvec2_uniform_location,
3052 													   m_po_bvec3_uniform_location, m_po_bvec4_uniform_location,
3053 													   m_po_float_uniform_location, m_po_int_uniform_location,
3054 													   m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
3055 													   m_po_ivec4_uniform_location, m_po_uint_uniform_location,
3056 													   m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3057 													   m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
3058 													   m_po_vec3_uniform_location,  m_po_vec4_uniform_location };
3059 	const unsigned int n_nondouble_uniform_locations =
3060 		sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3061 
3062 	gl.useProgram(m_po_id);
3063 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3064 
3065 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3066 	{
3067 		glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3068 
3069 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3070 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3071 		{
3072 			switch (static_cast<_uniform_function>(function))
3073 			{
3074 			case UNIFORM_FUNCTION_1D:
3075 				gl.uniform1d(uniform_location, 0.0);
3076 				break;
3077 			case UNIFORM_FUNCTION_1DV:
3078 				gl.uniform1dv(uniform_location, 1, double_data);
3079 				break;
3080 			case UNIFORM_FUNCTION_2D:
3081 				gl.uniform2d(uniform_location, 0.0, 1.0);
3082 				break;
3083 			case UNIFORM_FUNCTION_2DV:
3084 				gl.uniform2dv(uniform_location, 1, double_data);
3085 				break;
3086 			case UNIFORM_FUNCTION_3D:
3087 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3088 				break;
3089 			case UNIFORM_FUNCTION_3DV:
3090 				gl.uniform3dv(uniform_location, 1, double_data);
3091 				break;
3092 			case UNIFORM_FUNCTION_4D:
3093 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3094 				break;
3095 			case UNIFORM_FUNCTION_4DV:
3096 				gl.uniform4dv(uniform_location, 1, double_data);
3097 				break;
3098 
3099 			case UNIFORM_FUNCTION_MATRIX2DV:
3100 				gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3101 				break;
3102 			case UNIFORM_FUNCTION_MATRIX2X3DV:
3103 				gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3104 				break;
3105 			case UNIFORM_FUNCTION_MATRIX2X4DV:
3106 				gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3107 				break;
3108 			case UNIFORM_FUNCTION_MATRIX3DV:
3109 				gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3110 				break;
3111 			case UNIFORM_FUNCTION_MATRIX3X2DV:
3112 				gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3113 				break;
3114 			case UNIFORM_FUNCTION_MATRIX3X4DV:
3115 				gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3116 				break;
3117 			case UNIFORM_FUNCTION_MATRIX4DV:
3118 				gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3119 				break;
3120 			case UNIFORM_FUNCTION_MATRIX4X2DV:
3121 				gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3122 				break;
3123 			case UNIFORM_FUNCTION_MATRIX4X3DV:
3124 				gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3125 				break;
3126 
3127 			default:
3128 			{
3129 				DE_ASSERT(false);
3130 			}
3131 			} /* switch (function) */
3132 
3133 			error_code = gl.getError();
3134 			if (error_code != GL_INVALID_OPERATION)
3135 			{
3136 				m_testCtx.getLog() << tcu::TestLog::Message
3137 								   << getUniformFunctionString(static_cast<_uniform_function>(function))
3138 								   << "() function did not generate GL_INVALID_OPERATION error when called for"
3139 									  " a uniform of incompatible type."
3140 								   << tcu::TestLog::EndMessage;
3141 
3142 				result = false;
3143 			}
3144 		}
3145 	} /* for (all checks) */
3146 
3147 	return result;
3148 }
3149 
3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3151  *  glUniform*dv() functions are called without a bound program object.
3152  *
3153  *  @return true if the implementation was found to behave as expected, false otherwise.
3154  **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3156 {
3157 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3158 	bool				  result = true;
3159 
3160 	for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3161 		 function++)
3162 	{
3163 		const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
3164 
3165 		switch (static_cast<_uniform_function>(function))
3166 		{
3167 		case UNIFORM_FUNCTION_1D:
3168 			gl.uniform1d(m_po_double_uniform_location, 0.0);
3169 			break;
3170 		case UNIFORM_FUNCTION_1DV:
3171 			gl.uniform1dv(m_po_double_uniform_location, 1, data);
3172 			break;
3173 		case UNIFORM_FUNCTION_2D:
3174 			gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3175 			break;
3176 		case UNIFORM_FUNCTION_2DV:
3177 			gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3178 			break;
3179 		case UNIFORM_FUNCTION_3D:
3180 			gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3181 			break;
3182 		case UNIFORM_FUNCTION_3DV:
3183 			gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3184 			break;
3185 		case UNIFORM_FUNCTION_4D:
3186 			gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3187 			break;
3188 		case UNIFORM_FUNCTION_4DV:
3189 			gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3190 			break;
3191 
3192 		case UNIFORM_FUNCTION_MATRIX2DV:
3193 			gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3194 			break;
3195 		case UNIFORM_FUNCTION_MATRIX2X3DV:
3196 			gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3197 			break;
3198 		case UNIFORM_FUNCTION_MATRIX2X4DV:
3199 			gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3200 			break;
3201 		case UNIFORM_FUNCTION_MATRIX3DV:
3202 			gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3203 			break;
3204 		case UNIFORM_FUNCTION_MATRIX3X2DV:
3205 			gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3206 			break;
3207 		case UNIFORM_FUNCTION_MATRIX3X4DV:
3208 			gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3209 			break;
3210 		case UNIFORM_FUNCTION_MATRIX4DV:
3211 			gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3212 			break;
3213 		case UNIFORM_FUNCTION_MATRIX4X2DV:
3214 			gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3215 			break;
3216 		case UNIFORM_FUNCTION_MATRIX4X3DV:
3217 			gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3218 			break;
3219 
3220 		default:
3221 		{
3222 			TCU_FAIL("Unrecognized uniform function");
3223 		}
3224 		} /* switch (func) */
3225 
3226 		/* Query the error code */
3227 		glw::GLenum error_code = gl.getError();
3228 
3229 		if (error_code != GL_INVALID_OPERATION)
3230 		{
3231 			m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3232 							   << getUniformFunctionString(static_cast<_uniform_function>(function))
3233 							   << "() was called without an active program object" << tcu::TestLog::EndMessage;
3234 
3235 			result = false;
3236 		}
3237 	} /* for (all uniform functions) */
3238 
3239 	return result;
3240 }
3241 
3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3244 const glw::GLint  GPUShaderFP64Test2::m_result_failure	 = 2;
3245 const glw::GLint  GPUShaderFP64Test2::m_result_success	 = 1;
3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width	  = 32;
3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height	 = m_n_captured_results / m_texture_width;
3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3249 	m_n_captured_results * sizeof(captured_varying_type);
3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name				  = "UniformBlock";
3251 const glw::GLenum  GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3252 
3253 /** Constructor
3254  *
3255  * @param context Test context
3256  **/
GPUShaderFP64Test2(deqp::Context& context)3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context)
3258 	: TestCase(context, "max_uniform_components",
3259 			   "Verifies that maximum allowed uniform components can be used as double-precision float types")
3260 	, m_pDispatchCompute(0)
3261 	, m_framebuffer_id(0)
3262 	, m_texture_id(0)
3263 	, m_transform_feedback_buffer_id(0)
3264 	, m_uniform_buffer_id(0)
3265 	, m_vertex_array_object_id(0)
3266 {
3267 	/* Nothing to be done */
3268 }
3269 
3270 /** Deinitialize test
3271  *
3272  **/
deinit()3273 void GPUShaderFP64Test2::deinit()
3274 {
3275 	/* GL entry points */
3276 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3277 
3278 	/* Clean frambuffer */
3279 	if (0 != m_framebuffer_id)
3280 	{
3281 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3282 		gl.deleteFramebuffers(1, &m_framebuffer_id);
3283 		m_framebuffer_id = 0;
3284 	}
3285 
3286 	/* Clean texture */
3287 	if (0 != m_texture_id)
3288 	{
3289 		gl.bindTexture(GL_TEXTURE_2D, 0);
3290 		gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3291 							GL_READ_ONLY, GL_RGBA8);
3292 		gl.deleteTextures(1, &m_texture_id);
3293 		m_texture_id = 0;
3294 	}
3295 
3296 	/* Clean buffers */
3297 	if (0 != m_transform_feedback_buffer_id)
3298 	{
3299 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3300 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3301 		m_transform_feedback_buffer_id = 0;
3302 	}
3303 
3304 	if (0 != m_uniform_buffer_id)
3305 	{
3306 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3307 		gl.deleteBuffers(1, &m_uniform_buffer_id);
3308 		m_uniform_buffer_id = 0;
3309 	}
3310 
3311 	/* Clean VAO */
3312 	if (0 != m_vertex_array_object_id)
3313 	{
3314 		gl.bindVertexArray(0);
3315 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3316 		m_vertex_array_object_id = 0;
3317 	}
3318 }
3319 
3320 /** Execute test
3321  *
3322  * @return tcu::TestNode::STOP
3323  **/
iterate()3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3325 {
3326 	bool result = true;
3327 
3328 	/* Check if extension is supported */
3329 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3330 	{
3331 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3332 	}
3333 
3334 	/* Initialize test */
3335 	testInit();
3336 
3337 	prepareShaderStages();
3338 	prepareUniformTypes();
3339 
3340 	/* For all shaders and uniform type combinations */
3341 	for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3342 		 m_shader_stages.end() != shader_stage; ++shader_stage)
3343 	{
3344 		for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3345 			 m_uniform_types.end() != uniform_type; ++uniform_type)
3346 		{
3347 			/* Execute test */
3348 			if (false == test(*shader_stage, *uniform_type))
3349 			{
3350 				result = false;
3351 			}
3352 		}
3353 	}
3354 
3355 	/* Set result */
3356 	if (true == result)
3357 	{
3358 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3359 	}
3360 	else
3361 	{
3362 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3363 	}
3364 
3365 	/* Done */
3366 	return tcu::TestNode::STOP;
3367 }
3368 
3369 /** Constructor
3370  *
3371  * @param n_columns Number of columns
3372  * @param n_rows    Number of rows
3373  **/
uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3375 	: m_n_columns(n_columns), m_n_rows(n_rows)
3376 {
3377 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3378 
3379 	m_type_name = Utils::getVariableTypeString(type);
3380 	m_type		= Utils::getGLDataTypeOfVariableType(type);
3381 }
3382 
3383 /** Get primitive type captured with transform feedback
3384  *
3385  * @param shader_stage Tested shader stage id
3386  *
3387  * @return Primitive type
3388  **/
getCapturedPrimitiveType(shaderStage shader_stage) const3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3390 {
3391 	switch (shader_stage)
3392 	{
3393 	case GEOMETRY_SHADER:
3394 	case TESS_CTRL_SHADER:
3395 	case TESS_EVAL_SHADER:
3396 	case VERTEX_SHADER:
3397 		return GL_POINTS;
3398 
3399 	default:
3400 		return GL_NONE;
3401 	}
3402 }
3403 
3404 /** Get primitive type drawn with DrawArrays
3405  *
3406  * @param shader_stage Tested shader stage id
3407  *
3408  * @return Primitive type
3409  **/
getDrawPrimitiveType(shaderStage shader_stage) const3410 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3411 {
3412 	switch (shader_stage)
3413 	{
3414 	case FRAGMENT_SHADER:
3415 		return GL_TRIANGLE_FAN;
3416 
3417 	case GEOMETRY_SHADER:
3418 	case VERTEX_SHADER:
3419 		return GL_POINTS;
3420 
3421 	case TESS_CTRL_SHADER:
3422 	case TESS_EVAL_SHADER:
3423 		return GL_PATCHES;
3424 
3425 	default:
3426 		return GL_NONE;
3427 	}
3428 }
3429 
3430 /** Get maximum allowed number of uniform components
3431  *
3432  * @param shader_stage Tested shader stage id
3433  *
3434  * @return Maxmimum uniform components
3435  **/
getMaxUniformComponents(shaderStage shader_stage) const3436 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3437 {
3438 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3439 	glw::GLint			  max_uniform_components = 0;
3440 	glw::GLenum			  pname					 = 0;
3441 
3442 	switch (shader_stage)
3443 	{
3444 	case COMPUTE_SHADER:
3445 		pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3446 		break;
3447 	case FRAGMENT_SHADER:
3448 		pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3449 		break;
3450 	case GEOMETRY_SHADER:
3451 		pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3452 		break;
3453 	case TESS_CTRL_SHADER:
3454 		pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3455 		break;
3456 	case TESS_EVAL_SHADER:
3457 		pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3458 		break;
3459 	case VERTEX_SHADER:
3460 		pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3461 		break;
3462 	}
3463 
3464 	gl.getIntegerv(pname, &max_uniform_components);
3465 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3466 
3467 	return max_uniform_components;
3468 }
3469 
3470 /** Get maximum size allowed for an uniform block
3471  *
3472  * @return Maxmimum uniform block size
3473  **/
getMaxUniformBlockSize() const3474 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3475 {
3476 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3477 	glw::GLint			  max_uniform_block_size = 0;
3478 
3479 	gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3480 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3481 
3482 	return max_uniform_block_size;
3483 }
3484 
3485 /** Get number of components required to store single uniform of given type
3486  *
3487  * @param uniform_type Tested uniform type
3488  *
3489  * @return Number of components
3490  **/
getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const3491 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3492 {
3493 	static const glw::GLuint type_size	 = 2; /* double takes 2 N */
3494 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3495 
3496 	if (1 == uniform_type.m_n_columns)
3497 	{
3498 		return type_size * column_length;
3499 	}
3500 	else
3501 	{
3502 		const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3503 
3504 		return alignment * uniform_type.m_n_columns;
3505 	}
3506 }
3507 
3508 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3509  *
3510  * @param uniform_type Tested uniform type
3511  *
3512  * @return Size of a single member
3513  **/
getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const3514 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3515 {
3516 	static const glw::GLuint vec4_size	 = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3517 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3518 
3519 	/** Size for a layout(std140, column_major) uniform_type uniform[] **/
3520 	return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3521 }
3522 
3523 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3524  *
3525  * @param shader_stage Tested shader stage id
3526  * @param uniform_type Tested uniform type
3527  *
3528  * @return Number of components
3529  **/
getAmountUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const3530 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage				shader_stage,
3531 												  const uniformTypeDetails& uniform_type) const
3532 {
3533 	const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
3534 	const glw::GLuint required_components	  = getRequiredComponentsNumber(uniform_type);
3535 	const glw::GLuint n_uniforms			   = max_uniform_components / required_components;
3536 	const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
3537 	const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3538 	const glw::GLuint max_uniforms			   = max_uniform_block_size / uniform_type_member_size;
3539 
3540 	return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3541 }
3542 
3543 /** Get name of shader stage
3544  *
3545  * @param shader_stage Tested shader stage id
3546  *
3547  * @return Name
3548  **/
getShaderStageName(shaderStage shader_stage) const3549 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3550 {
3551 	switch (shader_stage)
3552 	{
3553 	case COMPUTE_SHADER:
3554 		return "compute shader";
3555 	case FRAGMENT_SHADER:
3556 		return "fragment shader";
3557 	case GEOMETRY_SHADER:
3558 		return "geometry shader";
3559 	case TESS_CTRL_SHADER:
3560 		return "tesselation control shader";
3561 	case TESS_EVAL_SHADER:
3562 		return "tesselation evaluation shader";
3563 	case VERTEX_SHADER:
3564 		return "vertex shader";
3565 	}
3566 
3567 	return 0;
3568 }
3569 
3570 /** Inspect program to get: buffer_size, offset, strides and block index
3571  *
3572  * @param program_id          Program id
3573  * @param out_buffer_size     Size of uniform buffer
3574  * @param out_uniform_details Uniform offset and strides
3575  * @param uniform_block_index Uniform block index
3576  **/
inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms, const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size, uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const3577 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3578 										const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3579 										uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const
3580 {
3581 	glw::GLint				 array_stride = 0;
3582 	std::vector<glw::GLchar> extracted_uniform_name;
3583 	const glw::Functions&	gl			   = m_context.getRenderContext().getFunctions();
3584 	glw::GLuint				 index		   = 0;
3585 	glw::GLint				 matrix_stride = 0;
3586 	glw::GLint				 offset		   = 0;
3587 	glw::GLsizei			 size		   = 0;
3588 	glw::GLenum				 type		   = 0;
3589 	const glw::GLchar*		 uniform_name  = 0;
3590 	std::string				 uniform_name_str;
3591 	std::stringstream		 uniform_name_stream;
3592 
3593 	/* Get index of uniform block */
3594 	uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3595 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3596 
3597 	if (GL_INVALID_INDEX == uniform_block_index)
3598 	{
3599 		TCU_FAIL("Unifom block is inactive");
3600 	}
3601 
3602 	/* Get size of uniform block */
3603 	gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3604 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3605 
3606 	if (0 == out_buffer_size)
3607 	{
3608 		TCU_FAIL("Unifom block size is 0");
3609 	}
3610 
3611 	/* Prepare uniform name */
3612 	uniform_name_stream << "uniform_array";
3613 
3614 	uniform_name_str = uniform_name_stream.str();
3615 	uniform_name	 = uniform_name_str.c_str();
3616 
3617 	/* Get index of uniform */
3618 	gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3619 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3620 
3621 	if (GL_INVALID_INDEX == index)
3622 	{
3623 		TCU_FAIL("Unifom is inactive");
3624 	}
3625 
3626 	/* Verify getActiveUniform results */
3627 	extracted_uniform_name.resize(uniform_name_str.length() * 2);
3628 
3629 	gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3630 						&extracted_uniform_name[0]);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3632 
3633 	if ((n_uniforms != size) || (uniform_type.m_type != type))
3634 	{
3635 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3636 											<< " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3637 											<< " expected: " << uniform_type.m_type
3638 											<< ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3639 
3640 		TCU_FAIL("Invalid GetActiveUniform results");
3641 	}
3642 
3643 	/* Get offset of uniform */
3644 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3645 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3646 
3647 	if (-1 == offset)
3648 	{
3649 		TCU_FAIL("Unifom has invalid offset");
3650 	}
3651 
3652 	out_uniform_details.m_offset = offset;
3653 
3654 	/* Get matrix stride of uniform */
3655 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3656 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3657 
3658 	if (-1 == matrix_stride)
3659 	{
3660 		TCU_FAIL("Unifom has invalid matrix stride");
3661 	}
3662 
3663 	out_uniform_details.m_matrix_stride = matrix_stride;
3664 
3665 	/* Get array stride of uniform */
3666 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3667 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3668 
3669 	if (-1 == matrix_stride)
3670 	{
3671 		TCU_FAIL("Unifom has invalid matrix stride");
3672 	}
3673 
3674 	out_uniform_details.m_array_stride = array_stride;
3675 }
3676 
3677 /** Prepare source code for "boilerplate" shaders
3678  *
3679  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3680  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3681  * @param out_source_code          Source code
3682  **/
prepareBoilerplateShader(const glw::GLchar* stage_specific_layout, const glw::GLchar* stage_specific_main_body, std::string& out_source_code) const3683 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3684 												  const glw::GLchar* stage_specific_main_body,
3685 												  std::string&		 out_source_code) const
3686 {
3687 	/* Shader template */
3688 	static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3689 																 "\n"
3690 																 "precision highp float;\n"
3691 																 "\n"
3692 																 "STAGE_SPECIFIC_LAYOUT"
3693 																 "void main()\n"
3694 																 "{\n"
3695 																 "STAGE_SPECIFIC_MAIN_BODY"
3696 																 "}\n"
3697 																 "\n";
3698 
3699 	std::string string = boilerplate_shader_template_code;
3700 
3701 	/* Tokens */
3702 	static const glw::GLchar* body_token   = "STAGE_SPECIFIC_MAIN_BODY";
3703 	static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3704 
3705 	size_t search_position = 0;
3706 
3707 	/* Replace tokens */
3708 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3709 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3710 
3711 	/* Store resuls */
3712 	out_source_code = string;
3713 }
3714 
3715 /** Prepare program for given combination of shader stage and uniform type
3716  *
3717  * @param shader_stage     Shader stage
3718  * @param uniform_type     Uniform type
3719  * @param out_program_info Instance of programInfo
3720  **/
prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type, Utils::programInfo& out_program_info) const3721 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3722 										Utils::programInfo& out_program_info) const
3723 {
3724 	/* Stage specific layouts */
3725 	static const glw::GLchar* geometry_shader_layout_code = "layout(points)                   in;\n"
3726 															"layout(points, max_vertices = 1) out;\n"
3727 															"\n";
3728 
3729 	static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3730 															 "\n";
3731 
3732 	static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3733 															 "\n";
3734 
3735 	/* Stage specific main body */
3736 	static const glw::GLchar* boilerplate_fragment_shader_body_code = "    discard;\n";
3737 
3738 	static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
3739 																	   "    gl_TessLevelOuter[1] = 1.0;\n"
3740 																	   "    gl_TessLevelOuter[2] = 1.0;\n"
3741 																	   "    gl_TessLevelOuter[3] = 1.0;\n"
3742 																	   "    gl_TessLevelInner[0] = 1.0;\n"
3743 																	   "    gl_TessLevelInner[1] = 1.0;\n";
3744 
3745 	static const glw::GLchar* boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
3746 
3747 	static const glw::GLchar* corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
3748 															   "    {\n"
3749 															   "        gl_Position = vec4(-1, -1, 0, 1);\n"
3750 															   "    }\n"
3751 															   "    else if (1 == gl_VertexID)\n"
3752 															   "    {\n"
3753 															   "        gl_Position = vec4(-1, 1, 0, 1);\n"
3754 															   "    }\n"
3755 															   "    else if (2 == gl_VertexID)\n"
3756 															   "    {\n"
3757 															   "        gl_Position = vec4(1, 1, 0, 1);\n"
3758 															   "    }\n"
3759 															   "    else if (3 == gl_VertexID)\n"
3760 															   "    {\n"
3761 															   "        gl_Position = vec4(1, -1, 0, 1);\n"
3762 															   "    }\n";
3763 
3764 	static const glw::GLchar* passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
3765 
3766 	static const glw::GLchar* test_shader_body_code = "\n    result = verification_result;\n";
3767 
3768 	static const glw::GLchar* test_geometry_shader_body_code = "\n    result = verification_result;\n"
3769 															   "\n"
3770 															   "    EmitVertex();\n"
3771 															   "    EndPrimitive();\n";
3772 
3773 	static const glw::GLchar* test_tess_ctrl_shader_body_code =
3774 		"\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
3775 		"\n"
3776 		"    gl_TessLevelOuter[0] = 1.0;\n"
3777 		"    gl_TessLevelOuter[1] = 1.0;\n"
3778 		"    gl_TessLevelOuter[2] = 1.0;\n"
3779 		"    gl_TessLevelOuter[3] = 1.0;\n"
3780 		"    gl_TessLevelInner[0] = 1.0;\n"
3781 		"    gl_TessLevelInner[1] = 1.0;\n";
3782 
3783 	/* In variables */
3784 	static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
3785 
3786 	/* Out variables */
3787 	static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3788 
3789 	static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3790 
3791 	static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3792 
3793 	/* Varying name */
3794 	static const glw::GLchar* varying_name = "result";
3795 	glw::GLuint				  n_varyings   = 1;
3796 
3797 	/* Storage for ready shaders */
3798 	std::string compute_shader_code;
3799 	std::string fragment_shader_code;
3800 	std::string geometry_shader_code;
3801 	std::string tess_ctrl_shader_code;
3802 	std::string tess_eval_shader_code;
3803 	std::string vertex_shader_code;
3804 
3805 	/* Storage for uniform definition and verification code */
3806 	std::string uniform_definitions;
3807 	std::string uniform_verification;
3808 
3809 	/* Get uniform definition and verification code */
3810 	prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3811 	prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3812 
3813 	/* Prepare vertex shader */
3814 	switch (shader_stage)
3815 	{
3816 	case FRAGMENT_SHADER:
3817 
3818 		prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3819 
3820 		break;
3821 
3822 	case GEOMETRY_SHADER:
3823 	case TESS_CTRL_SHADER:
3824 	case TESS_EVAL_SHADER:
3825 
3826 		prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3827 
3828 		break;
3829 
3830 	case VERTEX_SHADER:
3831 
3832 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3833 						  test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3834 						  test_shader_body_code /* body */, vertex_shader_code);
3835 
3836 		break;
3837 
3838 	default:
3839 		break;
3840 	}
3841 
3842 	/* Prepare fragment shader */
3843 	switch (shader_stage)
3844 	{
3845 	case FRAGMENT_SHADER:
3846 
3847 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3848 						  test_fragment_shader_out_variable /* out var */,
3849 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3850 						  fragment_shader_code);
3851 
3852 		break;
3853 
3854 	case GEOMETRY_SHADER:
3855 	case TESS_CTRL_SHADER:
3856 	case TESS_EVAL_SHADER:
3857 	case VERTEX_SHADER:
3858 
3859 		prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3860 								 fragment_shader_code);
3861 
3862 		break;
3863 
3864 	default:
3865 		break;
3866 	}
3867 
3868 	/* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3869 	switch (shader_stage)
3870 	{
3871 	case COMPUTE_SHADER:
3872 
3873 		prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3874 
3875 		break;
3876 
3877 	case GEOMETRY_SHADER:
3878 
3879 		prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3880 						  "" /* in var */, test_shader_out_variable /* out var */,
3881 						  uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3882 						  geometry_shader_code);
3883 
3884 		break;
3885 
3886 	case TESS_CTRL_SHADER:
3887 
3888 		prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3889 						  "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3890 						  uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3891 						  tess_ctrl_shader_code);
3892 
3893 		prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3894 						  test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3895 						  "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3896 						  tess_eval_shader_code);
3897 
3898 		break;
3899 
3900 	case TESS_EVAL_SHADER:
3901 
3902 		prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3903 								 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3904 
3905 		prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3906 						  "" /* in var */, test_shader_out_variable /* out var */,
3907 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3908 						  tess_eval_shader_code);
3909 
3910 		break;
3911 
3912 	default:
3913 		break;
3914 	}
3915 
3916 	/* Select shaders that will be used by program */
3917 	const glw::GLchar* cs_c_str  = 0;
3918 	const glw::GLchar* fs_c_str  = 0;
3919 	const glw::GLchar* gs_c_str  = 0;
3920 	const glw::GLchar* tcs_c_str = 0;
3921 	const glw::GLchar* tes_c_str = 0;
3922 	const glw::GLchar* vs_c_str  = 0;
3923 
3924 	if (false == compute_shader_code.empty())
3925 	{
3926 		cs_c_str = compute_shader_code.c_str();
3927 	}
3928 
3929 	if (false == fragment_shader_code.empty())
3930 	{
3931 		fs_c_str = fragment_shader_code.c_str();
3932 	}
3933 
3934 	if (false == geometry_shader_code.empty())
3935 	{
3936 		gs_c_str = geometry_shader_code.c_str();
3937 	}
3938 
3939 	if (false == tess_ctrl_shader_code.empty())
3940 	{
3941 		tcs_c_str = tess_ctrl_shader_code.c_str();
3942 	}
3943 
3944 	if (false == tess_eval_shader_code.empty())
3945 	{
3946 		tes_c_str = tess_eval_shader_code.c_str();
3947 	}
3948 
3949 	if (false == vertex_shader_code.empty())
3950 	{
3951 		vs_c_str = vertex_shader_code.c_str();
3952 	}
3953 
3954 	/* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3955 	if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3956 	{
3957 		n_varyings = 0;
3958 	}
3959 
3960 	/* Build */
3961 	out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
3962 }
3963 
3964 /** Prepare collection of tested shader stages
3965  *
3966  */
prepareShaderStages()3967 void GPUShaderFP64Test2::prepareShaderStages()
3968 {
3969 	/* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3970 	if (0 != m_pDispatchCompute)
3971 	{
3972 		m_shader_stages.push_back(COMPUTE_SHADER);
3973 	}
3974 
3975 	m_shader_stages.push_back(FRAGMENT_SHADER);
3976 	m_shader_stages.push_back(GEOMETRY_SHADER);
3977 	m_shader_stages.push_back(TESS_CTRL_SHADER);
3978 	m_shader_stages.push_back(TESS_EVAL_SHADER);
3979 	m_shader_stages.push_back(VERTEX_SHADER);
3980 }
3981 
3982 /** Prepare source code for "tested" shader stage
3983  *
3984  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3985  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
3986  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
3987  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
3988  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
3989  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3990  * @param out_source_code          Shader source code
3991  **/
prepareTestShader(const glw::GLchar* stage_specific_layout, const glw::GLchar* uniform_definitions, const glw::GLchar* in_variable_definitions, const glw::GLchar* out_variable_definitions, const glw::GLchar* uniform_verification, const glw::GLchar* stage_specific_main_body, std::string& out_source_code) const3992 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
3993 										   const glw::GLchar* uniform_definitions,
3994 										   const glw::GLchar* in_variable_definitions,
3995 										   const glw::GLchar* out_variable_definitions,
3996 										   const glw::GLchar* uniform_verification,
3997 										   const glw::GLchar* stage_specific_main_body,
3998 										   std::string&		  out_source_code) const
3999 {
4000 	/* Shader template */
4001 	static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4002 														  "\n"
4003 														  "precision highp float;\n"
4004 														  "\n"
4005 														  "STAGE_SPECIFIC_LAYOUT"
4006 														  "UNIFORM_DEFINITIONS"
4007 														  "IN_VARIABLE_DEFINITION"
4008 														  "OUT_VARIABLE_DEFINITION"
4009 														  "\n"
4010 														  "void main()\n"
4011 														  "{\n"
4012 														  "UNIFORM_VERIFICATION"
4013 														  "STAGE_SPECIFIC_MAIN_BODY"
4014 														  "}\n"
4015 														  "\n";
4016 
4017 	std::string string = test_shader_template_code;
4018 
4019 	/* Tokens */
4020 	static const glw::GLchar* body_token	= "STAGE_SPECIFIC_MAIN_BODY";
4021 	static const glw::GLchar* in_var_token  = "IN_VARIABLE_DEFINITION";
4022 	static const glw::GLchar* layout_token  = "STAGE_SPECIFIC_LAYOUT";
4023 	static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4024 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4025 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4026 
4027 	size_t search_position = 0;
4028 
4029 	/* Replace tokens */
4030 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4031 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4032 	Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4033 	Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4034 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4035 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4036 
4037 	/* Store resuls */
4038 	out_source_code = string;
4039 }
4040 
4041 /** Prepare source code for "tested" compute shaders
4042  *
4043  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
4044  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4045  * @param out_source_code      Source code
4046  **/
prepareTestComputeShader(const glw::GLchar* uniform_definitions, const glw::GLchar* uniform_verification, std::string& out_source_code) const4047 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4048 												  const glw::GLchar* uniform_verification,
4049 												  std::string&		 out_source_code) const
4050 {
4051 	/* Shader template */
4052 	static const glw::GLchar* test_shader_template_code =
4053 		"#version 420 core\n"
4054 		"#extension GL_ARB_compute_shader          : require\n"
4055 		"#extension GL_ARB_shader_image_load_store : require\n"
4056 		"\n"
4057 		"precision highp float;\n"
4058 		"\n"
4059 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4060 		"\n"
4061 		"UNIFORM_DEFINITIONS"
4062 		"layout(r32i) writeonly uniform iimage2D result;\n"
4063 		"\n"
4064 		"void main()\n"
4065 		"{\n"
4066 		"UNIFORM_VERIFICATION"
4067 		"\n"
4068 		"    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4069 		"}\n"
4070 		"\n";
4071 
4072 	std::string string = test_shader_template_code;
4073 
4074 	/* Tokens */
4075 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4076 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4077 
4078 	size_t search_position = 0;
4079 
4080 	/* Replace tokens */
4081 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4082 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083 
4084 	/* Store resuls */
4085 	out_source_code = string;
4086 }
4087 
4088 /** Prepare source code which defines uniforms for tested shader stage
4089  *
4090  * @param shader_stage    Shader stage id
4091  * @param uniform_type    Details of uniform type
4092  * @param out_source_code Source code
4093  **/
prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type, std::string& out_source_code) const4094 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4095 												   std::string& out_source_code) const
4096 {
4097 	const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4098 	std::stringstream stream;
4099 
4100 	/*
4101 	 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4102 	 * {
4103 	 *     TYPE_NAME uniform_array[N_UNIFORMS];
4104 	 * };
4105 	 */
4106 	stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4107 																   "{\n";
4108 
4109 	stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4110 
4111 	stream << "};\n\n";
4112 
4113 	out_source_code = stream.str();
4114 }
4115 
4116 /** Prepare uniform buffer for test
4117  *
4118  * @param shader_stage Shader stage id
4119  * @param uniform_type Details of uniform type
4120  * @param program_info Program object info
4121  **/
prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type, const Utils::programInfo& program_info) const4122 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4123 										 const Utils::programInfo& program_info) const
4124 {
4125 	glw::GLint				  buffer_size	 = 0;
4126 	glw::GLuint				  element_ordinal = 1;
4127 	const glw::Functions&	 gl			  = m_context.getRenderContext().getFunctions();
4128 	const glw::GLuint		  n_columns		  = uniform_type.m_n_columns;
4129 	const glw::GLuint		  n_rows		  = uniform_type.m_n_rows;
4130 	const glw::GLuint		  n_elements	  = n_columns * n_rows;
4131 	uniformDetails			  uniform_details;
4132 	const glw::GLuint		  program_id = program_info.m_program_object_id;
4133 	const glw::GLint		  n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4134 	std::vector<glw::GLubyte> uniform_buffer_data;
4135 	glw::GLuint				  uniform_block_index = 0;
4136 
4137 	/* Get uniform details */
4138 	inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4139 
4140 	/* Uniform offset and strides */
4141 	const glw::GLuint array_stride   = uniform_details.m_array_stride;
4142 	const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
4143 	const glw::GLuint uniform_offset = uniform_details.m_offset;
4144 
4145 	/* Prepare storage for buffer data */
4146 	uniform_buffer_data.resize(buffer_size);
4147 
4148 	/* Prepare uniform data */
4149 	for (glw::GLint i = 0; i < n_uniforms; ++i)
4150 	{
4151 		const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4152 
4153 		for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4154 		{
4155 			const glw::GLuint   column		 = element / n_rows;
4156 			const glw::GLuint   column_elem  = element % n_rows;
4157 			const glw::GLdouble value		 = element_ordinal;
4158 			const glw::GLuint   value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4159 																	  column_elem * sizeof(glw::GLdouble));
4160 			glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4161 
4162 			*value_dst = value;
4163 		}
4164 	}
4165 
4166 	/* Update uniform buffer with new set of data */
4167 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4168 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4169 
4170 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4171 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4172 
4173 	/* Bind uniform block to uniform buffer */
4174 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4175 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4176 
4177 	gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4178 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4179 }
4180 
4181 /** Prepare collection of tested uniform types
4182  *
4183  **/
prepareUniformTypes()4184 void GPUShaderFP64Test2::prepareUniformTypes()
4185 {
4186 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4187 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4188 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4189 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4190 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4191 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4192 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4193 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4194 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4195 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4196 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4197 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4198 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4199 }
4200 
4201 /** Prepare source code that verifes uniform values
4202  *
4203  * @param shader_stage    Shader stage id
4204  * @param uniform_type    Details of uniform type
4205  * @param out_source_code Source code
4206  **/
prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type, std::string& out_source_code) const4207 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4208 													std::string& out_source_code) const
4209 {
4210 	glw::GLuint		  element_ordinal = 1;
4211 	const glw::GLuint n_columns		  = uniform_type.m_n_columns;
4212 	const glw::GLuint n_rows		  = uniform_type.m_n_rows;
4213 	const glw::GLuint n_elements	  = n_columns * n_rows;
4214 	const glw::GLuint n_uniforms	  = getAmountUniforms(shader_stage, uniform_type);
4215 	std::stringstream stream;
4216 
4217 	/*
4218 	 * int verification_result = M_RESULT_SUCCESS;
4219 	 *
4220 	 * for (int i = 0; i < N_UNIFORMS; ++i)
4221 	 * {
4222 	 *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4223 	 *     {
4224 	 *         verification_result = M_RESULT_FAILURE
4225 	 *     }
4226 	 * }
4227 	 */
4228 	stream << "    int verification_result = " << m_result_success << ";\n"
4229 																	  "\n"
4230 																	  "    for (int i = 0; i < "
4231 		   << n_uniforms << "; ++i)\n"
4232 							"    {\n"
4233 							"        if ("
4234 		   << uniform_type.m_type_name << "(";
4235 
4236 	for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4237 	{
4238 		stream << "i * (" << n_elements << ") + " << element + 1;
4239 
4240 		if (n_elements != element + 1)
4241 		{
4242 			stream << ", ";
4243 		}
4244 	}
4245 
4246 	stream << ") != uniform_array[i])\n"
4247 			  "        {\n"
4248 			  "           verification_result = "
4249 		   << m_result_failure << ";\n"
4250 								  "        }\n"
4251 								  "    }\n";
4252 
4253 	out_source_code = stream.str();
4254 }
4255 
4256 /** Execute test for given combination of "tested" shader stage and uniform type
4257  *
4258  * @param shader_stage Tested shader stage id
4259  * @param uniform_type Tested uniform type
4260  *
4261  * @return true if test passed, false otherwise
4262  **/
test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const4263 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4264 {
4265 	const glw::GLenum		draw_primitive = getDrawPrimitiveType(shader_stage);
4266 	static const glw::GLint first_vertex   = 0;
4267 	const glw::Functions&   gl			   = m_context.getRenderContext().getFunctions();
4268 	const glw::GLsizei		n_vertices	 = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4269 	Utils::programInfo		program_info(m_context);
4270 	bool					result = true;
4271 
4272 	/* Prepare program */
4273 	prepareProgram(shader_stage, uniform_type, program_info);
4274 
4275 	gl.useProgram(program_info.m_program_object_id);
4276 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4277 
4278 	/* Prepare uniform buffer and bind it with uniform block */
4279 	prepareUniforms(shader_stage, uniform_type, program_info);
4280 
4281 	/* Prepare storage for test results */
4282 	testBegin(program_info.m_program_object_id, shader_stage);
4283 
4284 	/* Execute */
4285 	if (COMPUTE_SHADER == shader_stage)
4286 	{
4287 		m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4288 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4289 	}
4290 	else
4291 	{
4292 		gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4293 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4294 	}
4295 
4296 	/* Clean after test */
4297 	testEnd(shader_stage);
4298 
4299 	/* Check results */
4300 	if (false == verifyResults(shader_stage))
4301 	{
4302 		m_context.getTestContext().getLog()
4303 			<< tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4304 			<< ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4305 
4306 		result = false;
4307 	}
4308 
4309 	return result;
4310 }
4311 
4312 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4313  *
4314  * @param program_id   Program object id
4315  * @param shader_stage Tested shader stage id
4316  **/
testBegin(glw::GLuint program_id, shaderStage shader_stage) const4317 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4318 {
4319 	std::vector<glw::GLint> buffer_data;
4320 	const glw::GLenum		captured_primitive = getCapturedPrimitiveType(shader_stage);
4321 	const glw::Functions&   gl				   = m_context.getRenderContext().getFunctions();
4322 
4323 	/* Prepare buffer filled with m_result_failure */
4324 	buffer_data.resize(m_n_captured_results);
4325 	for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4326 	{
4327 		buffer_data[i] = m_result_failure;
4328 	}
4329 
4330 	/* Prepare buffer for test results */
4331 	switch (shader_stage)
4332 	{
4333 	case GEOMETRY_SHADER:
4334 	case TESS_CTRL_SHADER:
4335 	case TESS_EVAL_SHADER:
4336 	case VERTEX_SHADER:
4337 
4338 		/* Verify getTransformFeedbackVarying results */
4339 		{
4340 			glw::GLsizei size = 0;
4341 			glw::GLenum  type = 0;
4342 			glw::GLchar  name[16];
4343 
4344 			gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4345 										   name);
4346 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4347 
4348 			if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4349 			{
4350 				m_context.getTestContext().getLog()
4351 					<< tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4352 					<< " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4353 					<< ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4354 
4355 				TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4356 			}
4357 		}
4358 
4359 		/* Create/clean transform feedback buffer */
4360 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4361 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4362 
4363 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4364 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4365 
4366 		/* Set up transform feedback buffer */
4367 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4368 						   m_transform_feedback_buffer_size);
4369 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4370 
4371 		gl.beginTransformFeedback(captured_primitive);
4372 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4373 
4374 		break;
4375 
4376 	case FRAGMENT_SHADER:
4377 
4378 		/* Clean texture */
4379 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4380 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4381 
4382 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4383 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4385 
4386 		/* Set up texture as color attachment 0 */
4387 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4388 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4389 
4390 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4391 		GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4392 
4393 		gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4394 		GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4395 
4396 		break;
4397 
4398 	case COMPUTE_SHADER:
4399 
4400 		/* Clean texture */
4401 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4402 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4403 
4404 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4405 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4406 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4407 
4408 		glw::GLint location = gl.getUniformLocation(program_id, "result");
4409 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4410 
4411 		if (-1 == location)
4412 		{
4413 			TCU_FAIL("Inactive uniform \"result\"");
4414 		}
4415 
4416 		gl.uniform1i(location, 0 /* first image unit */);
4417 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4418 
4419 		/* Bind texture to first image unit */
4420 		gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4421 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4422 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4423 
4424 		break;
4425 	}
4426 }
4427 
4428 /** Unbind transform feedback buffer, framebuffer or image unit
4429  *
4430  * @param shader_stage Tested shader stage id
4431  **/
testEnd(shaderStage shader_stage) const4432 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4433 {
4434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4435 
4436 	switch (shader_stage)
4437 	{
4438 	case GEOMETRY_SHADER:
4439 	case TESS_CTRL_SHADER:
4440 	case TESS_EVAL_SHADER:
4441 	case VERTEX_SHADER:
4442 
4443 		gl.endTransformFeedback();
4444 
4445 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4446 
4447 		break;
4448 
4449 	case FRAGMENT_SHADER:
4450 
4451 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4452 								0 /* level */);
4453 
4454 		gl.bindTexture(GL_TEXTURE_2D, 0);
4455 
4456 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4457 
4458 		break;
4459 
4460 	case COMPUTE_SHADER:
4461 
4462 		gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4463 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4464 
4465 		break;
4466 	}
4467 }
4468 
4469 /** Initialize OpenGL objects for test
4470  *
4471  **/
testInit()4472 void GPUShaderFP64Test2::testInit()
4473 {
4474 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4475 
4476 	/* The test is in 4.0 group. However:
4477 	 * - compute_shader is core since 4.3
4478 	 * - compute_shader require at least version 4.2 of GL */
4479 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4480 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4481 	{
4482 		m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4483 	}
4484 
4485 	/* Tesselation patch set up */
4486 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
4487 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4488 
4489 	/* Generate FBO */
4490 	gl.genFramebuffers(1, &m_framebuffer_id);
4491 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4492 
4493 	/* Prepare texture */
4494 	gl.genTextures(1, &m_texture_id);
4495 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4496 
4497 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4498 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4499 
4500 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4501 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4502 
4503 	/* Prepare transform feedback buffer */
4504 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
4505 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4506 
4507 	/* Generate uniform buffer */
4508 	gl.genBuffers(1, &m_uniform_buffer_id);
4509 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4510 
4511 	/* Prepare VAO */
4512 	gl.genVertexArrays(1, &m_vertex_array_object_id);
4513 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4514 
4515 	gl.bindVertexArray(m_vertex_array_object_id);
4516 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4517 }
4518 
4519 /** Result verification, expected result is that whole buffer is filled with m_result_success
4520  *
4521  * @param shader_stage Tested shader stage id
4522  **/
verifyResults(shaderStage shader_stage) const4523 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4524 {
4525 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4526 
4527 	if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4528 	{
4529 		/* Verify contents of texture */
4530 
4531 		/* Prepare storage for testure data */
4532 		std::vector<glw::GLint> image_data;
4533 		image_data.resize(m_texture_width * m_texture_height);
4534 
4535 		/* Get texture contents */
4536 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4537 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4538 
4539 		gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4540 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4541 
4542 		for (glw::GLuint y = 0; y < m_texture_width; ++y)
4543 		{
4544 			for (glw::GLuint x = 0; x < m_texture_height; ++x)
4545 			{
4546 				const glw::GLuint offset = y * m_texture_width + x;
4547 				const glw::GLint  value  = image_data[offset];
4548 
4549 				if (m_result_success != value)
4550 				{
4551 					m_context.getTestContext().getLog()
4552 						<< tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4553 						<< tcu::TestLog::EndMessage;
4554 
4555 					return false;
4556 				}
4557 			}
4558 		}
4559 
4560 		return true;
4561 	}
4562 	else
4563 	{
4564 		/* Verify contents of transform feedback buffer */
4565 
4566 		bool result = true;
4567 
4568 		/* Get transform feedback data */
4569 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4570 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4571 
4572 		glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4573 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4574 
4575 		for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4576 		{
4577 			const glw::GLint value = feedback_data[i];
4578 
4579 			if (m_result_success != value)
4580 			{
4581 				m_context.getTestContext().getLog() << tcu::TestLog::Message
4582 													<< "Error. Transform feedback buffer contents are wrong at " << i
4583 													<< tcu::TestLog::EndMessage;
4584 
4585 				result = false;
4586 				break;
4587 			}
4588 		}
4589 
4590 		/* Unmap transform feedback buffer */
4591 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4592 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4593 
4594 		return result;
4595 	}
4596 }
4597 
4598 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4599 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4600 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4601 
4602 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name			 = "UniformBlock";
4603 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4604 
4605 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
4606 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result	= "gs_fs_gs_result";
4607 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
4608 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
4609 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result	= "gs_fs_vs_result";
4610 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4611 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
4612 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
4613 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
4614 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
4615 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
4616 
4617 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4618 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset			 = -1;
4619 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride	= -1;
4620 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4621 
4622 /** Constructor
4623  *
4624  * @param context Test context
4625  **/
GPUShaderFP64Test3(deqp::Context& context)4626 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4627 	: TestCase(context, "named_uniform_blocks",
4628 			   "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4629 {
4630 	/* Nothing to be done */
4631 }
4632 
4633 /** Deinitialize test
4634  *
4635  **/
deinit()4636 void GPUShaderFP64Test3::deinit()
4637 {
4638 	/* GL entry points */
4639 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4640 
4641 	/* Clean programs */
4642 	m_packed_program.deinit(m_context);
4643 	m_shared_program.deinit(m_context);
4644 	m_std140_program.deinit(m_context);
4645 
4646 	/* Clean frambuffer */
4647 	if (0 != m_framebuffer_id)
4648 	{
4649 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4650 		gl.deleteFramebuffers(1, &m_framebuffer_id);
4651 
4652 		m_framebuffer_id = 0;
4653 	}
4654 
4655 	/* Clean texture */
4656 	if (0 != m_color_texture_id)
4657 	{
4658 		gl.bindTexture(GL_TEXTURE_2D, 0);
4659 		gl.deleteTextures(1, &m_color_texture_id);
4660 
4661 		m_color_texture_id = 0;
4662 	}
4663 
4664 	/* Clean buffers */
4665 	if (0 != m_transform_feedback_buffer_id)
4666 	{
4667 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4668 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4669 
4670 		m_transform_feedback_buffer_id = 0;
4671 	}
4672 
4673 	if (0 != m_uniform_buffer_id)
4674 	{
4675 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4676 		gl.deleteBuffers(1, &m_uniform_buffer_id);
4677 
4678 		m_uniform_buffer_id = 0;
4679 	}
4680 
4681 	/* Clean VAO */
4682 	if (0 != m_vertex_array_object_id)
4683 	{
4684 		gl.bindVertexArray(0);
4685 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4686 
4687 		m_vertex_array_object_id = 0;
4688 	}
4689 }
4690 
4691 /** Execute test
4692  *
4693  * @return tcu::TestNode::STOP
4694  **/
iterate()4695 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4696 {
4697 	bool result = true;
4698 
4699 	/* Check if extension is supported */
4700 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4701 	{
4702 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4703 	}
4704 
4705 	/* Initialize test */
4706 	testInit();
4707 
4708 	/* Test "packed" uniform buffer layout */
4709 	if (false == test(PACKED))
4710 	{
4711 		result = false;
4712 	}
4713 
4714 	/* Test "shared" uniform buffer layout */
4715 	if (false == test(SHARED))
4716 	{
4717 		result = false;
4718 	}
4719 
4720 	/* Test "std140" uniform buffer layout */
4721 	if (false == test(STD140))
4722 	{
4723 		result = false;
4724 	}
4725 
4726 	/* Set result */
4727 	if (true == result)
4728 	{
4729 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4730 	}
4731 	else
4732 	{
4733 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4734 	}
4735 
4736 	/* Done */
4737 	return tcu::TestNode::STOP;
4738 }
4739 
4740 /** Constructor
4741  *
4742  **/
programInfo()4743 GPUShaderFP64Test3::programInfo::programInfo()
4744 	: m_fragment_shader_id(0)
4745 	, m_geometry_shader_id(0)
4746 	, m_program_object_id(0)
4747 	, m_tesselation_control_shader_id(0)
4748 	, m_tesselation_evaluation_shader_id(0)
4749 	, m_vertex_shader_id(0)
4750 	, m_buffer_size(0)
4751 	, m_uniform_block_index(0)
4752 {
4753 	/* Nothing to be done here */
4754 }
4755 
4756 /** Compile shader
4757  *
4758  * @param context     Test context
4759  * @param shader_id   Shader object id
4760  * @param shader_code Shader source code
4761  **/
compile(deqp::Context& context, glw::GLuint shader_id, const glw::GLchar* shader_code) const4762 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4763 											  const glw::GLchar* shader_code) const
4764 {
4765 	/* GL entry points */
4766 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4767 
4768 	/* Compilation status */
4769 	glw::GLint status = GL_FALSE;
4770 
4771 	/* Set source code */
4772 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4773 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4774 
4775 	/* Compile */
4776 	gl.compileShader(shader_id);
4777 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4778 
4779 	/* Get compilation status */
4780 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4781 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4782 
4783 	/* Log compilation error */
4784 	if (GL_TRUE != status)
4785 	{
4786 		glw::GLint				 length = 0;
4787 		std::vector<glw::GLchar> message;
4788 
4789 		/* Error log length */
4790 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4791 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4792 
4793 		/* Prepare storage */
4794 		message.resize(length);
4795 
4796 		/* Get error log */
4797 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4798 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4799 
4800 		/* Log */
4801 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4802 										  << &message[0] << "\nShader source\n"
4803 										  << shader_code << tcu::TestLog::EndMessage;
4804 
4805 		TCU_FAIL("Failed to compile shader");
4806 	}
4807 }
4808 
4809 /** Cleans program and attached shaders
4810  *
4811  * @param context Test context
4812  **/
deinit(deqp::Context& context)4813 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4814 {
4815 	/* GL entry points */
4816 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4817 
4818 	/* Restore default program */
4819 	gl.useProgram(0);
4820 
4821 	/* Clean program object */
4822 	if (0 != m_program_object_id)
4823 	{
4824 		gl.deleteProgram(m_program_object_id);
4825 		m_program_object_id = 0;
4826 	}
4827 
4828 	/* Clean shaders */
4829 	if (0 != m_fragment_shader_id)
4830 	{
4831 		gl.deleteShader(m_fragment_shader_id);
4832 		m_fragment_shader_id = 0;
4833 	}
4834 
4835 	if (0 != m_geometry_shader_id)
4836 	{
4837 		gl.deleteShader(m_geometry_shader_id);
4838 		m_geometry_shader_id = 0;
4839 	}
4840 
4841 	if (0 != m_tesselation_control_shader_id)
4842 	{
4843 		gl.deleteShader(m_tesselation_control_shader_id);
4844 		m_tesselation_control_shader_id = 0;
4845 	}
4846 
4847 	if (0 != m_tesselation_evaluation_shader_id)
4848 	{
4849 		gl.deleteShader(m_tesselation_evaluation_shader_id);
4850 		m_tesselation_evaluation_shader_id = 0;
4851 	}
4852 
4853 	if (0 != m_vertex_shader_id)
4854 	{
4855 		gl.deleteShader(m_vertex_shader_id);
4856 		m_vertex_shader_id = 0;
4857 	}
4858 }
4859 
4860 /** Build program and query for uniform layout
4861  *
4862  * @param context                            Test context
4863  * @param uniform_details                  Collection of uniform details
4864  * @param fragment_shader_code               Fragment shader source code
4865  * @param geometry_shader_code               Geometry shader source code
4866  * @param tesselation_control_shader_code    Tesselation control shader source code
4867  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4868  * @param vertex_shader_code                 Vertex shader source code
4869  **/
init(deqp::Context& context, const std::vector<uniformDetails> uniform_details, const glw::GLchar* fragment_shader_code, const glw::GLchar* geometry_shader_code, const glw::GLchar* tesselation_control_shader_code, const glw::GLchar* tesselation_evaluation_shader_code, const glw::GLchar* vertex_shader_code)4870 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4871 										   const glw::GLchar* fragment_shader_code,
4872 										   const glw::GLchar* geometry_shader_code,
4873 										   const glw::GLchar* tesselation_control_shader_code,
4874 										   const glw::GLchar* tesselation_evaluation_shader_code,
4875 										   const glw::GLchar* vertex_shader_code)
4876 {
4877 	/* GL entry points */
4878 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4879 
4880 	/* Names of varyings to be captured with transform feedback */
4881 	static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4882 												  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4883 	static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4884 
4885 	/* Create shader objects */
4886 	m_fragment_shader_id			   = gl.createShader(GL_FRAGMENT_SHADER);
4887 	m_geometry_shader_id			   = gl.createShader(GL_GEOMETRY_SHADER);
4888 	m_tesselation_control_shader_id	= gl.createShader(GL_TESS_CONTROL_SHADER);
4889 	m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4890 	m_vertex_shader_id				   = gl.createShader(GL_VERTEX_SHADER);
4891 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4892 
4893 	/* Create program object */
4894 	m_program_object_id = gl.createProgram();
4895 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4896 
4897 	/* Set up names of varyings to be captured with transform feedback */
4898 	gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4899 	GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4900 
4901 	/* Compile shaders */
4902 	compile(context, m_fragment_shader_id, fragment_shader_code);
4903 	compile(context, m_geometry_shader_id, geometry_shader_code);
4904 	compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4905 	compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4906 	compile(context, m_vertex_shader_id, vertex_shader_code);
4907 
4908 	/* Link program */
4909 	link(context);
4910 
4911 	/* Inspect program object */
4912 	/* Get index of named uniform block */
4913 	m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4914 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4915 
4916 	if (GL_INVALID_INDEX == m_uniform_block_index)
4917 	{
4918 		TCU_FAIL("Unifom block is inactive");
4919 	}
4920 
4921 	/* Get size of named uniform block */
4922 	gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4923 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4924 
4925 	if (0 == m_buffer_size)
4926 	{
4927 		TCU_FAIL("Unifom block size is 0");
4928 	}
4929 
4930 	/* Get information about "double precision" uniforms */
4931 	for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4932 		 end != it; ++it)
4933 	{
4934 		const glw::GLchar* uniform_name = 0;
4935 		std::string		   uniform_name_str;
4936 		std::stringstream  uniform_name_stream;
4937 		glw::GLuint		   index		 = 0;
4938 		glw::GLint		   offset		 = 0;
4939 		glw::GLint		   matrix_stride = 0;
4940 
4941 		/* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4942 		uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4943 
4944 		uniform_name_str = uniform_name_stream.str();
4945 		uniform_name	 = uniform_name_str.c_str();
4946 
4947 		/* Get index of uniform */
4948 		gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4949 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4950 
4951 		if (GL_INVALID_INDEX == index)
4952 		{
4953 			TCU_FAIL("Unifom is inactive");
4954 		}
4955 
4956 		/* Get offset of uniform */
4957 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4958 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4959 
4960 		if (m_invalid_uniform_offset == offset)
4961 		{
4962 			TCU_FAIL("Unifom has invalid offset");
4963 		}
4964 
4965 		m_uniform_offsets.push_back(offset);
4966 
4967 		/* Get matrix stride of uniform */
4968 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4969 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4970 
4971 		if (m_invalid_uniform_matrix_stride == offset)
4972 		{
4973 			TCU_FAIL("Unifom has invalid matrix stride");
4974 		}
4975 
4976 		m_uniform_matrix_strides.push_back(matrix_stride);
4977 	}
4978 }
4979 
4980 /** Attach shaders and link program
4981  *
4982  * @param context Test context
4983  **/
link(deqp::Context& context) const4984 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4985 {
4986 	/* GL entry points */
4987 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4988 
4989 	/* Link status */
4990 	glw::GLint status = GL_FALSE;
4991 
4992 	/* Attach shaders */
4993 	gl.attachShader(m_program_object_id, m_fragment_shader_id);
4994 	gl.attachShader(m_program_object_id, m_geometry_shader_id);
4995 	gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
4996 	gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
4997 	gl.attachShader(m_program_object_id, m_vertex_shader_id);
4998 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
4999 
5000 	/* Link */
5001 	gl.linkProgram(m_program_object_id);
5002 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5003 
5004 	/* Get link status */
5005 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5006 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5007 
5008 	/* Log link error */
5009 	if (GL_TRUE != status)
5010 	{
5011 		glw::GLint				 length = 0;
5012 		std::vector<glw::GLchar> message;
5013 
5014 		/* Get error log length */
5015 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5016 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5017 
5018 		message.resize(length);
5019 
5020 		/* Get error log */
5021 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5022 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5023 
5024 		/* Log */
5025 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5026 										  << &message[0] << tcu::TestLog::EndMessage;
5027 
5028 		TCU_FAIL("Failed to link program");
5029 	}
5030 }
5031 
5032 /** Returns "predefined" values that will be used to fill uniform data
5033  *
5034  * @param type_ordinal Ordinal number of "double precision" uniform type
5035  * @param element      Index of element in uniform
5036  *
5037  * @return "Predefined" value
5038  **/
getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const5039 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5040 {
5041 	return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5042 		   ((m_base_element - (glw::GLdouble)element) / 4.0);
5043 }
5044 
5045 /** Returns a reference of programInfo instance specific for given buffer layout
5046  *
5047  * @param uniform_data_layout Buffer layout
5048  *
5049  * @return Reference to an instance of programInfo
5050  **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5051 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5052 {
5053 	const programInfo* program_info = 0;
5054 
5055 	switch (uniform_data_layout)
5056 	{
5057 	case PACKED:
5058 
5059 		program_info = &m_packed_program;
5060 
5061 		break;
5062 
5063 	case SHARED:
5064 
5065 		program_info = &m_shared_program;
5066 
5067 		break;
5068 
5069 	case STD140:
5070 
5071 		program_info = &m_std140_program;
5072 
5073 		break;
5074 	}
5075 
5076 	return *program_info;
5077 }
5078 
5079 /** Get "name" of buffer layout
5080  *
5081  * @param uniform_data_layout Buffer layout
5082  *
5083  * @return "Name" of layout
5084  **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5085 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5086 {
5087 	const glw::GLchar* layout = "";
5088 
5089 	switch (uniform_data_layout)
5090 	{
5091 	case PACKED:
5092 		layout = "packed";
5093 		break;
5094 	case SHARED:
5095 		layout = "shared";
5096 		break;
5097 	case STD140:
5098 		layout = "std140";
5099 		break;
5100 	}
5101 
5102 	return layout;
5103 }
5104 
5105 /** Prepare programInfo instance for specific buffer layout
5106  *
5107  * @param program_info        Instance of programInfo
5108  * @param uniform_data_layout Buffer layout
5109  **/
prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const5110 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5111 {
5112 	/* Storage for shader source code */
5113 	std::stringstream fragment_shader_code;
5114 	std::stringstream geometry_shader_code;
5115 	std::stringstream tess_control_shader_code;
5116 	std::stringstream tess_eval_shader_code;
5117 	std::stringstream vertex_shader_code;
5118 
5119 	/* Write preambles */
5120 	writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5121 	writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5122 	writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5123 	writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5124 	writePreamble(vertex_shader_code, VERTEX_SHADER);
5125 
5126 	/* Write definition of named uniform block */
5127 	writeUniformBlock(fragment_shader_code, uniform_data_layout);
5128 	writeUniformBlock(geometry_shader_code, uniform_data_layout);
5129 	writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5130 	writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5131 	writeUniformBlock(vertex_shader_code, uniform_data_layout);
5132 
5133 	/* Write definitions of varyings */
5134 	writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5135 	writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5136 	writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5137 	writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5138 	writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5139 
5140 	/* Write main routine */
5141 	writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5142 	writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5143 	writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5144 	writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5145 	writeMainBody(vertex_shader_code, VERTEX_SHADER);
5146 
5147 	/* Init programInfo instance */
5148 	program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5149 					  geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5150 					  tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5151 }
5152 
5153 /** Prepare uniform buffer
5154  *
5155  * @param program_info   Instance of programInfo
5156  * @param verify_offsets If uniform offsets should be verified against expected values
5157  *
5158  * @return false if uniform offsets verification result is failure, true otherwise
5159  **/
prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const5160 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5161 {
5162 	const glw::GLuint							buffer_size = program_info.m_buffer_size;
5163 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
5164 	bool										offset_verification_result = true;
5165 	glw::GLuint									type_ordinal			   = 1;
5166 	std::vector<uniformDetails>::const_iterator it_uniform_details		   = m_uniform_details.begin();
5167 	std::vector<glw::GLint>::const_iterator		it_uniform_offsets		   = program_info.m_uniform_offsets.begin();
5168 	std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5169 
5170 	/* Prepare storage for uniform buffer data */
5171 	std::vector<glw::GLubyte> buffer_data;
5172 	buffer_data.resize(buffer_size);
5173 
5174 	/* For each "double precision" uniform */
5175 	for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5176 		 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5177 	{
5178 		const glw::GLint  matrix_stride  = *it_uniform_matrix_strides;
5179 		const glw::GLuint n_columns		 = it_uniform_details->m_n_columns;
5180 		const glw::GLuint n_elements	 = it_uniform_details->m_n_elements;
5181 		const glw::GLuint column_length  = n_elements / n_columns;
5182 		const glw::GLint  uniform_offset = *it_uniform_offsets;
5183 
5184 		/* For each element of uniform */
5185 		for (glw::GLuint element = 0; element < n_elements; ++element)
5186 		{
5187 			const glw::GLuint   column		= element / column_length;
5188 			const glw::GLuint   column_elem = element % column_length;
5189 			const glw::GLdouble value		= getExpectedValue(type_ordinal, element);
5190 			const glw::GLuint   value_offset =
5191 				static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5192 
5193 			glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5194 
5195 			/* Store value */
5196 			*value_dst = value;
5197 		}
5198 
5199 		/* Uniform offset verification */
5200 		if (true == verify_offsets)
5201 		{
5202 			const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5203 
5204 			if (expected_offset != uniform_offset)
5205 			{
5206 				if (true == offset_verification_result)
5207 				{
5208 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5209 				}
5210 
5211 				m_context.getTestContext().getLog()
5212 					<< tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5213 					<< " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5214 					<< tcu::TestLog::EndMessage;
5215 
5216 				offset_verification_result = false;
5217 			}
5218 		}
5219 	}
5220 
5221 	/* Update uniform buffer with prepared data */
5222 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5223 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5224 
5225 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5226 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5227 
5228 	/* Bind uniform buffer as data source for named uniform block */
5229 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5230 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5231 
5232 	gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5233 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5234 
5235 	/* Done */
5236 	return offset_verification_result;
5237 }
5238 
5239 /** Prepare data, execute draw call and verify results
5240  *
5241  * @param uniform_data_layout
5242  *
5243  * @return true if test pass, false otherwise
5244  **/
test(uniformDataLayout uniform_data_layout) const5245 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5246 {
5247 	bool				  are_offsets_verified		 = (STD140 == uniform_data_layout);
5248 	const glw::Functions& gl						 = m_context.getRenderContext().getFunctions();
5249 	bool				  offset_verification_result = true;
5250 	const programInfo&	program_info				 = getProgramInfo(uniform_data_layout);
5251 	bool				  result					 = true;
5252 
5253 	/* Set up program */
5254 	gl.useProgram(program_info.m_program_object_id);
5255 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5256 
5257 	/* Prepare uniform buffer */
5258 	offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5259 
5260 	if (true == are_offsets_verified && false == offset_verification_result)
5261 	{
5262 		/* Offsets verification failure was already reported, add info about buffer layout */
5263 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5264 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5265 											<< tcu::TestLog::EndMessage;
5266 
5267 		result = false;
5268 	}
5269 
5270 	/* Set up transform feedback buffer */
5271 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5272 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5273 
5274 	/* Begin transform feedback */
5275 	gl.beginTransformFeedback(GL_POINTS);
5276 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5277 
5278 	/* Execute draw call for singe vertex */
5279 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5280 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5281 
5282 	/* Stop transform feedback */
5283 	gl.endTransformFeedback();
5284 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5285 
5286 	/* Verify results */
5287 	if (false == verifyResults())
5288 	{
5289 		/* Result verificatioon failure was already reported, add info about layout */
5290 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5291 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5292 											<< tcu::TestLog::EndMessage;
5293 
5294 		result = false;
5295 	}
5296 
5297 	/* Done */
5298 	return result;
5299 }
5300 
testInit()5301 void GPUShaderFP64Test3::testInit()
5302 {
5303 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5304 
5305 	/* Uniform block declaration with std140 offsets calculated
5306 	 *                       | align | loc_req | begins | ends | offset in bytes | imp |
5307 	 * ivec3   unused1[3]    |     4 |      12 |      0 |   12 |               0 |     |
5308 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5309 	 * bool    unused2       |     1 |       1 |     14 |   15 |              56 |     |
5310 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5311 	 * bvec3   unused3       |     4 |       4 |     20 |   24 |              80 |     |
5312 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5313 	 * int     unused4[3]    |     4 |      12 |     32 |   44 |             128 |     |
5314 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5315 	 * bool    unused5       |     1 |       1 |     56 |   57 |             224 |     |
5316 	 * bool    unused6[2]    |     4 |       8 |     60 |   68 |             240 |     |
5317 	 * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
5318 	 * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
5319 	 * bool    unused7       |     1 |       1 |    104 |  105 |             416 |     |
5320 	 * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
5321 	 * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
5322 	 * uvec3   unused8       |     4 |       4 |    160 |  164 |             640 |     |
5323 	 * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
5324 	 * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
5325 	 * bool    unused9       |     1 |       1 |    196 |  197 |             784 |     |
5326 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5327 	 * int     unused10      |     1 |       1 |    224 |  225 |             896 |     |
5328 	 * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
5329 	 * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
5330 	 */
5331 
5332 	/* Prepare "double precision" unfiorms' details */
5333 	m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5334 											   1 /* n_elements */, "double" /* type_name */));
5335 	m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5336 											   2 /* n_elements */, "dvec2" /* type_name */));
5337 	m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5338 											   3 /* n_elements */, "dvec3" /* type_name */));
5339 	m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5340 											   4 /* n_elements */, "dvec4" /* type_name */));
5341 	m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5342 											   4 /* n_elements */, "dmat2" /* type_name */));
5343 	m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5344 											   9 /* n_elements */, "dmat3" /* type_name */));
5345 	m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5346 											   16 /* n_elements */, "dmat4" /* type_name */));
5347 	m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5348 											   6 /* n_elements */, "dmat2x3" /* type_name */));
5349 	m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5350 											   8 /* n_elements */, "dmat2x4" /* type_name */));
5351 	m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5352 											   6 /* n_elements */, "dmat3x2" /* type_name */));
5353 	m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5354 											   12 /* n_elements */, "dmat3x4" /* type_name */));
5355 	m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5356 											   8 /* n_elements */, "dmat4x2" /* type_name */));
5357 	m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5358 											   12 /* n_elements */, "dmat4x3" /* type_name */));
5359 
5360 	/* Get random values for getExpectedValue */
5361 	m_base_element		= (glw::GLdouble)(rand() % 13);
5362 	m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5363 
5364 	/* Prepare programInfos for all buffer layouts */
5365 	prepareProgram(m_packed_program, PACKED);
5366 	prepareProgram(m_shared_program, SHARED);
5367 	prepareProgram(m_std140_program, STD140);
5368 
5369 	/* Generate buffers */
5370 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
5371 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5372 
5373 	gl.genBuffers(1, &m_uniform_buffer_id);
5374 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5375 
5376 	/* Prepare transform feedback buffer */
5377 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5378 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5379 
5380 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5381 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5382 
5383 	/* Prepare texture for color attachment 0 */
5384 	gl.genTextures(1, &m_color_texture_id);
5385 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5386 
5387 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5388 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5389 
5390 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5391 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5392 
5393 	/* Prepare FBO with color attachment 0 */
5394 	gl.genFramebuffers(1, &m_framebuffer_id);
5395 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5396 
5397 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5398 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5399 
5400 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5401 							0 /* level */);
5402 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5403 
5404 	gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5405 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5406 
5407 	/* Prepare VAO */
5408 	gl.genVertexArrays(1, &m_vertex_array_object_id);
5409 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5410 
5411 	gl.bindVertexArray(m_vertex_array_object_id);
5412 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5413 
5414 	/* Tesselation patch set up */
5415 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
5416 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5417 }
5418 
5419 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5420  *
5421  * @return true if all values are as expected, false otherwise
5422  **/
verifyResults() const5423 bool GPUShaderFP64Test3::verifyResults() const
5424 {
5425 	glw::GLint*			  feedback_data			  = 0;
5426 	bool				  fragment_shader_result  = false;
5427 	bool				  geometry_shader_result  = false;
5428 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
5429 	bool				  tess_ctrl_shader_result = false;
5430 	bool				  tess_eval_shader_result = false;
5431 	bool				  vertex_shader_result	= false;
5432 
5433 	/* Prepare storage for testure data */
5434 	std::vector<glw::GLint> image_data;
5435 	image_data.resize(1);
5436 
5437 	/* Get texture contents */
5438 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5439 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5440 
5441 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5442 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5443 
5444 	/* Get transform feedback data */
5445 	feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5446 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5447 
5448 	/* Verify results */
5449 	fragment_shader_result  = (m_result_success == image_data[0]);
5450 	geometry_shader_result  = (m_result_success == feedback_data[0]);
5451 	tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5452 	tess_eval_shader_result = (m_result_success == feedback_data[2]);
5453 	vertex_shader_result	= (m_result_success == feedback_data[3]);
5454 
5455 	/* Unmap transform feedback buffer */
5456 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5457 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5458 
5459 	/* Set result */
5460 	if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5461 				 tess_eval_shader_result && vertex_shader_result))
5462 	{
5463 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5464 
5465 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5466 											<< "Vertex shader stage result: " << vertex_shader_result
5467 											<< tcu::TestLog::EndMessage;
5468 
5469 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5470 											<< "Tesselation control shader stage result: " << tess_ctrl_shader_result
5471 											<< tcu::TestLog::EndMessage;
5472 
5473 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5474 											<< "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5475 											<< tcu::TestLog::EndMessage;
5476 
5477 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 											<< "Geometry shader stage result: " << geometry_shader_result
5479 											<< tcu::TestLog::EndMessage;
5480 
5481 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 											<< "Fragment shader stage result: " << fragment_shader_result
5483 											<< tcu::TestLog::EndMessage;
5484 
5485 		return false;
5486 	}
5487 	else
5488 	{
5489 		return true;
5490 	}
5491 }
5492 
5493 /** Write main routine of <shader_stage> shader to stream
5494  *
5495  * @param stream       Output stream with source code of shader
5496  * @param shader_stage Shader stage
5497  **/
writeMainBody(std::ostream& stream, shaderStage shader_stage) const5498 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5499 {
5500 	glw::GLuint		   type_ordinal = 1;
5501 	const glw::GLchar* varying_name = "";
5502 
5503 	/* Select name for varying that will hold result of "that" shader_stage */
5504 	switch (shader_stage)
5505 	{
5506 	case FRAGMENT_SHADER:
5507 		varying_name = m_varying_name_fs_out_fs_result;
5508 		break;
5509 	case GEOMETRY_SHADER:
5510 		varying_name = m_varying_name_gs_fs_gs_result;
5511 		break;
5512 	case TESS_CONTROL_SHADER:
5513 		varying_name = m_varying_name_tcs_tes_tcs_result;
5514 		break;
5515 	case TESS_EVAL_SHADER:
5516 		varying_name = m_varying_name_tes_gs_tes_result;
5517 		break;
5518 	case VERTEX_SHADER:
5519 		varying_name = m_varying_name_vs_tcs_vs_result;
5520 		break;
5521 	}
5522 
5523 	/* void main() */
5524 	stream << "void main()\n"
5525 			  "{\n";
5526 
5527 	/* Tesselation levels output */
5528 	if (TESS_CONTROL_SHADER == shader_stage)
5529 	{
5530 		stream << "gl_TessLevelOuter[0] = 1.0;\n"
5531 				  "gl_TessLevelOuter[1] = 1.0;\n"
5532 				  "gl_TessLevelOuter[2] = 1.0;\n"
5533 				  "gl_TessLevelOuter[3] = 1.0;\n"
5534 				  "gl_TessLevelInner[0] = 1.0;\n"
5535 				  "gl_TessLevelInner[1] = 1.0;\n"
5536 				  "\n";
5537 	}
5538 
5539 	/* For each "double precision" uniform
5540 	 *
5541 	 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5542 	 * {
5543 	 *     VARYING_NAME = m_result_failure;
5544 	 * }
5545 	 */
5546 	for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5547 		 end != it; ++it, ++type_ordinal)
5548 	{
5549 		stream << "    ";
5550 
5551 		/* First comparison is done with if, next with else if */
5552 		if (1 != type_ordinal)
5553 		{
5554 			stream << "else ";
5555 		}
5556 
5557 		/* if (TYPE_NAME( */
5558 		stream << "if (" << it->m_type_name << "(";
5559 
5560 		/* PREDIFINED_VALUES */
5561 		for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5562 		{
5563 			stream << getExpectedValue(type_ordinal, element);
5564 
5565 			/* Separate with comma */
5566 			if (it->m_n_elements != element + 1)
5567 			{
5568 				stream << ", ";
5569 			}
5570 		}
5571 
5572 		/*
5573 		 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5574 		 * {
5575 		 *     VARYING_NAME
5576 		 */
5577 		stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5578 																				   "    {\n"
5579 																				   "        "
5580 			   << varying_name;
5581 
5582 		/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5583 		if (TESS_CONTROL_SHADER == shader_stage)
5584 		{
5585 			stream << "[gl_InvocationID]";
5586 		}
5587 
5588 		/*
5589 		 * = m_result_failure;
5590 		 * }
5591 		 */
5592 		stream << " = " << m_result_failure << ";\n"
5593 			   << "    }\n";
5594 	}
5595 
5596 	/* If all comparisons are ok
5597 	 *
5598 	 *     else
5599 	 *     {
5600 	 *         VARYING_NAME = m_result_success;
5601 	 *     }
5602 	 */
5603 
5604 	/*
5605 	 * else
5606 	 * {
5607 	 *     VARYING_NAME
5608 	 */
5609 	stream << "    else\n"
5610 			  "    {\n"
5611 			  "        "
5612 		   << varying_name;
5613 
5614 	/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5615 	if (TESS_CONTROL_SHADER == shader_stage)
5616 	{
5617 		stream << "[gl_InvocationID]";
5618 	}
5619 
5620 	/*
5621 	 * = m_result_success;
5622 	 * }
5623 	 *
5624 	 */
5625 	stream << " = " << m_result_success << ";\n"
5626 		   << "    }\n"
5627 		   << "\n";
5628 
5629 	/* For each pair of "input/output" varyings
5630 	 *
5631 	 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5632 	 **/
5633 	writeVaryingPassthrough(stream, shader_stage);
5634 
5635 	/* Geometry shader have to emit vertex */
5636 	if (GEOMETRY_SHADER == shader_stage)
5637 	{
5638 		stream << "\n"
5639 				  "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5640 				  "EmitVertex();\n"
5641 				  "EndPrimitive();\n";
5642 	}
5643 
5644 	/* Close scope of main */
5645 	stream << "}\n\n";
5646 }
5647 
5648 /** Write shader preamble to stream
5649  *
5650  * @param stream       Output stream with source code of shader
5651  * @param shader_stage Shader stage
5652  **/
writePreamble(std::ostream& stream, shaderStage shader_stage) const5653 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5654 {
5655 	stream << "#version 400 core\n"
5656 			  "\n"
5657 			  "precision highp float;\n"
5658 			  "\n";
5659 
5660 	switch (shader_stage)
5661 	{
5662 	case FRAGMENT_SHADER:
5663 		break;
5664 	case GEOMETRY_SHADER:
5665 		stream << "layout(points)                   in;\n"
5666 				  "layout(points, max_vertices = 1) out;\n"
5667 				  "\n";
5668 		break;
5669 	case TESS_CONTROL_SHADER:
5670 		stream << "layout(vertices = 1) out;\n"
5671 				  "\n";
5672 		break;
5673 	case TESS_EVAL_SHADER:
5674 		stream << "layout(isolines, point_mode) in;\n"
5675 				  "\n";
5676 		break;
5677 	case VERTEX_SHADER:
5678 		break;
5679 	}
5680 }
5681 
5682 /** Write name uniform blcok definition with specific layout to stream
5683  *
5684  * @param stream              Output stream with source code of shader
5685  * @param uniform_data_layout Buffer layout
5686  **/
writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const5687 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5688 {
5689 	const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5690 
5691 	stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5692 																			 "{\n"
5693 																			 "    ivec3   unused1[3];\n"
5694 																			 "    double  double_value;\n"
5695 																			 "    bool    unused2;\n"
5696 																			 "    dvec2   dvec2_value;\n"
5697 																			 "    bvec3   unused3;\n"
5698 																			 "    dvec3   dvec3_value;\n"
5699 																			 "    int     unused4[3];\n"
5700 																			 "    dvec4   dvec4_value;\n"
5701 																			 "    bool    unused5;\n"
5702 																			 "    bool    unused6[2];\n"
5703 																			 "    dmat2   dmat2_value;\n"
5704 																			 "    dmat3   dmat3_value;\n"
5705 																			 "    bool    unused7;\n"
5706 																			 "    dmat4   dmat4_value;\n"
5707 																			 "    dmat2x3 dmat2x3_value;\n"
5708 																			 "    uvec3   unused8;\n"
5709 																			 "    dmat2x4 dmat2x4_value;\n"
5710 																			 "    dmat3x2 dmat3x2_value;\n"
5711 																			 "    bool    unused9;\n"
5712 																			 "    dmat3x4 dmat3x4_value;\n"
5713 																			 "    int     unused10;\n"
5714 																			 "    dmat4x2 dmat4x2_value;\n"
5715 																			 "    dmat4x3 dmat4x3_value;\n"
5716 																			 "} "
5717 		   << m_uniform_block_instance_name << ";\n";
5718 
5719 	stream << "\n";
5720 }
5721 
5722 /** Write definitions of varyings specific for given <shader_stage> to stream
5723  *
5724  * @param stream       Output stream with source code of shader
5725  * @param shader_stage Shader stage
5726  **/
writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const5727 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5728 {
5729 	static const glw::GLchar* const varying_type = "int";
5730 
5731 	switch (shader_stage)
5732 	{
5733 	case FRAGMENT_SHADER:
5734 
5735 		/* In */
5736 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5737 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5738 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5739 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5740 
5741 		stream << "\n";
5742 
5743 		/* Out */
5744 		stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5745 
5746 		break;
5747 
5748 	case GEOMETRY_SHADER:
5749 
5750 		/* In */
5751 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5752 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5753 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5754 
5755 		stream << "\n";
5756 
5757 		/* Out */
5758 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5759 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5760 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5761 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5762 
5763 		break;
5764 
5765 	case TESS_CONTROL_SHADER:
5766 
5767 		/* In */
5768 		stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5769 
5770 		stream << "\n";
5771 
5772 		/* Out */
5773 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5774 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5775 
5776 		break;
5777 
5778 	case TESS_EVAL_SHADER:
5779 
5780 		/* In */
5781 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5782 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5783 
5784 		stream << "\n";
5785 
5786 		/* Out */
5787 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5788 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5789 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5790 
5791 		break;
5792 
5793 	case VERTEX_SHADER:
5794 
5795 		/* Out */
5796 		stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5797 
5798 		break;
5799 	}
5800 
5801 	stream << "\n";
5802 }
5803 
5804 /** Write passthrough code of "input/output" varying pairs to stream
5805  *
5806  * @param stream       Output stream with source code of shader
5807  * @param shader_stage Shader stage
5808  **/
writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const5809 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5810 {
5811 	switch (shader_stage)
5812 	{
5813 	case FRAGMENT_SHADER:
5814 		break;
5815 
5816 	case GEOMETRY_SHADER:
5817 
5818 		stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5819 		stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5820 		stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5821 
5822 		break;
5823 
5824 	case TESS_CONTROL_SHADER:
5825 
5826 		stream << "    " << m_varying_name_tcs_tes_vs_result
5827 			   << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5828 
5829 		break;
5830 
5831 	case TESS_EVAL_SHADER:
5832 
5833 		stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5834 		stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5835 
5836 		break;
5837 
5838 	case VERTEX_SHADER:
5839 
5840 		break;
5841 	}
5842 }
5843 
5844 /** Constructor. Sets all uniform locations to -1 and sets all
5845  *  values to 0.
5846  */
_data()5847 GPUShaderFP64Test4::_data::_data()
5848 {
5849 	memset(&uniform_double, 0, sizeof(uniform_double));
5850 	memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5851 	memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5852 	memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5853 	memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5854 	memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5855 	memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5856 
5857 	uniform_location_double		   = -1;
5858 	uniform_location_double_arr[0] = -1;
5859 	uniform_location_double_arr[1] = -1;
5860 	uniform_location_dvec2		   = -1;
5861 	uniform_location_dvec2_arr[0]  = -1;
5862 	uniform_location_dvec2_arr[1]  = -1;
5863 	uniform_location_dvec3		   = -1;
5864 	uniform_location_dvec3_arr[0]  = -1;
5865 	uniform_location_dvec3_arr[1]  = -1;
5866 	uniform_location_dvec4		   = -1;
5867 	uniform_location_dvec4_arr[0]  = -1;
5868 	uniform_location_dvec4_arr[1]  = -1;
5869 }
5870 
5871 /** Constructor
5872  *
5873  *  @param context Rendering context.
5874  */
GPUShaderFP64Test4(deqp::Context& context)5875 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5876 	: TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5877 									   " report correct properties of & values assigned to double-precision uniforms.")
5878 	, m_has_test_passed(true)
5879 	, m_uniform_name_buffer(0)
5880 	, m_cs_id(0)
5881 	, m_fs_id(0)
5882 	, m_gs_id(0)
5883 	, m_po_cs_id(0)
5884 	, m_po_noncs_id(0)
5885 	, m_tc_id(0)
5886 	, m_te_id(0)
5887 	, m_vs_id(0)
5888 {
5889 	/* Left blank intentionally */
5890 }
5891 
5892 /** Deinitializes all GL objects, as well as releases all bufers, that may
5893  *  have beenallocated or  created during test execution.
5894  **/
deinit()5895 void GPUShaderFP64Test4::deinit()
5896 {
5897 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5898 
5899 	if (m_cs_id != 0)
5900 	{
5901 		gl.deleteShader(m_cs_id);
5902 
5903 		m_cs_id = 0;
5904 	}
5905 
5906 	if (m_fs_id != 0)
5907 	{
5908 		gl.deleteShader(m_fs_id);
5909 
5910 		m_fs_id = 0;
5911 	}
5912 
5913 	if (m_gs_id != 0)
5914 	{
5915 		gl.deleteShader(m_gs_id);
5916 
5917 		m_gs_id = 0;
5918 	}
5919 
5920 	if (m_po_cs_id != 0)
5921 	{
5922 		gl.deleteProgram(m_po_cs_id);
5923 
5924 		m_po_cs_id = 0;
5925 	}
5926 
5927 	if (m_po_noncs_id != 0)
5928 	{
5929 		gl.deleteProgram(m_po_noncs_id);
5930 
5931 		m_po_noncs_id = 0;
5932 	}
5933 
5934 	if (m_tc_id != 0)
5935 	{
5936 		gl.deleteShader(m_tc_id);
5937 
5938 		m_tc_id = 0;
5939 	}
5940 
5941 	if (m_te_id != 0)
5942 	{
5943 		gl.deleteShader(m_te_id);
5944 
5945 		m_te_id = 0;
5946 	}
5947 
5948 	if (m_uniform_name_buffer != DE_NULL)
5949 	{
5950 		delete[] m_uniform_name_buffer;
5951 
5952 		m_uniform_name_buffer = DE_NULL;
5953 	}
5954 
5955 	if (m_vs_id != 0)
5956 	{
5957 		gl.deleteShader(m_vs_id);
5958 
5959 		m_vs_id = 0;
5960 	}
5961 }
5962 
5963 /** Generates double-precision values for all uniforms defined for all program objects
5964  *  used by the test.
5965  *
5966  *  This function DOES NOT use any GL API. It only calculates & stores the values
5967  *  in internal storage for further usage.
5968  */
generateUniformValues()5969 void GPUShaderFP64Test4::generateUniformValues()
5970 {
5971 	_stage_data*	   stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5972 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5973 
5974 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5975 	{
5976 		_stage_data* stage_ptr = stages[n_stage];
5977 
5978 		/* Iterate through all uniform components and assign them double values */
5979 		double* double_ptrs[] = {
5980 			&stage_ptr->uniform_structure_arrays[0].uniform_double,
5981 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5982 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5983 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5984 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5985 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
5986 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
5987 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
5988 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
5989 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
5990 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
5991 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
5992 			&stage_ptr->uniform_structure_arrays[1].uniform_double,
5993 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
5994 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
5995 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
5996 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
5997 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
5998 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
5999 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6000 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6001 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6002 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6003 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6004 			&stage_ptr->uniforms.uniform_double,
6005 			stage_ptr->uniforms.uniform_double_arr + 0,
6006 			stage_ptr->uniforms.uniform_double_arr + 1,
6007 			stage_ptr->uniforms.uniform_dvec2 + 0,
6008 			stage_ptr->uniforms.uniform_dvec2 + 1,
6009 			stage_ptr->uniforms.uniform_dvec2_arr + 0,
6010 			stage_ptr->uniforms.uniform_dvec2_arr + 1,
6011 			stage_ptr->uniforms.uniform_dvec2_arr + 2,
6012 			stage_ptr->uniforms.uniform_dvec2_arr + 3,
6013 			stage_ptr->uniforms.uniform_dvec3 + 0,
6014 			stage_ptr->uniforms.uniform_dvec3 + 1,
6015 			stage_ptr->uniforms.uniform_dvec3 + 2,
6016 			stage_ptr->uniforms.uniform_dvec3_arr + 0,
6017 			stage_ptr->uniforms.uniform_dvec3_arr + 1,
6018 			stage_ptr->uniforms.uniform_dvec3_arr + 2,
6019 			stage_ptr->uniforms.uniform_dvec3_arr + 3,
6020 			stage_ptr->uniforms.uniform_dvec3_arr + 4,
6021 			stage_ptr->uniforms.uniform_dvec3_arr + 5,
6022 			stage_ptr->uniforms.uniform_dvec4 + 0,
6023 			stage_ptr->uniforms.uniform_dvec4 + 1,
6024 			stage_ptr->uniforms.uniform_dvec4 + 2,
6025 			stage_ptr->uniforms.uniform_dvec4 + 3,
6026 			stage_ptr->uniforms.uniform_dvec4_arr + 0,
6027 			stage_ptr->uniforms.uniform_dvec4_arr + 1,
6028 			stage_ptr->uniforms.uniform_dvec4_arr + 2,
6029 			stage_ptr->uniforms.uniform_dvec4_arr + 3,
6030 			stage_ptr->uniforms.uniform_dvec4_arr + 4,
6031 			stage_ptr->uniforms.uniform_dvec4_arr + 5,
6032 			stage_ptr->uniforms.uniform_dvec4_arr + 6,
6033 			stage_ptr->uniforms.uniform_dvec4_arr + 7,
6034 		};
6035 		const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6036 
6037 		for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6038 		{
6039 			double* double_ptr = double_ptrs[n_double_ptr];
6040 
6041 			/* Generate the value. Use magic numbers to generate a set of double-precision
6042 			 * floating-point numbers.
6043 			 */
6044 			static int seed = 16762362;
6045 
6046 			*double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6047 
6048 			seed += 751;
6049 		} /* for (all pointers to double variables) */
6050 	}	 /* for (all stages) */
6051 }
6052 
6053 /** Initializes all program & shader objects required to run the test. The function also
6054  *  retrieves locations of all uniforms defined by both program objects.
6055  **/
initProgramObjects()6056 void GPUShaderFP64Test4::initProgramObjects()
6057 {
6058 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6059 
6060 	/* Create program & shader objects */
6061 
6062 	/* Compute shader support and GL 4.2 required */
6063 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6064 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6065 	{
6066 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6067 	}
6068 
6069 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6070 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6071 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6072 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6073 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6074 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6075 
6076 	/* m_cs_id is initialized only if compute shaders are supported */
6077 	if (0 != m_cs_id)
6078 	{
6079 		m_po_cs_id = gl.createProgram();
6080 	}
6081 
6082 	m_po_noncs_id = gl.createProgram();
6083 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6084 
6085 	/* Configure compute shader body */
6086 	const char* cs_body = "#version 420\n"
6087 						  "#extension GL_ARB_compute_shader          : require\n"
6088 						  "\n"
6089 						  "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6090 						  "\n"
6091 						  "layout(rgba32f) uniform image2D testImage;\n"
6092 						  "\n"
6093 						  "uniform double cs_double;\n"
6094 						  "uniform dvec2  cs_dvec2;\n"
6095 						  "uniform dvec3  cs_dvec3;\n"
6096 						  "uniform dvec4  cs_dvec4;\n"
6097 						  "uniform double cs_double_arr[2];\n"
6098 						  "uniform dvec2  cs_dvec2_arr [2];\n"
6099 						  "uniform dvec3  cs_dvec3_arr [2];\n"
6100 						  "uniform dvec4  cs_dvec4_arr [2];\n"
6101 						  "\n"
6102 						  "uniform struct cs_struct\n"
6103 						  "{\n"
6104 						  "    double struct_double;\n"
6105 						  "    dvec2  struct_dvec2;\n"
6106 						  "    dvec3  struct_dvec3;\n"
6107 						  "    dvec4  struct_dvec4;\n"
6108 						  "} cs_array[2];\n"
6109 						  "\n"
6110 						  "void main()\n"
6111 						  "{\n"
6112 						  "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
6113 						  "          * cs_dvec4.z                 *\n"
6114 						  "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
6115 						  "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
6116 						  "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
6117 						  "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
6118 						  "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
6119 						  "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6120 						  "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
6121 						  "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6122 						  "\n"
6123 						  "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6124 						  "}\n";
6125 
6126 	/* m_cs_id is initialized only if compute shaders are supported */
6127 	if (0 != m_cs_id)
6128 	{
6129 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6130 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6131 	}
6132 
6133 	/* Configure vertex shader body */
6134 	const char* vs_body = "#version 400\n"
6135 						  "\n"
6136 						  "uniform double vs_double;\n"
6137 						  "uniform dvec2  vs_dvec2;\n"
6138 						  "uniform dvec3  vs_dvec3;\n"
6139 						  "uniform dvec4  vs_dvec4;\n"
6140 						  "uniform double vs_double_arr[2];\n"
6141 						  "uniform dvec2  vs_dvec2_arr [2];\n"
6142 						  "uniform dvec3  vs_dvec3_arr [2];\n"
6143 						  "uniform dvec4  vs_dvec4_arr [2];\n"
6144 						  "\n"
6145 						  "uniform struct vs_struct\n"
6146 						  "{\n"
6147 						  "    double struct_double;\n"
6148 						  "    dvec2  struct_dvec2;\n"
6149 						  "    dvec3  struct_dvec3;\n"
6150 						  "    dvec4  struct_dvec4;\n"
6151 						  "} vs_array[2];\n"
6152 						  "\n"
6153 						  "void main()\n"
6154 						  "{\n"
6155 						  "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
6156 						  "* vs_dvec4.x                 *\n"
6157 						  "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
6158 						  "* vs_dvec4_arr[0].x          *\n"
6159 						  "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
6160 						  "* vs_dvec4_arr[1].x          *\n"
6161 						  "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6162 						  "* vs_array[0].struct_dvec4.x *\n"
6163 						  "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6164 						  "* vs_array[1].struct_dvec4.x > 1.0)\n"
6165 						  "    {\n"
6166 						  "        gl_Position = vec4(0);\n"
6167 						  "    }\n"
6168 						  "    else\n"
6169 						  "    {\n"
6170 						  "        gl_Position = vec4(1);\n"
6171 						  "    }\n"
6172 						  "}\n";
6173 
6174 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6176 
6177 	/* Configure tessellation control shader body */
6178 	const char* tc_body = "#version 400\n"
6179 						  "\n"
6180 						  "uniform double tc_double;\n"
6181 						  "uniform dvec2  tc_dvec2;\n"
6182 						  "uniform dvec3  tc_dvec3;\n"
6183 						  "uniform dvec4  tc_dvec4;\n"
6184 						  "uniform double tc_double_arr[2];\n"
6185 						  "uniform dvec2  tc_dvec2_arr [2];\n"
6186 						  "uniform dvec3  tc_dvec3_arr [2];\n"
6187 						  "uniform dvec4  tc_dvec4_arr [2];\n"
6188 						  "\n"
6189 						  "uniform struct tc_struct\n"
6190 						  "{\n"
6191 						  "    double struct_double;\n"
6192 						  "    dvec2  struct_dvec2;\n"
6193 						  "    dvec3  struct_dvec3;\n"
6194 						  "    dvec4  struct_dvec4;\n"
6195 						  "} tc_array[2];\n"
6196 						  "\n"
6197 						  "layout(vertices = 4) out;\n"
6198 						  "\n"
6199 						  "void main()\n"
6200 						  "{\n"
6201 						  "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
6202 						  "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
6203 						  "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
6204 						  "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
6205 						  "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6206 						  "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6207 						  "\n"
6208 						  "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
6209 						  "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
6210 						  "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
6211 						  "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
6212 						  "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6213 						  "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
6214 						  "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6215 						  "    {\n"
6216 						  "        gl_TessLevelInner[1] = 3.0;\n"
6217 						  "        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
6218 						  "    }\n"
6219 						  "    else\n"
6220 						  "    {\n"
6221 						  "        gl_TessLevelInner[1] = 0.0;\n"
6222 						  "        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(1);\n"
6223 						  "    }\n"
6224 						  "}\n";
6225 
6226 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6227 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6228 
6229 	/* Configure tessellation evaluation shader body */
6230 	const char* te_body = "#version 400\n"
6231 						  "\n"
6232 						  "uniform double te_double;\n"
6233 						  "uniform dvec2  te_dvec2;\n"
6234 						  "uniform dvec3  te_dvec3;\n"
6235 						  "uniform dvec4  te_dvec4;\n"
6236 						  "uniform double te_double_arr[2];\n"
6237 						  "uniform dvec2  te_dvec2_arr [2];\n"
6238 						  "uniform dvec3  te_dvec3_arr [2];\n"
6239 						  "uniform dvec4  te_dvec4_arr [2];\n"
6240 						  "\n"
6241 						  "uniform struct te_struct\n"
6242 						  "{\n"
6243 						  "    double struct_double;\n"
6244 						  "    dvec2  struct_dvec2;\n"
6245 						  "    dvec3  struct_dvec3;\n"
6246 						  "    dvec4  struct_dvec4;\n"
6247 						  "} te_array[2];\n"
6248 						  "\n"
6249 						  "layout(triangles) in;\n"
6250 						  "\n"
6251 						  "void main()\n"
6252 						  "{\n"
6253 						  "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
6254 						  "* te_dvec4.x                 *\n"
6255 						  "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
6256 						  "* te_dvec4_arr[0].x          *\n"
6257 						  "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
6258 						  "* te_dvec4_arr[1].x          *\n"
6259 						  "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6260 						  "* te_array[0].struct_dvec4.x *\n"
6261 						  "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6262 						  "* te_array[1].struct_dvec4.x > 1.0)\n"
6263 						  "    {\n"
6264 						  "        gl_Position = gl_in[0].gl_Position;\n"
6265 						  "    }\n"
6266 						  "    else\n"
6267 						  "    {\n"
6268 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6269 						  "    }\n"
6270 						  "}\n";
6271 
6272 	gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6273 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6274 
6275 	/* Configure geometry shader body */
6276 	const char* gs_body = "#version 400\n"
6277 						  "\n"
6278 						  "uniform double gs_double;\n"
6279 						  "uniform dvec2  gs_dvec2;\n"
6280 						  "uniform dvec3  gs_dvec3;\n"
6281 						  "uniform dvec4  gs_dvec4;\n"
6282 						  "uniform double gs_double_arr[2];\n"
6283 						  "uniform dvec2  gs_dvec2_arr [2];\n"
6284 						  "uniform dvec3  gs_dvec3_arr [2];\n"
6285 						  "uniform dvec4  gs_dvec4_arr [2];\n"
6286 						  "\n"
6287 						  "uniform struct gs_struct\n"
6288 						  "{\n"
6289 						  "    double struct_double;\n"
6290 						  "    dvec2  struct_dvec2;\n"
6291 						  "    dvec3  struct_dvec3;\n"
6292 						  "    dvec4  struct_dvec4;\n"
6293 						  "} gs_array[2];\n"
6294 						  "\n"
6295 						  "layout (points)                   in;\n"
6296 						  "layout (points, max_vertices = 1) out;\n"
6297 						  "\n"
6298 						  "void main()\n"
6299 						  "{\n"
6300 						  "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
6301 						  "* gs_dvec4.x        *\n"
6302 						  "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
6303 						  "* gs_dvec4_arr[0].x *\n"
6304 						  "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
6305 						  "* gs_dvec4_arr[1].x *\n"
6306 						  "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6307 						  "* gs_array[0].struct_dvec4.x *\n"
6308 						  "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6309 						  "* gs_array[1].struct_dvec4.x > 1.0)\n"
6310 						  "    {\n"
6311 						  "        gl_Position = gl_in[0].gl_Position;\n"
6312 						  "    }\n"
6313 						  "    else\n"
6314 						  "    {\n"
6315 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6316 						  "    }\n"
6317 						  "\n"
6318 						  "    EmitVertex();\n"
6319 						  "}\n";
6320 
6321 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6322 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6323 
6324 	/* Configure fragment shader body */
6325 	const char* fs_body = "#version 400\n"
6326 						  "\n"
6327 						  "uniform double fs_double;\n"
6328 						  "uniform dvec2  fs_dvec2;\n"
6329 						  "uniform dvec3  fs_dvec3;\n"
6330 						  "uniform dvec4  fs_dvec4;\n"
6331 						  "uniform double fs_double_arr[2];\n"
6332 						  "uniform dvec2  fs_dvec2_arr [2];\n"
6333 						  "uniform dvec3  fs_dvec3_arr [2];\n"
6334 						  "uniform dvec4  fs_dvec4_arr [2];\n"
6335 						  "\n"
6336 						  "uniform struct fs_struct\n"
6337 						  "{\n"
6338 						  "    double struct_double;\n"
6339 						  "    dvec2  struct_dvec2;\n"
6340 						  "    dvec3  struct_dvec3;\n"
6341 						  "    dvec4  struct_dvec4;\n"
6342 						  "} fs_array[2];\n"
6343 						  "\n"
6344 						  "out vec4 result;\n"
6345 						  "\n"
6346 						  "void main()\n"
6347 						  "{\n"
6348 						  "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
6349 						  "* fs_dvec4.x        *\n"
6350 						  "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
6351 						  "* fs_dvec4_arr[0].x *\n"
6352 						  "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
6353 						  "* fs_dvec4_arr[1].x *\n"
6354 						  "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6355 						  "* fs_array[0].struct_dvec4.x *\n"
6356 						  "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6357 						  "* fs_array[1].struct_dvec4.x > 1.0)\n"
6358 						  "    {\n"
6359 						  "        result = vec4(0.0);\n"
6360 						  "    }\n"
6361 						  "    else\n"
6362 						  "    {\n"
6363 						  "        result = vec4(1.0);\n"
6364 						  "    }\n"
6365 						  "}\n";
6366 
6367 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6368 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6369 
6370 	/* Compile the shaders */
6371 	const glw::GLuint  shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6372 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6373 
6374 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6375 	{
6376 		glw::GLint  compile_status = GL_FALSE;
6377 		glw::GLuint so_id		   = shaders[n_shader];
6378 
6379 		/* Skip compute shader if not supported */
6380 		if (0 == so_id)
6381 		{
6382 			continue;
6383 		}
6384 
6385 		gl.compileShader(so_id);
6386 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6387 
6388 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6389 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6390 
6391 		if (compile_status != GL_TRUE)
6392 		{
6393 			TCU_FAIL("Shader compilation failed");
6394 		}
6395 
6396 		if (so_id == m_cs_id)
6397 		{
6398 			gl.attachShader(m_po_cs_id, so_id);
6399 		}
6400 		else
6401 		{
6402 			gl.attachShader(m_po_noncs_id, so_id);
6403 		}
6404 
6405 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6406 	} /* for (all shaders) */
6407 
6408 	/* Link the program */
6409 	const glw::GLuint  programs[]  = { m_po_cs_id, m_po_noncs_id };
6410 	const unsigned int n_programs  = sizeof(programs) / sizeof(programs[0]);
6411 	glw::GLint		   link_status = GL_FALSE;
6412 
6413 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6414 	{
6415 		glw::GLuint po_id = programs[n_program];
6416 
6417 		/* Skip compute shader program if not supported */
6418 		if (0 == po_id)
6419 		{
6420 			continue;
6421 		}
6422 
6423 		gl.linkProgram(po_id);
6424 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6425 
6426 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6427 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6428 
6429 		if (link_status != GL_TRUE)
6430 		{
6431 			TCU_FAIL("Program linking failed");
6432 		}
6433 	} /* for (both program objects) */
6434 
6435 	/* Retrieve uniform locations */
6436 	_stage_data*			  cs_stage_data[]		= { &m_data_cs };
6437 	static const char*		  cs_uniform_prefixes[] = { "cs_" };
6438 	static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6439 
6440 	_stage_data*			  noncs_stage_data[]	   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6441 	static const char*		  noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6442 	static const unsigned int n_noncs_uniform_prefixes =
6443 		sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6444 
6445 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6446 	{
6447 		unsigned int  n_uniform_prefixes = DE_NULL;
6448 		glw::GLuint   po_id				 = programs[n_program];
6449 		_stage_data** stages_data		 = DE_NULL;
6450 		const char**  uniform_prefixes   = DE_NULL;
6451 
6452 		if (n_program == 0)
6453 		{
6454 			stages_data		   = cs_stage_data;
6455 			uniform_prefixes   = cs_uniform_prefixes;
6456 			n_uniform_prefixes = n_cs_uniform_prefixes;
6457 		}
6458 		else
6459 		{
6460 			stages_data		   = noncs_stage_data;
6461 			uniform_prefixes   = noncs_uniform_prefixes;
6462 			n_uniform_prefixes = n_noncs_uniform_prefixes;
6463 		}
6464 
6465 		/* Skip compute shader program if not supported */
6466 		if (0 == po_id)
6467 		{
6468 			continue;
6469 		}
6470 
6471 		/* Uniform names used by the test program consist of a prefix (different for each
6472 		 * shader stage) and a common part.
6473 		 */
6474 		for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6475 		{
6476 			_stage_data* stage_data				  = stages_data[n_uniform_prefix];
6477 			std::string  uniform_prefix			  = std::string(uniform_prefixes[n_uniform_prefix]);
6478 			std::string  uniform_double_name	  = uniform_prefix + "double";
6479 			std::string  uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6480 			std::string  uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6481 			std::string  uniform_dvec2_name		  = uniform_prefix + "dvec2";
6482 			std::string  uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
6483 			std::string  uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
6484 			std::string  uniform_dvec3_name		  = uniform_prefix + "dvec3";
6485 			std::string  uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
6486 			std::string  uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
6487 			std::string  uniform_dvec4_name		  = uniform_prefix + "dvec4";
6488 			std::string  uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
6489 			std::string  uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
6490 			std::string  uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6491 			std::string  uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
6492 			std::string  uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
6493 			std::string  uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
6494 			std::string  uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6495 			std::string  uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
6496 			std::string  uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
6497 			std::string  uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
6498 
6499 			/* Retrieve uniform locations */
6500 			stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6501 			stage_data->uniforms.uniform_location_double_arr[0] =
6502 				gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6503 			stage_data->uniforms.uniform_location_double_arr[1] =
6504 				gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6505 			stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6506 			stage_data->uniforms.uniform_location_dvec2_arr[0] =
6507 				gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6508 			stage_data->uniforms.uniform_location_dvec2_arr[1] =
6509 				gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6510 			stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6511 			stage_data->uniforms.uniform_location_dvec3_arr[0] =
6512 				gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6513 			stage_data->uniforms.uniform_location_dvec3_arr[1] =
6514 				gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6515 			stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6516 			stage_data->uniforms.uniform_location_dvec4_arr[0] =
6517 				gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6518 			stage_data->uniforms.uniform_location_dvec4_arr[1] =
6519 				gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6520 			stage_data->uniform_structure_arrays[0].uniform_location_double =
6521 				gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6522 			stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6523 				gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6524 			stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6525 				gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6526 			stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6527 				gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6528 			stage_data->uniform_structure_arrays[1].uniform_location_double =
6529 				gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6530 			stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6531 				gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6532 			stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6533 				gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6534 			stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6535 				gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6536 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6537 
6538 			if (stage_data->uniforms.uniform_location_double == -1 ||
6539 				stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6540 				stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6541 				stage_data->uniforms.uniform_location_dvec2 == -1 ||
6542 				stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6543 				stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6544 				stage_data->uniforms.uniform_location_dvec3 == -1 ||
6545 				stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6546 				stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6547 				stage_data->uniforms.uniform_location_dvec4 == -1 ||
6548 				stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6549 				stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6550 				stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6551 				stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6552 				stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6553 				stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6554 				stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6555 				stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6556 				stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6557 				stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6558 			{
6559 				TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6560 			}
6561 
6562 			/* Make sure locations of subsequent items in array uniforms are correct */
6563 			if (stage_data->uniforms.uniform_location_double_arr[1] !=
6564 					(stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6565 				stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6566 					(stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6567 				stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6568 					(stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6569 				stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6570 					(stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6571 			{
6572 				m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6573 															   " double_arr[0]:"
6574 								   << stage_data->uniforms.uniform_location_double_arr[0]
6575 								   << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6576 								   << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6577 								   << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6578 								   << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6579 								   << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6580 								   << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6581 								   << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6582 								   << tcu::TestLog::EndMessage;
6583 
6584 				TCU_FAIL("Double-precision uniform array item locations are invalid.");
6585 			}
6586 		} /* for (all uniform prefixes) */
6587 	}	 /* for (both program objects) */
6588 }
6589 
6590 /** Initializes all objects required to run the test. */
initTest()6591 void GPUShaderFP64Test4::initTest()
6592 {
6593 	initProgramObjects();
6594 
6595 	generateUniformValues();
6596 	initUniformValues();
6597 }
6598 
6599 /** Assigns values generated by generateUniformValues() to uniforms defined by
6600  *  both program objects.
6601  **/
initUniformValues()6602 void GPUShaderFP64Test4::initUniformValues()
6603 {
6604 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6605 
6606 	/* Iterate through all programs */
6607 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6608 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6609 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6610 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6611 
6612 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6613 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6614 
6615 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6616 	{
6617 		glw::GLuint   po_id		 = programs[n_program];
6618 		unsigned int  n_stages   = 0;
6619 		_stage_data** stage_data = DE_NULL;
6620 
6621 		if (po_id == m_po_cs_id)
6622 		{
6623 			n_stages   = n_cs_stages;
6624 			stage_data = cs_stages;
6625 		}
6626 		else
6627 		{
6628 			n_stages   = n_noncs_stages;
6629 			stage_data = noncs_stages;
6630 		}
6631 
6632 		/* Skip compute shader program if not supported */
6633 		if (0 == po_id)
6634 		{
6635 			continue;
6636 		}
6637 
6638 		gl.useProgram(po_id);
6639 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6640 
6641 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6642 		{
6643 			/* Iterate through all uniforms */
6644 			_stage_data* stage_ptr = stage_data[n_stage];
6645 
6646 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6647 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6648 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6649 			gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6650 						 stage_ptr->uniform_structure_arrays[0].uniform_double);
6651 			gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6652 						 stage_ptr->uniform_structure_arrays[1].uniform_double);
6653 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6654 
6655 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6656 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6657 						  stage_ptr->uniforms.uniform_dvec2_arr + 0);
6658 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6659 						  stage_ptr->uniforms.uniform_dvec2_arr + 2);
6660 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6661 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6662 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6663 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6664 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6665 
6666 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6667 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6668 						  stage_ptr->uniforms.uniform_dvec3_arr + 0);
6669 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6670 						  stage_ptr->uniforms.uniform_dvec3_arr + 3);
6671 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6672 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6673 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6674 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6675 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6676 
6677 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6678 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6679 						  stage_ptr->uniforms.uniform_dvec4_arr + 0);
6680 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6681 						  stage_ptr->uniforms.uniform_dvec4_arr + 4);
6682 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6683 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6684 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6685 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6686 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6687 		} /* for (all shader stages) */
6688 	}	 /* for (both program objects) */
6689 }
6690 
6691 /** Executes test iteration.
6692  *
6693  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6694  */
iterate()6695 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6696 {
6697 	/* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6698 
6699 	/* Initialize all objects required to run the test */
6700 	initTest();
6701 
6702 	/* Verify the implementation reports correct values for all stages we've configured */
6703 	m_has_test_passed &= verifyUniformValues();
6704 
6705 	/* Is this also the case when "program interface query" mechanism is used? */
6706 	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6707 	{
6708 		m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6709 	}
6710 
6711 	/* We're done */
6712 	if (m_has_test_passed)
6713 	{
6714 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6715 	}
6716 	else
6717 	{
6718 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6719 	}
6720 
6721 	return STOP;
6722 }
6723 
6724 /** Verifies that:
6725  *
6726  *  a) glGetProgramResourceIndex()
6727  *  b) glGetProgramResourceiv()
6728  *  c) glGetProgramResourceName()
6729  *
6730  *  functions return correct values for double-precision uniforms.
6731  *
6732  *  @return true if the verification was passed, false otherwise.
6733  */
verifyProgramInterfaceQuerySupport()6734 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6735 {
6736 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6737 	bool				  result = true;
6738 
6739 	/* Iterate through all programs */
6740 	const char*		   cs_prefixes[]	= { "cs_" };
6741 	_stage_data*	   cs_stages[]		= { &m_data_cs };
6742 	const char*		   noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6743 	_stage_data*	   noncs_stages[]   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6744 	const unsigned int n_cs_stages		= sizeof(cs_stages) / sizeof(cs_stages[0]);
6745 	const unsigned int n_noncs_stages   = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6746 
6747 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6748 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6749 
6750 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6751 	{
6752 		glw::GLuint   po_id			 = programs[n_program];
6753 		unsigned int  n_stages		 = 0;
6754 		const char**  stage_prefixes = DE_NULL;
6755 		_stage_data** stage_data	 = DE_NULL;
6756 
6757 		if (po_id == m_po_cs_id)
6758 		{
6759 			n_stages	   = n_cs_stages;
6760 			stage_data	 = cs_stages;
6761 			stage_prefixes = cs_prefixes;
6762 		}
6763 		else
6764 		{
6765 			n_stages	   = n_noncs_stages;
6766 			stage_data	 = noncs_stages;
6767 			stage_prefixes = noncs_prefixes;
6768 		}
6769 
6770 		/* Skip compute shader program if not supported */
6771 		if (0 == po_id)
6772 		{
6773 			continue;
6774 		}
6775 
6776 		/* Determine maximum uniform name length */
6777 		glw::GLint max_uniform_name_length = 0;
6778 
6779 		gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6780 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6781 
6782 		/* Allocate a buffer we will use to hold uniform names */
6783 		m_uniform_name_buffer = new char[max_uniform_name_length];
6784 
6785 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6786 		{
6787 			/* Iterate through all uniforms */
6788 			_stage_data* stage_ptr	= stage_data[n_stage];
6789 			const char*  stage_prefix = stage_prefixes[n_stage];
6790 
6791 			/* Construct an array that will be used to run the test in an automated manner */
6792 			_program_interface_query_test_item uniforms[] = {
6793 				/* array size */ /* name */ /* type */ /* location */
6794 				{ 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6795 				{ 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6796 				{ 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6797 				{ 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6798 				{ 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6799 				{ 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6800 				{ 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6801 				{ 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6802 				{ 1, "array[0].struct_double", GL_DOUBLE,
6803 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6804 				{ 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6805 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6806 				{ 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6807 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6808 				{ 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6809 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6810 				{ 1, "array[1].struct_double", GL_DOUBLE,
6811 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6812 				{ 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6813 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6814 				{ 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6815 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6816 				{ 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6817 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6818 			};
6819 			const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6820 
6821 			/* Prefix the names with stage-specific string */
6822 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6823 			{
6824 				_program_interface_query_test_item& current_item = uniforms[n_uniform];
6825 
6826 				current_item.name = std::string(stage_prefix) + current_item.name;
6827 			} /* for (all uniform descriptors) */
6828 
6829 			const glw::GLenum  properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6830 			const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6831 
6832 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6833 			{
6834 				_program_interface_query_test_item& current_item		  = uniforms[n_uniform];
6835 				glw::GLint							n_written_items		  = 0;
6836 				glw::GLint							retrieved_array_size  = 0;
6837 				glw::GLint							retrieved_name_length = 0;
6838 				glw::GLenum							retrieved_type		  = GL_NONE;
6839 				glw::GLint							temp_buffer[2]		  = { 0, GL_NONE };
6840 
6841 				/* Retrieve index of the iteration-specific uniform */
6842 				glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6843 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6844 
6845 				/* Make sure glGetProgramResourceName() returns correct values */
6846 				memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6847 
6848 				gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6849 										  resource_index, max_uniform_name_length, &retrieved_name_length,
6850 										  m_uniform_name_buffer);
6851 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6852 
6853 				if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6854 					memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6855 				{
6856 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6857 									   << resource_index << "]"
6858 															": expected:["
6859 									   << current_item.name << "]"
6860 															   ", reported:["
6861 									   << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6862 
6863 					result = false;
6864 					continue;
6865 				}
6866 
6867 				/* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6868 				gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6869 										resource_index, n_properties, properties,
6870 										sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6871 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6872 
6873 				if (n_written_items != n_properties)
6874 				{
6875 					TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6876 				}
6877 
6878 				/* For clarity, copy the retrieved values to separate variables */
6879 				retrieved_array_size = temp_buffer[0];
6880 				retrieved_type		 = temp_buffer[1];
6881 
6882 				/* Verify the values */
6883 				if (retrieved_array_size != current_item.expected_array_size)
6884 				{
6885 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6886 									   << current_item.name << "]"
6887 									   << ": expected:[" << current_item.expected_array_size << "]"
6888 																								", reported:["
6889 									   << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6890 
6891 					result = false;
6892 				}
6893 
6894 				if (retrieved_type != current_item.expected_type)
6895 				{
6896 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6897 									   << current_item.name << "]"
6898 									   << ": expected:[" << current_item.expected_type << "]"
6899 																						  ", reported:["
6900 									   << retrieved_type << "]" << tcu::TestLog::EndMessage;
6901 
6902 					result = false;
6903 				}
6904 			} /* for (all uniforms) */
6905 		}	 /* for (all shader stages) */
6906 
6907 		/* We're now OK to release the buffer we used to hold uniform names for
6908 		 * the program */
6909 		if (m_uniform_name_buffer != DE_NULL)
6910 		{
6911 			delete[] m_uniform_name_buffer;
6912 
6913 			m_uniform_name_buffer = DE_NULL;
6914 		}
6915 	} /* for (both program objects) */
6916 
6917 	return result;
6918 }
6919 
6920 /** Verifies glGetUniform*() calls return correct values assigned to
6921  *  double-precision uniforms.
6922  *
6923  *  @return true if all values reported by OpenGL were found to be correct,
6924  *          false otherwise.
6925  **/
verifyUniformValues()6926 bool GPUShaderFP64Test4::verifyUniformValues()
6927 {
6928 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6929 	bool				  result = true;
6930 
6931 	/* Iterate through all programs */
6932 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6933 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6934 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6935 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6936 
6937 	const glw::GLuint programs[] = {
6938 		m_po_noncs_id, m_po_cs_id,
6939 	};
6940 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6941 
6942 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6943 	{
6944 		glw::GLuint   po_id		 = programs[n_program];
6945 		unsigned int  n_stages   = 0;
6946 		_stage_data** stage_data = DE_NULL;
6947 
6948 		if (po_id == m_po_cs_id)
6949 		{
6950 			n_stages   = n_cs_stages;
6951 			stage_data = cs_stages;
6952 		}
6953 		else
6954 		{
6955 			n_stages   = n_noncs_stages;
6956 			stage_data = noncs_stages;
6957 		}
6958 
6959 		/* Skip compute shader program if not supported */
6960 		if (0 == po_id)
6961 		{
6962 			continue;
6963 		}
6964 
6965 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6966 		{
6967 			/* Iterate through all uniforms */
6968 			_stage_data* stage_ptr = stage_data[n_stage];
6969 
6970 			/* Set up arrays that we will guide the automated testing */
6971 			const uniform_value_pair double_uniforms[] = {
6972 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6973 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6974 								   stage_ptr->uniforms.uniform_double_arr + 0),
6975 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6976 								   stage_ptr->uniforms.uniform_double_arr + 1),
6977 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6978 								   &stage_ptr->uniform_structure_arrays[0].uniform_double),
6979 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6980 								   &stage_ptr->uniform_structure_arrays[1].uniform_double)
6981 			};
6982 			const uniform_value_pair dvec2_uniforms[] = {
6983 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6984 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6985 								   stage_ptr->uniforms.uniform_dvec2_arr + 0),
6986 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6987 								   stage_ptr->uniforms.uniform_dvec2_arr + 2),
6988 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6989 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6990 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6991 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6992 			};
6993 			const uniform_value_pair dvec3_uniforms[] = {
6994 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6995 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6996 								   stage_ptr->uniforms.uniform_dvec3_arr + 0),
6997 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6998 								   stage_ptr->uniforms.uniform_dvec3_arr + 3),
6999 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
7000 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
7001 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
7002 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7003 			};
7004 			const uniform_value_pair dvec4_uniforms[] = {
7005 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7006 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7007 								   stage_ptr->uniforms.uniform_dvec4_arr + 0),
7008 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7009 								   stage_ptr->uniforms.uniform_dvec4_arr + 4),
7010 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7011 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7012 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7013 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7014 			};
7015 
7016 			/* Iterate over all uniforms and verify the values reported by the API */
7017 			double		 returned_double_data[4];
7018 			float		 returned_float_data[4];
7019 			int			 returned_int_data[4];
7020 			unsigned int returned_uint_data[4];
7021 
7022 			for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7023 			{
7024 				const uniform_value_pair* current_uv_pairs  = NULL;
7025 				const unsigned int		  n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7026 				unsigned int			  n_pairs			= 0;
7027 
7028 				switch (n_type)
7029 				{
7030 				case 0: /* double */
7031 				{
7032 					current_uv_pairs = double_uniforms;
7033 					n_pairs			 = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7034 
7035 					break;
7036 				}
7037 
7038 				case 1: /* dvec2 */
7039 				{
7040 					current_uv_pairs = dvec2_uniforms;
7041 					n_pairs			 = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7042 
7043 					break;
7044 				}
7045 
7046 				case 2: /* dvec3 */
7047 				{
7048 					current_uv_pairs = dvec3_uniforms;
7049 					n_pairs			 = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7050 
7051 					break;
7052 				}
7053 
7054 				case 3: /* dvec4 */
7055 				{
7056 					current_uv_pairs = dvec4_uniforms;
7057 					n_pairs			 = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7058 
7059 					break;
7060 				}
7061 
7062 				default:
7063 				{
7064 					TCU_FAIL("Invalid type index requested");
7065 				}
7066 				} /* switch (n_type) */
7067 
7068 				for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7069 				{
7070 					const uniform_value_pair& current_uv_pair  = current_uv_pairs[n_pair];
7071 					glw::GLint				  uniform_location = current_uv_pair.first;
7072 					const double*			  uniform_value	= current_uv_pair.second;
7073 
7074 					/* Retrieve the values from the GL implementation*/
7075 					gl.getUniformdv(po_id, uniform_location, returned_double_data);
7076 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7077 
7078 					gl.getUniformfv(po_id, uniform_location, returned_float_data);
7079 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7080 
7081 					gl.getUniformiv(po_id, uniform_location, returned_int_data);
7082 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7083 
7084 					gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7085 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7086 
7087 					/* Make sure the values reported match the reference values */
7088 					bool		can_continue = true;
7089 					const float epsilon		 = 1e-5f;
7090 
7091 					for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7092 					{
7093 						if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7094 						{
7095 							m_testCtx.getLog()
7096 								<< tcu::TestLog::Message
7097 								<< "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7098 								<< uniform_location << "]"
7099 													   " and component ["
7100 								<< n_component << "]"
7101 												  ": retrieved:["
7102 								<< returned_double_data[n_component] << "]"
7103 																		", expected:["
7104 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7105 
7106 							result = false;
7107 						}
7108 
7109 						if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7110 						{
7111 							m_testCtx.getLog()
7112 								<< tcu::TestLog::Message
7113 								<< "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7114 								<< uniform_location << "]"
7115 													   " and component ["
7116 								<< n_component << "]"
7117 												  ": retrieved:["
7118 								<< returned_float_data[n_component] << "]"
7119 																	   ", expected:["
7120 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7121 
7122 							result = false;
7123 						}
7124 
7125 						/* ints */
7126 						int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7127 						unsigned int rounded_uniform_value_uint =
7128 							(unsigned int)(uniform_value[n_component] > 0.0) ?
7129 								((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7130 								0;
7131 
7132 						if (returned_int_data[n_component] != rounded_uniform_value_sint)
7133 						{
7134 							m_testCtx.getLog()
7135 								<< tcu::TestLog::Message
7136 								<< "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7137 								<< uniform_location << "]"
7138 													   " and component ["
7139 								<< n_component << "]"
7140 												  ": retrieved:["
7141 								<< returned_int_data[n_component] << "]"
7142 																	 ", expected:["
7143 								<< rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7144 
7145 							result = false;
7146 						}
7147 
7148 						if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7149 						{
7150 							m_testCtx.getLog()
7151 								<< tcu::TestLog::Message
7152 								<< "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7153 								<< uniform_location << "]"
7154 													   " and component ["
7155 								<< n_component << "]"
7156 												  ": retrieved:["
7157 								<< returned_uint_data[n_component] << "]"
7158 																	  ", expected:["
7159 								<< rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7160 
7161 							result = false;
7162 						}
7163 					} /* for (all components) */
7164 				}	 /* for (all uniform+value pairs) */
7165 			}		  /* for (all 4 uniform types) */
7166 		}			  /* for (all shader stages) */
7167 	}				  /* for (both program objects) */
7168 
7169 	/* All done! */
7170 	return result;
7171 }
7172 
7173 /** Constructor
7174  *
7175  *  @param context Rendering context.
7176  */
GPUShaderFP64Test5(deqp::Context& context)7177 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7178 	: TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7179 									   " floating-point variables work correctly")
7180 	, m_base_value_bo_data(DE_NULL)
7181 	, m_base_value_bo_id(0)
7182 	, m_has_test_passed(true)
7183 	, m_po_base_value_attribute_location(-1)
7184 	, m_po_id(0)
7185 	, m_vao_id(0)
7186 	, m_vs_id(0)
7187 	, m_xfb_bo_id(0)
7188 	, m_xfb_bo_size(0)
7189 {
7190 	/* Set up base value array (as per test spec) */
7191 	m_base_values[0] = -25.12065f;
7192 	m_base_values[1] = 0.0f;
7193 	m_base_values[2] = 0.001f;
7194 	m_base_values[3] = 1.0f;
7195 	m_base_values[4] = 256.78901f;
7196 
7197 	/* Set up swizzle matrix */
7198 	m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7199 	m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7200 	m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7201 	m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7202 	m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7203 	m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7204 	m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7205 	m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7206 	m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7207 	m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7208 	m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7209 	m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7210 	m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7211 	m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7212 	m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7213 	m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7214 }
7215 
deinit()7216 void GPUShaderFP64Test5::deinit()
7217 {
7218 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7219 
7220 	if (m_base_value_bo_data != DE_NULL)
7221 	{
7222 		delete[] m_base_value_bo_data;
7223 
7224 		m_base_value_bo_data = DE_NULL;
7225 	}
7226 
7227 	if (m_base_value_bo_id != 0)
7228 	{
7229 		gl.deleteBuffers(1, &m_base_value_bo_id);
7230 
7231 		m_base_value_bo_id = 0;
7232 	}
7233 
7234 	if (m_vao_id != 0)
7235 	{
7236 		gl.deleteVertexArrays(1, &m_vao_id);
7237 
7238 		m_vao_id = 0;
7239 	}
7240 
7241 	if (m_xfb_bo_id != 0)
7242 	{
7243 		gl.deleteBuffers(1, &m_xfb_bo_id);
7244 
7245 		m_xfb_bo_id = 0;
7246 	}
7247 
7248 	/* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7249 	 * take care of it here
7250 	 */
7251 	deinitInteration();
7252 }
7253 
7254 /** Deinitializes all buffers and GL objects that may have been generated
7255  *  during test execution.
7256  **/
deinitInteration()7257 void GPUShaderFP64Test5::deinitInteration()
7258 {
7259 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7260 
7261 	if (m_po_id != 0)
7262 	{
7263 		gl.deleteProgram(m_po_id);
7264 
7265 		m_po_id = 0;
7266 	}
7267 
7268 	if (m_vs_id != 0)
7269 	{
7270 		gl.deleteShader(m_vs_id);
7271 
7272 		m_vs_id = 0;
7273 	}
7274 }
7275 
7276 /** Executes a single test case iteration using user-provided test case descriptor.
7277  *
7278  *  This function may throw a TestError exception if GL implementation misbehaves.
7279  *
7280  *  @param test_case Test case descriptor to use.
7281  *
7282  *  @return true if the values returned by GL implementation were found to be valid,
7283  *          false otherwise.
7284  **/
executeIteration(const _test_case& test_case)7285 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7286 {
7287 	bool result = true;
7288 
7289 	/* Convert the base values array to the type of input attribute we'll be using
7290 	 * for the iteration.
7291 	 */
7292 	Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7293 
7294 	if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7295 	{
7296 		/* bools are actually represented by ints, since bool varyings are not allowed */
7297 		base_value_type = Utils::VARIABLE_TYPE_INT;
7298 	}
7299 
7300 	const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7301 	const unsigned int n_base_values			 = sizeof(m_base_values) / sizeof(m_base_values[0]);
7302 
7303 	m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7304 
7305 	unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7306 
7307 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7308 	{
7309 		switch (base_value_type)
7310 		{
7311 		case Utils::VARIABLE_TYPE_DOUBLE:
7312 			*((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7313 			break;
7314 		case Utils::VARIABLE_TYPE_FLOAT:
7315 			*((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7316 			break;
7317 		case Utils::VARIABLE_TYPE_INT:
7318 			*((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7319 			break;
7320 		case Utils::VARIABLE_TYPE_UINT:
7321 			*((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7322 			break;
7323 
7324 		default:
7325 		{
7326 			TCU_FAIL("Unrecognized base value type");
7327 		}
7328 		}
7329 
7330 		base_value_traveller_ptr += base_value_component_size;
7331 	} /* for (all base values) */
7332 
7333 	/* Update buffer object storage with the data we've just finished preparing. */
7334 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7335 
7336 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7337 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7338 
7339 	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7340 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7341 
7342 	/* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7343 	 * new data is interpreted correctly.
7344 	 */
7345 	if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7346 	{
7347 		gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,							  /* size */
7348 							   Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7349 							   0,																  /* stride */
7350 							   DE_NULL);														  /* pointer */
7351 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7352 	}
7353 	else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7354 	{
7355 		gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,						/* size */
7356 								Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7357 								DE_NULL);													/* pointer */
7358 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7359 	}
7360 	else
7361 	{
7362 		DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7363 
7364 		gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7365 								GL_DOUBLE, 0,						   /* stride */
7366 								DE_NULL);							   /* pointer */
7367 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7368 	}
7369 
7370 	gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7371 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7372 
7373 	/* Execute the draw call */
7374 	gl.useProgram(m_po_id);
7375 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7376 
7377 	gl.beginTransformFeedback(GL_POINTS);
7378 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7379 	{
7380 		gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7381 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7382 	}
7383 	gl.endTransformFeedback();
7384 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7385 
7386 	/* Map the XFB buffer object into process space */
7387 	void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7388 
7389 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7390 	DE_ASSERT(xfb_data_ptr != NULL);
7391 
7392 	/* Verify the data */
7393 	result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7394 
7395 	/* Unmap the XFB BO */
7396 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7398 
7399 	/** Good to release the data buffer at this point */
7400 	if (m_base_value_bo_data != DE_NULL)
7401 	{
7402 		delete[] m_base_value_bo_data;
7403 
7404 		m_base_value_bo_data = DE_NULL;
7405 	}
7406 
7407 	/* All done */
7408 	return result;
7409 }
7410 
7411 /** Returns properties of a swizzle operator described by @param type swizzle type.
7412  *
7413  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
7414  *                             corresponding to the specific swizzle operator.
7415  *                             Must not be NULL.
7416  *  @param out_n_components    Deref will be used to store the amount of components
7417  *                             used by the operator. Must not be NULL.
7418  *  @param out_component_order Deref will be used to store up to 4 integer values,
7419  *                             corresponding to component indices described by the
7420  *                             operator for a particular position.  Must not be NULL.
7421  **/
getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string, unsigned int* out_n_components, unsigned int* out_component_order)7422 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7423 												  unsigned int* out_n_components, unsigned int* out_component_order)
7424 {
7425 	unsigned int result_component_order[4] = { 0 };
7426 	unsigned int result_n_components	   = 0;
7427 	std::string  result_swizzle_string;
7428 
7429 	switch (type)
7430 	{
7431 	case SWIZZLE_TYPE_NONE:
7432 	{
7433 		result_swizzle_string = "";
7434 		result_n_components   = 0;
7435 
7436 		break;
7437 	}
7438 
7439 	case SWIZZLE_TYPE_XWZY:
7440 	{
7441 		result_swizzle_string	 = "xwzy";
7442 		result_n_components		  = 4;
7443 		result_component_order[0] = 0;
7444 		result_component_order[1] = 3;
7445 		result_component_order[2] = 2;
7446 		result_component_order[3] = 1;
7447 
7448 		break;
7449 	}
7450 
7451 	case SWIZZLE_TYPE_XZXY:
7452 	{
7453 		result_swizzle_string	 = "xzxy";
7454 		result_n_components		  = 4;
7455 		result_component_order[0] = 0;
7456 		result_component_order[1] = 2;
7457 		result_component_order[2] = 0;
7458 		result_component_order[3] = 1;
7459 
7460 		break;
7461 	}
7462 
7463 	case SWIZZLE_TYPE_XZY:
7464 	{
7465 		result_swizzle_string	 = "xzy";
7466 		result_n_components		  = 3;
7467 		result_component_order[0] = 0;
7468 		result_component_order[1] = 2;
7469 		result_component_order[2] = 1;
7470 
7471 		break;
7472 	}
7473 
7474 	case SWIZZLE_TYPE_XZYW:
7475 	{
7476 		result_swizzle_string	 = "xzyw";
7477 		result_n_components		  = 4;
7478 		result_component_order[0] = 0;
7479 		result_component_order[1] = 2;
7480 		result_component_order[2] = 1;
7481 		result_component_order[3] = 3;
7482 
7483 		break;
7484 	}
7485 
7486 	case SWIZZLE_TYPE_Y:
7487 	{
7488 		result_swizzle_string	 = "y";
7489 		result_n_components		  = 1;
7490 		result_component_order[0] = 1;
7491 
7492 		break;
7493 	}
7494 
7495 	case SWIZZLE_TYPE_YX:
7496 	{
7497 		result_swizzle_string	 = "yx";
7498 		result_n_components		  = 2;
7499 		result_component_order[0] = 1;
7500 		result_component_order[1] = 0;
7501 
7502 		break;
7503 	}
7504 
7505 	case SWIZZLE_TYPE_YXX:
7506 	{
7507 		result_swizzle_string	 = "yxx";
7508 		result_n_components		  = 3;
7509 		result_component_order[0] = 1;
7510 		result_component_order[1] = 0;
7511 		result_component_order[2] = 0;
7512 
7513 		break;
7514 	}
7515 
7516 	case SWIZZLE_TYPE_YXXY:
7517 	{
7518 		result_swizzle_string	 = "yxxy";
7519 		result_n_components		  = 4;
7520 		result_component_order[0] = 1;
7521 		result_component_order[1] = 0;
7522 		result_component_order[2] = 0;
7523 		result_component_order[3] = 1;
7524 
7525 		break;
7526 	}
7527 
7528 	case SWIZZLE_TYPE_Z:
7529 	{
7530 		result_swizzle_string	 = "z";
7531 		result_n_components		  = 1;
7532 		result_component_order[0] = 2;
7533 
7534 		break;
7535 	}
7536 
7537 	case SWIZZLE_TYPE_ZY:
7538 	{
7539 		result_swizzle_string	 = "zy";
7540 		result_n_components		  = 2;
7541 		result_component_order[0] = 2;
7542 		result_component_order[1] = 1;
7543 
7544 		break;
7545 	}
7546 
7547 	case SWIZZLE_TYPE_W:
7548 	{
7549 		result_swizzle_string	 = "w";
7550 		result_n_components		  = 1;
7551 		result_component_order[0] = 3;
7552 
7553 		break;
7554 	}
7555 
7556 	case SWIZZLE_TYPE_WX:
7557 	{
7558 		result_swizzle_string	 = "wx";
7559 		result_n_components		  = 2;
7560 		result_component_order[0] = 3;
7561 		result_component_order[1] = 0;
7562 
7563 		break;
7564 	}
7565 
7566 	default:
7567 	{
7568 		TCU_FAIL("Unrecognized swizzle type");
7569 	}
7570 	} /* switch (type) */
7571 
7572 	if (out_swizzle_string != DE_NULL)
7573 	{
7574 		*out_swizzle_string = result_swizzle_string;
7575 	}
7576 
7577 	if (out_n_components != DE_NULL)
7578 	{
7579 		*out_n_components = result_n_components;
7580 	}
7581 
7582 	if (out_component_order != DE_NULL)
7583 	{
7584 		memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7585 	}
7586 }
7587 
7588 /** Returns body of a vertex shader that should be used for particular test case,
7589  *  given user-specified test case descriptor.
7590  *
7591  *  @param test_case Descriptor to use for the query.
7592  *
7593  *  @return Requested data.
7594  **/
getVertexShaderBody(const _test_case& test_case)7595 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7596 {
7597 	std::stringstream  result;
7598 	const std::string  base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7599 	const std::string  dst_type_string  = Utils::getVariableTypeString(test_case.dst_type);
7600 	const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7601 	const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7602 	const std::string  src_type_string  = Utils::getVariableTypeString(test_case.src_type);
7603 
7604 	/* Add version preamble */
7605 	result << "#version 420\n"
7606 			  "\n";
7607 
7608 	/* Declare output variables. Note that boolean output variables are not supported, so we need
7609 	 * to handle that special case correctly */
7610 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7611 	{
7612 		result << "out int result;\n";
7613 	}
7614 	else
7615 	{
7616 		result << "out " << dst_type_string << " result;\n";
7617 	}
7618 
7619 	/* Declare input variables. Handle the bool case exclusively. */
7620 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7621 	{
7622 		/* Use ints for bools. We will cast them to bool in the code later. */
7623 		result << "in int base_value;\n";
7624 	}
7625 	else
7626 	{
7627 		result << "in " << base_type_string << " base_value;\n";
7628 	}
7629 
7630 	/* Declare main() and construct the value we will be casting from.
7631 	 *
7632 	 * Note: Addition operations on bool values cause an implicit conversion to int
7633 	 *       which is not allowed. Hence, we skip these operations for this special
7634 	 *       case.
7635 	 */
7636 	result << "void main()\n"
7637 			  "{\n"
7638 		   << src_type_string << " lside_value = ";
7639 
7640 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7641 	{
7642 		result << src_type_string << "(0 != ";
7643 	}
7644 	else
7645 	{
7646 		result << src_type_string << "(";
7647 	}
7648 
7649 	if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7650 	{
7651 		for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7652 		{
7653 			result << "base_value + " << n_component;
7654 
7655 			if (n_component != (n_src_components - 1))
7656 			{
7657 				result << ", ";
7658 			}
7659 		} /* for (all components) */
7660 	}
7661 	else
7662 	{
7663 		DE_ASSERT(n_src_components == 1);
7664 
7665 		result << "base_value";
7666 	}
7667 
7668 	result << ");\n";
7669 
7670 	/* Perform the casting operation. Add swizzle operator if possible. */
7671 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7672 	{
7673 		/* Handle the bool case exclusively */
7674 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7675 		{
7676 			result << "result = (bool(lside_value) == false) ? 0 : 1";
7677 		}
7678 		else
7679 		{
7680 			result << "result = (lside_value == false) ? 0 : 1";
7681 		}
7682 	}
7683 	else
7684 	{
7685 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7686 		{
7687 			result << "result = " << dst_type_string << "(lside_value)";
7688 		}
7689 		else
7690 		{
7691 			result << "result = lside_value";
7692 		}
7693 	}
7694 
7695 	if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7696 	{
7697 		/* Add a swizzle operator  */
7698 		DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7699 		DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7700 
7701 		unsigned int  swizzle_component_order[4] = { 0 };
7702 		unsigned int  swizzle_n_components		 = 0;
7703 		_swizzle_type swizzle_operator			 = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7704 		std::string   swizzle_string;
7705 
7706 		getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7707 
7708 		if (swizzle_n_components > 0)
7709 		{
7710 			result << "." << swizzle_string;
7711 		}
7712 	}
7713 
7714 	/* Close the shader implementation. */
7715 	result << ";\n"
7716 			  "}\n";
7717 
7718 	return result.str();
7719 }
7720 
7721 /** Initializes program & shader objects needed to run the iteration, given
7722  *  user-specified test case descriptor.
7723  *
7724  *  This function can throw a TestError exception if a GL error is detected
7725  *  during execution.
7726  *
7727  *  @param test_case Descriptor to use for the iteration.
7728  **/
initIteration(_test_case& test_case)7729 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7730 {
7731 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7732 
7733 	/* Create program & shader objects */
7734 	m_po_id = gl.createProgram();
7735 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7736 
7737 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7738 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7739 
7740 	/* Configure shader body */
7741 	std::string body		 = getVertexShaderBody(test_case);
7742 	const char* body_raw_ptr = body.c_str();
7743 
7744 	gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7745 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7746 
7747 	/* Store it in the test case descriptor for logging purposes */
7748 	test_case.shader_body = body;
7749 
7750 	/* Compile the shader */
7751 	glw::GLint compile_status = GL_FALSE;
7752 
7753 	gl.compileShader(m_vs_id);
7754 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7755 
7756 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7757 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7758 
7759 	if (compile_status != GL_TRUE)
7760 	{
7761 		TCU_FAIL("Shader compilation failed");
7762 	}
7763 
7764 	/* Attach the shader to the program obejct */
7765 	gl.attachShader(m_po_id, m_vs_id);
7766 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7767 
7768 	/* Configure XFB for the program object */
7769 	const char* xfb_varying_name = "result";
7770 
7771 	gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7773 
7774 	/* Link the program object */
7775 	glw::GLint link_status = GL_FALSE;
7776 
7777 	gl.linkProgram(m_po_id);
7778 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7779 
7780 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7781 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7782 
7783 	if (link_status != GL_TRUE)
7784 	{
7785 		TCU_FAIL("Program linking failed");
7786 	}
7787 
7788 	/* Retrieve attribute locations */
7789 	m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7790 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7791 
7792 	if (m_po_base_value_attribute_location == -1)
7793 	{
7794 		TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7795 	}
7796 }
7797 
7798 /** Initializes GL objects used by all test cases.
7799  *
7800  *  This function may throw a TestError exception if GL implementation reports
7801  *  an error at any point.
7802  **/
initTest()7803 void GPUShaderFP64Test5::initTest()
7804 {
7805 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7806 
7807 	/* Generate buffer object IDs */
7808 	gl.genBuffers(1, &m_base_value_bo_id);
7809 	gl.genBuffers(1, &m_xfb_bo_id);
7810 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7811 
7812 	/* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7813 	 * will never eat up more than 1 double (as per test spec) and we will be drawing
7814 	 * as many points in a single draw call as there are defined in m_base_values array.
7815 	 */
7816 	const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7817 
7818 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7819 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7820 
7821 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7822 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7823 
7824 	/* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7825 	 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7826 	 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7827 	 */
7828 	const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7829 
7830 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7831 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7832 
7833 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7834 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7835 
7836 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7838 
7839 	/* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7840 	m_xfb_bo_size = xfb_bo_size;
7841 
7842 	/* Generate a vertex array object we will need to use for the draw calls */
7843 	gl.genVertexArrays(1, &m_vao_id);
7844 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7845 
7846 	gl.bindVertexArray(m_vao_id);
7847 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7848 }
7849 
7850 /** Executes test iteration.
7851  *
7852  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7853  */
iterate()7854 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7855 {
7856 	/* Do not execute the test if GL_ARB_texture_view is not supported */
7857 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7858 	{
7859 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7860 	}
7861 
7862 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7863 	{
7864 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7865 	}
7866 
7867 	/* Initialize GL objects needed to run the tests */
7868 	initTest();
7869 
7870 	/* Build iteration array to run the tests in an automated manner */
7871 	_test_case test_cases[] = {
7872 		/* test case type */ /* source type */ /* destination type */
7873 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7874 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7875 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7876 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7877 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7878 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7879 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7880 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7881 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7882 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7883 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7884 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7885 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7886 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7887 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7888 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7889 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7890 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7891 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7892 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7893 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7894 
7895 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7896 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7897 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7898 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7899 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7900 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7901 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7902 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7903 	};
7904 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7905 
7906 	/* Execute all iterations */
7907 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7908 	{
7909 		_test_case& test_case = test_cases[n_test_case];
7910 
7911 		/* Initialize a program object we will use to perform the casting */
7912 		initIteration(test_case);
7913 
7914 		/* Use the program object to XFB the results */
7915 		m_has_test_passed &= executeIteration(test_case);
7916 
7917 		/* Release the GL Resource for this sub test */
7918 		deinitInteration();
7919 
7920 	} /* for (all test cases) */
7921 	/* We're done */
7922 	if (m_has_test_passed)
7923 	{
7924 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7925 	}
7926 	else
7927 	{
7928 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7929 	}
7930 
7931 	return STOP;
7932 }
7933 
7934 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7935  *  for which the data have been generated.
7936  *
7937  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
7938  *  @param test_case Descriptor of the test case, for which the vertex shader was
7939  *                   generated.
7940  *
7941  *  @return true if the data were found to be valid, false otherwise.
7942  **/
verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)7943 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7944 {
7945 	const Utils::_variable_type base_dst_type		= Utils::getBaseVariableType(test_case.dst_type);
7946 	const Utils::_variable_type base_src_type		= Utils::getBaseVariableType(test_case.src_type);
7947 	const float					epsilon				= 1e-5f;
7948 	const unsigned int			n_base_values		= sizeof(m_base_values) / sizeof(m_base_values[0]);
7949 	const unsigned int			n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7950 	const unsigned int			n_src_components	= Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7951 	bool						result				= true;
7952 	_swizzle_type				swizzle_operator	= SWIZZLE_TYPE_NONE;
7953 	unsigned int				swizzle_order[4]	= { 0 };
7954 	const unsigned char*		traveller_ptr		= data_ptr;
7955 
7956 	if (!Utils::isMatrixVariableType(test_case.src_type))
7957 	{
7958 		DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7959 		DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7960 
7961 		swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7962 
7963 		getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7964 								 DE_NULL,					/* out_n_components */
7965 								 swizzle_order);
7966 	}
7967 
7968 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7969 	{
7970 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7971 		{
7972 			unsigned int n_swizzled_component = n_result_component;
7973 
7974 			if (swizzle_operator != SWIZZLE_TYPE_NONE)
7975 			{
7976 				n_swizzled_component =
7977 					(n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7978 			}
7979 
7980 			switch (base_dst_type)
7981 			{
7982 			case Utils::VARIABLE_TYPE_BOOL:
7983 			case Utils::VARIABLE_TYPE_INT:
7984 			{
7985 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7986 				double expected_value	 = ref_expected_value;
7987 				int	result_value		  = *((int*)traveller_ptr);
7988 
7989 				if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7990 				{
7991 					if (expected_value != 0.0)
7992 					{
7993 						expected_value = 1.0;
7994 					}
7995 				}
7996 
7997 				if (result_value != (int)expected_value)
7998 				{
7999 					m_testCtx.getLog() << tcu::TestLog::Message
8000 									   << "Invalid boolean/integer value obtained when doing an "
8001 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8002 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8003 									   << "]"
8004 										  ", component index: ["
8005 									   << n_swizzled_component << "]"
8006 																  ", value: ["
8007 									   << ref_expected_value << "]"
8008 																" to GLSL type ["
8009 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8010 																							  ", retrieved value: ["
8011 									   << result_value << "]"
8012 														  ", expected value: ["
8013 									   << (int)expected_value << "]"
8014 																 ", shader used:\n"
8015 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8016 
8017 					result = false;
8018 				}
8019 
8020 				traveller_ptr += sizeof(int);
8021 				break;
8022 			} /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8023 
8024 			case Utils::VARIABLE_TYPE_DOUBLE:
8025 			{
8026 				double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8027 				double expected_value	 = ref_expected_value;
8028 				double result_value		  = *((double*)traveller_ptr);
8029 
8030 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8031 				{
8032 					expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8033 				}
8034 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8035 				{
8036 					expected_value = (int)expected_value;
8037 				}
8038 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8039 				{
8040 					// Negative values in base values array when converted to unsigned int will be ZERO
8041 					// Addition operations done inside the shader in such cases will operate on ZERO rather
8042 					// than the negative value being passed.
8043 					// Replicate the sequence of conversion and addition operations done on the
8044 					// shader input, to calculate the expected values in XFB data in the
8045 					// problematic cases.
8046 					if (expected_value < 0)
8047 					{
8048 						expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8049 					}
8050 					expected_value = (unsigned int)expected_value;
8051 				}
8052 
8053 				traveller_ptr += sizeof(double);
8054 				if (de::abs(result_value - expected_value) > epsilon)
8055 				{
8056 					m_testCtx.getLog() << tcu::TestLog::Message
8057 									   << "Invalid double-precision floating-point value obtained when doing an "
8058 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8059 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8060 									   << "]"
8061 										  ", component index: ["
8062 									   << n_swizzled_component << "]"
8063 																  ", value: ["
8064 									   << ref_expected_value << "]"
8065 																" to GLSL type ["
8066 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8067 																							  ", retrieved value: ["
8068 									   << std::setprecision(16) << result_value << "]"
8069 																				   ", expected value: ["
8070 									   << std::setprecision(16) << expected_value << "]"
8071 																					 ", shader used:\n"
8072 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8073 
8074 					result = false;
8075 				}
8076 
8077 				break;
8078 			} /* VARIABLE_TYPE_DOUBLE case */
8079 
8080 			case Utils::VARIABLE_TYPE_FLOAT:
8081 			{
8082 				float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8083 				float expected_value	 = ref_expected_value;
8084 				float result_value		 = *((float*)traveller_ptr);
8085 
8086 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8087 				{
8088 					expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8089 				}
8090 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8091 				{
8092 					expected_value = (float)((int)expected_value);
8093 				}
8094 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8095 				{
8096 					expected_value = (float)((unsigned int)expected_value);
8097 				}
8098 
8099 				traveller_ptr += sizeof(float);
8100 				if (de::abs(result_value - expected_value) > epsilon)
8101 				{
8102 					m_testCtx.getLog() << tcu::TestLog::Message
8103 									   << "Invalid single-precision floating-point value obtained when doing an "
8104 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8105 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8106 									   << "]"
8107 										  ", component index: ["
8108 									   << n_swizzled_component << "]"
8109 																  ", value: ["
8110 									   << ref_expected_value << "]"
8111 																" to GLSL type ["
8112 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8113 																							  ", retrieved value: ["
8114 									   << std::setprecision(16) << result_value << "]"
8115 																				   ", expected value: ["
8116 									   << std::setprecision(16) << expected_value << "]"
8117 																					 ", shader used:\n"
8118 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8119 
8120 					result = false;
8121 				}
8122 
8123 				break;
8124 			} /* VARIABLE_TYPE_FLOAT case */
8125 
8126 			case Utils::VARIABLE_TYPE_UINT:
8127 			{
8128 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8129 				double expected_value	 = ref_expected_value;
8130 				unsigned int result_value = *((unsigned int*)traveller_ptr);
8131 
8132 				traveller_ptr += sizeof(unsigned int);
8133 				if (result_value != (unsigned int)expected_value)
8134 				{
8135 					if (expected_value < 0.0)
8136 					{
8137 						// It is undefined to convert a negative floating-point value to an uint.
8138 						break;
8139 					}
8140 
8141 					m_testCtx.getLog() << tcu::TestLog::Message
8142 									   << "Invalid unsigned integer value obtained when doing an "
8143 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8144 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8145 									   << "]"
8146 										  ", component index: ["
8147 									   << n_swizzled_component << "]"
8148 																  ", value: ["
8149 									   << ref_expected_value << "]"
8150 																" to GLSL type ["
8151 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8152 																							  ", retrieved value: ["
8153 									   << result_value << "]"
8154 														  ", expected value: ["
8155 									   << (unsigned int)expected_value << "]"
8156 																		  ", shader used:\n"
8157 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8158 
8159 					result = false;
8160 				}
8161 
8162 				break;
8163 			} /* VARIABLE_TYPE_UINT case */
8164 
8165 			default:
8166 			{
8167 				TCU_FAIL("Unrecognized variable type");
8168 			}
8169 			} /* switch (test_case.dst_type) */
8170 		}	 /* for (all result components) */
8171 	}		  /* for (all base values) */
8172 
8173 	return result;
8174 }
8175 
8176 /** Constructor
8177  *
8178  *  @param context Rendering context.
8179  */
GPUShaderFP64Test6(deqp::Context& context)8180 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8181 	: TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8182 											   "during compilation time.")
8183 	, m_cs_id(0)
8184 	, m_fs_id(0)
8185 	, m_gs_id(0)
8186 	, m_tc_id(0)
8187 	, m_te_id(0)
8188 	, m_vs_id(0)
8189 	, m_has_test_passed(true)
8190 {
8191 }
8192 
8193 /** Deinitializes all buffers and GL objects that may have been generated
8194  *  during test execution.
8195  **/
deinit()8196 void GPUShaderFP64Test6::deinit()
8197 {
8198 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8199 
8200 	if (m_cs_id != 0)
8201 	{
8202 		gl.deleteShader(m_cs_id);
8203 
8204 		m_cs_id = 0;
8205 	}
8206 
8207 	if (m_fs_id != 0)
8208 	{
8209 		gl.deleteShader(m_fs_id);
8210 
8211 		m_fs_id = 0;
8212 	}
8213 
8214 	if (m_gs_id != 0)
8215 	{
8216 		gl.deleteShader(m_gs_id);
8217 
8218 		m_gs_id = 0;
8219 	}
8220 
8221 	if (m_tc_id != 0)
8222 	{
8223 		gl.deleteShader(m_tc_id);
8224 
8225 		m_tc_id = 0;
8226 	}
8227 
8228 	if (m_te_id != 0)
8229 	{
8230 		gl.deleteShader(m_te_id);
8231 
8232 		m_te_id = 0;
8233 	}
8234 
8235 	if (m_vs_id != 0)
8236 	{
8237 		gl.deleteShader(m_vs_id);
8238 
8239 		m_vs_id = 0;
8240 	}
8241 }
8242 
8243 /** Executes a single test case.
8244  *
8245  *  This function can throw TestError exceptions if GL implementation reports
8246  *  an error.
8247  *
8248  *  @param test_case Test case descriptor.
8249  *
8250  *  @return true if test case passed, false otherwise.
8251  **/
executeIteration(const _test_case& test_case)8252 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8253 {
8254 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
8255 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8256 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
8257 	bool				  result	 = true;
8258 	const char*			  stage_body = NULL;
8259 	const char*			  stage_name = NULL;
8260 
8261 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8262 	{
8263 		const glw::GLuint so_id = so_ids[n_so_id];
8264 
8265 		/* Skip compute shader if it is not supported */
8266 		if (0 == so_id)
8267 		{
8268 			continue;
8269 		}
8270 
8271 		/* Compile the shader */
8272 		gl.compileShader(so_id);
8273 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8274 
8275 		/* Has the compilation failed as expected? */
8276 		glw::GLint compile_status = GL_TRUE;
8277 
8278 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8279 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8280 
8281 		if (compile_status == GL_TRUE)
8282 		{
8283 			/* What is the current stage's name? */
8284 			if (so_id == m_cs_id)
8285 			{
8286 				stage_body = test_case.cs_shader_body.c_str();
8287 				stage_name = "Compute shader";
8288 			}
8289 			else if (so_id == m_fs_id)
8290 			{
8291 				stage_body = test_case.fs_shader_body.c_str();
8292 				stage_name = "Fragment shader";
8293 			}
8294 			else if (so_id == m_gs_id)
8295 			{
8296 				stage_body = test_case.gs_shader_body.c_str();
8297 				stage_name = "Geometry shader";
8298 			}
8299 			else if (so_id == m_tc_id)
8300 			{
8301 				stage_body = test_case.tc_shader_body.c_str();
8302 				stage_name = "Tessellation control shader";
8303 			}
8304 			else if (so_id == m_te_id)
8305 			{
8306 				stage_body = test_case.te_shader_body.c_str();
8307 				stage_name = "Tessellation evaluation shader";
8308 			}
8309 			else if (so_id == m_vs_id)
8310 			{
8311 				stage_body = test_case.vs_shader_body.c_str();
8312 				stage_name = "Vertex shader";
8313 			}
8314 			else
8315 			{
8316 				/* Doesn't make much sense to throw exceptions here so.. */
8317 				stage_body = "";
8318 				stage_name = "[?]";
8319 			}
8320 
8321 			/* This shader should have never compiled successfully! */
8322 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8323 							   << " has been compiled successfully, even though the shader was malformed."
8324 								  " Following is shader body:\n"
8325 							   << stage_body << tcu::TestLog::EndMessage;
8326 
8327 			result = false;
8328 		}
8329 	} /* for (all shader objects) */
8330 
8331 	return result;
8332 }
8333 
8334 /** Retrieves body of a compute shader that should be used for the purpose of
8335  *  user-specified test case.
8336  *
8337  *  @param test_case Test case descriptor to use.
8338  *
8339  *  @return Requested string.
8340  **/
getComputeShaderBody(const _test_case& test_case)8341 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8342 {
8343 	std::stringstream result_sstream;
8344 
8345 	/* Add pre-amble */
8346 	result_sstream << "#version 420\n"
8347 					  "#extension GL_ARB_compute_shader          : require\n"
8348 					  "\n"
8349 					  "layout(local_size_x = 6) in;\n"
8350 					  "\n"
8351 					  "void main()\n"
8352 					  "{\n";
8353 
8354 	/* Add local variable declarations */
8355 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8356 
8357 	if (test_case.src_array_size > 1)
8358 	{
8359 		result_sstream << "[" << test_case.src_array_size << "]";
8360 	}
8361 
8362 	result_sstream << ";\n";
8363 
8364 	if (test_case.wrap_dst_type_in_structure)
8365 	{
8366 		result_sstream << "struct\n"
8367 						  "{\n"
8368 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8369 	}
8370 	else
8371 	{
8372 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8373 	}
8374 
8375 	result_sstream << ";\n";
8376 
8377 	if (test_case.wrap_dst_type_in_structure)
8378 	{
8379 		result_sstream << "\n} dst;\n";
8380 	}
8381 
8382 	/* Add actual body */
8383 	result_sstream << "dst = src;\n"
8384 					  "}\n";
8385 
8386 	/* Return the body */
8387 	return result_sstream.str();
8388 }
8389 
8390 /** Retrieves body of a fragment shader that should be used for the purpose of
8391  *  user-specified test case.
8392  *
8393  *  @param test_case Test case descriptor to use.
8394  *
8395  *  @return Requested string.
8396  **/
getFragmentShaderBody(const _test_case& test_case)8397 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8398 {
8399 	std::stringstream result_sstream;
8400 
8401 	/* Add pre-amble */
8402 	result_sstream << "#version 420\n"
8403 					  "\n"
8404 					  "void main()\n"
8405 					  "{\n";
8406 
8407 	/* Add local variable declarations */
8408 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8409 
8410 	if (test_case.src_array_size > 1)
8411 	{
8412 		result_sstream << "[" << test_case.src_array_size << "]";
8413 	}
8414 
8415 	result_sstream << ";\n";
8416 
8417 	if (test_case.wrap_dst_type_in_structure)
8418 	{
8419 		result_sstream << "struct\n"
8420 						  "{\n"
8421 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8422 	}
8423 	else
8424 	{
8425 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8426 	}
8427 
8428 	result_sstream << ";\n";
8429 
8430 	if (test_case.wrap_dst_type_in_structure)
8431 	{
8432 		result_sstream << "\n} dst;\n";
8433 	}
8434 
8435 	/* Add actual body */
8436 	result_sstream << "dst = src;\n"
8437 					  "}\n";
8438 
8439 	/* Return the body */
8440 	return result_sstream.str();
8441 }
8442 
8443 /** Retrieves body of a geometry shader that should be used for the purpose of
8444  *  user-specified test case.
8445  *
8446  *  @param test_case Test case descriptor to use.
8447  *
8448  *  @return Requested string.
8449  **/
getGeometryShaderBody(const _test_case& test_case)8450 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8451 {
8452 	std::stringstream result_sstream;
8453 
8454 	/* Add preamble */
8455 	result_sstream << "#version 420\n"
8456 					  "\n"
8457 					  "layout(points)                 in;\n"
8458 					  "layout(max_vertices=1, points) out;\n"
8459 					  "\n"
8460 					  "void main()\n"
8461 					  "{\n";
8462 
8463 	/* Add local variable declarations */
8464 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8465 
8466 	if (test_case.src_array_size > 1)
8467 	{
8468 		result_sstream << "[" << test_case.src_array_size << "]";
8469 	}
8470 
8471 	result_sstream << ";\n";
8472 
8473 	if (test_case.wrap_dst_type_in_structure)
8474 	{
8475 		result_sstream << "struct\n"
8476 						  "{\n"
8477 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8478 	}
8479 	else
8480 	{
8481 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8482 	}
8483 
8484 	result_sstream << ";\n"
8485 					  "\n";
8486 
8487 	if (test_case.wrap_dst_type_in_structure)
8488 	{
8489 		result_sstream << "} dst;\n";
8490 	}
8491 
8492 	/* Add actual body */
8493 	result_sstream << "dst = src;\n"
8494 					  "}\n";
8495 
8496 	/* We're done! */
8497 	return result_sstream.str();
8498 }
8499 
8500 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8501  *  user-specified test case.
8502  *
8503  *  @param test_case Test case descriptor to use.
8504  *
8505  *  @return Requested string.
8506  **/
getTessellationControlShaderBody(const _test_case& test_case)8507 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8508 {
8509 	std::stringstream result_sstream;
8510 
8511 	/* Add preamble */
8512 	result_sstream << "#version 420\n"
8513 					  "\n"
8514 					  "layout(vertices=4) out;\n"
8515 					  "\n"
8516 					  "void main()\n"
8517 					  "{\n";
8518 
8519 	/* Add local variable declarations. */
8520 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8521 
8522 	if (test_case.src_array_size > 1)
8523 	{
8524 		result_sstream << "[" << test_case.src_array_size << "]";
8525 	}
8526 
8527 	result_sstream << ";\n";
8528 
8529 	if (test_case.wrap_dst_type_in_structure)
8530 	{
8531 		result_sstream << "struct\n"
8532 						  "{\n"
8533 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8534 	}
8535 	else
8536 	{
8537 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8538 	}
8539 
8540 	if (test_case.wrap_dst_type_in_structure)
8541 	{
8542 		result_sstream << ";\n"
8543 						  "} dst;\n";
8544 	}
8545 	else
8546 	{
8547 		result_sstream << ";\n";
8548 	}
8549 
8550 	/* Continue with the actual body. */
8551 	result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8552 					  "gl_TessLevelOuter[1] = 1.0;\n"
8553 					  "dst                  = src;\n"
8554 					  "}\n";
8555 
8556 	/* Return the body */
8557 	return result_sstream.str();
8558 }
8559 
8560 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8561  *  user-specified test case.
8562  *
8563  *  @param test_case Test case descriptor to use.
8564  *
8565  *  @return Requested string.
8566  **/
getTessellationEvaluationShaderBody(const _test_case& test_case)8567 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8568 {
8569 	std::stringstream result_sstream;
8570 
8571 	/* Add preamble */
8572 	result_sstream << "#version 420\n"
8573 					  "\n"
8574 					  "layout(isolines) in;\n"
8575 					  "\n"
8576 					  "void main()\n"
8577 					  "{\n";
8578 
8579 	/* Add local variable declarations */
8580 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8581 
8582 	if (test_case.src_array_size > 1)
8583 	{
8584 		result_sstream << "[" << test_case.src_array_size << "]";
8585 	}
8586 
8587 	result_sstream << ";\n";
8588 
8589 	if (test_case.wrap_dst_type_in_structure)
8590 	{
8591 		result_sstream << "struct\n"
8592 						  "{\n"
8593 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8594 	}
8595 	else
8596 	{
8597 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8598 	}
8599 
8600 	if (test_case.wrap_dst_type_in_structure)
8601 	{
8602 		result_sstream << ";\n"
8603 						  "} dst;\n";
8604 	}
8605 	else
8606 	{
8607 		result_sstream << ";\n";
8608 	}
8609 
8610 	/* Continue with the actual body. */
8611 	result_sstream << "dst = src;\n";
8612 
8613 	/* Complete the body */
8614 	result_sstream << "}\n";
8615 
8616 	/* Return the body */
8617 	return result_sstream.str();
8618 }
8619 
8620 /** Retrieves body of a vertex shader that should be used for the purpose of
8621  *  user-specified test case.
8622  *
8623  *  @param test_case Test case descriptor to use.
8624  *
8625  *  @return Requested string.
8626  **/
getVertexShaderBody(const _test_case& test_case)8627 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8628 {
8629 	std::stringstream result_sstream;
8630 
8631 	/* Add preamble */
8632 	result_sstream << "#version 420\n"
8633 					  "\n"
8634 					  "void main()\n"
8635 					  "{\n";
8636 
8637 	/* Add local variables */
8638 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8639 
8640 	if (test_case.src_array_size > 1)
8641 	{
8642 		result_sstream << "[" << test_case.src_array_size << "]";
8643 	}
8644 
8645 	result_sstream << ";\n";
8646 
8647 	if (test_case.wrap_dst_type_in_structure)
8648 	{
8649 		result_sstream << "struct\n"
8650 						  "{\n"
8651 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8652 	}
8653 	else
8654 	{
8655 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8656 	}
8657 
8658 	if (test_case.wrap_dst_type_in_structure)
8659 	{
8660 		result_sstream << ";\n"
8661 						  "} dst;\n";
8662 	}
8663 	else
8664 	{
8665 		result_sstream << ";\n";
8666 	}
8667 
8668 	/* Start actual body */
8669 	result_sstream << "dst         = src;\n"
8670 					  "gl_Position = vec4(1.0);\n"
8671 					  "}";
8672 
8673 	return result_sstream.str();
8674 }
8675 
8676 /** Initializes shader objects required to run the test. */
initTest()8677 void GPUShaderFP64Test6::initTest()
8678 {
8679 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8680 
8681 	/* Generate shader objects */
8682 
8683 	/* Compute shader support and GL 4.2 required */
8684 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8685 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8686 	{
8687 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8688 	}
8689 
8690 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8691 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8692 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8693 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8694 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8695 
8696 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8697 }
8698 
8699 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8700  *
8701  *  @param test_case Test case descriptor to generate the shader bodies for.
8702  **/
initIteration(_test_case& test_case)8703 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8704 {
8705 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8706 
8707 	test_case.cs_shader_body = getComputeShaderBody(test_case);
8708 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
8709 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
8710 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8711 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8712 	test_case.vs_shader_body = getVertexShaderBody(test_case);
8713 
8714 	/* Assign the bodies to relevant shaders */
8715 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8716 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8717 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8718 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8719 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8720 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8721 
8722 	/* m_cs_id is initialized only if compute_shader is supported */
8723 	if (0 != m_cs_id)
8724 	{
8725 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8726 	}
8727 
8728 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8729 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8730 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8731 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8732 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8733 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8734 }
8735 
8736 /** Executes test iteration.
8737  *
8738  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8739  */
iterate()8740 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8741 {
8742 	/* Do not execute the test if GL_ARB_texture_view is not supported */
8743 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8744 	{
8745 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8746 	}
8747 
8748 	/* Initialize GL objects needed to run the tests */
8749 	initTest();
8750 
8751 	/* Build iteration array to run the tests in an automated manner */
8752 	_test_case test_cases[] = {
8753 		/* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8754 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8755 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8756 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8757 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8758 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8759 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8760 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8761 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8762 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8763 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8764 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8765 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8766 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8767 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8768 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8769 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8770 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8771 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8772 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8773 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8774 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8775 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8776 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8777 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8778 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8779 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8780 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8781 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8782 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8783 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8784 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8785 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8786 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8787 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8788 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8789 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8790 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8791 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8792 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8793 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8794 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8795 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8796 	};
8797 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8798 
8799 	/* Execute all iterations */
8800 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8801 	{
8802 		_test_case& test_case = test_cases[n_test_case];
8803 
8804 		/* Initialize a program object we will use to perform the casting */
8805 		initIteration(test_case);
8806 
8807 		/* Use the program object to XFB the results */
8808 		m_has_test_passed &= executeIteration(test_case);
8809 
8810 	} /* for (all test cases) */
8811 
8812 	/* We're done */
8813 	if (m_has_test_passed)
8814 	{
8815 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8816 	}
8817 	else
8818 	{
8819 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8820 	}
8821 
8822 	return STOP;
8823 }
8824 
8825 /** Constructor
8826  *
8827  *  @param context Rendering context.
8828  */
GPUShaderFP64Test7(deqp::Context& context)8829 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8830 	: TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8831 									"in all shader stages.")
8832 	, m_are_double_inputs_supported(false)
8833 	, m_fbo_id(0)
8834 	, m_fs_id(0)
8835 	, m_gs_id(0)
8836 	, m_has_test_passed(true)
8837 	, m_n_max_components_per_stage(0)
8838 	, m_n_xfb_varyings(0)
8839 	, m_po_id(0)
8840 	, m_tc_id(0)
8841 	, m_te_id(0)
8842 	, m_to_id(0)
8843 	, m_to_data(NULL)
8844 	, m_to_height(4)
8845 	, m_to_width(4)
8846 	, m_xfb_bo_id(0)
8847 	, m_xfb_varyings(NULL)
8848 	, m_vao_id(0)
8849 	, m_vs_id(0)
8850 {
8851 }
8852 
8853 /** Compiles all shaders attached to test program object and links it.
8854  *
8855  *  @param variables
8856  *
8857  *  @return true if the process was executed successfully, false otherwise.
8858  */
buildTestProgram(_variables& variables)8859 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8860 {
8861 	std::string			  fs_body = getFragmentShaderBody(variables);
8862 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
8863 	std::string			  gs_body = getGeometryShaderBody(variables);
8864 	std::string			  tc_body = getTessellationControlShaderBody(variables);
8865 	std::string			  te_body = getTessellationEvaluationShaderBody(variables);
8866 	std::string			  vs_body = getVertexShaderBody(variables);
8867 	bool				  result  = false;
8868 
8869 	/* Try to link the program object */
8870 	glw::GLint link_status = GL_FALSE;
8871 
8872 	/* Compile the shaders */
8873 	if (!compileShader(m_fs_id, fs_body))
8874 	{
8875 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8876 
8877 		goto end;
8878 	}
8879 
8880 	if (!compileShader(m_gs_id, gs_body))
8881 	{
8882 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8883 
8884 		goto end;
8885 	}
8886 
8887 	if (!compileShader(m_tc_id, tc_body))
8888 	{
8889 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8890 						   << tcu::TestLog::EndMessage;
8891 
8892 		goto end;
8893 	}
8894 
8895 	if (!compileShader(m_te_id, te_body))
8896 	{
8897 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8898 						   << tcu::TestLog::EndMessage;
8899 
8900 		goto end;
8901 	}
8902 
8903 	if (!compileShader(m_vs_id, vs_body))
8904 	{
8905 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8906 
8907 		goto end;
8908 	}
8909 
8910 	/* Configure XFB */
8911 	releaseXFBVaryingNames();
8912 	generateXFBVaryingNames(variables);
8913 
8914 	gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8915 
8916 	gl.linkProgram(m_po_id);
8917 
8918 	/* Have we succeeded? */
8919 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8920 
8921 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8922 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8923 
8924 	if (link_status != GL_TRUE)
8925 	{
8926 		m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8927 						   << tcu::TestLog::EndMessage;
8928 
8929 		goto end;
8930 	}
8931 
8932 	/* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8933 	if (m_are_double_inputs_supported)
8934 	{
8935 		const size_t n_variables = variables.size();
8936 
8937 		for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8938 		{
8939 			_variable&		  current_variable = variables[n_variable];
8940 			std::stringstream attribute_name_sstream;
8941 
8942 			attribute_name_sstream << "in_vs_variable" << n_variable;
8943 
8944 			if (current_variable.array_size > 1)
8945 			{
8946 				attribute_name_sstream << "[0]";
8947 			}
8948 
8949 			current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8950 
8951 			if (current_variable.attribute_location == -1)
8952 			{
8953 				m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8954 								   << attribute_name_sstream.str().c_str()
8955 								   << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8956 
8957 				m_has_test_passed = false;
8958 				goto end;
8959 			}
8960 		} /* for (all test variables) */
8961 	}	 /* if (m_are_double_inputs_supported) */
8962 
8963 	m_current_fs_body = fs_body;
8964 	m_current_gs_body = gs_body;
8965 	m_current_tc_body = tc_body;
8966 	m_current_te_body = te_body;
8967 	m_current_vs_body = vs_body;
8968 
8969 	result = true;
8970 
8971 end:
8972 	return result;
8973 }
8974 
8975 /** Updates shader object's body and then compiles the shader.
8976  *
8977  *  @param body Body to use for the shader.
8978  *
8979  *  @return true if the shader compiled successfully, false otherwise.
8980  **/
compileShader(glw::GLint shader_id, const std::string& body)8981 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8982 {
8983 	const char*			  body_raw_ptr   = body.c_str();
8984 	glw::GLint			  compile_status = GL_FALSE;
8985 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
8986 
8987 	gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8989 
8990 	gl.compileShader(shader_id);
8991 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8992 
8993 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8994 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8995 
8996 	return (compile_status == GL_TRUE);
8997 }
8998 
8999 /** Configure storage of a buffer object used for capturing XFB data.
9000  *
9001  *  @param variables Holds descriptor for all variables used for the iteration the
9002  *                   BO is being configured for. Storage size will be directly related
9003  *                   to the number of the variables and their type.
9004  */
configureXFBBuffer(const _variables& variables)9005 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9006 {
9007 	DE_ASSERT(m_n_xfb_varyings != 0);
9008 
9009 	/* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9010 	 * The test only draws a single patch, and triangles are caught by transform feed-back.
9011 	 * Let's initialize the storage, according to the list of variables that will be used
9012 	 * for the test run.
9013 	 */
9014 	unsigned int bo_size = 0;
9015 
9016 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9017 		 variables_iterator++)
9018 	{
9019 		const _variable& variable		= *variables_iterator;
9020 		unsigned int	 n_bytes_needed = static_cast<unsigned int>(
9021 			Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9022 
9023 		bo_size += n_bytes_needed;
9024 	} /* for (all variables) */
9025 
9026 	bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9027 
9028 	/* Set up the BO storage */
9029 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9030 
9031 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9032 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9033 }
9034 
9035 /** Deinitializes all buffers and GL objects that may have been generated
9036  *  during test execution.
9037  **/
deinit()9038 void GPUShaderFP64Test7::deinit()
9039 {
9040 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9041 
9042 	if (m_fbo_id != 0)
9043 	{
9044 		gl.deleteFramebuffers(1, &m_fbo_id);
9045 
9046 		m_fbo_id = 0;
9047 	}
9048 
9049 	if (m_fs_id != 0)
9050 	{
9051 		gl.deleteShader(m_fs_id);
9052 
9053 		m_fs_id = 0;
9054 	}
9055 
9056 	if (m_gs_id != 0)
9057 	{
9058 		gl.deleteShader(m_gs_id);
9059 
9060 		m_gs_id = 0;
9061 	}
9062 
9063 	if (m_po_id != 0)
9064 	{
9065 		gl.deleteProgram(m_po_id);
9066 
9067 		m_po_id = 0;
9068 	}
9069 
9070 	if (m_tc_id != 0)
9071 	{
9072 		gl.deleteShader(m_tc_id);
9073 
9074 		m_tc_id = 0;
9075 	}
9076 
9077 	if (m_te_id != 0)
9078 	{
9079 		gl.deleteShader(m_te_id);
9080 
9081 		m_te_id = 0;
9082 	}
9083 
9084 	if (m_to_data != NULL)
9085 	{
9086 		delete[] m_to_data;
9087 
9088 		m_to_data = NULL;
9089 	}
9090 
9091 	if (m_to_id != 0)
9092 	{
9093 		gl.deleteTextures(1, &m_to_id);
9094 
9095 		m_to_id = 0;
9096 	}
9097 
9098 	if (m_xfb_bo_id != 0)
9099 	{
9100 		gl.deleteBuffers(1, &m_xfb_bo_id);
9101 
9102 		m_xfb_bo_id = 0;
9103 	}
9104 
9105 	if (m_xfb_varyings != DE_NULL)
9106 	{
9107 		releaseXFBVaryingNames();
9108 	}
9109 
9110 	if (m_vao_id != 0)
9111 	{
9112 		gl.deleteVertexArrays(1, &m_vao_id);
9113 
9114 		m_vao_id = 0;
9115 	}
9116 
9117 	if (m_vs_id != 0)
9118 	{
9119 		gl.deleteShader(m_vs_id);
9120 
9121 		m_vs_id = 0;
9122 	}
9123 }
9124 
9125 /** Executes the functional part of the test (case a) from the test spec)
9126  *
9127  *  @param variables Vector of variable descriptors defining properties of
9128  *                   variables that should be used for the iteration.
9129  *
9130  *  @return true if the test passed, false otherwise.
9131  **/
executeFunctionalTest(_variables& variables)9132 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9133 {
9134 	bool result = true;
9135 
9136 	/* Build the test program */
9137 	if (!buildTestProgram(variables))
9138 	{
9139 		return false;
9140 	}
9141 
9142 	/* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9143 	if (m_are_double_inputs_supported)
9144 	{
9145 		setInputAttributeValues(variables);
9146 	}
9147 
9148 	/* Set up buffer object to hold XFB data. The data will be used for logging purposes
9149 	 * only, if a data mismatch is detected.
9150 	 */
9151 	configureXFBBuffer(variables);
9152 
9153 	/* Issue a draw call using the test program */
9154 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9155 
9156 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9157 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9158 
9159 	gl.clear(GL_COLOR_BUFFER_BIT);
9160 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9161 
9162 	gl.useProgram(m_po_id);
9163 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9164 
9165 	gl.viewport(0, /* x */
9166 				0, /* y */
9167 				m_to_width, m_to_height);
9168 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9169 
9170 	gl.beginTransformFeedback(GL_TRIANGLES);
9171 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9172 	{
9173 		gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9174 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9175 	}
9176 	gl.endTransformFeedback();
9177 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9178 
9179 	/* Verify color attachment contents */
9180 	const float epsilon = 1.0f / 255.0f;
9181 
9182 	gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9183 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9184 
9185 	for (unsigned int y = 0; y < m_to_height; ++y)
9186 	{
9187 		const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9188 
9189 		for (unsigned int x = 0; x < m_to_width; ++x)
9190 		{
9191 			const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9192 
9193 			if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9194 				de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9195 			{
9196 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9197 								   << ")"
9198 									  "; expected:(0, 255, 0, 0), found: ("
9199 								   << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9200 								   << ", " << (int)pixel_ptr[3]
9201 								   << "), with the following variable types used as varyings:"
9202 								   << tcu::TestLog::EndMessage;
9203 
9204 				/* List the variable types that failed the test */
9205 				const size_t n_variables = variables.size();
9206 
9207 				for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9208 				{
9209 					m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9210 									   << Utils::getVariableTypeString(variables[n_variable].type)
9211 									   << " (array size:" << variables[n_variable].array_size << ")"
9212 									   << tcu::TestLog::EndMessage;
9213 				} /* for (all variable types) */
9214 
9215 				/* Log the variable contents */
9216 				logVariableContents(variables);
9217 
9218 				/* Log shaders used for the iteration */
9219 				m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9220 															   "\n"
9221 															   "(VS):\n"
9222 								   << m_current_vs_body.c_str() << "\n"
9223 								   << "(TC):\n"
9224 									  "\n"
9225 								   << m_current_tc_body.c_str() << "\n"
9226 																   "(TE):\n"
9227 																   "\n"
9228 								   << m_current_te_body.c_str() << "\n"
9229 																   "(GS):\n"
9230 								   << m_current_gs_body.c_str() << "\n"
9231 																   "(FS):\n"
9232 																   "\n"
9233 								   << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9234 
9235 				result = false;
9236 
9237 				goto end;
9238 			}
9239 		} /* for (all columns) */
9240 	}	 /* for (all rows) */
9241 
9242 /* All done! */
9243 end:
9244 	return result;
9245 }
9246 
9247 /** Takes user-input vector of test variables and allocates & fills an array of strings
9248  *  holding names of geometry shader stage varyings that should be captured during
9249  *  transform feedback operation. The array will be stored in m_xfb_varyings.
9250  *
9251  *  @param variables Holds all test variable descriptors to be used for the iteration.
9252  */
generateXFBVaryingNames(const _variables& variables)9253 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9254 {
9255 	unsigned int n_variable = 0;
9256 	unsigned int n_varying  = 0;
9257 	unsigned int n_varyings = 0;
9258 
9259 	if (m_xfb_varyings != NULL)
9260 	{
9261 		releaseXFBVaryingNames();
9262 	}
9263 
9264 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9265 		 ++variables_iterator)
9266 	{
9267 		const _variable& variable = *variables_iterator;
9268 
9269 		n_varyings += variable.array_size;
9270 	}
9271 
9272 	m_xfb_varyings = new glw::GLchar*[n_varyings];
9273 
9274 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9275 		 ++variables_iterator, ++n_variable)
9276 	{
9277 		const _variable& variable = *variables_iterator;
9278 
9279 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9280 		{
9281 			std::stringstream varying_sstream;
9282 			size_t			  varying_length;
9283 
9284 			varying_sstream << "gs_variable" << n_variable;
9285 
9286 			if (variable.array_size > 1)
9287 			{
9288 				varying_sstream << "[" << array_index << "]";
9289 			}
9290 
9291 			/* Store the varying name */
9292 			varying_length			  = varying_sstream.str().length();
9293 			m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9294 
9295 			memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9296 			m_xfb_varyings[n_varying][varying_length] = 0;
9297 		} /* for (all array indices) */
9298 	}	 /* for (all varyings) */
9299 
9300 	m_n_xfb_varyings = n_varyings;
9301 }
9302 
9303 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9304  *  without using the "flat" keyword. (case c) )
9305  *
9306  *  @param input_variable_type Variable type to use for input variable declaration.
9307  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9308  *                             of the arrayed variable.
9309  *
9310  *  @return Requested string.
9311  **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput( Utils::_variable_type input_variable_type, unsigned int array_size)9312 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9313 	Utils::_variable_type input_variable_type, unsigned int array_size)
9314 {
9315 	std::stringstream result_sstream;
9316 	std::stringstream array_index_stringstream;
9317 	std::stringstream array_size_stringstream;
9318 
9319 	if (array_size > 1)
9320 	{
9321 		array_index_stringstream << "[0]";
9322 		array_size_stringstream << "[" << array_size << "]";
9323 	}
9324 
9325 	if (Utils::isMatrixVariableType(input_variable_type))
9326 	{
9327 		array_index_stringstream << "[0].x";
9328 	}
9329 	else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9330 	{
9331 		array_index_stringstream << "[0]";
9332 	}
9333 
9334 	result_sstream << "#version 400\n"
9335 					  "\n"
9336 					  "in "
9337 				   << Utils::getVariableTypeString(input_variable_type) << " test_input"
9338 				   << array_size_stringstream.str() << ";\n"
9339 													   "\n"
9340 													   "out float test_output;\n"
9341 													   "\n"
9342 													   "void main()\n"
9343 													   "{\n"
9344 													   "    if (test_input"
9345 				   << array_index_stringstream.str() << " > 2.0)\n"
9346 														"    {\n"
9347 														"        test_output = 1.0;\n"
9348 														"    }\n"
9349 														"    else\n"
9350 														"    {\n"
9351 														"        test_output = 3.0;\n"
9352 														"    }\n"
9353 														"}\n";
9354 
9355 	return result_sstream.str();
9356 }
9357 
9358 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9359  *
9360  *  @param input_variable_type Variable type to use for input variable declaration.
9361  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9362  *                             of the arrayed variable.
9363  *
9364  *  @return Requested string.
9365  **/
getCodeOfFragmentShaderWithDoublePrecisionOutput( Utils::_variable_type output_variable_type, unsigned int array_size)9366 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9367 	Utils::_variable_type output_variable_type, unsigned int array_size)
9368 {
9369 	std::stringstream array_index_sstream;
9370 	std::stringstream array_size_sstream;
9371 	std::stringstream result_sstream;
9372 	std::string		  output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9373 
9374 	if (array_size > 1)
9375 	{
9376 		array_index_sstream << "[0]";
9377 		array_size_sstream << "[" << array_size << "]";
9378 	}
9379 
9380 	result_sstream << "#version 400\n"
9381 					  "\n"
9382 					  "out "
9383 				   << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9384 																								   "\n"
9385 																								   "void main()\n"
9386 																								   "{\n"
9387 																								   "    test_output"
9388 				   << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9389 																						   "}\n";
9390 
9391 	return result_sstream.str();
9392 }
9393 
9394 /** Retrieves body of a fragment shader that uses user-specified set of variables
9395  *  to declare contents of input & output block.
9396  *
9397  *  @param variables As per description.
9398  *
9399  *  @return Requested string.
9400  **/
getFragmentShaderBody(const _variables& variables)9401 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9402 {
9403 	std::stringstream result_sstream;
9404 
9405 	/* Form the pre-amble */
9406 	result_sstream << "#version 400\n"
9407 					  "\n"
9408 
9409 				   /* Add input block */
9410 				   << "in GS_DATA\n"
9411 					  "{\n"
9412 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9413 																		  "\n"
9414 
9415 				   /* Add output variable */
9416 				   << "out vec4 result;\n"
9417 					  "\n"
9418 
9419 					  /* Add main() definition */
9420 					  "void main()\n"
9421 					  "{\n"
9422 					  "const double epsilon = 1e-5;\n"
9423 					  "\n"
9424 					  "result = vec4(1, 0, 0, 0);\n"
9425 					  "\n";
9426 
9427 	/* Determine expected values first */
9428 	unsigned int base_counter = 1;
9429 	const size_t n_variables  = variables.size();
9430 
9431 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9432 	{
9433 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9434 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9435 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9436 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9437 
9438 		std::stringstream array_size_sstream;
9439 
9440 		if (variable_array_size > 1)
9441 		{
9442 			array_size_sstream << "[" << variable_array_size << "]";
9443 		}
9444 
9445 		/* Local variable declaration */
9446 		result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9447 					   << ";\n"
9448 						  "\n";
9449 
9450 		/* Set expected values */
9451 		for (unsigned int index = 0; index < variable_array_size; ++index)
9452 		{
9453 			std::stringstream array_index_sstream;
9454 
9455 			if (variable_array_size > 1)
9456 			{
9457 				array_index_sstream << "[" << index << "]";
9458 			}
9459 
9460 			result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9461 						   << variable_type_string << "(";
9462 
9463 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9464 			{
9465 				unsigned int expected_value =
9466 					(base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9467 
9468 				if (m_are_double_inputs_supported)
9469 				{
9470 					/* VS input attributes */
9471 					//expected_value += (base_counter + 6);
9472 					expected_value -= 1;
9473 				}
9474 
9475 				result_sstream << expected_value;
9476 
9477 				if (n_component != (n_variable_type_components - 1))
9478 				{
9479 					result_sstream << ", ";
9480 				}
9481 
9482 				++base_counter;
9483 			} /* for (all components) */
9484 
9485 			result_sstream << ");\n";
9486 		} /* for (all array indices) */
9487 
9488 		result_sstream << "\n";
9489 	} /* for (all variable types) */
9490 
9491 	/* Now that we know the expected values, do a huge conditional check to verify if all
9492 	 * input variables carry correct information.
9493 	 */
9494 	result_sstream << "if (";
9495 
9496 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9497 	{
9498 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9499 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9500 		bool				  is_variable_type_matrix	= Utils::isMatrixVariableType(variable_type);
9501 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9502 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9503 
9504 		for (unsigned int index = 0; index < variable_array_size; ++index)
9505 		{
9506 			std::stringstream array_index_sstream;
9507 
9508 			if (variable_array_size > 1)
9509 			{
9510 				array_index_sstream << "[" << index << "]";
9511 			}
9512 
9513 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9514 			{
9515 				std::stringstream component_index_sstream;
9516 
9517 				if (n_variable_type_components > 1)
9518 				{
9519 					component_index_sstream << "[" << n_component << "]";
9520 				}
9521 
9522 				result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9523 
9524 				if (is_variable_type_matrix)
9525 				{
9526 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9527 					const unsigned int column	= n_component % n_columns;
9528 					const unsigned int row		 = n_component / n_columns;
9529 
9530 					result_sstream << "[" << column << "]"
9531 													   "."
9532 								   << Utils::getComponentAtIndex(row);
9533 				}
9534 				else
9535 				{
9536 					result_sstream << component_index_sstream.str();
9537 				}
9538 
9539 				result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9540 
9541 				if (is_variable_type_matrix)
9542 				{
9543 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9544 					const unsigned int column	= n_component % n_columns;
9545 					const unsigned int row		 = n_component / n_columns;
9546 
9547 					result_sstream << "[" << column << "]"
9548 													   "."
9549 								   << Utils::getComponentAtIndex(row);
9550 				}
9551 				else
9552 				{
9553 					result_sstream << component_index_sstream.str();
9554 				}
9555 
9556 				result_sstream << ") <= epsilon &&";
9557 			} /* for (all components) */
9558 		}	 /* for (all array indices) */
9559 	}		  /* for (all variable types) */
9560 
9561 	result_sstream << "true)\n"
9562 					  "{\n"
9563 					  "    result = vec4(0, 1, 0, 0);\n"
9564 					  "}\n"
9565 					  "}\n";
9566 
9567 	/* All done */
9568 	return result_sstream.str();
9569 }
9570 
9571 /** Retrieves body of a geometry shader that uses user-specified set of variables
9572  *  to declare contents of input & output block.
9573  *
9574  *  @param variables As per description.
9575  *
9576  *  @return Requested string.
9577  **/
getGeometryShaderBody(const _variables& variables)9578 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9579 {
9580 	std::stringstream result_sstream;
9581 
9582 	/* Form the pre-amble */
9583 	result_sstream << "#version 400\n"
9584 					  "\n"
9585 					  "layout(triangles)                      in;\n"
9586 					  "layout(triangle_strip, max_vertices=4) out;\n"
9587 					  "\n"
9588 
9589 					  /* Add the input block */
9590 					  "in TE_DATA\n"
9591 					  "{\n"
9592 				   << getVariableDeclarations("te", variables) << "} in_data[];\n"
9593 																  "\n"
9594 
9595 																  /* Add the output block */
9596 																  "out GS_DATA\n"
9597 																  "{\n"
9598 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9599 																		  "\n"
9600 
9601 																		  /* Declare main() function */
9602 																		  "void main()\n"
9603 																		  "{\n";
9604 
9605 	/* Take input variables, add a predefined value and forward them to output variables */
9606 	const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9607 									1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
9608 	const unsigned int n_quad_vertices =
9609 		sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9610 	const size_t n_variables = variables.size();
9611 
9612 	for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9613 	{
9614 		unsigned int counter			 = 4;
9615 		const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9616 
9617 		for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9618 		{
9619 			unsigned int		  variable_array_size = variables[n_variable].array_size;
9620 			Utils::_variable_type variable_type		  = variables[n_variable].type;
9621 			unsigned int n_variable_type_components   = Utils::getNumberOfComponentsForVariableType(variable_type);
9622 			std::string  variable_type_string		  = Utils::getVariableTypeString(variable_type);
9623 
9624 			for (unsigned int index = 0; index < variable_array_size; ++index)
9625 			{
9626 				std::stringstream array_index_sstream;
9627 
9628 				if (variable_array_size > 1)
9629 				{
9630 					array_index_sstream << "[" << index << "]";
9631 				}
9632 
9633 				result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9634 							   << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9635 							   << variable_type_string << "(";
9636 
9637 				for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9638 				{
9639 					result_sstream << (counter++);
9640 
9641 					if (n_component != (n_variable_type_components - 1))
9642 					{
9643 						result_sstream << ", ";
9644 					}
9645 				} /* for (all components) */
9646 
9647 				result_sstream << ");\n";
9648 			} /* for (all array indices) */
9649 		}	 /* for (all variable types) */
9650 
9651 		result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9652 					   << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9653 																					  "EmitVertex();\n";
9654 	} /* for (all emitted quad vertices) */
9655 
9656 	result_sstream << "EndPrimitive();\n"
9657 					  "}\n";
9658 
9659 	/* All done */
9660 	return result_sstream.str();
9661 }
9662 
9663 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9664  *  to declare contents of input & output block.
9665  *
9666  *  @param variables As per description.
9667  *
9668  *  @return Requested string.
9669  **/
getTessellationControlShaderBody(const _variables& variables)9670 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9671 {
9672 	std::stringstream result_sstream;
9673 
9674 	/* Form the pre-amble */
9675 	result_sstream << "#version 400\n"
9676 					  "\n"
9677 					  "layout (vertices=4) out;\n"
9678 
9679 					  /* Declare input block */
9680 					  "in VS_DATA\n"
9681 					  "{\n"
9682 				   << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9683 
9684 																  /* Declare output block */
9685 																  "out TC_DATA\n"
9686 																  "{\n"
9687 				   << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9688 																  "\n"
9689 
9690 																  /* Define main() */
9691 																  "void main()\n"
9692 																  "{\n"
9693 																  "    gl_TessLevelInner[0] = 1;\n"
9694 																  "    gl_TessLevelInner[1] = 1;\n"
9695 																  "    gl_TessLevelOuter[0] = 1;\n"
9696 																  "    gl_TessLevelOuter[1] = 1;\n"
9697 																  "    gl_TessLevelOuter[2] = 1;\n"
9698 																  "    gl_TessLevelOuter[3] = 1;\n"
9699 																  "\n";
9700 
9701 	/* Take input variables, add a predefined value and forward them to output variables */
9702 	const size_t n_variables = variables.size();
9703 	unsigned int counter	 = 2;
9704 
9705 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9706 	{
9707 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9708 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9709 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9710 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9711 
9712 		for (unsigned int index = 0; index < variable_array_size; ++index)
9713 		{
9714 			std::stringstream array_index_sstream;
9715 
9716 			if (variable_array_size > 1)
9717 			{
9718 				array_index_sstream << "[" << index << "]";
9719 			}
9720 
9721 			result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9722 						   << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9723 						   << variable_type_string << "(";
9724 
9725 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9726 			{
9727 				result_sstream << (counter++);
9728 
9729 				if (n_component != (n_variable_type_components - 1))
9730 				{
9731 					result_sstream << ", ";
9732 				}
9733 			}
9734 
9735 			result_sstream << ");\n";
9736 		} /* for (all array indices) */
9737 	}	 /* for (all variable types) */
9738 
9739 	result_sstream << "}\n";
9740 
9741 	/* We're done */
9742 	return result_sstream.str();
9743 }
9744 
9745 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9746  *  to declare contents of input & output block.
9747  *
9748  *  @param variables As per description.
9749  *
9750  *  @return Requested string.
9751  **/
getTessellationEvaluationShaderBody(const _variables& variables)9752 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9753 {
9754 	std::stringstream result_sstream;
9755 
9756 	/* Form the pre-amble */
9757 	result_sstream << "#version 400\n"
9758 					  "\n"
9759 					  "layout(quads) in;\n"
9760 					  "\n"
9761 
9762 					  /* Define input block */
9763 					  "in TC_DATA\n"
9764 					  "{\n"
9765 				   << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9766 																  "\n"
9767 
9768 																  /* Define output block */
9769 																  "out TE_DATA\n"
9770 																  "{\n"
9771 				   << getVariableDeclarations("te", variables) << "};\n"
9772 																  "\n"
9773 
9774 																  /* Define main() */
9775 																  "void main()\n"
9776 																  "{\n";
9777 
9778 	/* Take input variables, add a predefined value and forward them to output variables */
9779 	const size_t n_variables = variables.size();
9780 	unsigned int counter	 = 3;
9781 
9782 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9783 	{
9784 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9785 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9786 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9787 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9788 
9789 		for (unsigned int index = 0; index < variable_array_size; ++index)
9790 		{
9791 			std::stringstream array_index_sstream;
9792 
9793 			if (variable_array_size > 1)
9794 			{
9795 				array_index_sstream << "[" << index << "]";
9796 			}
9797 
9798 			result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9799 						   << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9800 
9801 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9802 			{
9803 				result_sstream << (counter++);
9804 
9805 				if (n_component != (n_variable_type_components - 1))
9806 				{
9807 					result_sstream << ", ";
9808 				}
9809 			} /* for (all components) */
9810 
9811 			result_sstream << ");\n";
9812 		} /* for (all array indices) */
9813 	}	 /* for (all variable types) */
9814 
9815 	result_sstream << "}\n";
9816 
9817 	/* All done */
9818 	return result_sstream.str();
9819 }
9820 
9821 /** Returns a string containing declarations of user-specified set of variables.
9822  *  Each declaration can optionally use a layot qualifier requested by the caller.
9823  *
9824  *  @param prefix             Prefix to use for variable names.
9825  *  @param variables          List of variables to declare in the result string.
9826  *  @param explicit_locations true if each declaration should explicitly define location
9827  *                            of the variable ( eg. (layout location=X) )
9828  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
9829  *                            be NULL.
9830  *
9831  *  @return Requested string.
9832  **/
getVariableDeclarations(const char* prefix, const _variables& variables, const char* layout_qualifier)9833 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9834 														const char* layout_qualifier)
9835 {
9836 	std::stringstream result_sstream;
9837 
9838 	/* Define output variables */
9839 	const size_t n_variables = variables.size();
9840 
9841 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9842 	{
9843 		unsigned int		  variable_array_size  = variables[n_variable].array_size;
9844 		Utils::_variable_type variable_type		   = variables[n_variable].type;
9845 		std::string			  variable_type_string = Utils::getVariableTypeString(variable_type);
9846 
9847 		result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9848 
9849 		if (variable_array_size > 1)
9850 		{
9851 			result_sstream << "[" << variable_array_size << "]";
9852 		}
9853 
9854 		result_sstream << ";\n";
9855 	} /* for (all user-specified variable types) */
9856 
9857 	return result_sstream.str();
9858 }
9859 
9860 /** Retrieves body of a vertex shader that uses user-specified set of variables
9861  *  to declare contents of input & output block.
9862  *
9863  *  @param variables As per description.
9864  *
9865  *  @return Requested string.
9866  **/
getVertexShaderBody(const _variables& variables)9867 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9868 {
9869 	std::stringstream result_sstream;
9870 
9871 	/* Form pre-amble */
9872 	result_sstream << "#version 400\n"
9873 					  "\n";
9874 
9875 	/* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9876 	if (m_are_double_inputs_supported)
9877 	{
9878 		result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9879 					   << getVariableDeclarations("in_vs", variables, "in");
9880 	}
9881 
9882 	/* Define output variables */
9883 	result_sstream << "out VS_DATA\n"
9884 					  "{\n"
9885 				   << getVariableDeclarations("vs", variables);
9886 
9887 	/* Define main() */
9888 	result_sstream << "};\n"
9889 					  "\n"
9890 					  "void main()\n"
9891 					  "{\n";
9892 
9893 	/* Set output variable values */
9894 	unsigned int counter	 = 1;
9895 	const size_t n_variables = variables.size();
9896 
9897 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9898 	{
9899 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9900 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9901 		const unsigned int	n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9902 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9903 
9904 		for (unsigned int index = 0; index < variable_array_size; ++index)
9905 		{
9906 			if (variable_array_size == 1)
9907 			{
9908 				result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9909 			}
9910 			else
9911 			{
9912 				result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9913 							   << " = " << variable_type_string << "(";
9914 			}
9915 
9916 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9917 			{
9918 				result_sstream << (double)(counter++);
9919 
9920 				/* Use input attributes, if available */
9921 				if (m_are_double_inputs_supported)
9922 				{
9923 					result_sstream << " + in_vs_variable" << n_variable;
9924 
9925 					if (variable_array_size > 1)
9926 					{
9927 						result_sstream << "[" << index << "]";
9928 					}
9929 
9930 					if (Utils::isMatrixVariableType(variables[n_variable].type))
9931 					{
9932 						const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9933 						const unsigned int column	= n_component % n_columns;
9934 						const unsigned int row		 = n_component / n_columns;
9935 
9936 						result_sstream << "[" << (column) << "]"
9937 															 "."
9938 									   << Utils::getComponentAtIndex(row);
9939 					}
9940 					else if (n_variable_type_components > 1)
9941 					{
9942 						result_sstream << "[" << n_component << "]";
9943 					}
9944 				}
9945 
9946 				if (n_component != (n_variable_type_components - 1))
9947 				{
9948 					result_sstream << ", ";
9949 				}
9950 			} /* for (all components) */
9951 
9952 			result_sstream << ");\n";
9953 		}
9954 	} /* for (all variable types) */
9955 
9956 	/* We will be using geometry shader to lay out the actual vertices so
9957 	 * the only thing we need to make sure is that the vertex never gets
9958 	 * culled.
9959 	 */
9960 	result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9961 					  "}\n";
9962 
9963 	/* That's it */
9964 	return result_sstream.str();
9965 }
9966 
9967 /** Initializes shader objects required to run the test. */
initTest()9968 void GPUShaderFP64Test7::initTest()
9969 {
9970 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9971 
9972 	/* Are double-precision input variables supported? */
9973 	m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9974 
9975 	/* Create a vertex array object */
9976 	gl.genVertexArrays(1, &m_vao_id);
9977 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9978 
9979 	gl.bindVertexArray(m_vao_id);
9980 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9981 
9982 	/* Create a texture object we will use as FBO's color attachment */
9983 	gl.genTextures(1, &m_to_id);
9984 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9985 
9986 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9987 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9988 
9989 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9990 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9991 
9992 	/* Allocate temporary buffer to hold the texture data we will be reading
9993 	 * from color attachment. */
9994 	m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9995 
9996 	/* Create and set up a framebuffer object */
9997 	gl.genFramebuffers(1, &m_fbo_id);
9998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9999 
10000 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
10001 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
10002 
10003 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10004 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10005 
10006 	/* Create all shader objects */
10007 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10008 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10009 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10010 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10011 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10012 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10013 
10014 	/* Create test program object */
10015 	m_po_id = gl.createProgram();
10016 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10017 
10018 	/* Attach the shaders to the program object */
10019 	gl.attachShader(m_po_id, m_fs_id);
10020 	gl.attachShader(m_po_id, m_gs_id);
10021 	gl.attachShader(m_po_id, m_tc_id);
10022 	gl.attachShader(m_po_id, m_te_id);
10023 	gl.attachShader(m_po_id, m_vs_id);
10024 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10025 
10026 	/* The test passes double-precision values through the whole rendering pipeline.
10027 	 * This translates to a notable amount of components that we would need to transfer
10028 	 * all values in one fell swoop. The number is large enough to exceed minimum
10029 	 * capabilities as described for OpenGL 4.0 implementations.
10030 	 * For that reason, the test executes in turns. Each turn is allocated as many
10031 	 * double-precision scalar/matrix values as supported by the tested GL implementation.
10032 	 */
10033 	glw::GLint gl_max_fragment_input_components_value				  = 0;
10034 	glw::GLint gl_max_geometry_input_components_value				  = 0;
10035 	glw::GLint gl_max_geometry_output_components_value				  = 0;
10036 	glw::GLint gl_max_tess_control_input_components_value			  = 0;
10037 	glw::GLint gl_max_tess_control_output_components_value			  = 0;
10038 	glw::GLint gl_max_tess_evaluation_input_components_value		  = 0;
10039 	glw::GLint gl_max_tess_evaluation_output_components_value		  = 0;
10040 	glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10041 	glw::GLint gl_max_vertex_output_components_value				  = 0;
10042 
10043 	gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10044 	gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10045 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10046 	gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10047 	gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10048 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10049 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10050 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10051 				   &gl_max_transform_feedback_interleaved_components_value);
10052 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10053 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10054 
10055 	m_n_max_components_per_stage =
10056 		de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10057 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10058 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10059 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10060 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10061 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10062 	m_n_max_components_per_stage =
10063 		de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10064 	m_n_max_components_per_stage =
10065 		de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10066 
10067 	/* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10068 	 * the input patch */
10069 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
10070 
10071 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10072 
10073 	/* Initialize a BO we will use to hold XFB data */
10074 	gl.genBuffers(1, &m_xfb_bo_id);
10075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10076 
10077 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10079 
10080 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10081 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10082 }
10083 
10084 /** Executes test iteration.
10085  *
10086  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10087  */
iterate()10088 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10089 {
10090 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10091 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10092 	{
10093 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10094 	}
10095 
10096 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10097 	{
10098 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10099 	}
10100 
10101 	/* Initialize GL objects required to run the test */
10102 	initTest();
10103 
10104 	/* Check the negative cases first */
10105 	const Utils::_variable_type double_variable_types[] = {
10106 		Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10107 		Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10108 		Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10109 		Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10110 		Utils::VARIABLE_TYPE_DMAT4X3,
10111 	};
10112 	const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10113 
10114 	for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10115 		 ++n_double_variable_type)
10116 	{
10117 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
10118 		{
10119 			Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10120 
10121 			if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10122 			{
10123 				m_testCtx.getLog() << tcu::TestLog::Message
10124 								   << "A fragment shader with double-precision output variable compiled successfully."
10125 								   << tcu::TestLog::EndMessage;
10126 
10127 				m_has_test_passed = false;
10128 			}
10129 
10130 			if (compileShader(m_fs_id,
10131 							  getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10132 			{
10133 				m_testCtx.getLog()
10134 					<< tcu::TestLog::Message
10135 					<< "A fragment shader with double-precision input variables lacking flat layout qualifier"
10136 					   " compiled successfully."
10137 					<< tcu::TestLog::EndMessage;
10138 
10139 				m_has_test_passed = false;
10140 			}
10141 		}
10142 	} /* for (all variable types) */
10143 
10144 	/* Execute functional test. Split the run into as many iterations as necessary
10145 	 * so that we do not exceed GL implementation's capabilities. */
10146 	unsigned int n_tested_variables = 0;
10147 	_variables   variables_to_test;
10148 
10149 	while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10150 	{
10151 		glw::GLint total_n_used_components = 0;
10152 
10153 		/* Use as many variables as possible for the iterations. Do not exceed maximum amount
10154 		 * of varying components that can be used for all shadr stages.
10155 		 */
10156 		while (total_n_used_components < m_n_max_components_per_stage &&
10157 			   n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10158 		{
10159 			_variable	new_variable;
10160 			unsigned int n_type_components = 0;
10161 			glw::GLint   n_used_components = 0;
10162 
10163 			new_variable.array_size =
10164 				((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10165 			new_variable.type = double_variable_types[n_tested_variables / 2];
10166 
10167 			/* Double-precision varyings can use twice as many components as single-precision FPs */
10168 			n_type_components = 4 /* components per location */ *
10169 								Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10170 			n_used_components = n_type_components * new_variable.array_size * 2;
10171 
10172 			/* Do we have enough space? */
10173 			if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10174 			{
10175 				if (n_used_components > m_n_max_components_per_stage)
10176 				{ //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10177 					n_tested_variables++;
10178 				}
10179 				break;
10180 			}
10181 
10182 			/* We can safely test the type in current iteration */
10183 			total_n_used_components += n_used_components;
10184 			n_tested_variables++;
10185 
10186 			variables_to_test.push_back(new_variable);
10187 		}
10188 
10189 		if (variables_to_test.size() > 0)
10190 		{
10191 			m_has_test_passed &= executeFunctionalTest(variables_to_test);
10192 
10193 			variables_to_test.clear();
10194 		}
10195 	}
10196 
10197 	/* We're done */
10198 	if (m_has_test_passed)
10199 	{
10200 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10201 	}
10202 	else
10203 	{
10204 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10205 	}
10206 
10207 	return STOP;
10208 }
10209 
10210 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables& variables)10211 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10212 {
10213 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10214 	std::stringstream	 log_sstream;
10215 
10216 	log_sstream << "Test variable values as retrieved from geometry shader:\n";
10217 
10218 	/* Map the XFB BO contents into process space */
10219 	const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10220 
10221 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10222 
10223 	/* Read the variable contents. We only care about the set of varyings emitted
10224 	 * for first vertex in the geometry shader */
10225 	unsigned int		 n_varying	 = 0;
10226 	const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10227 
10228 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10229 		 ++variables_iterator, ++n_varying)
10230 	{
10231 		const _variable&			 variable			= *variables_iterator;
10232 		const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10233 		const unsigned int			 n_components		= Utils::getNumberOfComponentsForVariableType(variable.type);
10234 
10235 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10236 		{
10237 			log_sstream << "gs_variable" << n_varying;
10238 
10239 			if (variable.array_size > 1)
10240 			{
10241 				log_sstream << "[" << array_index << "]";
10242 			}
10243 
10244 			log_sstream << ": (";
10245 
10246 			for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10247 			{
10248 				log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10249 
10250 				if (n_component != (n_components - 1))
10251 				{
10252 					log_sstream << ", ";
10253 				}
10254 
10255 				traveller_ptr += sizeof(double);
10256 			}
10257 
10258 			log_sstream << ")\n";
10259 		} /* for (all array indices) */
10260 	}	 /* for (all variables) */
10261 
10262 	/* Unmap the BO */
10263 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10264 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10265 
10266 	/* Pass the logged stream into the framework */
10267 	m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10268 }
10269 
10270 /** De-allocates an arary holding strings representing names of varyings that
10271  *  should be used for transform feed-back.
10272  **/
releaseXFBVaryingNames()10273 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10274 {
10275 	for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10276 	{
10277 		delete[] m_xfb_varyings[n_varying];
10278 	}
10279 
10280 	delete[] m_xfb_varyings;
10281 	m_xfb_varyings = DE_NULL;
10282 
10283 	m_n_xfb_varyings = 0;
10284 }
10285 
10286 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10287  *  Takes a list of test variables used for current iteration and assigns increasing values
10288  *  to subsequent input attributes of the test program.
10289  *
10290  *  @param variables Test variables of the current iteration.
10291  */
setInputAttributeValues(const _variables& variables)10292 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10293 {
10294 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
10295 
10296 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10297 		 variable_iterator++)
10298 	{
10299 		const _variable&   variable			  = *variable_iterator;
10300 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
10301 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10302 		unsigned int	   n_components		  = 0;
10303 		unsigned int	   n_columns		  = 1;
10304 
10305 		if (is_matrix_type)
10306 		{
10307 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
10308 			n_components = n_total_components / n_columns;
10309 
10310 			DE_ASSERT(n_total_components % n_columns == 0);
10311 		}
10312 		else
10313 		{
10314 			n_components = n_total_components;
10315 		}
10316 
10317 		DE_ASSERT(n_components >= 1 && n_components <= 4);
10318 
10319 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10320 		{
10321 			const double data[] = { -1, -1, -1, -1 };
10322 
10323 			switch (n_components)
10324 			{
10325 			case 1:
10326 			{
10327 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
10328 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10329 
10330 				break;
10331 			}
10332 
10333 			case 2:
10334 			{
10335 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
10336 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10337 
10338 				break;
10339 			}
10340 
10341 			case 3:
10342 			{
10343 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
10344 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10345 
10346 				break;
10347 			}
10348 
10349 			case 4:
10350 			{
10351 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
10352 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10353 
10354 				break;
10355 			}
10356 
10357 			default:
10358 			{
10359 				TCU_FAIL("Unrecognized number of components");
10360 			}
10361 			} /* switch (n_components) */
10362 
10363 			/* Make sure VAAs are disabled */
10364 			gl.disableVertexAttribArray(variable.attribute_location + index);
10365 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
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 	// GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12356 #if (DE_COMPILER == DE_COMPILER_GCC)
12357 #	pragma GCC diagnostic push
12358 #	pragma GCC diagnostic ignored "-Warray-bounds"
12359 #endif
12360 
12361 	const glw::GLint eCol = static_cast<glw::GLint>(column);
12362 	const glw::GLint eRow = static_cast<glw::GLint>(row);
12363 
12364 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12365 
12366 	for (glw::GLint c = 0; c < Size; ++c)
12367 	{
12368 		/* Skip eliminated column */
12369 		if (eCol == c)
12370 		{
12371 			continue;
12372 		}
12373 
12374 		for (glw::GLint r = 0; r < Size; ++r)
12375 		{
12376 			/* Skip eliminated row */
12377 			if (eRow == r)
12378 			{
12379 				continue;
12380 			}
12381 
12382 			const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12383 			const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12384 
12385 			result(r + r_offset, c + c_offset) = matrix(r, c);
12386 		}
12387 	}
12388 
12389 	return result;
12390 
12391 #if (DE_COMPILER == DE_COMPILER_GCC)
12392 #	pragma GCC diagnostic pop
12393 #endif
12394 }
12395 
12396 template <int Size>
equal(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12397 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12398 											const tcu::Vector<glw::GLdouble, Size>& right)
12399 {
12400 	return convertBvecToUvec(tcu::equal(left, right));
12401 }
12402 
fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)12403 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12404 {
12405 	return a * b + c;
12406 }
12407 
fract(glw::GLdouble val)12408 static glw::GLdouble fract(glw::GLdouble val)
12409 {
12410 	return val - floor(val);
12411 }
12412 
12413 template <typename T>
frexp(T val, glw::GLint& exp)12414 static T frexp(T val, glw::GLint& exp)
12415 {
12416 	return ::frexp(val, &exp);
12417 }
12418 
12419 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12420 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12421 												  const tcu::Vector<glw::GLdouble, Size>& right)
12422 {
12423 	return convertBvecToUvec(tcu::greaterThan(left, right));
12424 }
12425 
12426 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12427 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12428 													   const tcu::Vector<glw::GLdouble, Size>& right)
12429 {
12430 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12431 }
12432 
12433 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)12434 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12435 {
12436 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
12437 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12438 	const glw::GLdouble det		= determinant(matrix);
12439 	const glw::GLdouble inv_det = 1.0 / det;
12440 
12441 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12442 
12443 	return result;
12444 }
12445 
inverseSqrt(glw::GLdouble val)12446 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12447 {
12448 	const glw::GLdouble root = sqrt(val);
12449 
12450 	return (1.0 / root);
12451 }
12452 
isinf_impl(glw::GLdouble val)12453 static glw::GLuint isinf_impl(glw::GLdouble val)
12454 {
12455 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12456 
12457 	return ((infinity == val) || (-infinity == val));
12458 }
12459 
isnan_impl(glw::GLdouble val)12460 static glw::GLuint isnan_impl(glw::GLdouble val)
12461 {
12462 	return val != val;
12463 }
12464 
12465 template <typename T>
ldexp(T val, glw::GLint exp)12466 static T ldexp(T val, glw::GLint exp)
12467 {
12468 	return ::ldexp(val, exp);
12469 }
12470 
12471 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12472 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12473 											   const tcu::Vector<glw::GLdouble, Size>& right)
12474 {
12475 	return convertBvecToUvec(tcu::lessThan(left, right));
12476 }
12477 
12478 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12479 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12480 													const tcu::Vector<glw::GLdouble, Size>& right)
12481 {
12482 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
12483 }
12484 
12485 template <typename T>
max(T left, T right)12486 static T max(T left, T right)
12487 {
12488 	return (left >= right) ? left : right;
12489 }
12490 
12491 template <typename T>
min(T left, T right)12492 static T min(T left, T right)
12493 {
12494 	return (left <= right) ? left : right;
12495 }
12496 
12497 template <int		 Size>
minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column, glw::GLuint row)12498 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12499 								glw::GLuint row)
12500 {
12501 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12502 
12503 	return determinant(eliminated);
12504 }
12505 
12506 template <>
minor_impl(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)12507 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12508 {
12509 	const glw::GLuint r = (0 == row) ? 1 : 0;
12510 	const glw::GLuint c = (0 == column) ? 1 : 0;
12511 
12512 	return matrix(r, c);
12513 }
12514 
12515 template <typename T>
mix(T left, T right, T weight)12516 static T mix(T left, T right, T weight)
12517 {
12518 	return left * (1 - weight) + right * (weight);
12519 }
12520 
12521 template <typename T>
mod(T left, T right)12522 static T mod(T left, T right)
12523 {
12524 	const T div_res = left / right;
12525 	const T floored = floor(div_res);
12526 
12527 	return left - right * floored;
12528 }
12529 
12530 template <typename T>
modf(T val, T& integer)12531 static T modf(T val, T& integer)
12532 {
12533 	return ::modf(val, &integer);
12534 }
12535 
12536 template <typename T>
multiply(T left, T right)12537 static T multiply(T left, T right)
12538 {
12539 	T result = left * right;
12540 
12541 	return result;
12542 }
12543 
12544 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12545 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12546 											   const tcu::Vector<glw::GLdouble, Size>& right)
12547 {
12548 	return convertBvecToUvec(tcu::notEqual(left, right));
12549 }
12550 
12551 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left, const tcu::Vector<glw::GLdouble, Cols>& right)12552 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12553 														   const tcu::Vector<glw::GLdouble, Cols>& right)
12554 {
12555 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
12556 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
12557 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12558 
12559 	for (glw::GLuint i = 0; i < Rows; ++i)
12560 	{
12561 		left_mat(i, 0) = left[i];
12562 	}
12563 
12564 	for (glw::GLuint i = 0; i < Cols; ++i)
12565 	{
12566 		right_mat(0, i) = right[i];
12567 	}
12568 
12569 	result = left_mat * right_mat;
12570 
12571 	return result;
12572 }
12573 
packDouble2x32(const tcu::UVec2& in)12574 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12575 {
12576 	const glw::GLuint buffer[2] = { in[0], in[1] };
12577 	glw::GLdouble	 result;
12578 	memcpy(&result, buffer, sizeof(result));
12579 	return result;
12580 }
12581 
12582 template <typename T>
round(T t)12583 static T round(T t)
12584 {
12585 	T frac = fract(t);
12586 	T res  = t - frac;
12587 
12588 	if (((T)0.5) < frac)
12589 	{
12590 		res += ((T)1.0);
12591 	}
12592 
12593 	return res;
12594 }
12595 
12596 template <typename T>
roundEven(T t)12597 static T roundEven(T t)
12598 {
12599 	T frac = fract(t);
12600 	T res  = t - frac;
12601 
12602 	if (((T)0.5) < frac)
12603 	{
12604 		res += ((T)1.0);
12605 	}
12606 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12607 	{
12608 		res += ((T)1.0);
12609 	}
12610 
12611 	return res;
12612 }
12613 
12614 template <typename T>
sign(T t)12615 static T sign(T t)
12616 {
12617 	if (0 > t)
12618 	{
12619 		return -1;
12620 	}
12621 	else if (0 == t)
12622 	{
12623 		return 0;
12624 	}
12625 	else
12626 	{
12627 		return 1;
12628 	}
12629 }
12630 
12631 template <typename T>
smoothStep(T e0, T e1, T val)12632 static T smoothStep(T e0, T e1, T val)
12633 {
12634 	if (e0 >= val)
12635 	{
12636 		return 0;
12637 	}
12638 
12639 	if (e1 <= val)
12640 	{
12641 		return 1;
12642 	}
12643 
12644 	T temp = (val - e0) / (e1 - e0);
12645 
12646 	T result = temp * temp * (3 - 2 * temp);
12647 
12648 	return result;
12649 }
12650 
12651 template <typename T>
step(T edge, T val)12652 static T step(T edge, T val)
12653 {
12654 	if (edge > val)
12655 	{
12656 		return 0;
12657 	}
12658 	else
12659 	{
12660 		return 1;
12661 	}
12662 }
12663 
12664 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T, Rows, Cols>& matrix)12665 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12666 {
12667 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12668 
12669 	return result;
12670 }
12671 
12672 template <typename T>
trunc(T t)12673 static T trunc(T t)
12674 {
12675 	const T abs_value	= de::abs(t);
12676 	const T result_value = floor(abs_value);
12677 
12678 	const T result = sign(t) * result_value;
12679 
12680 	return result;
12681 }
12682 
unpackDouble2x32(const glw::GLdouble& val)12683 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12684 {
12685 	glw::GLuint* ptr = (glw::GLuint*)&val;
12686 	tcu::UVec2   result(ptr[0], ptr[1]);
12687 
12688 	return result;
12689 }
12690 } /* Math */
12691 
12692 /** Enumeration of tested functions
12693  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12694  * For example "max" can be called for (dvec3, double).
12695  **/
12696 enum FunctionEnum
12697 {
12698 	FUNCTION_ABS = 0,
12699 	FUNCTION_CEIL,
12700 	FUNCTION_CLAMP,
12701 	FUNCTION_CLAMP_AGAINST_SCALAR,
12702 	FUNCTION_CROSS,
12703 	FUNCTION_DETERMINANT,
12704 	FUNCTION_DISTANCE,
12705 	FUNCTION_DOT,
12706 	FUNCTION_EQUAL,
12707 	FUNCTION_FACEFORWARD,
12708 	FUNCTION_FLOOR,
12709 	FUNCTION_FMA,
12710 	FUNCTION_FRACT,
12711 	FUNCTION_FREXP,
12712 	FUNCTION_GREATERTHAN,
12713 	FUNCTION_GREATERTHANEQUAL,
12714 	FUNCTION_INVERSE,
12715 	FUNCTION_INVERSESQRT,
12716 	FUNCTION_LDEXP,
12717 	FUNCTION_LESSTHAN,
12718 	FUNCTION_LESSTHANEQUAL,
12719 	FUNCTION_LENGTH,
12720 	FUNCTION_MATRIXCOMPMULT,
12721 	FUNCTION_MAX,
12722 	FUNCTION_MAX_AGAINST_SCALAR,
12723 	FUNCTION_MIN,
12724 	FUNCTION_MIN_AGAINST_SCALAR,
12725 	FUNCTION_MIX,
12726 	FUNCTION_MOD,
12727 	FUNCTION_MOD_AGAINST_SCALAR,
12728 	FUNCTION_MODF,
12729 	FUNCTION_NORMALIZE,
12730 	FUNCTION_NOTEQUAL,
12731 	FUNCTION_OUTERPRODUCT,
12732 	FUNCTION_PACKDOUBLE2X32,
12733 	FUNCTION_REFLECT,
12734 	FUNCTION_REFRACT,
12735 	FUNCTION_ROUND,
12736 	FUNCTION_ROUNDEVEN,
12737 	FUNCTION_SIGN,
12738 	FUNCTION_SMOOTHSTEP,
12739 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12740 	FUNCTION_SQRT,
12741 	FUNCTION_STEP,
12742 	FUNCTION_STEP_AGAINST_SCALAR,
12743 	FUNCTION_TRANSPOSE,
12744 	FUNCTION_TRUNC,
12745 	FUNCTION_UNPACKDOUBLE2X32,
12746 	FUNCTION_ISNAN,
12747 	FUNCTION_ISINF,
12748 };
12749 
12750 struct TypeDefinition
12751 {
12752 	std::string name;
12753 	glw::GLuint n_columns;
12754 	glw::GLuint n_rows;
12755 };
12756 
12757 /** Implementation of BuiltinFunctionTest test, description follows:
12758  *
12759  *  Verify double-precision support in common functions works correctly.
12760  *  All double-precision types that apply for particular cases should
12761  *  be tested for the following functions:
12762  *
12763  *  - abs();
12764  *  - ceil();
12765  *  - clamp();
12766  *  - cross();
12767  *  - determinant();
12768  *  - distance();
12769  *  - dot();
12770  *  - equal();
12771  *  - faceforward();
12772  *  - floor();
12773  *  - fma();
12774  *  - fract();
12775  *  - frexp();
12776  *  - greaterThan();
12777  *  - greaterThanEqual();
12778  *  - inverse();
12779  *  - inversesqrt();
12780  *  - ldexp();
12781  *  - lessThan();
12782  *  - lessThanEqual();
12783  *  - length();
12784  *  - matrixCompMult();
12785  *  - max();
12786  *  - min();
12787  *  - mix();
12788  *  - mod();
12789  *  - modf();
12790  *  - normalize();
12791  *  - notEqual();
12792  *  - outerProduct();
12793  *  - packDouble2x32();
12794  *  - reflect();
12795  *  - refract();
12796  *  - round();
12797  *  - roundEven();
12798  *  - sign();
12799  *  - smoothstep();
12800  *  - sqrt();
12801  *  - step();
12802  *  - transpose();
12803  *  - trunc();
12804  *  - unpackDouble2x32();
12805  *  - isnan();
12806  *  - isinf();
12807  *
12808  *  The test should work by creating a program object (for each case
12809  *  considered), to which a vertex shader should be attached. The
12810  *  shader should define input variables that should be used as
12811  *  arguments for the function in question. The result of the
12812  *  operation should then be XFBed back to the test, where the
12813  *  value should be verified.
12814  *
12815  *  Reference function implementation from pre-DEQP CTS framework
12816  *  should be ported to C for verification purposes where available.
12817  *
12818  *  The test should use 1024 different scalar/vector/matrix argument
12819  *  combinations. It should pass if all functions are determined
12820  *  to work correctly for all argument combinations used.
12821  **/
12822 class BuiltinFunctionTest : public deqp::TestCase
12823 {
12824 public:
12825 	/* Public methods */
12826 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12827 						TypeDefinition typeDefinition);
12828 
12829 	virtual void						 deinit();
12830 	virtual tcu::TestNode::IterateResult iterate();
12831 
12832 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12833 	 *
12834 	 **/
12835 	class functionObject
12836 	{
12837 	public:
12838 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12839 					   Utils::_variable_type result_type);
12840 
~functionObject()12841 		virtual ~functionObject()
12842 		{
12843 		}
12844 
12845 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12846 
12847 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
12848 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12849 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12850 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12851 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12852 		glw::GLuint getArgumentStride() const;
12853 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
12854 		FunctionEnum	   getFunctionEnum() const;
12855 		const glw::GLchar* getName() const;
12856 		glw::GLuint getResultComponents(glw::GLuint result) const;
12857 		virtual glw::GLuint getResultCount() const;
12858 		glw::GLuint getResultOffset(glw::GLuint result) const;
12859 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12860 		glw::GLuint getResultStride(glw::GLuint result) const;
12861 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12862 		glw::GLuint getResultStride() const;
12863 
12864 	protected:
12865 		const FunctionEnum			m_function_enum;
12866 		const glw::GLchar*			m_function_name;
12867 		const glw::GLvoid*			m_p_function;
12868 		const Utils::_variable_type m_res_type;
12869 	};
12870 
12871 private:
12872 	/* Private types */
12873 	/** General type enumeration
12874 	 *
12875 	 **/
12876 	enum generalType
12877 	{
12878 		SCALAR = 0,
12879 		VECTOR,
12880 		MATRIX,
12881 	};
12882 
12883 	/** Details of variable type
12884 	 *
12885 	 **/
12886 	struct typeDetails
12887 	{
12888 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12889 
12890 		generalType m_general_type;
12891 		glw::GLuint m_n_columns;
12892 		glw::GLuint m_n_rows;
12893 		glw::GLenum m_type;
12894 		std::string m_type_name;
12895 	};
12896 
12897 	/* Typedefs for gl.uniform* function pointers */
12898 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12899 																	   const glw::GLdouble*);
12900 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12901 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12902 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12903 
12904 	/* Private methods */
12905 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12906 
12907 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12908 
12909 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
12910 														 const functionObject& function_object) const;
12911 
12912 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
12913 														 const functionObject& function_object) const;
12914 
12915 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
12916 														 const functionObject& function_object) const;
12917 
12918 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
12919 														 const functionObject& function_object) const;
12920 
12921 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
12922 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12923 
12924 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12925 
12926 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12927 
12928 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12929 
12930 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12931 						   glw::GLubyte* buffer);
12932 
12933 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12934 
12935 	void prepareTestData(const functionObject& function_object);
12936 	void prepareVertexShaderCode(const functionObject& function_object);
12937 
12938 	bool test(FunctionEnum function, const typeDetails& type);
12939 
12940 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12941 
12942 	void testInit();
12943 
12944 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12945 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12946 						  const glw::GLvoid* result_src);
12947 
12948 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12949 
12950 	/* Private constants */
12951 	static const glw::GLdouble m_epsilon;
12952 	static const glw::GLuint   m_n_veritces;
12953 
12954 	/* Private fields */
12955 	glw::GLuint m_transform_feedback_buffer_id;
12956 	glw::GLuint m_vertex_array_object_id;
12957 
12958 	std::vector<glw::GLubyte> m_expected_results_data;
12959 	FunctionEnum			  m_function;
12960 	TypeDefinition			  m_typeDefinition;
12961 	std::vector<glw::GLubyte> m_argument_data;
12962 	std::string				  m_vertex_shader_code;
12963 };
12964 
12965 /* Constants used by BuiltinFunctionTest */
12966 /** Khronos Bug #14010
12967  *  Using an epsilon value for comparing floating points is error prone.
12968  *  Rather than writing a new floating point comparison function, I am
12969  *  increasing the epsilon value to allow greater orders of magnitude
12970  *  of floating point values.
12971  **/
12972 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
12973 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12974 
12975 /** Implementations of function objects required by "BuiltinFunctionTest"
12976  *
12977  **/
12978 namespace FunctionObject
12979 {
12980 /** Maps variable type with enumeration Utils::_variable_type
12981  *
12982  * @tparam T type
12983  **/
12984 template <typename T>
12985 class typeInfo
12986 {
12987 public:
12988 	static const Utils::_variable_type variable_type =
12989 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12990 };
12991 
12992 /** Place data from <in> into <buffer>
12993  *
12994  * @param buffer Buffer
12995  * @param in     Input data
12996  **/
12997 template <typename T>
12998 class pack
12999 {
13000 public:
set(glw::GLvoid* buffer, const T& in)13001 	static void set(glw::GLvoid* buffer, const T& in)
13002 	{
13003 		*(T*)buffer = in;
13004 	}
13005 };
13006 
13007 /** Place tcu::Matrix data from <in> into <buffer>
13008  *
13009  * @param buffer Buffer
13010  * @param in     Input data
13011  **/
13012 template <int Cols, int Rows>
13013 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13014 {
13015 public:
set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)13016 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13017 	{
13018 		glw::GLdouble* data = (glw::GLdouble*)buffer;
13019 
13020 		for (glw::GLint column = 0; column < Cols; ++column)
13021 		{
13022 			for (glw::GLint row = 0; row < Rows; ++row)
13023 			{
13024 				glw::GLint index = column * Rows + row;
13025 
13026 				data[index] = in(row, column);
13027 			}
13028 		}
13029 	}
13030 };
13031 
13032 /** Get data of <out> from <buffer>
13033  *
13034  * @param buffer Buffer
13035  * @param out    Output data
13036  **/
13037 template <typename T>
13038 class unpack
13039 {
13040 public:
get(const glw::GLvoid* buffer, T& out)13041 	static void get(const glw::GLvoid* buffer, T& out)
13042 	{
13043 		out = *(T*)buffer;
13044 	}
13045 };
13046 
13047 /** Get tcu::Matrix data from <buffer>
13048  *
13049  * @param buffer Buffer
13050  * @param out    Output data
13051  **/
13052 template <int Cols, int Rows>
13053 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13054 {
13055 public:
get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)13056 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13057 	{
13058 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
13059 
13060 		for (glw::GLint column = 0; column < Cols; ++column)
13061 		{
13062 			for (glw::GLint row = 0; row < Rows; ++row)
13063 			{
13064 				glw::GLint index = column * Rows + row;
13065 
13066 				out(row, column) = data[index];
13067 			}
13068 		}
13069 	}
13070 };
13071 
13072 /** Base of unary function classes
13073  *
13074  **/
13075 class unaryBase : public BuiltinFunctionTest::functionObject
13076 {
13077 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)13078 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13079 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13080 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13081 	{
13082 	}
13083 
getArgumentCount() const13084 	virtual glw::GLuint getArgumentCount() const
13085 	{
13086 		return 1;
13087 	}
13088 
getArgumentType(glw::GLuint ) const13089 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13090 	{
13091 		return m_arg_type;
13092 	}
13093 
13094 protected:
13095 	const Utils::_variable_type m_arg_type;
13096 };
13097 
13098 /** Unary function class. It treats input argument as one variable.
13099  *
13100  * @tparam ResT Type of result
13101  * @tparam ArgT Type of argument
13102  **/
13103 template <typename ResT, typename ArgT>
13104 class unary : public unaryBase
13105 {
13106 public:
13107 	typedef ResT (*functionPointer)(const ArgT&);
13108 
unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13109 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13110 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13111 					typeInfo<ArgT>::variable_type)
13112 	{
13113 	}
13114 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13115 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13116 	{
13117 		ResT result;
13118 		ArgT arg;
13119 
13120 		unpack<ArgT>::get(argument_src, arg);
13121 
13122 		functionPointer p_function = (functionPointer)m_p_function;
13123 
13124 		result = p_function(arg);
13125 
13126 		pack<ResT>::set(result_dst, result);
13127 	}
13128 };
13129 
13130 /** Unary function class. It treats input argument as separate components.
13131  *
13132  * @tparam ResT Type of result
13133  **/
13134 template <typename ResT>
13135 class unaryByComponent : public unaryBase
13136 {
13137 public:
13138 	typedef ResT (*functionPointer)(glw::GLdouble);
13139 
unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer, const Utils::_variable_type res_type, const Utils::_variable_type arg_type)13140 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13141 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13142 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13143 	{
13144 	}
13145 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13146 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13147 	{
13148 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13149 		ResT*		   p_result		= (ResT*)result_dst;
13150 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
13151 
13152 		functionPointer p_function = (functionPointer)m_p_function;
13153 
13154 		for (glw::GLuint component = 0; component < n_components; ++component)
13155 		{
13156 			p_result[component] = p_function(p_arg[component]);
13157 		}
13158 	}
13159 };
13160 
13161 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13162  *
13163  * @tparam ResT Type of result
13164  * @tparam ArgT Type of argument
13165  * @tparam OutT Type of output parameter
13166  **/
13167 template <typename ResT, typename ArgT, typename OutT>
13168 class unaryWithOutputByComponent : public unaryBase
13169 {
13170 public:
13171 	typedef ResT (*functionPointer)(ArgT, OutT&);
13172 
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)13173 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13174 							   functionPointer function_pointer, const Utils::_variable_type res_type,
13175 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13176 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13177 		, m_out_type(out_type)
13178 	{
13179 	}
13180 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13181 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13182 	{
13183 		ResT* p_result = (ResT*)result_dst;
13184 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13185 		ArgT* p_arg	= (ArgT*)argument_src;
13186 
13187 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13188 		const glw::GLuint n_components_1 = getResultComponents(1);
13189 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13190 
13191 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13192 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13193 
13194 		functionPointer p_function = (functionPointer)m_p_function;
13195 
13196 		for (glw::GLuint component = 0; component < n_components; ++component)
13197 		{
13198 			const ArgT first_arg  = p_arg[component * component_step_0];
13199 			OutT&	  second_arg = p_out[component * component_step_1];
13200 
13201 			p_result[component] = p_function(first_arg, second_arg);
13202 		}
13203 	}
13204 
getResultCount() const13205 	glw::GLuint getResultCount() const
13206 	{
13207 		return 2;
13208 	}
13209 
getResultType(glw::GLuint result) const13210 	Utils::_variable_type getResultType(glw::GLuint result) const
13211 	{
13212 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13213 
13214 		switch (result)
13215 		{
13216 		case 0:
13217 			type = m_res_type;
13218 			break;
13219 		case 1:
13220 			type = m_out_type;
13221 			break;
13222 		default:
13223 			TCU_FAIL("Not implemented");
13224 			break;
13225 		}
13226 
13227 		return type;
13228 	}
13229 
13230 protected:
13231 	const Utils::_variable_type m_out_type;
13232 };
13233 
13234 /** Base of binary function classes.
13235  *
13236  **/
13237 class binaryBase : public BuiltinFunctionTest::functionObject
13238 {
13239 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)13240 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13241 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13242 			   const Utils::_variable_type arg_2_type)
13243 		: functionObject(function_enum, function_name, function_pointer, res_type)
13244 		, m_arg_1_type(arg_1_type)
13245 		, m_arg_2_type(arg_2_type)
13246 	{
13247 	}
13248 
getArgumentCount() const13249 	virtual glw::GLuint getArgumentCount() const
13250 	{
13251 		return 2;
13252 	}
13253 
getArgumentType(glw::GLuint argument) const13254 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13255 	{
13256 		switch (argument)
13257 		{
13258 		case 0:
13259 			return m_arg_1_type;
13260 		case 1:
13261 			return m_arg_2_type;
13262 		default:
13263 			return Utils::VARIABLE_TYPE_UNKNOWN;
13264 		}
13265 	}
13266 
13267 protected:
13268 	const Utils::_variable_type m_arg_1_type;
13269 	const Utils::_variable_type m_arg_2_type;
13270 };
13271 
13272 /** Binary function class. It treats input arguments as two variables.
13273  *
13274  * @param ResT  Type of result
13275  * @param Arg1T Type of first argument
13276  * @param Arg2T Type of second argument
13277  **/
13278 template <typename ResT, typename Arg1T, typename Arg2T>
13279 class binary : public binaryBase
13280 {
13281 public:
13282 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13283 
binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13284 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13285 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13286 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13287 	{
13288 	}
13289 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13290 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13291 	{
13292 		const glw::GLuint argument_1_stride = getArgumentStride(0);
13293 
13294 		functionPointer p_function = (functionPointer)m_p_function;
13295 
13296 		Arg1T arg_1;
13297 		Arg2T arg_2;
13298 		ResT  result;
13299 
13300 		unpack<Arg1T>::get(argument_src, arg_1);
13301 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13302 
13303 		result = p_function(arg_1, arg_2);
13304 
13305 		pack<ResT>::set(result_dst, result);
13306 	}
13307 };
13308 
13309 /** Binary function class. It treats input arguments as separate components.
13310  *
13311  * @param ResT  Type of result
13312  * @param Arg1T Type of first argument
13313  * @param Arg2T Type of second argument
13314  **/
13315 template <typename ResT, typename Arg1T, typename Arg2T>
13316 class binaryByComponent : public binaryBase
13317 {
13318 public:
13319 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
13320 
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)13321 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13322 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13323 					  const Utils::_variable_type arg_2_type)
13324 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13325 	{
13326 	}
13327 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13328 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13329 	{
13330 		ResT*  p_result = (ResT*)result_dst;
13331 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
13332 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13333 
13334 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13335 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13336 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13337 
13338 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13339 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13340 
13341 		functionPointer p_function = (functionPointer)m_p_function;
13342 
13343 		for (glw::GLuint component = 0; component < n_components; ++component)
13344 		{
13345 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
13346 			const Arg2T second_arg = p_arg_2[component * component_step_1];
13347 
13348 			p_result[component] = p_function(first_arg, second_arg);
13349 		}
13350 	}
13351 };
13352 
13353 /** Base of tenary function classes.
13354  *
13355  **/
13356 class tenaryBase : public BuiltinFunctionTest::functionObject
13357 {
13358 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)13359 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13360 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13361 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13362 		: functionObject(function_enum, function_name, function_pointer, res_type)
13363 		, m_arg_1_type(arg_1_type)
13364 		, m_arg_2_type(arg_2_type)
13365 		, m_arg_3_type(arg_3_type)
13366 	{
13367 	}
13368 
getArgumentCount() const13369 	virtual glw::GLuint getArgumentCount() const
13370 	{
13371 		return 3;
13372 	}
13373 
getArgumentType(glw::GLuint argument) const13374 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13375 	{
13376 		switch (argument)
13377 		{
13378 		case 0:
13379 			return m_arg_1_type;
13380 		case 1:
13381 			return m_arg_2_type;
13382 		case 2:
13383 			return m_arg_3_type;
13384 		default:
13385 			return Utils::VARIABLE_TYPE_UNKNOWN;
13386 		}
13387 	}
13388 
13389 protected:
13390 	const Utils::_variable_type m_arg_1_type;
13391 	const Utils::_variable_type m_arg_2_type;
13392 	const Utils::_variable_type m_arg_3_type;
13393 };
13394 
13395 /** Tenary function class. It treats input arguments as three variables.
13396  *
13397  * @param ResT  Type of result
13398  * @param Arg1T Type of first argument
13399  * @param Arg2T Type of second argument
13400  * @param Arg3T Type of third argument
13401  **/
13402 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13403 class tenary : public tenaryBase
13404 {
13405 public:
13406 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13407 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13408 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13409 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13410 
tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13411 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13412 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13413 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13414 	{
13415 	}
13416 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13417 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13418 	{
13419 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
13420 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
13421 
13422 		functionPointer p_function = (functionPointer)m_p_function;
13423 
13424 		arg1T arg_1;
13425 		arg2T arg_2;
13426 		arg3T arg_3;
13427 		ResT  result;
13428 
13429 		unpack<arg1T>::get(argument_src, arg_1);
13430 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13431 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13432 
13433 		result = p_function(arg_1, arg_2, arg_3);
13434 
13435 		pack<ResT>::set(result_dst, result);
13436 	}
13437 };
13438 
13439 /** Tenary function class. It treats input arguments as separate components.
13440  *
13441 
13442  **/
13443 class tenaryByComponent : public tenaryBase
13444 {
13445 public:
13446 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13447 
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)13448 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13449 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13450 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13451 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13452 					 arg_3_type)
13453 	{
13454 	}
13455 
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13456 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13457 	{
13458 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
13459 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
13460 
13461 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13462 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13463 		const glw::GLuint n_components_2 = getArgumentComponents(2);
13464 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13465 
13466 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13467 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13468 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13469 
13470 		functionPointer p_function = (functionPointer)m_p_function;
13471 
13472 		for (glw::GLuint component = 0; component < n_components; ++component)
13473 		{
13474 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13475 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13476 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13477 
13478 			p_result[component] = p_function(first_arg, second_arg, third_arg);
13479 		}
13480 	}
13481 };
13482 } /* FunctionObject */
13483 
13484 /** Constructor.
13485  *
13486  *  @param context Rendering context.
13487  **/
BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function, TypeDefinition typeDefinition)13488 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13489 										 TypeDefinition typeDefinition)
13490 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13491 	, m_transform_feedback_buffer_id(0)
13492 	, m_vertex_array_object_id(0)
13493 	, m_function(function)
13494 	, m_typeDefinition(typeDefinition)
13495 {
13496 	/* Nothing to be done here */
13497 }
13498 
13499 /** Deinitializes all GL objects that may have been created during test execution.
13500  *
13501  **/
deinit()13502 void BuiltinFunctionTest::deinit()
13503 {
13504 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13505 
13506 	/* Clean buffers */
13507 	if (0 != m_transform_feedback_buffer_id)
13508 	{
13509 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13510 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13511 		m_transform_feedback_buffer_id = 0;
13512 	}
13513 
13514 	/* Clean VAO */
13515 	if (0 != m_vertex_array_object_id)
13516 	{
13517 		gl.bindVertexArray(0);
13518 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13519 		m_vertex_array_object_id = 0;
13520 	}
13521 }
13522 
13523 /** Execute test
13524  *
13525  * @return tcu::TestNode::STOP
13526  **/
iterate()13527 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13528 {
13529 	/* Check if extension is supported */
13530 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13531 	{
13532 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13533 	}
13534 
13535 	testInit();
13536 
13537 	/* Verify result */
13538 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13539 	if (test(m_function, type))
13540 	{
13541 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13542 	}
13543 	else
13544 	{
13545 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13546 	}
13547 
13548 	/* Done */
13549 	return tcu::TestNode::STOP;
13550 }
13551 
13552 /** Constructor
13553  *
13554  * @param function_enum    Function enumeration
13555  * @param function_name    Function name
13556  * @param function_pointer Pointer to routine that wiil be executed
13557  * @param result_type      Type of result
13558  **/
functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, Utils::_variable_type result_type)13559 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13560 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13561 	: m_function_enum(function_enum)
13562 	, m_function_name(function_name)
13563 	, m_p_function(function_pointer)
13564 	, m_res_type(result_type)
13565 {
13566 	/* Nothing to be done here */
13567 }
13568 
13569 /** Get number of components for <argument>
13570  *
13571  * @param argument Argument ordinal, starts with 0
13572  *
13573  * @return Number of components
13574  **/
getArgumentComponents(glw::GLuint argument) const13575 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13576 {
13577 	const Utils::_variable_type type		  = getArgumentType(argument);
13578 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13579 
13580 	return n_components;
13581 }
13582 
13583 /** Get size in bytes of single component of <argument>
13584  *
13585  * @param argument Argument ordinal, starts with 0
13586  *
13587  * @return Size of component
13588  **/
getArgumentComponentSize(glw::GLuint argument) const13589 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13590 {
13591 	const Utils::_variable_type type		   = getArgumentType(argument);
13592 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13593 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13594 
13595 	return base_type_size;
13596 }
13597 
13598 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13599  *
13600  * @param argument Argument ordinal, starts with 0
13601  *
13602  * @return Offset of arguemnt's data
13603  **/
getArgumentOffset(glw::GLuint argument) const13604 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13605 {
13606 	glw::GLuint result = 0;
13607 
13608 	for (glw::GLuint i = 0; i < argument; ++i)
13609 	{
13610 		result += getArgumentStride(i);
13611 	}
13612 
13613 	return result;
13614 }
13615 
13616 /** Get stride in bytes of all arguments
13617  *
13618  * @return Stride of all arguments
13619  **/
getArgumentStride() const13620 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13621 {
13622 	const glw::GLuint n_args = getArgumentCount();
13623 	glw::GLuint		  result = 0;
13624 
13625 	for (glw::GLuint i = 0; i < n_args; ++i)
13626 	{
13627 		result += getArgumentStride(i);
13628 	}
13629 
13630 	return result;
13631 }
13632 
13633 /** Get stride in bytes of <argument>
13634  *
13635  * @param argument Argument ordinal, starts with 0
13636  *
13637  * @return Stride of argument
13638  **/
getArgumentStride(glw::GLuint argument) const13639 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13640 {
13641 	const glw::GLuint component_size = getArgumentComponentSize(argument);
13642 	const glw::GLuint n_components   = getArgumentComponents(argument);
13643 
13644 	return n_components * component_size;
13645 }
13646 
13647 /** Get function enumeration
13648  *
13649  * @return Function enumeration
13650  **/
getFunctionEnum() const13651 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13652 {
13653 	return m_function_enum;
13654 }
13655 
13656 /** Get function name
13657  *
13658  * @return Function name
13659  **/
getName() const13660 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13661 {
13662 	return m_function_name;
13663 }
13664 
13665 /** Get number of components for <result>
13666  *
13667  * @param result Result ordinal, starts with 0
13668  *
13669  * @return Number of components
13670  **/
getResultComponents(glw::GLuint result) const13671 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13672 {
13673 	const Utils::_variable_type type		  = getResultType(result);
13674 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13675 
13676 	return n_components;
13677 }
13678 
13679 /** Get number of results
13680  *
13681  * @return Number of results
13682  **/
getResultCount() const13683 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13684 {
13685 	return 1;
13686 }
13687 
13688 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13689  *
13690  * @param result Result ordinal, starts with 0
13691  *
13692  * @return Offset
13693  **/
getResultOffset(glw::GLuint result) const13694 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13695 {
13696 	glw::GLuint offset = 0;
13697 
13698 	for (glw::GLuint i = 0; i < result; ++i)
13699 	{
13700 		offset += getResultStride(i);
13701 		offset = deAlign32(offset, getBaseTypeSize(i));
13702 	}
13703 
13704 	return offset;
13705 }
13706 
13707 /** Get stride in bytes of <result>.
13708  *
13709  * @param result Result ordinal, starts with 0
13710  *
13711  * @return Stride
13712  **/
getResultStride(glw::GLuint result) const13713 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13714 {
13715 	const Utils::_variable_type type		   = getResultType(result);
13716 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
13717 
13718 	return n_components * getBaseTypeSize(result);
13719 }
13720 
13721 /** Get size in bytes of <result> base component.
13722  *
13723  * @param result Result ordinal, starts with 0
13724  *
13725  * @return Alignment
13726  **/
getBaseTypeSize(glw::GLuint result) const13727 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13728 {
13729 	const Utils::_variable_type type		   = getResultType(result);
13730 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13731 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13732 
13733 	return base_type_size;
13734 }
13735 
13736 /** Get stride in bytes of all results.
13737  *
13738  * @return Stride
13739  **/
getResultStride() const13740 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13741 {
13742 	const glw::GLuint n_results	= getResultCount();
13743 	glw::GLuint		  stride	   = 0;
13744 	glw::GLuint		  maxAlignment = 0;
13745 
13746 	for (glw::GLuint i = 0; i < n_results; ++i)
13747 	{
13748 		const glw::GLuint alignment = getBaseTypeSize(i);
13749 		stride += getResultStride(i);
13750 		stride		 = deAlign32(stride, alignment);
13751 		maxAlignment = deMaxu32(maxAlignment, alignment);
13752 	}
13753 
13754 	// The stride of all results must also be aligned,
13755 	// so results for next vertex are aligned.
13756 	return deAlign32(stride, maxAlignment);
13757 }
13758 
13759 /** Get type of <result>.
13760  *
13761  * @param result Result ordinal, starts with 0
13762  *
13763  * @return Type
13764  **/
getResultType(glw::GLuint ) const13765 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13766 {
13767 	return m_res_type;
13768 }
13769 
13770 /** Constructor
13771  *
13772  * @param n_columns Number of columns
13773  * @param n_rows    Number of rows
13774  **/
typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)13775 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13776 	: m_n_columns(n_columns), m_n_rows(n_rows)
13777 {
13778 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13779 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
13780 	m_type_name				   = Utils::getVariableTypeString(type);
13781 
13782 	if (1 == m_n_columns)
13783 	{
13784 		if (1 == m_n_rows)
13785 		{
13786 			m_general_type = SCALAR;
13787 		}
13788 		else
13789 		{
13790 			m_general_type = VECTOR;
13791 		}
13792 	}
13793 	else
13794 	{
13795 		m_general_type = MATRIX;
13796 	}
13797 }
13798 
13799 /** Compare two values
13800  *
13801  * @param type  Type of values
13802  * @param left  Pointer to left value
13803  * @param right Pointer to right value
13804  *
13805  * @return true if values are equal, false otherwise
13806  **/
compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)13807 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13808 {
13809 	bool result = true;
13810 
13811 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
13812 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
13813 
13814 	switch (base_type)
13815 	{
13816 	case Utils::VARIABLE_TYPE_DOUBLE:
13817 
13818 	{
13819 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13820 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
13821 
13822 		for (glw::GLuint component = 0; component < n_components; ++component)
13823 		{
13824 			const glw::GLdouble left_value  = left_values[component];
13825 			const glw::GLdouble right_value = right_values[component];
13826 
13827 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13828 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13829 			{
13830 				result = false;
13831 				break;
13832 			}
13833 		}
13834 	}
13835 
13836 	break;
13837 
13838 	case Utils::VARIABLE_TYPE_INT:
13839 
13840 	{
13841 		const glw::GLint* left_values  = (glw::GLint*)left;
13842 		const glw::GLint* right_values = (glw::GLint*)right;
13843 
13844 		for (glw::GLuint component = 0; component < n_components; ++component)
13845 		{
13846 			const glw::GLint left_value  = left_values[component];
13847 			const glw::GLint right_value = right_values[component];
13848 
13849 			if (left_value != right_value)
13850 			{
13851 				result = false;
13852 				break;
13853 			}
13854 		}
13855 	}
13856 
13857 	break;
13858 
13859 	case Utils::VARIABLE_TYPE_UINT:
13860 
13861 	{
13862 		const glw::GLuint* left_values  = (glw::GLuint*)left;
13863 		const glw::GLuint* right_values = (glw::GLuint*)right;
13864 
13865 		for (glw::GLuint component = 0; component < n_components; ++component)
13866 		{
13867 			const glw::GLuint left_value  = left_values[component];
13868 			const glw::GLuint right_value = right_values[component];
13869 
13870 			if (left_value != right_value)
13871 			{
13872 				result = false;
13873 				break;
13874 			}
13875 		}
13876 	}
13877 
13878 	break;
13879 
13880 	default:
13881 
13882 		TCU_FAIL("Not implemented");
13883 	}
13884 
13885 	return result;
13886 }
13887 
13888 /** Create instance of function object for given function enumeration and type
13889  *
13890  * @param function Function enumeration
13891  * @param type     Type details
13892  *
13893  * @return Create object
13894  **/
getFunctionObject(FunctionEnum function, const typeDetails& type)13895 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
13896 																			const typeDetails& type)
13897 {
13898 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13899 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13900 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13901 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13902 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13903 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13904 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13905 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13906 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13907 
13908 	const glw::GLuint			n_columns	 = type.m_n_columns;
13909 	const glw::GLuint			n_rows		  = type.m_n_rows;
13910 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13911 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13912 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
13913 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
13914 
13915 	switch (function)
13916 	{
13917 	case FUNCTION_ABS:
13918 
13919 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13920 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13921 
13922 	case FUNCTION_CEIL:
13923 
13924 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13925 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13926 
13927 	case FUNCTION_CLAMP:
13928 
13929 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13930 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
13931 													 variable_type /* arg3_type */);
13932 
13933 	case FUNCTION_CLAMP_AGAINST_SCALAR:
13934 
13935 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13936 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13937 													 scalar_type /* arg3_type */);
13938 
13939 	case FUNCTION_CROSS:
13940 
13941 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13942 			function, "cross", tcu::cross);
13943 
13944 	case FUNCTION_DETERMINANT:
13945 
13946 		switch (variable_type)
13947 		{
13948 		case Utils::VARIABLE_TYPE_DMAT2:
13949 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13950 																						 Math::determinant);
13951 		case Utils::VARIABLE_TYPE_DMAT3:
13952 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13953 																						 Math::determinant);
13954 		case Utils::VARIABLE_TYPE_DMAT4:
13955 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13956 																						 Math::determinant);
13957 		default:
13958 			TCU_FAIL("Not implemented");
13959 		}
13960 
13961 	case FUNCTION_DISTANCE:
13962 
13963 		switch (variable_type)
13964 		{
13965 		case Utils::VARIABLE_TYPE_DVEC2:
13966 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13967 				function, "distance", tcu::distance);
13968 		case Utils::VARIABLE_TYPE_DVEC3:
13969 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13970 				function, "distance", tcu::distance);
13971 		case Utils::VARIABLE_TYPE_DVEC4:
13972 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13973 				function, "distance", tcu::distance);
13974 		default:
13975 			break;
13976 		}
13977 
13978 		break;
13979 
13980 	case FUNCTION_DOT:
13981 
13982 		switch (variable_type)
13983 		{
13984 		case Utils::VARIABLE_TYPE_DVEC2:
13985 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13986 				function, "dot", tcu::dot);
13987 		case Utils::VARIABLE_TYPE_DVEC3:
13988 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13989 				function, "dot", tcu::dot);
13990 		case Utils::VARIABLE_TYPE_DVEC4:
13991 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13992 				function, "dot", tcu::dot);
13993 		default:
13994 			break;
13995 		}
13996 
13997 		break;
13998 
13999 	case FUNCTION_EQUAL:
14000 
14001 		switch (variable_type)
14002 		{
14003 		case Utils::VARIABLE_TYPE_DVEC2:
14004 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14005 				function, "equal", Math::equal);
14006 		case Utils::VARIABLE_TYPE_DVEC3:
14007 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14008 				function, "equal", Math::equal);
14009 		case Utils::VARIABLE_TYPE_DVEC4:
14010 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14011 				function, "equal", Math::equal);
14012 		default:
14013 			break;
14014 		}
14015 
14016 		break;
14017 
14018 	case FUNCTION_FACEFORWARD:
14019 
14020 		switch (variable_type)
14021 		{
14022 		case Utils::VARIABLE_TYPE_DVEC2:
14023 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14024 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14025 				function, "faceforward", tcu::faceForward);
14026 		case Utils::VARIABLE_TYPE_DVEC3:
14027 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14028 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14029 				function, "faceforward", tcu::faceForward);
14030 		case Utils::VARIABLE_TYPE_DVEC4:
14031 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14032 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14033 				function, "faceforward", tcu::faceForward);
14034 		default:
14035 			break;
14036 		}
14037 
14038 		break;
14039 
14040 	case FUNCTION_FLOOR:
14041 
14042 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14043 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14044 
14045 	case FUNCTION_FMA:
14046 
14047 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14048 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14049 													 variable_type /* arg3_type */);
14050 
14051 	case FUNCTION_FRACT:
14052 
14053 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14054 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14055 
14056 	case FUNCTION_FREXP:
14057 
14058 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14059 															  glw::GLint /* OutT */>(
14060 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14061 			int_type /* out_type */);
14062 
14063 	case FUNCTION_GREATERTHAN:
14064 
14065 		switch (variable_type)
14066 		{
14067 		case Utils::VARIABLE_TYPE_DVEC2:
14068 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14069 				function, "greaterThan", Math::greaterThan);
14070 		case Utils::VARIABLE_TYPE_DVEC3:
14071 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14072 				function, "greaterThan", Math::greaterThan);
14073 		case Utils::VARIABLE_TYPE_DVEC4:
14074 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14075 				function, "greaterThan", Math::greaterThan);
14076 		default:
14077 			break;
14078 		}
14079 
14080 		break;
14081 
14082 	case FUNCTION_GREATERTHANEQUAL:
14083 
14084 		switch (variable_type)
14085 		{
14086 		case Utils::VARIABLE_TYPE_DVEC2:
14087 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14088 				function, "greaterThanEqual", Math::greaterThanEqual);
14089 		case Utils::VARIABLE_TYPE_DVEC3:
14090 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14091 				function, "greaterThanEqual", Math::greaterThanEqual);
14092 		case Utils::VARIABLE_TYPE_DVEC4:
14093 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14094 				function, "greaterThanEqual", Math::greaterThanEqual);
14095 		default:
14096 			break;
14097 		}
14098 
14099 		break;
14100 
14101 	case FUNCTION_INVERSE:
14102 
14103 		switch (variable_type)
14104 		{
14105 		case Utils::VARIABLE_TYPE_DMAT2:
14106 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14107 		case Utils::VARIABLE_TYPE_DMAT3:
14108 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14109 		case Utils::VARIABLE_TYPE_DMAT4:
14110 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14111 		default:
14112 			break;
14113 		}
14114 
14115 		break;
14116 
14117 	case FUNCTION_INVERSESQRT:
14118 
14119 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14120 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14121 
14122 	case FUNCTION_LDEXP:
14123 
14124 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14125 													 glw::GLint /* Arg2T */>(
14126 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14127 			int_type /* arg2_type */);
14128 
14129 	case FUNCTION_LESSTHAN:
14130 
14131 		switch (variable_type)
14132 		{
14133 		case Utils::VARIABLE_TYPE_DVEC2:
14134 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14135 				function, "lessThan", Math::lessThan);
14136 		case Utils::VARIABLE_TYPE_DVEC3:
14137 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14138 				function, "lessThan", Math::lessThan);
14139 		case Utils::VARIABLE_TYPE_DVEC4:
14140 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14141 				function, "lessThan", Math::lessThan);
14142 		default:
14143 			break;
14144 		}
14145 
14146 		break;
14147 
14148 	case FUNCTION_LESSTHANEQUAL:
14149 
14150 		switch (variable_type)
14151 		{
14152 		case Utils::VARIABLE_TYPE_DVEC2:
14153 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14154 				function, "lessThanEqual", Math::lessThanEqual);
14155 		case Utils::VARIABLE_TYPE_DVEC3:
14156 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14157 				function, "lessThanEqual", Math::lessThanEqual);
14158 		case Utils::VARIABLE_TYPE_DVEC4:
14159 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14160 				function, "lessThanEqual", Math::lessThanEqual);
14161 		default:
14162 			break;
14163 		}
14164 
14165 		break;
14166 
14167 	case FUNCTION_LENGTH:
14168 
14169 		switch (variable_type)
14170 		{
14171 		case Utils::VARIABLE_TYPE_DVEC2:
14172 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14173 																							  tcu::length);
14174 		case Utils::VARIABLE_TYPE_DVEC3:
14175 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14176 																							  tcu::length);
14177 		case Utils::VARIABLE_TYPE_DVEC4:
14178 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14179 																							  tcu::length);
14180 		default:
14181 			break;
14182 		}
14183 
14184 		break;
14185 
14186 	case FUNCTION_MATRIXCOMPMULT:
14187 
14188 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14189 													 glw::GLdouble /* Arg2T */>(
14190 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14191 			variable_type /* arg2_type */);
14192 
14193 	case FUNCTION_MAX:
14194 
14195 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14196 													 glw::GLdouble /* Arg2T */>(
14197 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14198 			variable_type /* arg2_type */);
14199 
14200 	case FUNCTION_MAX_AGAINST_SCALAR:
14201 
14202 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14203 													 glw::GLdouble /* Arg2T */>(
14204 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14205 			scalar_type /* arg2_type */);
14206 
14207 	case FUNCTION_MIN:
14208 
14209 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14210 													 glw::GLdouble /* Arg2T */>(
14211 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14212 			variable_type /* arg2_type */);
14213 
14214 	case FUNCTION_MIN_AGAINST_SCALAR:
14215 
14216 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14217 													 glw::GLdouble /* Arg2T */>(
14218 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14219 			scalar_type /* arg2_type */);
14220 
14221 	case FUNCTION_MIX:
14222 
14223 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14224 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14225 													 variable_type /* arg3_type */);
14226 
14227 	case FUNCTION_MOD:
14228 
14229 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14230 													 glw::GLdouble /* Arg2T */>(
14231 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14232 			variable_type /* arg2_type */);
14233 
14234 	case FUNCTION_MOD_AGAINST_SCALAR:
14235 
14236 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14237 													 glw::GLdouble /* Arg2T */>(
14238 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14239 			scalar_type /* arg2_type */);
14240 
14241 	case FUNCTION_MODF:
14242 
14243 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14244 															  glw::GLdouble /* OutT */>(
14245 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14246 			variable_type /* out_type */);
14247 
14248 	case FUNCTION_NORMALIZE:
14249 
14250 		switch (variable_type)
14251 		{
14252 		case Utils::VARIABLE_TYPE_DVEC2:
14253 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14254 																						   tcu::normalize);
14255 		case Utils::VARIABLE_TYPE_DVEC3:
14256 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14257 																						   tcu::normalize);
14258 		case Utils::VARIABLE_TYPE_DVEC4:
14259 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14260 																						   tcu::normalize);
14261 		default:
14262 			break;
14263 		}
14264 
14265 		break;
14266 
14267 	case FUNCTION_NOTEQUAL:
14268 
14269 		switch (variable_type)
14270 		{
14271 		case Utils::VARIABLE_TYPE_DVEC2:
14272 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14273 				function, "notEqual", Math::notEqual);
14274 		case Utils::VARIABLE_TYPE_DVEC3:
14275 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14276 				function, "notEqual", Math::notEqual);
14277 		case Utils::VARIABLE_TYPE_DVEC4:
14278 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14279 				function, "notEqual", Math::notEqual);
14280 		default:
14281 			break;
14282 		}
14283 
14284 		break;
14285 
14286 	case FUNCTION_OUTERPRODUCT:
14287 
14288 		switch (variable_type)
14289 		{
14290 		case Utils::VARIABLE_TYPE_DMAT2:
14291 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 				function, "outerProduct", Math::outerProduct);
14293 		case Utils::VARIABLE_TYPE_DMAT2X3:
14294 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14295 				function, "outerProduct", Math::outerProduct);
14296 		case Utils::VARIABLE_TYPE_DMAT2X4:
14297 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14298 				function, "outerProduct", Math::outerProduct);
14299 		case Utils::VARIABLE_TYPE_DMAT3:
14300 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 				function, "outerProduct", Math::outerProduct);
14302 		case Utils::VARIABLE_TYPE_DMAT3X2:
14303 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14304 				function, "outerProduct", Math::outerProduct);
14305 		case Utils::VARIABLE_TYPE_DMAT3X4:
14306 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14307 				function, "outerProduct", Math::outerProduct);
14308 		case Utils::VARIABLE_TYPE_DMAT4:
14309 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 				function, "outerProduct", Math::outerProduct);
14311 		case Utils::VARIABLE_TYPE_DMAT4X2:
14312 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14313 				function, "outerProduct", Math::outerProduct);
14314 		case Utils::VARIABLE_TYPE_DMAT4X3:
14315 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14316 				function, "outerProduct", Math::outerProduct);
14317 		default:
14318 			break;
14319 		}
14320 
14321 		break;
14322 
14323 	case FUNCTION_PACKDOUBLE2X32:
14324 
14325 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14326 																						  Math::packDouble2x32);
14327 
14328 	case FUNCTION_REFLECT:
14329 
14330 		switch (variable_type)
14331 		{
14332 		case Utils::VARIABLE_TYPE_DVEC2:
14333 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14334 				function, "reflect", tcu::reflect);
14335 		case Utils::VARIABLE_TYPE_DVEC3:
14336 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14337 				function, "reflect", tcu::reflect);
14338 		case Utils::VARIABLE_TYPE_DVEC4:
14339 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14340 				function, "reflect", tcu::reflect);
14341 		default:
14342 			break;
14343 		}
14344 
14345 		break;
14346 
14347 	case FUNCTION_REFRACT:
14348 
14349 		switch (variable_type)
14350 		{
14351 		case Utils::VARIABLE_TYPE_DVEC2:
14352 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14353 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14354 				function, "refract", tcu::refract);
14355 		case Utils::VARIABLE_TYPE_DVEC3:
14356 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14357 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14358 				function, "refract", tcu::refract);
14359 		case Utils::VARIABLE_TYPE_DVEC4:
14360 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14361 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14362 				function, "refract", tcu::refract);
14363 		default:
14364 			break;
14365 		}
14366 
14367 		break;
14368 
14369 	case FUNCTION_ROUND:
14370 
14371 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14372 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14373 
14374 	case FUNCTION_ROUNDEVEN:
14375 
14376 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14377 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14378 
14379 	case FUNCTION_SIGN:
14380 
14381 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14382 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14383 
14384 	case FUNCTION_SMOOTHSTEP:
14385 
14386 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14387 													 variable_type /* res_type  */, variable_type /* arg1_type */,
14388 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
14389 
14390 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14391 
14392 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14393 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
14394 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14395 
14396 	case FUNCTION_SQRT:
14397 
14398 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14399 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14400 
14401 	case FUNCTION_STEP:
14402 
14403 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14404 													 glw::GLdouble /* Arg2T */>(
14405 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14406 			variable_type /* arg2_type */);
14407 
14408 	case FUNCTION_STEP_AGAINST_SCALAR:
14409 
14410 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14411 													 glw::GLdouble /* Arg2T */>(
14412 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14413 			variable_type /* arg2_type */);
14414 
14415 	case FUNCTION_TRANSPOSE:
14416 
14417 		switch (variable_type)
14418 		{
14419 		case Utils::VARIABLE_TYPE_DMAT2:
14420 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14421 																				 Math::transpose);
14422 		case Utils::VARIABLE_TYPE_DMAT2X3:
14423 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14424 																					 Math::transpose);
14425 		case Utils::VARIABLE_TYPE_DMAT2X4:
14426 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14427 																					 Math::transpose);
14428 		case Utils::VARIABLE_TYPE_DMAT3:
14429 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14430 																				 Math::transpose);
14431 		case Utils::VARIABLE_TYPE_DMAT3X2:
14432 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14433 																					 Math::transpose);
14434 		case Utils::VARIABLE_TYPE_DMAT3X4:
14435 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14436 																					 Math::transpose);
14437 		case Utils::VARIABLE_TYPE_DMAT4:
14438 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14439 																				 Math::transpose);
14440 		case Utils::VARIABLE_TYPE_DMAT4X2:
14441 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14442 																					 Math::transpose);
14443 		case Utils::VARIABLE_TYPE_DMAT4X3:
14444 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14445 																					 Math::transpose);
14446 		default:
14447 			break;
14448 		}
14449 
14450 		break;
14451 
14452 	case FUNCTION_TRUNC:
14453 
14454 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14455 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14456 
14457 	case FUNCTION_UNPACKDOUBLE2X32:
14458 
14459 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14460 																						  Math::unpackDouble2x32);
14461 
14462 	case FUNCTION_ISNAN:
14463 
14464 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14465 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14466 
14467 	case FUNCTION_ISINF:
14468 
14469 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14470 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14471 
14472 	default:
14473 		TCU_FAIL("Not implemented");
14474 		return 0;
14475 	}
14476 
14477 	TCU_FAIL("Not implemented");
14478 	return 0;
14479 }
14480 
14481 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14482  *
14483  * @param argument        Argument index
14484  * @param function_object Function object
14485  *
14486  * @return Function pointer
14487  **/
getUniformFunctionForDMat( glw::GLuint argument, const functionObject& function_object) const14488 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14489 	glw::GLuint argument, const functionObject& function_object) const
14490 {
14491 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14492 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14493 
14494 	switch (argument_type)
14495 	{
14496 	case Utils::VARIABLE_TYPE_DMAT2:
14497 		return gl.uniformMatrix2dv;
14498 	case Utils::VARIABLE_TYPE_DMAT2X3:
14499 		return gl.uniformMatrix2x3dv;
14500 	case Utils::VARIABLE_TYPE_DMAT2X4:
14501 		return gl.uniformMatrix2x4dv;
14502 	case Utils::VARIABLE_TYPE_DMAT3:
14503 		return gl.uniformMatrix3dv;
14504 	case Utils::VARIABLE_TYPE_DMAT3X2:
14505 		return gl.uniformMatrix3x2dv;
14506 	case Utils::VARIABLE_TYPE_DMAT3X4:
14507 		return gl.uniformMatrix3x4dv;
14508 	case Utils::VARIABLE_TYPE_DMAT4:
14509 		return gl.uniformMatrix4dv;
14510 	case Utils::VARIABLE_TYPE_DMAT4X2:
14511 		return gl.uniformMatrix4x2dv;
14512 	case Utils::VARIABLE_TYPE_DMAT4X3:
14513 		return gl.uniformMatrix4x3dv;
14514 	default:
14515 		break;
14516 	}
14517 
14518 	TCU_FAIL("Not implemented");
14519 	return 0;
14520 }
14521 
14522 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14523  *
14524  * @param argument        Argument index
14525  * @param function_object Function object
14526  *
14527  * @return Function pointer
14528  **/
getUniformFunctionForDVec( glw::GLuint argument, const functionObject& function_object) const14529 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14530 	glw::GLuint argument, const functionObject& function_object) const
14531 {
14532 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14533 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14534 
14535 	switch (argument_type)
14536 	{
14537 	case Utils::VARIABLE_TYPE_DOUBLE:
14538 		return gl.uniform1dv;
14539 	case Utils::VARIABLE_TYPE_DVEC2:
14540 		return gl.uniform2dv;
14541 	case Utils::VARIABLE_TYPE_DVEC3:
14542 		return gl.uniform3dv;
14543 	case Utils::VARIABLE_TYPE_DVEC4:
14544 		return gl.uniform4dv;
14545 	default:
14546 		TCU_FAIL("Not implemented");
14547 	}
14548 
14549 	return 0;
14550 }
14551 
14552 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14553  *
14554  * @param argument        Argument index
14555  * @param function_object Function object
14556  *
14557  * @return Function pointer
14558  **/
getUniformFunctionForIVec( glw::GLuint argument, const functionObject& function_object) const14559 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14560 	glw::GLuint argument, const functionObject& function_object) const
14561 {
14562 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14563 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14564 
14565 	switch (argument_type)
14566 	{
14567 	case Utils::VARIABLE_TYPE_INT:
14568 		return gl.uniform1iv;
14569 	case Utils::VARIABLE_TYPE_IVEC2:
14570 		return gl.uniform2iv;
14571 	case Utils::VARIABLE_TYPE_IVEC3:
14572 		return gl.uniform3iv;
14573 	case Utils::VARIABLE_TYPE_IVEC4:
14574 		return gl.uniform4iv;
14575 	default:
14576 		TCU_FAIL("Not implemented");
14577 	}
14578 
14579 	return 0;
14580 }
14581 
14582 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14583  *
14584  * @param argument        Argument index
14585  * @param function_object Function object
14586  *
14587  * @return Function pointer
14588  **/
getUniformFunctionForUVec( glw::GLuint argument, const functionObject& function_object) const14589 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14590 	glw::GLuint argument, const functionObject& function_object) const
14591 {
14592 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14593 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14594 
14595 	switch (argument_type)
14596 	{
14597 	case Utils::VARIABLE_TYPE_UVEC2:
14598 		return gl.uniform2uiv;
14599 	default:
14600 		TCU_FAIL("Not implemented");
14601 	}
14602 
14603 	return 0;
14604 }
14605 
14606 /** Get name of uniform that will be used as <argument>.
14607  *
14608  * @param argument Argument index
14609  *
14610  * @return Name of uniform
14611  **/
getUniformName(glw::GLuint argument) const14612 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14613 {
14614 	switch (argument)
14615 	{
14616 	case 0:
14617 		return "uniform_0";
14618 	case 1:
14619 		return "uniform_1";
14620 	case 2:
14621 		return "uniform_2";
14622 	default:
14623 		TCU_FAIL("Not implemented");
14624 		return 0;
14625 	}
14626 }
14627 
14628 /** Get name of varying that will be used as <result>.
14629  *
14630  * @param result Result index
14631  *
14632  * @return Name of varying
14633  **/
getVaryingName(glw::GLuint result) const14634 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14635 {
14636 	switch (result)
14637 	{
14638 	case 0:
14639 		return "result_0";
14640 	case 1:
14641 		return "result_1";
14642 	case 2:
14643 		return "result_2";
14644 	default:
14645 		TCU_FAIL("Not implemented");
14646 		return 0;
14647 	}
14648 }
14649 
14650 /** Check if given combination of function and type is implemented
14651  *
14652  * @param function Function enumeration
14653  * @param type     Type details
14654  *
14655  * @return true if function is available for given type, false otherwise
14656  **/
isFunctionImplemented(FunctionEnum function, const typeDetails& type) const14657 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14658 {
14659 	static const bool look_up_table[][3] = {
14660 		/* SCALAR, VECTOR, MATRIX */
14661 		/* FUNCTION_ABS:                       */ { true, true, false },
14662 		/* FUNCTION_CEIL:                      */ { true, true, false },
14663 		/* FUNCTION_CLAMP:                     */ { true, true, false },
14664 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14665 		/* FUNCTION_CROSS:                     */ { false, true, false },
14666 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
14667 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
14668 		/* FUNCTION_DOT:                       */ { false, true, false },
14669 		/* FUNCTION_EQUAL:                     */ { false, true, false },
14670 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
14671 		/* FUNCTION_FLOOR:                     */ { true, true, false },
14672 		/* FUNCTION_FMA:                       */ { true, true, false },
14673 		/* FUNCTION_FRACT:                     */ { true, true, false },
14674 		/* FUNCTION_FREXP:                     */ { true, true, false },
14675 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
14676 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14677 		/* FUNCTION_INVERSE:                   */ { false, false, true },
14678 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
14679 		/* FUNCTION_LDEXP:                     */ { true, true, false },
14680 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
14681 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14682 		/* FUNCTION_LENGTH:                    */ { false, true, false },
14683 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14684 		/* FUNCTION_MAX:                       */ { true, true, false },
14685 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14686 		/* FUNCTION_MIN:                       */ { true, true, false },
14687 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14688 		/* FUNCTION_MIX:                       */ { true, true, false },
14689 		/* FUNCTION_MOD:                       */ { true, true, false },
14690 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14691 		/* FUNCTION_MODF:                      */ { true, true, false },
14692 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
14693 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14694 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14695 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14696 		/* FUNCTION_REFLECT:                   */ { false, true, false },
14697 		/* FUNCTION_REFRACT:                   */ { false, true, false },
14698 		/* FUNCTION_ROUND:                     */ { true, true, false },
14699 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14700 		/* FUNCTION_SIGN:                      */ { true, false, false },
14701 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14702 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14703 		/* FUNCTION_SQRT:                      */ { true, true, false },
14704 		/* FUNCTION_STEP:                      */ { true, true, false },
14705 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14706 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14707 		/* FUNCTION_TRUNC:                     */ { true, true, false },
14708 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14709 		/* FUNCTION_ISNAN:                     */ { true, true, false },
14710 		/* FUNCTION_ISINF:                     */ { true, true, false },
14711 	};
14712 
14713 	bool result = look_up_table[function][type.m_general_type];
14714 
14715 	if (true == result)
14716 	{
14717 		switch (function)
14718 		{
14719 		case FUNCTION_CROSS: /* Only 3 element vectors */
14720 			result = (3 == type.m_n_rows);
14721 			break;
14722 		case FUNCTION_DETERMINANT: /* Only square matrices */
14723 		case FUNCTION_INVERSE:
14724 			result = (type.m_n_columns == type.m_n_rows);
14725 			break;
14726 		default:
14727 			break;
14728 		}
14729 	}
14730 
14731 	return result;
14732 }
14733 
14734 /** Logs variable of given type: name (type) [values]
14735  *
14736  * @param buffer Source of data
14737  * @param name   Name of variable
14738  * @param type   Type of variable
14739  **/
logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const14740 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14741 										  Utils::_variable_type type) const
14742 {
14743 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
14744 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
14745 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14746 
14747 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14748 
14749 	for (glw::GLuint component = 0; component < n_components; ++component)
14750 	{
14751 		if (0 != component)
14752 		{
14753 			message << ", ";
14754 		}
14755 
14756 		switch (base_type)
14757 		{
14758 		case Utils::VARIABLE_TYPE_DOUBLE:
14759 			message << ((glw::GLdouble*)buffer)[component];
14760 			break;
14761 		case Utils::VARIABLE_TYPE_INT:
14762 			message << ((glw::GLint*)buffer)[component];
14763 			break;
14764 		case Utils::VARIABLE_TYPE_UINT:
14765 			message << ((glw::GLuint*)buffer)[component];
14766 			break;
14767 		default:
14768 			TCU_FAIL("Not implemented");
14769 		}
14770 	}
14771 
14772 	message << "]" << tcu::TestLog::EndMessage;
14773 }
14774 
14775 /** Prepare input arguments, data are stored in <buffer>
14776  *
14777  * @param function_object Function object
14778  * @param vertex          Vertex index
14779  * @param buffer          Buffer pointer
14780  **/
prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer)14781 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14782 										  glw::GLubyte* buffer)
14783 {
14784 	const glw::GLuint n_arguments = function_object.getArgumentCount();
14785 
14786 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14787 	{
14788 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
14789 
14790 		prepareComponents(function_object, vertex, argument, buffer + offset);
14791 	}
14792 }
14793 
14794 /** Prepare components for given <function_object>, <vertex> and <argument>
14795  *
14796  * @param function_object Function object
14797  * @param vertex          Vertex index
14798  * @param argument        Argument index
14799  * @param buffer          Buffer pointer
14800  **/
prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument, glw::GLubyte* buffer)14801 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14802 											glw::GLuint argument, glw::GLubyte* buffer)
14803 {
14804 	glw::GLuint					argument_index[3]		 = { 0 };
14805 	glw::GLuint					argument_reset[3]		 = { 0 };
14806 	glw::GLuint					argument_step[3]		 = { 0 };
14807 	glw::GLdouble				double_argument_start[3] = { 0.0 };
14808 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14809 	glw::GLuint					int_argument_start  = -4;
14810 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
14811 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
14812 	glw::GLuint					uint_argument_start = 0;
14813 
14814 	switch (n_arguments)
14815 	{
14816 	case 1:
14817 		argument_step[0]		 = 1;
14818 		argument_reset[0]		 = 1024;
14819 		double_argument_start[0] = -511.5;
14820 		break;
14821 	case 2:
14822 		argument_step[0]		 = 32;
14823 		argument_step[1]		 = 1;
14824 		argument_reset[0]		 = 32;
14825 		argument_reset[1]		 = 32;
14826 		double_argument_start[0] = -15.5;
14827 		double_argument_start[1] = -15.5;
14828 		break;
14829 	case 3:
14830 		argument_step[0]		 = 64;
14831 		argument_step[1]		 = 8;
14832 		argument_step[2]		 = 1;
14833 		argument_reset[0]		 = 16;
14834 		argument_reset[1]		 = 8;
14835 		argument_reset[2]		 = 8;
14836 		double_argument_start[0] = -7.5;
14837 		double_argument_start[1] = -3.5;
14838 		double_argument_start[2] = -3.5;
14839 		break;
14840 	default:
14841 		TCU_FAIL("Not implemented");
14842 		return;
14843 	}
14844 
14845 	switch (function_object.getFunctionEnum())
14846 	{
14847 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14848 	case FUNCTION_CLAMP_AGAINST_SCALAR:
14849 		double_argument_start[2] = 4.5;
14850 		break;
14851 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14852 		double_argument_start[0] = 16.5;
14853 		break;
14854 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14855 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14856 		argument_step[0]		 = 1;
14857 		argument_step[1]		 = 8;
14858 		argument_step[2]		 = 64;
14859 		argument_reset[0]		 = 8;
14860 		argument_reset[1]		 = 8;
14861 		argument_reset[2]		 = 16;
14862 		double_argument_start[0] = -3.5;
14863 		double_argument_start[1] = 4.5;
14864 		double_argument_start[2] = -7.5;
14865 		break;
14866 	default:
14867 		break;
14868 	}
14869 
14870 	for (glw::GLuint i = 0; i < n_arguments; ++i)
14871 	{
14872 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14873 	}
14874 
14875 	switch (base_arg_type)
14876 	{
14877 	case Utils::VARIABLE_TYPE_DOUBLE:
14878 	{
14879 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14880 
14881 		double_argument_start[argument] += argument_index[argument];
14882 
14883 		for (glw::GLuint component = 0; component < n_components; ++component)
14884 		{
14885 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14886 
14887 			switch (function_object.getFunctionEnum())
14888 			{
14889 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14890 				if (0.5 == Math::fract(value))
14891 				{
14892 					value += 0.01;
14893 				}
14894 				break;
14895 			default:
14896 				break;
14897 			}
14898 
14899 			argument_dst[component] = value;
14900 		}
14901 	}
14902 	break;
14903 	case Utils::VARIABLE_TYPE_INT:
14904 	{
14905 		glw::GLint* argument_dst = (glw::GLint*)buffer;
14906 
14907 		uint_argument_start += argument_index[argument];
14908 
14909 		for (glw::GLuint component = 0; component < n_components; ++component)
14910 		{
14911 			const glw::GLint value = int_argument_start + component;
14912 
14913 			argument_dst[component] = value;
14914 		}
14915 	}
14916 	break;
14917 	case Utils::VARIABLE_TYPE_UINT:
14918 	{
14919 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14920 
14921 		uint_argument_start += argument_index[argument];
14922 
14923 		for (glw::GLuint component = 0; component < n_components; ++component)
14924 		{
14925 			const glw::GLuint value = uint_argument_start + component;
14926 
14927 			argument_dst[component] = value;
14928 		}
14929 	}
14930 	break;
14931 	default:
14932 		TCU_FAIL("Not implemented");
14933 		return;
14934 	}
14935 }
14936 
14937 /** Prepare programInfo for given functionObject
14938  *
14939  * @param function_object  Function object
14940  * @param out_program_info Program info
14941  **/
prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)14942 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14943 {
14944 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
14945 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14946 
14947 	prepareVertexShaderCode(function_object);
14948 
14949 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14950 						   varying_names, n_varying_names);
14951 }
14952 
14953 /** Prepare input data and expected results for given function object
14954  *
14955  * @param function_object Function object
14956  **/
prepareTestData(const functionObject& function_object)14957 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14958 {
14959 	const glw::GLuint result_stride		   = function_object.getResultStride();
14960 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
14961 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
14962 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14963 
14964 	m_argument_data.clear();
14965 	m_expected_results_data.clear();
14966 
14967 	m_argument_data.resize(argument_buffer_size);
14968 	m_expected_results_data.resize(result_buffer_size);
14969 
14970 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14971 	{
14972 		const glw::GLuint result_offset   = vertex * result_stride;
14973 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
14974 		const glw::GLuint argument_offset = vertex * argument_stride;
14975 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
14976 
14977 		prepareArgument(function_object, vertex, argument_dst);
14978 		function_object.call(result_dst, argument_dst);
14979 	}
14980 }
14981 
14982 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14983  *
14984  * @param function_object Function object
14985  **/
prepareVertexShaderCode(const functionObject& function_object)14986 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14987 {
14988 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
14989 													 "\n"
14990 													 "precision highp float;\n"
14991 													 "\n"
14992 													 "ARGUMENT_DEFINITION"
14993 													 "\n"
14994 													 "RESULT_DEFINITION"
14995 													 "\n"
14996 													 "void main()\n"
14997 													 "{\n"
14998 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14999 													 "}\n"
15000 													 "\n";
15001 
15002 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15003 	static const glw::GLchar* argument_token			= "ARGUMENT";
15004 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
15005 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15006 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
15007 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
15008 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
15009 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
15010 
15011 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15012 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
15013 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
15014 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15015 
15016 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15017 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
15018 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
15019 	const glw::GLuint n_results					 = function_object.getResultCount();
15020 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15021 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
15022 
15023 	size_t		search_position = 0;
15024 	std::string string			= shader_template_code;
15025 
15026 	/* Replace ARGUMENT_DEFINITION with definitions */
15027 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15028 	{
15029 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15030 		const glw::GLchar*	uniform_name  = getUniformName(argument);
15031 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
15032 
15033 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15034 
15035 		search_position -= argument_definition_length;
15036 
15037 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15038 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15039 	}
15040 
15041 	/* Remove ARGUMENT_DEFINITION */
15042 	Utils::replaceToken(argument_definition_token, search_position, "", string);
15043 
15044 	/* Replace RESULT_DEFINITION with definitions */
15045 	for (glw::GLuint result = 0; result < n_results; ++result)
15046 	{
15047 		Utils::_variable_type variable_type = function_object.getResultType(result);
15048 		const glw::GLchar*	varying_name  = getVaryingName(result);
15049 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
15050 
15051 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15052 
15053 		search_position -= result_definition_length;
15054 
15055 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15056 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
15057 	}
15058 
15059 	/* Remove RESULT_DEFINITION */
15060 	Utils::replaceToken(result_definition_token, search_position, "", string);
15061 
15062 	/* Replace RESULT_NAME */
15063 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15064 
15065 	/* Replace RESULT_TYPE */
15066 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15067 
15068 	/* Replace FUNCTION_NAME */
15069 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15070 
15071 	/* Replace ARGUMENT with list of arguments */
15072 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15073 	{
15074 		const glw::GLchar* uniform_name = getUniformName(argument);
15075 
15076 		if (0 == argument)
15077 		{
15078 			Utils::replaceToken(argument_token, search_position, first_argument, string);
15079 		}
15080 		else
15081 		{
15082 			Utils::replaceToken(argument_token, search_position, argument_str, string);
15083 		}
15084 
15085 		search_position -= first_argument_length;
15086 
15087 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15088 	}
15089 
15090 	for (glw::GLuint result = 1; result < n_results; ++result)
15091 	{
15092 		const glw::GLchar* varying_name = getVaryingName(result);
15093 
15094 		Utils::replaceToken(argument_token, search_position, argument_str, string);
15095 
15096 		search_position -= first_argument_length;
15097 
15098 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15099 	}
15100 
15101 	/* Remove ARGUMENT */
15102 	Utils::replaceToken(argument_token, search_position, "", string);
15103 
15104 	m_vertex_shader_code = string;
15105 }
15106 
15107 /** Test single function with one type
15108  *
15109  * param function Function enumeration
15110  * param type     Type details
15111  *
15112  * @return true if test pass (or function is not available for <type>), false otherwise
15113  **/
test(FunctionEnum function, const typeDetails& type)15114 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15115 {
15116 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15117 
15118 	/* Skip if function is not implemented for type */
15119 	if (false == isFunctionImplemented(function, type))
15120 	{
15121 		return true;
15122 	}
15123 
15124 	Utils::programInfo			  program(m_context);
15125 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15126 
15127 	prepareProgram(*function_object, program);
15128 	prepareTestData(*function_object);
15129 
15130 	/* Set up program */
15131 	gl.useProgram(program.m_program_object_id);
15132 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15133 
15134 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15135 	{
15136 		testBegin(*function_object, program.m_program_object_id, vertex);
15137 
15138 		gl.beginTransformFeedback(GL_POINTS);
15139 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15140 
15141 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15142 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15143 
15144 		gl.endTransformFeedback();
15145 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15146 
15147 		if (false == verifyResults(*function_object, vertex))
15148 		{
15149 			return false;
15150 		}
15151 	}
15152 
15153 	return true;
15154 }
15155 
15156 /** Update transform feedback buffer and uniforms
15157  *
15158  * @param function_object Function object
15159  * @param program_id      Program object id
15160  * @param vertex          Vertex index
15161  **/
testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)15162 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15163 {
15164 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
15165 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
15166 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
15167 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
15168 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
15169 
15170 	/* Update transform feedback buffer */
15171 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
15172 	transform_feedback_buffer_data.resize(result_buffer_size);
15173 
15174 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15175 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15176 
15177 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15178 				  GL_DYNAMIC_COPY);
15179 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15180 
15181 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15182 					   result_buffer_size);
15183 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15184 
15185 	/* Update VAO */
15186 	gl.bindVertexArray(m_vertex_array_object_id);
15187 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15188 
15189 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15190 	{
15191 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
15192 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
15193 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
15194 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
15195 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
15196 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15197 
15198 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15199 
15200 		if (-1 == uniform_location)
15201 		{
15202 			TCU_FAIL("Inactive uniform");
15203 		}
15204 
15205 		if (1 == n_columns)
15206 		{
15207 			switch (Utils::getBaseVariableType(argument_type))
15208 			{
15209 			case Utils::VARIABLE_TYPE_DOUBLE:
15210 			{
15211 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15212 
15213 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15214 			}
15215 			break;
15216 			case Utils::VARIABLE_TYPE_UINT:
15217 			{
15218 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15219 
15220 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15221 			}
15222 			break;
15223 			case Utils::VARIABLE_TYPE_INT:
15224 			{
15225 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15226 
15227 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15228 			}
15229 			break;
15230 			default:
15231 				TCU_FAIL("Not implemented");
15232 			}
15233 		}
15234 		else
15235 		{
15236 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15237 
15238 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15239 		}
15240 	}
15241 }
15242 
15243 /** Init GL obejcts
15244  *
15245  **/
testInit()15246 void BuiltinFunctionTest::testInit()
15247 {
15248 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15249 
15250 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
15251 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15252 
15253 	gl.genVertexArrays(1, &m_vertex_array_object_id);
15254 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15255 
15256 	gl.enable(GL_RASTERIZER_DISCARD);
15257 }
15258 
15259 /** Checks if function result is an acceptable edge case
15260  *
15261  * @param function_object Function object
15262  * @param vertex          Vertex index
15263  *
15264  * @return true if all results are as expected, false otherwise
15265  **/
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)15266 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15267 										   const Utils::_variable_type result_type,
15268 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15269 {
15270 	FunctionEnum function_type = function_object.getFunctionEnum();
15271 	switch (function_type)
15272 	{
15273 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15274 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15275 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15276 	case FUNCTION_MOD:
15277 	case FUNCTION_MOD_AGAINST_SCALAR:
15278 	{
15279 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
15280 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
15281 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
15282 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
15283 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
15284 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
15285 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
15286 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
15287 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15288 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15289 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15290 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
15291 		bool				 edge_case_present = false;
15292 		bool				 recheck		   = false;
15293 
15294 		// verify if there is a mod(a, a) case and prepare new expected result
15295 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15296 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15297 		for (glw::GLuint component = 0; component < n_components; ++component)
15298 		{
15299 			glw::GLdouble expected_result_component = expected_result[component];
15300 			glw::GLdouble actual_result_component   = actual_result[component];
15301 			glw::GLdouble argument_1_component		= argument_1[component];
15302 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15303 
15304 			// if coresponding components of arguments are equal and if component of first argument
15305 			// and component of result are equal then expected result must be corrected
15306                         bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15307                                                                       round(argument_1_component / argument_2_component));
15308                         edge_case_present = possible_edge_case &&
15309                                             (m_epsilon > de::abs(argument_2_component - actual_result_component));
15310 			recheck |= edge_case_present;
15311                         corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15312 		}
15313 
15314 		// recheck test result with corrected expected result
15315 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15316 	}
15317 	default:
15318 		return false;
15319 	}
15320 }
15321 
15322 /** Compare contents of transform feedback buffer with expected results
15323  *
15324  * @param function_object Function object
15325  * @param vertex          Vertex index
15326  *
15327  * @return true if all results are as expected, false otherwise
15328  **/
verifyResults(const functionObject& function_object, glw::GLuint vertex)15329 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15330 {
15331 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
15332 	bool				  test_result	  = true;
15333 	const glw::GLuint	 n_results		   = function_object.getResultCount();
15334 	const glw::GLuint	 results_stride   = function_object.getResultStride();
15335 	const glw::GLuint	 results_offset   = vertex * results_stride;
15336 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15337 
15338 	/* Get transform feedback data */
15339 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15340 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15341 
15342 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15343 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15344 
15345 	for (glw::GLuint result = 0; result < n_results; ++result)
15346 	{
15347 		const Utils::_variable_type result_type   = function_object.getResultType(result);
15348 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
15349 
15350 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
15351 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
15352 
15353 		if (compare(result_type, expected_result_src, result_src))
15354 			continue;
15355 
15356 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15357 		{
15358 			test_result = false;
15359 			break;
15360 		}
15361 	}
15362 
15363 	/* Unmap transform feedback buffer */
15364 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15365 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15366 
15367 	if (false == test_result)
15368 	{
15369 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
15370 		const glw::GLuint arguments_offset = vertex * argument_stride;
15371 
15372 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15373 											<< tcu::TestLog::EndMessage;
15374 
15375 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15376 											<< tcu::TestLog::EndMessage;
15377 
15378 		for (glw::GLuint result = 0; result < n_results; ++result)
15379 		{
15380 			const Utils::_variable_type result_type   = function_object.getResultType(result);
15381 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
15382 
15383 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
15384 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
15385 
15386 			logVariableType(result_src, "Result", result_type);
15387 			logVariableType(expected_result_src, "Expected result", result_type);
15388 		}
15389 
15390 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15391 		{
15392 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15393 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
15394 
15395 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15396 		}
15397 
15398 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15399 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
15400 	}
15401 
15402 	return test_result;
15403 }
15404 
15405 /** Constructor.
15406  *
15407  *  @param context Rendering context.
15408  **/
GPUShaderFP64Tests(deqp::Context& context)15409 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15410 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15411 {
15412 	/* Left blank on purpose */
15413 }
15414 
15415 /** Initializes a texture_storage_multisample test group.
15416  *
15417  **/
init(void)15418 void GPUShaderFP64Tests::init(void)
15419 {
15420 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15421 	fp64->addChild(new GPUShaderFP64Test1(m_context));
15422 	fp64->addChild(new GPUShaderFP64Test2(m_context));
15423 	fp64->addChild(new GPUShaderFP64Test3(m_context));
15424 	fp64->addChild(new GPUShaderFP64Test4(m_context));
15425 	fp64->addChild(new GPUShaderFP64Test5(m_context));
15426 	fp64->addChild(new GPUShaderFP64Test6(m_context));
15427 	fp64->addChild(new GPUShaderFP64Test7(m_context));
15428 	fp64->addChild(new GPUShaderFP64Test8(m_context));
15429 	fp64->addChild(new GPUShaderFP64Test9(m_context));
15430 	addChild(fp64);
15431 
15432 	TypeDefinition typeDefinition[] =
15433 	{
15434 		{ "double",  1, 1 },
15435 		{ "dvec2",   1, 2 },
15436 		{ "dvec3",   1, 3 },
15437 		{ "dvec4",   1, 4 },
15438 		{ "dmat2",   2, 2 },
15439 		{ "dmat2x3", 2, 3 },
15440 		{ "dmat2x4", 2, 4 },
15441 		{ "dmat3x2", 3, 2 },
15442 		{ "dmat3",   3, 3 },
15443 		{ "dmat3x4", 3, 4 },
15444 		{ "dmat4x2", 4, 2 },
15445 		{ "dmat4x3", 4, 3 },
15446 		{ "dmat4",   4, 4 }
15447 	};
15448 
15449 	struct BuiltinFunctions
15450 	{
15451 		std::string  name;
15452 		FunctionEnum function;
15453 	} builtinFunctions[] = {
15454 		{ "abs",						FUNCTION_ABS },
15455 		{ "ceil",						FUNCTION_CEIL },
15456 		{ "clamp",						FUNCTION_CLAMP },
15457 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
15458 		{ "cross",						FUNCTION_CROSS },
15459 		{ "determinant",				FUNCTION_DETERMINANT },
15460 		{ "distance",					FUNCTION_DISTANCE },
15461 		{ "dot",						FUNCTION_DOT },
15462 		{ "equal",						FUNCTION_EQUAL },
15463 		{ "faceforward",				FUNCTION_FACEFORWARD },
15464 		{ "floor",						FUNCTION_FLOOR },
15465 		{ "fma",						FUNCTION_FMA },
15466 		{ "fract",						FUNCTION_FRACT },
15467 		{ "frexp",						FUNCTION_FREXP },
15468 		{ "greaterthan",				FUNCTION_GREATERTHAN },
15469 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
15470 		{ "inverse",					FUNCTION_INVERSE },
15471 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
15472 		{ "ldexp",						FUNCTION_LDEXP },
15473 		{ "lessthan",					FUNCTION_LESSTHAN },
15474 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
15475 		{ "length",						FUNCTION_LENGTH },
15476 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
15477 		{ "max",						FUNCTION_MAX },
15478 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
15479 		{ "min",						FUNCTION_MIN },
15480 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
15481 		{ "mix",						FUNCTION_MIX },
15482 		{ "mod",						FUNCTION_MOD },
15483 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
15484 		{ "modf",						FUNCTION_MODF },
15485 		{ "normalize",					FUNCTION_NORMALIZE },
15486 		{ "notequal",					FUNCTION_NOTEQUAL },
15487 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
15488 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
15489 		{ "reflect",					FUNCTION_REFLECT },
15490 		{ "refract",					FUNCTION_REFRACT },
15491 		{ "round",						FUNCTION_ROUND },
15492 		{ "roundeven",					FUNCTION_ROUNDEVEN },
15493 		{ "sign",						FUNCTION_SIGN },
15494 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
15495 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15496 		{ "sqrt",						FUNCTION_SQRT },
15497 		{ "step",						FUNCTION_STEP },
15498 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
15499 		{ "transpose",					FUNCTION_TRANSPOSE },
15500 		{ "trunc",						FUNCTION_TRUNC },
15501 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
15502 		{ "isnan",						FUNCTION_ISNAN },
15503 		{ "isinf",						FUNCTION_ISINF }
15504 	};
15505 
15506 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15507 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15508 	{
15509 		const BuiltinFunctions& bf = builtinFunctions[i];
15510 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15511 		{
15512 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
15513 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15514 		}
15515 	}
15516 	addChild(builin);
15517 }
15518 
15519 } /* glcts namespace */
15520