• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  * \file  gl4GPUShaderFP64Tests.cpp
26  * \brief Implements conformance tests for "GPU Shader FP64" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cGPUShaderFP64Tests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuTestLog.hpp"
34 
35 #include <iomanip>
36 
37 #include "deMath.h"
38 #include "deUniquePtr.hpp"
39 #include "tcuMatrixUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 
42 #include <cstdlib>
43 #include <cstring>
44 #include <limits>
45 #include <memory>
46 
47 namespace gl4cts
48 {
49 
50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9;
51 
52 /** Constructor
53  *
54  * @param context Test context
55  **/
programInfo(deqp::Context & context)56 Utils::programInfo::programInfo(deqp::Context& context)
57 	: m_context(context)
58 	, m_compute_shader_id(0)
59 	, m_fragment_shader_id(0)
60 	, m_geometry_shader_id(0)
61 	, m_program_object_id(0)
62 	, m_tesselation_control_shader_id(0)
63 	, m_tesselation_evaluation_shader_id(0)
64 	, m_vertex_shader_id(0)
65 {
66 	/* Nothing to be done here */
67 }
68 
69 /** Destructor
70  *
71  **/
~programInfo()72 Utils::programInfo::~programInfo()
73 {
74 	/* GL entry points */
75 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
76 
77 	/* Make sure program object is no longer used by GL */
78 	gl.useProgram(0);
79 
80 	/* Clean program object */
81 	if (0 != m_program_object_id)
82 	{
83 		gl.deleteProgram(m_program_object_id);
84 		m_program_object_id = 0;
85 	}
86 
87 	/* Clean shaders */
88 	if (0 != m_compute_shader_id)
89 	{
90 		gl.deleteShader(m_compute_shader_id);
91 		m_compute_shader_id = 0;
92 	}
93 
94 	if (0 != m_fragment_shader_id)
95 	{
96 		gl.deleteShader(m_fragment_shader_id);
97 		m_fragment_shader_id = 0;
98 	}
99 
100 	if (0 != m_geometry_shader_id)
101 	{
102 		gl.deleteShader(m_geometry_shader_id);
103 		m_geometry_shader_id = 0;
104 	}
105 
106 	if (0 != m_tesselation_control_shader_id)
107 	{
108 		gl.deleteShader(m_tesselation_control_shader_id);
109 		m_tesselation_control_shader_id = 0;
110 	}
111 
112 	if (0 != m_tesselation_evaluation_shader_id)
113 	{
114 		gl.deleteShader(m_tesselation_evaluation_shader_id);
115 		m_tesselation_evaluation_shader_id = 0;
116 	}
117 
118 	if (0 != m_vertex_shader_id)
119 	{
120 		gl.deleteShader(m_vertex_shader_id);
121 		m_vertex_shader_id = 0;
122 	}
123 }
124 
125 /** Build program
126  *
127  * @param compute_shader_code                Compute shader source code
128  * @param fragment_shader_code               Fragment shader source code
129  * @param geometry_shader_code               Geometry shader source code
130  * @param tesselation_control_shader_code    Tesselation control shader source code
131  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
132  * @param vertex_shader_code                 Vertex shader source code
133  * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
134  * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
135  **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names)136 void Utils::programInfo::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
137 							   const glw::GLchar* geometry_shader_code,
138 							   const glw::GLchar* tesselation_control_shader_code,
139 							   const glw::GLchar* tesselation_evaluation_shader_code,
140 							   const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names,
141 							   glw::GLuint n_varying_names)
142 {
143 	/* GL entry points */
144 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
145 
146 	/* Create shader objects and compile */
147 	if (0 != compute_shader_code)
148 	{
149 		m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
150 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
151 
152 		compile(m_compute_shader_id, compute_shader_code);
153 	}
154 
155 	if (0 != fragment_shader_code)
156 	{
157 		m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
158 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
159 
160 		compile(m_fragment_shader_id, fragment_shader_code);
161 	}
162 
163 	if (0 != geometry_shader_code)
164 	{
165 		m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
166 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
167 
168 		compile(m_geometry_shader_id, geometry_shader_code);
169 	}
170 
171 	if (0 != tesselation_control_shader_code)
172 	{
173 		m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
174 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
175 
176 		compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
177 	}
178 
179 	if (0 != tesselation_evaluation_shader_code)
180 	{
181 		m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
182 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
183 
184 		compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
185 	}
186 
187 	if (0 != vertex_shader_code)
188 	{
189 		m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
190 		GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
191 
192 		compile(m_vertex_shader_id, vertex_shader_code);
193 	}
194 
195 	/* Create program object */
196 	m_program_object_id = gl.createProgram();
197 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
198 
199 	/* Set up captyured varyings' names */
200 	if (0 != n_varying_names)
201 	{
202 		gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
203 		GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
204 	}
205 
206 	/* Link program */
207 	link();
208 }
209 
210 /** Compile shader
211  *
212  * @param shader_id   Shader object id
213  * @param shader_code Shader source code
214  **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
216 {
217 	/* GL entry points */
218 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
219 
220 	/* Compilation status */
221 	glw::GLint status = GL_FALSE;
222 
223 	/* Set source code */
224 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
225 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
226 
227 	/* Compile */
228 	gl.compileShader(shader_id);
229 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
230 
231 	/* Get compilation status */
232 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
233 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
234 
235 	/* Log compilation error */
236 	if (GL_TRUE != status)
237 	{
238 		glw::GLint				 length = 0;
239 		std::vector<glw::GLchar> message;
240 
241 		/* Error log length */
242 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
243 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
244 
245 		/* Prepare storage */
246 		message.resize(length);
247 
248 		/* Get error log */
249 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
250 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
251 
252 		/* Log */
253 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
254 											<< &message[0] << "\nShader source\n"
255 											<< shader_code << tcu::TestLog::EndMessage;
256 
257 		TCU_FAIL("Failed to compile shader");
258 	}
259 }
260 
261 /** Attach shaders and link program
262  *
263  **/
link() const264 void Utils::programInfo::link() const
265 {
266 	/* GL entry points */
267 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
268 
269 	/* Link status */
270 	glw::GLint status = GL_FALSE;
271 
272 	/* Attach shaders */
273 	if (0 != m_compute_shader_id)
274 	{
275 		gl.attachShader(m_program_object_id, m_compute_shader_id);
276 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
277 	}
278 
279 	if (0 != m_fragment_shader_id)
280 	{
281 		gl.attachShader(m_program_object_id, m_fragment_shader_id);
282 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
283 	}
284 
285 	if (0 != m_geometry_shader_id)
286 	{
287 		gl.attachShader(m_program_object_id, m_geometry_shader_id);
288 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
289 	}
290 
291 	if (0 != m_tesselation_control_shader_id)
292 	{
293 		gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
294 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
295 	}
296 
297 	if (0 != m_tesselation_evaluation_shader_id)
298 	{
299 		gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
300 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
301 	}
302 
303 	if (0 != m_vertex_shader_id)
304 	{
305 		gl.attachShader(m_program_object_id, m_vertex_shader_id);
306 		GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
307 	}
308 
309 	/* Link */
310 	gl.linkProgram(m_program_object_id);
311 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
312 
313 	/* Get link status */
314 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
315 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
316 
317 	/* Log link error */
318 	if (GL_TRUE != status)
319 	{
320 		glw::GLint				 length = 0;
321 		std::vector<glw::GLchar> message;
322 
323 		/* Get error log length */
324 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
325 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
326 
327 		message.resize(length);
328 
329 		/* Get error log */
330 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
331 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
332 
333 		/* Log */
334 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
335 											<< &message[0] << tcu::TestLog::EndMessage;
336 
337 		TCU_FAIL("Failed to link program");
338 	}
339 }
340 
341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision
342  *  matrix types.
343  *
344  *  @param type Variable type to return base type for.
345  *
346  *  @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized.
347  **/
getBaseVariableType(_variable_type type)348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type)
349 {
350 	_variable_type result = VARIABLE_TYPE_UNKNOWN;
351 
352 	switch (type)
353 	{
354 	case VARIABLE_TYPE_BOOL:
355 	{
356 		result = VARIABLE_TYPE_BOOL;
357 
358 		break;
359 	}
360 
361 	case VARIABLE_TYPE_DOUBLE:
362 	case VARIABLE_TYPE_DMAT2:
363 	case VARIABLE_TYPE_DMAT2X3:
364 	case VARIABLE_TYPE_DMAT2X4:
365 	case VARIABLE_TYPE_DMAT3:
366 	case VARIABLE_TYPE_DMAT3X2:
367 	case VARIABLE_TYPE_DMAT3X4:
368 	case VARIABLE_TYPE_DMAT4:
369 	case VARIABLE_TYPE_DMAT4X2:
370 	case VARIABLE_TYPE_DMAT4X3:
371 	case VARIABLE_TYPE_DVEC2:
372 	case VARIABLE_TYPE_DVEC3:
373 	case VARIABLE_TYPE_DVEC4:
374 	{
375 		result = VARIABLE_TYPE_DOUBLE;
376 
377 		break;
378 	}
379 
380 	case VARIABLE_TYPE_INT:
381 	case VARIABLE_TYPE_IVEC2:
382 	case VARIABLE_TYPE_IVEC3:
383 	case VARIABLE_TYPE_IVEC4:
384 	{
385 		result = VARIABLE_TYPE_INT;
386 
387 		break;
388 	}
389 
390 	case VARIABLE_TYPE_UINT:
391 	case VARIABLE_TYPE_UVEC2:
392 	case VARIABLE_TYPE_UVEC3:
393 	case VARIABLE_TYPE_UVEC4:
394 	{
395 		result = VARIABLE_TYPE_UINT;
396 
397 		break;
398 	}
399 
400 	case VARIABLE_TYPE_FLOAT:
401 	case VARIABLE_TYPE_MAT2:
402 	case VARIABLE_TYPE_MAT2X3:
403 	case VARIABLE_TYPE_MAT2X4:
404 	case VARIABLE_TYPE_MAT3:
405 	case VARIABLE_TYPE_MAT3X2:
406 	case VARIABLE_TYPE_MAT3X4:
407 	case VARIABLE_TYPE_MAT4:
408 	case VARIABLE_TYPE_MAT4X2:
409 	case VARIABLE_TYPE_MAT4X3:
410 	case VARIABLE_TYPE_VEC2:
411 	case VARIABLE_TYPE_VEC3:
412 	case VARIABLE_TYPE_VEC4:
413 	{
414 		result = VARIABLE_TYPE_FLOAT;
415 
416 		break;
417 	}
418 
419 	default:
420 	{
421 		TCU_FAIL("Unrecognized variable type");
422 	}
423 	} /* switch (type) */
424 
425 	return result;
426 }
427 
428 /** Returns size (in bytes) of a single component of a base variable type.
429  *
430  *  @param type Base variable type to use for the query.
431  *
432  *  @return Requested value or 0 if @param type was not recognized.
433  **/
getBaseVariableTypeComponentSize(_variable_type type)434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type)
435 {
436 	unsigned int result = 0;
437 
438 	switch (type)
439 	{
440 	case VARIABLE_TYPE_BOOL:
441 		result = sizeof(bool);
442 		break;
443 	case VARIABLE_TYPE_DOUBLE:
444 		result = sizeof(double);
445 		break;
446 	case VARIABLE_TYPE_FLOAT:
447 		result = sizeof(float);
448 		break;
449 	case VARIABLE_TYPE_INT:
450 		result = sizeof(int);
451 		break;
452 	case VARIABLE_TYPE_UINT:
453 		result = sizeof(unsigned int);
454 		break;
455 
456 	default:
457 	{
458 		TCU_FAIL("Unrecognized variable type");
459 	}
460 	} /* switch (type) */
461 
462 	return result;
463 }
464 
465 /** Returns component, corresponding to user-specified index
466  *  (eg. index:0 corresponds to 'x', index:1 corresponds to 'y',
467  *  and so on.
468  *
469  *  @param index Component index.
470  *
471  *  @return As per description.
472  **/
getComponentAtIndex(unsigned int index)473 unsigned char Utils::getComponentAtIndex(unsigned int index)
474 {
475 	unsigned char result = '?';
476 
477 	switch (index)
478 	{
479 	case 0:
480 		result = 'x';
481 		break;
482 	case 1:
483 		result = 'y';
484 		break;
485 	case 2:
486 		result = 'z';
487 		break;
488 	case 3:
489 		result = 'w';
490 		break;
491 
492 	default:
493 	{
494 		TCU_FAIL("Unrecognized component index");
495 	}
496 	}
497 
498 	return result;
499 }
500 
501 /** Get _variable_type representing double-precision type with given dimmensions
502  *
503  * @param n_columns Number of columns
504  * @param n_row     Number of rows
505  *
506  * @return Corresponding _variable_type
507  **/
getDoubleVariableType(glw::GLuint n_columns,glw::GLuint n_rows)508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
509 {
510 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
511 
512 	static const _variable_type types[4][4] = {
513 		{ VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 },
514 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 },
515 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 },
516 		{ VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 }
517 	};
518 
519 	type = types[n_columns - 1][n_rows - 1];
520 
521 	return type;
522 }
523 
524 /** Returns a single-precision equivalent of a double-precision floating-point variable
525  *  type.
526  *
527  *  @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
528  *              are accepted.
529  *
530  *  @return Requested GLSL type.
531  **/
getFPVariableTypeStringForVariableType(_variable_type type)532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
533 {
534 	std::string result = "[?]";
535 
536 	switch (type)
537 	{
538 	case VARIABLE_TYPE_DOUBLE:
539 		result = "float";
540 		break;
541 	case VARIABLE_TYPE_DMAT2:
542 		result = "mat2";
543 		break;
544 	case VARIABLE_TYPE_DMAT2X3:
545 		result = "mat2x3";
546 		break;
547 	case VARIABLE_TYPE_DMAT2X4:
548 		result = "mat2x4";
549 		break;
550 	case VARIABLE_TYPE_DMAT3:
551 		result = "mat3";
552 		break;
553 	case VARIABLE_TYPE_DMAT3X2:
554 		result = "mat3x2";
555 		break;
556 	case VARIABLE_TYPE_DMAT3X4:
557 		result = "mat3x4";
558 		break;
559 	case VARIABLE_TYPE_DMAT4:
560 		result = "mat4";
561 		break;
562 	case VARIABLE_TYPE_DMAT4X2:
563 		result = "mat4x2";
564 		break;
565 	case VARIABLE_TYPE_DMAT4X3:
566 		result = "mat4x3";
567 		break;
568 	case VARIABLE_TYPE_DVEC2:
569 		result = "vec2";
570 		break;
571 	case VARIABLE_TYPE_DVEC3:
572 		result = "vec3";
573 		break;
574 	case VARIABLE_TYPE_DVEC4:
575 		result = "vec4";
576 		break;
577 
578 	default:
579 	{
580 		TCU_FAIL("Unrecognized variable type");
581 	}
582 	} /* switch (type) */
583 
584 	return result;
585 }
586 
587 /** Returns GL data type enum corresponding to user-provided base variable type.
588  *
589  *  @param type Base variable type to return corresponding GLenum value for.
590  *
591  *  @return Corresponding GLenum value or GL_NONE if the input value was not
592  *          recognized.
593  **/
getGLDataTypeOfBaseVariableType(_variable_type type)594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
595 {
596 	glw::GLenum result = GL_NONE;
597 
598 	switch (type)
599 	{
600 	case VARIABLE_TYPE_BOOL:
601 		result = GL_BOOL;
602 		break;
603 	case VARIABLE_TYPE_DOUBLE:
604 		result = GL_DOUBLE;
605 		break;
606 	case VARIABLE_TYPE_FLOAT:
607 		result = GL_FLOAT;
608 		break;
609 	case VARIABLE_TYPE_INT:
610 		result = GL_INT;
611 		break;
612 	case VARIABLE_TYPE_UINT:
613 		result = GL_UNSIGNED_INT;
614 		break;
615 
616 	default:
617 	{
618 		TCU_FAIL("Unrecognized variable type");
619 	}
620 	}
621 
622 	return result;
623 }
624 
625 /** Return GLenum representing given <type>
626  *
627  * @param type Type of variable
628  *
629  * @return GL enumeration
630  **/
getGLDataTypeOfVariableType(_variable_type type)631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
632 {
633 	glw::GLenum result = GL_NONE;
634 
635 	switch (type)
636 	{
637 	case VARIABLE_TYPE_BOOL:
638 		result = GL_BOOL;
639 		break;
640 	case VARIABLE_TYPE_DOUBLE:
641 		result = GL_DOUBLE;
642 		break;
643 	case VARIABLE_TYPE_DMAT2:
644 		result = GL_DOUBLE_MAT2;
645 		break;
646 	case VARIABLE_TYPE_DMAT2X3:
647 		result = GL_DOUBLE_MAT2x3;
648 		break;
649 	case VARIABLE_TYPE_DMAT2X4:
650 		result = GL_DOUBLE_MAT2x4;
651 		break;
652 	case VARIABLE_TYPE_DMAT3:
653 		result = GL_DOUBLE_MAT3;
654 		break;
655 	case VARIABLE_TYPE_DMAT3X2:
656 		result = GL_DOUBLE_MAT3x2;
657 		break;
658 	case VARIABLE_TYPE_DMAT3X4:
659 		result = GL_DOUBLE_MAT3x4;
660 		break;
661 	case VARIABLE_TYPE_DMAT4:
662 		result = GL_DOUBLE_MAT4;
663 		break;
664 	case VARIABLE_TYPE_DMAT4X2:
665 		result = GL_DOUBLE_MAT4x2;
666 		break;
667 	case VARIABLE_TYPE_DMAT4X3:
668 		result = GL_DOUBLE_MAT4x3;
669 		break;
670 	case VARIABLE_TYPE_DVEC2:
671 		result = GL_DOUBLE_VEC2;
672 		break;
673 	case VARIABLE_TYPE_DVEC3:
674 		result = GL_DOUBLE_VEC3;
675 		break;
676 	case VARIABLE_TYPE_DVEC4:
677 		result = GL_DOUBLE_VEC4;
678 		break;
679 	case VARIABLE_TYPE_FLOAT:
680 		result = GL_FLOAT;
681 		break;
682 	case VARIABLE_TYPE_INT:
683 		result = GL_INT;
684 		break;
685 	case VARIABLE_TYPE_IVEC2:
686 		result = GL_INT_VEC2;
687 		break;
688 	case VARIABLE_TYPE_IVEC3:
689 		result = GL_INT_VEC3;
690 		break;
691 	case VARIABLE_TYPE_IVEC4:
692 		result = GL_INT_VEC4;
693 		break;
694 	case VARIABLE_TYPE_MAT2:
695 		result = GL_FLOAT_MAT2;
696 		break;
697 	case VARIABLE_TYPE_MAT2X3:
698 		result = GL_FLOAT_MAT2x3;
699 		break;
700 	case VARIABLE_TYPE_MAT2X4:
701 		result = GL_FLOAT_MAT2x4;
702 		break;
703 	case VARIABLE_TYPE_MAT3:
704 		result = GL_FLOAT_MAT3;
705 		break;
706 	case VARIABLE_TYPE_MAT3X2:
707 		result = GL_FLOAT_MAT3x2;
708 		break;
709 	case VARIABLE_TYPE_MAT3X4:
710 		result = GL_FLOAT_MAT3x4;
711 		break;
712 	case VARIABLE_TYPE_MAT4:
713 		result = GL_FLOAT_MAT4;
714 		break;
715 	case VARIABLE_TYPE_MAT4X2:
716 		result = GL_FLOAT_MAT4x2;
717 		break;
718 	case VARIABLE_TYPE_MAT4X3:
719 		result = GL_FLOAT_MAT4x3;
720 		break;
721 	case VARIABLE_TYPE_UINT:
722 		result = GL_UNSIGNED_INT;
723 		break;
724 	case VARIABLE_TYPE_UVEC2:
725 		result = GL_UNSIGNED_INT_VEC2;
726 		break;
727 	case VARIABLE_TYPE_UVEC3:
728 		result = GL_UNSIGNED_INT_VEC3;
729 		break;
730 	case VARIABLE_TYPE_UVEC4:
731 		result = GL_UNSIGNED_INT_VEC4;
732 		break;
733 	case VARIABLE_TYPE_VEC2:
734 		result = GL_FLOAT_VEC2;
735 		break;
736 	case VARIABLE_TYPE_VEC3:
737 		result = GL_FLOAT_VEC3;
738 		break;
739 	case VARIABLE_TYPE_VEC4:
740 		result = GL_FLOAT_VEC4;
741 		break;
742 
743 	default:
744 	{
745 		TCU_FAIL("Unrecognized variable type");
746 	}
747 	}
748 
749 	return result;
750 }
751 
752 /** Get _variable_type representing integer type with given dimmensions
753  *
754  * @param n_columns Number of columns
755  * @param n_row     Number of rows
756  *
757  * @return Corresponding _variable_type
758  **/
getIntVariableType(glw::GLuint n_columns,glw::GLuint n_rows)759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
760 {
761 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
762 
763 	static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
764 											 VARIABLE_TYPE_IVEC4 };
765 
766 	if (1 != n_columns)
767 	{
768 		TCU_FAIL("Not implemented");
769 	}
770 	else
771 	{
772 		type = types[n_rows - 1];
773 	}
774 
775 	return type;
776 }
777 
778 /** Returns te number of components that variables defined with user-specified type
779  *  support. For matrix types, total amount of values accessible for the type will be
780  *  returned.
781  *
782  *  @param type Variable type to return the described vale for.
783  *
784  *  @return As per description or 0 if @param type was not recognized.
785  */
getNumberOfComponentsForVariableType(_variable_type type)786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
787 {
788 	unsigned int result = 0;
789 
790 	switch (type)
791 	{
792 	case VARIABLE_TYPE_BOOL:
793 	case VARIABLE_TYPE_DOUBLE:
794 	case VARIABLE_TYPE_FLOAT:
795 	case VARIABLE_TYPE_INT:
796 	case VARIABLE_TYPE_UINT:
797 	{
798 		result = 1;
799 
800 		break;
801 	}
802 
803 	case VARIABLE_TYPE_DVEC2:
804 	case VARIABLE_TYPE_IVEC2:
805 	case VARIABLE_TYPE_UVEC2:
806 	case VARIABLE_TYPE_VEC2:
807 	{
808 		result = 2;
809 
810 		break;
811 	}
812 
813 	case VARIABLE_TYPE_DVEC3:
814 	case VARIABLE_TYPE_IVEC3:
815 	case VARIABLE_TYPE_UVEC3:
816 	case VARIABLE_TYPE_VEC3:
817 	{
818 		result = 3;
819 
820 		break;
821 	}
822 
823 	case VARIABLE_TYPE_DVEC4:
824 	case VARIABLE_TYPE_IVEC4:
825 	case VARIABLE_TYPE_UVEC4:
826 	case VARIABLE_TYPE_VEC4:
827 	{
828 		result = 4;
829 
830 		break;
831 	}
832 
833 	case VARIABLE_TYPE_DMAT2:
834 	case VARIABLE_TYPE_MAT2:
835 	{
836 		result = 2 * 2;
837 
838 		break;
839 	}
840 
841 	case VARIABLE_TYPE_DMAT2X3:
842 	case VARIABLE_TYPE_DMAT3X2:
843 	case VARIABLE_TYPE_MAT2X3:
844 	case VARIABLE_TYPE_MAT3X2:
845 	{
846 		result = 2 * 3;
847 
848 		break;
849 	}
850 
851 	case VARIABLE_TYPE_DMAT2X4:
852 	case VARIABLE_TYPE_DMAT4X2:
853 	case VARIABLE_TYPE_MAT2X4:
854 	case VARIABLE_TYPE_MAT4X2:
855 	{
856 		result = 2 * 4;
857 
858 		break;
859 	}
860 
861 	case VARIABLE_TYPE_DMAT3:
862 	case VARIABLE_TYPE_MAT3:
863 	{
864 		result = 3 * 3;
865 
866 		break;
867 	}
868 
869 	case VARIABLE_TYPE_DMAT3X4:
870 	case VARIABLE_TYPE_DMAT4X3:
871 	case VARIABLE_TYPE_MAT3X4:
872 	case VARIABLE_TYPE_MAT4X3:
873 	{
874 		result = 3 * 4;
875 
876 		break;
877 	}
878 
879 	case VARIABLE_TYPE_DMAT4:
880 	case VARIABLE_TYPE_MAT4:
881 	{
882 		result = 4 * 4;
883 
884 		break;
885 	}
886 
887 	default:
888 	{
889 		TCU_FAIL("Unrecognized type");
890 	}
891 	} /* switch (type) */
892 
893 	return result;
894 }
895 
896 /** Returns number of columns user-specified matrix variable type describes.
897  *
898  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
899  *              values are valid.
900  *
901  *  @return As per description.
902  **/
getNumberOfColumnsForVariableType(_variable_type type)903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
904 {
905 	unsigned int result = 0;
906 
907 	switch (type)
908 	{
909 	case VARIABLE_TYPE_BOOL:
910 	case VARIABLE_TYPE_DOUBLE:
911 	case VARIABLE_TYPE_FLOAT:
912 	case VARIABLE_TYPE_INT:
913 	case VARIABLE_TYPE_UINT:
914 	case VARIABLE_TYPE_DVEC2:
915 	case VARIABLE_TYPE_IVEC2:
916 	case VARIABLE_TYPE_UVEC2:
917 	case VARIABLE_TYPE_VEC2:
918 	case VARIABLE_TYPE_DVEC3:
919 	case VARIABLE_TYPE_IVEC3:
920 	case VARIABLE_TYPE_UVEC3:
921 	case VARIABLE_TYPE_VEC3:
922 	case VARIABLE_TYPE_DVEC4:
923 	case VARIABLE_TYPE_IVEC4:
924 	case VARIABLE_TYPE_UVEC4:
925 	case VARIABLE_TYPE_VEC4:
926 	{
927 		result = 1;
928 
929 		break;
930 	}
931 
932 	case VARIABLE_TYPE_DMAT2:
933 	case VARIABLE_TYPE_DMAT2X3:
934 	case VARIABLE_TYPE_DMAT2X4:
935 	case VARIABLE_TYPE_MAT2:
936 	case VARIABLE_TYPE_MAT2X3:
937 	case VARIABLE_TYPE_MAT2X4:
938 	{
939 		result = 2;
940 
941 		break;
942 	}
943 
944 	case VARIABLE_TYPE_DMAT3:
945 	case VARIABLE_TYPE_DMAT3X2:
946 	case VARIABLE_TYPE_DMAT3X4:
947 	case VARIABLE_TYPE_MAT3:
948 	case VARIABLE_TYPE_MAT3X2:
949 	case VARIABLE_TYPE_MAT3X4:
950 	{
951 		result = 3;
952 
953 		break;
954 	}
955 
956 	case VARIABLE_TYPE_DMAT4:
957 	case VARIABLE_TYPE_DMAT4X2:
958 	case VARIABLE_TYPE_DMAT4X3:
959 	case VARIABLE_TYPE_MAT4:
960 	case VARIABLE_TYPE_MAT4X2:
961 	case VARIABLE_TYPE_MAT4X3:
962 	{
963 		result = 4;
964 
965 		break;
966 	}
967 
968 	default:
969 	{
970 		TCU_FAIL("Unrecognized type");
971 	}
972 	} /* switch (type) */
973 
974 	return result;
975 }
976 
977 /** Returns maximum number of uniform locations taken by user-specified double-precision
978  *  variable type.
979  *
980  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
981  *
982  *  @return As per description.
983  **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
985 {
986 	unsigned int result = 0;
987 
988 	switch (type)
989 	{
990 	case VARIABLE_TYPE_DOUBLE:
991 		result = 1;
992 		break;
993 	case VARIABLE_TYPE_DVEC2:
994 		result = 1;
995 		break;
996 	case VARIABLE_TYPE_DVEC3:
997 		result = 2;
998 		break;
999 	case VARIABLE_TYPE_DVEC4:
1000 		result = 2;
1001 		break;
1002 	case VARIABLE_TYPE_DMAT2:
1003 		result = 2;
1004 		break;
1005 	case VARIABLE_TYPE_DMAT2X3:
1006 		result = 6;
1007 		break;
1008 	case VARIABLE_TYPE_DMAT2X4:
1009 		result = 8;
1010 		break;
1011 	case VARIABLE_TYPE_DMAT3:
1012 		result = 6;
1013 		break;
1014 	case VARIABLE_TYPE_DMAT3X2:
1015 		result = 4;
1016 		break;
1017 	case VARIABLE_TYPE_DMAT3X4:
1018 		result = 8;
1019 		break;
1020 	case VARIABLE_TYPE_DMAT4:
1021 		result = 8;
1022 		break;
1023 	case VARIABLE_TYPE_DMAT4X2:
1024 		result = 4;
1025 		break;
1026 	case VARIABLE_TYPE_DMAT4X3:
1027 		result = 6;
1028 		break;
1029 
1030 	default:
1031 	{
1032 		TCU_FAIL("Unrecognized type");
1033 	}
1034 	} /* switch (type) */
1035 
1036 	return result;
1037 }
1038 
1039 /** Get number of rows for given variable type
1040  *
1041  * @param type Type of variable
1042  *
1043  * @return Number of rows
1044  **/
getNumberOfRowsForVariableType(_variable_type type)1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1046 {
1047 	unsigned int result = 0;
1048 
1049 	switch (type)
1050 	{
1051 	case VARIABLE_TYPE_BOOL:
1052 	case VARIABLE_TYPE_DOUBLE:
1053 	case VARIABLE_TYPE_FLOAT:
1054 	case VARIABLE_TYPE_INT:
1055 	case VARIABLE_TYPE_UINT:
1056 	{
1057 		result = 1;
1058 
1059 		break;
1060 	}
1061 
1062 	case VARIABLE_TYPE_DVEC2:
1063 	case VARIABLE_TYPE_IVEC2:
1064 	case VARIABLE_TYPE_UVEC2:
1065 	case VARIABLE_TYPE_VEC2:
1066 	case VARIABLE_TYPE_DMAT2:
1067 	case VARIABLE_TYPE_DMAT3X2:
1068 	case VARIABLE_TYPE_DMAT4X2:
1069 	case VARIABLE_TYPE_MAT2:
1070 	case VARIABLE_TYPE_MAT3X2:
1071 	case VARIABLE_TYPE_MAT4X2:
1072 	{
1073 		result = 2;
1074 
1075 		break;
1076 	}
1077 
1078 	case VARIABLE_TYPE_DVEC3:
1079 	case VARIABLE_TYPE_IVEC3:
1080 	case VARIABLE_TYPE_UVEC3:
1081 	case VARIABLE_TYPE_VEC3:
1082 	case VARIABLE_TYPE_DMAT2X3:
1083 	case VARIABLE_TYPE_DMAT3:
1084 	case VARIABLE_TYPE_DMAT4X3:
1085 	case VARIABLE_TYPE_MAT2X3:
1086 	case VARIABLE_TYPE_MAT3:
1087 	case VARIABLE_TYPE_MAT4X3:
1088 	{
1089 		result = 3;
1090 
1091 		break;
1092 	}
1093 
1094 	case VARIABLE_TYPE_DVEC4:
1095 	case VARIABLE_TYPE_IVEC4:
1096 	case VARIABLE_TYPE_UVEC4:
1097 	case VARIABLE_TYPE_VEC4:
1098 	case VARIABLE_TYPE_DMAT2X4:
1099 	case VARIABLE_TYPE_DMAT3X4:
1100 	case VARIABLE_TYPE_DMAT4:
1101 	case VARIABLE_TYPE_MAT2X4:
1102 	case VARIABLE_TYPE_MAT3X4:
1103 	case VARIABLE_TYPE_MAT4:
1104 	{
1105 		result = 4;
1106 
1107 		break;
1108 	}
1109 
1110 	default:
1111 	{
1112 		TCU_FAIL("Unrecognized type");
1113 	}
1114 	} /* switch (type) */
1115 
1116 	return result;
1117 }
1118 
1119 /** Returns variable type of a matrix constructed by multiplying two matrices.
1120  *
1121  *  @param type_matrix_a L-side matrix type.
1122  *  @param type_matrix_b R-side matrix type.
1123  *
1124  *  @return As per description.
1125  **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,_variable_type type_matrix_b)1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1127 																	 _variable_type type_matrix_b)
1128 {
1129 	const unsigned int	n_a_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1130 	const unsigned int	n_a_components   = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1131 	const unsigned int	n_a_rows		   = n_a_components / n_a_columns;
1132 	const unsigned int	n_b_columns	  = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1133 	const unsigned int	n_result_columns = n_b_columns;
1134 	const unsigned int	n_result_rows	= n_a_rows;
1135 	Utils::_variable_type result;
1136 
1137 	switch (n_result_columns)
1138 	{
1139 	case 2:
1140 	{
1141 		switch (n_result_rows)
1142 		{
1143 		case 2:
1144 			result = VARIABLE_TYPE_DMAT2;
1145 			break;
1146 		case 3:
1147 			result = VARIABLE_TYPE_DMAT2X3;
1148 			break;
1149 		case 4:
1150 			result = VARIABLE_TYPE_DMAT2X4;
1151 			break;
1152 
1153 		default:
1154 		{
1155 			TCU_FAIL("Unrecognized amount of rows in result variable");
1156 		}
1157 		} /* switch (n_result_rows) */
1158 
1159 		break;
1160 	} /* case 2: */
1161 
1162 	case 3:
1163 	{
1164 		switch (n_result_rows)
1165 		{
1166 		case 2:
1167 			result = VARIABLE_TYPE_DMAT3X2;
1168 			break;
1169 		case 3:
1170 			result = VARIABLE_TYPE_DMAT3;
1171 			break;
1172 		case 4:
1173 			result = VARIABLE_TYPE_DMAT3X4;
1174 			break;
1175 
1176 		default:
1177 		{
1178 			TCU_FAIL("Unrecognized amount of rows in result variable");
1179 		}
1180 		} /* switch (n_result_rows) */
1181 
1182 		break;
1183 	} /* case 3: */
1184 
1185 	case 4:
1186 	{
1187 		switch (n_result_rows)
1188 		{
1189 		case 2:
1190 			result = VARIABLE_TYPE_DMAT4X2;
1191 			break;
1192 		case 3:
1193 			result = VARIABLE_TYPE_DMAT4X3;
1194 			break;
1195 		case 4:
1196 			result = VARIABLE_TYPE_DMAT4;
1197 			break;
1198 
1199 		default:
1200 		{
1201 			TCU_FAIL("Unrecognized amount of rows in result variable");
1202 		}
1203 		} /* switch (n_result_rows) */
1204 
1205 		break;
1206 	} /* case 4: */
1207 
1208 	default:
1209 	{
1210 		TCU_FAIL("Unrecognized amount of columns in result variable");
1211 	}
1212 	} /* switch (n_result_columns) */
1213 
1214 	/* Done */
1215 	return result;
1216 }
1217 
1218 /** Returns a string holding the value represented by user-provided variable, for which
1219  *  the data are represented in @param type variable type.
1220  *
1221  *  @return As per description.
1222  **/
getStringForVariableTypeValue(_variable_type type,const unsigned char * data_ptr)1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)
1224 {
1225 	std::stringstream result_sstream;
1226 
1227 	switch (type)
1228 	{
1229 	case VARIABLE_TYPE_BOOL:
1230 		result_sstream << *((bool*)data_ptr);
1231 		break;
1232 	case VARIABLE_TYPE_DOUBLE:
1233 		result_sstream << *((double*)data_ptr);
1234 		break;
1235 	case VARIABLE_TYPE_FLOAT:
1236 		result_sstream << *((float*)data_ptr);
1237 		break;
1238 	case VARIABLE_TYPE_INT:
1239 		result_sstream << *((int*)data_ptr);
1240 		break;
1241 	case VARIABLE_TYPE_UINT:
1242 		result_sstream << *((unsigned int*)data_ptr);
1243 		break;
1244 
1245 	default:
1246 	{
1247 		TCU_FAIL("Unrecognized variable type requested");
1248 	}
1249 	} /* switch (type) */
1250 
1251 	return result_sstream.str();
1252 }
1253 
1254 /** Returns variable type of a transposed matrix of user-specified variable type.
1255  *
1256  *  @param type Variable type of the matrix to be transposed.
1257  *
1258  *  @return Transposed matrix variable type.
1259  **/
getTransposedMatrixVariableType(Utils::_variable_type type)1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1261 {
1262 	Utils::_variable_type result;
1263 
1264 	switch (type)
1265 	{
1266 	case VARIABLE_TYPE_DMAT2:
1267 		result = VARIABLE_TYPE_DMAT2;
1268 		break;
1269 	case VARIABLE_TYPE_DMAT2X3:
1270 		result = VARIABLE_TYPE_DMAT3X2;
1271 		break;
1272 	case VARIABLE_TYPE_DMAT2X4:
1273 		result = VARIABLE_TYPE_DMAT4X2;
1274 		break;
1275 	case VARIABLE_TYPE_DMAT3:
1276 		result = VARIABLE_TYPE_DMAT3;
1277 		break;
1278 	case VARIABLE_TYPE_DMAT3X2:
1279 		result = VARIABLE_TYPE_DMAT2X3;
1280 		break;
1281 	case VARIABLE_TYPE_DMAT3X4:
1282 		result = VARIABLE_TYPE_DMAT4X3;
1283 		break;
1284 	case VARIABLE_TYPE_DMAT4:
1285 		result = VARIABLE_TYPE_DMAT4;
1286 		break;
1287 	case VARIABLE_TYPE_DMAT4X2:
1288 		result = VARIABLE_TYPE_DMAT2X4;
1289 		break;
1290 	case VARIABLE_TYPE_DMAT4X3:
1291 		result = VARIABLE_TYPE_DMAT3X4;
1292 		break;
1293 
1294 	default:
1295 	{
1296 		TCU_FAIL("Unrecognized double-precision matrix variable type.");
1297 	}
1298 	} /* switch (type) */
1299 
1300 	return result;
1301 }
1302 
1303 /** Get _variable_type representing unsigned integer type with given dimmensions
1304  *
1305  * @param n_columns Number of columns
1306  * @param n_row     Number of rows
1307  *
1308  * @return Corresponding _variable_type
1309  **/
getUintVariableType(glw::GLuint n_columns,glw::GLuint n_rows)1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1311 {
1312 	Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1313 
1314 	static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1315 											 VARIABLE_TYPE_UVEC4 };
1316 
1317 	if (1 != n_columns)
1318 	{
1319 		TCU_FAIL("Not implemented");
1320 	}
1321 	else
1322 	{
1323 		type = types[n_rows - 1];
1324 	}
1325 
1326 	return type;
1327 }
1328 
1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1330  *  variable type.
1331  *
1332  *  @param type Variable type to use for the query.
1333  *
1334  *  @return Requested GLSL keyword or [?] if @param type was not recognized.
1335  **/
getVariableTypeString(_variable_type type)1336 std::string Utils::getVariableTypeString(_variable_type type)
1337 {
1338 	std::string result = "[?]";
1339 
1340 	switch (type)
1341 	{
1342 	case VARIABLE_TYPE_BOOL:
1343 		result = "bool";
1344 		break;
1345 	case VARIABLE_TYPE_BVEC2:
1346 		result = "bvec2";
1347 		break;
1348 	case VARIABLE_TYPE_BVEC3:
1349 		result = "bvec3";
1350 		break;
1351 	case VARIABLE_TYPE_BVEC4:
1352 		result = "bvec4";
1353 		break;
1354 	case VARIABLE_TYPE_DOUBLE:
1355 		result = "double";
1356 		break;
1357 	case VARIABLE_TYPE_DMAT2:
1358 		result = "dmat2";
1359 		break;
1360 	case VARIABLE_TYPE_DMAT2X3:
1361 		result = "dmat2x3";
1362 		break;
1363 	case VARIABLE_TYPE_DMAT2X4:
1364 		result = "dmat2x4";
1365 		break;
1366 	case VARIABLE_TYPE_DMAT3:
1367 		result = "dmat3";
1368 		break;
1369 	case VARIABLE_TYPE_DMAT3X2:
1370 		result = "dmat3x2";
1371 		break;
1372 	case VARIABLE_TYPE_DMAT3X4:
1373 		result = "dmat3x4";
1374 		break;
1375 	case VARIABLE_TYPE_DMAT4:
1376 		result = "dmat4";
1377 		break;
1378 	case VARIABLE_TYPE_DMAT4X2:
1379 		result = "dmat4x2";
1380 		break;
1381 	case VARIABLE_TYPE_DMAT4X3:
1382 		result = "dmat4x3";
1383 		break;
1384 	case VARIABLE_TYPE_DVEC2:
1385 		result = "dvec2";
1386 		break;
1387 	case VARIABLE_TYPE_DVEC3:
1388 		result = "dvec3";
1389 		break;
1390 	case VARIABLE_TYPE_DVEC4:
1391 		result = "dvec4";
1392 		break;
1393 	case VARIABLE_TYPE_FLOAT:
1394 		result = "float";
1395 		break;
1396 	case VARIABLE_TYPE_INT:
1397 		result = "int";
1398 		break;
1399 	case VARIABLE_TYPE_IVEC2:
1400 		result = "ivec2";
1401 		break;
1402 	case VARIABLE_TYPE_IVEC3:
1403 		result = "ivec3";
1404 		break;
1405 	case VARIABLE_TYPE_IVEC4:
1406 		result = "ivec4";
1407 		break;
1408 	case VARIABLE_TYPE_MAT2:
1409 		result = "mat2";
1410 		break;
1411 	case VARIABLE_TYPE_MAT2X3:
1412 		result = "mat2x3";
1413 		break;
1414 	case VARIABLE_TYPE_MAT2X4:
1415 		result = "mat2x4";
1416 		break;
1417 	case VARIABLE_TYPE_MAT3:
1418 		result = "mat3";
1419 		break;
1420 	case VARIABLE_TYPE_MAT3X2:
1421 		result = "mat3x2";
1422 		break;
1423 	case VARIABLE_TYPE_MAT3X4:
1424 		result = "mat3x4";
1425 		break;
1426 	case VARIABLE_TYPE_MAT4:
1427 		result = "mat4";
1428 		break;
1429 	case VARIABLE_TYPE_MAT4X2:
1430 		result = "mat4x2";
1431 		break;
1432 	case VARIABLE_TYPE_MAT4X3:
1433 		result = "mat4x3";
1434 		break;
1435 	case VARIABLE_TYPE_UINT:
1436 		result = "uint";
1437 		break;
1438 	case VARIABLE_TYPE_UVEC2:
1439 		result = "uvec2";
1440 		break;
1441 	case VARIABLE_TYPE_UVEC3:
1442 		result = "uvec3";
1443 		break;
1444 	case VARIABLE_TYPE_UVEC4:
1445 		result = "uvec4";
1446 		break;
1447 	case VARIABLE_TYPE_VEC2:
1448 		result = "vec2";
1449 		break;
1450 	case VARIABLE_TYPE_VEC3:
1451 		result = "vec3";
1452 		break;
1453 	case VARIABLE_TYPE_VEC4:
1454 		result = "vec4";
1455 		break;
1456 
1457 	default:
1458 	{
1459 		TCU_FAIL("Unrecognized variable type");
1460 	}
1461 	} /* switch (type) */
1462 
1463 	return result;
1464 }
1465 
1466 /** Check if GL context meets version requirements
1467  *
1468  * @param gl             Functions
1469  * @param required_major Minimum required MAJOR_VERSION
1470  * @param required_minor Minimum required MINOR_VERSION
1471  *
1472  * @return true if GL context version is at least as requested, false otherwise
1473  **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
1475 {
1476 	glw::GLint major = 0;
1477 	glw::GLint minor = 0;
1478 
1479 	gl.getIntegerv(GL_MAJOR_VERSION, &major);
1480 	gl.getIntegerv(GL_MINOR_VERSION, &minor);
1481 
1482 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483 
1484 	if (major > required_major)
1485 	{
1486 		/* Major is higher than required one */
1487 		return true;
1488 	}
1489 	else if (major == required_major)
1490 	{
1491 		if (minor >= required_minor)
1492 		{
1493 			/* Major is equal to required one */
1494 			/* Minor is higher than or equal to required one */
1495 			return true;
1496 		}
1497 		else
1498 		{
1499 			/* Major is equal to required one */
1500 			/* Minor is lower than required one */
1501 			return false;
1502 		}
1503 	}
1504 	else
1505 	{
1506 		/* Major is lower than required one */
1507 		return false;
1508 	}
1509 }
1510 
1511 /** Tells whether user-specified variable type corresponds to a matrix type.
1512  *
1513  *  @param type Variable type to use for the query.
1514  *
1515  *  @return true if the variable type describes a matrix, false otherwise.
1516  **/
isMatrixVariableType(_variable_type type)1517 bool Utils::isMatrixVariableType(_variable_type type)
1518 {
1519 	return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1520 			type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1521 			type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1522 			type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1523 			type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1524 			type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1525 }
1526 
1527 /** Tells whether user-specified variable type is scalar.
1528  *
1529  *  @return true if @param type is a scalar variable type, false otherwise.
1530  **/
isScalarVariableType(_variable_type type)1531 bool Utils::isScalarVariableType(_variable_type type)
1532 {
1533 	bool result = false;
1534 
1535 	switch (type)
1536 	{
1537 	case VARIABLE_TYPE_BOOL:
1538 		result = true;
1539 		break;
1540 	case VARIABLE_TYPE_DOUBLE:
1541 		result = true;
1542 		break;
1543 	case VARIABLE_TYPE_FLOAT:
1544 		result = true;
1545 		break;
1546 	case VARIABLE_TYPE_INT:
1547 		result = true;
1548 		break;
1549 	case VARIABLE_TYPE_UINT:
1550 		result = true;
1551 		break;
1552 	default:
1553 		break;
1554 	} /* switch (type) */
1555 
1556 	return result;
1557 }
1558 
1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1560  *
1561  * @param token           Token string
1562  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1563  * @param text            String that will be used as replacement for <token>
1564  * @param string          String to work on
1565  **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
1567 						 std::string& string)
1568 {
1569 	const size_t text_length	= strlen(text);
1570 	const size_t token_length   = strlen(token);
1571 	const size_t token_position = string.find(token, search_position);
1572 
1573 	string.replace(token_position, token_length, text, text_length);
1574 
1575 	search_position = token_position + text_length;
1576 }
1577 
1578 /** Constructor.
1579  *
1580  *  @param context Rendering context.
1581  *
1582  **/
GPUShaderFP64Test1(deqp::Context & context)1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context)
1584 	: TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision "
1585 								  "float uniform support & glUniform*() / glUniformMatrix*() API "
1586 								  " are reported correctly.")
1587 	, m_has_test_passed(true)
1588 	, m_po_bool_arr_uniform_location(0)
1589 	, m_po_bool_uniform_location(0)
1590 	, m_po_bvec2_arr_uniform_location(0)
1591 	, m_po_bvec2_uniform_location(0)
1592 	, m_po_bvec3_arr_uniform_location(0)
1593 	, m_po_bvec3_uniform_location(0)
1594 	, m_po_bvec4_arr_uniform_location(0)
1595 	, m_po_bvec4_uniform_location(0)
1596 	, m_po_dmat2_arr_uniform_location(0)
1597 	, m_po_dmat2_uniform_location(0)
1598 	, m_po_dmat2x3_arr_uniform_location(0)
1599 	, m_po_dmat2x3_uniform_location(0)
1600 	, m_po_dmat2x4_arr_uniform_location(0)
1601 	, m_po_dmat2x4_uniform_location(0)
1602 	, m_po_dmat3_arr_uniform_location(0)
1603 	, m_po_dmat3_uniform_location(0)
1604 	, m_po_dmat3x2_arr_uniform_location(0)
1605 	, m_po_dmat3x2_uniform_location(0)
1606 	, m_po_dmat3x4_arr_uniform_location(0)
1607 	, m_po_dmat3x4_uniform_location(0)
1608 	, m_po_dmat4_arr_uniform_location(0)
1609 	, m_po_dmat4_uniform_location(0)
1610 	, m_po_dmat4x2_arr_uniform_location(0)
1611 	, m_po_dmat4x2_uniform_location(0)
1612 	, m_po_dmat4x3_arr_uniform_location(0)
1613 	, m_po_dmat4x3_uniform_location(0)
1614 	, m_po_double_arr_uniform_location(0)
1615 	, m_po_double_uniform_location(0)
1616 	, m_po_dvec2_arr_uniform_location(0)
1617 	, m_po_dvec2_uniform_location(0)
1618 	, m_po_dvec3_arr_uniform_location(0)
1619 	, m_po_dvec3_uniform_location(0)
1620 	, m_po_dvec4_arr_uniform_location(0)
1621 	, m_po_dvec4_uniform_location(0)
1622 	, m_po_float_arr_uniform_location(0)
1623 	, m_po_float_uniform_location(0)
1624 	, m_po_int_arr_uniform_location(0)
1625 	, m_po_int_uniform_location(0)
1626 	, m_po_ivec2_arr_uniform_location(0)
1627 	, m_po_ivec2_uniform_location(0)
1628 	, m_po_ivec3_arr_uniform_location(0)
1629 	, m_po_ivec3_uniform_location(0)
1630 	, m_po_ivec4_arr_uniform_location(0)
1631 	, m_po_ivec4_uniform_location(0)
1632 	, m_po_sampler_uniform_location(0)
1633 	, m_po_uint_arr_uniform_location(0)
1634 	, m_po_uint_uniform_location(0)
1635 	, m_po_uvec2_arr_uniform_location(0)
1636 	, m_po_uvec2_uniform_location(0)
1637 	, m_po_uvec3_arr_uniform_location(0)
1638 	, m_po_uvec3_uniform_location(0)
1639 	, m_po_uvec4_arr_uniform_location(0)
1640 	, m_po_uvec4_uniform_location(0)
1641 	, m_po_vec2_arr_uniform_location(0)
1642 	, m_po_vec2_uniform_location(0)
1643 	, m_po_vec3_arr_uniform_location(0)
1644 	, m_po_vec3_uniform_location(0)
1645 	, m_po_vec4_arr_uniform_location(0)
1646 	, m_po_vec4_uniform_location(0)
1647 	, m_po_id(0)
1648 	, m_vs_id(0)
1649 {
1650 	/* Left blank intentionally */
1651 }
1652 
1653 /** Deinitializes all GL objects that may have been created during
1654  *  test execution.
1655  **/
deinit()1656 void GPUShaderFP64Test1::deinit()
1657 {
1658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1659 
1660 	if (m_po_id != 0)
1661 	{
1662 		gl.deleteProgram(m_po_id);
1663 
1664 		m_po_id = 0;
1665 	}
1666 
1667 	if (m_vs_id != 0)
1668 	{
1669 		gl.deleteShader(m_vs_id);
1670 
1671 		m_vs_id = 0;
1672 	}
1673 }
1674 
1675 /** Returns a string describing GL API function represented by user-provided enum.
1676  *
1677  *  @param func Uniform function to return the string for.
1678  *
1679  *  @return As per description. [?] will be returned if the function was not recognized.
1680  **/
getUniformFunctionString(_uniform_function func)1681 const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func)
1682 {
1683 	const char* result = "[?]";
1684 
1685 	switch (func)
1686 	{
1687 	case UNIFORM_FUNCTION_1D:
1688 		result = "glUniform1d";
1689 		break;
1690 	case UNIFORM_FUNCTION_1DV:
1691 		result = "glUniform1dv";
1692 		break;
1693 	case UNIFORM_FUNCTION_2D:
1694 		result = "glUniform2d";
1695 		break;
1696 	case UNIFORM_FUNCTION_2DV:
1697 		result = "glUniform2dv";
1698 		break;
1699 	case UNIFORM_FUNCTION_3D:
1700 		result = "glUniform3d";
1701 		break;
1702 	case UNIFORM_FUNCTION_3DV:
1703 		result = "glUniform3dv";
1704 		break;
1705 	case UNIFORM_FUNCTION_4D:
1706 		result = "glUniform4d";
1707 		break;
1708 	case UNIFORM_FUNCTION_4DV:
1709 		result = "glUniform4dv";
1710 		break;
1711 	case UNIFORM_FUNCTION_MATRIX2DV:
1712 		result = "glUniformMatrix2dv";
1713 		break;
1714 	case UNIFORM_FUNCTION_MATRIX2X3DV:
1715 		result = "glUniformMatrix2x3dv";
1716 		break;
1717 	case UNIFORM_FUNCTION_MATRIX2X4DV:
1718 		result = "glUniformMatrix2x4dv";
1719 		break;
1720 	case UNIFORM_FUNCTION_MATRIX3DV:
1721 		result = "glUniformMatrix3dv";
1722 		break;
1723 	case UNIFORM_FUNCTION_MATRIX3X2DV:
1724 		result = "glUniformMatrix3x2dv";
1725 		break;
1726 	case UNIFORM_FUNCTION_MATRIX3X4DV:
1727 		result = "glUniformMatrix3x4dv";
1728 		break;
1729 	case UNIFORM_FUNCTION_MATRIX4DV:
1730 		result = "glUniformMatrix4dv";
1731 		break;
1732 	case UNIFORM_FUNCTION_MATRIX4X2DV:
1733 		result = "glUniformMatrix4x2dv";
1734 		break;
1735 	case UNIFORM_FUNCTION_MATRIX4X3DV:
1736 		result = "glUniformMatrix4x3dv";
1737 		break;
1738 	default:
1739 		break;
1740 	}
1741 
1742 	return result;
1743 }
1744 
1745 /** Returns name of an uniform bound to user-provided location.
1746  *
1747  *  @param location Location of the uniform to return the name for.
1748  *
1749  *  @return As per description. [?] will be returned if the location was not
1750  *          recognized.
1751  **/
getUniformNameForLocation(glw::GLint location)1752 const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location)
1753 {
1754 	const char* result = "[?]";
1755 
1756 	if (location == m_po_bool_arr_uniform_location)
1757 		result = "uniform_bool_arr";
1758 	else if (location == m_po_bool_uniform_location)
1759 		result = "uniform_bool";
1760 	else if (location == m_po_bvec2_arr_uniform_location)
1761 		result = "uniform_bvec2_arr";
1762 	else if (location == m_po_bvec2_uniform_location)
1763 		result = "uniform_bvec2";
1764 	else if (location == m_po_bvec3_arr_uniform_location)
1765 		result = "uniform_bvec3_arr";
1766 	else if (location == m_po_bvec3_uniform_location)
1767 		result = "uniform_bvec3";
1768 	else if (location == m_po_bvec4_arr_uniform_location)
1769 		result = "uniform_bvec4_arr";
1770 	else if (location == m_po_bvec4_uniform_location)
1771 		result = "uniform_bvec4";
1772 	else if (location == m_po_dmat2_arr_uniform_location)
1773 		result = "uniform_dmat2_arr";
1774 	else if (location == m_po_dmat2_uniform_location)
1775 		result = "uniform_dmat2";
1776 	else if (location == m_po_dmat2x3_arr_uniform_location)
1777 		result = "uniform_dmat2x3_arr";
1778 	else if (location == m_po_dmat2x3_uniform_location)
1779 		result = "uniform_dmat2x3";
1780 	else if (location == m_po_dmat2x4_arr_uniform_location)
1781 		result = "uniform_dmat2x4_arr";
1782 	else if (location == m_po_dmat2x4_uniform_location)
1783 		result = "uniform_dmat2x4";
1784 	else if (location == m_po_dmat3_arr_uniform_location)
1785 		result = "uniform_dmat3_arr";
1786 	else if (location == m_po_dmat3_uniform_location)
1787 		result = "uniform_dmat3";
1788 	else if (location == m_po_dmat3x2_arr_uniform_location)
1789 		result = "uniform_dmat3x2_arr";
1790 	else if (location == m_po_dmat3x2_uniform_location)
1791 		result = "uniform_dmat3x2";
1792 	else if (location == m_po_dmat3x4_arr_uniform_location)
1793 		result = "uniform_dmat3x4_arr";
1794 	else if (location == m_po_dmat3x4_uniform_location)
1795 		result = "uniform_dmat3x4";
1796 	else if (location == m_po_dmat4_arr_uniform_location)
1797 		result = "uniform_dmat4_arr";
1798 	else if (location == m_po_dmat4_uniform_location)
1799 		result = "uniform_dmat4";
1800 	else if (location == m_po_dmat4x2_arr_uniform_location)
1801 		result = "uniform_dmat4x2_arr";
1802 	else if (location == m_po_dmat4x2_uniform_location)
1803 		result = "uniform_dmat4x2";
1804 	else if (location == m_po_dmat4x3_arr_uniform_location)
1805 		result = "uniform_dmat4x3_arr";
1806 	else if (location == m_po_dmat4x3_uniform_location)
1807 		result = "uniform_dmat4x3";
1808 	else if (location == m_po_double_arr_uniform_location)
1809 		result = "uniform_double_arr";
1810 	else if (location == m_po_double_uniform_location)
1811 		result = "uniform_double";
1812 	else if (location == m_po_dvec2_arr_uniform_location)
1813 		result = "uniform_dvec2_arr";
1814 	else if (location == m_po_dvec2_uniform_location)
1815 		result = "uniform_dvec2";
1816 	else if (location == m_po_dvec3_arr_uniform_location)
1817 		result = "uniform_dvec3_arr";
1818 	else if (location == m_po_dvec3_uniform_location)
1819 		result = "uniform_dvec3";
1820 	else if (location == m_po_dvec4_arr_uniform_location)
1821 		result = "uniform_dvec4_arr";
1822 	else if (location == m_po_dvec4_uniform_location)
1823 		result = "uniform_dvec4";
1824 	else if (location == m_po_float_arr_uniform_location)
1825 		result = "uniform_float_arr";
1826 	else if (location == m_po_float_uniform_location)
1827 		result = "uniform_float";
1828 	else if (location == m_po_int_arr_uniform_location)
1829 		result = "uniform_int_arr";
1830 	else if (location == m_po_int_uniform_location)
1831 		result = "uniform_int";
1832 	else if (location == m_po_ivec2_arr_uniform_location)
1833 		result = "uniform_ivec2_arr";
1834 	else if (location == m_po_ivec2_uniform_location)
1835 		result = "uniform_ivec2";
1836 	else if (location == m_po_ivec3_arr_uniform_location)
1837 		result = "uniform_ivec3_arr";
1838 	else if (location == m_po_ivec3_uniform_location)
1839 		result = "uniform_ivec3";
1840 	else if (location == m_po_ivec4_arr_uniform_location)
1841 		result = "uniform_ivec4_arr";
1842 	else if (location == m_po_ivec4_uniform_location)
1843 		result = "uniform_ivec4";
1844 	else if (location == m_po_uint_arr_uniform_location)
1845 		result = "uniform_uint_arr";
1846 	else if (location == m_po_uint_uniform_location)
1847 		result = "uniform_uint";
1848 	else if (location == m_po_uvec2_arr_uniform_location)
1849 		result = "uniform_uvec2_arr";
1850 	else if (location == m_po_uvec2_uniform_location)
1851 		result = "uniform_uvec2";
1852 	else if (location == m_po_uvec3_arr_uniform_location)
1853 		result = "uniform_uvec3_arr";
1854 	else if (location == m_po_uvec3_uniform_location)
1855 		result = "uniform_uvec3";
1856 	else if (location == m_po_uvec4_arr_uniform_location)
1857 		result = "uniform_uvec4_arr";
1858 	else if (location == m_po_uvec4_uniform_location)
1859 		result = "uniform_uvec4";
1860 	else if (location == m_po_vec2_arr_uniform_location)
1861 		result = "uniform_vec2_arr";
1862 	else if (location == m_po_vec2_uniform_location)
1863 		result = "uniform_vec2";
1864 	else if (location == m_po_vec3_arr_uniform_location)
1865 		result = "uniform_vec3_arr";
1866 	else if (location == m_po_vec3_uniform_location)
1867 		result = "uniform_vec3";
1868 	else if (location == m_po_vec4_arr_uniform_location)
1869 		result = "uniform_vec4_arr";
1870 	else if (location == m_po_vec4_uniform_location)
1871 		result = "uniform_vec4";
1872 
1873 	return result;
1874 }
1875 
1876 /** Initializes all GL objects required to run the test. Also extracts locations of all
1877  *  uniforms used by the test.
1878  *
1879  *  This function can throw a TestError exception if the implementation misbehaves.
1880  */
initTest()1881 void GPUShaderFP64Test1::initTest()
1882 {
1883 	glw::GLint			  compile_status = GL_FALSE;
1884 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
1885 	glw::GLint			  link_status	= GL_FALSE;
1886 
1887 	/* Set up a program object using all new double-precision types */
1888 	const char* vs_body =
1889 		"#version 400\n"
1890 		"\n"
1891 		"uniform bool      uniform_bool;\n"
1892 		"uniform bvec2     uniform_bvec2;\n"
1893 		"uniform bvec3     uniform_bvec3;\n"
1894 		"uniform bvec4     uniform_bvec4;\n"
1895 		"uniform dmat2     uniform_dmat2;\n"
1896 		"uniform dmat2x3   uniform_dmat2x3;\n"
1897 		"uniform dmat2x4   uniform_dmat2x4;\n"
1898 		"uniform dmat3     uniform_dmat3;\n"
1899 		"uniform dmat3x2   uniform_dmat3x2;\n"
1900 		"uniform dmat3x4   uniform_dmat3x4;\n"
1901 		"uniform dmat4     uniform_dmat4;\n"
1902 		"uniform dmat4x2   uniform_dmat4x2;\n"
1903 		"uniform dmat4x3   uniform_dmat4x3;\n"
1904 		"uniform double    uniform_double;\n"
1905 		"uniform dvec2     uniform_dvec2;\n"
1906 		"uniform dvec3     uniform_dvec3;\n"
1907 		"uniform dvec4     uniform_dvec4;\n"
1908 		"uniform float     uniform_float;\n"
1909 		"uniform int       uniform_int;\n"
1910 		"uniform ivec2     uniform_ivec2;\n"
1911 		"uniform ivec3     uniform_ivec3;\n"
1912 		"uniform ivec4     uniform_ivec4;\n"
1913 		"uniform sampler2D uniform_sampler;\n"
1914 		"uniform uint      uniform_uint;\n"
1915 		"uniform uvec2     uniform_uvec2;\n"
1916 		"uniform uvec3     uniform_uvec3;\n"
1917 		"uniform uvec4     uniform_uvec4;\n"
1918 		"uniform vec2      uniform_vec2;\n"
1919 		"uniform vec3      uniform_vec3;\n"
1920 		"uniform vec4      uniform_vec4;\n"
1921 		"uniform bool      uniform_bool_arr   [2];\n"
1922 		"uniform bvec2     uniform_bvec2_arr  [2];\n"
1923 		"uniform bvec3     uniform_bvec3_arr  [2];\n"
1924 		"uniform bvec4     uniform_bvec4_arr  [2];\n"
1925 		"uniform dmat2     uniform_dmat2_arr  [2];\n"
1926 		"uniform dmat2x3   uniform_dmat2x3_arr[2];\n"
1927 		"uniform dmat2x4   uniform_dmat2x4_arr[2];\n"
1928 		"uniform dmat3     uniform_dmat3_arr  [2];\n"
1929 		"uniform dmat3x2   uniform_dmat3x2_arr[2];\n"
1930 		"uniform dmat3x4   uniform_dmat3x4_arr[2];\n"
1931 		"uniform dmat4     uniform_dmat4_arr  [2];\n"
1932 		"uniform dmat4x2   uniform_dmat4x2_arr[2];\n"
1933 		"uniform dmat4x3   uniform_dmat4x3_arr[2];\n"
1934 		"uniform double    uniform_double_arr [2];\n"
1935 		"uniform dvec2     uniform_dvec2_arr  [2];\n"
1936 		"uniform dvec3     uniform_dvec3_arr  [2];\n"
1937 		"uniform dvec4     uniform_dvec4_arr  [2];\n"
1938 		"uniform float     uniform_float_arr  [2];\n"
1939 		"uniform int       uniform_int_arr    [2];\n"
1940 		"uniform ivec2     uniform_ivec2_arr  [2];\n"
1941 		"uniform ivec3     uniform_ivec3_arr  [2];\n"
1942 		"uniform ivec4     uniform_ivec4_arr  [2];\n"
1943 		"uniform uint      uniform_uint_arr   [2];\n"
1944 		"uniform uvec2     uniform_uvec2_arr  [2];\n"
1945 		"uniform uvec3     uniform_uvec3_arr  [2];\n"
1946 		"uniform uvec4     uniform_uvec4_arr  [2];\n"
1947 		"uniform vec2      uniform_vec2_arr   [2];\n"
1948 		"uniform vec3      uniform_vec3_arr   [2];\n"
1949 		"uniform vec4      uniform_vec4_arr   [2];\n"
1950 		"\n"
1951 		"void main()\n"
1952 		"{\n"
1953 		"    gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n"
1954 		"\n"
1955 		"    if (uniform_bool        && uniform_bvec2.y        && uniform_bvec3.z        && uniform_bvec4.w        &&\n"
1956 		"        uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n"
1957 		"    {\n"
1958 		"        double sum = uniform_dmat2       [0].x + uniform_dmat2x3       [0].x + uniform_dmat2x4       [0].x +\n"
1959 		"                     uniform_dmat3       [0].x + uniform_dmat3x2       [0].x + uniform_dmat3x4       [0].x +\n"
1960 		"                     uniform_dmat4       [0].x + uniform_dmat4x2       [0].x + uniform_dmat4x3       [0].x +\n"
1961 		"                     uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n"
1962 		"                     uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n"
1963 		"                     uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n"
1964 		"                     uniform_double            + uniform_double_arr [0]      +\n"
1965 		"                     uniform_dvec2.x           + uniform_dvec3.x             + uniform_dvec4.x        +\n"
1966 		"                     uniform_dvec2_arr[0].x    + uniform_dvec3_arr[0].x      + uniform_dvec4_arr[0].x;\n"
1967 		"        int   sum2 = uniform_int               + uniform_ivec2.x             + uniform_ivec3.x        +\n"
1968 		"                     uniform_ivec4.x           + uniform_ivec2_arr[0].x      + uniform_ivec3_arr[0].x +\n"
1969 		"                     uniform_ivec4_arr[0].x    + uniform_int_arr[0];\n"
1970 		"        uint  sum3 = uniform_uint              + uniform_uvec2.x             + uniform_uvec3.x        +\n"
1971 		"                     uniform_uvec4.x           + uniform_uint_arr[0]         + uniform_uvec2_arr[0].x +\n"
1972 		"                     uniform_uvec3_arr[0].x    + uniform_uvec4_arr[0].x;\n"
1973 		"        float sum4 = uniform_float             + uniform_float_arr[0]  + \n"
1974 		"                     uniform_vec2.x            + uniform_vec2_arr[0].x + \n"
1975 		"                     uniform_vec3.x            + uniform_vec3_arr[0].x + \n"
1976 		"                     uniform_vec4.x            + uniform_vec4_arr[0].x;\n"
1977 		"\n"
1978 		"        if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n"
1979 		"        {\n"
1980 		"            gl_Position = vec4(1);\n"
1981 		"        }\n"
1982 		"    }\n"
1983 		"}\n";
1984 
1985 	m_po_id = gl.createProgram();
1986 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1987 
1988 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1989 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
1990 
1991 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
1992 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1993 
1994 	gl.compileShader(m_vs_id);
1995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1996 
1997 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1999 
2000 	if (compile_status != GL_TRUE)
2001 	{
2002 		TCU_FAIL("Shader compilation failed.");
2003 	}
2004 
2005 	gl.attachShader(m_po_id, m_vs_id);
2006 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
2007 
2008 	gl.linkProgram(m_po_id);
2009 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2010 
2011 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
2012 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2013 
2014 	if (link_status != GL_TRUE)
2015 	{
2016 		TCU_FAIL("Program linking failed.");
2017 	}
2018 
2019 	m_po_bool_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]");
2020 	m_po_bool_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bool");
2021 	m_po_bvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]");
2022 	m_po_bvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec2");
2023 	m_po_bvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]");
2024 	m_po_bvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec3");
2025 	m_po_bvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]");
2026 	m_po_bvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_bvec4");
2027 	m_po_dmat2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]");
2028 	m_po_dmat2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat2");
2029 	m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]");
2030 	m_po_dmat2x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x3");
2031 	m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]");
2032 	m_po_dmat2x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat2x4");
2033 	m_po_dmat3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]");
2034 	m_po_dmat3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat3");
2035 	m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]");
2036 	m_po_dmat3x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x2");
2037 	m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]");
2038 	m_po_dmat3x4_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat3x4");
2039 	m_po_dmat4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]");
2040 	m_po_dmat4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dmat4");
2041 	m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]");
2042 	m_po_dmat4x2_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x2");
2043 	m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]");
2044 	m_po_dmat4x3_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_dmat4x3");
2045 	m_po_double_arr_uniform_location  = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]");
2046 	m_po_double_uniform_location	  = gl.getUniformLocation(m_po_id, "uniform_double");
2047 	m_po_dvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]");
2048 	m_po_dvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec2");
2049 	m_po_dvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]");
2050 	m_po_dvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec3");
2051 	m_po_dvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]");
2052 	m_po_dvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_dvec4");
2053 	m_po_float_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]");
2054 	m_po_float_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_float");
2055 	m_po_int_arr_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]");
2056 	m_po_int_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_int");
2057 	m_po_ivec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]");
2058 	m_po_ivec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec2");
2059 	m_po_ivec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]");
2060 	m_po_ivec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec3");
2061 	m_po_ivec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]");
2062 	m_po_ivec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_ivec4");
2063 	m_po_sampler_uniform_location	 = gl.getUniformLocation(m_po_id, "uniform_sampler");
2064 	m_po_uint_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]");
2065 	m_po_uint_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uint");
2066 	m_po_uvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]");
2067 	m_po_uvec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec2");
2068 	m_po_uvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]");
2069 	m_po_uvec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec3");
2070 	m_po_uvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]");
2071 	m_po_uvec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_uvec4");
2072 	m_po_vec2_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]");
2073 	m_po_vec2_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec2");
2074 	m_po_vec3_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]");
2075 	m_po_vec3_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec3");
2076 	m_po_vec4_arr_uniform_location	= gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]");
2077 	m_po_vec4_uniform_location		  = gl.getUniformLocation(m_po_id, "uniform_vec4");
2078 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
2079 
2080 	if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 ||
2081 		m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 ||
2082 		m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 ||
2083 		m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 ||
2084 		m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 ||
2085 		m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 ||
2086 		m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 ||
2087 		m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 ||
2088 		m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 ||
2089 		m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 ||
2090 		m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 ||
2091 		m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 ||
2092 		m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 ||
2093 		m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 ||
2094 		m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 ||
2095 		m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 ||
2096 		m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 ||
2097 		m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 ||
2098 		m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 ||
2099 		m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 ||
2100 		m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 ||
2101 		m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 ||
2102 		m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 ||
2103 		m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 ||
2104 		m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 ||
2105 		m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 ||
2106 		m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 ||
2107 		m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 ||
2108 		m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1)
2109 	{
2110 		TCU_FAIL("At last one of the required uniforms is considered inactive.");
2111 	}
2112 }
2113 
2114 /** Tells wheter uniform at user-specified location represents a double-precision
2115  *  matrix uniform.
2116  *
2117  *  @param uniform_location Location of the uniform to use for the query.
2118  *
2119  *  @return Requested information.
2120  **/
isMatrixUniform(glw::GLint uniform_location)2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location)
2122 {
2123 	return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location ||
2124 			uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location ||
2125 			uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location ||
2126 			uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location ||
2127 			uniform_location == m_po_dmat4x3_uniform_location);
2128 }
2129 
2130 /** Tells whether user-specified uniform function corresponds to one of the
2131  *  functions in glUniformMatrix*() class.
2132  *
2133  *  @param func Uniform function enum to use for the query.
2134  *
2135  *  @return true if the specified enum represents one of the glUniformMatrix*() functions,
2136  *          false otherwise.
2137  **/
isMatrixUniformFunction(_uniform_function func)2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func)
2139 {
2140 	return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV ||
2141 			func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV ||
2142 			func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV ||
2143 			func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV ||
2144 			func == UNIFORM_FUNCTION_MATRIX4X3DV);
2145 }
2146 
2147 /** Executes test iteration.
2148  *
2149  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2150  */
iterate()2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate()
2152 {
2153 	/* Do not execute the test if GL_ARB_texture_view is not supported */
2154 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
2155 	{
2156 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
2157 	}
2158 
2159 	/* Initialize all ES objects required to run all the checks */
2160 	initTest();
2161 
2162 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() and
2163 	 * glUniformMatrix*() functions if there is no current program object.
2164 	 */
2165 	m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO();
2166 
2167 	/* Make sure GL_INVALID_OPERATION is generated by glUniform*() if
2168 	 * the size of the uniform variable declared in the shader does not
2169 	 * match the size indicated by the command.
2170 	 */
2171 	m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions();
2172 
2173 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2174 	 * glUniformMatrix*() are used to load a uniform variable of type
2175 	 * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4,
2176 	 * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array
2177 	 * of these.
2178 	 */
2179 	m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions();
2180 
2181 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2182 	 * glUniformMatrix*() are used to load incompatible double-typed
2183 	 * uniforms, as presented below:
2184 	 *
2185 	 * I.    double-typed uniform configured by glUniform2d();
2186 	 * II.   double-typed uniform configured by glUniform3d();
2187 	 * III.  double-typed uniform configured by glUniform4d();
2188 	 * IV.   double-typed uniform configured by glUniformMatrix*();
2189 	 * V.    dvec2-typed  uniform configured by glUniform1d();
2190 	 * VI.   dvec2-typed  uniform configured by glUniform3d();
2191 	 * VII.  dvec2-typed  uniform configured by glUniform4d();
2192 	 * VIII. dvec2-typed  uniform configured by glUniformMatrix*();
2193 	 *
2194 	 *                          (etc.)
2195 	 *
2196 	 */
2197 	m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions();
2198 
2199 	/* Make sure GL_INVALID_OPERATION is generated if <location> of
2200 	 * glUniform*() and glUniformMatrix*() is an invalid uniform
2201 	 * location for the current program object and location is not
2202 	 * equal to -1.
2203 	 */
2204 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation();
2205 
2206 	/* Make sure GL_INVALID_VALUE is generated if <count> of
2207 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2208 	 * negative.
2209 	 */
2210 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount();
2211 
2212 	/* Make sure GL_INVALID_OPERATION is generated if <count> of
2213 	 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2214 	 * greater than 1 and the indicated uniform variable is not an
2215 	 * array variable.
2216 	 */
2217 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount();
2218 
2219 	/* Make sure GL_INVALID_OPERATION is generated if a sampler is
2220 	 * loaded by glUniform*() and glUniformMatrix*().
2221 	 */
2222 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers();
2223 
2224 	/* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2225 	 * glUniformMatrix*() is used to load values for uniforms of
2226 	 * boolean types.
2227 	 */
2228 	m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans();
2229 
2230 	if (m_has_test_passed)
2231 	{
2232 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2233 	}
2234 	else
2235 	{
2236 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2237 	}
2238 
2239 	return STOP;
2240 }
2241 
2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2243  *  glUniformMatrix*dv() functions is used to load a boolean uniform.
2244  *
2245  *  @return true if the implementation was found to behave as expected, false otherwise.
2246  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()
2248 {
2249 	const double double_data[] = {
2250 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2251 	};
2252 	const glw::Functions& gl				  = m_context.getRenderContext().getFunctions();
2253 	bool				  result			  = true;
2254 	glw::GLint			  uniform_locations[] = { m_po_bool_arr_uniform_location,  m_po_bool_uniform_location,
2255 									   m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2256 									   m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2257 									   m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location };
2258 	const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2259 
2260 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2261 		 ++n_uniform_function)
2262 	{
2263 		const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2264 
2265 		for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2266 		{
2267 			const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2268 
2269 			switch (uniform_function)
2270 			{
2271 			case UNIFORM_FUNCTION_1D:
2272 				gl.uniform1d(uniform_location, 0.0);
2273 				break;
2274 			case UNIFORM_FUNCTION_2D:
2275 				gl.uniform2d(uniform_location, 0.0, 1.0);
2276 				break;
2277 			case UNIFORM_FUNCTION_3D:
2278 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2279 				break;
2280 			case UNIFORM_FUNCTION_4D:
2281 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2282 				break;
2283 
2284 			case UNIFORM_FUNCTION_1DV:
2285 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2286 				break;
2287 			case UNIFORM_FUNCTION_2DV:
2288 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2289 				break;
2290 			case UNIFORM_FUNCTION_3DV:
2291 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2292 				break;
2293 			case UNIFORM_FUNCTION_4DV:
2294 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2295 				break;
2296 
2297 			case UNIFORM_FUNCTION_MATRIX2DV:
2298 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2299 				break;
2300 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2301 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2302 				break;
2303 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2304 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2305 				break;
2306 			case UNIFORM_FUNCTION_MATRIX3DV:
2307 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2308 				break;
2309 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2310 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2311 				break;
2312 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2313 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2314 				break;
2315 			case UNIFORM_FUNCTION_MATRIX4DV:
2316 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2317 				break;
2318 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2319 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2320 				break;
2321 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2322 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2323 				break;
2324 
2325 			default:
2326 			{
2327 				TCU_FAIL("Unrecognized uniform function");
2328 			}
2329 			}
2330 
2331 			/* Make sure GL_INVALID_OPERATION was generated by the call */
2332 			const glw::GLenum error_code = gl.getError();
2333 
2334 			if (error_code != GL_INVALID_OPERATION)
2335 			{
2336 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2337 								   << "() did not generate an error"
2338 									  " when applied against a boolean uniform."
2339 								   << tcu::TestLog::EndMessage;
2340 
2341 				result = false;
2342 			}
2343 		} /* for (all bool uniforms) */
2344 	}	 /* for (all uniform functions) */
2345 
2346 	return result;
2347 }
2348 
2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2350  *  glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2351  *
2352  *  @return true if the implementation was found to behave as expected, false otherwise.
2353  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2355 {
2356 	const double double_data[] = {
2357 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2358 	};
2359 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2360 	bool				  result = true;
2361 
2362 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2363 		 ++n_uniform_function)
2364 	{
2365 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2366 
2367 		switch (uniform_function)
2368 		{
2369 		case UNIFORM_FUNCTION_1D:
2370 			gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2371 			break;
2372 		case UNIFORM_FUNCTION_2D:
2373 			gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2374 			break;
2375 		case UNIFORM_FUNCTION_3D:
2376 			gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2377 			break;
2378 		case UNIFORM_FUNCTION_4D:
2379 			gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2380 			break;
2381 
2382 		case UNIFORM_FUNCTION_1DV:
2383 			gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2384 			break;
2385 		case UNIFORM_FUNCTION_2DV:
2386 			gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2387 			break;
2388 		case UNIFORM_FUNCTION_3DV:
2389 			gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2390 			break;
2391 		case UNIFORM_FUNCTION_4DV:
2392 			gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2393 			break;
2394 
2395 		case UNIFORM_FUNCTION_MATRIX2DV:
2396 			gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2397 			break;
2398 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2399 			gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2400 			break;
2401 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2402 			gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2403 			break;
2404 		case UNIFORM_FUNCTION_MATRIX3DV:
2405 			gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2406 			break;
2407 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2408 			gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2409 			break;
2410 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2411 			gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2412 			break;
2413 		case UNIFORM_FUNCTION_MATRIX4DV:
2414 			gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2415 			break;
2416 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2417 			gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2418 			break;
2419 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2420 			gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2421 			break;
2422 
2423 		default:
2424 		{
2425 			TCU_FAIL("Unrecognized uniform function");
2426 		}
2427 		}
2428 
2429 		/* Make sure GL_INVALID_OPERATION was generated by the call */
2430 		const glw::GLenum error_code = gl.getError();
2431 
2432 		if (error_code != GL_INVALID_OPERATION)
2433 		{
2434 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2435 							   << "() did not generate an error"
2436 								  " when applied against a sampler uniform."
2437 							   << tcu::TestLog::EndMessage;
2438 
2439 			result = false;
2440 		}
2441 	} /* for (all uniform functions) */
2442 
2443 	return result;
2444 }
2445 
2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2447  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2448  *  invalid <count> argument.
2449  *
2450  *  @return true if the implementation was found to behave as expected, false otherwise.
2451  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2453 {
2454 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2455 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2456 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2457 	bool					result				= true;
2458 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2459 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2460 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2461 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2462 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2463 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2464 													UNIFORM_FUNCTION_MATRIX4X3DV };
2465 	const glw::GLint uniforms[] = {
2466 		m_po_bool_uniform_location,	m_po_bvec2_uniform_location,  m_po_bvec3_uniform_location,
2467 		m_po_bvec4_uniform_location,   m_po_dmat2_uniform_location,  m_po_dmat2x3_uniform_location,
2468 		m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,  m_po_dmat3x2_uniform_location,
2469 		m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location,  m_po_dmat4x2_uniform_location,
2470 		m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2471 		m_po_dvec3_uniform_location,   m_po_dvec4_uniform_location,  m_po_float_uniform_location,
2472 		m_po_int_uniform_location,	 m_po_ivec2_uniform_location,  m_po_ivec3_uniform_location,
2473 		m_po_ivec4_uniform_location,   m_po_uint_uniform_location,   m_po_uvec2_uniform_location,
2474 		m_po_uvec3_uniform_location,   m_po_uvec4_uniform_location,  m_po_vec2_uniform_location,
2475 		m_po_vec3_uniform_location,	m_po_vec4_uniform_location
2476 	};
2477 
2478 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2479 	const unsigned int n_uniforms		   = sizeof(uniforms) / sizeof(uniforms[0]);
2480 
2481 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2482 	{
2483 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2484 
2485 		for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2486 		{
2487 			glw::GLint uniform_location = uniforms[n_uniform];
2488 
2489 			/* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2490 			 * and glUniform*() functions with vector uniforms.
2491 			 */
2492 			bool is_matrix_uniform = isMatrixUniform(uniform_location);
2493 
2494 			if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2495 				((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2496 			{
2497 				continue;
2498 			}
2499 
2500 			/* Issue the call with an invalid <count> argument */
2501 			switch (uniform_function)
2502 			{
2503 			case UNIFORM_FUNCTION_1DV:
2504 				gl.uniform1dv(uniform_location, 2, double_values);
2505 				break;
2506 			case UNIFORM_FUNCTION_2DV:
2507 				gl.uniform2dv(uniform_location, 2, double_values);
2508 				break;
2509 			case UNIFORM_FUNCTION_3DV:
2510 				gl.uniform3dv(uniform_location, 2, double_values);
2511 				break;
2512 			case UNIFORM_FUNCTION_4DV:
2513 				gl.uniform4dv(uniform_location, 2, double_values);
2514 				break;
2515 			case UNIFORM_FUNCTION_MATRIX2DV:
2516 				gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2517 				break;
2518 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2519 				gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2520 				break;
2521 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2522 				gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2523 				break;
2524 			case UNIFORM_FUNCTION_MATRIX3DV:
2525 				gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2526 				break;
2527 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2528 				gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2529 				break;
2530 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2531 				gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2532 				break;
2533 			case UNIFORM_FUNCTION_MATRIX4DV:
2534 				gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2535 				break;
2536 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2537 				gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2538 				break;
2539 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2540 				gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2541 				break;
2542 
2543 			default:
2544 			{
2545 				TCU_FAIL("Unrecognized uniform function");
2546 			}
2547 			} /* switch (uniform_function) */
2548 
2549 			/* Make sure GL_INVALID_VALUE was generated */
2550 			glw::GLenum error_code = gl.getError();
2551 
2552 			if (error_code != GL_INVALID_OPERATION)
2553 			{
2554 				m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2555 								   << "() "
2556 									  "was called with an invalid count argument but did not generate a "
2557 									  "GL_INVALID_OPERATION error"
2558 								   << tcu::TestLog::EndMessage;
2559 
2560 				result = false;
2561 			}
2562 		} /* for (all non-arrayed uniforms) */
2563 	}	 /* for (all uniform functions) */
2564 
2565 	return result;
2566 }
2567 
2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2569  *  glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2570  *
2571  *  @return true if the implementation was found to behave as expected, false otherwise.
2572  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2574 {
2575 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
2576 	bool				  result = true;
2577 
2578 	/* Find the largest valid uniform location */
2579 	const glw::GLint uniform_locations[] = {
2580 		m_po_bool_arr_uniform_location,	m_po_bool_uniform_location,		  m_po_bvec2_arr_uniform_location,
2581 		m_po_bvec2_uniform_location,	   m_po_bvec3_arr_uniform_location,   m_po_bvec3_uniform_location,
2582 		m_po_bvec4_arr_uniform_location,   m_po_bvec4_uniform_location,		  m_po_dmat2_arr_uniform_location,
2583 		m_po_dmat2_uniform_location,	   m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2584 		m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location,	 m_po_dmat3_arr_uniform_location,
2585 		m_po_dmat3_uniform_location,	   m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2586 		m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location,	 m_po_dmat4_arr_uniform_location,
2587 		m_po_dmat4_uniform_location,	   m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2588 		m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location,	 m_po_double_arr_uniform_location,
2589 		m_po_double_uniform_location,	  m_po_dvec2_arr_uniform_location,   m_po_dvec2_uniform_location,
2590 		m_po_dvec3_arr_uniform_location,   m_po_dvec3_uniform_location,		  m_po_dvec4_arr_uniform_location,
2591 		m_po_dvec4_uniform_location,	   m_po_float_arr_uniform_location,   m_po_float_uniform_location,
2592 		m_po_int_arr_uniform_location,	 m_po_int_uniform_location,		  m_po_ivec2_arr_uniform_location,
2593 		m_po_ivec2_uniform_location,	   m_po_ivec3_arr_uniform_location,   m_po_ivec3_uniform_location,
2594 		m_po_ivec4_arr_uniform_location,   m_po_ivec4_uniform_location,		  m_po_uint_arr_uniform_location,
2595 		m_po_uint_uniform_location,		   m_po_uvec2_arr_uniform_location,   m_po_uvec2_uniform_location,
2596 		m_po_uvec3_arr_uniform_location,   m_po_uvec3_uniform_location,		  m_po_uvec4_arr_uniform_location,
2597 		m_po_uvec4_uniform_location,	   m_po_vec2_arr_uniform_location,	m_po_vec2_uniform_location,
2598 		m_po_vec3_arr_uniform_location,	m_po_vec3_uniform_location,		  m_po_vec4_arr_uniform_location,
2599 		m_po_vec4_uniform_location
2600 	};
2601 	const unsigned int n_uniform_locations	= sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2602 	glw::GLint		   valid_uniform_location = -1;
2603 
2604 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2605 	{
2606 		glw::GLint uniform_location = uniform_locations[n_uniform_location];
2607 
2608 		if (uniform_location > valid_uniform_location)
2609 		{
2610 			valid_uniform_location = uniform_location;
2611 		}
2612 	} /* for (all  uniform locations) */
2613 
2614 	/* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2615 	 * for invalid uniform location that is != -1
2616 	 */
2617 	const double double_data[] = {
2618 		1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2619 	};
2620 	const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2621 
2622 	for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2623 		 ++n_uniform_function)
2624 	{
2625 		_uniform_function uniform_function = (_uniform_function)n_uniform_function;
2626 
2627 		switch (uniform_function)
2628 		{
2629 		case UNIFORM_FUNCTION_1D:
2630 			gl.uniform1d(invalid_uniform_location, 0.0);
2631 			break;
2632 		case UNIFORM_FUNCTION_2D:
2633 			gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2634 			break;
2635 		case UNIFORM_FUNCTION_3D:
2636 			gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2637 			break;
2638 		case UNIFORM_FUNCTION_4D:
2639 			gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2640 			break;
2641 
2642 		case UNIFORM_FUNCTION_1DV:
2643 			gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2644 			break;
2645 		case UNIFORM_FUNCTION_2DV:
2646 			gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2647 			break;
2648 		case UNIFORM_FUNCTION_3DV:
2649 			gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2650 			break;
2651 		case UNIFORM_FUNCTION_4DV:
2652 			gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2653 			break;
2654 
2655 		case UNIFORM_FUNCTION_MATRIX2DV:
2656 			gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657 			break;
2658 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2659 			gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660 			break;
2661 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2662 			gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663 			break;
2664 		case UNIFORM_FUNCTION_MATRIX3DV:
2665 			gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666 			break;
2667 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2668 			gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669 			break;
2670 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2671 			gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672 			break;
2673 		case UNIFORM_FUNCTION_MATRIX4DV:
2674 			gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675 			break;
2676 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2677 			gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2678 			break;
2679 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2680 			gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2681 			break;
2682 
2683 		default:
2684 		{
2685 			TCU_FAIL("Unrecognized uniform function");
2686 		}
2687 		}
2688 
2689 		const glw::GLenum error_code = gl.getError();
2690 
2691 		if (error_code != GL_INVALID_OPERATION)
2692 		{
2693 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2694 							   << "() did not generate an error"
2695 								  " when passed an invalid uniform location different from -1."
2696 							   << tcu::TestLog::EndMessage;
2697 
2698 			result = false;
2699 		}
2700 	} /* for (all uniform functions) */
2701 
2702 	return result;
2703 }
2704 
2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2706  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2707  *  invalid <count> argument of -1.
2708  *
2709  *  @return true if the implementation was found to behave as expected, false otherwise.
2710  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2712 {
2713 	const glw::GLdouble double_values[16] = { 1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2714 											  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2715 	const glw::Functions&   gl					= m_context.getRenderContext().getFunctions();
2716 	bool					result				= true;
2717 	const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV,		  UNIFORM_FUNCTION_2DV,
2718 													UNIFORM_FUNCTION_3DV,		  UNIFORM_FUNCTION_4DV,
2719 													UNIFORM_FUNCTION_MATRIX2DV,   UNIFORM_FUNCTION_MATRIX2X3DV,
2720 													UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2721 													UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2722 													UNIFORM_FUNCTION_MATRIX4DV,   UNIFORM_FUNCTION_MATRIX4X2DV,
2723 													UNIFORM_FUNCTION_MATRIX4X3DV };
2724 	const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2725 
2726 	for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2727 	{
2728 		_uniform_function uniform_function = uniform_functions[n_uniform_function];
2729 
2730 		switch (uniform_function)
2731 		{
2732 		case UNIFORM_FUNCTION_1DV:
2733 			gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2734 			break;
2735 		case UNIFORM_FUNCTION_2DV:
2736 			gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2737 			break;
2738 		case UNIFORM_FUNCTION_3DV:
2739 			gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2740 			break;
2741 		case UNIFORM_FUNCTION_4DV:
2742 			gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2743 			break;
2744 		case UNIFORM_FUNCTION_MATRIX2DV:
2745 			gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2746 			break;
2747 		case UNIFORM_FUNCTION_MATRIX2X3DV:
2748 			gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2749 			break;
2750 		case UNIFORM_FUNCTION_MATRIX2X4DV:
2751 			gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2752 			break;
2753 		case UNIFORM_FUNCTION_MATRIX3DV:
2754 			gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2755 			break;
2756 		case UNIFORM_FUNCTION_MATRIX3X2DV:
2757 			gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2758 			break;
2759 		case UNIFORM_FUNCTION_MATRIX3X4DV:
2760 			gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2761 			break;
2762 		case UNIFORM_FUNCTION_MATRIX4DV:
2763 			gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2764 			break;
2765 		case UNIFORM_FUNCTION_MATRIX4X2DV:
2766 			gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2767 			break;
2768 		case UNIFORM_FUNCTION_MATRIX4X3DV:
2769 			gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2770 			break;
2771 
2772 		default:
2773 		{
2774 			TCU_FAIL("Unrecognized uniform function");
2775 		}
2776 		} /* switch (uniform_function) */
2777 
2778 		/* Make sure GL_INVALID_VALUE was generated */
2779 		glw::GLenum error_code = gl.getError();
2780 
2781 		if (error_code != GL_INVALID_VALUE)
2782 		{
2783 			m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2784 							   << "() "
2785 								  "was called with a negative count argument but did not generate a "
2786 								  "GL_INVALID_VALUE error"
2787 							   << tcu::TestLog::EndMessage;
2788 
2789 			result = false;
2790 		}
2791 	} /* for (all uniform functions) */
2792 
2793 	return result;
2794 }
2795 
2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2797  *  glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2798  *  function (as per spec).
2799  *
2800  *  @return true if the implementation was found to behave as expected, false otherwise.
2801  **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2803 {
2804 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2805 	glw::GLenum			  error_code	= GL_NO_ERROR;
2806 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2807 	bool				  result		= true;
2808 
2809 	const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location,   m_po_dmat2x3_uniform_location,
2810 													m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,
2811 													m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2812 													m_po_dmat4_uniform_location,   m_po_dmat4x2_uniform_location,
2813 													m_po_dmat4x3_uniform_location, m_po_double_uniform_location,
2814 													m_po_dvec2_uniform_location,   m_po_dvec3_uniform_location,
2815 													m_po_dvec4_uniform_location };
2816 	const unsigned int n_double_uniform_locations =
2817 		sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2818 
2819 	gl.useProgram(m_po_id);
2820 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2821 
2822 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2823 	{
2824 		glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2825 
2826 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2827 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2828 		{
2829 			_uniform_function e_function = static_cast<_uniform_function>(function);
2830 			/* Exclude valid combinations */
2831 			if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2832 				((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2833 				((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2834 				((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2835 				((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2836 				((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2837 				((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2838 				((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2839 				((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2840 				((uniform_location == m_po_double_uniform_location) &&
2841 				 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2842 				((uniform_location == m_po_dvec2_uniform_location) &&
2843 				 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2844 				((uniform_location == m_po_dvec3_uniform_location) &&
2845 				 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2846 				((uniform_location == m_po_dvec4_uniform_location) &&
2847 				 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2848 			{
2849 				continue;
2850 			}
2851 
2852 			switch (e_function)
2853 			{
2854 			case UNIFORM_FUNCTION_1D:
2855 			{
2856 				gl.uniform1d(uniform_location, double_data[0]);
2857 
2858 				break;
2859 			}
2860 
2861 			case UNIFORM_FUNCTION_2D:
2862 			{
2863 				gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2864 
2865 				break;
2866 			}
2867 
2868 			case UNIFORM_FUNCTION_3D:
2869 			{
2870 				gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2871 
2872 				break;
2873 			}
2874 
2875 			case UNIFORM_FUNCTION_4D:
2876 			{
2877 				gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2878 
2879 				break;
2880 			}
2881 
2882 			case UNIFORM_FUNCTION_1DV:
2883 				gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2884 				break;
2885 			case UNIFORM_FUNCTION_2DV:
2886 				gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2887 				break;
2888 			case UNIFORM_FUNCTION_3DV:
2889 				gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2890 				break;
2891 			case UNIFORM_FUNCTION_4DV:
2892 				gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2893 				break;
2894 			case UNIFORM_FUNCTION_MATRIX2DV:
2895 				gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2896 				break;
2897 			case UNIFORM_FUNCTION_MATRIX2X3DV:
2898 				gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2899 				break;
2900 			case UNIFORM_FUNCTION_MATRIX2X4DV:
2901 				gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2902 				break;
2903 			case UNIFORM_FUNCTION_MATRIX3DV:
2904 				gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2905 				break;
2906 			case UNIFORM_FUNCTION_MATRIX3X2DV:
2907 				gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2908 				break;
2909 			case UNIFORM_FUNCTION_MATRIX3X4DV:
2910 				gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2911 				break;
2912 			case UNIFORM_FUNCTION_MATRIX4DV:
2913 				gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2914 				break;
2915 			case UNIFORM_FUNCTION_MATRIX4X2DV:
2916 				gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2917 				break;
2918 			case UNIFORM_FUNCTION_MATRIX4X3DV:
2919 				gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2920 				break;
2921 
2922 			default:
2923 			{
2924 				TCU_FAIL("Unrecognized function");
2925 			}
2926 			} /* switch (function) */
2927 
2928 			/* Make sure GL_INVALID_OPERATION error was generated */
2929 			error_code = gl.getError();
2930 
2931 			if (error_code != GL_INVALID_OPERATION)
2932 			{
2933 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2934 								   << "] was generated when a mismatched "
2935 									  "double-precision uniform function "
2936 								   << getUniformFunctionString(e_function) << "() was used to configure uniform "
2937 								   << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2938 
2939 				result = false;
2940 			}
2941 		} /* for (all uniform functions) */
2942 	}	 /* for (all uniform locations) */
2943 
2944 	return result;
2945 }
2946 
2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2948  *  glUniform*dv() functions is used to load an uniform, size of which is incompatible
2949  *  with the function.
2950  *
2951  *  @return true if the implementation was found to behave as expected, false otherwise.
2952  **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2954 {
2955 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2956 	glw::GLenum			  error_code	= GL_NO_ERROR;
2957 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
2958 	bool				  result		= true;
2959 
2960 	const int data[] = {
2961 		/* API function */ /* Uniform location */ /* Count (dv functions only) */
2962 		(int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV,
2963 		m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0,
2964 		(int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2965 		m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2,
2966 		(int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2967 		m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0,
2968 		(int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2969 		m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2,
2970 		(int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2971 		m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0,
2972 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2973 		m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2,
2974 		(int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2975 		m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0,
2976 		(int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D,
2977 		m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2,
2978 	};
2979 	const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
2980 
2981 	gl.useProgram(m_po_id);
2982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2983 
2984 	for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
2985 	{
2986 		_uniform_function function		   = (_uniform_function)data[n_check * 3 + 0];
2987 		int				  uniform_location = data[n_check * 3 + 1];
2988 		int				  uniform_count	= data[n_check * 3 + 2];
2989 
2990 		switch (function)
2991 		{
2992 		case UNIFORM_FUNCTION_1D:
2993 			gl.uniform1d(uniform_location, 0.0);
2994 			break;
2995 		case UNIFORM_FUNCTION_1DV:
2996 			gl.uniform1dv(uniform_location, uniform_count, double_data);
2997 			break;
2998 		case UNIFORM_FUNCTION_2D:
2999 			gl.uniform2d(uniform_location, 0.0, 1.0);
3000 			break;
3001 		case UNIFORM_FUNCTION_2DV:
3002 			gl.uniform2dv(uniform_location, uniform_count, double_data);
3003 			break;
3004 		case UNIFORM_FUNCTION_3D:
3005 			gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3006 			break;
3007 		case UNIFORM_FUNCTION_3DV:
3008 			gl.uniform3dv(uniform_location, uniform_count, double_data);
3009 			break;
3010 		case UNIFORM_FUNCTION_4D:
3011 			gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3012 			break;
3013 		case UNIFORM_FUNCTION_4DV:
3014 			gl.uniform4dv(uniform_location, uniform_count, double_data);
3015 			break;
3016 
3017 		default:
3018 		{
3019 			DE_ASSERT(false);
3020 		}
3021 		} /* switch (function) */
3022 
3023 		error_code = gl.getError();
3024 		if (error_code != GL_INVALID_OPERATION)
3025 		{
3026 			m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3027 							   << "() function did not generate GL_INVALID_OPERATION error when called for"
3028 								  " a uniform of incompatible size. (check index: "
3029 							   << n_check << ")" << tcu::TestLog::EndMessage;
3030 
3031 			result = false;
3032 		}
3033 	} /* for (all checks) */
3034 
3035 	return result;
3036 }
3037 
3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3039  *  glUniform*dv() functions is used to load an uniform, type of which is incompatible
3040  *  with the function.
3041  *
3042  *  @return true if the implementation was found to behave as expected, false otherwise.
3043  **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3045 {
3046 	const double		  double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
3047 	glw::GLenum			  error_code	= GL_NO_ERROR;
3048 	const glw::Functions& gl			= m_context.getRenderContext().getFunctions();
3049 	bool				  result		= true;
3050 
3051 	const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location,  m_po_bvec2_uniform_location,
3052 													   m_po_bvec3_uniform_location, m_po_bvec4_uniform_location,
3053 													   m_po_float_uniform_location, m_po_int_uniform_location,
3054 													   m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
3055 													   m_po_ivec4_uniform_location, m_po_uint_uniform_location,
3056 													   m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3057 													   m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
3058 													   m_po_vec3_uniform_location,  m_po_vec4_uniform_location };
3059 	const unsigned int n_nondouble_uniform_locations =
3060 		sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3061 
3062 	gl.useProgram(m_po_id);
3063 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3064 
3065 	for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3066 	{
3067 		glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3068 
3069 		for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3070 			 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3071 		{
3072 			switch (static_cast<_uniform_function>(function))
3073 			{
3074 			case UNIFORM_FUNCTION_1D:
3075 				gl.uniform1d(uniform_location, 0.0);
3076 				break;
3077 			case UNIFORM_FUNCTION_1DV:
3078 				gl.uniform1dv(uniform_location, 1, double_data);
3079 				break;
3080 			case UNIFORM_FUNCTION_2D:
3081 				gl.uniform2d(uniform_location, 0.0, 1.0);
3082 				break;
3083 			case UNIFORM_FUNCTION_2DV:
3084 				gl.uniform2dv(uniform_location, 1, double_data);
3085 				break;
3086 			case UNIFORM_FUNCTION_3D:
3087 				gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3088 				break;
3089 			case UNIFORM_FUNCTION_3DV:
3090 				gl.uniform3dv(uniform_location, 1, double_data);
3091 				break;
3092 			case UNIFORM_FUNCTION_4D:
3093 				gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3094 				break;
3095 			case UNIFORM_FUNCTION_4DV:
3096 				gl.uniform4dv(uniform_location, 1, double_data);
3097 				break;
3098 
3099 			case UNIFORM_FUNCTION_MATRIX2DV:
3100 				gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3101 				break;
3102 			case UNIFORM_FUNCTION_MATRIX2X3DV:
3103 				gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3104 				break;
3105 			case UNIFORM_FUNCTION_MATRIX2X4DV:
3106 				gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3107 				break;
3108 			case UNIFORM_FUNCTION_MATRIX3DV:
3109 				gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3110 				break;
3111 			case UNIFORM_FUNCTION_MATRIX3X2DV:
3112 				gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3113 				break;
3114 			case UNIFORM_FUNCTION_MATRIX3X4DV:
3115 				gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3116 				break;
3117 			case UNIFORM_FUNCTION_MATRIX4DV:
3118 				gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3119 				break;
3120 			case UNIFORM_FUNCTION_MATRIX4X2DV:
3121 				gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3122 				break;
3123 			case UNIFORM_FUNCTION_MATRIX4X3DV:
3124 				gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3125 				break;
3126 
3127 			default:
3128 			{
3129 				DE_ASSERT(false);
3130 			}
3131 			} /* switch (function) */
3132 
3133 			error_code = gl.getError();
3134 			if (error_code != GL_INVALID_OPERATION)
3135 			{
3136 				m_testCtx.getLog() << tcu::TestLog::Message
3137 								   << getUniformFunctionString(static_cast<_uniform_function>(function))
3138 								   << "() function did not generate GL_INVALID_OPERATION error when called for"
3139 									  " a uniform of incompatible type."
3140 								   << tcu::TestLog::EndMessage;
3141 
3142 				result = false;
3143 			}
3144 		}
3145 	} /* for (all checks) */
3146 
3147 	return result;
3148 }
3149 
3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3151  *  glUniform*dv() functions are called without a bound program object.
3152  *
3153  *  @return true if the implementation was found to behave as expected, false otherwise.
3154  **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3156 {
3157 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
3158 	bool				  result = true;
3159 
3160 	for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3161 		 function++)
3162 	{
3163 		const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
3164 
3165 		switch (static_cast<_uniform_function>(function))
3166 		{
3167 		case UNIFORM_FUNCTION_1D:
3168 			gl.uniform1d(m_po_double_uniform_location, 0.0);
3169 			break;
3170 		case UNIFORM_FUNCTION_1DV:
3171 			gl.uniform1dv(m_po_double_uniform_location, 1, data);
3172 			break;
3173 		case UNIFORM_FUNCTION_2D:
3174 			gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3175 			break;
3176 		case UNIFORM_FUNCTION_2DV:
3177 			gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3178 			break;
3179 		case UNIFORM_FUNCTION_3D:
3180 			gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3181 			break;
3182 		case UNIFORM_FUNCTION_3DV:
3183 			gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3184 			break;
3185 		case UNIFORM_FUNCTION_4D:
3186 			gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3187 			break;
3188 		case UNIFORM_FUNCTION_4DV:
3189 			gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3190 			break;
3191 
3192 		case UNIFORM_FUNCTION_MATRIX2DV:
3193 			gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3194 			break;
3195 		case UNIFORM_FUNCTION_MATRIX2X3DV:
3196 			gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3197 			break;
3198 		case UNIFORM_FUNCTION_MATRIX2X4DV:
3199 			gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3200 			break;
3201 		case UNIFORM_FUNCTION_MATRIX3DV:
3202 			gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3203 			break;
3204 		case UNIFORM_FUNCTION_MATRIX3X2DV:
3205 			gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3206 			break;
3207 		case UNIFORM_FUNCTION_MATRIX3X4DV:
3208 			gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3209 			break;
3210 		case UNIFORM_FUNCTION_MATRIX4DV:
3211 			gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3212 			break;
3213 		case UNIFORM_FUNCTION_MATRIX4X2DV:
3214 			gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3215 			break;
3216 		case UNIFORM_FUNCTION_MATRIX4X3DV:
3217 			gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3218 			break;
3219 
3220 		default:
3221 		{
3222 			TCU_FAIL("Unrecognized uniform function");
3223 		}
3224 		} /* switch (func) */
3225 
3226 		/* Query the error code */
3227 		glw::GLenum error_code = gl.getError();
3228 
3229 		if (error_code != GL_INVALID_OPERATION)
3230 		{
3231 			m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3232 							   << getUniformFunctionString(static_cast<_uniform_function>(function))
3233 							   << "() was called without an active program object" << tcu::TestLog::EndMessage;
3234 
3235 			result = false;
3236 		}
3237 	} /* for (all uniform functions) */
3238 
3239 	return result;
3240 }
3241 
3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3244 const glw::GLint  GPUShaderFP64Test2::m_result_failure	 = 2;
3245 const glw::GLint  GPUShaderFP64Test2::m_result_success	 = 1;
3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width	  = 32;
3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height	 = m_n_captured_results / m_texture_width;
3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3249 	m_n_captured_results * sizeof(captured_varying_type);
3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name				  = "UniformBlock";
3251 const glw::GLenum  GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3252 
3253 /** Constructor
3254  *
3255  * @param context Test context
3256  **/
GPUShaderFP64Test2(deqp::Context & context)3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context)
3258 	: TestCase(context, "max_uniform_components",
3259 			   "Verifies that maximum allowed uniform components can be used as double-precision float types")
3260 	, m_pDispatchCompute(0)
3261 	, m_framebuffer_id(0)
3262 	, m_texture_id(0)
3263 	, m_transform_feedback_buffer_id(0)
3264 	, m_uniform_buffer_id(0)
3265 	, m_vertex_array_object_id(0)
3266 {
3267 	/* Nothing to be done */
3268 }
3269 
3270 /** Deinitialize test
3271  *
3272  **/
deinit()3273 void GPUShaderFP64Test2::deinit()
3274 {
3275 	/* GL entry points */
3276 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3277 
3278 	/* Clean frambuffer */
3279 	if (0 != m_framebuffer_id)
3280 	{
3281 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3282 		gl.deleteFramebuffers(1, &m_framebuffer_id);
3283 		m_framebuffer_id = 0;
3284 	}
3285 
3286 	/* Clean texture */
3287 	if (0 != m_texture_id)
3288 	{
3289 		gl.bindTexture(GL_TEXTURE_2D, 0);
3290 		gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3291 							GL_READ_ONLY, GL_RGBA8);
3292 		gl.deleteTextures(1, &m_texture_id);
3293 		m_texture_id = 0;
3294 	}
3295 
3296 	/* Clean buffers */
3297 	if (0 != m_transform_feedback_buffer_id)
3298 	{
3299 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3300 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3301 		m_transform_feedback_buffer_id = 0;
3302 	}
3303 
3304 	if (0 != m_uniform_buffer_id)
3305 	{
3306 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3307 		gl.deleteBuffers(1, &m_uniform_buffer_id);
3308 		m_uniform_buffer_id = 0;
3309 	}
3310 
3311 	/* Clean VAO */
3312 	if (0 != m_vertex_array_object_id)
3313 	{
3314 		gl.bindVertexArray(0);
3315 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3316 		m_vertex_array_object_id = 0;
3317 	}
3318 }
3319 
3320 /** Execute test
3321  *
3322  * @return tcu::TestNode::STOP
3323  **/
iterate()3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3325 {
3326 	bool result = true;
3327 
3328 	/* Check if extension is supported */
3329 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3330 	{
3331 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3332 	}
3333 
3334 	/* Initialize test */
3335 	testInit();
3336 
3337 	prepareShaderStages();
3338 	prepareUniformTypes();
3339 
3340 	/* For all shaders and uniform type combinations */
3341 	for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3342 		 m_shader_stages.end() != shader_stage; ++shader_stage)
3343 	{
3344 		for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3345 			 m_uniform_types.end() != uniform_type; ++uniform_type)
3346 		{
3347 			/* Execute test */
3348 			if (false == test(*shader_stage, *uniform_type))
3349 			{
3350 				result = false;
3351 			}
3352 		}
3353 	}
3354 
3355 	/* Set result */
3356 	if (true == result)
3357 	{
3358 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3359 	}
3360 	else
3361 	{
3362 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3363 	}
3364 
3365 	/* Done */
3366 	return tcu::TestNode::STOP;
3367 }
3368 
3369 /** Constructor
3370  *
3371  * @param n_columns Number of columns
3372  * @param n_rows    Number of rows
3373  **/
uniformTypeDetails(glw::GLuint n_columns,glw::GLuint n_rows)3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3375 	: m_n_columns(n_columns), m_n_rows(n_rows)
3376 {
3377 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3378 
3379 	m_type_name = Utils::getVariableTypeString(type);
3380 	m_type		= Utils::getGLDataTypeOfVariableType(type);
3381 }
3382 
3383 /** Get primitive type captured with transform feedback
3384  *
3385  * @param shader_stage Tested shader stage id
3386  *
3387  * @return Primitive type
3388  **/
getCapturedPrimitiveType(shaderStage shader_stage) const3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3390 {
3391 	switch (shader_stage)
3392 	{
3393 	case GEOMETRY_SHADER:
3394 	case TESS_CTRL_SHADER:
3395 	case TESS_EVAL_SHADER:
3396 	case VERTEX_SHADER:
3397 		return GL_POINTS;
3398 
3399 	default:
3400 		return GL_NONE;
3401 	}
3402 }
3403 
3404 /** Get primitive type drawn with DrawArrays
3405  *
3406  * @param shader_stage Tested shader stage id
3407  *
3408  * @return Primitive type
3409  **/
getDrawPrimitiveType(shaderStage shader_stage) const3410 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3411 {
3412 	switch (shader_stage)
3413 	{
3414 	case FRAGMENT_SHADER:
3415 		return GL_TRIANGLE_FAN;
3416 
3417 	case GEOMETRY_SHADER:
3418 	case VERTEX_SHADER:
3419 		return GL_POINTS;
3420 
3421 	case TESS_CTRL_SHADER:
3422 	case TESS_EVAL_SHADER:
3423 		return GL_PATCHES;
3424 
3425 	default:
3426 		return GL_NONE;
3427 	}
3428 }
3429 
3430 /** Get maximum allowed number of uniform components
3431  *
3432  * @param shader_stage Tested shader stage id
3433  *
3434  * @return Maxmimum uniform components
3435  **/
getMaxUniformComponents(shaderStage shader_stage) const3436 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3437 {
3438 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3439 	glw::GLint			  max_uniform_components = 0;
3440 	glw::GLenum			  pname					 = 0;
3441 
3442 	switch (shader_stage)
3443 	{
3444 	case COMPUTE_SHADER:
3445 		pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3446 		break;
3447 	case FRAGMENT_SHADER:
3448 		pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3449 		break;
3450 	case GEOMETRY_SHADER:
3451 		pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3452 		break;
3453 	case TESS_CTRL_SHADER:
3454 		pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3455 		break;
3456 	case TESS_EVAL_SHADER:
3457 		pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3458 		break;
3459 	case VERTEX_SHADER:
3460 		pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3461 		break;
3462 	}
3463 
3464 	gl.getIntegerv(pname, &max_uniform_components);
3465 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3466 
3467 	return max_uniform_components;
3468 }
3469 
3470 /** Get maximum size allowed for an uniform block
3471  *
3472  * @return Maxmimum uniform block size
3473  **/
getMaxUniformBlockSize() const3474 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3475 {
3476 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
3477 	glw::GLint			  max_uniform_block_size = 0;
3478 
3479 	gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3480 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3481 
3482 	return max_uniform_block_size;
3483 }
3484 
3485 /** Get number of components required to store single uniform of given type
3486  *
3487  * @param uniform_type Tested uniform type
3488  *
3489  * @return Number of components
3490  **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3491 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3492 {
3493 	static const glw::GLuint type_size	 = 2; /* double takes 2 N */
3494 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3495 
3496 	if (1 == uniform_type.m_n_columns)
3497 	{
3498 		return type_size * column_length;
3499 	}
3500 	else
3501 	{
3502 		const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3503 
3504 		return alignment * uniform_type.m_n_columns;
3505 	}
3506 }
3507 
3508 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3509  *
3510  * @param uniform_type Tested uniform type
3511  *
3512  * @return Size of a single member
3513  **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3514 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3515 {
3516 	static const glw::GLuint vec4_size	 = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3517 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
3518 
3519 	/** Size for a layout(std140, column_major) uniform_type uniform[] **/
3520 	return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3521 }
3522 
3523 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3524  *
3525  * @param shader_stage Tested shader stage id
3526  * @param uniform_type Tested uniform type
3527  *
3528  * @return Number of components
3529  **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3530 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage				shader_stage,
3531 												  const uniformTypeDetails& uniform_type) const
3532 {
3533 	const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
3534 	const glw::GLuint required_components	  = getRequiredComponentsNumber(uniform_type);
3535 	const glw::GLuint n_uniforms			   = max_uniform_components / required_components;
3536 	const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
3537 	const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3538 	const glw::GLuint max_uniforms			   = max_uniform_block_size / uniform_type_member_size;
3539 
3540 	return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3541 }
3542 
3543 /** Get name of shader stage
3544  *
3545  * @param shader_stage Tested shader stage id
3546  *
3547  * @return Name
3548  **/
getShaderStageName(shaderStage shader_stage) const3549 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3550 {
3551 	switch (shader_stage)
3552 	{
3553 	case COMPUTE_SHADER:
3554 		return "compute shader";
3555 	case FRAGMENT_SHADER:
3556 		return "fragment shader";
3557 	case GEOMETRY_SHADER:
3558 		return "geometry shader";
3559 	case TESS_CTRL_SHADER:
3560 		return "tesselation control shader";
3561 	case TESS_EVAL_SHADER:
3562 		return "tesselation evaluation shader";
3563 	case VERTEX_SHADER:
3564 		return "vertex shader";
3565 	}
3566 
3567 	return 0;
3568 }
3569 
3570 /** Inspect program to get: buffer_size, offset, strides and block index
3571  *
3572  * @param program_id          Program id
3573  * @param out_buffer_size     Size of uniform buffer
3574  * @param out_uniform_details Uniform offset and strides
3575  * @param uniform_block_index Uniform block index
3576  **/
inspectProgram(glw::GLuint program_id,glw::GLint n_uniforms,const uniformTypeDetails & uniform_type,glw::GLint & out_buffer_size,uniformDetails & out_uniform_details,glw::GLuint & uniform_block_index) const3577 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3578 										const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3579 										uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const
3580 {
3581 	glw::GLint				 array_stride = 0;
3582 	std::vector<glw::GLchar> extracted_uniform_name;
3583 	const glw::Functions&	gl			   = m_context.getRenderContext().getFunctions();
3584 	glw::GLuint				 index		   = 0;
3585 	glw::GLint				 matrix_stride = 0;
3586 	glw::GLint				 offset		   = 0;
3587 	glw::GLsizei			 size		   = 0;
3588 	glw::GLenum				 type		   = 0;
3589 	const glw::GLchar*		 uniform_name  = 0;
3590 	std::string				 uniform_name_str;
3591 	std::stringstream		 uniform_name_stream;
3592 
3593 	/* Get index of uniform block */
3594 	uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3595 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3596 
3597 	if (GL_INVALID_INDEX == uniform_block_index)
3598 	{
3599 		TCU_FAIL("Unifom block is inactive");
3600 	}
3601 
3602 	/* Get size of uniform block */
3603 	gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3604 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3605 
3606 	if (0 == out_buffer_size)
3607 	{
3608 		TCU_FAIL("Unifom block size is 0");
3609 	}
3610 
3611 	/* Prepare uniform name */
3612 	uniform_name_stream << "uniform_array";
3613 
3614 	uniform_name_str = uniform_name_stream.str();
3615 	uniform_name	 = uniform_name_str.c_str();
3616 
3617 	/* Get index of uniform */
3618 	gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3619 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3620 
3621 	if (GL_INVALID_INDEX == index)
3622 	{
3623 		TCU_FAIL("Unifom is inactive");
3624 	}
3625 
3626 	/* Verify getActiveUniform results */
3627 	extracted_uniform_name.resize(uniform_name_str.length() * 2);
3628 
3629 	gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3630 						&extracted_uniform_name[0]);
3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3632 
3633 	if ((n_uniforms != size) || (uniform_type.m_type != type))
3634 	{
3635 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3636 											<< " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3637 											<< " expected: " << uniform_type.m_type
3638 											<< ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3639 
3640 		TCU_FAIL("Invalid GetActiveUniform results");
3641 	}
3642 
3643 	/* Get offset of uniform */
3644 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3645 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3646 
3647 	if (-1 == offset)
3648 	{
3649 		TCU_FAIL("Unifom has invalid offset");
3650 	}
3651 
3652 	out_uniform_details.m_offset = offset;
3653 
3654 	/* Get matrix stride of uniform */
3655 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3656 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3657 
3658 	if (-1 == matrix_stride)
3659 	{
3660 		TCU_FAIL("Unifom has invalid matrix stride");
3661 	}
3662 
3663 	out_uniform_details.m_matrix_stride = matrix_stride;
3664 
3665 	/* Get array stride of uniform */
3666 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3667 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3668 
3669 	if (-1 == matrix_stride)
3670 	{
3671 		TCU_FAIL("Unifom has invalid matrix stride");
3672 	}
3673 
3674 	out_uniform_details.m_array_stride = array_stride;
3675 }
3676 
3677 /** Prepare source code for "boilerplate" shaders
3678  *
3679  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3680  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3681  * @param out_source_code          Source code
3682  **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3683 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3684 												  const glw::GLchar* stage_specific_main_body,
3685 												  std::string&		 out_source_code) const
3686 {
3687 	/* Shader template */
3688 	static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3689 																 "\n"
3690 																 "precision highp float;\n"
3691 																 "\n"
3692 																 "STAGE_SPECIFIC_LAYOUT"
3693 																 "void main()\n"
3694 																 "{\n"
3695 																 "STAGE_SPECIFIC_MAIN_BODY"
3696 																 "}\n"
3697 																 "\n";
3698 
3699 	std::string string = boilerplate_shader_template_code;
3700 
3701 	/* Tokens */
3702 	static const glw::GLchar* body_token   = "STAGE_SPECIFIC_MAIN_BODY";
3703 	static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3704 
3705 	size_t search_position = 0;
3706 
3707 	/* Replace tokens */
3708 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3709 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3710 
3711 	/* Store resuls */
3712 	out_source_code = string;
3713 }
3714 
3715 /** Prepare program for given combination of shader stage and uniform type
3716  *
3717  * @param shader_stage     Shader stage
3718  * @param uniform_type     Uniform type
3719  * @param out_program_info Instance of programInfo
3720  **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3721 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3722 										Utils::programInfo& out_program_info) const
3723 {
3724 	/* Stage specific layouts */
3725 	static const glw::GLchar* geometry_shader_layout_code = "layout(points)                   in;\n"
3726 															"layout(points, max_vertices = 1) out;\n"
3727 															"\n";
3728 
3729 	static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3730 															 "\n";
3731 
3732 	static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3733 															 "\n";
3734 
3735 	/* Stage specific main body */
3736 	static const glw::GLchar* boilerplate_fragment_shader_body_code = "    discard;\n";
3737 
3738 	static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
3739 																	   "    gl_TessLevelOuter[1] = 1.0;\n"
3740 																	   "    gl_TessLevelOuter[2] = 1.0;\n"
3741 																	   "    gl_TessLevelOuter[3] = 1.0;\n"
3742 																	   "    gl_TessLevelInner[0] = 1.0;\n"
3743 																	   "    gl_TessLevelInner[1] = 1.0;\n";
3744 
3745 	static const glw::GLchar* boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
3746 
3747 	static const glw::GLchar* corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
3748 															   "    {\n"
3749 															   "        gl_Position = vec4(-1, -1, 0, 1);\n"
3750 															   "    }\n"
3751 															   "    else if (1 == gl_VertexID)\n"
3752 															   "    {\n"
3753 															   "        gl_Position = vec4(-1, 1, 0, 1);\n"
3754 															   "    }\n"
3755 															   "    else if (2 == gl_VertexID)\n"
3756 															   "    {\n"
3757 															   "        gl_Position = vec4(1, 1, 0, 1);\n"
3758 															   "    }\n"
3759 															   "    else if (3 == gl_VertexID)\n"
3760 															   "    {\n"
3761 															   "        gl_Position = vec4(1, -1, 0, 1);\n"
3762 															   "    }\n";
3763 
3764 	static const glw::GLchar* passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
3765 
3766 	static const glw::GLchar* test_shader_body_code = "\n    result = verification_result;\n";
3767 
3768 	static const glw::GLchar* test_geometry_shader_body_code = "\n    result = verification_result;\n"
3769 															   "\n"
3770 															   "    EmitVertex();\n"
3771 															   "    EndPrimitive();\n";
3772 
3773 	static const glw::GLchar* test_tess_ctrl_shader_body_code =
3774 		"\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
3775 		"\n"
3776 		"    gl_TessLevelOuter[0] = 1.0;\n"
3777 		"    gl_TessLevelOuter[1] = 1.0;\n"
3778 		"    gl_TessLevelOuter[2] = 1.0;\n"
3779 		"    gl_TessLevelOuter[3] = 1.0;\n"
3780 		"    gl_TessLevelInner[0] = 1.0;\n"
3781 		"    gl_TessLevelInner[1] = 1.0;\n";
3782 
3783 	/* In variables */
3784 	static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
3785 
3786 	/* Out variables */
3787 	static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3788 
3789 	static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3790 
3791 	static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3792 
3793 	/* Varying name */
3794 	static const glw::GLchar* varying_name = "result";
3795 	glw::GLuint				  n_varyings   = 1;
3796 
3797 	/* Storage for ready shaders */
3798 	std::string compute_shader_code;
3799 	std::string fragment_shader_code;
3800 	std::string geometry_shader_code;
3801 	std::string tess_ctrl_shader_code;
3802 	std::string tess_eval_shader_code;
3803 	std::string vertex_shader_code;
3804 
3805 	/* Storage for uniform definition and verification code */
3806 	std::string uniform_definitions;
3807 	std::string uniform_verification;
3808 
3809 	/* Get uniform definition and verification code */
3810 	prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3811 	prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3812 
3813 	/* Prepare vertex shader */
3814 	switch (shader_stage)
3815 	{
3816 	case FRAGMENT_SHADER:
3817 
3818 		prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3819 
3820 		break;
3821 
3822 	case GEOMETRY_SHADER:
3823 	case TESS_CTRL_SHADER:
3824 	case TESS_EVAL_SHADER:
3825 
3826 		prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3827 
3828 		break;
3829 
3830 	case VERTEX_SHADER:
3831 
3832 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3833 						  test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3834 						  test_shader_body_code /* body */, vertex_shader_code);
3835 
3836 		break;
3837 
3838 	default:
3839 		break;
3840 	}
3841 
3842 	/* Prepare fragment shader */
3843 	switch (shader_stage)
3844 	{
3845 	case FRAGMENT_SHADER:
3846 
3847 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3848 						  test_fragment_shader_out_variable /* out var */,
3849 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3850 						  fragment_shader_code);
3851 
3852 		break;
3853 
3854 	case GEOMETRY_SHADER:
3855 	case TESS_CTRL_SHADER:
3856 	case TESS_EVAL_SHADER:
3857 	case VERTEX_SHADER:
3858 
3859 		prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3860 								 fragment_shader_code);
3861 
3862 		break;
3863 
3864 	default:
3865 		break;
3866 	}
3867 
3868 	/* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3869 	switch (shader_stage)
3870 	{
3871 	case COMPUTE_SHADER:
3872 
3873 		prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3874 
3875 		break;
3876 
3877 	case GEOMETRY_SHADER:
3878 
3879 		prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3880 						  "" /* in var */, test_shader_out_variable /* out var */,
3881 						  uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3882 						  geometry_shader_code);
3883 
3884 		break;
3885 
3886 	case TESS_CTRL_SHADER:
3887 
3888 		prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3889 						  "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3890 						  uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3891 						  tess_ctrl_shader_code);
3892 
3893 		prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3894 						  test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3895 						  "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3896 						  tess_eval_shader_code);
3897 
3898 		break;
3899 
3900 	case TESS_EVAL_SHADER:
3901 
3902 		prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3903 								 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3904 
3905 		prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3906 						  "" /* in var */, test_shader_out_variable /* out var */,
3907 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3908 						  tess_eval_shader_code);
3909 
3910 		break;
3911 
3912 	default:
3913 		break;
3914 	}
3915 
3916 	/* Select shaders that will be used by program */
3917 	const glw::GLchar* cs_c_str  = 0;
3918 	const glw::GLchar* fs_c_str  = 0;
3919 	const glw::GLchar* gs_c_str  = 0;
3920 	const glw::GLchar* tcs_c_str = 0;
3921 	const glw::GLchar* tes_c_str = 0;
3922 	const glw::GLchar* vs_c_str  = 0;
3923 
3924 	if (false == compute_shader_code.empty())
3925 	{
3926 		cs_c_str = compute_shader_code.c_str();
3927 	}
3928 
3929 	if (false == fragment_shader_code.empty())
3930 	{
3931 		fs_c_str = fragment_shader_code.c_str();
3932 	}
3933 
3934 	if (false == geometry_shader_code.empty())
3935 	{
3936 		gs_c_str = geometry_shader_code.c_str();
3937 	}
3938 
3939 	if (false == tess_ctrl_shader_code.empty())
3940 	{
3941 		tcs_c_str = tess_ctrl_shader_code.c_str();
3942 	}
3943 
3944 	if (false == tess_eval_shader_code.empty())
3945 	{
3946 		tes_c_str = tess_eval_shader_code.c_str();
3947 	}
3948 
3949 	if (false == vertex_shader_code.empty())
3950 	{
3951 		vs_c_str = vertex_shader_code.c_str();
3952 	}
3953 
3954 	/* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3955 	if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3956 	{
3957 		n_varyings = 0;
3958 	}
3959 
3960 	/* Build */
3961 	out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
3962 }
3963 
3964 /** Prepare collection of tested shader stages
3965  *
3966  */
prepareShaderStages()3967 void GPUShaderFP64Test2::prepareShaderStages()
3968 {
3969 	/* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3970 	if (0 != m_pDispatchCompute)
3971 	{
3972 		m_shader_stages.push_back(COMPUTE_SHADER);
3973 	}
3974 
3975 	m_shader_stages.push_back(FRAGMENT_SHADER);
3976 	m_shader_stages.push_back(GEOMETRY_SHADER);
3977 	m_shader_stages.push_back(TESS_CTRL_SHADER);
3978 	m_shader_stages.push_back(TESS_EVAL_SHADER);
3979 	m_shader_stages.push_back(VERTEX_SHADER);
3980 }
3981 
3982 /** Prepare source code for "tested" shader stage
3983  *
3984  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3985  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
3986  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
3987  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
3988  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
3989  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3990  * @param out_source_code          Shader source code
3991  **/
prepareTestShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * uniform_definitions,const glw::GLchar * in_variable_definitions,const glw::GLchar * out_variable_definitions,const glw::GLchar * uniform_verification,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3992 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
3993 										   const glw::GLchar* uniform_definitions,
3994 										   const glw::GLchar* in_variable_definitions,
3995 										   const glw::GLchar* out_variable_definitions,
3996 										   const glw::GLchar* uniform_verification,
3997 										   const glw::GLchar* stage_specific_main_body,
3998 										   std::string&		  out_source_code) const
3999 {
4000 	/* Shader template */
4001 	static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4002 														  "\n"
4003 														  "precision highp float;\n"
4004 														  "\n"
4005 														  "STAGE_SPECIFIC_LAYOUT"
4006 														  "UNIFORM_DEFINITIONS"
4007 														  "IN_VARIABLE_DEFINITION"
4008 														  "OUT_VARIABLE_DEFINITION"
4009 														  "\n"
4010 														  "void main()\n"
4011 														  "{\n"
4012 														  "UNIFORM_VERIFICATION"
4013 														  "STAGE_SPECIFIC_MAIN_BODY"
4014 														  "}\n"
4015 														  "\n";
4016 
4017 	std::string string = test_shader_template_code;
4018 
4019 	/* Tokens */
4020 	static const glw::GLchar* body_token	= "STAGE_SPECIFIC_MAIN_BODY";
4021 	static const glw::GLchar* in_var_token  = "IN_VARIABLE_DEFINITION";
4022 	static const glw::GLchar* layout_token  = "STAGE_SPECIFIC_LAYOUT";
4023 	static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4024 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4025 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4026 
4027 	size_t search_position = 0;
4028 
4029 	/* Replace tokens */
4030 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4031 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4032 	Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4033 	Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4034 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4035 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4036 
4037 	/* Store resuls */
4038 	out_source_code = string;
4039 }
4040 
4041 /** Prepare source code for "tested" compute shaders
4042  *
4043  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
4044  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4045  * @param out_source_code      Source code
4046  **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4047 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4048 												  const glw::GLchar* uniform_verification,
4049 												  std::string&		 out_source_code) const
4050 {
4051 	/* Shader template */
4052 	static const glw::GLchar* test_shader_template_code =
4053 		"#version 420 core\n"
4054 		"#extension GL_ARB_compute_shader          : require\n"
4055 		"#extension GL_ARB_shader_image_load_store : require\n"
4056 		"\n"
4057 		"precision highp float;\n"
4058 		"\n"
4059 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4060 		"\n"
4061 		"UNIFORM_DEFINITIONS"
4062 		"layout(r32i) writeonly uniform iimage2D result;\n"
4063 		"\n"
4064 		"void main()\n"
4065 		"{\n"
4066 		"UNIFORM_VERIFICATION"
4067 		"\n"
4068 		"    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4069 		"}\n"
4070 		"\n";
4071 
4072 	std::string string = test_shader_template_code;
4073 
4074 	/* Tokens */
4075 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4076 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4077 
4078 	size_t search_position = 0;
4079 
4080 	/* Replace tokens */
4081 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4082 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083 
4084 	/* Store resuls */
4085 	out_source_code = string;
4086 }
4087 
4088 /** Prepare source code which defines uniforms for tested shader stage
4089  *
4090  * @param shader_stage    Shader stage id
4091  * @param uniform_type    Details of uniform type
4092  * @param out_source_code Source code
4093  **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4094 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4095 												   std::string& out_source_code) const
4096 {
4097 	const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4098 	std::stringstream stream;
4099 
4100 	/*
4101 	 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4102 	 * {
4103 	 *     TYPE_NAME uniform_array[N_UNIFORMS];
4104 	 * };
4105 	 */
4106 	stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4107 																   "{\n";
4108 
4109 	stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4110 
4111 	stream << "};\n\n";
4112 
4113 	out_source_code = stream.str();
4114 }
4115 
4116 /** Prepare uniform buffer for test
4117  *
4118  * @param shader_stage Shader stage id
4119  * @param uniform_type Details of uniform type
4120  * @param program_info Program object info
4121  **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4122 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4123 										 const Utils::programInfo& program_info) const
4124 {
4125 	glw::GLint				  buffer_size	 = 0;
4126 	glw::GLuint				  element_ordinal = 1;
4127 	const glw::Functions&	 gl			  = m_context.getRenderContext().getFunctions();
4128 	const glw::GLuint		  n_columns		  = uniform_type.m_n_columns;
4129 	const glw::GLuint		  n_rows		  = uniform_type.m_n_rows;
4130 	const glw::GLuint		  n_elements	  = n_columns * n_rows;
4131 	uniformDetails			  uniform_details;
4132 	const glw::GLuint		  program_id = program_info.m_program_object_id;
4133 	const glw::GLint		  n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4134 	std::vector<glw::GLubyte> uniform_buffer_data;
4135 	glw::GLuint				  uniform_block_index = 0;
4136 
4137 	/* Get uniform details */
4138 	inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4139 
4140 	/* Uniform offset and strides */
4141 	const glw::GLuint array_stride   = uniform_details.m_array_stride;
4142 	const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
4143 	const glw::GLuint uniform_offset = uniform_details.m_offset;
4144 
4145 	/* Prepare storage for buffer data */
4146 	uniform_buffer_data.resize(buffer_size);
4147 
4148 	/* Prepare uniform data */
4149 	for (glw::GLint i = 0; i < n_uniforms; ++i)
4150 	{
4151 		const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4152 
4153 		for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4154 		{
4155 			const glw::GLuint   column		 = element / n_rows;
4156 			const glw::GLuint   column_elem  = element % n_rows;
4157 			const glw::GLdouble value		 = element_ordinal;
4158 			const glw::GLuint   value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4159 																	  column_elem * sizeof(glw::GLdouble));
4160 			glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4161 
4162 			*value_dst = value;
4163 		}
4164 	}
4165 
4166 	/* Update uniform buffer with new set of data */
4167 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4168 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4169 
4170 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4171 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4172 
4173 	/* Bind uniform block to uniform buffer */
4174 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4175 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4176 
4177 	gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4178 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4179 }
4180 
4181 /** Prepare collection of tested uniform types
4182  *
4183  **/
prepareUniformTypes()4184 void GPUShaderFP64Test2::prepareUniformTypes()
4185 {
4186 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4187 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4188 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4189 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4190 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4191 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4192 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4193 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4194 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4195 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4196 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4197 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4198 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4199 }
4200 
4201 /** Prepare source code that verifes uniform values
4202  *
4203  * @param shader_stage    Shader stage id
4204  * @param uniform_type    Details of uniform type
4205  * @param out_source_code Source code
4206  **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4207 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4208 													std::string& out_source_code) const
4209 {
4210 	glw::GLuint		  element_ordinal = 1;
4211 	const glw::GLuint n_columns		  = uniform_type.m_n_columns;
4212 	const glw::GLuint n_rows		  = uniform_type.m_n_rows;
4213 	const glw::GLuint n_elements	  = n_columns * n_rows;
4214 	const glw::GLuint n_uniforms	  = getAmountUniforms(shader_stage, uniform_type);
4215 	std::stringstream stream;
4216 
4217 	/*
4218 	 * int verification_result = M_RESULT_SUCCESS;
4219 	 *
4220 	 * for (int i = 0; i < N_UNIFORMS; ++i)
4221 	 * {
4222 	 *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4223 	 *     {
4224 	 *         verification_result = M_RESULT_FAILURE
4225 	 *     }
4226 	 * }
4227 	 */
4228 	stream << "    int verification_result = " << m_result_success << ";\n"
4229 																	  "\n"
4230 																	  "    for (int i = 0; i < "
4231 		   << n_uniforms << "; ++i)\n"
4232 							"    {\n"
4233 							"        if ("
4234 		   << uniform_type.m_type_name << "(";
4235 
4236 	for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4237 	{
4238 		stream << "i * (" << n_elements << ") + " << element + 1;
4239 
4240 		if (n_elements != element + 1)
4241 		{
4242 			stream << ", ";
4243 		}
4244 	}
4245 
4246 	stream << ") != uniform_array[i])\n"
4247 			  "        {\n"
4248 			  "           verification_result = "
4249 		   << m_result_failure << ";\n"
4250 								  "        }\n"
4251 								  "    }\n";
4252 
4253 	out_source_code = stream.str();
4254 }
4255 
4256 /** Execute test for given combination of "tested" shader stage and uniform type
4257  *
4258  * @param shader_stage Tested shader stage id
4259  * @param uniform_type Tested uniform type
4260  *
4261  * @return true if test passed, false otherwise
4262  **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4263 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4264 {
4265 	const glw::GLenum		draw_primitive = getDrawPrimitiveType(shader_stage);
4266 	static const glw::GLint first_vertex   = 0;
4267 	const glw::Functions&   gl			   = m_context.getRenderContext().getFunctions();
4268 	const glw::GLsizei		n_vertices	 = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4269 	Utils::programInfo		program_info(m_context);
4270 	bool					result = true;
4271 
4272 	/* Prepare program */
4273 	prepareProgram(shader_stage, uniform_type, program_info);
4274 
4275 	gl.useProgram(program_info.m_program_object_id);
4276 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4277 
4278 	/* Prepare uniform buffer and bind it with uniform block */
4279 	prepareUniforms(shader_stage, uniform_type, program_info);
4280 
4281 	/* Prepare storage for test results */
4282 	testBegin(program_info.m_program_object_id, shader_stage);
4283 
4284 	/* Execute */
4285 	if (COMPUTE_SHADER == shader_stage)
4286 	{
4287 		m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4288 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4289 	}
4290 	else
4291 	{
4292 		gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4293 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4294 	}
4295 
4296 	/* Clean after test */
4297 	testEnd(shader_stage);
4298 
4299 	/* Check results */
4300 	if (false == verifyResults(shader_stage))
4301 	{
4302 		m_context.getTestContext().getLog()
4303 			<< tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4304 			<< ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4305 
4306 		result = false;
4307 	}
4308 
4309 	return result;
4310 }
4311 
4312 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4313  *
4314  * @param program_id   Program object id
4315  * @param shader_stage Tested shader stage id
4316  **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4317 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4318 {
4319 	std::vector<glw::GLint> buffer_data;
4320 	const glw::GLenum		captured_primitive = getCapturedPrimitiveType(shader_stage);
4321 	const glw::Functions&   gl				   = m_context.getRenderContext().getFunctions();
4322 
4323 	/* Prepare buffer filled with m_result_failure */
4324 	buffer_data.resize(m_n_captured_results);
4325 	for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4326 	{
4327 		buffer_data[i] = m_result_failure;
4328 	}
4329 
4330 	/* Prepare buffer for test results */
4331 	switch (shader_stage)
4332 	{
4333 	case GEOMETRY_SHADER:
4334 	case TESS_CTRL_SHADER:
4335 	case TESS_EVAL_SHADER:
4336 	case VERTEX_SHADER:
4337 
4338 		/* Verify getTransformFeedbackVarying results */
4339 		{
4340 			glw::GLsizei size = 0;
4341 			glw::GLenum  type = 0;
4342 			glw::GLchar  name[16];
4343 
4344 			gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4345 										   name);
4346 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4347 
4348 			if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4349 			{
4350 				m_context.getTestContext().getLog()
4351 					<< tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4352 					<< " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4353 					<< ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4354 
4355 				TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4356 			}
4357 		}
4358 
4359 		/* Create/clean transform feedback buffer */
4360 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4361 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4362 
4363 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4364 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4365 
4366 		/* Set up transform feedback buffer */
4367 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4368 						   m_transform_feedback_buffer_size);
4369 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4370 
4371 		gl.beginTransformFeedback(captured_primitive);
4372 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4373 
4374 		break;
4375 
4376 	case FRAGMENT_SHADER:
4377 
4378 		/* Clean texture */
4379 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4380 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4381 
4382 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4383 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4385 
4386 		/* Set up texture as color attachment 0 */
4387 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4388 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4389 
4390 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4391 		GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4392 
4393 		gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4394 		GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4395 
4396 		break;
4397 
4398 	case COMPUTE_SHADER:
4399 
4400 		/* Clean texture */
4401 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4402 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4403 
4404 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4405 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4406 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4407 
4408 		glw::GLint location = gl.getUniformLocation(program_id, "result");
4409 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4410 
4411 		if (-1 == location)
4412 		{
4413 			TCU_FAIL("Inactive uniform \"result\"");
4414 		}
4415 
4416 		gl.uniform1i(location, 0 /* first image unit */);
4417 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4418 
4419 		/* Bind texture to first image unit */
4420 		gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4421 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4422 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4423 
4424 		break;
4425 	}
4426 }
4427 
4428 /** Unbind transform feedback buffer, framebuffer or image unit
4429  *
4430  * @param shader_stage Tested shader stage id
4431  **/
testEnd(shaderStage shader_stage) const4432 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4433 {
4434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4435 
4436 	switch (shader_stage)
4437 	{
4438 	case GEOMETRY_SHADER:
4439 	case TESS_CTRL_SHADER:
4440 	case TESS_EVAL_SHADER:
4441 	case VERTEX_SHADER:
4442 
4443 		gl.endTransformFeedback();
4444 
4445 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4446 
4447 		break;
4448 
4449 	case FRAGMENT_SHADER:
4450 
4451 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4452 								0 /* level */);
4453 
4454 		gl.bindTexture(GL_TEXTURE_2D, 0);
4455 
4456 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4457 
4458 		break;
4459 
4460 	case COMPUTE_SHADER:
4461 
4462 		gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4463 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4464 
4465 		break;
4466 	}
4467 }
4468 
4469 /** Initialize OpenGL objects for test
4470  *
4471  **/
testInit()4472 void GPUShaderFP64Test2::testInit()
4473 {
4474 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4475 
4476 	/* The test is in 4.0 group. However:
4477 	 * - compute_shader is core since 4.3
4478 	 * - compute_shader require at least version 4.2 of GL */
4479 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4480 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4481 	{
4482 		m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4483 	}
4484 
4485 	/* Tesselation patch set up */
4486 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
4487 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4488 
4489 	/* Generate FBO */
4490 	gl.genFramebuffers(1, &m_framebuffer_id);
4491 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4492 
4493 	/* Prepare texture */
4494 	gl.genTextures(1, &m_texture_id);
4495 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4496 
4497 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4498 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4499 
4500 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4501 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4502 
4503 	/* Prepare transform feedback buffer */
4504 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
4505 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4506 
4507 	/* Generate uniform buffer */
4508 	gl.genBuffers(1, &m_uniform_buffer_id);
4509 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4510 
4511 	/* Prepare VAO */
4512 	gl.genVertexArrays(1, &m_vertex_array_object_id);
4513 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4514 
4515 	gl.bindVertexArray(m_vertex_array_object_id);
4516 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4517 }
4518 
4519 /** Result verification, expected result is that whole buffer is filled with m_result_success
4520  *
4521  * @param shader_stage Tested shader stage id
4522  **/
verifyResults(shaderStage shader_stage) const4523 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4524 {
4525 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4526 
4527 	if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4528 	{
4529 		/* Verify contents of texture */
4530 
4531 		/* Prepare storage for testure data */
4532 		std::vector<glw::GLint> image_data;
4533 		image_data.resize(m_texture_width * m_texture_height);
4534 
4535 		/* Get texture contents */
4536 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4537 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4538 
4539 		gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4540 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4541 
4542 		for (glw::GLuint y = 0; y < m_texture_width; ++y)
4543 		{
4544 			for (glw::GLuint x = 0; x < m_texture_height; ++x)
4545 			{
4546 				const glw::GLuint offset = y * m_texture_width + x;
4547 				const glw::GLint  value  = image_data[offset];
4548 
4549 				if (m_result_success != value)
4550 				{
4551 					m_context.getTestContext().getLog()
4552 						<< tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4553 						<< tcu::TestLog::EndMessage;
4554 
4555 					return false;
4556 				}
4557 			}
4558 		}
4559 
4560 		return true;
4561 	}
4562 	else
4563 	{
4564 		/* Verify contents of transform feedback buffer */
4565 
4566 		bool result = true;
4567 
4568 		/* Get transform feedback data */
4569 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4570 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4571 
4572 		glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4573 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4574 
4575 		for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4576 		{
4577 			const glw::GLint value = feedback_data[i];
4578 
4579 			if (m_result_success != value)
4580 			{
4581 				m_context.getTestContext().getLog() << tcu::TestLog::Message
4582 													<< "Error. Transform feedback buffer contents are wrong at " << i
4583 													<< tcu::TestLog::EndMessage;
4584 
4585 				result = false;
4586 				break;
4587 			}
4588 		}
4589 
4590 		/* Unmap transform feedback buffer */
4591 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4592 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4593 
4594 		return result;
4595 	}
4596 }
4597 
4598 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4599 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4600 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4601 
4602 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name			 = "UniformBlock";
4603 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4604 
4605 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
4606 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result	= "gs_fs_gs_result";
4607 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
4608 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
4609 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result	= "gs_fs_vs_result";
4610 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4611 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
4612 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
4613 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
4614 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
4615 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
4616 
4617 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4618 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset			 = -1;
4619 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride	= -1;
4620 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4621 
4622 /** Constructor
4623  *
4624  * @param context Test context
4625  **/
GPUShaderFP64Test3(deqp::Context & context)4626 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4627 	: TestCase(context, "named_uniform_blocks",
4628 			   "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4629 {
4630 	/* Nothing to be done */
4631 }
4632 
4633 /** Deinitialize test
4634  *
4635  **/
deinit()4636 void GPUShaderFP64Test3::deinit()
4637 {
4638 	/* GL entry points */
4639 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4640 
4641 	/* Clean programs */
4642 	m_packed_program.deinit(m_context);
4643 	m_shared_program.deinit(m_context);
4644 	m_std140_program.deinit(m_context);
4645 
4646 	/* Clean frambuffer */
4647 	if (0 != m_framebuffer_id)
4648 	{
4649 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4650 		gl.deleteFramebuffers(1, &m_framebuffer_id);
4651 
4652 		m_framebuffer_id = 0;
4653 	}
4654 
4655 	/* Clean texture */
4656 	if (0 != m_color_texture_id)
4657 	{
4658 		gl.bindTexture(GL_TEXTURE_2D, 0);
4659 		gl.deleteTextures(1, &m_color_texture_id);
4660 
4661 		m_color_texture_id = 0;
4662 	}
4663 
4664 	/* Clean buffers */
4665 	if (0 != m_transform_feedback_buffer_id)
4666 	{
4667 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4668 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4669 
4670 		m_transform_feedback_buffer_id = 0;
4671 	}
4672 
4673 	if (0 != m_uniform_buffer_id)
4674 	{
4675 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4676 		gl.deleteBuffers(1, &m_uniform_buffer_id);
4677 
4678 		m_uniform_buffer_id = 0;
4679 	}
4680 
4681 	/* Clean VAO */
4682 	if (0 != m_vertex_array_object_id)
4683 	{
4684 		gl.bindVertexArray(0);
4685 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4686 
4687 		m_vertex_array_object_id = 0;
4688 	}
4689 }
4690 
4691 /** Execute test
4692  *
4693  * @return tcu::TestNode::STOP
4694  **/
iterate()4695 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4696 {
4697 	bool result = true;
4698 
4699 	/* Check if extension is supported */
4700 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4701 	{
4702 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4703 	}
4704 
4705 	/* Initialize test */
4706 	testInit();
4707 
4708 	/* Test "packed" uniform buffer layout */
4709 	if (false == test(PACKED))
4710 	{
4711 		result = false;
4712 	}
4713 
4714 	/* Test "shared" uniform buffer layout */
4715 	if (false == test(SHARED))
4716 	{
4717 		result = false;
4718 	}
4719 
4720 	/* Test "std140" uniform buffer layout */
4721 	if (false == test(STD140))
4722 	{
4723 		result = false;
4724 	}
4725 
4726 	/* Set result */
4727 	if (true == result)
4728 	{
4729 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4730 	}
4731 	else
4732 	{
4733 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4734 	}
4735 
4736 	/* Done */
4737 	return tcu::TestNode::STOP;
4738 }
4739 
4740 /** Constructor
4741  *
4742  **/
programInfo()4743 GPUShaderFP64Test3::programInfo::programInfo()
4744 	: m_fragment_shader_id(0)
4745 	, m_geometry_shader_id(0)
4746 	, m_program_object_id(0)
4747 	, m_tesselation_control_shader_id(0)
4748 	, m_tesselation_evaluation_shader_id(0)
4749 	, m_vertex_shader_id(0)
4750 	, m_buffer_size(0)
4751 	, m_uniform_block_index(0)
4752 {
4753 	/* Nothing to be done here */
4754 }
4755 
4756 /** Compile shader
4757  *
4758  * @param context     Test context
4759  * @param shader_id   Shader object id
4760  * @param shader_code Shader source code
4761  **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4762 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4763 											  const glw::GLchar* shader_code) const
4764 {
4765 	/* GL entry points */
4766 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4767 
4768 	/* Compilation status */
4769 	glw::GLint status = GL_FALSE;
4770 
4771 	/* Set source code */
4772 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4773 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4774 
4775 	/* Compile */
4776 	gl.compileShader(shader_id);
4777 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4778 
4779 	/* Get compilation status */
4780 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4781 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4782 
4783 	/* Log compilation error */
4784 	if (GL_TRUE != status)
4785 	{
4786 		glw::GLint				 length = 0;
4787 		std::vector<glw::GLchar> message;
4788 
4789 		/* Error log length */
4790 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4791 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4792 
4793 		/* Prepare storage */
4794 		message.resize(length);
4795 
4796 		/* Get error log */
4797 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4798 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4799 
4800 		/* Log */
4801 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4802 										  << &message[0] << "\nShader source\n"
4803 										  << shader_code << tcu::TestLog::EndMessage;
4804 
4805 		TCU_FAIL("Failed to compile shader");
4806 	}
4807 }
4808 
4809 /** Cleans program and attached shaders
4810  *
4811  * @param context Test context
4812  **/
deinit(deqp::Context & context)4813 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4814 {
4815 	/* GL entry points */
4816 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4817 
4818 	/* Restore default program */
4819 	gl.useProgram(0);
4820 
4821 	/* Clean program object */
4822 	if (0 != m_program_object_id)
4823 	{
4824 		gl.deleteProgram(m_program_object_id);
4825 		m_program_object_id = 0;
4826 	}
4827 
4828 	/* Clean shaders */
4829 	if (0 != m_fragment_shader_id)
4830 	{
4831 		gl.deleteShader(m_fragment_shader_id);
4832 		m_fragment_shader_id = 0;
4833 	}
4834 
4835 	if (0 != m_geometry_shader_id)
4836 	{
4837 		gl.deleteShader(m_geometry_shader_id);
4838 		m_geometry_shader_id = 0;
4839 	}
4840 
4841 	if (0 != m_tesselation_control_shader_id)
4842 	{
4843 		gl.deleteShader(m_tesselation_control_shader_id);
4844 		m_tesselation_control_shader_id = 0;
4845 	}
4846 
4847 	if (0 != m_tesselation_evaluation_shader_id)
4848 	{
4849 		gl.deleteShader(m_tesselation_evaluation_shader_id);
4850 		m_tesselation_evaluation_shader_id = 0;
4851 	}
4852 
4853 	if (0 != m_vertex_shader_id)
4854 	{
4855 		gl.deleteShader(m_vertex_shader_id);
4856 		m_vertex_shader_id = 0;
4857 	}
4858 }
4859 
4860 /** Build program and query for uniform layout
4861  *
4862  * @param context                            Test context
4863  * @param uniform_details                  Collection of uniform details
4864  * @param fragment_shader_code               Fragment shader source code
4865  * @param geometry_shader_code               Geometry shader source code
4866  * @param tesselation_control_shader_code    Tesselation control shader source code
4867  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4868  * @param vertex_shader_code                 Vertex shader source code
4869  **/
init(deqp::Context & context,const std::vector<uniformDetails> uniform_details,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code)4870 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4871 										   const glw::GLchar* fragment_shader_code,
4872 										   const glw::GLchar* geometry_shader_code,
4873 										   const glw::GLchar* tesselation_control_shader_code,
4874 										   const glw::GLchar* tesselation_evaluation_shader_code,
4875 										   const glw::GLchar* vertex_shader_code)
4876 {
4877 	/* GL entry points */
4878 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4879 
4880 	/* Names of varyings to be captured with transform feedback */
4881 	static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4882 												  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4883 	static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4884 
4885 	/* Create shader objects */
4886 	m_fragment_shader_id			   = gl.createShader(GL_FRAGMENT_SHADER);
4887 	m_geometry_shader_id			   = gl.createShader(GL_GEOMETRY_SHADER);
4888 	m_tesselation_control_shader_id	= gl.createShader(GL_TESS_CONTROL_SHADER);
4889 	m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4890 	m_vertex_shader_id				   = gl.createShader(GL_VERTEX_SHADER);
4891 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4892 
4893 	/* Create program object */
4894 	m_program_object_id = gl.createProgram();
4895 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4896 
4897 	/* Set up names of varyings to be captured with transform feedback */
4898 	gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4899 	GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4900 
4901 	/* Compile shaders */
4902 	compile(context, m_fragment_shader_id, fragment_shader_code);
4903 	compile(context, m_geometry_shader_id, geometry_shader_code);
4904 	compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4905 	compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4906 	compile(context, m_vertex_shader_id, vertex_shader_code);
4907 
4908 	/* Link program */
4909 	link(context);
4910 
4911 	/* Inspect program object */
4912 	/* Get index of named uniform block */
4913 	m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4914 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4915 
4916 	if (GL_INVALID_INDEX == m_uniform_block_index)
4917 	{
4918 		TCU_FAIL("Unifom block is inactive");
4919 	}
4920 
4921 	/* Get size of named uniform block */
4922 	gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4923 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4924 
4925 	if (0 == m_buffer_size)
4926 	{
4927 		TCU_FAIL("Unifom block size is 0");
4928 	}
4929 
4930 	/* Get information about "double precision" uniforms */
4931 	for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4932 		 end != it; ++it)
4933 	{
4934 		const glw::GLchar* uniform_name = 0;
4935 		std::string		   uniform_name_str;
4936 		std::stringstream  uniform_name_stream;
4937 		glw::GLuint		   index		 = 0;
4938 		glw::GLint		   offset		 = 0;
4939 		glw::GLint		   matrix_stride = 0;
4940 
4941 		/* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4942 		uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4943 
4944 		uniform_name_str = uniform_name_stream.str();
4945 		uniform_name	 = uniform_name_str.c_str();
4946 
4947 		/* Get index of uniform */
4948 		gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4949 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4950 
4951 		if (GL_INVALID_INDEX == index)
4952 		{
4953 			TCU_FAIL("Unifom is inactive");
4954 		}
4955 
4956 		/* Get offset of uniform */
4957 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4958 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4959 
4960 		if (m_invalid_uniform_offset == offset)
4961 		{
4962 			TCU_FAIL("Unifom has invalid offset");
4963 		}
4964 
4965 		m_uniform_offsets.push_back(offset);
4966 
4967 		/* Get matrix stride of uniform */
4968 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4969 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4970 
4971 		if (m_invalid_uniform_matrix_stride == offset)
4972 		{
4973 			TCU_FAIL("Unifom has invalid matrix stride");
4974 		}
4975 
4976 		m_uniform_matrix_strides.push_back(matrix_stride);
4977 	}
4978 }
4979 
4980 /** Attach shaders and link program
4981  *
4982  * @param context Test context
4983  **/
link(deqp::Context & context) const4984 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4985 {
4986 	/* GL entry points */
4987 	const glw::Functions& gl = context.getRenderContext().getFunctions();
4988 
4989 	/* Link status */
4990 	glw::GLint status = GL_FALSE;
4991 
4992 	/* Attach shaders */
4993 	gl.attachShader(m_program_object_id, m_fragment_shader_id);
4994 	gl.attachShader(m_program_object_id, m_geometry_shader_id);
4995 	gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
4996 	gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
4997 	gl.attachShader(m_program_object_id, m_vertex_shader_id);
4998 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
4999 
5000 	/* Link */
5001 	gl.linkProgram(m_program_object_id);
5002 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5003 
5004 	/* Get link status */
5005 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5006 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5007 
5008 	/* Log link error */
5009 	if (GL_TRUE != status)
5010 	{
5011 		glw::GLint				 length = 0;
5012 		std::vector<glw::GLchar> message;
5013 
5014 		/* Get error log length */
5015 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5016 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5017 
5018 		message.resize(length);
5019 
5020 		/* Get error log */
5021 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5022 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5023 
5024 		/* Log */
5025 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5026 										  << &message[0] << tcu::TestLog::EndMessage;
5027 
5028 		TCU_FAIL("Failed to link program");
5029 	}
5030 }
5031 
5032 /** Returns "predefined" values that will be used to fill uniform data
5033  *
5034  * @param type_ordinal Ordinal number of "double precision" uniform type
5035  * @param element      Index of element in uniform
5036  *
5037  * @return "Predefined" value
5038  **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5039 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5040 {
5041 	return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5042 		   ((m_base_element - (glw::GLdouble)element) / 4.0);
5043 }
5044 
5045 /** Returns a reference of programInfo instance specific for given buffer layout
5046  *
5047  * @param uniform_data_layout Buffer layout
5048  *
5049  * @return Reference to an instance of programInfo
5050  **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5051 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5052 {
5053 	const programInfo* program_info = 0;
5054 
5055 	switch (uniform_data_layout)
5056 	{
5057 	case PACKED:
5058 
5059 		program_info = &m_packed_program;
5060 
5061 		break;
5062 
5063 	case SHARED:
5064 
5065 		program_info = &m_shared_program;
5066 
5067 		break;
5068 
5069 	case STD140:
5070 
5071 		program_info = &m_std140_program;
5072 
5073 		break;
5074 	}
5075 
5076 	return *program_info;
5077 }
5078 
5079 /** Get "name" of buffer layout
5080  *
5081  * @param uniform_data_layout Buffer layout
5082  *
5083  * @return "Name" of layout
5084  **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5085 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5086 {
5087 	const glw::GLchar* layout = "";
5088 
5089 	switch (uniform_data_layout)
5090 	{
5091 	case PACKED:
5092 		layout = "packed";
5093 		break;
5094 	case SHARED:
5095 		layout = "shared";
5096 		break;
5097 	case STD140:
5098 		layout = "std140";
5099 		break;
5100 	}
5101 
5102 	return layout;
5103 }
5104 
5105 /** Prepare programInfo instance for specific buffer layout
5106  *
5107  * @param program_info        Instance of programInfo
5108  * @param uniform_data_layout Buffer layout
5109  **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5110 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5111 {
5112 	/* Storage for shader source code */
5113 	std::stringstream fragment_shader_code;
5114 	std::stringstream geometry_shader_code;
5115 	std::stringstream tess_control_shader_code;
5116 	std::stringstream tess_eval_shader_code;
5117 	std::stringstream vertex_shader_code;
5118 
5119 	/* Write preambles */
5120 	writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5121 	writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5122 	writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5123 	writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5124 	writePreamble(vertex_shader_code, VERTEX_SHADER);
5125 
5126 	/* Write definition of named uniform block */
5127 	writeUniformBlock(fragment_shader_code, uniform_data_layout);
5128 	writeUniformBlock(geometry_shader_code, uniform_data_layout);
5129 	writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5130 	writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5131 	writeUniformBlock(vertex_shader_code, uniform_data_layout);
5132 
5133 	/* Write definitions of varyings */
5134 	writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5135 	writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5136 	writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5137 	writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5138 	writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5139 
5140 	/* Write main routine */
5141 	writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5142 	writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5143 	writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5144 	writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5145 	writeMainBody(vertex_shader_code, VERTEX_SHADER);
5146 
5147 	/* Init programInfo instance */
5148 	program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5149 					  geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5150 					  tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5151 }
5152 
5153 /** Prepare uniform buffer
5154  *
5155  * @param program_info   Instance of programInfo
5156  * @param verify_offsets If uniform offsets should be verified against expected values
5157  *
5158  * @return false if uniform offsets verification result is failure, true otherwise
5159  **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5160 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5161 {
5162 	const glw::GLuint							buffer_size = program_info.m_buffer_size;
5163 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
5164 	bool										offset_verification_result = true;
5165 	glw::GLuint									type_ordinal			   = 1;
5166 	std::vector<uniformDetails>::const_iterator it_uniform_details		   = m_uniform_details.begin();
5167 	std::vector<glw::GLint>::const_iterator		it_uniform_offsets		   = program_info.m_uniform_offsets.begin();
5168 	std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5169 
5170 	/* Prepare storage for uniform buffer data */
5171 	std::vector<glw::GLubyte> buffer_data;
5172 	buffer_data.resize(buffer_size);
5173 
5174 	/* For each "double precision" uniform */
5175 	for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5176 		 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5177 	{
5178 		const glw::GLint  matrix_stride  = *it_uniform_matrix_strides;
5179 		const glw::GLuint n_columns		 = it_uniform_details->m_n_columns;
5180 		const glw::GLuint n_elements	 = it_uniform_details->m_n_elements;
5181 		const glw::GLuint column_length  = n_elements / n_columns;
5182 		const glw::GLint  uniform_offset = *it_uniform_offsets;
5183 
5184 		/* For each element of uniform */
5185 		for (glw::GLuint element = 0; element < n_elements; ++element)
5186 		{
5187 			const glw::GLuint   column		= element / column_length;
5188 			const glw::GLuint   column_elem = element % column_length;
5189 			const glw::GLdouble value		= getExpectedValue(type_ordinal, element);
5190 			const glw::GLuint   value_offset =
5191 				static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5192 
5193 			glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5194 
5195 			/* Store value */
5196 			*value_dst = value;
5197 		}
5198 
5199 		/* Uniform offset verification */
5200 		if (true == verify_offsets)
5201 		{
5202 			const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5203 
5204 			if (expected_offset != uniform_offset)
5205 			{
5206 				if (true == offset_verification_result)
5207 				{
5208 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5209 				}
5210 
5211 				m_context.getTestContext().getLog()
5212 					<< tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5213 					<< " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5214 					<< tcu::TestLog::EndMessage;
5215 
5216 				offset_verification_result = false;
5217 			}
5218 		}
5219 	}
5220 
5221 	/* Update uniform buffer with prepared data */
5222 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5223 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5224 
5225 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5226 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5227 
5228 	/* Bind uniform buffer as data source for named uniform block */
5229 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5230 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5231 
5232 	gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5233 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5234 
5235 	/* Done */
5236 	return offset_verification_result;
5237 }
5238 
5239 /** Prepare data, execute draw call and verify results
5240  *
5241  * @param uniform_data_layout
5242  *
5243  * @return true if test pass, false otherwise
5244  **/
test(uniformDataLayout uniform_data_layout) const5245 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5246 {
5247 	bool				  are_offsets_verified		 = (STD140 == uniform_data_layout);
5248 	const glw::Functions& gl						 = m_context.getRenderContext().getFunctions();
5249 	bool				  offset_verification_result = true;
5250 	const programInfo&	program_info				 = getProgramInfo(uniform_data_layout);
5251 	bool				  result					 = true;
5252 
5253 	/* Set up program */
5254 	gl.useProgram(program_info.m_program_object_id);
5255 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5256 
5257 	/* Prepare uniform buffer */
5258 	offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5259 
5260 	if (true == are_offsets_verified && false == offset_verification_result)
5261 	{
5262 		/* Offsets verification failure was already reported, add info about buffer layout */
5263 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5264 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5265 											<< tcu::TestLog::EndMessage;
5266 
5267 		result = false;
5268 	}
5269 
5270 	/* Set up transform feedback buffer */
5271 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5272 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5273 
5274 	/* Begin transform feedback */
5275 	gl.beginTransformFeedback(GL_POINTS);
5276 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5277 
5278 	/* Execute draw call for singe vertex */
5279 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5280 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5281 
5282 	/* Stop transform feedback */
5283 	gl.endTransformFeedback();
5284 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5285 
5286 	/* Verify results */
5287 	if (false == verifyResults())
5288 	{
5289 		/* Result verificatioon failure was already reported, add info about layout */
5290 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5291 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5292 											<< tcu::TestLog::EndMessage;
5293 
5294 		result = false;
5295 	}
5296 
5297 	/* Done */
5298 	return result;
5299 }
5300 
testInit()5301 void GPUShaderFP64Test3::testInit()
5302 {
5303 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5304 
5305 	/* Uniform block declaration with std140 offsets calculated
5306 	 *                       | align | loc_req | begins | ends | offset in bytes | imp |
5307 	 * ivec3   unused1[3]    |     4 |      12 |      0 |   12 |               0 |     |
5308 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5309 	 * bool    unused2       |     1 |       1 |     14 |   15 |              56 |     |
5310 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5311 	 * bvec3   unused3       |     4 |       4 |     20 |   24 |              80 |     |
5312 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5313 	 * int     unused4[3]    |     4 |      12 |     32 |   44 |             128 |     |
5314 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5315 	 * bool    unused5       |     1 |       1 |     56 |   57 |             224 |     |
5316 	 * bool    unused6[2]    |     4 |       8 |     60 |   68 |             240 |     |
5317 	 * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
5318 	 * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
5319 	 * bool    unused7       |     1 |       1 |    104 |  105 |             416 |     |
5320 	 * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
5321 	 * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
5322 	 * uvec3   unused8       |     4 |       4 |    160 |  164 |             640 |     |
5323 	 * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
5324 	 * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
5325 	 * bool    unused9       |     1 |       1 |    196 |  197 |             784 |     |
5326 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5327 	 * int     unused10      |     1 |       1 |    224 |  225 |             896 |     |
5328 	 * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
5329 	 * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
5330 	 */
5331 
5332 	/* Prepare "double precision" unfiorms' details */
5333 	m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5334 											   1 /* n_elements */, "double" /* type_name */));
5335 	m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5336 											   2 /* n_elements */, "dvec2" /* type_name */));
5337 	m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5338 											   3 /* n_elements */, "dvec3" /* type_name */));
5339 	m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5340 											   4 /* n_elements */, "dvec4" /* type_name */));
5341 	m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5342 											   4 /* n_elements */, "dmat2" /* type_name */));
5343 	m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5344 											   9 /* n_elements */, "dmat3" /* type_name */));
5345 	m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5346 											   16 /* n_elements */, "dmat4" /* type_name */));
5347 	m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5348 											   6 /* n_elements */, "dmat2x3" /* type_name */));
5349 	m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5350 											   8 /* n_elements */, "dmat2x4" /* type_name */));
5351 	m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5352 											   6 /* n_elements */, "dmat3x2" /* type_name */));
5353 	m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5354 											   12 /* n_elements */, "dmat3x4" /* type_name */));
5355 	m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5356 											   8 /* n_elements */, "dmat4x2" /* type_name */));
5357 	m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5358 											   12 /* n_elements */, "dmat4x3" /* type_name */));
5359 
5360 	/* Get random values for getExpectedValue */
5361 	m_base_element		= (glw::GLdouble)(rand() % 13);
5362 	m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5363 
5364 	/* Prepare programInfos for all buffer layouts */
5365 	prepareProgram(m_packed_program, PACKED);
5366 	prepareProgram(m_shared_program, SHARED);
5367 	prepareProgram(m_std140_program, STD140);
5368 
5369 	/* Generate buffers */
5370 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
5371 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5372 
5373 	gl.genBuffers(1, &m_uniform_buffer_id);
5374 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5375 
5376 	/* Prepare transform feedback buffer */
5377 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5378 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5379 
5380 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5381 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5382 
5383 	/* Prepare texture for color attachment 0 */
5384 	gl.genTextures(1, &m_color_texture_id);
5385 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5386 
5387 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5388 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5389 
5390 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5391 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5392 
5393 	/* Prepare FBO with color attachment 0 */
5394 	gl.genFramebuffers(1, &m_framebuffer_id);
5395 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5396 
5397 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5398 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5399 
5400 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5401 							0 /* level */);
5402 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5403 
5404 	gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5405 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5406 
5407 	/* Prepare VAO */
5408 	gl.genVertexArrays(1, &m_vertex_array_object_id);
5409 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5410 
5411 	gl.bindVertexArray(m_vertex_array_object_id);
5412 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5413 
5414 	/* Tesselation patch set up */
5415 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
5416 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5417 }
5418 
5419 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5420  *
5421  * @return true if all values are as expected, false otherwise
5422  **/
verifyResults() const5423 bool GPUShaderFP64Test3::verifyResults() const
5424 {
5425 	glw::GLint*			  feedback_data			  = 0;
5426 	bool				  fragment_shader_result  = false;
5427 	bool				  geometry_shader_result  = false;
5428 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
5429 	bool				  tess_ctrl_shader_result = false;
5430 	bool				  tess_eval_shader_result = false;
5431 	bool				  vertex_shader_result	= false;
5432 
5433 	/* Prepare storage for testure data */
5434 	std::vector<glw::GLint> image_data;
5435 	image_data.resize(1);
5436 
5437 	/* Get texture contents */
5438 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5439 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5440 
5441 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5442 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5443 
5444 	/* Get transform feedback data */
5445 	feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5446 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5447 
5448 	/* Verify results */
5449 	fragment_shader_result  = (m_result_success == image_data[0]);
5450 	geometry_shader_result  = (m_result_success == feedback_data[0]);
5451 	tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5452 	tess_eval_shader_result = (m_result_success == feedback_data[2]);
5453 	vertex_shader_result	= (m_result_success == feedback_data[3]);
5454 
5455 	/* Unmap transform feedback buffer */
5456 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5457 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5458 
5459 	/* Set result */
5460 	if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5461 				 tess_eval_shader_result && vertex_shader_result))
5462 	{
5463 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5464 
5465 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5466 											<< "Vertex shader stage result: " << vertex_shader_result
5467 											<< tcu::TestLog::EndMessage;
5468 
5469 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5470 											<< "Tesselation control shader stage result: " << tess_ctrl_shader_result
5471 											<< tcu::TestLog::EndMessage;
5472 
5473 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5474 											<< "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5475 											<< tcu::TestLog::EndMessage;
5476 
5477 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 											<< "Geometry shader stage result: " << geometry_shader_result
5479 											<< tcu::TestLog::EndMessage;
5480 
5481 		m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 											<< "Fragment shader stage result: " << fragment_shader_result
5483 											<< tcu::TestLog::EndMessage;
5484 
5485 		return false;
5486 	}
5487 	else
5488 	{
5489 		return true;
5490 	}
5491 }
5492 
5493 /** Write main routine of <shader_stage> shader to stream
5494  *
5495  * @param stream       Output stream with source code of shader
5496  * @param shader_stage Shader stage
5497  **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5498 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5499 {
5500 	glw::GLuint		   type_ordinal = 1;
5501 	const glw::GLchar* varying_name = "";
5502 
5503 	/* Select name for varying that will hold result of "that" shader_stage */
5504 	switch (shader_stage)
5505 	{
5506 	case FRAGMENT_SHADER:
5507 		varying_name = m_varying_name_fs_out_fs_result;
5508 		break;
5509 	case GEOMETRY_SHADER:
5510 		varying_name = m_varying_name_gs_fs_gs_result;
5511 		break;
5512 	case TESS_CONTROL_SHADER:
5513 		varying_name = m_varying_name_tcs_tes_tcs_result;
5514 		break;
5515 	case TESS_EVAL_SHADER:
5516 		varying_name = m_varying_name_tes_gs_tes_result;
5517 		break;
5518 	case VERTEX_SHADER:
5519 		varying_name = m_varying_name_vs_tcs_vs_result;
5520 		break;
5521 	}
5522 
5523 	/* void main() */
5524 	stream << "void main()\n"
5525 			  "{\n";
5526 
5527 	/* Tesselation levels output */
5528 	if (TESS_CONTROL_SHADER == shader_stage)
5529 	{
5530 		stream << "gl_TessLevelOuter[0] = 1.0;\n"
5531 				  "gl_TessLevelOuter[1] = 1.0;\n"
5532 				  "gl_TessLevelOuter[2] = 1.0;\n"
5533 				  "gl_TessLevelOuter[3] = 1.0;\n"
5534 				  "gl_TessLevelInner[0] = 1.0;\n"
5535 				  "gl_TessLevelInner[1] = 1.0;\n"
5536 				  "\n";
5537 	}
5538 
5539 	/* For each "double precision" uniform
5540 	 *
5541 	 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5542 	 * {
5543 	 *     VARYING_NAME = m_result_failure;
5544 	 * }
5545 	 */
5546 	for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5547 		 end != it; ++it, ++type_ordinal)
5548 	{
5549 		stream << "    ";
5550 
5551 		/* First comparison is done with if, next with else if */
5552 		if (1 != type_ordinal)
5553 		{
5554 			stream << "else ";
5555 		}
5556 
5557 		/* if (TYPE_NAME( */
5558 		stream << "if (" << it->m_type_name << "(";
5559 
5560 		/* PREDIFINED_VALUES */
5561 		for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5562 		{
5563 			stream << getExpectedValue(type_ordinal, element);
5564 
5565 			/* Separate with comma */
5566 			if (it->m_n_elements != element + 1)
5567 			{
5568 				stream << ", ";
5569 			}
5570 		}
5571 
5572 		/*
5573 		 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5574 		 * {
5575 		 *     VARYING_NAME
5576 		 */
5577 		stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5578 																				   "    {\n"
5579 																				   "        "
5580 			   << varying_name;
5581 
5582 		/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5583 		if (TESS_CONTROL_SHADER == shader_stage)
5584 		{
5585 			stream << "[gl_InvocationID]";
5586 		}
5587 
5588 		/*
5589 		 * = m_result_failure;
5590 		 * }
5591 		 */
5592 		stream << " = " << m_result_failure << ";\n"
5593 			   << "    }\n";
5594 	}
5595 
5596 	/* If all comparisons are ok
5597 	 *
5598 	 *     else
5599 	 *     {
5600 	 *         VARYING_NAME = m_result_success;
5601 	 *     }
5602 	 */
5603 
5604 	/*
5605 	 * else
5606 	 * {
5607 	 *     VARYING_NAME
5608 	 */
5609 	stream << "    else\n"
5610 			  "    {\n"
5611 			  "        "
5612 		   << varying_name;
5613 
5614 	/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5615 	if (TESS_CONTROL_SHADER == shader_stage)
5616 	{
5617 		stream << "[gl_InvocationID]";
5618 	}
5619 
5620 	/*
5621 	 * = m_result_success;
5622 	 * }
5623 	 *
5624 	 */
5625 	stream << " = " << m_result_success << ";\n"
5626 		   << "    }\n"
5627 		   << "\n";
5628 
5629 	/* For each pair of "input/output" varyings
5630 	 *
5631 	 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5632 	 **/
5633 	writeVaryingPassthrough(stream, shader_stage);
5634 
5635 	/* Geometry shader have to emit vertex */
5636 	if (GEOMETRY_SHADER == shader_stage)
5637 	{
5638 		stream << "\n"
5639 				  "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5640 				  "EmitVertex();\n"
5641 				  "EndPrimitive();\n";
5642 	}
5643 
5644 	/* Close scope of main */
5645 	stream << "}\n\n";
5646 }
5647 
5648 /** Write shader preamble to stream
5649  *
5650  * @param stream       Output stream with source code of shader
5651  * @param shader_stage Shader stage
5652  **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5653 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5654 {
5655 	stream << "#version 400 core\n"
5656 			  "\n"
5657 			  "precision highp float;\n"
5658 			  "\n";
5659 
5660 	switch (shader_stage)
5661 	{
5662 	case FRAGMENT_SHADER:
5663 		break;
5664 	case GEOMETRY_SHADER:
5665 		stream << "layout(points)                   in;\n"
5666 				  "layout(points, max_vertices = 1) out;\n"
5667 				  "\n";
5668 		break;
5669 	case TESS_CONTROL_SHADER:
5670 		stream << "layout(vertices = 1) out;\n"
5671 				  "\n";
5672 		break;
5673 	case TESS_EVAL_SHADER:
5674 		stream << "layout(isolines, point_mode) in;\n"
5675 				  "\n";
5676 		break;
5677 	case VERTEX_SHADER:
5678 		break;
5679 	}
5680 }
5681 
5682 /** Write name uniform blcok definition with specific layout to stream
5683  *
5684  * @param stream              Output stream with source code of shader
5685  * @param uniform_data_layout Buffer layout
5686  **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5687 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5688 {
5689 	const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5690 
5691 	stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5692 																			 "{\n"
5693 																			 "    ivec3   unused1[3];\n"
5694 																			 "    double  double_value;\n"
5695 																			 "    bool    unused2;\n"
5696 																			 "    dvec2   dvec2_value;\n"
5697 																			 "    bvec3   unused3;\n"
5698 																			 "    dvec3   dvec3_value;\n"
5699 																			 "    int     unused4[3];\n"
5700 																			 "    dvec4   dvec4_value;\n"
5701 																			 "    bool    unused5;\n"
5702 																			 "    bool    unused6[2];\n"
5703 																			 "    dmat2   dmat2_value;\n"
5704 																			 "    dmat3   dmat3_value;\n"
5705 																			 "    bool    unused7;\n"
5706 																			 "    dmat4   dmat4_value;\n"
5707 																			 "    dmat2x3 dmat2x3_value;\n"
5708 																			 "    uvec3   unused8;\n"
5709 																			 "    dmat2x4 dmat2x4_value;\n"
5710 																			 "    dmat3x2 dmat3x2_value;\n"
5711 																			 "    bool    unused9;\n"
5712 																			 "    dmat3x4 dmat3x4_value;\n"
5713 																			 "    int     unused10;\n"
5714 																			 "    dmat4x2 dmat4x2_value;\n"
5715 																			 "    dmat4x3 dmat4x3_value;\n"
5716 																			 "} "
5717 		   << m_uniform_block_instance_name << ";\n";
5718 
5719 	stream << "\n";
5720 }
5721 
5722 /** Write definitions of varyings specific for given <shader_stage> to stream
5723  *
5724  * @param stream       Output stream with source code of shader
5725  * @param shader_stage Shader stage
5726  **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5727 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5728 {
5729 	static const glw::GLchar* const varying_type = "int";
5730 
5731 	switch (shader_stage)
5732 	{
5733 	case FRAGMENT_SHADER:
5734 
5735 		/* In */
5736 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5737 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5738 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5739 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5740 
5741 		stream << "\n";
5742 
5743 		/* Out */
5744 		stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5745 
5746 		break;
5747 
5748 	case GEOMETRY_SHADER:
5749 
5750 		/* In */
5751 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5752 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5753 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5754 
5755 		stream << "\n";
5756 
5757 		/* Out */
5758 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5759 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5760 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5761 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5762 
5763 		break;
5764 
5765 	case TESS_CONTROL_SHADER:
5766 
5767 		/* In */
5768 		stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5769 
5770 		stream << "\n";
5771 
5772 		/* Out */
5773 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5774 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5775 
5776 		break;
5777 
5778 	case TESS_EVAL_SHADER:
5779 
5780 		/* In */
5781 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5782 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5783 
5784 		stream << "\n";
5785 
5786 		/* Out */
5787 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5788 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5789 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5790 
5791 		break;
5792 
5793 	case VERTEX_SHADER:
5794 
5795 		/* Out */
5796 		stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5797 
5798 		break;
5799 	}
5800 
5801 	stream << "\n";
5802 }
5803 
5804 /** Write passthrough code of "input/output" varying pairs to stream
5805  *
5806  * @param stream       Output stream with source code of shader
5807  * @param shader_stage Shader stage
5808  **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5809 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5810 {
5811 	switch (shader_stage)
5812 	{
5813 	case FRAGMENT_SHADER:
5814 		break;
5815 
5816 	case GEOMETRY_SHADER:
5817 
5818 		stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5819 		stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5820 		stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5821 
5822 		break;
5823 
5824 	case TESS_CONTROL_SHADER:
5825 
5826 		stream << "    " << m_varying_name_tcs_tes_vs_result
5827 			   << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5828 
5829 		break;
5830 
5831 	case TESS_EVAL_SHADER:
5832 
5833 		stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5834 		stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5835 
5836 		break;
5837 
5838 	case VERTEX_SHADER:
5839 
5840 		break;
5841 	}
5842 }
5843 
5844 /** Constructor. Sets all uniform locations to -1 and sets all
5845  *  values to 0.
5846  */
_data()5847 GPUShaderFP64Test4::_data::_data()
5848 {
5849 	memset(&uniform_double, 0, sizeof(uniform_double));
5850 	memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5851 	memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5852 	memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5853 	memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5854 	memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5855 	memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5856 
5857 	uniform_location_double		   = -1;
5858 	uniform_location_double_arr[0] = -1;
5859 	uniform_location_double_arr[1] = -1;
5860 	uniform_location_dvec2		   = -1;
5861 	uniform_location_dvec2_arr[0]  = -1;
5862 	uniform_location_dvec2_arr[1]  = -1;
5863 	uniform_location_dvec3		   = -1;
5864 	uniform_location_dvec3_arr[0]  = -1;
5865 	uniform_location_dvec3_arr[1]  = -1;
5866 	uniform_location_dvec4		   = -1;
5867 	uniform_location_dvec4_arr[0]  = -1;
5868 	uniform_location_dvec4_arr[1]  = -1;
5869 }
5870 
5871 /** Constructor
5872  *
5873  *  @param context Rendering context.
5874  */
GPUShaderFP64Test4(deqp::Context & context)5875 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5876 	: TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5877 									   " report correct properties of & values assigned to double-precision uniforms.")
5878 	, m_has_test_passed(true)
5879 	, m_uniform_name_buffer(0)
5880 	, m_cs_id(0)
5881 	, m_fs_id(0)
5882 	, m_gs_id(0)
5883 	, m_po_cs_id(0)
5884 	, m_po_noncs_id(0)
5885 	, m_tc_id(0)
5886 	, m_te_id(0)
5887 	, m_vs_id(0)
5888 {
5889 	/* Left blank intentionally */
5890 }
5891 
5892 /** Deinitializes all GL objects, as well as releases all bufers, that may
5893  *  have beenallocated or  created during test execution.
5894  **/
deinit()5895 void GPUShaderFP64Test4::deinit()
5896 {
5897 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5898 
5899 	if (m_cs_id != 0)
5900 	{
5901 		gl.deleteShader(m_cs_id);
5902 
5903 		m_cs_id = 0;
5904 	}
5905 
5906 	if (m_fs_id != 0)
5907 	{
5908 		gl.deleteShader(m_fs_id);
5909 
5910 		m_fs_id = 0;
5911 	}
5912 
5913 	if (m_gs_id != 0)
5914 	{
5915 		gl.deleteShader(m_gs_id);
5916 
5917 		m_gs_id = 0;
5918 	}
5919 
5920 	if (m_po_cs_id != 0)
5921 	{
5922 		gl.deleteProgram(m_po_cs_id);
5923 
5924 		m_po_cs_id = 0;
5925 	}
5926 
5927 	if (m_po_noncs_id != 0)
5928 	{
5929 		gl.deleteProgram(m_po_noncs_id);
5930 
5931 		m_po_noncs_id = 0;
5932 	}
5933 
5934 	if (m_tc_id != 0)
5935 	{
5936 		gl.deleteShader(m_tc_id);
5937 
5938 		m_tc_id = 0;
5939 	}
5940 
5941 	if (m_te_id != 0)
5942 	{
5943 		gl.deleteShader(m_te_id);
5944 
5945 		m_te_id = 0;
5946 	}
5947 
5948 	if (m_uniform_name_buffer != DE_NULL)
5949 	{
5950 		delete[] m_uniform_name_buffer;
5951 
5952 		m_uniform_name_buffer = DE_NULL;
5953 	}
5954 
5955 	if (m_vs_id != 0)
5956 	{
5957 		gl.deleteShader(m_vs_id);
5958 
5959 		m_vs_id = 0;
5960 	}
5961 }
5962 
5963 /** Generates double-precision values for all uniforms defined for all program objects
5964  *  used by the test.
5965  *
5966  *  This function DOES NOT use any GL API. It only calculates & stores the values
5967  *  in internal storage for further usage.
5968  */
generateUniformValues()5969 void GPUShaderFP64Test4::generateUniformValues()
5970 {
5971 	_stage_data*	   stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5972 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5973 
5974 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5975 	{
5976 		_stage_data* stage_ptr = stages[n_stage];
5977 
5978 		/* Iterate through all uniform components and assign them double values */
5979 		double* double_ptrs[] = {
5980 			&stage_ptr->uniform_structure_arrays[0].uniform_double,
5981 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5982 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5983 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5984 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5985 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
5986 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
5987 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
5988 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
5989 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
5990 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
5991 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
5992 			&stage_ptr->uniform_structure_arrays[1].uniform_double,
5993 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
5994 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
5995 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
5996 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
5997 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
5998 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
5999 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6000 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6001 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6002 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6003 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6004 			&stage_ptr->uniforms.uniform_double,
6005 			stage_ptr->uniforms.uniform_double_arr + 0,
6006 			stage_ptr->uniforms.uniform_double_arr + 1,
6007 			stage_ptr->uniforms.uniform_dvec2 + 0,
6008 			stage_ptr->uniforms.uniform_dvec2 + 1,
6009 			stage_ptr->uniforms.uniform_dvec2_arr + 0,
6010 			stage_ptr->uniforms.uniform_dvec2_arr + 1,
6011 			stage_ptr->uniforms.uniform_dvec2_arr + 2,
6012 			stage_ptr->uniforms.uniform_dvec2_arr + 3,
6013 			stage_ptr->uniforms.uniform_dvec3 + 0,
6014 			stage_ptr->uniforms.uniform_dvec3 + 1,
6015 			stage_ptr->uniforms.uniform_dvec3 + 2,
6016 			stage_ptr->uniforms.uniform_dvec3_arr + 0,
6017 			stage_ptr->uniforms.uniform_dvec3_arr + 1,
6018 			stage_ptr->uniforms.uniform_dvec3_arr + 2,
6019 			stage_ptr->uniforms.uniform_dvec3_arr + 3,
6020 			stage_ptr->uniforms.uniform_dvec3_arr + 4,
6021 			stage_ptr->uniforms.uniform_dvec3_arr + 5,
6022 			stage_ptr->uniforms.uniform_dvec4 + 0,
6023 			stage_ptr->uniforms.uniform_dvec4 + 1,
6024 			stage_ptr->uniforms.uniform_dvec4 + 2,
6025 			stage_ptr->uniforms.uniform_dvec4 + 3,
6026 			stage_ptr->uniforms.uniform_dvec4_arr + 0,
6027 			stage_ptr->uniforms.uniform_dvec4_arr + 1,
6028 			stage_ptr->uniforms.uniform_dvec4_arr + 2,
6029 			stage_ptr->uniforms.uniform_dvec4_arr + 3,
6030 			stage_ptr->uniforms.uniform_dvec4_arr + 4,
6031 			stage_ptr->uniforms.uniform_dvec4_arr + 5,
6032 			stage_ptr->uniforms.uniform_dvec4_arr + 6,
6033 			stage_ptr->uniforms.uniform_dvec4_arr + 7,
6034 		};
6035 		const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6036 
6037 		for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6038 		{
6039 			double* double_ptr = double_ptrs[n_double_ptr];
6040 
6041 			/* Generate the value. Use magic numbers to generate a set of double-precision
6042 			 * floating-point numbers.
6043 			 */
6044 			static int seed = 16762362;
6045 
6046 			*double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6047 
6048 			seed += 751;
6049 		} /* for (all pointers to double variables) */
6050 	}	 /* for (all stages) */
6051 }
6052 
6053 /** Initializes all program & shader objects required to run the test. The function also
6054  *  retrieves locations of all uniforms defined by both program objects.
6055  **/
initProgramObjects()6056 void GPUShaderFP64Test4::initProgramObjects()
6057 {
6058 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6059 
6060 	/* Create program & shader objects */
6061 
6062 	/* Compute shader support and GL 4.2 required */
6063 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6064 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6065 	{
6066 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6067 	}
6068 
6069 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6070 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6071 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6072 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6073 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6074 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6075 
6076 	/* m_cs_id is initialized only if compute shaders are supported */
6077 	if (0 != m_cs_id)
6078 	{
6079 		m_po_cs_id = gl.createProgram();
6080 	}
6081 
6082 	m_po_noncs_id = gl.createProgram();
6083 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6084 
6085 	/* Configure compute shader body */
6086 	const char* cs_body = "#version 420\n"
6087 						  "#extension GL_ARB_compute_shader          : require\n"
6088 						  "\n"
6089 						  "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6090 						  "\n"
6091 						  "layout(rgba32f) uniform image2D testImage;\n"
6092 						  "\n"
6093 						  "uniform double cs_double;\n"
6094 						  "uniform dvec2  cs_dvec2;\n"
6095 						  "uniform dvec3  cs_dvec3;\n"
6096 						  "uniform dvec4  cs_dvec4;\n"
6097 						  "uniform double cs_double_arr[2];\n"
6098 						  "uniform dvec2  cs_dvec2_arr [2];\n"
6099 						  "uniform dvec3  cs_dvec3_arr [2];\n"
6100 						  "uniform dvec4  cs_dvec4_arr [2];\n"
6101 						  "\n"
6102 						  "uniform struct cs_struct\n"
6103 						  "{\n"
6104 						  "    double struct_double;\n"
6105 						  "    dvec2  struct_dvec2;\n"
6106 						  "    dvec3  struct_dvec3;\n"
6107 						  "    dvec4  struct_dvec4;\n"
6108 						  "} cs_array[2];\n"
6109 						  "\n"
6110 						  "void main()\n"
6111 						  "{\n"
6112 						  "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
6113 						  "          * cs_dvec4.z                 *\n"
6114 						  "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
6115 						  "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
6116 						  "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
6117 						  "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
6118 						  "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
6119 						  "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6120 						  "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
6121 						  "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6122 						  "\n"
6123 						  "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6124 						  "}\n";
6125 
6126 	/* m_cs_id is initialized only if compute shaders are supported */
6127 	if (0 != m_cs_id)
6128 	{
6129 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6130 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6131 	}
6132 
6133 	/* Configure vertex shader body */
6134 	const char* vs_body = "#version 400\n"
6135 						  "\n"
6136 						  "uniform double vs_double;\n"
6137 						  "uniform dvec2  vs_dvec2;\n"
6138 						  "uniform dvec3  vs_dvec3;\n"
6139 						  "uniform dvec4  vs_dvec4;\n"
6140 						  "uniform double vs_double_arr[2];\n"
6141 						  "uniform dvec2  vs_dvec2_arr [2];\n"
6142 						  "uniform dvec3  vs_dvec3_arr [2];\n"
6143 						  "uniform dvec4  vs_dvec4_arr [2];\n"
6144 						  "\n"
6145 						  "uniform struct vs_struct\n"
6146 						  "{\n"
6147 						  "    double struct_double;\n"
6148 						  "    dvec2  struct_dvec2;\n"
6149 						  "    dvec3  struct_dvec3;\n"
6150 						  "    dvec4  struct_dvec4;\n"
6151 						  "} vs_array[2];\n"
6152 						  "\n"
6153 						  "void main()\n"
6154 						  "{\n"
6155 						  "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
6156 						  "* vs_dvec4.x                 *\n"
6157 						  "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
6158 						  "* vs_dvec4_arr[0].x          *\n"
6159 						  "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
6160 						  "* vs_dvec4_arr[1].x          *\n"
6161 						  "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6162 						  "* vs_array[0].struct_dvec4.x *\n"
6163 						  "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6164 						  "* vs_array[1].struct_dvec4.x > 1.0)\n"
6165 						  "    {\n"
6166 						  "        gl_Position = vec4(0);\n"
6167 						  "    }\n"
6168 						  "    else\n"
6169 						  "    {\n"
6170 						  "        gl_Position = vec4(1);\n"
6171 						  "    }\n"
6172 						  "}\n";
6173 
6174 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6175 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6176 
6177 	/* Configure tessellation control shader body */
6178 	const char* tc_body = "#version 400\n"
6179 						  "\n"
6180 						  "uniform double tc_double;\n"
6181 						  "uniform dvec2  tc_dvec2;\n"
6182 						  "uniform dvec3  tc_dvec3;\n"
6183 						  "uniform dvec4  tc_dvec4;\n"
6184 						  "uniform double tc_double_arr[2];\n"
6185 						  "uniform dvec2  tc_dvec2_arr [2];\n"
6186 						  "uniform dvec3  tc_dvec3_arr [2];\n"
6187 						  "uniform dvec4  tc_dvec4_arr [2];\n"
6188 						  "\n"
6189 						  "uniform struct tc_struct\n"
6190 						  "{\n"
6191 						  "    double struct_double;\n"
6192 						  "    dvec2  struct_dvec2;\n"
6193 						  "    dvec3  struct_dvec3;\n"
6194 						  "    dvec4  struct_dvec4;\n"
6195 						  "} tc_array[2];\n"
6196 						  "\n"
6197 						  "layout(vertices = 4) out;\n"
6198 						  "\n"
6199 						  "void main()\n"
6200 						  "{\n"
6201 						  "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
6202 						  "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
6203 						  "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
6204 						  "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
6205 						  "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6206 						  "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6207 						  "\n"
6208 						  "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
6209 						  "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
6210 						  "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
6211 						  "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
6212 						  "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6213 						  "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
6214 						  "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6215 						  "    {\n"
6216 						  "        gl_TessLevelInner[1] = 3.0;\n"
6217 						  "    }\n"
6218 						  "}\n";
6219 
6220 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6221 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6222 
6223 	/* Configure tessellation evaluation shader body */
6224 	const char* te_body = "#version 400\n"
6225 						  "\n"
6226 						  "uniform double te_double;\n"
6227 						  "uniform dvec2  te_dvec2;\n"
6228 						  "uniform dvec3  te_dvec3;\n"
6229 						  "uniform dvec4  te_dvec4;\n"
6230 						  "uniform double te_double_arr[2];\n"
6231 						  "uniform dvec2  te_dvec2_arr [2];\n"
6232 						  "uniform dvec3  te_dvec3_arr [2];\n"
6233 						  "uniform dvec4  te_dvec4_arr [2];\n"
6234 						  "\n"
6235 						  "uniform struct te_struct\n"
6236 						  "{\n"
6237 						  "    double struct_double;\n"
6238 						  "    dvec2  struct_dvec2;\n"
6239 						  "    dvec3  struct_dvec3;\n"
6240 						  "    dvec4  struct_dvec4;\n"
6241 						  "} te_array[2];\n"
6242 						  "\n"
6243 						  "layout(triangles) in;\n"
6244 						  "\n"
6245 						  "void main()\n"
6246 						  "{\n"
6247 						  "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
6248 						  "* te_dvec4.x                 *\n"
6249 						  "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
6250 						  "* te_dvec4_arr[0].x          *\n"
6251 						  "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
6252 						  "* te_dvec4_arr[1].x          *\n"
6253 						  "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6254 						  "* te_array[0].struct_dvec4.x *\n"
6255 						  "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6256 						  "* te_array[1].struct_dvec4.x > 1.0)\n"
6257 						  "    {\n"
6258 						  "        gl_Position = gl_in[0].gl_Position;\n"
6259 						  "    }\n"
6260 						  "    else\n"
6261 						  "    {\n"
6262 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6263 						  "    }\n"
6264 						  "}\n";
6265 
6266 	gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6267 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6268 
6269 	/* Configure geometry shader body */
6270 	const char* gs_body = "#version 400\n"
6271 						  "\n"
6272 						  "uniform double gs_double;\n"
6273 						  "uniform dvec2  gs_dvec2;\n"
6274 						  "uniform dvec3  gs_dvec3;\n"
6275 						  "uniform dvec4  gs_dvec4;\n"
6276 						  "uniform double gs_double_arr[2];\n"
6277 						  "uniform dvec2  gs_dvec2_arr [2];\n"
6278 						  "uniform dvec3  gs_dvec3_arr [2];\n"
6279 						  "uniform dvec4  gs_dvec4_arr [2];\n"
6280 						  "\n"
6281 						  "uniform struct gs_struct\n"
6282 						  "{\n"
6283 						  "    double struct_double;\n"
6284 						  "    dvec2  struct_dvec2;\n"
6285 						  "    dvec3  struct_dvec3;\n"
6286 						  "    dvec4  struct_dvec4;\n"
6287 						  "} gs_array[2];\n"
6288 						  "\n"
6289 						  "layout (points)                   in;\n"
6290 						  "layout (points, max_vertices = 1) out;\n"
6291 						  "\n"
6292 						  "void main()\n"
6293 						  "{\n"
6294 						  "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
6295 						  "* gs_dvec4.x        *\n"
6296 						  "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
6297 						  "* gs_dvec4_arr[0].x *\n"
6298 						  "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
6299 						  "* gs_dvec4_arr[1].x *\n"
6300 						  "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6301 						  "* gs_array[0].struct_dvec4.x *\n"
6302 						  "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6303 						  "* gs_array[1].struct_dvec4.x > 1.0)\n"
6304 						  "    {\n"
6305 						  "        gl_Position = gl_in[0].gl_Position;\n"
6306 						  "    }\n"
6307 						  "    else\n"
6308 						  "    {\n"
6309 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6310 						  "    }\n"
6311 						  "\n"
6312 						  "    EmitVertex();\n"
6313 						  "}\n";
6314 
6315 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6316 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6317 
6318 	/* Configure fragment shader body */
6319 	const char* fs_body = "#version 400\n"
6320 						  "\n"
6321 						  "uniform double fs_double;\n"
6322 						  "uniform dvec2  fs_dvec2;\n"
6323 						  "uniform dvec3  fs_dvec3;\n"
6324 						  "uniform dvec4  fs_dvec4;\n"
6325 						  "uniform double fs_double_arr[2];\n"
6326 						  "uniform dvec2  fs_dvec2_arr [2];\n"
6327 						  "uniform dvec3  fs_dvec3_arr [2];\n"
6328 						  "uniform dvec4  fs_dvec4_arr [2];\n"
6329 						  "\n"
6330 						  "uniform struct fs_struct\n"
6331 						  "{\n"
6332 						  "    double struct_double;\n"
6333 						  "    dvec2  struct_dvec2;\n"
6334 						  "    dvec3  struct_dvec3;\n"
6335 						  "    dvec4  struct_dvec4;\n"
6336 						  "} fs_array[2];\n"
6337 						  "\n"
6338 						  "out vec4 result;\n"
6339 						  "\n"
6340 						  "void main()\n"
6341 						  "{\n"
6342 						  "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
6343 						  "* fs_dvec4.x        *\n"
6344 						  "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
6345 						  "* fs_dvec4_arr[0].x *\n"
6346 						  "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
6347 						  "* fs_dvec4_arr[1].x *\n"
6348 						  "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6349 						  "* fs_array[0].struct_dvec4.x *\n"
6350 						  "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6351 						  "* fs_array[1].struct_dvec4.x > 1.0)\n"
6352 						  "    {\n"
6353 						  "        result = vec4(0.0);\n"
6354 						  "    }\n"
6355 						  "    else\n"
6356 						  "    {\n"
6357 						  "        result = vec4(1.0);\n"
6358 						  "    }\n"
6359 						  "}\n";
6360 
6361 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6362 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6363 
6364 	/* Compile the shaders */
6365 	const glw::GLuint  shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6366 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6367 
6368 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6369 	{
6370 		glw::GLint  compile_status = GL_FALSE;
6371 		glw::GLuint so_id		   = shaders[n_shader];
6372 
6373 		/* Skip compute shader if not supported */
6374 		if (0 == so_id)
6375 		{
6376 			continue;
6377 		}
6378 
6379 		gl.compileShader(so_id);
6380 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6381 
6382 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6383 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6384 
6385 		if (compile_status != GL_TRUE)
6386 		{
6387 			TCU_FAIL("Shader compilation failed");
6388 		}
6389 
6390 		if (so_id == m_cs_id)
6391 		{
6392 			gl.attachShader(m_po_cs_id, so_id);
6393 		}
6394 		else
6395 		{
6396 			gl.attachShader(m_po_noncs_id, so_id);
6397 		}
6398 
6399 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6400 	} /* for (all shaders) */
6401 
6402 	/* Link the program */
6403 	const glw::GLuint  programs[]  = { m_po_cs_id, m_po_noncs_id };
6404 	const unsigned int n_programs  = sizeof(programs) / sizeof(programs[0]);
6405 	glw::GLint		   link_status = GL_FALSE;
6406 
6407 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6408 	{
6409 		glw::GLuint po_id = programs[n_program];
6410 
6411 		/* Skip compute shader program if not supported */
6412 		if (0 == po_id)
6413 		{
6414 			continue;
6415 		}
6416 
6417 		gl.linkProgram(po_id);
6418 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6419 
6420 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6421 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6422 
6423 		if (link_status != GL_TRUE)
6424 		{
6425 			TCU_FAIL("Program linking failed");
6426 		}
6427 	} /* for (both program objects) */
6428 
6429 	/* Retrieve uniform locations */
6430 	_stage_data*			  cs_stage_data[]		= { &m_data_cs };
6431 	static const char*		  cs_uniform_prefixes[] = { "cs_" };
6432 	static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6433 
6434 	_stage_data*			  noncs_stage_data[]	   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6435 	static const char*		  noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6436 	static const unsigned int n_noncs_uniform_prefixes =
6437 		sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6438 
6439 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6440 	{
6441 		unsigned int  n_uniform_prefixes = DE_NULL;
6442 		glw::GLuint   po_id				 = programs[n_program];
6443 		_stage_data** stages_data		 = DE_NULL;
6444 		const char**  uniform_prefixes   = DE_NULL;
6445 
6446 		if (n_program == 0)
6447 		{
6448 			stages_data		   = cs_stage_data;
6449 			uniform_prefixes   = cs_uniform_prefixes;
6450 			n_uniform_prefixes = n_cs_uniform_prefixes;
6451 		}
6452 		else
6453 		{
6454 			stages_data		   = noncs_stage_data;
6455 			uniform_prefixes   = noncs_uniform_prefixes;
6456 			n_uniform_prefixes = n_noncs_uniform_prefixes;
6457 		}
6458 
6459 		/* Skip compute shader program if not supported */
6460 		if (0 == po_id)
6461 		{
6462 			continue;
6463 		}
6464 
6465 		/* Uniform names used by the test program consist of a prefix (different for each
6466 		 * shader stage) and a common part.
6467 		 */
6468 		for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6469 		{
6470 			_stage_data* stage_data				  = stages_data[n_uniform_prefix];
6471 			std::string  uniform_prefix			  = std::string(uniform_prefixes[n_uniform_prefix]);
6472 			std::string  uniform_double_name	  = uniform_prefix + "double";
6473 			std::string  uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6474 			std::string  uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6475 			std::string  uniform_dvec2_name		  = uniform_prefix + "dvec2";
6476 			std::string  uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
6477 			std::string  uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
6478 			std::string  uniform_dvec3_name		  = uniform_prefix + "dvec3";
6479 			std::string  uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
6480 			std::string  uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
6481 			std::string  uniform_dvec4_name		  = uniform_prefix + "dvec4";
6482 			std::string  uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
6483 			std::string  uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
6484 			std::string  uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6485 			std::string  uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
6486 			std::string  uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
6487 			std::string  uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
6488 			std::string  uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6489 			std::string  uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
6490 			std::string  uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
6491 			std::string  uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
6492 
6493 			/* Retrieve uniform locations */
6494 			stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6495 			stage_data->uniforms.uniform_location_double_arr[0] =
6496 				gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6497 			stage_data->uniforms.uniform_location_double_arr[1] =
6498 				gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6499 			stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6500 			stage_data->uniforms.uniform_location_dvec2_arr[0] =
6501 				gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6502 			stage_data->uniforms.uniform_location_dvec2_arr[1] =
6503 				gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6504 			stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6505 			stage_data->uniforms.uniform_location_dvec3_arr[0] =
6506 				gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6507 			stage_data->uniforms.uniform_location_dvec3_arr[1] =
6508 				gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6509 			stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6510 			stage_data->uniforms.uniform_location_dvec4_arr[0] =
6511 				gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6512 			stage_data->uniforms.uniform_location_dvec4_arr[1] =
6513 				gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6514 			stage_data->uniform_structure_arrays[0].uniform_location_double =
6515 				gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6516 			stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6517 				gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6518 			stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6519 				gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6520 			stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6521 				gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6522 			stage_data->uniform_structure_arrays[1].uniform_location_double =
6523 				gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6524 			stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6525 				gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6526 			stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6527 				gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6528 			stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6529 				gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6530 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6531 
6532 			if (stage_data->uniforms.uniform_location_double == -1 ||
6533 				stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6534 				stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6535 				stage_data->uniforms.uniform_location_dvec2 == -1 ||
6536 				stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6537 				stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6538 				stage_data->uniforms.uniform_location_dvec3 == -1 ||
6539 				stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6540 				stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6541 				stage_data->uniforms.uniform_location_dvec4 == -1 ||
6542 				stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6543 				stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6544 				stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6545 				stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6546 				stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6547 				stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6548 				stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6549 				stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6550 				stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6551 				stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6552 			{
6553 				TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6554 			}
6555 
6556 			/* Make sure locations of subsequent items in array uniforms are correct */
6557 			if (stage_data->uniforms.uniform_location_double_arr[1] !=
6558 					(stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6559 				stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6560 					(stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6561 				stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6562 					(stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6563 				stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6564 					(stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6565 			{
6566 				m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6567 															   " double_arr[0]:"
6568 								   << stage_data->uniforms.uniform_location_double_arr[0]
6569 								   << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6570 								   << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6571 								   << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6572 								   << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6573 								   << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6574 								   << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6575 								   << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6576 								   << tcu::TestLog::EndMessage;
6577 
6578 				TCU_FAIL("Double-precision uniform array item locations are invalid.");
6579 			}
6580 		} /* for (all uniform prefixes) */
6581 	}	 /* for (both program objects) */
6582 }
6583 
6584 /** Initializes all objects required to run the test. */
initTest()6585 void GPUShaderFP64Test4::initTest()
6586 {
6587 	initProgramObjects();
6588 
6589 	generateUniformValues();
6590 	initUniformValues();
6591 }
6592 
6593 /** Assigns values generated by generateUniformValues() to uniforms defined by
6594  *  both program objects.
6595  **/
initUniformValues()6596 void GPUShaderFP64Test4::initUniformValues()
6597 {
6598 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6599 
6600 	/* Iterate through all programs */
6601 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6602 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6603 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6604 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6605 
6606 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6607 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6608 
6609 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6610 	{
6611 		glw::GLuint   po_id		 = programs[n_program];
6612 		unsigned int  n_stages   = 0;
6613 		_stage_data** stage_data = DE_NULL;
6614 
6615 		if (po_id == m_po_cs_id)
6616 		{
6617 			n_stages   = n_cs_stages;
6618 			stage_data = cs_stages;
6619 		}
6620 		else
6621 		{
6622 			n_stages   = n_noncs_stages;
6623 			stage_data = noncs_stages;
6624 		}
6625 
6626 		/* Skip compute shader program if not supported */
6627 		if (0 == po_id)
6628 		{
6629 			continue;
6630 		}
6631 
6632 		gl.useProgram(po_id);
6633 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6634 
6635 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6636 		{
6637 			/* Iterate through all uniforms */
6638 			_stage_data* stage_ptr = stage_data[n_stage];
6639 
6640 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6641 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6642 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6643 			gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6644 						 stage_ptr->uniform_structure_arrays[0].uniform_double);
6645 			gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6646 						 stage_ptr->uniform_structure_arrays[1].uniform_double);
6647 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6648 
6649 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6650 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6651 						  stage_ptr->uniforms.uniform_dvec2_arr + 0);
6652 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6653 						  stage_ptr->uniforms.uniform_dvec2_arr + 2);
6654 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6655 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6656 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6657 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6658 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6659 
6660 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6661 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6662 						  stage_ptr->uniforms.uniform_dvec3_arr + 0);
6663 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6664 						  stage_ptr->uniforms.uniform_dvec3_arr + 3);
6665 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6666 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6667 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6668 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6669 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6670 
6671 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6672 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6673 						  stage_ptr->uniforms.uniform_dvec4_arr + 0);
6674 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6675 						  stage_ptr->uniforms.uniform_dvec4_arr + 4);
6676 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6677 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6678 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6679 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6680 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6681 		} /* for (all shader stages) */
6682 	}	 /* for (both program objects) */
6683 }
6684 
6685 /** Executes test iteration.
6686  *
6687  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6688  */
iterate()6689 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6690 {
6691 	/* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6692 
6693 	/* Initialize all objects required to run the test */
6694 	initTest();
6695 
6696 	/* Verify the implementation reports correct values for all stages we've configured */
6697 	m_has_test_passed &= verifyUniformValues();
6698 
6699 	/* Is this also the case when "program interface query" mechanism is used? */
6700 	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6701 	{
6702 		m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6703 	}
6704 
6705 	/* We're done */
6706 	if (m_has_test_passed)
6707 	{
6708 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6709 	}
6710 	else
6711 	{
6712 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6713 	}
6714 
6715 	return STOP;
6716 }
6717 
6718 /** Verifies that:
6719  *
6720  *  a) glGetProgramResourceIndex()
6721  *  b) glGetProgramResourceiv()
6722  *  c) glGetProgramResourceName()
6723  *
6724  *  functions return correct values for double-precision uniforms.
6725  *
6726  *  @return true if the verification was passed, false otherwise.
6727  */
verifyProgramInterfaceQuerySupport()6728 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6729 {
6730 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6731 	bool				  result = true;
6732 
6733 	/* Iterate through all programs */
6734 	const char*		   cs_prefixes[]	= { "cs_" };
6735 	_stage_data*	   cs_stages[]		= { &m_data_cs };
6736 	const char*		   noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6737 	_stage_data*	   noncs_stages[]   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6738 	const unsigned int n_cs_stages		= sizeof(cs_stages) / sizeof(cs_stages[0]);
6739 	const unsigned int n_noncs_stages   = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6740 
6741 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
6742 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6743 
6744 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6745 	{
6746 		glw::GLuint   po_id			 = programs[n_program];
6747 		unsigned int  n_stages		 = 0;
6748 		const char**  stage_prefixes = DE_NULL;
6749 		_stage_data** stage_data	 = DE_NULL;
6750 
6751 		if (po_id == m_po_cs_id)
6752 		{
6753 			n_stages	   = n_cs_stages;
6754 			stage_data	 = cs_stages;
6755 			stage_prefixes = cs_prefixes;
6756 		}
6757 		else
6758 		{
6759 			n_stages	   = n_noncs_stages;
6760 			stage_data	 = noncs_stages;
6761 			stage_prefixes = noncs_prefixes;
6762 		}
6763 
6764 		/* Skip compute shader program if not supported */
6765 		if (0 == po_id)
6766 		{
6767 			continue;
6768 		}
6769 
6770 		/* Determine maximum uniform name length */
6771 		glw::GLint max_uniform_name_length = 0;
6772 
6773 		gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6774 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6775 
6776 		/* Allocate a buffer we will use to hold uniform names */
6777 		m_uniform_name_buffer = new char[max_uniform_name_length];
6778 
6779 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6780 		{
6781 			/* Iterate through all uniforms */
6782 			_stage_data* stage_ptr	= stage_data[n_stage];
6783 			const char*  stage_prefix = stage_prefixes[n_stage];
6784 
6785 			/* Construct an array that will be used to run the test in an automated manner */
6786 			_program_interface_query_test_item uniforms[] = {
6787 				/* array size */ /* name */ /* type */ /* location */
6788 				{ 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6789 				{ 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6790 				{ 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6791 				{ 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6792 				{ 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6793 				{ 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6794 				{ 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6795 				{ 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6796 				{ 1, "array[0].struct_double", GL_DOUBLE,
6797 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6798 				{ 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6799 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6800 				{ 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6801 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6802 				{ 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6803 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6804 				{ 1, "array[1].struct_double", GL_DOUBLE,
6805 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
6806 				{ 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6807 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6808 				{ 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6809 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6810 				{ 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6811 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6812 			};
6813 			const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6814 
6815 			/* Prefix the names with stage-specific string */
6816 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6817 			{
6818 				_program_interface_query_test_item& current_item = uniforms[n_uniform];
6819 
6820 				current_item.name = std::string(stage_prefix) + current_item.name;
6821 			} /* for (all uniform descriptors) */
6822 
6823 			const glw::GLenum  properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6824 			const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6825 
6826 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6827 			{
6828 				_program_interface_query_test_item& current_item		  = uniforms[n_uniform];
6829 				glw::GLint							n_written_items		  = 0;
6830 				glw::GLint							retrieved_array_size  = 0;
6831 				glw::GLint							retrieved_name_length = 0;
6832 				glw::GLenum							retrieved_type		  = GL_NONE;
6833 				glw::GLint							temp_buffer[2]		  = { 0, GL_NONE };
6834 
6835 				/* Retrieve index of the iteration-specific uniform */
6836 				glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6837 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6838 
6839 				/* Make sure glGetProgramResourceName() returns correct values */
6840 				memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6841 
6842 				gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6843 										  resource_index, max_uniform_name_length, &retrieved_name_length,
6844 										  m_uniform_name_buffer);
6845 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6846 
6847 				if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6848 					memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6849 				{
6850 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6851 									   << resource_index << "]"
6852 															": expected:["
6853 									   << current_item.name << "]"
6854 															   ", reported:["
6855 									   << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6856 
6857 					result = false;
6858 					continue;
6859 				}
6860 
6861 				/* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6862 				gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6863 										resource_index, n_properties, properties,
6864 										sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6865 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6866 
6867 				if (n_written_items != n_properties)
6868 				{
6869 					TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6870 				}
6871 
6872 				/* For clarity, copy the retrieved values to separate variables */
6873 				retrieved_array_size = temp_buffer[0];
6874 				retrieved_type		 = temp_buffer[1];
6875 
6876 				/* Verify the values */
6877 				if (retrieved_array_size != current_item.expected_array_size)
6878 				{
6879 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6880 									   << current_item.name << "]"
6881 									   << ": expected:[" << current_item.expected_array_size << "]"
6882 																								", reported:["
6883 									   << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6884 
6885 					result = false;
6886 				}
6887 
6888 				if (retrieved_type != current_item.expected_type)
6889 				{
6890 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6891 									   << current_item.name << "]"
6892 									   << ": expected:[" << current_item.expected_type << "]"
6893 																						  ", reported:["
6894 									   << retrieved_type << "]" << tcu::TestLog::EndMessage;
6895 
6896 					result = false;
6897 				}
6898 			} /* for (all uniforms) */
6899 		}	 /* for (all shader stages) */
6900 
6901 		/* We're now OK to release the buffer we used to hold uniform names for
6902 		 * the program */
6903 		if (m_uniform_name_buffer != DE_NULL)
6904 		{
6905 			delete[] m_uniform_name_buffer;
6906 
6907 			m_uniform_name_buffer = DE_NULL;
6908 		}
6909 	} /* for (both program objects) */
6910 
6911 	return result;
6912 }
6913 
6914 /** Verifies glGetUniform*() calls return correct values assigned to
6915  *  double-precision uniforms.
6916  *
6917  *  @return true if all values reported by OpenGL were found to be correct,
6918  *          false otherwise.
6919  **/
verifyUniformValues()6920 bool GPUShaderFP64Test4::verifyUniformValues()
6921 {
6922 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
6923 	bool				  result = true;
6924 
6925 	/* Iterate through all programs */
6926 	_stage_data*	   cs_stages[]	= { &m_data_cs };
6927 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6928 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
6929 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6930 
6931 	const glw::GLuint programs[] = {
6932 		m_po_noncs_id, m_po_cs_id,
6933 	};
6934 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6935 
6936 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6937 	{
6938 		glw::GLuint   po_id		 = programs[n_program];
6939 		unsigned int  n_stages   = 0;
6940 		_stage_data** stage_data = DE_NULL;
6941 
6942 		if (po_id == m_po_cs_id)
6943 		{
6944 			n_stages   = n_cs_stages;
6945 			stage_data = cs_stages;
6946 		}
6947 		else
6948 		{
6949 			n_stages   = n_noncs_stages;
6950 			stage_data = noncs_stages;
6951 		}
6952 
6953 		/* Skip compute shader program if not supported */
6954 		if (0 == po_id)
6955 		{
6956 			continue;
6957 		}
6958 
6959 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6960 		{
6961 			/* Iterate through all uniforms */
6962 			_stage_data* stage_ptr = stage_data[n_stage];
6963 
6964 			/* Set up arrays that we will guide the automated testing */
6965 			const uniform_value_pair double_uniforms[] = {
6966 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6967 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6968 								   stage_ptr->uniforms.uniform_double_arr + 0),
6969 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6970 								   stage_ptr->uniforms.uniform_double_arr + 1),
6971 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6972 								   &stage_ptr->uniform_structure_arrays[0].uniform_double),
6973 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6974 								   &stage_ptr->uniform_structure_arrays[1].uniform_double)
6975 			};
6976 			const uniform_value_pair dvec2_uniforms[] = {
6977 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6978 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6979 								   stage_ptr->uniforms.uniform_dvec2_arr + 0),
6980 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6981 								   stage_ptr->uniforms.uniform_dvec2_arr + 2),
6982 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6983 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6984 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6985 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6986 			};
6987 			const uniform_value_pair dvec3_uniforms[] = {
6988 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6989 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6990 								   stage_ptr->uniforms.uniform_dvec3_arr + 0),
6991 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6992 								   stage_ptr->uniforms.uniform_dvec3_arr + 3),
6993 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
6994 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
6995 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
6996 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
6997 			};
6998 			const uniform_value_pair dvec4_uniforms[] = {
6999 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7000 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7001 								   stage_ptr->uniforms.uniform_dvec4_arr + 0),
7002 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7003 								   stage_ptr->uniforms.uniform_dvec4_arr + 4),
7004 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7005 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7006 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7007 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7008 			};
7009 
7010 			/* Iterate over all uniforms and verify the values reported by the API */
7011 			double		 returned_double_data[4];
7012 			float		 returned_float_data[4];
7013 			int			 returned_int_data[4];
7014 			unsigned int returned_uint_data[4];
7015 
7016 			for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7017 			{
7018 				const uniform_value_pair* current_uv_pairs  = NULL;
7019 				const unsigned int		  n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7020 				unsigned int			  n_pairs			= 0;
7021 
7022 				switch (n_type)
7023 				{
7024 				case 0: /* double */
7025 				{
7026 					current_uv_pairs = double_uniforms;
7027 					n_pairs			 = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7028 
7029 					break;
7030 				}
7031 
7032 				case 1: /* dvec2 */
7033 				{
7034 					current_uv_pairs = dvec2_uniforms;
7035 					n_pairs			 = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7036 
7037 					break;
7038 				}
7039 
7040 				case 2: /* dvec3 */
7041 				{
7042 					current_uv_pairs = dvec3_uniforms;
7043 					n_pairs			 = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7044 
7045 					break;
7046 				}
7047 
7048 				case 3: /* dvec4 */
7049 				{
7050 					current_uv_pairs = dvec4_uniforms;
7051 					n_pairs			 = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7052 
7053 					break;
7054 				}
7055 
7056 				default:
7057 				{
7058 					TCU_FAIL("Invalid type index requested");
7059 				}
7060 				} /* switch (n_type) */
7061 
7062 				for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7063 				{
7064 					const uniform_value_pair& current_uv_pair  = current_uv_pairs[n_pair];
7065 					glw::GLint				  uniform_location = current_uv_pair.first;
7066 					const double*			  uniform_value	= current_uv_pair.second;
7067 
7068 					/* Retrieve the values from the GL implementation*/
7069 					gl.getUniformdv(po_id, uniform_location, returned_double_data);
7070 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7071 
7072 					gl.getUniformfv(po_id, uniform_location, returned_float_data);
7073 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7074 
7075 					gl.getUniformiv(po_id, uniform_location, returned_int_data);
7076 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7077 
7078 					gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7079 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7080 
7081 					/* Make sure the values reported match the reference values */
7082 					bool		can_continue = true;
7083 					const float epsilon		 = 1e-5f;
7084 
7085 					for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7086 					{
7087 						if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7088 						{
7089 							m_testCtx.getLog()
7090 								<< tcu::TestLog::Message
7091 								<< "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7092 								<< uniform_location << "]"
7093 													   " and component ["
7094 								<< n_component << "]"
7095 												  ": retrieved:["
7096 								<< returned_double_data[n_component] << "]"
7097 																		", expected:["
7098 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7099 
7100 							result = false;
7101 						}
7102 
7103 						if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7104 						{
7105 							m_testCtx.getLog()
7106 								<< tcu::TestLog::Message
7107 								<< "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7108 								<< uniform_location << "]"
7109 													   " and component ["
7110 								<< n_component << "]"
7111 												  ": retrieved:["
7112 								<< returned_float_data[n_component] << "]"
7113 																	   ", expected:["
7114 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7115 
7116 							result = false;
7117 						}
7118 
7119 						/* ints */
7120 						int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7121 						unsigned int rounded_uniform_value_uint =
7122 							(unsigned int)(uniform_value[n_component] > 0.0) ?
7123 								((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7124 								0;
7125 
7126 						if (returned_int_data[n_component] != rounded_uniform_value_sint)
7127 						{
7128 							m_testCtx.getLog()
7129 								<< tcu::TestLog::Message
7130 								<< "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7131 								<< uniform_location << "]"
7132 													   " and component ["
7133 								<< n_component << "]"
7134 												  ": retrieved:["
7135 								<< returned_int_data[n_component] << "]"
7136 																	 ", expected:["
7137 								<< rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7138 
7139 							result = false;
7140 						}
7141 
7142 						if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7143 						{
7144 							m_testCtx.getLog()
7145 								<< tcu::TestLog::Message
7146 								<< "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7147 								<< uniform_location << "]"
7148 													   " and component ["
7149 								<< n_component << "]"
7150 												  ": retrieved:["
7151 								<< returned_uint_data[n_component] << "]"
7152 																	  ", expected:["
7153 								<< rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7154 
7155 							result = false;
7156 						}
7157 					} /* for (all components) */
7158 				}	 /* for (all uniform+value pairs) */
7159 			}		  /* for (all 4 uniform types) */
7160 		}			  /* for (all shader stages) */
7161 	}				  /* for (both program objects) */
7162 
7163 	/* All done! */
7164 	return result;
7165 }
7166 
7167 /** Constructor
7168  *
7169  *  @param context Rendering context.
7170  */
GPUShaderFP64Test5(deqp::Context & context)7171 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7172 	: TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7173 									   " floating-point variables work correctly")
7174 	, m_base_value_bo_data(DE_NULL)
7175 	, m_base_value_bo_id(0)
7176 	, m_has_test_passed(true)
7177 	, m_po_base_value_attribute_location(-1)
7178 	, m_po_id(0)
7179 	, m_vao_id(0)
7180 	, m_vs_id(0)
7181 	, m_xfb_bo_id(0)
7182 	, m_xfb_bo_size(0)
7183 {
7184 	/* Set up base value array (as per test spec) */
7185 	m_base_values[0] = -25.12065f;
7186 	m_base_values[1] = 0.0f;
7187 	m_base_values[2] = 0.001f;
7188 	m_base_values[3] = 1.0f;
7189 	m_base_values[4] = 256.78901f;
7190 
7191 	/* Set up swizzle matrix */
7192 	m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7193 	m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7194 	m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7195 	m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7196 	m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7197 	m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7198 	m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7199 	m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7200 	m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7201 	m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7202 	m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7203 	m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7204 	m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7205 	m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7206 	m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7207 	m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7208 }
7209 
deinit()7210 void GPUShaderFP64Test5::deinit()
7211 {
7212 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7213 
7214 	if (m_base_value_bo_data != DE_NULL)
7215 	{
7216 		delete[] m_base_value_bo_data;
7217 
7218 		m_base_value_bo_data = DE_NULL;
7219 	}
7220 
7221 	if (m_base_value_bo_id != 0)
7222 	{
7223 		gl.deleteBuffers(1, &m_base_value_bo_id);
7224 
7225 		m_base_value_bo_id = 0;
7226 	}
7227 
7228 	if (m_vao_id != 0)
7229 	{
7230 		gl.deleteVertexArrays(1, &m_vao_id);
7231 
7232 		m_vao_id = 0;
7233 	}
7234 
7235 	if (m_xfb_bo_id != 0)
7236 	{
7237 		gl.deleteBuffers(1, &m_xfb_bo_id);
7238 
7239 		m_xfb_bo_id = 0;
7240 	}
7241 
7242 	/* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7243 	 * take care of it here
7244 	 */
7245 	deinitInteration();
7246 }
7247 
7248 /** Deinitializes all buffers and GL objects that may have been generated
7249  *  during test execution.
7250  **/
deinitInteration()7251 void GPUShaderFP64Test5::deinitInteration()
7252 {
7253 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7254 
7255 	if (m_po_id != 0)
7256 	{
7257 		gl.deleteProgram(m_po_id);
7258 
7259 		m_po_id = 0;
7260 	}
7261 
7262 	if (m_vs_id != 0)
7263 	{
7264 		gl.deleteShader(m_vs_id);
7265 
7266 		m_vs_id = 0;
7267 	}
7268 }
7269 
7270 /** Executes a single test case iteration using user-provided test case descriptor.
7271  *
7272  *  This function may throw a TestError exception if GL implementation misbehaves.
7273  *
7274  *  @param test_case Test case descriptor to use.
7275  *
7276  *  @return true if the values returned by GL implementation were found to be valid,
7277  *          false otherwise.
7278  **/
executeIteration(const _test_case & test_case)7279 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7280 {
7281 	bool result = true;
7282 
7283 	/* Convert the base values array to the type of input attribute we'll be using
7284 	 * for the iteration.
7285 	 */
7286 	Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7287 
7288 	if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7289 	{
7290 		/* bools are actually represented by ints, since bool varyings are not allowed */
7291 		base_value_type = Utils::VARIABLE_TYPE_INT;
7292 	}
7293 
7294 	const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7295 	const unsigned int n_base_values			 = sizeof(m_base_values) / sizeof(m_base_values[0]);
7296 
7297 	m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7298 
7299 	unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7300 
7301 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7302 	{
7303 		switch (base_value_type)
7304 		{
7305 		case Utils::VARIABLE_TYPE_DOUBLE:
7306 			*((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7307 			break;
7308 		case Utils::VARIABLE_TYPE_FLOAT:
7309 			*((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7310 			break;
7311 		case Utils::VARIABLE_TYPE_INT:
7312 			*((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7313 			break;
7314 		case Utils::VARIABLE_TYPE_UINT:
7315 			*((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7316 			break;
7317 
7318 		default:
7319 		{
7320 			TCU_FAIL("Unrecognized base value type");
7321 		}
7322 		}
7323 
7324 		base_value_traveller_ptr += base_value_component_size;
7325 	} /* for (all base values) */
7326 
7327 	/* Update buffer object storage with the data we've just finished preparing. */
7328 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7329 
7330 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7331 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7332 
7333 	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7334 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7335 
7336 	/* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7337 	 * new data is interpreted correctly.
7338 	 */
7339 	if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7340 	{
7341 		gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,							  /* size */
7342 							   Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7343 							   0,																  /* stride */
7344 							   DE_NULL);														  /* pointer */
7345 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7346 	}
7347 	else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7348 	{
7349 		gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,						/* size */
7350 								Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7351 								DE_NULL);													/* pointer */
7352 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7353 	}
7354 	else
7355 	{
7356 		DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7357 
7358 		gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7359 								GL_DOUBLE, 0,						   /* stride */
7360 								DE_NULL);							   /* pointer */
7361 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7362 	}
7363 
7364 	gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7365 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7366 
7367 	/* Execute the draw call */
7368 	gl.useProgram(m_po_id);
7369 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7370 
7371 	gl.beginTransformFeedback(GL_POINTS);
7372 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7373 	{
7374 		gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7375 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7376 	}
7377 	gl.endTransformFeedback();
7378 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7379 
7380 	/* Map the XFB buffer object into process space */
7381 	void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7382 
7383 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7384 	DE_ASSERT(xfb_data_ptr != NULL);
7385 
7386 	/* Verify the data */
7387 	result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7388 
7389 	/* Unmap the XFB BO */
7390 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7391 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7392 
7393 	/** Good to release the data buffer at this point */
7394 	if (m_base_value_bo_data != DE_NULL)
7395 	{
7396 		delete[] m_base_value_bo_data;
7397 
7398 		m_base_value_bo_data = DE_NULL;
7399 	}
7400 
7401 	/* All done */
7402 	return result;
7403 }
7404 
7405 /** Returns properties of a swizzle operator described by @param type swizzle type.
7406  *
7407  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
7408  *                             corresponding to the specific swizzle operator.
7409  *                             Must not be NULL.
7410  *  @param out_n_components    Deref will be used to store the amount of components
7411  *                             used by the operator. Must not be NULL.
7412  *  @param out_component_order Deref will be used to store up to 4 integer values,
7413  *                             corresponding to component indices described by the
7414  *                             operator for a particular position.  Must not be NULL.
7415  **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7416 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7417 												  unsigned int* out_n_components, unsigned int* out_component_order)
7418 {
7419 	unsigned int result_component_order[4] = { 0 };
7420 	unsigned int result_n_components	   = 0;
7421 	std::string  result_swizzle_string;
7422 
7423 	switch (type)
7424 	{
7425 	case SWIZZLE_TYPE_NONE:
7426 	{
7427 		result_swizzle_string = "";
7428 		result_n_components   = 0;
7429 
7430 		break;
7431 	}
7432 
7433 	case SWIZZLE_TYPE_XWZY:
7434 	{
7435 		result_swizzle_string	 = "xwzy";
7436 		result_n_components		  = 4;
7437 		result_component_order[0] = 0;
7438 		result_component_order[1] = 3;
7439 		result_component_order[2] = 2;
7440 		result_component_order[3] = 1;
7441 
7442 		break;
7443 	}
7444 
7445 	case SWIZZLE_TYPE_XZXY:
7446 	{
7447 		result_swizzle_string	 = "xzxy";
7448 		result_n_components		  = 4;
7449 		result_component_order[0] = 0;
7450 		result_component_order[1] = 2;
7451 		result_component_order[2] = 0;
7452 		result_component_order[3] = 1;
7453 
7454 		break;
7455 	}
7456 
7457 	case SWIZZLE_TYPE_XZY:
7458 	{
7459 		result_swizzle_string	 = "xzy";
7460 		result_n_components		  = 3;
7461 		result_component_order[0] = 0;
7462 		result_component_order[1] = 2;
7463 		result_component_order[2] = 1;
7464 
7465 		break;
7466 	}
7467 
7468 	case SWIZZLE_TYPE_XZYW:
7469 	{
7470 		result_swizzle_string	 = "xzyw";
7471 		result_n_components		  = 4;
7472 		result_component_order[0] = 0;
7473 		result_component_order[1] = 2;
7474 		result_component_order[2] = 1;
7475 		result_component_order[3] = 3;
7476 
7477 		break;
7478 	}
7479 
7480 	case SWIZZLE_TYPE_Y:
7481 	{
7482 		result_swizzle_string	 = "y";
7483 		result_n_components		  = 1;
7484 		result_component_order[0] = 1;
7485 
7486 		break;
7487 	}
7488 
7489 	case SWIZZLE_TYPE_YX:
7490 	{
7491 		result_swizzle_string	 = "yx";
7492 		result_n_components		  = 2;
7493 		result_component_order[0] = 1;
7494 		result_component_order[1] = 0;
7495 
7496 		break;
7497 	}
7498 
7499 	case SWIZZLE_TYPE_YXX:
7500 	{
7501 		result_swizzle_string	 = "yxx";
7502 		result_n_components		  = 3;
7503 		result_component_order[0] = 1;
7504 		result_component_order[1] = 0;
7505 		result_component_order[2] = 0;
7506 
7507 		break;
7508 	}
7509 
7510 	case SWIZZLE_TYPE_YXXY:
7511 	{
7512 		result_swizzle_string	 = "yxxy";
7513 		result_n_components		  = 4;
7514 		result_component_order[0] = 1;
7515 		result_component_order[1] = 0;
7516 		result_component_order[2] = 0;
7517 		result_component_order[3] = 1;
7518 
7519 		break;
7520 	}
7521 
7522 	case SWIZZLE_TYPE_Z:
7523 	{
7524 		result_swizzle_string	 = "z";
7525 		result_n_components		  = 1;
7526 		result_component_order[0] = 2;
7527 
7528 		break;
7529 	}
7530 
7531 	case SWIZZLE_TYPE_ZY:
7532 	{
7533 		result_swizzle_string	 = "zy";
7534 		result_n_components		  = 2;
7535 		result_component_order[0] = 2;
7536 		result_component_order[1] = 1;
7537 
7538 		break;
7539 	}
7540 
7541 	case SWIZZLE_TYPE_W:
7542 	{
7543 		result_swizzle_string	 = "w";
7544 		result_n_components		  = 1;
7545 		result_component_order[0] = 3;
7546 
7547 		break;
7548 	}
7549 
7550 	case SWIZZLE_TYPE_WX:
7551 	{
7552 		result_swizzle_string	 = "wx";
7553 		result_n_components		  = 2;
7554 		result_component_order[0] = 3;
7555 		result_component_order[1] = 0;
7556 
7557 		break;
7558 	}
7559 
7560 	default:
7561 	{
7562 		TCU_FAIL("Unrecognized swizzle type");
7563 	}
7564 	} /* switch (type) */
7565 
7566 	if (out_swizzle_string != DE_NULL)
7567 	{
7568 		*out_swizzle_string = result_swizzle_string;
7569 	}
7570 
7571 	if (out_n_components != DE_NULL)
7572 	{
7573 		*out_n_components = result_n_components;
7574 	}
7575 
7576 	if (out_component_order != DE_NULL)
7577 	{
7578 		memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7579 	}
7580 }
7581 
7582 /** Returns body of a vertex shader that should be used for particular test case,
7583  *  given user-specified test case descriptor.
7584  *
7585  *  @param test_case Descriptor to use for the query.
7586  *
7587  *  @return Requested data.
7588  **/
getVertexShaderBody(const _test_case & test_case)7589 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7590 {
7591 	std::stringstream  result;
7592 	const std::string  base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7593 	const std::string  dst_type_string  = Utils::getVariableTypeString(test_case.dst_type);
7594 	const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7595 	const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7596 	const std::string  src_type_string  = Utils::getVariableTypeString(test_case.src_type);
7597 
7598 	/* Add version preamble */
7599 	result << "#version 420\n"
7600 			  "\n";
7601 
7602 	/* Declare output variables. Note that boolean output variables are not supported, so we need
7603 	 * to handle that special case correctly */
7604 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7605 	{
7606 		result << "out int result;\n";
7607 	}
7608 	else
7609 	{
7610 		result << "out " << dst_type_string << " result;\n";
7611 	}
7612 
7613 	/* Declare input variables. Handle the bool case exclusively. */
7614 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7615 	{
7616 		/* Use ints for bools. We will cast them to bool in the code later. */
7617 		result << "in int base_value;\n";
7618 	}
7619 	else
7620 	{
7621 		result << "in " << base_type_string << " base_value;\n";
7622 	}
7623 
7624 	/* Declare main() and construct the value we will be casting from.
7625 	 *
7626 	 * Note: Addition operations on bool values cause an implicit conversion to int
7627 	 *       which is not allowed. Hence, we skip these operations for this special
7628 	 *       case.
7629 	 */
7630 	result << "void main()\n"
7631 			  "{\n"
7632 		   << src_type_string << " lside_value = ";
7633 
7634 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7635 	{
7636 		result << src_type_string << "(0 != ";
7637 	}
7638 	else
7639 	{
7640 		result << src_type_string << "(";
7641 	}
7642 
7643 	if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7644 	{
7645 		for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7646 		{
7647 			result << "base_value + " << n_component;
7648 
7649 			if (n_component != (n_src_components - 1))
7650 			{
7651 				result << ", ";
7652 			}
7653 		} /* for (all components) */
7654 	}
7655 	else
7656 	{
7657 		DE_ASSERT(n_src_components == 1);
7658 
7659 		result << "base_value";
7660 	}
7661 
7662 	result << ");\n";
7663 
7664 	/* Perform the casting operation. Add swizzle operator if possible. */
7665 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7666 	{
7667 		/* Handle the bool case exclusively */
7668 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7669 		{
7670 			result << "result = (bool(lside_value) == false) ? 0 : 1";
7671 		}
7672 		else
7673 		{
7674 			result << "result = (lside_value == false) ? 0 : 1";
7675 		}
7676 	}
7677 	else
7678 	{
7679 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7680 		{
7681 			result << "result = " << dst_type_string << "(lside_value)";
7682 		}
7683 		else
7684 		{
7685 			result << "result = lside_value";
7686 		}
7687 	}
7688 
7689 	if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7690 	{
7691 		/* Add a swizzle operator  */
7692 		DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7693 		DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7694 
7695 		unsigned int  swizzle_component_order[4] = { 0 };
7696 		unsigned int  swizzle_n_components		 = 0;
7697 		_swizzle_type swizzle_operator			 = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7698 		std::string   swizzle_string;
7699 
7700 		getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7701 
7702 		if (swizzle_n_components > 0)
7703 		{
7704 			result << "." << swizzle_string;
7705 		}
7706 	}
7707 
7708 	/* Close the shader implementation. */
7709 	result << ";\n"
7710 			  "}\n";
7711 
7712 	return result.str();
7713 }
7714 
7715 /** Initializes program & shader objects needed to run the iteration, given
7716  *  user-specified test case descriptor.
7717  *
7718  *  This function can throw a TestError exception if a GL error is detected
7719  *  during execution.
7720  *
7721  *  @param test_case Descriptor to use for the iteration.
7722  **/
initIteration(_test_case & test_case)7723 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7724 {
7725 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7726 
7727 	/* Create program & shader objects */
7728 	m_po_id = gl.createProgram();
7729 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7730 
7731 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7732 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7733 
7734 	/* Configure shader body */
7735 	std::string body		 = getVertexShaderBody(test_case);
7736 	const char* body_raw_ptr = body.c_str();
7737 
7738 	gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7739 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7740 
7741 	/* Store it in the test case descriptor for logging purposes */
7742 	test_case.shader_body = body;
7743 
7744 	/* Compile the shader */
7745 	glw::GLint compile_status = GL_FALSE;
7746 
7747 	gl.compileShader(m_vs_id);
7748 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7749 
7750 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7751 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7752 
7753 	if (compile_status != GL_TRUE)
7754 	{
7755 		TCU_FAIL("Shader compilation failed");
7756 	}
7757 
7758 	/* Attach the shader to the program obejct */
7759 	gl.attachShader(m_po_id, m_vs_id);
7760 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7761 
7762 	/* Configure XFB for the program object */
7763 	const char* xfb_varying_name = "result";
7764 
7765 	gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7766 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7767 
7768 	/* Link the program object */
7769 	glw::GLint link_status = GL_FALSE;
7770 
7771 	gl.linkProgram(m_po_id);
7772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7773 
7774 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7775 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7776 
7777 	if (link_status != GL_TRUE)
7778 	{
7779 		TCU_FAIL("Program linking failed");
7780 	}
7781 
7782 	/* Retrieve attribute locations */
7783 	m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7784 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7785 
7786 	if (m_po_base_value_attribute_location == -1)
7787 	{
7788 		TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7789 	}
7790 }
7791 
7792 /** Initializes GL objects used by all test cases.
7793  *
7794  *  This function may throw a TestError exception if GL implementation reports
7795  *  an error at any point.
7796  **/
initTest()7797 void GPUShaderFP64Test5::initTest()
7798 {
7799 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7800 
7801 	/* Generate buffer object IDs */
7802 	gl.genBuffers(1, &m_base_value_bo_id);
7803 	gl.genBuffers(1, &m_xfb_bo_id);
7804 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7805 
7806 	/* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7807 	 * will never eat up more than 1 double (as per test spec) and we will be drawing
7808 	 * as many points in a single draw call as there are defined in m_base_values array.
7809 	 */
7810 	const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7811 
7812 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7813 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7814 
7815 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7816 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7817 
7818 	/* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7819 	 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7820 	 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7821 	 */
7822 	const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7823 
7824 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7825 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7826 
7827 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7828 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7829 
7830 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7831 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7832 
7833 	/* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7834 	m_xfb_bo_size = xfb_bo_size;
7835 
7836 	/* Generate a vertex array object we will need to use for the draw calls */
7837 	gl.genVertexArrays(1, &m_vao_id);
7838 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7839 
7840 	gl.bindVertexArray(m_vao_id);
7841 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7842 }
7843 
7844 /** Executes test iteration.
7845  *
7846  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7847  */
iterate()7848 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7849 {
7850 	/* Do not execute the test if GL_ARB_texture_view is not supported */
7851 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7852 	{
7853 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7854 	}
7855 
7856 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7857 	{
7858 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7859 	}
7860 
7861 	/* Initialize GL objects needed to run the tests */
7862 	initTest();
7863 
7864 	/* Build iteration array to run the tests in an automated manner */
7865 	_test_case test_cases[] = {
7866 		/* test case type */ /* source type */ /* destination type */
7867 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7868 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7869 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7870 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7871 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7872 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7873 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7874 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7875 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7876 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7877 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7878 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7879 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7880 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7881 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7882 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7883 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7884 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7885 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7886 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7887 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7888 
7889 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7890 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7891 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7892 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7893 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7894 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7895 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7896 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7897 	};
7898 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7899 
7900 	/* Execute all iterations */
7901 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7902 	{
7903 		_test_case& test_case = test_cases[n_test_case];
7904 
7905 		/* Initialize a program object we will use to perform the casting */
7906 		initIteration(test_case);
7907 
7908 		/* Use the program object to XFB the results */
7909 		m_has_test_passed &= executeIteration(test_case);
7910 
7911 		/* Release the GL Resource for this sub test */
7912 		deinitInteration();
7913 
7914 	} /* for (all test cases) */
7915 	/* We're done */
7916 	if (m_has_test_passed)
7917 	{
7918 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7919 	}
7920 	else
7921 	{
7922 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7923 	}
7924 
7925 	return STOP;
7926 }
7927 
7928 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7929  *  for which the data have been generated.
7930  *
7931  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
7932  *  @param test_case Descriptor of the test case, for which the vertex shader was
7933  *                   generated.
7934  *
7935  *  @return true if the data were found to be valid, false otherwise.
7936  **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7937 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7938 {
7939 	const Utils::_variable_type base_dst_type		= Utils::getBaseVariableType(test_case.dst_type);
7940 	const Utils::_variable_type base_src_type		= Utils::getBaseVariableType(test_case.src_type);
7941 	const float					epsilon				= 1e-5f;
7942 	const unsigned int			n_base_values		= sizeof(m_base_values) / sizeof(m_base_values[0]);
7943 	const unsigned int			n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7944 	const unsigned int			n_src_components	= Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7945 	bool						result				= true;
7946 	_swizzle_type				swizzle_operator	= SWIZZLE_TYPE_NONE;
7947 	unsigned int				swizzle_order[4]	= { 0 };
7948 	const unsigned char*		traveller_ptr		= data_ptr;
7949 
7950 	if (!Utils::isMatrixVariableType(test_case.src_type))
7951 	{
7952 		DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7953 		DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7954 
7955 		swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7956 
7957 		getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7958 								 DE_NULL,					/* out_n_components */
7959 								 swizzle_order);
7960 	}
7961 
7962 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7963 	{
7964 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7965 		{
7966 			unsigned int n_swizzled_component = n_result_component;
7967 
7968 			if (swizzle_operator != SWIZZLE_TYPE_NONE)
7969 			{
7970 				n_swizzled_component =
7971 					(n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7972 			}
7973 
7974 			switch (base_dst_type)
7975 			{
7976 			case Utils::VARIABLE_TYPE_BOOL:
7977 			case Utils::VARIABLE_TYPE_INT:
7978 			{
7979 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7980 				double expected_value	 = ref_expected_value;
7981 				int	result_value		  = *((int*)traveller_ptr);
7982 
7983 				if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7984 				{
7985 					if (expected_value != 0.0)
7986 					{
7987 						expected_value = 1.0;
7988 					}
7989 				}
7990 
7991 				if (result_value != (int)expected_value)
7992 				{
7993 					m_testCtx.getLog() << tcu::TestLog::Message
7994 									   << "Invalid boolean/integer value obtained when doing an "
7995 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
7996 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
7997 									   << "]"
7998 										  ", component index: ["
7999 									   << n_swizzled_component << "]"
8000 																  ", value: ["
8001 									   << ref_expected_value << "]"
8002 																" to GLSL type ["
8003 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8004 																							  ", retrieved value: ["
8005 									   << result_value << "]"
8006 														  ", expected value: ["
8007 									   << (int)expected_value << "]"
8008 																 ", shader used:\n"
8009 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8010 
8011 					result = false;
8012 				}
8013 
8014 				traveller_ptr += sizeof(int);
8015 				break;
8016 			} /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8017 
8018 			case Utils::VARIABLE_TYPE_DOUBLE:
8019 			{
8020 				double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8021 				double expected_value	 = ref_expected_value;
8022 				double result_value		  = *((double*)traveller_ptr);
8023 
8024 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8025 				{
8026 					expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8027 				}
8028 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8029 				{
8030 					expected_value = (int)expected_value;
8031 				}
8032 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8033 				{
8034 					// Negative values in base values array when converted to unsigned int will be ZERO
8035 					// Addition operations done inside the shader in such cases will operate on ZERO rather
8036 					// than the negative value being passed.
8037 					// Replicate the sequence of conversion and addition operations done on the
8038 					// shader input, to calculate the expected values in XFB data in the
8039 					// problematic cases.
8040 					if (expected_value < 0)
8041 					{
8042 						expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8043 					}
8044 					expected_value = (unsigned int)expected_value;
8045 				}
8046 
8047 				traveller_ptr += sizeof(double);
8048 				if (de::abs(result_value - expected_value) > epsilon)
8049 				{
8050 					m_testCtx.getLog() << tcu::TestLog::Message
8051 									   << "Invalid double-precision floating-point value obtained when doing an "
8052 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8053 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8054 									   << "]"
8055 										  ", component index: ["
8056 									   << n_swizzled_component << "]"
8057 																  ", value: ["
8058 									   << ref_expected_value << "]"
8059 																" to GLSL type ["
8060 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8061 																							  ", retrieved value: ["
8062 									   << std::setprecision(16) << result_value << "]"
8063 																				   ", expected value: ["
8064 									   << std::setprecision(16) << expected_value << "]"
8065 																					 ", shader used:\n"
8066 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8067 
8068 					result = false;
8069 				}
8070 
8071 				break;
8072 			} /* VARIABLE_TYPE_DOUBLE case */
8073 
8074 			case Utils::VARIABLE_TYPE_FLOAT:
8075 			{
8076 				float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8077 				float expected_value	 = ref_expected_value;
8078 				float result_value		 = *((float*)traveller_ptr);
8079 
8080 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8081 				{
8082 					expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8083 				}
8084 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8085 				{
8086 					expected_value = (float)((int)expected_value);
8087 				}
8088 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8089 				{
8090 					expected_value = (float)((unsigned int)expected_value);
8091 				}
8092 
8093 				traveller_ptr += sizeof(float);
8094 				if (de::abs(result_value - expected_value) > epsilon)
8095 				{
8096 					m_testCtx.getLog() << tcu::TestLog::Message
8097 									   << "Invalid single-precision floating-point value obtained when doing an "
8098 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8099 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8100 									   << "]"
8101 										  ", component index: ["
8102 									   << n_swizzled_component << "]"
8103 																  ", value: ["
8104 									   << ref_expected_value << "]"
8105 																" to GLSL type ["
8106 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8107 																							  ", retrieved value: ["
8108 									   << std::setprecision(16) << result_value << "]"
8109 																				   ", expected value: ["
8110 									   << std::setprecision(16) << expected_value << "]"
8111 																					 ", shader used:\n"
8112 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8113 
8114 					result = false;
8115 				}
8116 
8117 				break;
8118 			} /* VARIABLE_TYPE_FLOAT case */
8119 
8120 			case Utils::VARIABLE_TYPE_UINT:
8121 			{
8122 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8123 				double expected_value	 = ref_expected_value;
8124 				unsigned int result_value = *((unsigned int*)traveller_ptr);
8125 
8126 				traveller_ptr += sizeof(unsigned int);
8127 				if (result_value != (unsigned int)expected_value)
8128 				{
8129 					if (expected_value < 0.0)
8130 					{
8131 						// It is undefined to convert a negative floating-point value to an uint.
8132 						break;
8133 					}
8134 
8135 					m_testCtx.getLog() << tcu::TestLog::Message
8136 									   << "Invalid unsigned integer value obtained when doing an "
8137 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8138 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8139 									   << "]"
8140 										  ", component index: ["
8141 									   << n_swizzled_component << "]"
8142 																  ", value: ["
8143 									   << ref_expected_value << "]"
8144 																" to GLSL type ["
8145 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
8146 																							  ", retrieved value: ["
8147 									   << result_value << "]"
8148 														  ", expected value: ["
8149 									   << (unsigned int)expected_value << "]"
8150 																		  ", shader used:\n"
8151 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8152 
8153 					result = false;
8154 				}
8155 
8156 				break;
8157 			} /* VARIABLE_TYPE_UINT case */
8158 
8159 			default:
8160 			{
8161 				TCU_FAIL("Unrecognized variable type");
8162 			}
8163 			} /* switch (test_case.dst_type) */
8164 		}	 /* for (all result components) */
8165 	}		  /* for (all base values) */
8166 
8167 	return result;
8168 }
8169 
8170 /** Constructor
8171  *
8172  *  @param context Rendering context.
8173  */
GPUShaderFP64Test6(deqp::Context & context)8174 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8175 	: TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8176 											   "during compilation time.")
8177 	, m_cs_id(0)
8178 	, m_fs_id(0)
8179 	, m_gs_id(0)
8180 	, m_tc_id(0)
8181 	, m_te_id(0)
8182 	, m_vs_id(0)
8183 	, m_has_test_passed(true)
8184 {
8185 }
8186 
8187 /** Deinitializes all buffers and GL objects that may have been generated
8188  *  during test execution.
8189  **/
deinit()8190 void GPUShaderFP64Test6::deinit()
8191 {
8192 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8193 
8194 	if (m_cs_id != 0)
8195 	{
8196 		gl.deleteShader(m_cs_id);
8197 
8198 		m_cs_id = 0;
8199 	}
8200 
8201 	if (m_fs_id != 0)
8202 	{
8203 		gl.deleteShader(m_fs_id);
8204 
8205 		m_fs_id = 0;
8206 	}
8207 
8208 	if (m_gs_id != 0)
8209 	{
8210 		gl.deleteShader(m_gs_id);
8211 
8212 		m_gs_id = 0;
8213 	}
8214 
8215 	if (m_tc_id != 0)
8216 	{
8217 		gl.deleteShader(m_tc_id);
8218 
8219 		m_tc_id = 0;
8220 	}
8221 
8222 	if (m_te_id != 0)
8223 	{
8224 		gl.deleteShader(m_te_id);
8225 
8226 		m_te_id = 0;
8227 	}
8228 
8229 	if (m_vs_id != 0)
8230 	{
8231 		gl.deleteShader(m_vs_id);
8232 
8233 		m_vs_id = 0;
8234 	}
8235 }
8236 
8237 /** Executes a single test case.
8238  *
8239  *  This function can throw TestError exceptions if GL implementation reports
8240  *  an error.
8241  *
8242  *  @param test_case Test case descriptor.
8243  *
8244  *  @return true if test case passed, false otherwise.
8245  **/
executeIteration(const _test_case & test_case)8246 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8247 {
8248 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
8249 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8250 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
8251 	bool				  result	 = true;
8252 	const char*			  stage_body = NULL;
8253 	const char*			  stage_name = NULL;
8254 
8255 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8256 	{
8257 		const glw::GLuint so_id = so_ids[n_so_id];
8258 
8259 		/* Skip compute shader if it is not supported */
8260 		if (0 == so_id)
8261 		{
8262 			continue;
8263 		}
8264 
8265 		/* Compile the shader */
8266 		gl.compileShader(so_id);
8267 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8268 
8269 		/* Has the compilation failed as expected? */
8270 		glw::GLint compile_status = GL_TRUE;
8271 
8272 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8273 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8274 
8275 		if (compile_status == GL_TRUE)
8276 		{
8277 			/* What is the current stage's name? */
8278 			if (so_id == m_cs_id)
8279 			{
8280 				stage_body = test_case.cs_shader_body.c_str();
8281 				stage_name = "Compute shader";
8282 			}
8283 			else if (so_id == m_fs_id)
8284 			{
8285 				stage_body = test_case.fs_shader_body.c_str();
8286 				stage_name = "Fragment shader";
8287 			}
8288 			else if (so_id == m_gs_id)
8289 			{
8290 				stage_body = test_case.gs_shader_body.c_str();
8291 				stage_name = "Geometry shader";
8292 			}
8293 			else if (so_id == m_tc_id)
8294 			{
8295 				stage_body = test_case.tc_shader_body.c_str();
8296 				stage_name = "Tessellation control shader";
8297 			}
8298 			else if (so_id == m_te_id)
8299 			{
8300 				stage_body = test_case.te_shader_body.c_str();
8301 				stage_name = "Tessellation evaluation shader";
8302 			}
8303 			else if (so_id == m_vs_id)
8304 			{
8305 				stage_body = test_case.vs_shader_body.c_str();
8306 				stage_name = "Vertex shader";
8307 			}
8308 			else
8309 			{
8310 				/* Doesn't make much sense to throw exceptions here so.. */
8311 				stage_body = "";
8312 				stage_name = "[?]";
8313 			}
8314 
8315 			/* This shader should have never compiled successfully! */
8316 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8317 							   << " has been compiled successfully, even though the shader was malformed."
8318 								  " Following is shader body:\n"
8319 							   << stage_body << tcu::TestLog::EndMessage;
8320 
8321 			result = false;
8322 		}
8323 	} /* for (all shader objects) */
8324 
8325 	return result;
8326 }
8327 
8328 /** Retrieves body of a compute shader that should be used for the purpose of
8329  *  user-specified test case.
8330  *
8331  *  @param test_case Test case descriptor to use.
8332  *
8333  *  @return Requested string.
8334  **/
getComputeShaderBody(const _test_case & test_case)8335 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8336 {
8337 	std::stringstream result_sstream;
8338 
8339 	/* Add pre-amble */
8340 	result_sstream << "#version 420\n"
8341 					  "#extension GL_ARB_compute_shader          : require\n"
8342 					  "\n"
8343 					  "layout(local_size_x = 6) in;\n"
8344 					  "\n"
8345 					  "void main()\n"
8346 					  "{\n";
8347 
8348 	/* Add local variable declarations */
8349 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8350 
8351 	if (test_case.src_array_size > 1)
8352 	{
8353 		result_sstream << "[" << test_case.src_array_size << "]";
8354 	}
8355 
8356 	result_sstream << ";\n";
8357 
8358 	if (test_case.wrap_dst_type_in_structure)
8359 	{
8360 		result_sstream << "struct\n"
8361 						  "{\n"
8362 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8363 	}
8364 	else
8365 	{
8366 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8367 	}
8368 
8369 	result_sstream << ";\n";
8370 
8371 	if (test_case.wrap_dst_type_in_structure)
8372 	{
8373 		result_sstream << "\n} dst;\n";
8374 	}
8375 
8376 	/* Add actual body */
8377 	result_sstream << "dst = src;\n"
8378 					  "}\n";
8379 
8380 	/* Return the body */
8381 	return result_sstream.str();
8382 }
8383 
8384 /** Retrieves body of a fragment shader that should be used for the purpose of
8385  *  user-specified test case.
8386  *
8387  *  @param test_case Test case descriptor to use.
8388  *
8389  *  @return Requested string.
8390  **/
getFragmentShaderBody(const _test_case & test_case)8391 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8392 {
8393 	std::stringstream result_sstream;
8394 
8395 	/* Add pre-amble */
8396 	result_sstream << "#version 420\n"
8397 					  "\n"
8398 					  "void main()\n"
8399 					  "{\n";
8400 
8401 	/* Add local variable declarations */
8402 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8403 
8404 	if (test_case.src_array_size > 1)
8405 	{
8406 		result_sstream << "[" << test_case.src_array_size << "]";
8407 	}
8408 
8409 	result_sstream << ";\n";
8410 
8411 	if (test_case.wrap_dst_type_in_structure)
8412 	{
8413 		result_sstream << "struct\n"
8414 						  "{\n"
8415 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8416 	}
8417 	else
8418 	{
8419 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8420 	}
8421 
8422 	result_sstream << ";\n";
8423 
8424 	if (test_case.wrap_dst_type_in_structure)
8425 	{
8426 		result_sstream << "\n} dst;\n";
8427 	}
8428 
8429 	/* Add actual body */
8430 	result_sstream << "dst = src;\n"
8431 					  "}\n";
8432 
8433 	/* Return the body */
8434 	return result_sstream.str();
8435 }
8436 
8437 /** Retrieves body of a geometry shader that should be used for the purpose of
8438  *  user-specified test case.
8439  *
8440  *  @param test_case Test case descriptor to use.
8441  *
8442  *  @return Requested string.
8443  **/
getGeometryShaderBody(const _test_case & test_case)8444 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8445 {
8446 	std::stringstream result_sstream;
8447 
8448 	/* Add preamble */
8449 	result_sstream << "#version 420\n"
8450 					  "\n"
8451 					  "layout(points)                 in;\n"
8452 					  "layout(max_vertices=1, points) out;\n"
8453 					  "\n"
8454 					  "void main()\n"
8455 					  "{\n";
8456 
8457 	/* Add local variable declarations */
8458 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8459 
8460 	if (test_case.src_array_size > 1)
8461 	{
8462 		result_sstream << "[" << test_case.src_array_size << "]";
8463 	}
8464 
8465 	result_sstream << ";\n";
8466 
8467 	if (test_case.wrap_dst_type_in_structure)
8468 	{
8469 		result_sstream << "struct\n"
8470 						  "{\n"
8471 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8472 	}
8473 	else
8474 	{
8475 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8476 	}
8477 
8478 	result_sstream << ";\n"
8479 					  "\n";
8480 
8481 	if (test_case.wrap_dst_type_in_structure)
8482 	{
8483 		result_sstream << "} dst;\n";
8484 	}
8485 
8486 	/* Add actual body */
8487 	result_sstream << "dst = src;\n"
8488 					  "}\n";
8489 
8490 	/* We're done! */
8491 	return result_sstream.str();
8492 }
8493 
8494 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8495  *  user-specified test case.
8496  *
8497  *  @param test_case Test case descriptor to use.
8498  *
8499  *  @return Requested string.
8500  **/
getTessellationControlShaderBody(const _test_case & test_case)8501 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8502 {
8503 	std::stringstream result_sstream;
8504 
8505 	/* Add preamble */
8506 	result_sstream << "#version 420\n"
8507 					  "\n"
8508 					  "layout(vertices=4) out;\n"
8509 					  "\n"
8510 					  "void main()\n"
8511 					  "{\n";
8512 
8513 	/* Add local variable declarations. */
8514 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8515 
8516 	if (test_case.src_array_size > 1)
8517 	{
8518 		result_sstream << "[" << test_case.src_array_size << "]";
8519 	}
8520 
8521 	result_sstream << ";\n";
8522 
8523 	if (test_case.wrap_dst_type_in_structure)
8524 	{
8525 		result_sstream << "struct\n"
8526 						  "{\n"
8527 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8528 	}
8529 	else
8530 	{
8531 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8532 	}
8533 
8534 	if (test_case.wrap_dst_type_in_structure)
8535 	{
8536 		result_sstream << ";\n"
8537 						  "} dst;\n";
8538 	}
8539 	else
8540 	{
8541 		result_sstream << ";\n";
8542 	}
8543 
8544 	/* Continue with the actual body. */
8545 	result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8546 					  "gl_TessLevelOuter[1] = 1.0;\n"
8547 					  "dst                  = src;\n"
8548 					  "}\n";
8549 
8550 	/* Return the body */
8551 	return result_sstream.str();
8552 }
8553 
8554 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8555  *  user-specified test case.
8556  *
8557  *  @param test_case Test case descriptor to use.
8558  *
8559  *  @return Requested string.
8560  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8561 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8562 {
8563 	std::stringstream result_sstream;
8564 
8565 	/* Add preamble */
8566 	result_sstream << "#version 420\n"
8567 					  "\n"
8568 					  "layout(isolines) in;\n"
8569 					  "\n"
8570 					  "void main()\n"
8571 					  "{\n";
8572 
8573 	/* Add local variable declarations */
8574 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8575 
8576 	if (test_case.src_array_size > 1)
8577 	{
8578 		result_sstream << "[" << test_case.src_array_size << "]";
8579 	}
8580 
8581 	result_sstream << ";\n";
8582 
8583 	if (test_case.wrap_dst_type_in_structure)
8584 	{
8585 		result_sstream << "struct\n"
8586 						  "{\n"
8587 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8588 	}
8589 	else
8590 	{
8591 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8592 	}
8593 
8594 	if (test_case.wrap_dst_type_in_structure)
8595 	{
8596 		result_sstream << ";\n"
8597 						  "} dst;\n";
8598 	}
8599 	else
8600 	{
8601 		result_sstream << ";\n";
8602 	}
8603 
8604 	/* Continue with the actual body. */
8605 	result_sstream << "dst = src;\n";
8606 
8607 	/* Complete the body */
8608 	result_sstream << "}\n";
8609 
8610 	/* Return the body */
8611 	return result_sstream.str();
8612 }
8613 
8614 /** Retrieves body of a vertex shader that should be used for the purpose of
8615  *  user-specified test case.
8616  *
8617  *  @param test_case Test case descriptor to use.
8618  *
8619  *  @return Requested string.
8620  **/
getVertexShaderBody(const _test_case & test_case)8621 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8622 {
8623 	std::stringstream result_sstream;
8624 
8625 	/* Add preamble */
8626 	result_sstream << "#version 420\n"
8627 					  "\n"
8628 					  "void main()\n"
8629 					  "{\n";
8630 
8631 	/* Add local variables */
8632 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8633 
8634 	if (test_case.src_array_size > 1)
8635 	{
8636 		result_sstream << "[" << test_case.src_array_size << "]";
8637 	}
8638 
8639 	result_sstream << ";\n";
8640 
8641 	if (test_case.wrap_dst_type_in_structure)
8642 	{
8643 		result_sstream << "struct\n"
8644 						  "{\n"
8645 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
8646 	}
8647 	else
8648 	{
8649 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8650 	}
8651 
8652 	if (test_case.wrap_dst_type_in_structure)
8653 	{
8654 		result_sstream << ";\n"
8655 						  "} dst;\n";
8656 	}
8657 	else
8658 	{
8659 		result_sstream << ";\n";
8660 	}
8661 
8662 	/* Start actual body */
8663 	result_sstream << "dst         = src;\n"
8664 					  "gl_Position = vec4(1.0);\n"
8665 					  "}";
8666 
8667 	return result_sstream.str();
8668 }
8669 
8670 /** Initializes shader objects required to run the test. */
initTest()8671 void GPUShaderFP64Test6::initTest()
8672 {
8673 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8674 
8675 	/* Generate shader objects */
8676 
8677 	/* Compute shader support and GL 4.2 required */
8678 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8679 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8680 	{
8681 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8682 	}
8683 
8684 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8685 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8686 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8687 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8688 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8689 
8690 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8691 }
8692 
8693 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8694  *
8695  *  @param test_case Test case descriptor to generate the shader bodies for.
8696  **/
initIteration(_test_case & test_case)8697 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8698 {
8699 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8700 
8701 	test_case.cs_shader_body = getComputeShaderBody(test_case);
8702 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
8703 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
8704 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8705 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8706 	test_case.vs_shader_body = getVertexShaderBody(test_case);
8707 
8708 	/* Assign the bodies to relevant shaders */
8709 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8710 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8711 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8712 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8713 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8714 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8715 
8716 	/* m_cs_id is initialized only if compute_shader is supported */
8717 	if (0 != m_cs_id)
8718 	{
8719 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8720 	}
8721 
8722 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8723 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8724 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8725 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8726 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8727 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8728 }
8729 
8730 /** Executes test iteration.
8731  *
8732  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8733  */
iterate()8734 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8735 {
8736 	/* Do not execute the test if GL_ARB_texture_view is not supported */
8737 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8738 	{
8739 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8740 	}
8741 
8742 	/* Initialize GL objects needed to run the tests */
8743 	initTest();
8744 
8745 	/* Build iteration array to run the tests in an automated manner */
8746 	_test_case test_cases[] = {
8747 		/* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8748 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8749 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8750 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8751 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8752 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8753 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8754 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8755 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8756 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8757 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8758 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8759 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8760 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8761 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8762 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8763 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8764 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8765 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8766 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8767 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8768 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8769 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8770 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8771 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8772 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8773 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8774 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8775 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8776 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8777 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8778 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8779 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8780 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8781 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8782 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8783 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8784 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8785 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8786 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8787 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8788 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8789 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8790 	};
8791 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8792 
8793 	/* Execute all iterations */
8794 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8795 	{
8796 		_test_case& test_case = test_cases[n_test_case];
8797 
8798 		/* Initialize a program object we will use to perform the casting */
8799 		initIteration(test_case);
8800 
8801 		/* Use the program object to XFB the results */
8802 		m_has_test_passed &= executeIteration(test_case);
8803 
8804 	} /* for (all test cases) */
8805 
8806 	/* We're done */
8807 	if (m_has_test_passed)
8808 	{
8809 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8810 	}
8811 	else
8812 	{
8813 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8814 	}
8815 
8816 	return STOP;
8817 }
8818 
8819 /** Constructor
8820  *
8821  *  @param context Rendering context.
8822  */
GPUShaderFP64Test7(deqp::Context & context)8823 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8824 	: TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8825 									"in all shader stages.")
8826 	, m_are_double_inputs_supported(false)
8827 	, m_fbo_id(0)
8828 	, m_fs_id(0)
8829 	, m_gs_id(0)
8830 	, m_has_test_passed(true)
8831 	, m_n_max_components_per_stage(0)
8832 	, m_n_xfb_varyings(0)
8833 	, m_po_id(0)
8834 	, m_tc_id(0)
8835 	, m_te_id(0)
8836 	, m_to_id(0)
8837 	, m_to_data(NULL)
8838 	, m_to_height(4)
8839 	, m_to_width(4)
8840 	, m_xfb_bo_id(0)
8841 	, m_xfb_varyings(NULL)
8842 	, m_vao_id(0)
8843 	, m_vs_id(0)
8844 {
8845 }
8846 
8847 /** Compiles all shaders attached to test program object and links it.
8848  *
8849  *  @param variables
8850  *
8851  *  @return true if the process was executed successfully, false otherwise.
8852  */
buildTestProgram(_variables & variables)8853 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8854 {
8855 	std::string			  fs_body = getFragmentShaderBody(variables);
8856 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
8857 	std::string			  gs_body = getGeometryShaderBody(variables);
8858 	std::string			  tc_body = getTessellationControlShaderBody(variables);
8859 	std::string			  te_body = getTessellationEvaluationShaderBody(variables);
8860 	std::string			  vs_body = getVertexShaderBody(variables);
8861 	bool				  result  = false;
8862 
8863 	/* Try to link the program object */
8864 	glw::GLint link_status = GL_FALSE;
8865 
8866 	/* Compile the shaders */
8867 	if (!compileShader(m_fs_id, fs_body))
8868 	{
8869 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8870 
8871 		goto end;
8872 	}
8873 
8874 	if (!compileShader(m_gs_id, gs_body))
8875 	{
8876 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8877 
8878 		goto end;
8879 	}
8880 
8881 	if (!compileShader(m_tc_id, tc_body))
8882 	{
8883 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8884 						   << tcu::TestLog::EndMessage;
8885 
8886 		goto end;
8887 	}
8888 
8889 	if (!compileShader(m_te_id, te_body))
8890 	{
8891 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8892 						   << tcu::TestLog::EndMessage;
8893 
8894 		goto end;
8895 	}
8896 
8897 	if (!compileShader(m_vs_id, vs_body))
8898 	{
8899 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8900 
8901 		goto end;
8902 	}
8903 
8904 	/* Configure XFB */
8905 	releaseXFBVaryingNames();
8906 	generateXFBVaryingNames(variables);
8907 
8908 	gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8909 
8910 	gl.linkProgram(m_po_id);
8911 
8912 	/* Have we succeeded? */
8913 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8914 
8915 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8916 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8917 
8918 	if (link_status != GL_TRUE)
8919 	{
8920 		m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8921 						   << tcu::TestLog::EndMessage;
8922 
8923 		goto end;
8924 	}
8925 
8926 	/* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8927 	if (m_are_double_inputs_supported)
8928 	{
8929 		const size_t n_variables = variables.size();
8930 
8931 		for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8932 		{
8933 			_variable&		  current_variable = variables[n_variable];
8934 			std::stringstream attribute_name_sstream;
8935 
8936 			attribute_name_sstream << "in_vs_variable" << n_variable;
8937 
8938 			if (current_variable.array_size > 1)
8939 			{
8940 				attribute_name_sstream << "[0]";
8941 			}
8942 
8943 			current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8944 
8945 			if (current_variable.attribute_location == -1)
8946 			{
8947 				m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8948 								   << attribute_name_sstream.str().c_str()
8949 								   << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8950 
8951 				m_has_test_passed = false;
8952 				goto end;
8953 			}
8954 		} /* for (all test variables) */
8955 	}	 /* if (m_are_double_inputs_supported) */
8956 
8957 	m_current_fs_body = fs_body;
8958 	m_current_gs_body = gs_body;
8959 	m_current_tc_body = tc_body;
8960 	m_current_te_body = te_body;
8961 	m_current_vs_body = vs_body;
8962 
8963 	result = true;
8964 
8965 end:
8966 	return result;
8967 }
8968 
8969 /** Updates shader object's body and then compiles the shader.
8970  *
8971  *  @param body Body to use for the shader.
8972  *
8973  *  @return true if the shader compiled successfully, false otherwise.
8974  **/
compileShader(glw::GLint shader_id,const std::string & body)8975 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8976 {
8977 	const char*			  body_raw_ptr   = body.c_str();
8978 	glw::GLint			  compile_status = GL_FALSE;
8979 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
8980 
8981 	gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8982 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8983 
8984 	gl.compileShader(shader_id);
8985 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8986 
8987 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8988 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8989 
8990 	return (compile_status == GL_TRUE);
8991 }
8992 
8993 /** Configure storage of a buffer object used for capturing XFB data.
8994  *
8995  *  @param variables Holds descriptor for all variables used for the iteration the
8996  *                   BO is being configured for. Storage size will be directly related
8997  *                   to the number of the variables and their type.
8998  */
configureXFBBuffer(const _variables & variables)8999 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9000 {
9001 	DE_ASSERT(m_n_xfb_varyings != 0);
9002 
9003 	/* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9004 	 * The test only draws a single patch, and triangles are caught by transform feed-back.
9005 	 * Let's initialize the storage, according to the list of variables that will be used
9006 	 * for the test run.
9007 	 */
9008 	unsigned int bo_size = 0;
9009 
9010 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9011 		 variables_iterator++)
9012 	{
9013 		const _variable& variable		= *variables_iterator;
9014 		unsigned int	 n_bytes_needed = static_cast<unsigned int>(
9015 			Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9016 
9017 		bo_size += n_bytes_needed;
9018 	} /* for (all variables) */
9019 
9020 	bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9021 
9022 	/* Set up the BO storage */
9023 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9024 
9025 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9026 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9027 }
9028 
9029 /** Deinitializes all buffers and GL objects that may have been generated
9030  *  during test execution.
9031  **/
deinit()9032 void GPUShaderFP64Test7::deinit()
9033 {
9034 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9035 
9036 	if (m_fbo_id != 0)
9037 	{
9038 		gl.deleteFramebuffers(1, &m_fbo_id);
9039 
9040 		m_fbo_id = 0;
9041 	}
9042 
9043 	if (m_fs_id != 0)
9044 	{
9045 		gl.deleteShader(m_fs_id);
9046 
9047 		m_fs_id = 0;
9048 	}
9049 
9050 	if (m_gs_id != 0)
9051 	{
9052 		gl.deleteShader(m_gs_id);
9053 
9054 		m_gs_id = 0;
9055 	}
9056 
9057 	if (m_po_id != 0)
9058 	{
9059 		gl.deleteProgram(m_po_id);
9060 
9061 		m_po_id = 0;
9062 	}
9063 
9064 	if (m_tc_id != 0)
9065 	{
9066 		gl.deleteShader(m_tc_id);
9067 
9068 		m_tc_id = 0;
9069 	}
9070 
9071 	if (m_te_id != 0)
9072 	{
9073 		gl.deleteShader(m_te_id);
9074 
9075 		m_te_id = 0;
9076 	}
9077 
9078 	if (m_to_data != NULL)
9079 	{
9080 		delete[] m_to_data;
9081 
9082 		m_to_data = NULL;
9083 	}
9084 
9085 	if (m_to_id != 0)
9086 	{
9087 		gl.deleteTextures(1, &m_to_id);
9088 
9089 		m_to_id = 0;
9090 	}
9091 
9092 	if (m_xfb_bo_id != 0)
9093 	{
9094 		gl.deleteBuffers(1, &m_xfb_bo_id);
9095 
9096 		m_xfb_bo_id = 0;
9097 	}
9098 
9099 	if (m_xfb_varyings != DE_NULL)
9100 	{
9101 		releaseXFBVaryingNames();
9102 	}
9103 
9104 	if (m_vao_id != 0)
9105 	{
9106 		gl.deleteVertexArrays(1, &m_vao_id);
9107 
9108 		m_vao_id = 0;
9109 	}
9110 
9111 	if (m_vs_id != 0)
9112 	{
9113 		gl.deleteShader(m_vs_id);
9114 
9115 		m_vs_id = 0;
9116 	}
9117 }
9118 
9119 /** Executes the functional part of the test (case a) from the test spec)
9120  *
9121  *  @param variables Vector of variable descriptors defining properties of
9122  *                   variables that should be used for the iteration.
9123  *
9124  *  @return true if the test passed, false otherwise.
9125  **/
executeFunctionalTest(_variables & variables)9126 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9127 {
9128 	bool result = true;
9129 
9130 	/* Build the test program */
9131 	if (!buildTestProgram(variables))
9132 	{
9133 		return false;
9134 	}
9135 
9136 	/* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9137 	if (m_are_double_inputs_supported)
9138 	{
9139 		setInputAttributeValues(variables);
9140 	}
9141 
9142 	/* Set up buffer object to hold XFB data. The data will be used for logging purposes
9143 	 * only, if a data mismatch is detected.
9144 	 */
9145 	configureXFBBuffer(variables);
9146 
9147 	/* Issue a draw call using the test program */
9148 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9149 
9150 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9151 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9152 
9153 	gl.clear(GL_COLOR_BUFFER_BIT);
9154 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9155 
9156 	gl.useProgram(m_po_id);
9157 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9158 
9159 	gl.viewport(0, /* x */
9160 				0, /* y */
9161 				m_to_width, m_to_height);
9162 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9163 
9164 	gl.beginTransformFeedback(GL_TRIANGLES);
9165 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9166 	{
9167 		gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9168 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9169 	}
9170 	gl.endTransformFeedback();
9171 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9172 
9173 	/* Verify color attachment contents */
9174 	const float epsilon = 1.0f / 255.0f;
9175 
9176 	gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9177 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9178 
9179 	for (unsigned int y = 0; y < m_to_height; ++y)
9180 	{
9181 		const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9182 
9183 		for (unsigned int x = 0; x < m_to_width; ++x)
9184 		{
9185 			const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9186 
9187 			if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9188 				de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9189 			{
9190 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9191 								   << ")"
9192 									  "; expected:(0, 255, 0, 0), found: ("
9193 								   << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9194 								   << ", " << (int)pixel_ptr[3]
9195 								   << "), with the following variable types used as varyings:"
9196 								   << tcu::TestLog::EndMessage;
9197 
9198 				/* List the variable types that failed the test */
9199 				const size_t n_variables = variables.size();
9200 
9201 				for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9202 				{
9203 					m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9204 									   << Utils::getVariableTypeString(variables[n_variable].type)
9205 									   << " (array size:" << variables[n_variable].array_size << ")"
9206 									   << tcu::TestLog::EndMessage;
9207 				} /* for (all variable types) */
9208 
9209 				/* Log the variable contents */
9210 				logVariableContents(variables);
9211 
9212 				/* Log shaders used for the iteration */
9213 				m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9214 															   "\n"
9215 															   "(VS):\n"
9216 								   << m_current_vs_body.c_str() << "\n"
9217 								   << "(TC):\n"
9218 									  "\n"
9219 								   << m_current_tc_body.c_str() << "\n"
9220 																   "(TE):\n"
9221 																   "\n"
9222 								   << m_current_te_body.c_str() << "\n"
9223 																   "(GS):\n"
9224 								   << m_current_gs_body.c_str() << "\n"
9225 																   "(FS):\n"
9226 																   "\n"
9227 								   << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9228 
9229 				result = false;
9230 
9231 				goto end;
9232 			}
9233 		} /* for (all columns) */
9234 	}	 /* for (all rows) */
9235 
9236 /* All done! */
9237 end:
9238 	return result;
9239 }
9240 
9241 /** Takes user-input vector of test variables and allocates & fills an array of strings
9242  *  holding names of geometry shader stage varyings that should be captured during
9243  *  transform feedback operation. The array will be stored in m_xfb_varyings.
9244  *
9245  *  @param variables Holds all test variable descriptors to be used for the iteration.
9246  */
generateXFBVaryingNames(const _variables & variables)9247 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9248 {
9249 	unsigned int n_variable = 0;
9250 	unsigned int n_varying  = 0;
9251 	unsigned int n_varyings = 0;
9252 
9253 	if (m_xfb_varyings != NULL)
9254 	{
9255 		releaseXFBVaryingNames();
9256 	}
9257 
9258 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9259 		 ++variables_iterator)
9260 	{
9261 		const _variable& variable = *variables_iterator;
9262 
9263 		n_varyings += variable.array_size;
9264 	}
9265 
9266 	m_xfb_varyings = new glw::GLchar*[n_varyings];
9267 
9268 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9269 		 ++variables_iterator, ++n_variable)
9270 	{
9271 		const _variable& variable = *variables_iterator;
9272 
9273 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9274 		{
9275 			std::stringstream varying_sstream;
9276 			size_t			  varying_length;
9277 
9278 			varying_sstream << "gs_variable" << n_variable;
9279 
9280 			if (variable.array_size > 1)
9281 			{
9282 				varying_sstream << "[" << array_index << "]";
9283 			}
9284 
9285 			/* Store the varying name */
9286 			varying_length			  = varying_sstream.str().length();
9287 			m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9288 
9289 			memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9290 			m_xfb_varyings[n_varying][varying_length] = 0;
9291 		} /* for (all array indices) */
9292 	}	 /* for (all varyings) */
9293 
9294 	m_n_xfb_varyings = n_varyings;
9295 }
9296 
9297 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9298  *  without using the "flat" keyword. (case c) )
9299  *
9300  *  @param input_variable_type Variable type to use for input variable declaration.
9301  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9302  *                             of the arrayed variable.
9303  *
9304  *  @return Requested string.
9305  **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9306 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9307 	Utils::_variable_type input_variable_type, unsigned int array_size)
9308 {
9309 	std::stringstream result_sstream;
9310 	std::stringstream array_index_stringstream;
9311 	std::stringstream array_size_stringstream;
9312 
9313 	if (array_size > 1)
9314 	{
9315 		array_index_stringstream << "[0]";
9316 		array_size_stringstream << "[" << array_size << "]";
9317 	}
9318 
9319 	if (Utils::isMatrixVariableType(input_variable_type))
9320 	{
9321 		array_index_stringstream << "[0].x";
9322 	}
9323 	else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9324 	{
9325 		array_index_stringstream << "[0]";
9326 	}
9327 
9328 	result_sstream << "#version 400\n"
9329 					  "\n"
9330 					  "in "
9331 				   << Utils::getVariableTypeString(input_variable_type) << " test_input"
9332 				   << array_size_stringstream.str() << ";\n"
9333 													   "\n"
9334 													   "out float test_output;\n"
9335 													   "\n"
9336 													   "void main()\n"
9337 													   "{\n"
9338 													   "    if (test_input"
9339 				   << array_index_stringstream.str() << " > 2.0)\n"
9340 														"    {\n"
9341 														"        test_output = 1.0;\n"
9342 														"    }\n"
9343 														"    else\n"
9344 														"    {\n"
9345 														"        test_output = 3.0;\n"
9346 														"    }\n"
9347 														"}\n";
9348 
9349 	return result_sstream.str();
9350 }
9351 
9352 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9353  *
9354  *  @param input_variable_type Variable type to use for input variable declaration.
9355  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9356  *                             of the arrayed variable.
9357  *
9358  *  @return Requested string.
9359  **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9360 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9361 	Utils::_variable_type output_variable_type, unsigned int array_size)
9362 {
9363 	std::stringstream array_index_sstream;
9364 	std::stringstream array_size_sstream;
9365 	std::stringstream result_sstream;
9366 	std::string		  output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9367 
9368 	if (array_size > 1)
9369 	{
9370 		array_index_sstream << "[0]";
9371 		array_size_sstream << "[" << array_size << "]";
9372 	}
9373 
9374 	result_sstream << "#version 400\n"
9375 					  "\n"
9376 					  "out "
9377 				   << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9378 																								   "\n"
9379 																								   "void main()\n"
9380 																								   "{\n"
9381 																								   "    test_output"
9382 				   << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9383 																						   "}\n";
9384 
9385 	return result_sstream.str();
9386 }
9387 
9388 /** Retrieves body of a fragment shader that uses user-specified set of variables
9389  *  to declare contents of input & output block.
9390  *
9391  *  @param variables As per description.
9392  *
9393  *  @return Requested string.
9394  **/
getFragmentShaderBody(const _variables & variables)9395 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9396 {
9397 	std::stringstream result_sstream;
9398 
9399 	/* Form the pre-amble */
9400 	result_sstream << "#version 400\n"
9401 					  "\n"
9402 
9403 				   /* Add input block */
9404 				   << "in GS_DATA\n"
9405 					  "{\n"
9406 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9407 																		  "\n"
9408 
9409 				   /* Add output variable */
9410 				   << "out vec4 result;\n"
9411 					  "\n"
9412 
9413 					  /* Add main() definition */
9414 					  "void main()\n"
9415 					  "{\n"
9416 					  "const double epsilon = 1e-5;\n"
9417 					  "\n"
9418 					  "result = vec4(1, 0, 0, 0);\n"
9419 					  "\n";
9420 
9421 	/* Determine expected values first */
9422 	unsigned int base_counter = 1;
9423 	const size_t n_variables  = variables.size();
9424 
9425 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9426 	{
9427 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9428 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9429 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9430 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9431 
9432 		std::stringstream array_size_sstream;
9433 
9434 		if (variable_array_size > 1)
9435 		{
9436 			array_size_sstream << "[" << variable_array_size << "]";
9437 		}
9438 
9439 		/* Local variable declaration */
9440 		result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9441 					   << ";\n"
9442 						  "\n";
9443 
9444 		/* Set expected values */
9445 		for (unsigned int index = 0; index < variable_array_size; ++index)
9446 		{
9447 			std::stringstream array_index_sstream;
9448 
9449 			if (variable_array_size > 1)
9450 			{
9451 				array_index_sstream << "[" << index << "]";
9452 			}
9453 
9454 			result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9455 						   << variable_type_string << "(";
9456 
9457 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9458 			{
9459 				unsigned int expected_value =
9460 					(base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9461 
9462 				if (m_are_double_inputs_supported)
9463 				{
9464 					/* VS input attributes */
9465 					//expected_value += (base_counter + 6);
9466 					expected_value -= 1;
9467 				}
9468 
9469 				result_sstream << expected_value;
9470 
9471 				if (n_component != (n_variable_type_components - 1))
9472 				{
9473 					result_sstream << ", ";
9474 				}
9475 
9476 				++base_counter;
9477 			} /* for (all components) */
9478 
9479 			result_sstream << ");\n";
9480 		} /* for (all array indices) */
9481 
9482 		result_sstream << "\n";
9483 	} /* for (all variable types) */
9484 
9485 	/* Now that we know the expected values, do a huge conditional check to verify if all
9486 	 * input variables carry correct information.
9487 	 */
9488 	result_sstream << "if (";
9489 
9490 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9491 	{
9492 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9493 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9494 		bool				  is_variable_type_matrix	= Utils::isMatrixVariableType(variable_type);
9495 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9496 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9497 
9498 		for (unsigned int index = 0; index < variable_array_size; ++index)
9499 		{
9500 			std::stringstream array_index_sstream;
9501 
9502 			if (variable_array_size > 1)
9503 			{
9504 				array_index_sstream << "[" << index << "]";
9505 			}
9506 
9507 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9508 			{
9509 				std::stringstream component_index_sstream;
9510 
9511 				if (n_variable_type_components > 1)
9512 				{
9513 					component_index_sstream << "[" << n_component << "]";
9514 				}
9515 
9516 				result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9517 
9518 				if (is_variable_type_matrix)
9519 				{
9520 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9521 					const unsigned int column	= n_component % n_columns;
9522 					const unsigned int row		 = n_component / n_columns;
9523 
9524 					result_sstream << "[" << column << "]"
9525 													   "."
9526 								   << Utils::getComponentAtIndex(row);
9527 				}
9528 				else
9529 				{
9530 					result_sstream << component_index_sstream.str();
9531 				}
9532 
9533 				result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9534 
9535 				if (is_variable_type_matrix)
9536 				{
9537 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9538 					const unsigned int column	= n_component % n_columns;
9539 					const unsigned int row		 = n_component / n_columns;
9540 
9541 					result_sstream << "[" << column << "]"
9542 													   "."
9543 								   << Utils::getComponentAtIndex(row);
9544 				}
9545 				else
9546 				{
9547 					result_sstream << component_index_sstream.str();
9548 				}
9549 
9550 				result_sstream << ") <= epsilon &&";
9551 			} /* for (all components) */
9552 		}	 /* for (all array indices) */
9553 	}		  /* for (all variable types) */
9554 
9555 	result_sstream << "true)\n"
9556 					  "{\n"
9557 					  "    result = vec4(0, 1, 0, 0);\n"
9558 					  "}\n"
9559 					  "}\n";
9560 
9561 	/* All done */
9562 	return result_sstream.str();
9563 }
9564 
9565 /** Retrieves body of a geometry shader that uses user-specified set of variables
9566  *  to declare contents of input & output block.
9567  *
9568  *  @param variables As per description.
9569  *
9570  *  @return Requested string.
9571  **/
getGeometryShaderBody(const _variables & variables)9572 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9573 {
9574 	std::stringstream result_sstream;
9575 
9576 	/* Form the pre-amble */
9577 	result_sstream << "#version 400\n"
9578 					  "\n"
9579 					  "layout(triangles)                      in;\n"
9580 					  "layout(triangle_strip, max_vertices=4) out;\n"
9581 					  "\n"
9582 
9583 					  /* Add the input block */
9584 					  "in TE_DATA\n"
9585 					  "{\n"
9586 				   << getVariableDeclarations("te", variables) << "} in_data[];\n"
9587 																  "\n"
9588 
9589 																  /* Add the output block */
9590 																  "out GS_DATA\n"
9591 																  "{\n"
9592 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
9593 																		  "\n"
9594 
9595 																		  /* Declare main() function */
9596 																		  "void main()\n"
9597 																		  "{\n";
9598 
9599 	/* Take input variables, add a predefined value and forward them to output variables */
9600 	const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9601 									1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
9602 	const unsigned int n_quad_vertices =
9603 		sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9604 	const size_t n_variables = variables.size();
9605 
9606 	for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9607 	{
9608 		unsigned int counter			 = 4;
9609 		const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9610 
9611 		for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9612 		{
9613 			unsigned int		  variable_array_size = variables[n_variable].array_size;
9614 			Utils::_variable_type variable_type		  = variables[n_variable].type;
9615 			unsigned int n_variable_type_components   = Utils::getNumberOfComponentsForVariableType(variable_type);
9616 			std::string  variable_type_string		  = Utils::getVariableTypeString(variable_type);
9617 
9618 			for (unsigned int index = 0; index < variable_array_size; ++index)
9619 			{
9620 				std::stringstream array_index_sstream;
9621 
9622 				if (variable_array_size > 1)
9623 				{
9624 					array_index_sstream << "[" << index << "]";
9625 				}
9626 
9627 				result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9628 							   << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9629 							   << variable_type_string << "(";
9630 
9631 				for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9632 				{
9633 					result_sstream << (counter++);
9634 
9635 					if (n_component != (n_variable_type_components - 1))
9636 					{
9637 						result_sstream << ", ";
9638 					}
9639 				} /* for (all components) */
9640 
9641 				result_sstream << ");\n";
9642 			} /* for (all array indices) */
9643 		}	 /* for (all variable types) */
9644 
9645 		result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9646 					   << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9647 																					  "EmitVertex();\n";
9648 	} /* for (all emitted quad vertices) */
9649 
9650 	result_sstream << "EndPrimitive();\n"
9651 					  "}\n";
9652 
9653 	/* All done */
9654 	return result_sstream.str();
9655 }
9656 
9657 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9658  *  to declare contents of input & output block.
9659  *
9660  *  @param variables As per description.
9661  *
9662  *  @return Requested string.
9663  **/
getTessellationControlShaderBody(const _variables & variables)9664 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9665 {
9666 	std::stringstream result_sstream;
9667 
9668 	/* Form the pre-amble */
9669 	result_sstream << "#version 400\n"
9670 					  "\n"
9671 					  "layout (vertices=4) out;\n"
9672 
9673 					  /* Declare input block */
9674 					  "in VS_DATA\n"
9675 					  "{\n"
9676 				   << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9677 
9678 																  /* Declare output block */
9679 																  "out TC_DATA\n"
9680 																  "{\n"
9681 				   << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9682 																  "\n"
9683 
9684 																  /* Define main() */
9685 																  "void main()\n"
9686 																  "{\n"
9687 																  "    gl_TessLevelInner[0] = 1;\n"
9688 																  "    gl_TessLevelInner[1] = 1;\n"
9689 																  "    gl_TessLevelOuter[0] = 1;\n"
9690 																  "    gl_TessLevelOuter[1] = 1;\n"
9691 																  "    gl_TessLevelOuter[2] = 1;\n"
9692 																  "    gl_TessLevelOuter[3] = 1;\n"
9693 																  "\n";
9694 
9695 	/* Take input variables, add a predefined value and forward them to output variables */
9696 	const size_t n_variables = variables.size();
9697 	unsigned int counter	 = 2;
9698 
9699 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9700 	{
9701 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9702 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9703 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9704 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9705 
9706 		for (unsigned int index = 0; index < variable_array_size; ++index)
9707 		{
9708 			std::stringstream array_index_sstream;
9709 
9710 			if (variable_array_size > 1)
9711 			{
9712 				array_index_sstream << "[" << index << "]";
9713 			}
9714 
9715 			result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9716 						   << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9717 						   << variable_type_string << "(";
9718 
9719 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9720 			{
9721 				result_sstream << (counter++);
9722 
9723 				if (n_component != (n_variable_type_components - 1))
9724 				{
9725 					result_sstream << ", ";
9726 				}
9727 			}
9728 
9729 			result_sstream << ");\n";
9730 		} /* for (all array indices) */
9731 	}	 /* for (all variable types) */
9732 
9733 	result_sstream << "}\n";
9734 
9735 	/* We're done */
9736 	return result_sstream.str();
9737 }
9738 
9739 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9740  *  to declare contents of input & output block.
9741  *
9742  *  @param variables As per description.
9743  *
9744  *  @return Requested string.
9745  **/
getTessellationEvaluationShaderBody(const _variables & variables)9746 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9747 {
9748 	std::stringstream result_sstream;
9749 
9750 	/* Form the pre-amble */
9751 	result_sstream << "#version 400\n"
9752 					  "\n"
9753 					  "layout(quads) in;\n"
9754 					  "\n"
9755 
9756 					  /* Define input block */
9757 					  "in TC_DATA\n"
9758 					  "{\n"
9759 				   << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9760 																  "\n"
9761 
9762 																  /* Define output block */
9763 																  "out TE_DATA\n"
9764 																  "{\n"
9765 				   << getVariableDeclarations("te", variables) << "};\n"
9766 																  "\n"
9767 
9768 																  /* Define main() */
9769 																  "void main()\n"
9770 																  "{\n";
9771 
9772 	/* Take input variables, add a predefined value and forward them to output variables */
9773 	const size_t n_variables = variables.size();
9774 	unsigned int counter	 = 3;
9775 
9776 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9777 	{
9778 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9779 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9780 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9781 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9782 
9783 		for (unsigned int index = 0; index < variable_array_size; ++index)
9784 		{
9785 			std::stringstream array_index_sstream;
9786 
9787 			if (variable_array_size > 1)
9788 			{
9789 				array_index_sstream << "[" << index << "]";
9790 			}
9791 
9792 			result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9793 						   << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9794 
9795 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9796 			{
9797 				result_sstream << (counter++);
9798 
9799 				if (n_component != (n_variable_type_components - 1))
9800 				{
9801 					result_sstream << ", ";
9802 				}
9803 			} /* for (all components) */
9804 
9805 			result_sstream << ");\n";
9806 		} /* for (all array indices) */
9807 	}	 /* for (all variable types) */
9808 
9809 	result_sstream << "}\n";
9810 
9811 	/* All done */
9812 	return result_sstream.str();
9813 }
9814 
9815 /** Returns a string containing declarations of user-specified set of variables.
9816  *  Each declaration can optionally use a layot qualifier requested by the caller.
9817  *
9818  *  @param prefix             Prefix to use for variable names.
9819  *  @param variables          List of variables to declare in the result string.
9820  *  @param explicit_locations true if each declaration should explicitly define location
9821  *                            of the variable ( eg. (layout location=X) )
9822  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
9823  *                            be NULL.
9824  *
9825  *  @return Requested string.
9826  **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9827 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9828 														const char* layout_qualifier)
9829 {
9830 	std::stringstream result_sstream;
9831 
9832 	/* Define output variables */
9833 	const size_t n_variables = variables.size();
9834 
9835 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9836 	{
9837 		unsigned int		  variable_array_size  = variables[n_variable].array_size;
9838 		Utils::_variable_type variable_type		   = variables[n_variable].type;
9839 		std::string			  variable_type_string = Utils::getVariableTypeString(variable_type);
9840 
9841 		result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9842 
9843 		if (variable_array_size > 1)
9844 		{
9845 			result_sstream << "[" << variable_array_size << "]";
9846 		}
9847 
9848 		result_sstream << ";\n";
9849 	} /* for (all user-specified variable types) */
9850 
9851 	return result_sstream.str();
9852 }
9853 
9854 /** Retrieves body of a vertex shader that uses user-specified set of variables
9855  *  to declare contents of input & output block.
9856  *
9857  *  @param variables As per description.
9858  *
9859  *  @return Requested string.
9860  **/
getVertexShaderBody(const _variables & variables)9861 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9862 {
9863 	std::stringstream result_sstream;
9864 
9865 	/* Form pre-amble */
9866 	result_sstream << "#version 400\n"
9867 					  "\n";
9868 
9869 	/* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9870 	if (m_are_double_inputs_supported)
9871 	{
9872 		result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9873 					   << getVariableDeclarations("in_vs", variables, "in");
9874 	}
9875 
9876 	/* Define output variables */
9877 	result_sstream << "out VS_DATA\n"
9878 					  "{\n"
9879 				   << getVariableDeclarations("vs", variables);
9880 
9881 	/* Define main() */
9882 	result_sstream << "};\n"
9883 					  "\n"
9884 					  "void main()\n"
9885 					  "{\n";
9886 
9887 	/* Set output variable values */
9888 	unsigned int counter	 = 1;
9889 	const size_t n_variables = variables.size();
9890 
9891 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9892 	{
9893 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
9894 		Utils::_variable_type variable_type				 = variables[n_variable].type;
9895 		const unsigned int	n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9896 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
9897 
9898 		for (unsigned int index = 0; index < variable_array_size; ++index)
9899 		{
9900 			if (variable_array_size == 1)
9901 			{
9902 				result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9903 			}
9904 			else
9905 			{
9906 				result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9907 							   << " = " << variable_type_string << "(";
9908 			}
9909 
9910 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9911 			{
9912 				result_sstream << (double)(counter++);
9913 
9914 				/* Use input attributes, if available */
9915 				if (m_are_double_inputs_supported)
9916 				{
9917 					result_sstream << " + in_vs_variable" << n_variable;
9918 
9919 					if (variable_array_size > 1)
9920 					{
9921 						result_sstream << "[" << index << "]";
9922 					}
9923 
9924 					if (Utils::isMatrixVariableType(variables[n_variable].type))
9925 					{
9926 						const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9927 						const unsigned int column	= n_component % n_columns;
9928 						const unsigned int row		 = n_component / n_columns;
9929 
9930 						result_sstream << "[" << (column) << "]"
9931 															 "."
9932 									   << Utils::getComponentAtIndex(row);
9933 					}
9934 					else if (n_variable_type_components > 1)
9935 					{
9936 						result_sstream << "[" << n_component << "]";
9937 					}
9938 				}
9939 
9940 				if (n_component != (n_variable_type_components - 1))
9941 				{
9942 					result_sstream << ", ";
9943 				}
9944 			} /* for (all components) */
9945 
9946 			result_sstream << ");\n";
9947 		}
9948 	} /* for (all variable types) */
9949 
9950 	/* We will be using geometry shader to lay out the actual vertices so
9951 	 * the only thing we need to make sure is that the vertex never gets
9952 	 * culled.
9953 	 */
9954 	result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9955 					  "}\n";
9956 
9957 	/* That's it */
9958 	return result_sstream.str();
9959 }
9960 
9961 /** Initializes shader objects required to run the test. */
initTest()9962 void GPUShaderFP64Test7::initTest()
9963 {
9964 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9965 
9966 	/* Are double-precision input variables supported? */
9967 	m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9968 
9969 	/* Create a vertex array object */
9970 	gl.genVertexArrays(1, &m_vao_id);
9971 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9972 
9973 	gl.bindVertexArray(m_vao_id);
9974 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9975 
9976 	/* Create a texture object we will use as FBO's color attachment */
9977 	gl.genTextures(1, &m_to_id);
9978 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9979 
9980 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9981 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9982 
9983 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9984 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9985 
9986 	/* Allocate temporary buffer to hold the texture data we will be reading
9987 	 * from color attachment. */
9988 	m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9989 
9990 	/* Create and set up a framebuffer object */
9991 	gl.genFramebuffers(1, &m_fbo_id);
9992 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9993 
9994 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9995 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
9996 
9997 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9998 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9999 
10000 	/* Create all shader objects */
10001 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10002 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10003 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10004 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10005 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10006 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10007 
10008 	/* Create test program object */
10009 	m_po_id = gl.createProgram();
10010 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10011 
10012 	/* Attach the shaders to the program object */
10013 	gl.attachShader(m_po_id, m_fs_id);
10014 	gl.attachShader(m_po_id, m_gs_id);
10015 	gl.attachShader(m_po_id, m_tc_id);
10016 	gl.attachShader(m_po_id, m_te_id);
10017 	gl.attachShader(m_po_id, m_vs_id);
10018 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10019 
10020 	/* The test passes double-precision values through the whole rendering pipeline.
10021 	 * This translates to a notable amount of components that we would need to transfer
10022 	 * all values in one fell swoop. The number is large enough to exceed minimum
10023 	 * capabilities as described for OpenGL 4.0 implementations.
10024 	 * For that reason, the test executes in turns. Each turn is allocated as many
10025 	 * double-precision scalar/matrix values as supported by the tested GL implementation.
10026 	 */
10027 	glw::GLint gl_max_fragment_input_components_value				  = 0;
10028 	glw::GLint gl_max_geometry_input_components_value				  = 0;
10029 	glw::GLint gl_max_geometry_output_components_value				  = 0;
10030 	glw::GLint gl_max_tess_control_input_components_value			  = 0;
10031 	glw::GLint gl_max_tess_control_output_components_value			  = 0;
10032 	glw::GLint gl_max_tess_evaluation_input_components_value		  = 0;
10033 	glw::GLint gl_max_tess_evaluation_output_components_value		  = 0;
10034 	glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10035 	glw::GLint gl_max_vertex_output_components_value				  = 0;
10036 
10037 	gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10038 	gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10039 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10040 	gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10041 	gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10042 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10043 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10044 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10045 				   &gl_max_transform_feedback_interleaved_components_value);
10046 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10047 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10048 
10049 	m_n_max_components_per_stage =
10050 		de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10051 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10052 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10053 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10054 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10055 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10056 	m_n_max_components_per_stage =
10057 		de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10058 	m_n_max_components_per_stage =
10059 		de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10060 
10061 	/* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10062 	 * the input patch */
10063 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
10064 
10065 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10066 
10067 	/* Initialize a BO we will use to hold XFB data */
10068 	gl.genBuffers(1, &m_xfb_bo_id);
10069 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10070 
10071 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10072 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10073 
10074 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10075 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10076 }
10077 
10078 /** Executes test iteration.
10079  *
10080  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10081  */
iterate()10082 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10083 {
10084 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10085 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10086 	{
10087 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10088 	}
10089 
10090 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10091 	{
10092 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10093 	}
10094 
10095 	/* Initialize GL objects required to run the test */
10096 	initTest();
10097 
10098 	/* Check the negative cases first */
10099 	const Utils::_variable_type double_variable_types[] = {
10100 		Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10101 		Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10102 		Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10103 		Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10104 		Utils::VARIABLE_TYPE_DMAT4X3,
10105 	};
10106 	const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10107 
10108 	for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10109 		 ++n_double_variable_type)
10110 	{
10111 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
10112 		{
10113 			Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10114 
10115 			if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10116 			{
10117 				m_testCtx.getLog() << tcu::TestLog::Message
10118 								   << "A fragment shader with double-precision output variable compiled successfully."
10119 								   << tcu::TestLog::EndMessage;
10120 
10121 				m_has_test_passed = false;
10122 			}
10123 
10124 			if (compileShader(m_fs_id,
10125 							  getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10126 			{
10127 				m_testCtx.getLog()
10128 					<< tcu::TestLog::Message
10129 					<< "A fragment shader with double-precision input variables lacking flat layout qualifier"
10130 					   " compiled successfully."
10131 					<< tcu::TestLog::EndMessage;
10132 
10133 				m_has_test_passed = false;
10134 			}
10135 		}
10136 	} /* for (all variable types) */
10137 
10138 	/* Execute functional test. Split the run into as many iterations as necessary
10139 	 * so that we do not exceed GL implementation's capabilities. */
10140 	unsigned int n_tested_variables = 0;
10141 	_variables   variables_to_test;
10142 
10143 	while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10144 	{
10145 		glw::GLint total_n_used_components = 0;
10146 
10147 		/* Use as many variables as possible for the iterations. Do not exceed maximum amount
10148 		 * of varying components that can be used for all shadr stages.
10149 		 */
10150 		while (total_n_used_components < m_n_max_components_per_stage &&
10151 			   n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10152 		{
10153 			_variable	new_variable;
10154 			unsigned int n_type_components = 0;
10155 			glw::GLint   n_used_components = 0;
10156 
10157 			new_variable.array_size =
10158 				((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10159 			new_variable.type = double_variable_types[n_tested_variables / 2];
10160 
10161 			/* Double-precision varyings can use twice as many components as single-precision FPs */
10162 			n_type_components = 4 /* components per location */ *
10163 								Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10164 			n_used_components = n_type_components * new_variable.array_size * 2;
10165 
10166 			/* Do we have enough space? */
10167 			if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10168 			{
10169 				if (n_used_components > m_n_max_components_per_stage)
10170 				{ //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10171 					n_tested_variables++;
10172 				}
10173 				break;
10174 			}
10175 
10176 			/* We can safely test the type in current iteration */
10177 			total_n_used_components += n_used_components;
10178 			n_tested_variables++;
10179 
10180 			variables_to_test.push_back(new_variable);
10181 		}
10182 
10183 		if (variables_to_test.size() > 0)
10184 		{
10185 			m_has_test_passed &= executeFunctionalTest(variables_to_test);
10186 
10187 			variables_to_test.clear();
10188 		}
10189 	}
10190 
10191 	/* We're done */
10192 	if (m_has_test_passed)
10193 	{
10194 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10195 	}
10196 	else
10197 	{
10198 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10199 	}
10200 
10201 	return STOP;
10202 }
10203 
10204 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10205 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10206 {
10207 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10208 	std::stringstream	 log_sstream;
10209 
10210 	log_sstream << "Test variable values as retrieved from geometry shader:\n";
10211 
10212 	/* Map the XFB BO contents into process space */
10213 	const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10214 
10215 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10216 
10217 	/* Read the variable contents. We only care about the set of varyings emitted
10218 	 * for first vertex in the geometry shader */
10219 	unsigned int		 n_varying	 = 0;
10220 	const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10221 
10222 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10223 		 ++variables_iterator, ++n_varying)
10224 	{
10225 		const _variable&			 variable			= *variables_iterator;
10226 		const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10227 		const unsigned int			 n_components		= Utils::getNumberOfComponentsForVariableType(variable.type);
10228 
10229 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10230 		{
10231 			log_sstream << "gs_variable" << n_varying;
10232 
10233 			if (variable.array_size > 1)
10234 			{
10235 				log_sstream << "[" << array_index << "]";
10236 			}
10237 
10238 			log_sstream << ": (";
10239 
10240 			for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10241 			{
10242 				log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10243 
10244 				if (n_component != (n_components - 1))
10245 				{
10246 					log_sstream << ", ";
10247 				}
10248 
10249 				traveller_ptr += sizeof(double);
10250 			}
10251 
10252 			log_sstream << ")\n";
10253 		} /* for (all array indices) */
10254 	}	 /* for (all variables) */
10255 
10256 	/* Unmap the BO */
10257 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10258 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10259 
10260 	/* Pass the logged stream into the framework */
10261 	m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10262 }
10263 
10264 /** De-allocates an arary holding strings representing names of varyings that
10265  *  should be used for transform feed-back.
10266  **/
releaseXFBVaryingNames()10267 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10268 {
10269 	for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10270 	{
10271 		delete[] m_xfb_varyings[n_varying];
10272 	}
10273 
10274 	delete[] m_xfb_varyings;
10275 	m_xfb_varyings = DE_NULL;
10276 
10277 	m_n_xfb_varyings = 0;
10278 }
10279 
10280 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10281  *  Takes a list of test variables used for current iteration and assigns increasing values
10282  *  to subsequent input attributes of the test program.
10283  *
10284  *  @param variables Test variables of the current iteration.
10285  */
setInputAttributeValues(const _variables & variables)10286 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10287 {
10288 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
10289 
10290 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10291 		 variable_iterator++)
10292 	{
10293 		const _variable&   variable			  = *variable_iterator;
10294 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
10295 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10296 		unsigned int	   n_components		  = 0;
10297 		unsigned int	   n_columns		  = 1;
10298 
10299 		if (is_matrix_type)
10300 		{
10301 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
10302 			n_components = n_total_components / n_columns;
10303 
10304 			DE_ASSERT(n_total_components % n_columns == 0);
10305 		}
10306 		else
10307 		{
10308 			n_components = n_total_components;
10309 		}
10310 
10311 		DE_ASSERT(n_components >= 1 && n_components <= 4);
10312 
10313 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10314 		{
10315 			const double data[] = { -1, -1, -1, -1 };
10316 
10317 			switch (n_components)
10318 			{
10319 			case 1:
10320 			{
10321 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
10322 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10323 
10324 				break;
10325 			}
10326 
10327 			case 2:
10328 			{
10329 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
10330 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10331 
10332 				break;
10333 			}
10334 
10335 			case 3:
10336 			{
10337 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
10338 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10339 
10340 				break;
10341 			}
10342 
10343 			case 4:
10344 			{
10345 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
10346 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10347 
10348 				break;
10349 			}
10350 
10351 			default:
10352 			{
10353 				TCU_FAIL("Unrecognized number of components");
10354 			}
10355 			} /* switch (n_components) */
10356 
10357 			/* Make sure VAAs are disabled */
10358 			gl.disableVertexAttribArray(variable.attribute_location + index);
10359 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10360 		} /* for (all array indices) */
10361 	}	 /* for (all variables) */
10362 }
10363 
10364 /** Constructor
10365  *
10366  *  @param context Rendering context.
10367  */
GPUShaderFP64Test8(deqp::Context & context)10368 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10369 	: TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10370 											  "are accepted during compilation stage")
10371 	, m_cs_id(0)
10372 	, m_fs_id(0)
10373 	, m_gs_id(0)
10374 	, m_tc_id(0)
10375 	, m_te_id(0)
10376 	, m_vs_id(0)
10377 	, m_has_test_passed(true)
10378 {
10379 }
10380 
10381 /** Deinitializes all buffers and GL objects that may have been generated
10382  *  during test execution.
10383  **/
deinit()10384 void GPUShaderFP64Test8::deinit()
10385 {
10386 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10387 
10388 	if (m_cs_id != 0)
10389 	{
10390 		gl.deleteShader(m_cs_id);
10391 
10392 		m_cs_id = 0;
10393 	}
10394 
10395 	if (m_fs_id != 0)
10396 	{
10397 		gl.deleteShader(m_fs_id);
10398 
10399 		m_fs_id = 0;
10400 	}
10401 
10402 	if (m_gs_id != 0)
10403 	{
10404 		gl.deleteShader(m_gs_id);
10405 
10406 		m_gs_id = 0;
10407 	}
10408 
10409 	if (m_tc_id != 0)
10410 	{
10411 		gl.deleteShader(m_tc_id);
10412 
10413 		m_tc_id = 0;
10414 	}
10415 
10416 	if (m_te_id != 0)
10417 	{
10418 		gl.deleteShader(m_te_id);
10419 
10420 		m_te_id = 0;
10421 	}
10422 
10423 	if (m_vs_id != 0)
10424 	{
10425 		gl.deleteShader(m_vs_id);
10426 
10427 		m_vs_id = 0;
10428 	}
10429 }
10430 
10431 /** Executes a single test case.
10432  *
10433  *  This function can throw TestError exceptions if GL implementation reports
10434  *  an error.
10435  *
10436  *  @param test_case Test case descriptor.
10437  *
10438  *  @return true if test case passed, false otherwise.
10439  **/
executeIteration(const _test_case & test_case)10440 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10441 {
10442 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
10443 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10444 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
10445 	bool				  result	 = true;
10446 	const char*			  stage_body = NULL;
10447 	const char*			  stage_name = NULL;
10448 
10449 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10450 	{
10451 		const glw::GLuint so_id = so_ids[n_so_id];
10452 
10453 		/* Skip compute shader if it is not supported */
10454 		if (0 == so_id)
10455 		{
10456 			continue;
10457 		}
10458 
10459 		/* Compile the shader */
10460 		gl.compileShader(so_id);
10461 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10462 
10463 		/* Has the compilation succeeded as expected? */
10464 		glw::GLint compile_status = GL_FALSE;
10465 
10466 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10467 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10468 
10469 		if (compile_status == GL_FALSE)
10470 		{
10471 			/* What is the current stage's name? */
10472 			if (so_id == m_cs_id)
10473 			{
10474 				stage_body = test_case.cs_shader_body.c_str();
10475 				stage_name = "Compute shader";
10476 			}
10477 			else if (so_id == m_fs_id)
10478 			{
10479 				stage_body = test_case.fs_shader_body.c_str();
10480 				stage_name = "Fragment shader";
10481 			}
10482 			else if (so_id == m_gs_id)
10483 			{
10484 				stage_body = test_case.gs_shader_body.c_str();
10485 				stage_name = "Geometry shader";
10486 			}
10487 			else if (so_id == m_tc_id)
10488 			{
10489 				stage_body = test_case.tc_shader_body.c_str();
10490 				stage_name = "Tessellation control shader";
10491 			}
10492 			else if (so_id == m_te_id)
10493 			{
10494 				stage_body = test_case.te_shader_body.c_str();
10495 				stage_name = "Tessellation evaluation shader";
10496 			}
10497 			else if (so_id == m_vs_id)
10498 			{
10499 				stage_body = test_case.vs_shader_body.c_str();
10500 				stage_name = "Vertex shader";
10501 			}
10502 			else
10503 			{
10504 				/* Doesn't make much sense to throw exceptions here so.. */
10505 				stage_body = "";
10506 				stage_name = "[?]";
10507 			}
10508 
10509 			/* This shader should have never failed to compile! */
10510 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10511 							   << " has not compiled successfully, even though the shader is valid."
10512 								  " Following is shader's body:\n"
10513 							   << stage_body << tcu::TestLog::EndMessage;
10514 
10515 			result = false;
10516 		}
10517 	} /* for (all shader objects) */
10518 
10519 	return result;
10520 }
10521 
10522 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10523  *  type.
10524  *
10525  *  @param variable_type Variable type to return valid argument lists for.
10526  **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10527 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10528 	const Utils::_variable_type& variable_type)
10529 {
10530 	const Utils::_variable_type matrix_types[] = {
10531 		Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10532 		Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10533 		Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10534 	};
10535 	const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10536 												   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10537 	const unsigned int n_matrix_types	 = sizeof(matrix_types) / sizeof(matrix_types[0]);
10538 	const unsigned int n_scalar_types	 = sizeof(scalar_types) / sizeof(scalar_types[0]);
10539 	const int		   n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10540 
10541 	/* Construct the argument list tree root. Each node carries a counter that tells how many components
10542 	 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10543 	 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10544 	 * used to define a subsequent argument, and its counter is increased by the amount of components
10545 	 * described by the type.
10546 	 */
10547 	_argument_list_tree_node root;
10548 
10549 	root.n_components_used = 0;
10550 	root.parent			   = NULL;
10551 	root.type			   = variable_type;
10552 
10553 	/* Fill till all leaves use up all available components */
10554 	_argument_list_tree_node_queue nodes_queue;
10555 
10556 	nodes_queue.push(&root);
10557 
10558 	do
10559 	{
10560 		/* Pop the first item in the queue */
10561 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10562 		nodes_queue.pop();
10563 
10564 		/* Matrix variable types can be defined by a combination of non-matrix variable types OR
10565 		 * a single matrix variable type.
10566 		 *
10567 		 * Let's handle the latter case first.
10568 		 */
10569 		const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10570 
10571 		if (Utils::isMatrixVariableType(current_node_ptr->type))
10572 		{
10573 			/* Iterate through all known matrix types. All the types can be used
10574 			 * as a constructor, assuming only one value is used to define new matrix's
10575 			 * contents. */
10576 			for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10577 			{
10578 				Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10579 
10580 				/* Construct a new child node. Since GLSL spec clearly states we must not use more
10581 				 * than one constructor argument if the only argument is a matrix type, mark the node
10582 				 * as if it defined all available components.
10583 				 */
10584 				_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10585 
10586 				new_subnode->n_components_used = n_total_components;
10587 				new_subnode->parent			   = current_node_ptr;
10588 				new_subnode->type			   = new_argument_type;
10589 
10590 				/* Add the descriptor to node list but do not add it to the queue. This would be
10591 				 * a redundant operation, since no new children nodes would have been assigned to
10592 				 * this node anyway.
10593 				 */
10594 				current_node_ptr->children.push_back(new_subnode);
10595 			} /* for (all matrix types) */
10596 		}	 /* if (current node's type is a matrix) */
10597 
10598 		/* Now for a combination of non-matrix variable types.. */
10599 		if (!Utils::isMatrixVariableType(current_node_ptr->type))
10600 		{
10601 			/* Iterate through all known scalar types */
10602 			for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10603 			{
10604 				Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10605 				const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10606 
10607 				/* Only use the scalar type if we don't exceed the amount of components we can define
10608 				 * for requested type.
10609 				 */
10610 				if (n_new_argument_components <= n_components_remaining)
10611 				{
10612 					/* Form new node descriptor */
10613 					_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10614 
10615 					new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10616 					new_subnode->parent			   = current_node_ptr;
10617 					new_subnode->type			   = new_argument_type;
10618 
10619 					current_node_ptr->children.push_back(new_subnode);
10620 					nodes_queue.push(new_subnode);
10621 				}
10622 			} /* for (all scalar types) */
10623 		}	 /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10624 	} while (nodes_queue.size() > 0);
10625 
10626 	/* To construct the argument lists, traverse the tree. Each path from root to child
10627 	 * gives us a single argument list.
10628 	 *
10629 	 * First, identify leaf nodes.
10630 	 */
10631 	_argument_list_tree_nodes leaf_nodes;
10632 
10633 	nodes_queue.push(&root);
10634 
10635 	do
10636 	{
10637 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
10638 		nodes_queue.pop();
10639 
10640 		if (current_node_ptr->children.size() == 0)
10641 		{
10642 			/* This is a leaf node !*/
10643 			leaf_nodes.push_back(current_node_ptr);
10644 		}
10645 		else
10646 		{
10647 			/* Throw all children nodes to the queue */
10648 			const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10649 
10650 			for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10651 			{
10652 				nodes_queue.push(current_node_ptr->children[n_children_node]);
10653 			} /* for (all children nodes) */
10654 		}
10655 	} while (nodes_queue.size() > 0);
10656 
10657 	/* For all leaf nodes, move up the tree and construct the argument lists. */
10658 	const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10659 	_argument_lists	result;
10660 
10661 	for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10662 	{
10663 		_argument_list			  argument_list;
10664 		_argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10665 
10666 		do
10667 		{
10668 			if (current_node_ptr != &root)
10669 			{
10670 				if (argument_list.size() == 0)
10671 				{
10672 					argument_list.push_back(current_node_ptr->type);
10673 				}
10674 				else
10675 				{
10676 					argument_list.insert(argument_list.begin(), current_node_ptr->type);
10677 				}
10678 			}
10679 
10680 			current_node_ptr = current_node_ptr->parent;
10681 		} while (current_node_ptr != NULL);
10682 
10683 		result.push_back(argument_list);
10684 	} /* for (all leaf nodes) */
10685 
10686 	return result;
10687 }
10688 
10689 /** Retrieves body of a compute shader that should be used for the purpose of
10690  *  user-specified test case.
10691  *
10692  *  @param test_case Test case descriptor to use.
10693  *
10694  *  @return Requested string.
10695  **/
getComputeShaderBody(const _test_case & test_case)10696 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10697 {
10698 	std::stringstream result_sstream;
10699 
10700 	/* Form the body */
10701 	result_sstream << "#version 420\n"
10702 					  "#extension GL_ARB_compute_shader          : require\n"
10703 					  "\n"
10704 					  "layout(local_size_x = 1) in;\n"
10705 					  "\n"
10706 					  "void main()\n"
10707 					  "{\n"
10708 				   << getGeneralBody(test_case) << "}\n";
10709 
10710 	/* Return the body */
10711 	return result_sstream.str();
10712 }
10713 
10714 /** Retrieves body of a fragment shader that should be used for the purpose of
10715  *  user-specified test case.
10716  *
10717  *  @param test_case Test case descriptor to use.
10718  *
10719  *  @return Requested string.
10720  **/
getFragmentShaderBody(const _test_case & test_case)10721 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10722 {
10723 	std::stringstream result_sstream;
10724 
10725 	/* Form the body */
10726 	result_sstream << "#version 420\n"
10727 					  "\n"
10728 					  "void main()\n"
10729 					  "{\n"
10730 				   << getGeneralBody(test_case) << "}\n"
10731 												   "\n";
10732 
10733 	/* Return the body */
10734 	return result_sstream.str();
10735 }
10736 
10737 /** Returns a GLSL line that defines and initializes a variable as described by
10738  *  user-specified test case descriptor.
10739  *
10740  *  @param test_case Test case descriptor to use for the query.
10741  *
10742  *  @return As per description
10743  **/
getGeneralBody(const _test_case & test_case)10744 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10745 {
10746 	std::stringstream result_sstream;
10747 
10748 	/* Form the body */
10749 	std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10750 
10751 	result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10752 
10753 	for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10754 		 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10755 	{
10756 		const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10757 		std::string		   argument_variable_type_string   = Utils::getVariableTypeString(argument_variable_type);
10758 		const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10759 
10760 		if (argument_list_iterator != test_case.argument_list.begin())
10761 		{
10762 			result_sstream << ", ";
10763 		}
10764 
10765 		result_sstream << argument_variable_type_string << "(";
10766 
10767 		for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10768 		{
10769 			result_sstream << (double)(n_component + 1);
10770 
10771 			if (n_component != (argument_n_components - 1))
10772 			{
10773 				result_sstream << ", ";
10774 			}
10775 		} /* for (all argument components) */
10776 
10777 		result_sstream << ")";
10778 	} /* for (all arguments) */
10779 
10780 	result_sstream << ");\n";
10781 
10782 	return result_sstream.str();
10783 }
10784 
10785 /** Retrieves body of a geometry shader that should be used for the purpose of
10786  *  user-specified test case.
10787  *
10788  *  @param test_case Test case descriptor to use.
10789  *
10790  *  @return Requested string.
10791  **/
getGeometryShaderBody(const _test_case & test_case)10792 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10793 {
10794 	std::stringstream result_sstream;
10795 
10796 	/* Form the body */
10797 	result_sstream << "#version 420\n"
10798 					  "\n"
10799 					  "layout(points)                 in;\n"
10800 					  "layout(max_vertices=1, points) out;\n"
10801 					  "\n"
10802 					  "void main()\n"
10803 					  "{\n"
10804 				   << getGeneralBody(test_case) << "}\n"
10805 												   "\n";
10806 
10807 	/* We're done! */
10808 	return result_sstream.str();
10809 }
10810 
10811 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10812  *  user-specified test case.
10813  *
10814  *  @param test_case Test case descriptor to use.
10815  *
10816  *  @return Requested string.
10817  **/
getTessellationControlShaderBody(const _test_case & test_case)10818 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10819 {
10820 	std::stringstream result_sstream;
10821 
10822 	/* Form the body */
10823 	result_sstream << "#version 420\n"
10824 					  "\n"
10825 					  "layout(vertices=4) out;\n"
10826 					  "\n"
10827 					  "void main()\n"
10828 					  "{\n"
10829 				   << getGeneralBody(test_case) << "}\n"
10830 												   "\n";
10831 
10832 	/* Return the body */
10833 	return result_sstream.str();
10834 }
10835 
10836 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10837  *  user-specified test case.
10838  *
10839  *  @param test_case Test case descriptor to use.
10840  *
10841  *  @return Requested string.
10842  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10843 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10844 {
10845 	std::stringstream result_sstream;
10846 
10847 	/* Form the body */
10848 	result_sstream << "#version 420\n"
10849 					  "\n"
10850 					  "layout(isolines) in;\n"
10851 					  "\n"
10852 					  "void main()\n"
10853 					  "{\n"
10854 				   << getGeneralBody(test_case) << "}\n"
10855 												   "\n";
10856 
10857 	/* Return the body */
10858 	return result_sstream.str();
10859 }
10860 
10861 /** Retrieves body of a vertex shader that should be used for the purpose of
10862  *  user-specified test case.
10863  *
10864  *  @param test_case Test case descriptor to use.
10865  *
10866  *  @return Requested string.
10867  **/
getVertexShaderBody(const _test_case & test_case)10868 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10869 {
10870 	std::stringstream result_sstream;
10871 
10872 	/* Form the body */
10873 	result_sstream << "#version 420\n"
10874 					  "\n"
10875 					  "void main()\n"
10876 					  "{\n"
10877 				   << getGeneralBody(test_case) << "}\n"
10878 												   "\n";
10879 
10880 	return result_sstream.str();
10881 }
10882 
10883 /** Initializes shader objects required to run the test. */
initTest()10884 void GPUShaderFP64Test8::initTest()
10885 {
10886 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10887 
10888 	/* Generate shader objects */
10889 
10890 	/* Compute shader support and GL 4.2 required */
10891 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10892 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10893 	{
10894 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10895 	}
10896 
10897 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10898 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10899 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10900 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10901 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10902 
10903 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10904 }
10905 
10906 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10907  *
10908  *  @param test_case Test case descriptor to generate the shader bodies for.
10909  **/
initIteration(_test_case & test_case)10910 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10911 {
10912 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10913 
10914 	test_case.cs_shader_body = getComputeShaderBody(test_case);
10915 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
10916 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
10917 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10918 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10919 	test_case.vs_shader_body = getVertexShaderBody(test_case);
10920 
10921 	/* Assign the bodies to relevant shaders */
10922 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10923 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10924 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10925 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10926 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10927 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10928 
10929 	/* m_cs_id is initialized only if compute_shader is supported */
10930 	if (0 != m_cs_id)
10931 	{
10932 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10933 	}
10934 
10935 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10936 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10937 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10938 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10939 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10940 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10941 }
10942 
10943 /** Executes test iteration.
10944  *
10945  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10946  */
iterate()10947 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10948 {
10949 	/* Do not execute the test if GL_ARB_texture_view is not supported */
10950 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10951 	{
10952 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10953 	}
10954 
10955 	/* Initialize GL objects needed to run the tests */
10956 	initTest();
10957 
10958 	/* Build iteration array to run the tests in an automated manner */
10959 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
10960 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10961 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10962 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
10963 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10964 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
10965 													 Utils::VARIABLE_TYPE_DVEC4 };
10966 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10967 
10968 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10969 	{
10970 		const Utils::_variable_type variable_type = variable_types[n_variable_type];
10971 
10972 		/* Construct a set of argument lists valid for the variable type considered */
10973 		_argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10974 
10975 		for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10976 			 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10977 		{
10978 			/* Constructor thwe test case descriptor */
10979 			_test_case test_case;
10980 
10981 			test_case.argument_list = *argument_list_iterator;
10982 			test_case.type			= variable_type;
10983 
10984 			/* Initialize a program object we will use to perform the casting */
10985 			initIteration(test_case);
10986 
10987 			/* See if the shader compiles. */
10988 			m_has_test_passed &= executeIteration(test_case);
10989 		} /* for (all argument lists) */
10990 	}	 /* for (all variable types) */
10991 
10992 	/* We're done */
10993 	if (m_has_test_passed)
10994 	{
10995 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10996 	}
10997 	else
10998 	{
10999 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11000 	}
11001 
11002 	return STOP;
11003 }
11004 
11005 /** Constructor.
11006  *
11007  *  @param context Rendering context.
11008  *
11009  **/
GPUShaderFP64Test9(deqp::Context & context)11010 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11011 	: TestCase(context, "operators", "Verifies that general and relational operators work "
11012 									 "correctly when used against double-precision floating-"
11013 									 "point types.")
11014 	, m_has_test_passed(true)
11015 	, m_po_id(0)
11016 	, m_xfb_bo_id(0)
11017 	, m_vao_id(0)
11018 	, m_vs_id(0)
11019 {
11020 	/* Left blank intentionally */
11021 }
11022 
11023 /** Deinitializes all ES objects that may have been created during
11024  *  test execution.
11025  **/
deinit()11026 void GPUShaderFP64Test9::deinit()
11027 {
11028 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11029 
11030 	if (m_po_id != 0)
11031 	{
11032 		gl.deleteProgram(m_po_id);
11033 
11034 		m_po_id = 0;
11035 	}
11036 
11037 	if (m_xfb_bo_id != 0)
11038 	{
11039 		gl.deleteBuffers(1, &m_xfb_bo_id);
11040 
11041 		m_xfb_bo_id = 0;
11042 	}
11043 
11044 	if (m_vao_id != 0)
11045 	{
11046 		gl.deleteVertexArrays(1, &m_vao_id);
11047 
11048 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11049 	}
11050 
11051 	if (m_vs_id != 0)
11052 	{
11053 		gl.deleteShader(m_vs_id);
11054 
11055 		m_vs_id = 0;
11056 	}
11057 }
11058 
11059 /** Executes a single test iteration using user-specified test case properties.
11060  *
11061  *  @param test_case Test case descriptor.
11062  *
11063  *  @return true if the pass was successful, false if the test should fail.
11064  **/
executeTestIteration(const _test_case & test_case)11065 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11066 {
11067 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
11068 	bool				  result = true;
11069 
11070 	/* Activate the test program object */
11071 	gl.useProgram(m_po_id);
11072 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11073 
11074 	/* Draw a single point with XFB enabled */
11075 	gl.beginTransformFeedback(GL_POINTS);
11076 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11077 	{
11078 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11079 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11080 	}
11081 	gl.endTransformFeedback();
11082 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11083 
11084 	/* Map the XFB BO into process space */
11085 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11086 
11087 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11088 
11089 	result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11090 
11091 	/* Unmap the BO */
11092 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11093 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11094 
11095 	return result;
11096 }
11097 
11098 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11099  *  under user-specified location.
11100  *
11101  *  @param matrix_a_type  Type of the l-side matrix.
11102  *  @param matrix_a_data  Row-ordered data of l-side matrix.
11103  *  @param matrix_b_type  Type of the r-side matrix.
11104  *  @param matrix_b_data  Row-ordered data of r-side matrix.
11105  *  @param out_result_ptr Deref to be used to store the multiplication result.
11106  **/
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)11107 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11108 													   const std::vector<double>&   matrix_a_data,
11109 													   const Utils::_variable_type& matrix_b_type,
11110 													   const std::vector<double>& matrix_b_data, double* out_result_ptr)
11111 {
11112 	(void)matrix_b_type;
11113 	using namespace tcu;
11114 	/* To keep the code maintainable, we only consider cases relevant for this test */
11115 	switch (matrix_a_type)
11116 	{
11117 	case Utils::VARIABLE_TYPE_DMAT2:
11118 	{
11119 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11120 
11121 		tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11122 		tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11123 		tcu::Matrix2d result;
11124 
11125 		matrix_a = transpose(matrix_a);
11126 		matrix_b = transpose(matrix_b);
11127 		result   = matrix_a * matrix_b;
11128 
11129 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11130 		break;
11131 	}
11132 
11133 	case Utils::VARIABLE_TYPE_DMAT2X3:
11134 	{
11135 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11136 
11137 		tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11138 		tcu::Matrix<double, 3, 2> matrix_a_transposed;
11139 		tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11140 		tcu::Matrix<double, 2, 3> matrix_b_transposed;
11141 		tcu::Matrix<double, 3, 3> result;
11142 
11143 		matrix_a_transposed = transpose(matrix_a);
11144 		matrix_b_transposed = transpose(matrix_b);
11145 		result				= matrix_a_transposed * matrix_b_transposed;
11146 
11147 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11148 		break;
11149 	}
11150 
11151 	case Utils::VARIABLE_TYPE_DMAT2X4:
11152 	{
11153 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11154 
11155 		tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11156 		tcu::Matrix<double, 4, 2> matrix_a_transposed;
11157 		tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11158 		tcu::Matrix<double, 2, 4> matrix_b_transposed;
11159 		tcu::Matrix<double, 4, 4> result;
11160 
11161 		matrix_a_transposed = transpose(matrix_a);
11162 		matrix_b_transposed = transpose(matrix_b);
11163 		result				= matrix_a_transposed * matrix_b_transposed;
11164 
11165 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11166 		break;
11167 	}
11168 
11169 	case Utils::VARIABLE_TYPE_DMAT3:
11170 	{
11171 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11172 
11173 		tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11174 		tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11175 		tcu::Matrix<double, 3, 3> result;
11176 
11177 		matrix_a = transpose(matrix_a);
11178 		matrix_b = transpose(matrix_b);
11179 		result   = matrix_a * matrix_b;
11180 
11181 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11182 		break;
11183 	}
11184 
11185 	case Utils::VARIABLE_TYPE_DMAT3X2:
11186 	{
11187 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11188 
11189 		tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11190 		tcu::Matrix<double, 2, 3> matrix_a_transposed;
11191 		tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11192 		tcu::Matrix<double, 3, 2> matrix_b_transposed;
11193 		tcu::Matrix<double, 2, 2> result;
11194 
11195 		matrix_a_transposed = transpose(matrix_a);
11196 		matrix_b_transposed = transpose(matrix_b);
11197 		result				= matrix_a_transposed * matrix_b_transposed;
11198 
11199 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11200 		break;
11201 	}
11202 
11203 	case Utils::VARIABLE_TYPE_DMAT3X4:
11204 	{
11205 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11206 
11207 		tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11208 		tcu::Matrix<double, 4, 3> matrix_a_transposed;
11209 		tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11210 		tcu::Matrix<double, 3, 4> matrix_b_transposed;
11211 		tcu::Matrix<double, 4, 4> result;
11212 
11213 		matrix_a_transposed = transpose(matrix_a);
11214 		matrix_b_transposed = transpose(matrix_b);
11215 		result				= matrix_a_transposed * matrix_b_transposed;
11216 
11217 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11218 		break;
11219 	}
11220 
11221 	case Utils::VARIABLE_TYPE_DMAT4:
11222 	{
11223 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11224 
11225 		tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11226 		tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11227 		tcu::Matrix<double, 4, 4> result;
11228 
11229 		matrix_a = transpose(matrix_a);
11230 		matrix_b = transpose(matrix_b);
11231 		result   = matrix_a * matrix_b;
11232 
11233 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11234 		break;
11235 	}
11236 
11237 	case Utils::VARIABLE_TYPE_DMAT4X2:
11238 	{
11239 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11240 
11241 		tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11242 		tcu::Matrix<double, 2, 4> matrix_a_transposed;
11243 		tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11244 		tcu::Matrix<double, 4, 2> matrix_b_transposed;
11245 		tcu::Matrix<double, 2, 2> result;
11246 
11247 		matrix_a_transposed = transpose(matrix_a);
11248 		matrix_b_transposed = transpose(matrix_b);
11249 		result				= matrix_a_transposed * matrix_b_transposed;
11250 
11251 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11252 		break;
11253 	}
11254 
11255 	case Utils::VARIABLE_TYPE_DMAT4X3:
11256 	{
11257 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11258 
11259 		tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11260 		tcu::Matrix<double, 3, 4> matrix_a_transposed;
11261 		tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11262 		tcu::Matrix<double, 4, 3> matrix_b_transposed;
11263 		tcu::Matrix<double, 3, 3> result;
11264 
11265 		matrix_a_transposed = transpose(matrix_a);
11266 		matrix_b_transposed = transpose(matrix_b);
11267 		result				= matrix_a_transposed * matrix_b_transposed;
11268 
11269 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11270 		break;
11271 	}
11272 
11273 	default:
11274 	{
11275 		TCU_FAIL("Unrecognized matrix A type");
11276 	}
11277 	} /* switch (matrix_a_type) */
11278 }
11279 
11280 /** Returns GLSL operator representation of the user-specified operation.
11281  *
11282  *  @param operation_type Internal operation type to retrieve the operator for.
11283  *
11284  *  @return As per description.
11285  **/
getOperatorForOperationType(const _operation_type & operation_type)11286 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11287 {
11288 	const char* result = NULL;
11289 
11290 	switch (operation_type)
11291 	{
11292 	case OPERATION_TYPE_ADDITION:
11293 		result = "+";
11294 		break;
11295 	case OPERATION_TYPE_DIVISION:
11296 		result = "/";
11297 		break;
11298 	case OPERATION_TYPE_MULTIPLICATION:
11299 		result = "*";
11300 		break;
11301 	case OPERATION_TYPE_SUBTRACTION:
11302 		result = "-";
11303 		break;
11304 
11305 	case OPERATION_TYPE_PRE_DECREMENTATION:
11306 	case OPERATION_TYPE_POST_DECREMENTATION:
11307 	{
11308 		result = "--";
11309 
11310 		break;
11311 	}
11312 
11313 	case OPERATION_TYPE_PRE_INCREMENTATION:
11314 	case OPERATION_TYPE_POST_INCREMENTATION:
11315 	{
11316 		result = "++";
11317 
11318 		break;
11319 	}
11320 
11321 	default:
11322 	{
11323 		TCU_FAIL("Unrecognized operation type");
11324 	}
11325 	} /* switch(operation_type) */
11326 
11327 	return result;
11328 }
11329 
11330 /** Returns a string representing user-specified operation type.
11331  *
11332  *  @param operation_type Operation type to return the literal for.
11333  *
11334  *  @return Requested string.
11335  **/
getOperationTypeString(const _operation_type & operation_type)11336 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11337 {
11338 	std::string result = "[?]";
11339 
11340 	switch (operation_type)
11341 	{
11342 	case OPERATION_TYPE_ADDITION:
11343 		result = "addition";
11344 		break;
11345 	case OPERATION_TYPE_DIVISION:
11346 		result = "division";
11347 		break;
11348 	case OPERATION_TYPE_MULTIPLICATION:
11349 		result = "multiplication";
11350 		break;
11351 	case OPERATION_TYPE_SUBTRACTION:
11352 		result = "subtraction";
11353 		break;
11354 	case OPERATION_TYPE_PRE_DECREMENTATION:
11355 		result = "pre-decrementation";
11356 		break;
11357 	case OPERATION_TYPE_PRE_INCREMENTATION:
11358 		result = "pre-incrementation";
11359 		break;
11360 	case OPERATION_TYPE_POST_DECREMENTATION:
11361 		result = "post-decrementation";
11362 		break;
11363 	case OPERATION_TYPE_POST_INCREMENTATION:
11364 		result = "post-incrementation";
11365 		break;
11366 
11367 	default:
11368 	{
11369 		TCU_FAIL("Unrecognized operation type");
11370 	}
11371 	}
11372 
11373 	return result;
11374 }
11375 
11376 /** Returns body of a vertex shader that should be used for user-specified test case
11377  *  descriptor.
11378  *
11379  *  @param test_case Test case descriptor.
11380  *
11381  *  @return Requested GLSL shader body.
11382  **/
getVertexShaderBody(_test_case & test_case)11383 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11384 {
11385 	std::stringstream  result_sstream;
11386 	std::string		   result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11387 	std::string		   variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11388 	std::string		   variable_type_string	= Utils::getVariableTypeString(test_case.variable_type);
11389 	const unsigned int n_variable_components   = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11390 
11391 	/* If we are to multiply matrices, we will need to use a different type
11392 	 * for the result variable if either of the matrices is not square.
11393 	 */
11394 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11395 		Utils::isMatrixVariableType(test_case.variable_type))
11396 	{
11397 		Utils::_variable_type result_variable_type;
11398 		Utils::_variable_type transposed_matrix_variable_type =
11399 			Utils::getTransposedMatrixVariableType(test_case.variable_type);
11400 
11401 		result_variable_type =
11402 			Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11403 		result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11404 
11405 		test_case.result_variable_type = result_variable_type;
11406 	}
11407 
11408 	/* Form the pre-amble */
11409 	result_sstream << "#version 400\n"
11410 					  "\n"
11411 
11412 					  /* Add output variables */
11413 					  "out "
11414 				   << result_variable_type_string << " result;\n"
11415 													 "out ivec2 result_lt;\n"
11416 													 "out ivec2 result_lte;\n"
11417 													 "out ivec2 result_gt;\n"
11418 													 "out ivec2 result_gte;\n"
11419 													 "void main()\n"
11420 													 "{\n";
11421 
11422 	/* Form reference values */
11423 	result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11424 
11425 	for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11426 	{
11427 		result_sstream << (n_variable_component + 1);
11428 
11429 		if (n_variable_component != (n_variable_components - 1))
11430 		{
11431 			result_sstream << ", ";
11432 		}
11433 	} /* for (all variable components) */
11434 
11435 	result_sstream << ");\n";
11436 
11437 	for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11438 		 ++n_ref2_case)
11439 	{
11440 		Utils::_variable_type compatible_variable_type = test_case.variable_type;
11441 
11442 		if (Utils::isMatrixVariableType(compatible_variable_type) &&
11443 			test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11444 		{
11445 			compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11446 		}
11447 
11448 		std::string ref2_variable_type_fp_string =
11449 			Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11450 		std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11451 		std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11452 		std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11453 
11454 		result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11455 
11456 		for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11457 			 ++n_variable_component)
11458 		{
11459 			result_sstream << (n_variable_components - (n_variable_component + 1));
11460 
11461 			if (n_variable_component != (n_variable_components - 1))
11462 			{
11463 				result_sstream << ", ";
11464 			}
11465 		} /* for (all variable components) */
11466 
11467 		result_sstream << ");\n";
11468 	} /* for (both reference2 declarations) */
11469 
11470 	/* Add actual body */
11471 	result_sstream << "\n"
11472 					  "result = ";
11473 
11474 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11475 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11476 	{
11477 		result_sstream << getOperatorForOperationType(test_case.operation_type);
11478 	}
11479 
11480 	result_sstream << "reference1 ";
11481 
11482 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11483 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11484 		test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11485 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11486 	{
11487 		if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11488 			test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11489 		{
11490 			result_sstream << getOperatorForOperationType(test_case.operation_type);
11491 		}
11492 	}
11493 	else
11494 	{
11495 		result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11496 	}
11497 
11498 	result_sstream << ";\n";
11499 
11500 	if (Utils::isScalarVariableType(test_case.variable_type))
11501 	{
11502 		result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
11503 						  "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
11504 						  "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
11505 						  "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11506 						  "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
11507 						  "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
11508 						  "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
11509 						  "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11510 	}
11511 	else
11512 	{
11513 		result_sstream << "result_lt [0] = 1;\n"
11514 						  "result_lt [1] = 1;\n"
11515 						  "result_lte[0] = 1;\n"
11516 						  "result_lte[1] = 1;\n"
11517 						  "result_gt [0] = 1;\n"
11518 						  "result_gt [1] = 1;\n"
11519 						  "result_gte[0] = 1;\n"
11520 						  "result_gte[1] = 1;\n";
11521 	}
11522 
11523 	result_sstream << "}\n";
11524 
11525 	/* All done */
11526 	return result_sstream.str();
11527 }
11528 
11529 /** Initializes all GL objects required to run the test.
11530  *
11531  *  This function can throw a TestError exception if the implementation misbehaves.
11532  */
initTest()11533 void GPUShaderFP64Test9::initTest()
11534 {
11535 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11536 
11537 	/* Create program & vertex shader objects */
11538 	m_po_id = gl.createProgram();
11539 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11540 
11541 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11542 
11543 	/* Attach the shader to the program */
11544 	gl.attachShader(m_po_id, m_vs_id);
11545 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11546 
11547 	/* Set up a buffer object */
11548 	gl.genBuffers(1, &m_xfb_bo_id);
11549 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11550 
11551 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11552 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11553 
11554 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11555 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11556 
11557 	/* Set up a vertex array object */
11558 	gl.genVertexArrays(1, &m_vao_id);
11559 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11560 
11561 	gl.bindVertexArray(m_vao_id);
11562 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11563 }
11564 
11565 /** Initializes all GL objects required to run an iteration described by
11566  *  user-specified test case descriptor.
11567  *
11568  *  @param test_case Test case descriptor to use for the initialization.
11569  **/
initTestIteration(_test_case & test_case)11570 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11571 {
11572 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
11573 	std::string			  vs_body		  = getVertexShaderBody(test_case);
11574 	const char*			  vs_body_raw_ptr = vs_body.c_str();
11575 
11576 	/* Store the shader's body */
11577 	test_case.vs_body = vs_body;
11578 
11579 	/* Try to compile the shader */
11580 	glw::GLint compile_status = GL_FALSE;
11581 
11582 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11583 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11584 
11585 	gl.compileShader(m_vs_id);
11586 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11587 
11588 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11589 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11590 
11591 	if (compile_status != GL_TRUE)
11592 	{
11593 		TCU_FAIL("Test shader compilation failed.");
11594 	}
11595 
11596 	/* Configure XFB */
11597 	const char*		   xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11598 	const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11599 
11600 	gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11601 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11602 
11603 	/* Try to link the program */
11604 	glw::GLint link_status = GL_FALSE;
11605 
11606 	gl.linkProgram(m_po_id);
11607 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11608 
11609 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11610 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11611 
11612 	if (link_status != GL_TRUE)
11613 	{
11614 		TCU_FAIL("Test program linking failure");
11615 	}
11616 
11617 	/* Set up XFB BO data storage */
11618 	const unsigned int result_variable_size = static_cast<unsigned int>(
11619 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11620 	const unsigned int xfb_bo_size = static_cast<unsigned int>(
11621 		result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11622 
11623 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11624 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11625 }
11626 
11627 /** Executes test iteration.
11628  *
11629  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11630  */
iterate()11631 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11632 {
11633 	/* Do not execute the test if GL_ARB_texture_view is not supported */
11634 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11635 	{
11636 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11637 	}
11638 
11639 	/* Initialize all ES objects required to run all the checks */
11640 	initTest();
11641 
11642 	/* Iterate through all variable types we want to test */
11643 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
11644 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11645 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11646 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
11647 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11648 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11649 													 Utils::VARIABLE_TYPE_DVEC4 };
11650 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11651 
11652 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11653 	{
11654 		/* Iterate through all operation types we want to check */
11655 		for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11656 		{
11657 			_operation_type				 operation_type = (_operation_type)n_operation_type;
11658 			const Utils::_variable_type& variable_type  = variable_types[n_variable_type];
11659 
11660 			/* Construct test case descriptor */
11661 			_test_case test_case;
11662 
11663 			test_case.operation_type	   = operation_type;
11664 			test_case.result_variable_type = variable_type;
11665 			test_case.variable_type		   = variable_type;
11666 
11667 			/* Run the iteration */
11668 			initTestIteration(test_case);
11669 
11670 			m_has_test_passed &= executeTestIteration(test_case);
11671 		} /* for (all operation types) */
11672 	}	 /* for (all variable types) */
11673 
11674 	/* All done. */
11675 	if (m_has_test_passed)
11676 	{
11677 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11678 	}
11679 	else
11680 	{
11681 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11682 	}
11683 
11684 	return STOP;
11685 }
11686 
11687 /** Verifies data XFBed out by the draw call for user-specified test case
11688  *  descriptor.
11689  *
11690  *  @param test_case Test case descriptor
11691  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
11692  *                   Must not be NULL.
11693  *
11694  *  @return true if the data was found to be correct, false otherwise.
11695  **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11696 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11697 {
11698 	const double	   epsilon = 1e-5;
11699 	const unsigned int n_result_components =
11700 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11701 	bool		  result			  = true;
11702 	const double* xfb_data_result	 = (const double*)xfb_data;
11703 	const int*	xfb_data_result_lt  = (const int*)(xfb_data_result + n_result_components);
11704 	const int*	xfb_data_result_lte = (const int*)xfb_data_result_lt + 2;  /* cast/non-cast cases */
11705 	const int*	xfb_data_result_gt  = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11706 	const int*	xfb_data_result_gte = (const int*)xfb_data_result_gt + 2;  /* cast/non-cast cases */
11707 
11708 	/* Prepare reference values */
11709 	int					modifier;
11710 	std::vector<double> reference1;
11711 	std::vector<double> reference2;
11712 
11713 	if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11714 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11715 	{
11716 		modifier = 1;
11717 	}
11718 	else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11719 			 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11720 	{
11721 		modifier = -1;
11722 	}
11723 	else
11724 	{
11725 		modifier = 0;
11726 	}
11727 
11728 	if (Utils::isMatrixVariableType(test_case.variable_type))
11729 	{
11730 		/* Matrices may be of different sizes so we need to compute the
11731 		 * reference values separately for each matrix
11732 		 */
11733 		const Utils::_variable_type matrix_a_type = test_case.variable_type;
11734 		const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11735 		const unsigned int			n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11736 		const unsigned int			n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11737 
11738 		for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11739 		{
11740 			reference1.push_back(modifier + n_component + 1);
11741 		}
11742 
11743 		for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11744 		{
11745 			reference2.push_back(n_matrix_b_components - (n_component + 1));
11746 		}
11747 	} /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11748 	else
11749 	{
11750 		/* Generate as many components as will be expected for the result variable */
11751 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11752 		{
11753 			reference1.push_back(modifier + n_result_component + 1);
11754 			reference2.push_back(n_result_components - (n_result_component + 1));
11755 		}
11756 	}
11757 
11758 	/* Verify the result value(s) */
11759 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11760 		Utils::isMatrixVariableType(test_case.variable_type))
11761 	{
11762 		/* Matrix multiplication */
11763 		double				  expected_result_data[4 * 4];
11764 		Utils::_variable_type matrix_a_type = test_case.variable_type;
11765 		Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11766 
11767 		getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11768 
11769 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11770 		{
11771 			if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11772 			{
11773 				std::stringstream log_sstream;
11774 
11775 				log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11776 							<< Utils::getVariableTypeString(matrix_b_type)
11777 							<< " matrix multiplication was incorrect; expected:(";
11778 
11779 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11780 					 ++n_logged_component)
11781 				{
11782 					log_sstream << expected_result_data[n_logged_component];
11783 
11784 					if (n_logged_component != (n_result_components - 1))
11785 					{
11786 						log_sstream << ", ";
11787 					}
11788 				} /* for (all components to be logged) */
11789 
11790 				log_sstream << "), retrieved:(";
11791 
11792 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11793 					 ++n_logged_component)
11794 				{
11795 					log_sstream << xfb_data_result[n_logged_component];
11796 
11797 					if (n_logged_component != (n_result_components - 1))
11798 					{
11799 						log_sstream << ", ";
11800 					}
11801 				} /* for (all components to be logged) */
11802 
11803 				log_sstream << ")";
11804 
11805 				m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11806 
11807 				result = false;
11808 				break;
11809 			}
11810 		} /* for (all result components) */
11811 	}	 /* if (dealing with matrix multiplication) */
11812 	else
11813 	{
11814 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11815 		{
11816 			double expected_value = reference1[n_component];
11817 
11818 			switch (test_case.operation_type)
11819 			{
11820 			case OPERATION_TYPE_ADDITION:
11821 				expected_value += reference2[n_component];
11822 				break;
11823 			case OPERATION_TYPE_DIVISION:
11824 				expected_value /= reference2[n_component];
11825 				break;
11826 			case OPERATION_TYPE_MULTIPLICATION:
11827 				expected_value *= reference2[n_component];
11828 				break;
11829 			case OPERATION_TYPE_SUBTRACTION:
11830 				expected_value -= reference2[n_component];
11831 				break;
11832 
11833 			case OPERATION_TYPE_PRE_DECREMENTATION:
11834 			case OPERATION_TYPE_PRE_INCREMENTATION:
11835 			{
11836 				/* Modifier already applied */
11837 				break;
11838 			}
11839 
11840 			case OPERATION_TYPE_POST_DECREMENTATION:
11841 			case OPERATION_TYPE_POST_INCREMENTATION:
11842 			{
11843 				/* Need to reverse the modification for the purpose of the following check */
11844 				expected_value -= modifier;
11845 
11846 				break;
11847 			}
11848 
11849 			default:
11850 			{
11851 				TCU_FAIL("Unrecognized operation type");
11852 			}
11853 			} /* switch (test_case.operation_type) */
11854 
11855 			if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11856 			{
11857 				std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11858 				std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11859 
11860 				m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11861 								   << variable_type_string << "]"
11862 															  " and operation type ["
11863 								   << operation_type_string << "]"
11864 															   " were found invalid."
11865 								   << tcu::TestLog::EndMessage;
11866 
11867 				result = false;
11868 				break;
11869 			} /* if (test case failed) */
11870 		}	 /* for (all components) */
11871 	}
11872 
11873 	/* Verify the comparison operation results */
11874 	if (Utils::isScalarVariableType(test_case.variable_type))
11875 	{
11876 		DE_ASSERT(n_result_components == 1);
11877 
11878 		const bool expected_result_lt[2]  = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11879 		const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11880 		const bool expected_result_gt[2]  = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11881 		const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11882 
11883 		if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11884 			(xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11885 		{
11886 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11887 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11888 
11889 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11890 														   "variable type ["
11891 							   << variable_type_string << "]"
11892 														  "and operation type ["
11893 							   << operation_type_string << "]"
11894 														   "was found invalid; expected:("
11895 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11896 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11897 							   << tcu::TestLog::EndMessage;
11898 
11899 			result = false;
11900 		}
11901 
11902 		if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11903 			(xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11904 		{
11905 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11906 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11907 
11908 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11909 														   "variable type ["
11910 							   << variable_type_string << "]"
11911 														  "and operation type ["
11912 							   << operation_type_string << "]"
11913 														   "was found invalid; expected:("
11914 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11915 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11916 							   << tcu::TestLog::EndMessage;
11917 
11918 			result = false;
11919 		}
11920 
11921 		if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11922 			(xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11923 		{
11924 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11925 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11926 
11927 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11928 														   "variable type ["
11929 							   << variable_type_string << "]"
11930 														  "and operation type ["
11931 							   << operation_type_string << "]"
11932 														   "was found invalid; expected:("
11933 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11934 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11935 							   << tcu::TestLog::EndMessage;
11936 
11937 			result = false;
11938 		}
11939 
11940 		if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11941 			(xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11942 		{
11943 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11944 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11945 
11946 			m_testCtx.getLog() << tcu::TestLog::Message
11947 							   << "Values reported for greater-than-or-equal operator used for "
11948 								  "variable type ["
11949 							   << variable_type_string << "]"
11950 														  "and operation type ["
11951 							   << operation_type_string << "]"
11952 														   "was found invalid; expected:("
11953 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11954 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11955 							   << tcu::TestLog::EndMessage;
11956 
11957 			result = false;
11958 		}
11959 	} /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11960 	else
11961 	{
11962 		if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11963 			xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11964 			xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11965 		{
11966 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11967 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11968 
11969 			m_testCtx.getLog() << tcu::TestLog::Message
11970 							   << "Invalid value was reported for matrix variable type, for which "
11971 								  " operator checks are not executed; variable type ["
11972 							   << variable_type_string << "]"
11973 														  "and operation type ["
11974 							   << operation_type_string << "]" << tcu::TestLog::EndMessage;
11975 
11976 			result = false;
11977 		}
11978 	}
11979 
11980 	return result;
11981 }
11982 
11983 namespace TypeHelpers
11984 {
11985 /** Get base type for reference types
11986  *
11987  * @tparam T type
11988  **/
11989 template <typename T>
11990 class referenceToType
11991 {
11992 public:
11993 	typedef T result;
11994 };
11995 
11996 template <typename T>
11997 class referenceToType<const T&>
11998 {
11999 public:
12000 	typedef T result;
12001 };
12002 
12003 /** Maps variable type with enumeration Utils::_variable_type
12004  *
12005  * @tparam T type
12006  **/
12007 template <typename T>
12008 class typeInfo;
12009 
12010 template <>
12011 class typeInfo<glw::GLboolean>
12012 {
12013 public:
12014 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12015 };
12016 
12017 template <>
12018 class typeInfo<glw::GLdouble>
12019 {
12020 public:
12021 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12022 };
12023 
12024 template <>
12025 class typeInfo<tcu::UVec2>
12026 {
12027 public:
12028 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12029 };
12030 
12031 template <>
12032 class typeInfo<tcu::UVec3>
12033 {
12034 public:
12035 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12036 };
12037 
12038 template <>
12039 class typeInfo<tcu::UVec4>
12040 {
12041 public:
12042 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12043 };
12044 
12045 template <>
12046 class typeInfo<tcu::DVec2>
12047 {
12048 public:
12049 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12050 };
12051 
12052 template <>
12053 class typeInfo<tcu::DVec3>
12054 {
12055 public:
12056 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12057 };
12058 
12059 template <>
12060 class typeInfo<tcu::DVec4>
12061 {
12062 public:
12063 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12064 };
12065 
12066 template <>
12067 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12068 {
12069 public:
12070 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12071 };
12072 
12073 template <>
12074 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12075 {
12076 public:
12077 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12078 };
12079 
12080 template <>
12081 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12082 {
12083 public:
12084 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12085 };
12086 
12087 template <>
12088 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12089 {
12090 public:
12091 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12092 };
12093 
12094 template <>
12095 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12096 {
12097 public:
12098 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12099 };
12100 
12101 template <>
12102 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12103 {
12104 public:
12105 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12106 };
12107 
12108 template <>
12109 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12110 {
12111 public:
12112 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12113 };
12114 
12115 template <>
12116 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12117 {
12118 public:
12119 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12120 };
12121 
12122 template <>
12123 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12124 {
12125 public:
12126 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12127 };
12128 } /* TypeHelpers */
12129 
12130 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12131  *
12132  **/
12133 namespace Math
12134 {
12135 template <typename T>
12136 static T clamp(T x, T minVal, T maxVal);
12137 
12138 template <int Size>
12139 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12140 
12141 template <int Size>
12142 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12143 
12144 template <typename T>
12145 static T determinant(T val);
12146 
12147 template <typename T>
12148 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12149 
12150 template <typename T>
12151 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12152 
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12155 
12156 template <int Size>
12157 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12158 																glw::GLuint column, glw::GLuint row);
12159 
12160 template <int Size>
12161 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12162 											const tcu::Vector<glw::GLdouble, Size>& right);
12163 
12164 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12165 
12166 static glw::GLdouble fract(glw::GLdouble val);
12167 
12168 template <typename T>
12169 static T frexp(T val, glw::GLint& exp);
12170 
12171 template <int Size>
12172 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12173 												  const tcu::Vector<glw::GLdouble, Size>& right);
12174 
12175 template <int Size>
12176 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12177 													   const tcu::Vector<glw::GLdouble, Size>& right);
12178 
12179 template <int Size>
12180 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12181 
12182 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12183 
12184 static glw::GLuint isinf_impl(glw::GLdouble val);
12185 
12186 static glw::GLuint isnan_impl(glw::GLdouble val);
12187 
12188 template <typename T>
12189 static T ldexp(T val, glw::GLint exp);
12190 
12191 template <int Size>
12192 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12193 											   const tcu::Vector<glw::GLdouble, Size>& right);
12194 
12195 template <int Size>
12196 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12197 													const tcu::Vector<glw::GLdouble, Size>& right);
12198 
12199 template <typename T>
12200 static T max(T left, T right);
12201 
12202 template <typename T>
12203 static T min(T left, T right);
12204 
12205 template <int		 Size>
12206 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12207 								glw::GLuint row);
12208 
12209 template <typename T>
12210 static T mix(T left, T right, T weight);
12211 
12212 template <typename T>
12213 static T mod(T left, T right);
12214 
12215 template <typename T>
12216 static T modf(T val, T& integer);
12217 
12218 template <typename T>
12219 static T multiply(T left, T right);
12220 
12221 template <int Size>
12222 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12223 											   const tcu::Vector<glw::GLdouble, Size>& right);
12224 
12225 template <int Cols, int Rows>
12226 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12227 														   const tcu::Vector<glw::GLdouble, Cols>& right);
12228 
12229 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12230 
12231 template <typename T>
12232 static T round(T t);
12233 
12234 template <typename T>
12235 static T roundEven(T t);
12236 
12237 template <typename T>
12238 static T sign(T t);
12239 
12240 template <typename T>
12241 static T smoothStep(T e0, T e1, T val);
12242 
12243 template <typename T>
12244 static T step(T edge, T val);
12245 
12246 template <typename T, int Rows, int Cols>
12247 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12248 
12249 template <typename T>
12250 static T trunc(T t);
12251 
12252 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12253 
12254 template <typename T>
clamp(T x,T minVal,T maxVal)12255 static T clamp(T x, T minVal, T maxVal)
12256 {
12257 	return min(max(x, minVal), maxVal);
12258 }
12259 
12260 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12261 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12262 {
12263 	tcu::Matrix<glw::GLdouble, Size, Size> result;
12264 
12265 	for (glw::GLuint c = 0; c < Size; ++c)
12266 	{
12267 		for (glw::GLuint r = 0; r < Size; ++r)
12268 		{
12269 			const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12270 
12271 			result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12272 		}
12273 	}
12274 
12275 	return result;
12276 }
12277 
12278 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12279 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12280 {
12281 	tcu::Vector<glw::GLuint, Size> result;
12282 
12283 	for (glw::GLint i = 0; i < Size; ++i)
12284 	{
12285 		if (GL_FALSE != src[i])
12286 		{
12287 			result[i] = 1;
12288 		}
12289 		else
12290 		{
12291 			result[i] = 0;
12292 		}
12293 	}
12294 
12295 	return result;
12296 }
12297 
12298 template <typename T>
det2(T _00,T _10,T _01,T _11)12299 static T det2(T _00, T _10, T _01, T _11)
12300 {
12301 	return _00 * _11 - _01 * _10;
12302 }
12303 
12304 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12305 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12306 {
12307 	return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12308 }
12309 
12310 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)12311 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,
12312 			  T _33)
12313 {
12314 	return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12315 		   _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12316 		   _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12317 		   _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12318 }
12319 
12320 template <typename T>
determinant(T val)12321 static T determinant(T val)
12322 {
12323 	return val;
12324 }
12325 
12326 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12327 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12328 {
12329 	return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12330 }
12331 
12332 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12333 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12334 {
12335 	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));
12336 }
12337 
12338 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12339 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12340 {
12341 	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),
12342 				mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12343 }
12344 
12345 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12346 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12347 																glw::GLuint column, glw::GLuint row)
12348 {
12349 	// GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12350 #if (DE_COMPILER == DE_COMPILER_GCC)
12351 #	pragma GCC diagnostic push
12352 #	pragma GCC diagnostic ignored "-Warray-bounds"
12353 #endif
12354 
12355 	const glw::GLint eCol = static_cast<glw::GLint>(column);
12356 	const glw::GLint eRow = static_cast<glw::GLint>(row);
12357 
12358 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12359 
12360 	for (glw::GLint c = 0; c < Size; ++c)
12361 	{
12362 		/* Skip eliminated column */
12363 		if (eCol == c)
12364 		{
12365 			continue;
12366 		}
12367 
12368 		for (glw::GLint r = 0; r < Size; ++r)
12369 		{
12370 			/* Skip eliminated row */
12371 			if (eRow == r)
12372 			{
12373 				continue;
12374 			}
12375 
12376 			const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12377 			const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12378 
12379 			result(r + r_offset, c + c_offset) = matrix(r, c);
12380 		}
12381 	}
12382 
12383 	return result;
12384 
12385 #if (DE_COMPILER == DE_COMPILER_GCC)
12386 #	pragma GCC diagnostic pop
12387 #endif
12388 }
12389 
12390 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12391 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12392 											const tcu::Vector<glw::GLdouble, Size>& right)
12393 {
12394 	return convertBvecToUvec(tcu::equal(left, right));
12395 }
12396 
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12397 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12398 {
12399 	return a * b + c;
12400 }
12401 
fract(glw::GLdouble val)12402 static glw::GLdouble fract(glw::GLdouble val)
12403 {
12404 	return val - floor(val);
12405 }
12406 
12407 template <typename T>
frexp(T val,glw::GLint & exp)12408 static T frexp(T val, glw::GLint& exp)
12409 {
12410 	return ::frexp(val, &exp);
12411 }
12412 
12413 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12415 												  const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 	return convertBvecToUvec(tcu::greaterThan(left, right));
12418 }
12419 
12420 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12421 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12422 													   const tcu::Vector<glw::GLdouble, Size>& right)
12423 {
12424 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12425 }
12426 
12427 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12428 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12429 {
12430 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
12431 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12432 	const glw::GLdouble det		= determinant(matrix);
12433 	const glw::GLdouble inv_det = 1.0 / det;
12434 
12435 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12436 
12437 	return result;
12438 }
12439 
inverseSqrt(glw::GLdouble val)12440 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12441 {
12442 	const glw::GLdouble root = sqrt(val);
12443 
12444 	return (1.0 / root);
12445 }
12446 
isinf_impl(glw::GLdouble val)12447 static glw::GLuint isinf_impl(glw::GLdouble val)
12448 {
12449 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12450 
12451 	return ((infinity == val) || (-infinity == val));
12452 }
12453 
isnan_impl(glw::GLdouble val)12454 static glw::GLuint isnan_impl(glw::GLdouble val)
12455 {
12456 	return val != val;
12457 }
12458 
12459 template <typename T>
ldexp(T val,glw::GLint exp)12460 static T ldexp(T val, glw::GLint exp)
12461 {
12462 	return ::ldexp(val, exp);
12463 }
12464 
12465 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12466 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12467 											   const tcu::Vector<glw::GLdouble, Size>& right)
12468 {
12469 	return convertBvecToUvec(tcu::lessThan(left, right));
12470 }
12471 
12472 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12473 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12474 													const tcu::Vector<glw::GLdouble, Size>& right)
12475 {
12476 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
12477 }
12478 
12479 template <typename T>
max(T left,T right)12480 static T max(T left, T right)
12481 {
12482 	return (left >= right) ? left : right;
12483 }
12484 
12485 template <typename T>
min(T left,T right)12486 static T min(T left, T right)
12487 {
12488 	return (left <= right) ? left : right;
12489 }
12490 
12491 template <int		 Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12492 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12493 								glw::GLuint row)
12494 {
12495 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12496 
12497 	return determinant(eliminated);
12498 }
12499 
12500 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12501 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12502 {
12503 	const glw::GLuint r = (0 == row) ? 1 : 0;
12504 	const glw::GLuint c = (0 == column) ? 1 : 0;
12505 
12506 	return matrix(r, c);
12507 }
12508 
12509 template <typename T>
mix(T left,T right,T weight)12510 static T mix(T left, T right, T weight)
12511 {
12512 	return left * (1 - weight) + right * (weight);
12513 }
12514 
12515 template <typename T>
mod(T left,T right)12516 static T mod(T left, T right)
12517 {
12518 	const T div_res = left / right;
12519 	const T floored = floor(div_res);
12520 
12521 	return left - right * floored;
12522 }
12523 
12524 template <typename T>
modf(T val,T & integer)12525 static T modf(T val, T& integer)
12526 {
12527 	return ::modf(val, &integer);
12528 }
12529 
12530 template <typename T>
multiply(T left,T right)12531 static T multiply(T left, T right)
12532 {
12533 	T result = left * right;
12534 
12535 	return result;
12536 }
12537 
12538 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12539 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12540 											   const tcu::Vector<glw::GLdouble, Size>& right)
12541 {
12542 	return convertBvecToUvec(tcu::notEqual(left, right));
12543 }
12544 
12545 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12546 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12547 														   const tcu::Vector<glw::GLdouble, Cols>& right)
12548 {
12549 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
12550 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
12551 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12552 
12553 	for (glw::GLuint i = 0; i < Rows; ++i)
12554 	{
12555 		left_mat(i, 0) = left[i];
12556 	}
12557 
12558 	for (glw::GLuint i = 0; i < Cols; ++i)
12559 	{
12560 		right_mat(0, i) = right[i];
12561 	}
12562 
12563 	result = left_mat * right_mat;
12564 
12565 	return result;
12566 }
12567 
packDouble2x32(const tcu::UVec2 & in)12568 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12569 {
12570 	const glw::GLuint buffer[2] = { in[0], in[1] };
12571 	glw::GLdouble	 result;
12572 	memcpy(&result, buffer, sizeof(result));
12573 	return result;
12574 }
12575 
12576 template <typename T>
round(T t)12577 static T round(T t)
12578 {
12579 	T frac = fract(t);
12580 	T res  = t - frac;
12581 
12582 	if (((T)0.5) < frac)
12583 	{
12584 		res += ((T)1.0);
12585 	}
12586 
12587 	return res;
12588 }
12589 
12590 template <typename T>
roundEven(T t)12591 static T roundEven(T t)
12592 {
12593 	T frac = fract(t);
12594 	T res  = t - frac;
12595 
12596 	if (((T)0.5) < frac)
12597 	{
12598 		res += ((T)1.0);
12599 	}
12600 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12601 	{
12602 		res += ((T)1.0);
12603 	}
12604 
12605 	return res;
12606 }
12607 
12608 template <typename T>
sign(T t)12609 static T sign(T t)
12610 {
12611 	if (0 > t)
12612 	{
12613 		return -1;
12614 	}
12615 	else if (0 == t)
12616 	{
12617 		return 0;
12618 	}
12619 	else
12620 	{
12621 		return 1;
12622 	}
12623 }
12624 
12625 template <typename T>
smoothStep(T e0,T e1,T val)12626 static T smoothStep(T e0, T e1, T val)
12627 {
12628 	if (e0 >= val)
12629 	{
12630 		return 0;
12631 	}
12632 
12633 	if (e1 <= val)
12634 	{
12635 		return 1;
12636 	}
12637 
12638 	T temp = (val - e0) / (e1 - e0);
12639 
12640 	T result = temp * temp * (3 - 2 * temp);
12641 
12642 	return result;
12643 }
12644 
12645 template <typename T>
step(T edge,T val)12646 static T step(T edge, T val)
12647 {
12648 	if (edge > val)
12649 	{
12650 		return 0;
12651 	}
12652 	else
12653 	{
12654 		return 1;
12655 	}
12656 }
12657 
12658 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12659 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12660 {
12661 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12662 
12663 	return result;
12664 }
12665 
12666 template <typename T>
trunc(T t)12667 static T trunc(T t)
12668 {
12669 	const T abs_value	= de::abs(t);
12670 	const T result_value = floor(abs_value);
12671 
12672 	const T result = sign(t) * result_value;
12673 
12674 	return result;
12675 }
12676 
unpackDouble2x32(const glw::GLdouble & val)12677 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12678 {
12679 	glw::GLuint* ptr = (glw::GLuint*)&val;
12680 	tcu::UVec2   result(ptr[0], ptr[1]);
12681 
12682 	return result;
12683 }
12684 } /* Math */
12685 
12686 /** Enumeration of tested functions
12687  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12688  * For example "max" can be called for (dvec3, double).
12689  **/
12690 enum FunctionEnum
12691 {
12692 	FUNCTION_ABS = 0,
12693 	FUNCTION_CEIL,
12694 	FUNCTION_CLAMP,
12695 	FUNCTION_CLAMP_AGAINST_SCALAR,
12696 	FUNCTION_CROSS,
12697 	FUNCTION_DETERMINANT,
12698 	FUNCTION_DISTANCE,
12699 	FUNCTION_DOT,
12700 	FUNCTION_EQUAL,
12701 	FUNCTION_FACEFORWARD,
12702 	FUNCTION_FLOOR,
12703 	FUNCTION_FMA,
12704 	FUNCTION_FRACT,
12705 	FUNCTION_FREXP,
12706 	FUNCTION_GREATERTHAN,
12707 	FUNCTION_GREATERTHANEQUAL,
12708 	FUNCTION_INVERSE,
12709 	FUNCTION_INVERSESQRT,
12710 	FUNCTION_LDEXP,
12711 	FUNCTION_LESSTHAN,
12712 	FUNCTION_LESSTHANEQUAL,
12713 	FUNCTION_LENGTH,
12714 	FUNCTION_MATRIXCOMPMULT,
12715 	FUNCTION_MAX,
12716 	FUNCTION_MAX_AGAINST_SCALAR,
12717 	FUNCTION_MIN,
12718 	FUNCTION_MIN_AGAINST_SCALAR,
12719 	FUNCTION_MIX,
12720 	FUNCTION_MOD,
12721 	FUNCTION_MOD_AGAINST_SCALAR,
12722 	FUNCTION_MODF,
12723 	FUNCTION_NORMALIZE,
12724 	FUNCTION_NOTEQUAL,
12725 	FUNCTION_OUTERPRODUCT,
12726 	FUNCTION_PACKDOUBLE2X32,
12727 	FUNCTION_REFLECT,
12728 	FUNCTION_REFRACT,
12729 	FUNCTION_ROUND,
12730 	FUNCTION_ROUNDEVEN,
12731 	FUNCTION_SIGN,
12732 	FUNCTION_SMOOTHSTEP,
12733 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12734 	FUNCTION_SQRT,
12735 	FUNCTION_STEP,
12736 	FUNCTION_STEP_AGAINST_SCALAR,
12737 	FUNCTION_TRANSPOSE,
12738 	FUNCTION_TRUNC,
12739 	FUNCTION_UNPACKDOUBLE2X32,
12740 	FUNCTION_ISNAN,
12741 	FUNCTION_ISINF,
12742 };
12743 
12744 struct TypeDefinition
12745 {
12746 	std::string name;
12747 	glw::GLuint n_columns;
12748 	glw::GLuint n_rows;
12749 };
12750 
12751 /** Implementation of BuiltinFunctionTest test, description follows:
12752  *
12753  *  Verify double-precision support in common functions works correctly.
12754  *  All double-precision types that apply for particular cases should
12755  *  be tested for the following functions:
12756  *
12757  *  - abs();
12758  *  - ceil();
12759  *  - clamp();
12760  *  - cross();
12761  *  - determinant();
12762  *  - distance();
12763  *  - dot();
12764  *  - equal();
12765  *  - faceforward();
12766  *  - floor();
12767  *  - fma();
12768  *  - fract();
12769  *  - frexp();
12770  *  - greaterThan();
12771  *  - greaterThanEqual();
12772  *  - inverse();
12773  *  - inversesqrt();
12774  *  - ldexp();
12775  *  - lessThan();
12776  *  - lessThanEqual();
12777  *  - length();
12778  *  - matrixCompMult();
12779  *  - max();
12780  *  - min();
12781  *  - mix();
12782  *  - mod();
12783  *  - modf();
12784  *  - normalize();
12785  *  - notEqual();
12786  *  - outerProduct();
12787  *  - packDouble2x32();
12788  *  - reflect();
12789  *  - refract();
12790  *  - round();
12791  *  - roundEven();
12792  *  - sign();
12793  *  - smoothstep();
12794  *  - sqrt();
12795  *  - step();
12796  *  - transpose();
12797  *  - trunc();
12798  *  - unpackDouble2x32();
12799  *  - isnan();
12800  *  - isinf();
12801  *
12802  *  The test should work by creating a program object (for each case
12803  *  considered), to which a vertex shader should be attached. The
12804  *  shader should define input variables that should be used as
12805  *  arguments for the function in question. The result of the
12806  *  operation should then be XFBed back to the test, where the
12807  *  value should be verified.
12808  *
12809  *  Reference function implementation from pre-DEQP CTS framework
12810  *  should be ported to C for verification purposes where available.
12811  *
12812  *  The test should use 1024 different scalar/vector/matrix argument
12813  *  combinations. It should pass if all functions are determined
12814  *  to work correctly for all argument combinations used.
12815  **/
12816 class BuiltinFunctionTest : public deqp::TestCase
12817 {
12818 public:
12819 	/* Public methods */
12820 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12821 						TypeDefinition typeDefinition);
12822 
12823 	virtual void						 deinit();
12824 	virtual tcu::TestNode::IterateResult iterate();
12825 
12826 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12827 	 *
12828 	 **/
12829 	class functionObject
12830 	{
12831 	public:
12832 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12833 					   Utils::_variable_type result_type);
12834 
~functionObject()12835 		virtual ~functionObject()
12836 		{
12837 		}
12838 
12839 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12840 
12841 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
12842 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12843 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12844 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12845 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12846 		glw::GLuint getArgumentStride() const;
12847 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
12848 		FunctionEnum	   getFunctionEnum() const;
12849 		const glw::GLchar* getName() const;
12850 		glw::GLuint getResultComponents(glw::GLuint result) const;
12851 		virtual glw::GLuint getResultCount() const;
12852 		glw::GLuint getResultOffset(glw::GLuint result) const;
12853 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12854 		glw::GLuint getResultStride(glw::GLuint result) const;
12855 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12856 		glw::GLuint getResultStride() const;
12857 
12858 	protected:
12859 		const FunctionEnum			m_function_enum;
12860 		const glw::GLchar*			m_function_name;
12861 		const glw::GLvoid*			m_p_function;
12862 		const Utils::_variable_type m_res_type;
12863 	};
12864 
12865 private:
12866 	/* Private types */
12867 	/** General type enumeration
12868 	 *
12869 	 **/
12870 	enum generalType
12871 	{
12872 		SCALAR = 0,
12873 		VECTOR,
12874 		MATRIX,
12875 	};
12876 
12877 	/** Details of variable type
12878 	 *
12879 	 **/
12880 	struct typeDetails
12881 	{
12882 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12883 
12884 		generalType m_general_type;
12885 		glw::GLuint m_n_columns;
12886 		glw::GLuint m_n_rows;
12887 		glw::GLenum m_type;
12888 		std::string m_type_name;
12889 	};
12890 
12891 	/* Typedefs for gl.uniform* function pointers */
12892 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12893 																	   const glw::GLdouble*);
12894 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12895 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12896 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12897 
12898 	/* Private methods */
12899 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12900 
12901 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12902 
12903 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
12904 														 const functionObject& function_object) const;
12905 
12906 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
12907 														 const functionObject& function_object) const;
12908 
12909 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
12910 														 const functionObject& function_object) const;
12911 
12912 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
12913 														 const functionObject& function_object) const;
12914 
12915 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
12916 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12917 
12918 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12919 
12920 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12921 
12922 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12923 
12924 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12925 						   glw::GLubyte* buffer);
12926 
12927 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12928 
12929 	void prepareTestData(const functionObject& function_object);
12930 	void prepareVertexShaderCode(const functionObject& function_object);
12931 
12932 	bool test(FunctionEnum function, const typeDetails& type);
12933 
12934 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12935 
12936 	void testInit();
12937 
12938 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12939 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12940 						  const glw::GLvoid* result_src);
12941 
12942 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12943 
12944 	/* Private constants */
12945 	static const glw::GLdouble m_epsilon;
12946 	static const glw::GLuint   m_n_veritces;
12947 
12948 	/* Private fields */
12949 	glw::GLuint m_transform_feedback_buffer_id;
12950 	glw::GLuint m_vertex_array_object_id;
12951 
12952 	std::vector<glw::GLubyte> m_expected_results_data;
12953 	FunctionEnum			  m_function;
12954 	TypeDefinition			  m_typeDefinition;
12955 	std::vector<glw::GLubyte> m_argument_data;
12956 	std::string				  m_vertex_shader_code;
12957 };
12958 
12959 /* Constants used by BuiltinFunctionTest */
12960 /** Khronos Bug #14010
12961  *  Using an epsilon value for comparing floating points is error prone.
12962  *  Rather than writing a new floating point comparison function, I am
12963  *  increasing the epsilon value to allow greater orders of magnitude
12964  *  of floating point values.
12965  **/
12966 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
12967 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12968 
12969 /** Implementations of function objects required by "BuiltinFunctionTest"
12970  *
12971  **/
12972 namespace FunctionObject
12973 {
12974 /** Maps variable type with enumeration Utils::_variable_type
12975  *
12976  * @tparam T type
12977  **/
12978 template <typename T>
12979 class typeInfo
12980 {
12981 public:
12982 	static const Utils::_variable_type variable_type =
12983 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12984 };
12985 
12986 /** Place data from <in> into <buffer>
12987  *
12988  * @param buffer Buffer
12989  * @param in     Input data
12990  **/
12991 template <typename T>
12992 class pack
12993 {
12994 public:
set(glw::GLvoid * buffer,const T & in)12995 	static void set(glw::GLvoid* buffer, const T& in)
12996 	{
12997 		*(T*)buffer = in;
12998 	}
12999 };
13000 
13001 /** Place tcu::Matrix data from <in> into <buffer>
13002  *
13003  * @param buffer Buffer
13004  * @param in     Input data
13005  **/
13006 template <int Cols, int Rows>
13007 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13008 {
13009 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13010 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13011 	{
13012 		glw::GLdouble* data = (glw::GLdouble*)buffer;
13013 
13014 		for (glw::GLint column = 0; column < Cols; ++column)
13015 		{
13016 			for (glw::GLint row = 0; row < Rows; ++row)
13017 			{
13018 				glw::GLint index = column * Rows + row;
13019 
13020 				data[index] = in(row, column);
13021 			}
13022 		}
13023 	}
13024 };
13025 
13026 /** Get data of <out> from <buffer>
13027  *
13028  * @param buffer Buffer
13029  * @param out    Output data
13030  **/
13031 template <typename T>
13032 class unpack
13033 {
13034 public:
get(const glw::GLvoid * buffer,T & out)13035 	static void get(const glw::GLvoid* buffer, T& out)
13036 	{
13037 		out = *(T*)buffer;
13038 	}
13039 };
13040 
13041 /** Get tcu::Matrix data from <buffer>
13042  *
13043  * @param buffer Buffer
13044  * @param out    Output data
13045  **/
13046 template <int Cols, int Rows>
13047 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13048 {
13049 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13050 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13051 	{
13052 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
13053 
13054 		for (glw::GLint column = 0; column < Cols; ++column)
13055 		{
13056 			for (glw::GLint row = 0; row < Rows; ++row)
13057 			{
13058 				glw::GLint index = column * Rows + row;
13059 
13060 				out(row, column) = data[index];
13061 			}
13062 		}
13063 	}
13064 };
13065 
13066 /** Base of unary function classes
13067  *
13068  **/
13069 class unaryBase : public BuiltinFunctionTest::functionObject
13070 {
13071 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)13072 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13073 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13074 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13075 	{
13076 	}
13077 
getArgumentCount() const13078 	virtual glw::GLuint getArgumentCount() const
13079 	{
13080 		return 1;
13081 	}
13082 
getArgumentType(glw::GLuint) const13083 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13084 	{
13085 		return m_arg_type;
13086 	}
13087 
13088 protected:
13089 	const Utils::_variable_type m_arg_type;
13090 };
13091 
13092 /** Unary function class. It treats input argument as one variable.
13093  *
13094  * @tparam ResT Type of result
13095  * @tparam ArgT Type of argument
13096  **/
13097 template <typename ResT, typename ArgT>
13098 class unary : public unaryBase
13099 {
13100 public:
13101 	typedef ResT (*functionPointer)(const ArgT&);
13102 
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13103 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13104 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13105 					typeInfo<ArgT>::variable_type)
13106 	{
13107 	}
13108 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13109 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13110 	{
13111 		ResT result;
13112 		ArgT arg;
13113 
13114 		unpack<ArgT>::get(argument_src, arg);
13115 
13116 		functionPointer p_function = (functionPointer)m_p_function;
13117 
13118 		result = p_function(arg);
13119 
13120 		pack<ResT>::set(result_dst, result);
13121 	}
13122 };
13123 
13124 /** Unary function class. It treats input argument as separate components.
13125  *
13126  * @tparam ResT Type of result
13127  **/
13128 template <typename ResT>
13129 class unaryByComponent : public unaryBase
13130 {
13131 public:
13132 	typedef ResT (*functionPointer)(glw::GLdouble);
13133 
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13134 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13135 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13136 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13137 	{
13138 	}
13139 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13140 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13141 	{
13142 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13143 		ResT*		   p_result		= (ResT*)result_dst;
13144 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
13145 
13146 		functionPointer p_function = (functionPointer)m_p_function;
13147 
13148 		for (glw::GLuint component = 0; component < n_components; ++component)
13149 		{
13150 			p_result[component] = p_function(p_arg[component]);
13151 		}
13152 	}
13153 };
13154 
13155 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13156  *
13157  * @tparam ResT Type of result
13158  * @tparam ArgT Type of argument
13159  * @tparam OutT Type of output parameter
13160  **/
13161 template <typename ResT, typename ArgT, typename OutT>
13162 class unaryWithOutputByComponent : public unaryBase
13163 {
13164 public:
13165 	typedef ResT (*functionPointer)(ArgT, OutT&);
13166 
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)13167 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13168 							   functionPointer function_pointer, const Utils::_variable_type res_type,
13169 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13170 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13171 		, m_out_type(out_type)
13172 	{
13173 	}
13174 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13175 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13176 	{
13177 		ResT* p_result = (ResT*)result_dst;
13178 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13179 		ArgT* p_arg	= (ArgT*)argument_src;
13180 
13181 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13182 		const glw::GLuint n_components_1 = getResultComponents(1);
13183 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13184 
13185 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13186 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13187 
13188 		functionPointer p_function = (functionPointer)m_p_function;
13189 
13190 		for (glw::GLuint component = 0; component < n_components; ++component)
13191 		{
13192 			const ArgT first_arg  = p_arg[component * component_step_0];
13193 			OutT&	  second_arg = p_out[component * component_step_1];
13194 
13195 			p_result[component] = p_function(first_arg, second_arg);
13196 		}
13197 	}
13198 
getResultCount() const13199 	glw::GLuint getResultCount() const
13200 	{
13201 		return 2;
13202 	}
13203 
getResultType(glw::GLuint result) const13204 	Utils::_variable_type getResultType(glw::GLuint result) const
13205 	{
13206 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13207 
13208 		switch (result)
13209 		{
13210 		case 0:
13211 			type = m_res_type;
13212 			break;
13213 		case 1:
13214 			type = m_out_type;
13215 			break;
13216 		default:
13217 			TCU_FAIL("Not implemented");
13218 			break;
13219 		}
13220 
13221 		return type;
13222 	}
13223 
13224 protected:
13225 	const Utils::_variable_type m_out_type;
13226 };
13227 
13228 /** Base of binary function classes.
13229  *
13230  **/
13231 class binaryBase : public BuiltinFunctionTest::functionObject
13232 {
13233 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)13234 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13235 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13236 			   const Utils::_variable_type arg_2_type)
13237 		: functionObject(function_enum, function_name, function_pointer, res_type)
13238 		, m_arg_1_type(arg_1_type)
13239 		, m_arg_2_type(arg_2_type)
13240 	{
13241 	}
13242 
getArgumentCount() const13243 	virtual glw::GLuint getArgumentCount() const
13244 	{
13245 		return 2;
13246 	}
13247 
getArgumentType(glw::GLuint argument) const13248 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13249 	{
13250 		switch (argument)
13251 		{
13252 		case 0:
13253 			return m_arg_1_type;
13254 		case 1:
13255 			return m_arg_2_type;
13256 		default:
13257 			return Utils::VARIABLE_TYPE_UNKNOWN;
13258 		}
13259 	}
13260 
13261 protected:
13262 	const Utils::_variable_type m_arg_1_type;
13263 	const Utils::_variable_type m_arg_2_type;
13264 };
13265 
13266 /** Binary function class. It treats input arguments as two variables.
13267  *
13268  * @param ResT  Type of result
13269  * @param Arg1T Type of first argument
13270  * @param Arg2T Type of second argument
13271  **/
13272 template <typename ResT, typename Arg1T, typename Arg2T>
13273 class binary : public binaryBase
13274 {
13275 public:
13276 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13277 
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13278 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13279 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13280 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13281 	{
13282 	}
13283 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13284 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13285 	{
13286 		const glw::GLuint argument_1_stride = getArgumentStride(0);
13287 
13288 		functionPointer p_function = (functionPointer)m_p_function;
13289 
13290 		Arg1T arg_1;
13291 		Arg2T arg_2;
13292 		ResT  result;
13293 
13294 		unpack<Arg1T>::get(argument_src, arg_1);
13295 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13296 
13297 		result = p_function(arg_1, arg_2);
13298 
13299 		pack<ResT>::set(result_dst, result);
13300 	}
13301 };
13302 
13303 /** Binary function class. It treats input arguments as separate components.
13304  *
13305  * @param ResT  Type of result
13306  * @param Arg1T Type of first argument
13307  * @param Arg2T Type of second argument
13308  **/
13309 template <typename ResT, typename Arg1T, typename Arg2T>
13310 class binaryByComponent : public binaryBase
13311 {
13312 public:
13313 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
13314 
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)13315 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13316 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13317 					  const Utils::_variable_type arg_2_type)
13318 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13319 	{
13320 	}
13321 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13322 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13323 	{
13324 		ResT*  p_result = (ResT*)result_dst;
13325 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
13326 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13327 
13328 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13329 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13330 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13331 
13332 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13333 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13334 
13335 		functionPointer p_function = (functionPointer)m_p_function;
13336 
13337 		for (glw::GLuint component = 0; component < n_components; ++component)
13338 		{
13339 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
13340 			const Arg2T second_arg = p_arg_2[component * component_step_1];
13341 
13342 			p_result[component] = p_function(first_arg, second_arg);
13343 		}
13344 	}
13345 };
13346 
13347 /** Base of tenary function classes.
13348  *
13349  **/
13350 class tenaryBase : public BuiltinFunctionTest::functionObject
13351 {
13352 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)13353 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13354 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13355 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13356 		: functionObject(function_enum, function_name, function_pointer, res_type)
13357 		, m_arg_1_type(arg_1_type)
13358 		, m_arg_2_type(arg_2_type)
13359 		, m_arg_3_type(arg_3_type)
13360 	{
13361 	}
13362 
getArgumentCount() const13363 	virtual glw::GLuint getArgumentCount() const
13364 	{
13365 		return 3;
13366 	}
13367 
getArgumentType(glw::GLuint argument) const13368 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13369 	{
13370 		switch (argument)
13371 		{
13372 		case 0:
13373 			return m_arg_1_type;
13374 		case 1:
13375 			return m_arg_2_type;
13376 		case 2:
13377 			return m_arg_3_type;
13378 		default:
13379 			return Utils::VARIABLE_TYPE_UNKNOWN;
13380 		}
13381 	}
13382 
13383 protected:
13384 	const Utils::_variable_type m_arg_1_type;
13385 	const Utils::_variable_type m_arg_2_type;
13386 	const Utils::_variable_type m_arg_3_type;
13387 };
13388 
13389 /** Tenary function class. It treats input arguments as three variables.
13390  *
13391  * @param ResT  Type of result
13392  * @param Arg1T Type of first argument
13393  * @param Arg2T Type of second argument
13394  * @param Arg3T Type of third argument
13395  **/
13396 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13397 class tenary : public tenaryBase
13398 {
13399 public:
13400 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13401 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13402 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13403 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13404 
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13405 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13406 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13407 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13408 	{
13409 	}
13410 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13411 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13412 	{
13413 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
13414 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
13415 
13416 		functionPointer p_function = (functionPointer)m_p_function;
13417 
13418 		arg1T arg_1;
13419 		arg2T arg_2;
13420 		arg3T arg_3;
13421 		ResT  result;
13422 
13423 		unpack<arg1T>::get(argument_src, arg_1);
13424 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13425 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13426 
13427 		result = p_function(arg_1, arg_2, arg_3);
13428 
13429 		pack<ResT>::set(result_dst, result);
13430 	}
13431 };
13432 
13433 /** Tenary function class. It treats input arguments as separate components.
13434  *
13435 
13436  **/
13437 class tenaryByComponent : public tenaryBase
13438 {
13439 public:
13440 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13441 
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)13442 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13443 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13444 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13445 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13446 					 arg_3_type)
13447 	{
13448 	}
13449 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13450 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13451 	{
13452 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
13453 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
13454 
13455 		const glw::GLuint n_components_0 = getArgumentComponents(0);
13456 		const glw::GLuint n_components_1 = getArgumentComponents(1);
13457 		const glw::GLuint n_components_2 = getArgumentComponents(2);
13458 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13459 
13460 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13461 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13462 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13463 
13464 		functionPointer p_function = (functionPointer)m_p_function;
13465 
13466 		for (glw::GLuint component = 0; component < n_components; ++component)
13467 		{
13468 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13469 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13470 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13471 
13472 			p_result[component] = p_function(first_arg, second_arg, third_arg);
13473 		}
13474 	}
13475 };
13476 } /* FunctionObject */
13477 
13478 /** Constructor.
13479  *
13480  *  @param context Rendering context.
13481  **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13482 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13483 										 TypeDefinition typeDefinition)
13484 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13485 	, m_transform_feedback_buffer_id(0)
13486 	, m_vertex_array_object_id(0)
13487 	, m_function(function)
13488 	, m_typeDefinition(typeDefinition)
13489 {
13490 	/* Nothing to be done here */
13491 }
13492 
13493 /** Deinitializes all GL objects that may have been created during test execution.
13494  *
13495  **/
deinit()13496 void BuiltinFunctionTest::deinit()
13497 {
13498 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13499 
13500 	/* Clean buffers */
13501 	if (0 != m_transform_feedback_buffer_id)
13502 	{
13503 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13504 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13505 		m_transform_feedback_buffer_id = 0;
13506 	}
13507 
13508 	/* Clean VAO */
13509 	if (0 != m_vertex_array_object_id)
13510 	{
13511 		gl.bindVertexArray(0);
13512 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13513 		m_vertex_array_object_id = 0;
13514 	}
13515 }
13516 
13517 /** Execute test
13518  *
13519  * @return tcu::TestNode::STOP
13520  **/
iterate()13521 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13522 {
13523 	/* Check if extension is supported */
13524 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13525 	{
13526 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13527 	}
13528 
13529 	testInit();
13530 
13531 	/* Verify result */
13532 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13533 	if (test(m_function, type))
13534 	{
13535 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13536 	}
13537 	else
13538 	{
13539 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13540 	}
13541 
13542 	/* Done */
13543 	return tcu::TestNode::STOP;
13544 }
13545 
13546 /** Constructor
13547  *
13548  * @param function_enum    Function enumeration
13549  * @param function_name    Function name
13550  * @param function_pointer Pointer to routine that wiil be executed
13551  * @param result_type      Type of result
13552  **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13553 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13554 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13555 	: m_function_enum(function_enum)
13556 	, m_function_name(function_name)
13557 	, m_p_function(function_pointer)
13558 	, m_res_type(result_type)
13559 {
13560 	/* Nothing to be done here */
13561 }
13562 
13563 /** Get number of components for <argument>
13564  *
13565  * @param argument Argument ordinal, starts with 0
13566  *
13567  * @return Number of components
13568  **/
getArgumentComponents(glw::GLuint argument) const13569 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13570 {
13571 	const Utils::_variable_type type		  = getArgumentType(argument);
13572 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13573 
13574 	return n_components;
13575 }
13576 
13577 /** Get size in bytes of single component of <argument>
13578  *
13579  * @param argument Argument ordinal, starts with 0
13580  *
13581  * @return Size of component
13582  **/
getArgumentComponentSize(glw::GLuint argument) const13583 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13584 {
13585 	const Utils::_variable_type type		   = getArgumentType(argument);
13586 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13587 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13588 
13589 	return base_type_size;
13590 }
13591 
13592 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13593  *
13594  * @param argument Argument ordinal, starts with 0
13595  *
13596  * @return Offset of arguemnt's data
13597  **/
getArgumentOffset(glw::GLuint argument) const13598 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13599 {
13600 	glw::GLuint result = 0;
13601 
13602 	for (glw::GLuint i = 0; i < argument; ++i)
13603 	{
13604 		result += getArgumentStride(i);
13605 	}
13606 
13607 	return result;
13608 }
13609 
13610 /** Get stride in bytes of all arguments
13611  *
13612  * @return Stride of all arguments
13613  **/
getArgumentStride() const13614 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13615 {
13616 	const glw::GLuint n_args = getArgumentCount();
13617 	glw::GLuint		  result = 0;
13618 
13619 	for (glw::GLuint i = 0; i < n_args; ++i)
13620 	{
13621 		result += getArgumentStride(i);
13622 	}
13623 
13624 	return result;
13625 }
13626 
13627 /** Get stride in bytes of <argument>
13628  *
13629  * @param argument Argument ordinal, starts with 0
13630  *
13631  * @return Stride of argument
13632  **/
getArgumentStride(glw::GLuint argument) const13633 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13634 {
13635 	const glw::GLuint component_size = getArgumentComponentSize(argument);
13636 	const glw::GLuint n_components   = getArgumentComponents(argument);
13637 
13638 	return n_components * component_size;
13639 }
13640 
13641 /** Get function enumeration
13642  *
13643  * @return Function enumeration
13644  **/
getFunctionEnum() const13645 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13646 {
13647 	return m_function_enum;
13648 }
13649 
13650 /** Get function name
13651  *
13652  * @return Function name
13653  **/
getName() const13654 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13655 {
13656 	return m_function_name;
13657 }
13658 
13659 /** Get number of components for <result>
13660  *
13661  * @param result Result ordinal, starts with 0
13662  *
13663  * @return Number of components
13664  **/
getResultComponents(glw::GLuint result) const13665 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13666 {
13667 	const Utils::_variable_type type		  = getResultType(result);
13668 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
13669 
13670 	return n_components;
13671 }
13672 
13673 /** Get number of results
13674  *
13675  * @return Number of results
13676  **/
getResultCount() const13677 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13678 {
13679 	return 1;
13680 }
13681 
13682 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13683  *
13684  * @param result Result ordinal, starts with 0
13685  *
13686  * @return Offset
13687  **/
getResultOffset(glw::GLuint result) const13688 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13689 {
13690 	glw::GLuint offset = 0;
13691 
13692 	for (glw::GLuint i = 0; i < result; ++i)
13693 	{
13694 		offset += getResultStride(i);
13695 		offset = deAlign32(offset, getBaseTypeSize(i));
13696 	}
13697 
13698 	return offset;
13699 }
13700 
13701 /** Get stride in bytes of <result>.
13702  *
13703  * @param result Result ordinal, starts with 0
13704  *
13705  * @return Stride
13706  **/
getResultStride(glw::GLuint result) const13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13708 {
13709 	const Utils::_variable_type type		   = getResultType(result);
13710 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
13711 
13712 	return n_components * getBaseTypeSize(result);
13713 }
13714 
13715 /** Get size in bytes of <result> base component.
13716  *
13717  * @param result Result ordinal, starts with 0
13718  *
13719  * @return Alignment
13720  **/
getBaseTypeSize(glw::GLuint result) const13721 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13722 {
13723 	const Utils::_variable_type type		   = getResultType(result);
13724 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
13725 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13726 
13727 	return base_type_size;
13728 }
13729 
13730 /** Get stride in bytes of all results.
13731  *
13732  * @return Stride
13733  **/
getResultStride() const13734 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13735 {
13736 	const glw::GLuint n_results	= getResultCount();
13737 	glw::GLuint		  stride	   = 0;
13738 	glw::GLuint		  maxAlignment = 0;
13739 
13740 	for (glw::GLuint i = 0; i < n_results; ++i)
13741 	{
13742 		const glw::GLuint alignment = getBaseTypeSize(i);
13743 		stride += getResultStride(i);
13744 		stride		 = deAlign32(stride, alignment);
13745 		maxAlignment = deMaxu32(maxAlignment, alignment);
13746 	}
13747 
13748 	// The stride of all results must also be aligned,
13749 	// so results for next vertex are aligned.
13750 	return deAlign32(stride, maxAlignment);
13751 }
13752 
13753 /** Get type of <result>.
13754  *
13755  * @param result Result ordinal, starts with 0
13756  *
13757  * @return Type
13758  **/
getResultType(glw::GLuint) const13759 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13760 {
13761 	return m_res_type;
13762 }
13763 
13764 /** Constructor
13765  *
13766  * @param n_columns Number of columns
13767  * @param n_rows    Number of rows
13768  **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13769 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13770 	: m_n_columns(n_columns), m_n_rows(n_rows)
13771 {
13772 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13773 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
13774 	m_type_name				   = Utils::getVariableTypeString(type);
13775 
13776 	if (1 == m_n_columns)
13777 	{
13778 		if (1 == m_n_rows)
13779 		{
13780 			m_general_type = SCALAR;
13781 		}
13782 		else
13783 		{
13784 			m_general_type = VECTOR;
13785 		}
13786 	}
13787 	else
13788 	{
13789 		m_general_type = MATRIX;
13790 	}
13791 }
13792 
13793 /** Compare two values
13794  *
13795  * @param type  Type of values
13796  * @param left  Pointer to left value
13797  * @param right Pointer to right value
13798  *
13799  * @return true if values are equal, false otherwise
13800  **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13801 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13802 {
13803 	bool result = true;
13804 
13805 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
13806 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
13807 
13808 	switch (base_type)
13809 	{
13810 	case Utils::VARIABLE_TYPE_DOUBLE:
13811 
13812 	{
13813 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13814 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
13815 
13816 		for (glw::GLuint component = 0; component < n_components; ++component)
13817 		{
13818 			const glw::GLdouble left_value  = left_values[component];
13819 			const glw::GLdouble right_value = right_values[component];
13820 
13821 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13822 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13823 			{
13824 				result = false;
13825 				break;
13826 			}
13827 		}
13828 	}
13829 
13830 	break;
13831 
13832 	case Utils::VARIABLE_TYPE_INT:
13833 
13834 	{
13835 		const glw::GLint* left_values  = (glw::GLint*)left;
13836 		const glw::GLint* right_values = (glw::GLint*)right;
13837 
13838 		for (glw::GLuint component = 0; component < n_components; ++component)
13839 		{
13840 			const glw::GLint left_value  = left_values[component];
13841 			const glw::GLint right_value = right_values[component];
13842 
13843 			if (left_value != right_value)
13844 			{
13845 				result = false;
13846 				break;
13847 			}
13848 		}
13849 	}
13850 
13851 	break;
13852 
13853 	case Utils::VARIABLE_TYPE_UINT:
13854 
13855 	{
13856 		const glw::GLuint* left_values  = (glw::GLuint*)left;
13857 		const glw::GLuint* right_values = (glw::GLuint*)right;
13858 
13859 		for (glw::GLuint component = 0; component < n_components; ++component)
13860 		{
13861 			const glw::GLuint left_value  = left_values[component];
13862 			const glw::GLuint right_value = right_values[component];
13863 
13864 			if (left_value != right_value)
13865 			{
13866 				result = false;
13867 				break;
13868 			}
13869 		}
13870 	}
13871 
13872 	break;
13873 
13874 	default:
13875 
13876 		TCU_FAIL("Not implemented");
13877 	}
13878 
13879 	return result;
13880 }
13881 
13882 /** Create instance of function object for given function enumeration and type
13883  *
13884  * @param function Function enumeration
13885  * @param type     Type details
13886  *
13887  * @return Create object
13888  **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13889 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
13890 																			const typeDetails& type)
13891 {
13892 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13893 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13894 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13895 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13896 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13897 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13898 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13899 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13900 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13901 
13902 	const glw::GLuint			n_columns	 = type.m_n_columns;
13903 	const glw::GLuint			n_rows		  = type.m_n_rows;
13904 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13905 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13906 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
13907 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
13908 
13909 	switch (function)
13910 	{
13911 	case FUNCTION_ABS:
13912 
13913 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13914 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13915 
13916 	case FUNCTION_CEIL:
13917 
13918 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13919 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13920 
13921 	case FUNCTION_CLAMP:
13922 
13923 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13924 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
13925 													 variable_type /* arg3_type */);
13926 
13927 	case FUNCTION_CLAMP_AGAINST_SCALAR:
13928 
13929 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13930 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13931 													 scalar_type /* arg3_type */);
13932 
13933 	case FUNCTION_CROSS:
13934 
13935 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13936 			function, "cross", tcu::cross);
13937 
13938 	case FUNCTION_DETERMINANT:
13939 
13940 		switch (variable_type)
13941 		{
13942 		case Utils::VARIABLE_TYPE_DMAT2:
13943 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13944 																						 Math::determinant);
13945 		case Utils::VARIABLE_TYPE_DMAT3:
13946 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13947 																						 Math::determinant);
13948 		case Utils::VARIABLE_TYPE_DMAT4:
13949 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13950 																						 Math::determinant);
13951 		default:
13952 			TCU_FAIL("Not implemented");
13953 		}
13954 
13955 	case FUNCTION_DISTANCE:
13956 
13957 		switch (variable_type)
13958 		{
13959 		case Utils::VARIABLE_TYPE_DVEC2:
13960 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13961 				function, "distance", tcu::distance);
13962 		case Utils::VARIABLE_TYPE_DVEC3:
13963 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13964 				function, "distance", tcu::distance);
13965 		case Utils::VARIABLE_TYPE_DVEC4:
13966 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13967 				function, "distance", tcu::distance);
13968 		default:
13969 			break;
13970 		}
13971 
13972 		break;
13973 
13974 	case FUNCTION_DOT:
13975 
13976 		switch (variable_type)
13977 		{
13978 		case Utils::VARIABLE_TYPE_DVEC2:
13979 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13980 				function, "dot", tcu::dot);
13981 		case Utils::VARIABLE_TYPE_DVEC3:
13982 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13983 				function, "dot", tcu::dot);
13984 		case Utils::VARIABLE_TYPE_DVEC4:
13985 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13986 				function, "dot", tcu::dot);
13987 		default:
13988 			break;
13989 		}
13990 
13991 		break;
13992 
13993 	case FUNCTION_EQUAL:
13994 
13995 		switch (variable_type)
13996 		{
13997 		case Utils::VARIABLE_TYPE_DVEC2:
13998 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13999 				function, "equal", Math::equal);
14000 		case Utils::VARIABLE_TYPE_DVEC3:
14001 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14002 				function, "equal", Math::equal);
14003 		case Utils::VARIABLE_TYPE_DVEC4:
14004 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14005 				function, "equal", Math::equal);
14006 		default:
14007 			break;
14008 		}
14009 
14010 		break;
14011 
14012 	case FUNCTION_FACEFORWARD:
14013 
14014 		switch (variable_type)
14015 		{
14016 		case Utils::VARIABLE_TYPE_DVEC2:
14017 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14018 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14019 				function, "faceforward", tcu::faceForward);
14020 		case Utils::VARIABLE_TYPE_DVEC3:
14021 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14022 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14023 				function, "faceforward", tcu::faceForward);
14024 		case Utils::VARIABLE_TYPE_DVEC4:
14025 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14026 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14027 				function, "faceforward", tcu::faceForward);
14028 		default:
14029 			break;
14030 		}
14031 
14032 		break;
14033 
14034 	case FUNCTION_FLOOR:
14035 
14036 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14037 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14038 
14039 	case FUNCTION_FMA:
14040 
14041 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14042 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14043 													 variable_type /* arg3_type */);
14044 
14045 	case FUNCTION_FRACT:
14046 
14047 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14048 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14049 
14050 	case FUNCTION_FREXP:
14051 
14052 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14053 															  glw::GLint /* OutT */>(
14054 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14055 			int_type /* out_type */);
14056 
14057 	case FUNCTION_GREATERTHAN:
14058 
14059 		switch (variable_type)
14060 		{
14061 		case Utils::VARIABLE_TYPE_DVEC2:
14062 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14063 				function, "greaterThan", Math::greaterThan);
14064 		case Utils::VARIABLE_TYPE_DVEC3:
14065 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14066 				function, "greaterThan", Math::greaterThan);
14067 		case Utils::VARIABLE_TYPE_DVEC4:
14068 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14069 				function, "greaterThan", Math::greaterThan);
14070 		default:
14071 			break;
14072 		}
14073 
14074 		break;
14075 
14076 	case FUNCTION_GREATERTHANEQUAL:
14077 
14078 		switch (variable_type)
14079 		{
14080 		case Utils::VARIABLE_TYPE_DVEC2:
14081 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14082 				function, "greaterThanEqual", Math::greaterThanEqual);
14083 		case Utils::VARIABLE_TYPE_DVEC3:
14084 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14085 				function, "greaterThanEqual", Math::greaterThanEqual);
14086 		case Utils::VARIABLE_TYPE_DVEC4:
14087 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14088 				function, "greaterThanEqual", Math::greaterThanEqual);
14089 		default:
14090 			break;
14091 		}
14092 
14093 		break;
14094 
14095 	case FUNCTION_INVERSE:
14096 
14097 		switch (variable_type)
14098 		{
14099 		case Utils::VARIABLE_TYPE_DMAT2:
14100 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14101 		case Utils::VARIABLE_TYPE_DMAT3:
14102 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14103 		case Utils::VARIABLE_TYPE_DMAT4:
14104 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14105 		default:
14106 			break;
14107 		}
14108 
14109 		break;
14110 
14111 	case FUNCTION_INVERSESQRT:
14112 
14113 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14114 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14115 
14116 	case FUNCTION_LDEXP:
14117 
14118 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14119 													 glw::GLint /* Arg2T */>(
14120 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14121 			int_type /* arg2_type */);
14122 
14123 	case FUNCTION_LESSTHAN:
14124 
14125 		switch (variable_type)
14126 		{
14127 		case Utils::VARIABLE_TYPE_DVEC2:
14128 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14129 				function, "lessThan", Math::lessThan);
14130 		case Utils::VARIABLE_TYPE_DVEC3:
14131 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14132 				function, "lessThan", Math::lessThan);
14133 		case Utils::VARIABLE_TYPE_DVEC4:
14134 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14135 				function, "lessThan", Math::lessThan);
14136 		default:
14137 			break;
14138 		}
14139 
14140 		break;
14141 
14142 	case FUNCTION_LESSTHANEQUAL:
14143 
14144 		switch (variable_type)
14145 		{
14146 		case Utils::VARIABLE_TYPE_DVEC2:
14147 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14148 				function, "lessThanEqual", Math::lessThanEqual);
14149 		case Utils::VARIABLE_TYPE_DVEC3:
14150 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14151 				function, "lessThanEqual", Math::lessThanEqual);
14152 		case Utils::VARIABLE_TYPE_DVEC4:
14153 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14154 				function, "lessThanEqual", Math::lessThanEqual);
14155 		default:
14156 			break;
14157 		}
14158 
14159 		break;
14160 
14161 	case FUNCTION_LENGTH:
14162 
14163 		switch (variable_type)
14164 		{
14165 		case Utils::VARIABLE_TYPE_DVEC2:
14166 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14167 																							  tcu::length);
14168 		case Utils::VARIABLE_TYPE_DVEC3:
14169 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14170 																							  tcu::length);
14171 		case Utils::VARIABLE_TYPE_DVEC4:
14172 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14173 																							  tcu::length);
14174 		default:
14175 			break;
14176 		}
14177 
14178 		break;
14179 
14180 	case FUNCTION_MATRIXCOMPMULT:
14181 
14182 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14183 													 glw::GLdouble /* Arg2T */>(
14184 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14185 			variable_type /* arg2_type */);
14186 
14187 	case FUNCTION_MAX:
14188 
14189 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14190 													 glw::GLdouble /* Arg2T */>(
14191 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14192 			variable_type /* arg2_type */);
14193 
14194 	case FUNCTION_MAX_AGAINST_SCALAR:
14195 
14196 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14197 													 glw::GLdouble /* Arg2T */>(
14198 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14199 			scalar_type /* arg2_type */);
14200 
14201 	case FUNCTION_MIN:
14202 
14203 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14204 													 glw::GLdouble /* Arg2T */>(
14205 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14206 			variable_type /* arg2_type */);
14207 
14208 	case FUNCTION_MIN_AGAINST_SCALAR:
14209 
14210 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14211 													 glw::GLdouble /* Arg2T */>(
14212 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14213 			scalar_type /* arg2_type */);
14214 
14215 	case FUNCTION_MIX:
14216 
14217 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14218 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
14219 													 variable_type /* arg3_type */);
14220 
14221 	case FUNCTION_MOD:
14222 
14223 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14224 													 glw::GLdouble /* Arg2T */>(
14225 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14226 			variable_type /* arg2_type */);
14227 
14228 	case FUNCTION_MOD_AGAINST_SCALAR:
14229 
14230 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14231 													 glw::GLdouble /* Arg2T */>(
14232 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14233 			scalar_type /* arg2_type */);
14234 
14235 	case FUNCTION_MODF:
14236 
14237 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14238 															  glw::GLdouble /* OutT */>(
14239 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14240 			variable_type /* out_type */);
14241 
14242 	case FUNCTION_NORMALIZE:
14243 
14244 		switch (variable_type)
14245 		{
14246 		case Utils::VARIABLE_TYPE_DVEC2:
14247 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14248 																						   tcu::normalize);
14249 		case Utils::VARIABLE_TYPE_DVEC3:
14250 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14251 																						   tcu::normalize);
14252 		case Utils::VARIABLE_TYPE_DVEC4:
14253 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14254 																						   tcu::normalize);
14255 		default:
14256 			break;
14257 		}
14258 
14259 		break;
14260 
14261 	case FUNCTION_NOTEQUAL:
14262 
14263 		switch (variable_type)
14264 		{
14265 		case Utils::VARIABLE_TYPE_DVEC2:
14266 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14267 				function, "notEqual", Math::notEqual);
14268 		case Utils::VARIABLE_TYPE_DVEC3:
14269 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14270 				function, "notEqual", Math::notEqual);
14271 		case Utils::VARIABLE_TYPE_DVEC4:
14272 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14273 				function, "notEqual", Math::notEqual);
14274 		default:
14275 			break;
14276 		}
14277 
14278 		break;
14279 
14280 	case FUNCTION_OUTERPRODUCT:
14281 
14282 		switch (variable_type)
14283 		{
14284 		case Utils::VARIABLE_TYPE_DMAT2:
14285 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14286 				function, "outerProduct", Math::outerProduct);
14287 		case Utils::VARIABLE_TYPE_DMAT2X3:
14288 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14289 				function, "outerProduct", Math::outerProduct);
14290 		case Utils::VARIABLE_TYPE_DMAT2X4:
14291 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 				function, "outerProduct", Math::outerProduct);
14293 		case Utils::VARIABLE_TYPE_DMAT3:
14294 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14295 				function, "outerProduct", Math::outerProduct);
14296 		case Utils::VARIABLE_TYPE_DMAT3X2:
14297 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14298 				function, "outerProduct", Math::outerProduct);
14299 		case Utils::VARIABLE_TYPE_DMAT3X4:
14300 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 				function, "outerProduct", Math::outerProduct);
14302 		case Utils::VARIABLE_TYPE_DMAT4:
14303 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14304 				function, "outerProduct", Math::outerProduct);
14305 		case Utils::VARIABLE_TYPE_DMAT4X2:
14306 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14307 				function, "outerProduct", Math::outerProduct);
14308 		case Utils::VARIABLE_TYPE_DMAT4X3:
14309 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 				function, "outerProduct", Math::outerProduct);
14311 		default:
14312 			break;
14313 		}
14314 
14315 		break;
14316 
14317 	case FUNCTION_PACKDOUBLE2X32:
14318 
14319 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14320 																						  Math::packDouble2x32);
14321 
14322 	case FUNCTION_REFLECT:
14323 
14324 		switch (variable_type)
14325 		{
14326 		case Utils::VARIABLE_TYPE_DVEC2:
14327 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14328 				function, "reflect", tcu::reflect);
14329 		case Utils::VARIABLE_TYPE_DVEC3:
14330 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14331 				function, "reflect", tcu::reflect);
14332 		case Utils::VARIABLE_TYPE_DVEC4:
14333 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14334 				function, "reflect", tcu::reflect);
14335 		default:
14336 			break;
14337 		}
14338 
14339 		break;
14340 
14341 	case FUNCTION_REFRACT:
14342 
14343 		switch (variable_type)
14344 		{
14345 		case Utils::VARIABLE_TYPE_DVEC2:
14346 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14347 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14348 				function, "refract", tcu::refract);
14349 		case Utils::VARIABLE_TYPE_DVEC3:
14350 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14351 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14352 				function, "refract", tcu::refract);
14353 		case Utils::VARIABLE_TYPE_DVEC4:
14354 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14355 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14356 				function, "refract", tcu::refract);
14357 		default:
14358 			break;
14359 		}
14360 
14361 		break;
14362 
14363 	case FUNCTION_ROUND:
14364 
14365 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14366 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14367 
14368 	case FUNCTION_ROUNDEVEN:
14369 
14370 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14371 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14372 
14373 	case FUNCTION_SIGN:
14374 
14375 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14376 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14377 
14378 	case FUNCTION_SMOOTHSTEP:
14379 
14380 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14381 													 variable_type /* res_type  */, variable_type /* arg1_type */,
14382 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
14383 
14384 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14385 
14386 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14387 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
14388 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14389 
14390 	case FUNCTION_SQRT:
14391 
14392 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14393 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14394 
14395 	case FUNCTION_STEP:
14396 
14397 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14398 													 glw::GLdouble /* Arg2T */>(
14399 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14400 			variable_type /* arg2_type */);
14401 
14402 	case FUNCTION_STEP_AGAINST_SCALAR:
14403 
14404 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14405 													 glw::GLdouble /* Arg2T */>(
14406 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14407 			variable_type /* arg2_type */);
14408 
14409 	case FUNCTION_TRANSPOSE:
14410 
14411 		switch (variable_type)
14412 		{
14413 		case Utils::VARIABLE_TYPE_DMAT2:
14414 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14415 																				 Math::transpose);
14416 		case Utils::VARIABLE_TYPE_DMAT2X3:
14417 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14418 																					 Math::transpose);
14419 		case Utils::VARIABLE_TYPE_DMAT2X4:
14420 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14421 																					 Math::transpose);
14422 		case Utils::VARIABLE_TYPE_DMAT3:
14423 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14424 																				 Math::transpose);
14425 		case Utils::VARIABLE_TYPE_DMAT3X2:
14426 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14427 																					 Math::transpose);
14428 		case Utils::VARIABLE_TYPE_DMAT3X4:
14429 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14430 																					 Math::transpose);
14431 		case Utils::VARIABLE_TYPE_DMAT4:
14432 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14433 																				 Math::transpose);
14434 		case Utils::VARIABLE_TYPE_DMAT4X2:
14435 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14436 																					 Math::transpose);
14437 		case Utils::VARIABLE_TYPE_DMAT4X3:
14438 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14439 																					 Math::transpose);
14440 		default:
14441 			break;
14442 		}
14443 
14444 		break;
14445 
14446 	case FUNCTION_TRUNC:
14447 
14448 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14449 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14450 
14451 	case FUNCTION_UNPACKDOUBLE2X32:
14452 
14453 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14454 																						  Math::unpackDouble2x32);
14455 
14456 	case FUNCTION_ISNAN:
14457 
14458 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14459 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14460 
14461 	case FUNCTION_ISINF:
14462 
14463 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14464 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14465 
14466 	default:
14467 		TCU_FAIL("Not implemented");
14468 		return 0;
14469 	}
14470 
14471 	TCU_FAIL("Not implemented");
14472 	return 0;
14473 }
14474 
14475 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14476  *
14477  * @param argument        Argument index
14478  * @param function_object Function object
14479  *
14480  * @return Function pointer
14481  **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14482 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14483 	glw::GLuint argument, const functionObject& function_object) const
14484 {
14485 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14486 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14487 
14488 	switch (argument_type)
14489 	{
14490 	case Utils::VARIABLE_TYPE_DMAT2:
14491 		return gl.uniformMatrix2dv;
14492 	case Utils::VARIABLE_TYPE_DMAT2X3:
14493 		return gl.uniformMatrix2x3dv;
14494 	case Utils::VARIABLE_TYPE_DMAT2X4:
14495 		return gl.uniformMatrix2x4dv;
14496 	case Utils::VARIABLE_TYPE_DMAT3:
14497 		return gl.uniformMatrix3dv;
14498 	case Utils::VARIABLE_TYPE_DMAT3X2:
14499 		return gl.uniformMatrix3x2dv;
14500 	case Utils::VARIABLE_TYPE_DMAT3X4:
14501 		return gl.uniformMatrix3x4dv;
14502 	case Utils::VARIABLE_TYPE_DMAT4:
14503 		return gl.uniformMatrix4dv;
14504 	case Utils::VARIABLE_TYPE_DMAT4X2:
14505 		return gl.uniformMatrix4x2dv;
14506 	case Utils::VARIABLE_TYPE_DMAT4X3:
14507 		return gl.uniformMatrix4x3dv;
14508 	default:
14509 		break;
14510 	}
14511 
14512 	TCU_FAIL("Not implemented");
14513 	return 0;
14514 }
14515 
14516 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14517  *
14518  * @param argument        Argument index
14519  * @param function_object Function object
14520  *
14521  * @return Function pointer
14522  **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14523 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14524 	glw::GLuint argument, const functionObject& function_object) const
14525 {
14526 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14527 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14528 
14529 	switch (argument_type)
14530 	{
14531 	case Utils::VARIABLE_TYPE_DOUBLE:
14532 		return gl.uniform1dv;
14533 	case Utils::VARIABLE_TYPE_DVEC2:
14534 		return gl.uniform2dv;
14535 	case Utils::VARIABLE_TYPE_DVEC3:
14536 		return gl.uniform3dv;
14537 	case Utils::VARIABLE_TYPE_DVEC4:
14538 		return gl.uniform4dv;
14539 	default:
14540 		TCU_FAIL("Not implemented");
14541 	}
14542 
14543 	return 0;
14544 }
14545 
14546 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14547  *
14548  * @param argument        Argument index
14549  * @param function_object Function object
14550  *
14551  * @return Function pointer
14552  **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14553 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14554 	glw::GLuint argument, const functionObject& function_object) const
14555 {
14556 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14557 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14558 
14559 	switch (argument_type)
14560 	{
14561 	case Utils::VARIABLE_TYPE_INT:
14562 		return gl.uniform1iv;
14563 	case Utils::VARIABLE_TYPE_IVEC2:
14564 		return gl.uniform2iv;
14565 	case Utils::VARIABLE_TYPE_IVEC3:
14566 		return gl.uniform3iv;
14567 	case Utils::VARIABLE_TYPE_IVEC4:
14568 		return gl.uniform4iv;
14569 	default:
14570 		TCU_FAIL("Not implemented");
14571 	}
14572 
14573 	return 0;
14574 }
14575 
14576 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14577  *
14578  * @param argument        Argument index
14579  * @param function_object Function object
14580  *
14581  * @return Function pointer
14582  **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14583 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14584 	glw::GLuint argument, const functionObject& function_object) const
14585 {
14586 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14587 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
14588 
14589 	switch (argument_type)
14590 	{
14591 	case Utils::VARIABLE_TYPE_UVEC2:
14592 		return gl.uniform2uiv;
14593 	default:
14594 		TCU_FAIL("Not implemented");
14595 	}
14596 
14597 	return 0;
14598 }
14599 
14600 /** Get name of uniform that will be used as <argument>.
14601  *
14602  * @param argument Argument index
14603  *
14604  * @return Name of uniform
14605  **/
getUniformName(glw::GLuint argument) const14606 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14607 {
14608 	switch (argument)
14609 	{
14610 	case 0:
14611 		return "uniform_0";
14612 	case 1:
14613 		return "uniform_1";
14614 	case 2:
14615 		return "uniform_2";
14616 	default:
14617 		TCU_FAIL("Not implemented");
14618 		return 0;
14619 	}
14620 }
14621 
14622 /** Get name of varying that will be used as <result>.
14623  *
14624  * @param result Result index
14625  *
14626  * @return Name of varying
14627  **/
getVaryingName(glw::GLuint result) const14628 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14629 {
14630 	switch (result)
14631 	{
14632 	case 0:
14633 		return "result_0";
14634 	case 1:
14635 		return "result_1";
14636 	case 2:
14637 		return "result_2";
14638 	default:
14639 		TCU_FAIL("Not implemented");
14640 		return 0;
14641 	}
14642 }
14643 
14644 /** Check if given combination of function and type is implemented
14645  *
14646  * @param function Function enumeration
14647  * @param type     Type details
14648  *
14649  * @return true if function is available for given type, false otherwise
14650  **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14651 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14652 {
14653 	static const bool look_up_table[][3] = {
14654 		/* SCALAR, VECTOR, MATRIX */
14655 		/* FUNCTION_ABS:                       */ { true, true, false },
14656 		/* FUNCTION_CEIL:                      */ { true, true, false },
14657 		/* FUNCTION_CLAMP:                     */ { true, true, false },
14658 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14659 		/* FUNCTION_CROSS:                     */ { false, true, false },
14660 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
14661 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
14662 		/* FUNCTION_DOT:                       */ { false, true, false },
14663 		/* FUNCTION_EQUAL:                     */ { false, true, false },
14664 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
14665 		/* FUNCTION_FLOOR:                     */ { true, true, false },
14666 		/* FUNCTION_FMA:                       */ { true, true, false },
14667 		/* FUNCTION_FRACT:                     */ { true, true, false },
14668 		/* FUNCTION_FREXP:                     */ { true, true, false },
14669 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
14670 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14671 		/* FUNCTION_INVERSE:                   */ { false, false, true },
14672 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
14673 		/* FUNCTION_LDEXP:                     */ { true, true, false },
14674 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
14675 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14676 		/* FUNCTION_LENGTH:                    */ { false, true, false },
14677 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14678 		/* FUNCTION_MAX:                       */ { true, true, false },
14679 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14680 		/* FUNCTION_MIN:                       */ { true, true, false },
14681 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14682 		/* FUNCTION_MIX:                       */ { true, true, false },
14683 		/* FUNCTION_MOD:                       */ { true, true, false },
14684 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14685 		/* FUNCTION_MODF:                      */ { true, true, false },
14686 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
14687 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14688 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14689 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14690 		/* FUNCTION_REFLECT:                   */ { false, true, false },
14691 		/* FUNCTION_REFRACT:                   */ { false, true, false },
14692 		/* FUNCTION_ROUND:                     */ { true, true, false },
14693 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14694 		/* FUNCTION_SIGN:                      */ { true, false, false },
14695 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14696 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14697 		/* FUNCTION_SQRT:                      */ { true, true, false },
14698 		/* FUNCTION_STEP:                      */ { true, true, false },
14699 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14700 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14701 		/* FUNCTION_TRUNC:                     */ { true, true, false },
14702 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14703 		/* FUNCTION_ISNAN:                     */ { true, true, false },
14704 		/* FUNCTION_ISINF:                     */ { true, true, false },
14705 	};
14706 
14707 	bool result = look_up_table[function][type.m_general_type];
14708 
14709 	if (true == result)
14710 	{
14711 		switch (function)
14712 		{
14713 		case FUNCTION_CROSS: /* Only 3 element vectors */
14714 			result = (3 == type.m_n_rows);
14715 			break;
14716 		case FUNCTION_DETERMINANT: /* Only square matrices */
14717 		case FUNCTION_INVERSE:
14718 			result = (type.m_n_columns == type.m_n_rows);
14719 			break;
14720 		default:
14721 			break;
14722 		}
14723 	}
14724 
14725 	return result;
14726 }
14727 
14728 /** Logs variable of given type: name (type) [values]
14729  *
14730  * @param buffer Source of data
14731  * @param name   Name of variable
14732  * @param type   Type of variable
14733  **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14734 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14735 										  Utils::_variable_type type) const
14736 {
14737 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
14738 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
14739 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14740 
14741 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14742 
14743 	for (glw::GLuint component = 0; component < n_components; ++component)
14744 	{
14745 		if (0 != component)
14746 		{
14747 			message << ", ";
14748 		}
14749 
14750 		switch (base_type)
14751 		{
14752 		case Utils::VARIABLE_TYPE_DOUBLE:
14753 			message << ((glw::GLdouble*)buffer)[component];
14754 			break;
14755 		case Utils::VARIABLE_TYPE_INT:
14756 			message << ((glw::GLint*)buffer)[component];
14757 			break;
14758 		case Utils::VARIABLE_TYPE_UINT:
14759 			message << ((glw::GLuint*)buffer)[component];
14760 			break;
14761 		default:
14762 			TCU_FAIL("Not implemented");
14763 		}
14764 	}
14765 
14766 	message << "]" << tcu::TestLog::EndMessage;
14767 }
14768 
14769 /** Prepare input arguments, data are stored in <buffer>
14770  *
14771  * @param function_object Function object
14772  * @param vertex          Vertex index
14773  * @param buffer          Buffer pointer
14774  **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14775 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14776 										  glw::GLubyte* buffer)
14777 {
14778 	const glw::GLuint n_arguments = function_object.getArgumentCount();
14779 
14780 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14781 	{
14782 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
14783 
14784 		prepareComponents(function_object, vertex, argument, buffer + offset);
14785 	}
14786 }
14787 
14788 /** Prepare components for given <function_object>, <vertex> and <argument>
14789  *
14790  * @param function_object Function object
14791  * @param vertex          Vertex index
14792  * @param argument        Argument index
14793  * @param buffer          Buffer pointer
14794  **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14795 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14796 											glw::GLuint argument, glw::GLubyte* buffer)
14797 {
14798 	glw::GLuint					argument_index[3]		 = { 0 };
14799 	glw::GLuint					argument_reset[3]		 = { 0 };
14800 	glw::GLuint					argument_step[3]		 = { 0 };
14801 	glw::GLdouble				double_argument_start[3] = { 0.0 };
14802 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14803 	glw::GLuint					int_argument_start  = -4;
14804 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
14805 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
14806 	glw::GLuint					uint_argument_start = 0;
14807 
14808 	switch (n_arguments)
14809 	{
14810 	case 1:
14811 		argument_step[0]		 = 1;
14812 		argument_reset[0]		 = 1024;
14813 		double_argument_start[0] = -511.5;
14814 		break;
14815 	case 2:
14816 		argument_step[0]		 = 32;
14817 		argument_step[1]		 = 1;
14818 		argument_reset[0]		 = 32;
14819 		argument_reset[1]		 = 32;
14820 		double_argument_start[0] = -15.5;
14821 		double_argument_start[1] = -15.5;
14822 		break;
14823 	case 3:
14824 		argument_step[0]		 = 64;
14825 		argument_step[1]		 = 8;
14826 		argument_step[2]		 = 1;
14827 		argument_reset[0]		 = 16;
14828 		argument_reset[1]		 = 8;
14829 		argument_reset[2]		 = 8;
14830 		double_argument_start[0] = -7.5;
14831 		double_argument_start[1] = -3.5;
14832 		double_argument_start[2] = -3.5;
14833 		break;
14834 	default:
14835 		TCU_FAIL("Not implemented");
14836 		return;
14837 	}
14838 
14839 	switch (function_object.getFunctionEnum())
14840 	{
14841 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14842 	case FUNCTION_CLAMP_AGAINST_SCALAR:
14843 		double_argument_start[2] = 4.5;
14844 		break;
14845 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14846 		double_argument_start[0] = 16.5;
14847 		break;
14848 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14849 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14850 		argument_step[0]		 = 1;
14851 		argument_step[1]		 = 8;
14852 		argument_step[2]		 = 64;
14853 		argument_reset[0]		 = 8;
14854 		argument_reset[1]		 = 8;
14855 		argument_reset[2]		 = 16;
14856 		double_argument_start[0] = -3.5;
14857 		double_argument_start[1] = 4.5;
14858 		double_argument_start[2] = -7.5;
14859 		break;
14860 	default:
14861 		break;
14862 	}
14863 
14864 	for (glw::GLuint i = 0; i < n_arguments; ++i)
14865 	{
14866 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14867 	}
14868 
14869 	switch (base_arg_type)
14870 	{
14871 	case Utils::VARIABLE_TYPE_DOUBLE:
14872 	{
14873 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14874 
14875 		double_argument_start[argument] += argument_index[argument];
14876 
14877 		for (glw::GLuint component = 0; component < n_components; ++component)
14878 		{
14879 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14880 
14881 			switch (function_object.getFunctionEnum())
14882 			{
14883 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14884 				if (0.5 == Math::fract(value))
14885 				{
14886 					value += 0.01;
14887 				}
14888 				break;
14889 			default:
14890 				break;
14891 			}
14892 
14893 			argument_dst[component] = value;
14894 		}
14895 	}
14896 	break;
14897 	case Utils::VARIABLE_TYPE_INT:
14898 	{
14899 		glw::GLint* argument_dst = (glw::GLint*)buffer;
14900 
14901 		uint_argument_start += argument_index[argument];
14902 
14903 		for (glw::GLuint component = 0; component < n_components; ++component)
14904 		{
14905 			const glw::GLint value = int_argument_start + component;
14906 
14907 			argument_dst[component] = value;
14908 		}
14909 	}
14910 	break;
14911 	case Utils::VARIABLE_TYPE_UINT:
14912 	{
14913 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14914 
14915 		uint_argument_start += argument_index[argument];
14916 
14917 		for (glw::GLuint component = 0; component < n_components; ++component)
14918 		{
14919 			const glw::GLuint value = uint_argument_start + component;
14920 
14921 			argument_dst[component] = value;
14922 		}
14923 	}
14924 	break;
14925 	default:
14926 		TCU_FAIL("Not implemented");
14927 		return;
14928 	}
14929 }
14930 
14931 /** Prepare programInfo for given functionObject
14932  *
14933  * @param function_object  Function object
14934  * @param out_program_info Program info
14935  **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14936 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14937 {
14938 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
14939 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14940 
14941 	prepareVertexShaderCode(function_object);
14942 
14943 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14944 						   varying_names, n_varying_names);
14945 }
14946 
14947 /** Prepare input data and expected results for given function object
14948  *
14949  * @param function_object Function object
14950  **/
prepareTestData(const functionObject & function_object)14951 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14952 {
14953 	const glw::GLuint result_stride		   = function_object.getResultStride();
14954 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
14955 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
14956 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14957 
14958 	m_argument_data.clear();
14959 	m_expected_results_data.clear();
14960 
14961 	m_argument_data.resize(argument_buffer_size);
14962 	m_expected_results_data.resize(result_buffer_size);
14963 
14964 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14965 	{
14966 		const glw::GLuint result_offset   = vertex * result_stride;
14967 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
14968 		const glw::GLuint argument_offset = vertex * argument_stride;
14969 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
14970 
14971 		prepareArgument(function_object, vertex, argument_dst);
14972 		function_object.call(result_dst, argument_dst);
14973 	}
14974 }
14975 
14976 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14977  *
14978  * @param function_object Function object
14979  **/
prepareVertexShaderCode(const functionObject & function_object)14980 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14981 {
14982 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
14983 													 "\n"
14984 													 "precision highp float;\n"
14985 													 "\n"
14986 													 "ARGUMENT_DEFINITION"
14987 													 "\n"
14988 													 "RESULT_DEFINITION"
14989 													 "\n"
14990 													 "void main()\n"
14991 													 "{\n"
14992 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14993 													 "}\n"
14994 													 "\n";
14995 
14996 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
14997 	static const glw::GLchar* argument_token			= "ARGUMENT";
14998 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
14999 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15000 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
15001 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
15002 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
15003 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
15004 
15005 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15006 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
15007 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
15008 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15009 
15010 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15011 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
15012 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
15013 	const glw::GLuint n_results					 = function_object.getResultCount();
15014 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15015 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
15016 
15017 	size_t		search_position = 0;
15018 	std::string string			= shader_template_code;
15019 
15020 	/* Replace ARGUMENT_DEFINITION with definitions */
15021 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15022 	{
15023 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15024 		const glw::GLchar*	uniform_name  = getUniformName(argument);
15025 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
15026 
15027 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15028 
15029 		search_position -= argument_definition_length;
15030 
15031 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15032 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15033 	}
15034 
15035 	/* Remove ARGUMENT_DEFINITION */
15036 	Utils::replaceToken(argument_definition_token, search_position, "", string);
15037 
15038 	/* Replace RESULT_DEFINITION with definitions */
15039 	for (glw::GLuint result = 0; result < n_results; ++result)
15040 	{
15041 		Utils::_variable_type variable_type = function_object.getResultType(result);
15042 		const glw::GLchar*	varying_name  = getVaryingName(result);
15043 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
15044 
15045 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15046 
15047 		search_position -= result_definition_length;
15048 
15049 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15050 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
15051 	}
15052 
15053 	/* Remove RESULT_DEFINITION */
15054 	Utils::replaceToken(result_definition_token, search_position, "", string);
15055 
15056 	/* Replace RESULT_NAME */
15057 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15058 
15059 	/* Replace RESULT_TYPE */
15060 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15061 
15062 	/* Replace FUNCTION_NAME */
15063 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15064 
15065 	/* Replace ARGUMENT with list of arguments */
15066 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15067 	{
15068 		const glw::GLchar* uniform_name = getUniformName(argument);
15069 
15070 		if (0 == argument)
15071 		{
15072 			Utils::replaceToken(argument_token, search_position, first_argument, string);
15073 		}
15074 		else
15075 		{
15076 			Utils::replaceToken(argument_token, search_position, argument_str, string);
15077 		}
15078 
15079 		search_position -= first_argument_length;
15080 
15081 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15082 	}
15083 
15084 	for (glw::GLuint result = 1; result < n_results; ++result)
15085 	{
15086 		const glw::GLchar* varying_name = getVaryingName(result);
15087 
15088 		Utils::replaceToken(argument_token, search_position, argument_str, string);
15089 
15090 		search_position -= first_argument_length;
15091 
15092 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15093 	}
15094 
15095 	/* Remove ARGUMENT */
15096 	Utils::replaceToken(argument_token, search_position, "", string);
15097 
15098 	m_vertex_shader_code = string;
15099 }
15100 
15101 /** Test single function with one type
15102  *
15103  * param function Function enumeration
15104  * param type     Type details
15105  *
15106  * @return true if test pass (or function is not available for <type>), false otherwise
15107  **/
test(FunctionEnum function,const typeDetails & type)15108 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15109 {
15110 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15111 
15112 	/* Skip if function is not implemented for type */
15113 	if (false == isFunctionImplemented(function, type))
15114 	{
15115 		return true;
15116 	}
15117 
15118 	Utils::programInfo			  program(m_context);
15119 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15120 
15121 	prepareProgram(*function_object, program);
15122 	prepareTestData(*function_object);
15123 
15124 	/* Set up program */
15125 	gl.useProgram(program.m_program_object_id);
15126 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15127 
15128 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15129 	{
15130 		testBegin(*function_object, program.m_program_object_id, vertex);
15131 
15132 		gl.beginTransformFeedback(GL_POINTS);
15133 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15134 
15135 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15136 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15137 
15138 		gl.endTransformFeedback();
15139 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15140 
15141 		if (false == verifyResults(*function_object, vertex))
15142 		{
15143 			return false;
15144 		}
15145 	}
15146 
15147 	return true;
15148 }
15149 
15150 /** Update transform feedback buffer and uniforms
15151  *
15152  * @param function_object Function object
15153  * @param program_id      Program object id
15154  * @param vertex          Vertex index
15155  **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15156 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15157 {
15158 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
15159 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
15160 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
15161 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
15162 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
15163 
15164 	/* Update transform feedback buffer */
15165 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
15166 	transform_feedback_buffer_data.resize(result_buffer_size);
15167 
15168 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15169 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15170 
15171 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15172 				  GL_DYNAMIC_COPY);
15173 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15174 
15175 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15176 					   result_buffer_size);
15177 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15178 
15179 	/* Update VAO */
15180 	gl.bindVertexArray(m_vertex_array_object_id);
15181 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15182 
15183 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15184 	{
15185 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
15186 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
15187 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
15188 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
15189 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
15190 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15191 
15192 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15193 
15194 		if (-1 == uniform_location)
15195 		{
15196 			TCU_FAIL("Inactive uniform");
15197 		}
15198 
15199 		if (1 == n_columns)
15200 		{
15201 			switch (Utils::getBaseVariableType(argument_type))
15202 			{
15203 			case Utils::VARIABLE_TYPE_DOUBLE:
15204 			{
15205 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15206 
15207 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15208 			}
15209 			break;
15210 			case Utils::VARIABLE_TYPE_UINT:
15211 			{
15212 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15213 
15214 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15215 			}
15216 			break;
15217 			case Utils::VARIABLE_TYPE_INT:
15218 			{
15219 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15220 
15221 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15222 			}
15223 			break;
15224 			default:
15225 				TCU_FAIL("Not implemented");
15226 			}
15227 		}
15228 		else
15229 		{
15230 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15231 
15232 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15233 		}
15234 	}
15235 }
15236 
15237 /** Init GL obejcts
15238  *
15239  **/
testInit()15240 void BuiltinFunctionTest::testInit()
15241 {
15242 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15243 
15244 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
15245 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15246 
15247 	gl.genVertexArrays(1, &m_vertex_array_object_id);
15248 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15249 
15250 	gl.enable(GL_RASTERIZER_DISCARD);
15251 }
15252 
15253 /** Checks if function result is an acceptable edge case
15254  *
15255  * @param function_object Function object
15256  * @param vertex          Vertex index
15257  *
15258  * @return true if all results are as expected, false otherwise
15259  **/
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)15260 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15261 										   const Utils::_variable_type result_type,
15262 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15263 {
15264 	FunctionEnum function_type = function_object.getFunctionEnum();
15265 	switch (function_type)
15266 	{
15267 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15268 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15269 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15270 	case FUNCTION_MOD:
15271 	case FUNCTION_MOD_AGAINST_SCALAR:
15272 	{
15273 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
15274 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
15275 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
15276 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
15277 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
15278 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
15279 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
15280 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
15281 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15282 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15283 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15284 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
15285 		bool				 edge_case_present = false;
15286 		bool				 recheck		   = false;
15287 
15288 		// verify if there is a mod(a, a) case and prepare new expected result
15289 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15290 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15291 		for (glw::GLuint component = 0; component < n_components; ++component)
15292 		{
15293 			glw::GLdouble expected_result_component = expected_result[component];
15294 			glw::GLdouble actual_result_component   = actual_result[component];
15295 			glw::GLdouble argument_1_component		= argument_1[component];
15296 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15297 
15298 			// if coresponding components of arguments are equal and if component of first argument
15299 			// and component of result are equal then expected result must be corrected
15300                         bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15301                                                                       round(argument_1_component / argument_2_component));
15302                         edge_case_present = possible_edge_case &&
15303                                             (m_epsilon > de::abs(argument_2_component - actual_result_component));
15304 			recheck |= edge_case_present;
15305                         corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15306 		}
15307 
15308 		// recheck test result with corrected expected result
15309 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15310 	}
15311 	default:
15312 		return false;
15313 	}
15314 }
15315 
15316 /** Compare contents of transform feedback buffer with expected results
15317  *
15318  * @param function_object Function object
15319  * @param vertex          Vertex index
15320  *
15321  * @return true if all results are as expected, false otherwise
15322  **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15323 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15324 {
15325 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
15326 	bool				  test_result	  = true;
15327 	const glw::GLuint	 n_results		   = function_object.getResultCount();
15328 	const glw::GLuint	 results_stride   = function_object.getResultStride();
15329 	const glw::GLuint	 results_offset   = vertex * results_stride;
15330 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15331 
15332 	/* Get transform feedback data */
15333 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15334 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15335 
15336 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15337 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15338 
15339 	for (glw::GLuint result = 0; result < n_results; ++result)
15340 	{
15341 		const Utils::_variable_type result_type   = function_object.getResultType(result);
15342 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
15343 
15344 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
15345 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
15346 
15347 		if (compare(result_type, expected_result_src, result_src))
15348 			continue;
15349 
15350 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15351 		{
15352 			test_result = false;
15353 			break;
15354 		}
15355 	}
15356 
15357 	/* Unmap transform feedback buffer */
15358 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15359 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15360 
15361 	if (false == test_result)
15362 	{
15363 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
15364 		const glw::GLuint arguments_offset = vertex * argument_stride;
15365 
15366 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15367 											<< tcu::TestLog::EndMessage;
15368 
15369 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15370 											<< tcu::TestLog::EndMessage;
15371 
15372 		for (glw::GLuint result = 0; result < n_results; ++result)
15373 		{
15374 			const Utils::_variable_type result_type   = function_object.getResultType(result);
15375 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
15376 
15377 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
15378 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
15379 
15380 			logVariableType(result_src, "Result", result_type);
15381 			logVariableType(expected_result_src, "Expected result", result_type);
15382 		}
15383 
15384 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15385 		{
15386 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15387 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
15388 
15389 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15390 		}
15391 
15392 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15393 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
15394 	}
15395 
15396 	return test_result;
15397 }
15398 
15399 /** Constructor.
15400  *
15401  *  @param context Rendering context.
15402  **/
GPUShaderFP64Tests(deqp::Context & context)15403 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15404 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15405 {
15406 	/* Left blank on purpose */
15407 }
15408 
15409 /** Initializes a texture_storage_multisample test group.
15410  *
15411  **/
init(void)15412 void GPUShaderFP64Tests::init(void)
15413 {
15414 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15415 	fp64->addChild(new GPUShaderFP64Test1(m_context));
15416 	fp64->addChild(new GPUShaderFP64Test2(m_context));
15417 	fp64->addChild(new GPUShaderFP64Test3(m_context));
15418 	fp64->addChild(new GPUShaderFP64Test4(m_context));
15419 	fp64->addChild(new GPUShaderFP64Test5(m_context));
15420 	fp64->addChild(new GPUShaderFP64Test6(m_context));
15421 	fp64->addChild(new GPUShaderFP64Test7(m_context));
15422 	fp64->addChild(new GPUShaderFP64Test8(m_context));
15423 	fp64->addChild(new GPUShaderFP64Test9(m_context));
15424 	addChild(fp64);
15425 
15426 	TypeDefinition typeDefinition[] =
15427 	{
15428 		{ "double",  1, 1 },
15429 		{ "dvec2",   1, 2 },
15430 		{ "dvec3",   1, 3 },
15431 		{ "dvec4",   1, 4 },
15432 		{ "dmat2",   2, 2 },
15433 		{ "dmat2x3", 2, 3 },
15434 		{ "dmat2x4", 2, 4 },
15435 		{ "dmat3x2", 3, 2 },
15436 		{ "dmat3",   3, 3 },
15437 		{ "dmat3x4", 3, 4 },
15438 		{ "dmat4x2", 4, 2 },
15439 		{ "dmat4x3", 4, 3 },
15440 		{ "dmat4",   4, 4 }
15441 	};
15442 
15443 	struct BuiltinFunctions
15444 	{
15445 		std::string  name;
15446 		FunctionEnum function;
15447 	} builtinFunctions[] = {
15448 		{ "abs",						FUNCTION_ABS },
15449 		{ "ceil",						FUNCTION_CEIL },
15450 		{ "clamp",						FUNCTION_CLAMP },
15451 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
15452 		{ "cross",						FUNCTION_CROSS },
15453 		{ "determinant",				FUNCTION_DETERMINANT },
15454 		{ "distance",					FUNCTION_DISTANCE },
15455 		{ "dot",						FUNCTION_DOT },
15456 		{ "equal",						FUNCTION_EQUAL },
15457 		{ "faceforward",				FUNCTION_FACEFORWARD },
15458 		{ "floor",						FUNCTION_FLOOR },
15459 		{ "fma",						FUNCTION_FMA },
15460 		{ "fract",						FUNCTION_FRACT },
15461 		{ "frexp",						FUNCTION_FREXP },
15462 		{ "greaterthan",				FUNCTION_GREATERTHAN },
15463 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
15464 		{ "inverse",					FUNCTION_INVERSE },
15465 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
15466 		{ "ldexp",						FUNCTION_LDEXP },
15467 		{ "lessthan",					FUNCTION_LESSTHAN },
15468 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
15469 		{ "length",						FUNCTION_LENGTH },
15470 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
15471 		{ "max",						FUNCTION_MAX },
15472 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
15473 		{ "min",						FUNCTION_MIN },
15474 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
15475 		{ "mix",						FUNCTION_MIX },
15476 		{ "mod",						FUNCTION_MOD },
15477 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
15478 		{ "modf",						FUNCTION_MODF },
15479 		{ "normalize",					FUNCTION_NORMALIZE },
15480 		{ "notequal",					FUNCTION_NOTEQUAL },
15481 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
15482 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
15483 		{ "reflect",					FUNCTION_REFLECT },
15484 		{ "refract",					FUNCTION_REFRACT },
15485 		{ "round",						FUNCTION_ROUND },
15486 		{ "roundeven",					FUNCTION_ROUNDEVEN },
15487 		{ "sign",						FUNCTION_SIGN },
15488 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
15489 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15490 		{ "sqrt",						FUNCTION_SQRT },
15491 		{ "step",						FUNCTION_STEP },
15492 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
15493 		{ "transpose",					FUNCTION_TRANSPOSE },
15494 		{ "trunc",						FUNCTION_TRUNC },
15495 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
15496 		{ "isnan",						FUNCTION_ISNAN },
15497 		{ "isinf",						FUNCTION_ISINF }
15498 	};
15499 
15500 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15501 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15502 	{
15503 		const BuiltinFunctions& bf = builtinFunctions[i];
15504 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15505 		{
15506 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
15507 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15508 		}
15509 	}
15510 	addChild(builin);
15511 }
15512 
15513 } /* glcts namespace */
15514