Home | History | Annotate | Download | only in gl
      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  **/
     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  **/
     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  **/
    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  **/
    215 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  **/
    264 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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  **/
    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  */
    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  **/
    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  **/
    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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  */
   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  **/
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
   3390 {
   3391 	switch (shader_stage)
   3392 	{
   3393 	case GEOMETRY_SHADER:
   3394 	case TESS_CTRL_SHADER:
   3395 	case TESS_EVAL_SHADER:
   3396 	case VERTEX_SHADER:
   3397 		return GL_POINTS;
   3398 		break;
   3399 
   3400 	default:
   3401 		return GL_NONE;
   3402 		break;
   3403 	}
   3404 }
   3405 
   3406 /** Get primitive type drawn with DrawArrays
   3407  *
   3408  * @param shader_stage Tested shader stage id
   3409  *
   3410  * @return Primitive type
   3411  **/
   3412 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
   3413 {
   3414 	switch (shader_stage)
   3415 	{
   3416 	case FRAGMENT_SHADER:
   3417 		return GL_TRIANGLE_FAN;
   3418 		break;
   3419 
   3420 	case GEOMETRY_SHADER:
   3421 	case VERTEX_SHADER:
   3422 		return GL_POINTS;
   3423 		break;
   3424 
   3425 	case TESS_CTRL_SHADER:
   3426 	case TESS_EVAL_SHADER:
   3427 		return GL_PATCHES;
   3428 		break;
   3429 
   3430 	default:
   3431 		return GL_NONE;
   3432 		break;
   3433 	}
   3434 }
   3435 
   3436 /** Get maximum allowed number of uniform components
   3437  *
   3438  * @param shader_stage Tested shader stage id
   3439  *
   3440  * @return Maxmimum uniform components
   3441  **/
   3442 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
   3443 {
   3444 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
   3445 	glw::GLint			  max_uniform_components = 0;
   3446 	glw::GLenum			  pname					 = 0;
   3447 
   3448 	switch (shader_stage)
   3449 	{
   3450 	case COMPUTE_SHADER:
   3451 		pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
   3452 		break;
   3453 	case FRAGMENT_SHADER:
   3454 		pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
   3455 		break;
   3456 	case GEOMETRY_SHADER:
   3457 		pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
   3458 		break;
   3459 	case TESS_CTRL_SHADER:
   3460 		pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
   3461 		break;
   3462 	case TESS_EVAL_SHADER:
   3463 		pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
   3464 		break;
   3465 	case VERTEX_SHADER:
   3466 		pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
   3467 		break;
   3468 	}
   3469 
   3470 	gl.getIntegerv(pname, &max_uniform_components);
   3471 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
   3472 
   3473 	return max_uniform_components;
   3474 }
   3475 
   3476 /** Get maximum size allowed for an uniform block
   3477  *
   3478  * @return Maxmimum uniform block size
   3479  **/
   3480 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
   3481 {
   3482 	const glw::Functions& gl					 = m_context.getRenderContext().getFunctions();
   3483 	glw::GLint			  max_uniform_block_size = 0;
   3484 
   3485 	gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
   3486 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
   3487 
   3488 	return max_uniform_block_size;
   3489 }
   3490 
   3491 /** Get number of components required to store single uniform of given type
   3492  *
   3493  * @param uniform_type Tested uniform type
   3494  *
   3495  * @return Number of components
   3496  **/
   3497 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
   3498 {
   3499 	static const glw::GLuint type_size	 = 2; /* double takes 2 N */
   3500 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
   3501 
   3502 	if (1 == uniform_type.m_n_columns)
   3503 	{
   3504 		return type_size * column_length;
   3505 	}
   3506 	else
   3507 	{
   3508 		const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
   3509 
   3510 		return alignment * uniform_type.m_n_columns;
   3511 	}
   3512 }
   3513 
   3514 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
   3515  *
   3516  * @param uniform_type Tested uniform type
   3517  *
   3518  * @return Size of a single member
   3519  **/
   3520 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
   3521 {
   3522 	static const glw::GLuint vec4_size	 = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
   3523 	const glw::GLuint		 column_length = uniform_type.m_n_rows;
   3524 
   3525 	/** Size for a layout(std140, column_major) uniform_type uniform[] **/
   3526 	return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
   3527 }
   3528 
   3529 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
   3530  *
   3531  * @param shader_stage Tested shader stage id
   3532  * @param uniform_type Tested uniform type
   3533  *
   3534  * @return Number of components
   3535  **/
   3536 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage				shader_stage,
   3537 												  const uniformTypeDetails& uniform_type) const
   3538 {
   3539 	const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
   3540 	const glw::GLuint required_components	  = getRequiredComponentsNumber(uniform_type);
   3541 	const glw::GLuint n_uniforms			   = max_uniform_components / required_components;
   3542 	const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
   3543 	const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
   3544 	const glw::GLuint max_uniforms			   = max_uniform_block_size / uniform_type_member_size;
   3545 
   3546 	return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
   3547 }
   3548 
   3549 /** Get name of shader stage
   3550  *
   3551  * @param shader_stage Tested shader stage id
   3552  *
   3553  * @return Name
   3554  **/
   3555 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
   3556 {
   3557 	switch (shader_stage)
   3558 	{
   3559 	case COMPUTE_SHADER:
   3560 		return "compute shader";
   3561 		break;
   3562 	case FRAGMENT_SHADER:
   3563 		return "fragment shader";
   3564 		break;
   3565 	case GEOMETRY_SHADER:
   3566 		return "geometry shader";
   3567 		break;
   3568 	case TESS_CTRL_SHADER:
   3569 		return "tesselation control shader";
   3570 		break;
   3571 	case TESS_EVAL_SHADER:
   3572 		return "tesselation evaluation shader";
   3573 		break;
   3574 	case VERTEX_SHADER:
   3575 		return "vertex shader";
   3576 		break;
   3577 	}
   3578 
   3579 	return 0;
   3580 }
   3581 
   3582 /** Inspect program to get: buffer_size, offset, strides and block index
   3583  *
   3584  * @param program_id          Program id
   3585  * @param out_buffer_size     Size of uniform buffer
   3586  * @param out_uniform_details Uniform offset and strides
   3587  * @param uniform_block_index Uniform block index
   3588  **/
   3589 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
   3590 										const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
   3591 										uniformDetails& out_uniform_details, glw::GLuint uniform_block_index) const
   3592 {
   3593 	glw::GLint				 array_stride = 0;
   3594 	std::vector<glw::GLchar> extracted_uniform_name;
   3595 	const glw::Functions&	gl			   = m_context.getRenderContext().getFunctions();
   3596 	glw::GLuint				 index		   = 0;
   3597 	glw::GLint				 matrix_stride = 0;
   3598 	glw::GLint				 offset		   = 0;
   3599 	glw::GLsizei			 size		   = 0;
   3600 	glw::GLenum				 type		   = 0;
   3601 	const glw::GLchar*		 uniform_name  = 0;
   3602 	std::string				 uniform_name_str;
   3603 	std::stringstream		 uniform_name_stream;
   3604 
   3605 	/* Get index of uniform block */
   3606 	uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
   3607 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
   3608 
   3609 	if (GL_INVALID_INDEX == uniform_block_index)
   3610 	{
   3611 		TCU_FAIL("Unifom block is inactive");
   3612 	}
   3613 
   3614 	/* Get size of uniform block */
   3615 	gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
   3616 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
   3617 
   3618 	if (0 == out_buffer_size)
   3619 	{
   3620 		TCU_FAIL("Unifom block size is 0");
   3621 	}
   3622 
   3623 	/* Prepare uniform name */
   3624 	uniform_name_stream << "uniform_array";
   3625 
   3626 	uniform_name_str = uniform_name_stream.str();
   3627 	uniform_name	 = uniform_name_str.c_str();
   3628 
   3629 	/* Get index of uniform */
   3630 	gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
   3631 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
   3632 
   3633 	if (GL_INVALID_INDEX == index)
   3634 	{
   3635 		TCU_FAIL("Unifom is inactive");
   3636 	}
   3637 
   3638 	/* Verify getActiveUniform results */
   3639 	extracted_uniform_name.resize(uniform_name_str.length() * 2);
   3640 
   3641 	gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
   3642 						&extracted_uniform_name[0]);
   3643 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
   3644 
   3645 	if ((n_uniforms != size) || (uniform_type.m_type != type))
   3646 	{
   3647 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
   3648 											<< " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
   3649 											<< " expected: " << uniform_type.m_type
   3650 											<< ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
   3651 
   3652 		TCU_FAIL("Invalid GetActiveUniform results");
   3653 	}
   3654 
   3655 	/* Get offset of uniform */
   3656 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
   3657 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
   3658 
   3659 	if (-1 == offset)
   3660 	{
   3661 		TCU_FAIL("Unifom has invalid offset");
   3662 	}
   3663 
   3664 	out_uniform_details.m_offset = offset;
   3665 
   3666 	/* Get matrix stride of uniform */
   3667 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
   3668 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
   3669 
   3670 	if (-1 == matrix_stride)
   3671 	{
   3672 		TCU_FAIL("Unifom has invalid matrix stride");
   3673 	}
   3674 
   3675 	out_uniform_details.m_matrix_stride = matrix_stride;
   3676 
   3677 	/* Get array stride of uniform */
   3678 	gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
   3679 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
   3680 
   3681 	if (-1 == matrix_stride)
   3682 	{
   3683 		TCU_FAIL("Unifom has invalid matrix stride");
   3684 	}
   3685 
   3686 	out_uniform_details.m_array_stride = array_stride;
   3687 }
   3688 
   3689 /** Prepare source code for "boilerplate" shaders
   3690  *
   3691  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
   3692  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
   3693  * @param out_source_code          Source code
   3694  **/
   3695 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
   3696 												  const glw::GLchar* stage_specific_main_body,
   3697 												  std::string&		 out_source_code) const
   3698 {
   3699 	/* Shader template */
   3700 	static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
   3701 																 "\n"
   3702 																 "precision highp float;\n"
   3703 																 "\n"
   3704 																 "STAGE_SPECIFIC_LAYOUT"
   3705 																 "void main()\n"
   3706 																 "{\n"
   3707 																 "STAGE_SPECIFIC_MAIN_BODY"
   3708 																 "}\n"
   3709 																 "\n";
   3710 
   3711 	std::string string = boilerplate_shader_template_code;
   3712 
   3713 	/* Tokens */
   3714 	static const glw::GLchar* body_token   = "STAGE_SPECIFIC_MAIN_BODY";
   3715 	static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
   3716 
   3717 	size_t search_position = 0;
   3718 
   3719 	/* Replace tokens */
   3720 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
   3721 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
   3722 
   3723 	/* Store resuls */
   3724 	out_source_code = string;
   3725 }
   3726 
   3727 /** Prepare program for given combination of shader stage and uniform type
   3728  *
   3729  * @param shader_stage     Shader stage
   3730  * @param uniform_type     Uniform type
   3731  * @param out_program_info Instance of programInfo
   3732  **/
   3733 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
   3734 										Utils::programInfo& out_program_info) const
   3735 {
   3736 	/* Stage specific layouts */
   3737 	static const glw::GLchar* geometry_shader_layout_code = "layout(points)                   in;\n"
   3738 															"layout(points, max_vertices = 1) out;\n"
   3739 															"\n";
   3740 
   3741 	static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
   3742 															 "\n";
   3743 
   3744 	static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
   3745 															 "\n";
   3746 
   3747 	/* Stage specific main body */
   3748 	static const glw::GLchar* boilerplate_fragment_shader_body_code = "    discard;\n";
   3749 
   3750 	static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
   3751 																	   "    gl_TessLevelOuter[1] = 1.0;\n"
   3752 																	   "    gl_TessLevelOuter[2] = 1.0;\n"
   3753 																	   "    gl_TessLevelOuter[3] = 1.0;\n"
   3754 																	   "    gl_TessLevelInner[0] = 1.0;\n"
   3755 																	   "    gl_TessLevelInner[1] = 1.0;\n";
   3756 
   3757 	static const glw::GLchar* boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
   3758 
   3759 	static const glw::GLchar* corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
   3760 															   "    {\n"
   3761 															   "        gl_Position = vec4(-1, -1, 0, 1);\n"
   3762 															   "    }\n"
   3763 															   "    else if (1 == gl_VertexID)\n"
   3764 															   "    {\n"
   3765 															   "        gl_Position = vec4(-1, 1, 0, 1);\n"
   3766 															   "    }\n"
   3767 															   "    else if (2 == gl_VertexID)\n"
   3768 															   "    {\n"
   3769 															   "        gl_Position = vec4(1, 1, 0, 1);\n"
   3770 															   "    }\n"
   3771 															   "    else if (3 == gl_VertexID)\n"
   3772 															   "    {\n"
   3773 															   "        gl_Position = vec4(1, -1, 0, 1);\n"
   3774 															   "    }\n";
   3775 
   3776 	static const glw::GLchar* passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
   3777 
   3778 	static const glw::GLchar* test_shader_body_code = "\n    result = verification_result;\n";
   3779 
   3780 	static const glw::GLchar* test_geometry_shader_body_code = "\n    result = verification_result;\n"
   3781 															   "\n"
   3782 															   "    EmitVertex();\n"
   3783 															   "    EndPrimitive();\n";
   3784 
   3785 	static const glw::GLchar* test_tess_ctrl_shader_body_code =
   3786 		"\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
   3787 		"\n"
   3788 		"    gl_TessLevelOuter[0] = 1.0;\n"
   3789 		"    gl_TessLevelOuter[1] = 1.0;\n"
   3790 		"    gl_TessLevelOuter[2] = 1.0;\n"
   3791 		"    gl_TessLevelOuter[3] = 1.0;\n"
   3792 		"    gl_TessLevelInner[0] = 1.0;\n"
   3793 		"    gl_TessLevelInner[1] = 1.0;\n";
   3794 
   3795 	/* In variables */
   3796 	static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
   3797 
   3798 	/* Out variables */
   3799 	static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
   3800 
   3801 	static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
   3802 
   3803 	static const glw::GLchar* test_shader_out_variable = "out int result;\n";
   3804 
   3805 	/* Varying name */
   3806 	static const glw::GLchar* varying_name = "result";
   3807 	glw::GLuint				  n_varyings   = 1;
   3808 
   3809 	/* Storage for ready shaders */
   3810 	std::string compute_shader_code;
   3811 	std::string fragment_shader_code;
   3812 	std::string geometry_shader_code;
   3813 	std::string tess_ctrl_shader_code;
   3814 	std::string tess_eval_shader_code;
   3815 	std::string vertex_shader_code;
   3816 
   3817 	/* Storage for uniform definition and verification code */
   3818 	std::string uniform_definitions;
   3819 	std::string uniform_verification;
   3820 
   3821 	/* Get uniform definition and verification code */
   3822 	prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
   3823 	prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
   3824 
   3825 	/* Prepare vertex shader */
   3826 	switch (shader_stage)
   3827 	{
   3828 	case FRAGMENT_SHADER:
   3829 
   3830 		prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
   3831 
   3832 		break;
   3833 
   3834 	case GEOMETRY_SHADER:
   3835 	case TESS_CTRL_SHADER:
   3836 	case TESS_EVAL_SHADER:
   3837 
   3838 		prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
   3839 
   3840 		break;
   3841 
   3842 	case VERTEX_SHADER:
   3843 
   3844 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
   3845 						  test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
   3846 						  test_shader_body_code /* body */, vertex_shader_code);
   3847 
   3848 		break;
   3849 
   3850 	default:
   3851 		break;
   3852 	}
   3853 
   3854 	/* Prepare fragment shader */
   3855 	switch (shader_stage)
   3856 	{
   3857 	case FRAGMENT_SHADER:
   3858 
   3859 		prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
   3860 						  test_fragment_shader_out_variable /* out var */,
   3861 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
   3862 						  fragment_shader_code);
   3863 
   3864 		break;
   3865 
   3866 	case GEOMETRY_SHADER:
   3867 	case TESS_CTRL_SHADER:
   3868 	case TESS_EVAL_SHADER:
   3869 	case VERTEX_SHADER:
   3870 
   3871 		prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
   3872 								 fragment_shader_code);
   3873 
   3874 		break;
   3875 
   3876 	default:
   3877 		break;
   3878 	}
   3879 
   3880 	/* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
   3881 	switch (shader_stage)
   3882 	{
   3883 	case COMPUTE_SHADER:
   3884 
   3885 		prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
   3886 
   3887 		break;
   3888 
   3889 	case GEOMETRY_SHADER:
   3890 
   3891 		prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
   3892 						  "" /* in var */, test_shader_out_variable /* out var */,
   3893 						  uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
   3894 						  geometry_shader_code);
   3895 
   3896 		break;
   3897 
   3898 	case TESS_CTRL_SHADER:
   3899 
   3900 		prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
   3901 						  "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
   3902 						  uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
   3903 						  tess_ctrl_shader_code);
   3904 
   3905 		prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
   3906 						  test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
   3907 						  "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
   3908 						  tess_eval_shader_code);
   3909 
   3910 		break;
   3911 
   3912 	case TESS_EVAL_SHADER:
   3913 
   3914 		prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
   3915 								 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
   3916 
   3917 		prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
   3918 						  "" /* in var */, test_shader_out_variable /* out var */,
   3919 						  uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
   3920 						  tess_eval_shader_code);
   3921 
   3922 		break;
   3923 
   3924 	default:
   3925 		break;
   3926 	};
   3927 
   3928 	/* Select shaders that will be used by program */
   3929 	const glw::GLchar* cs_c_str  = 0;
   3930 	const glw::GLchar* fs_c_str  = 0;
   3931 	const glw::GLchar* gs_c_str  = 0;
   3932 	const glw::GLchar* tcs_c_str = 0;
   3933 	const glw::GLchar* tes_c_str = 0;
   3934 	const glw::GLchar* vs_c_str  = 0;
   3935 
   3936 	if (false == compute_shader_code.empty())
   3937 	{
   3938 		cs_c_str = compute_shader_code.c_str();
   3939 	}
   3940 
   3941 	if (false == fragment_shader_code.empty())
   3942 	{
   3943 		fs_c_str = fragment_shader_code.c_str();
   3944 	}
   3945 
   3946 	if (false == geometry_shader_code.empty())
   3947 	{
   3948 		gs_c_str = geometry_shader_code.c_str();
   3949 	}
   3950 
   3951 	if (false == tess_ctrl_shader_code.empty())
   3952 	{
   3953 		tcs_c_str = tess_ctrl_shader_code.c_str();
   3954 	}
   3955 
   3956 	if (false == tess_eval_shader_code.empty())
   3957 	{
   3958 		tes_c_str = tess_eval_shader_code.c_str();
   3959 	}
   3960 
   3961 	if (false == vertex_shader_code.empty())
   3962 	{
   3963 		vs_c_str = vertex_shader_code.c_str();
   3964 	}
   3965 
   3966 	/* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
   3967 	if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
   3968 	{
   3969 		n_varyings = 0;
   3970 	}
   3971 
   3972 	/* Build */
   3973 	out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
   3974 }
   3975 
   3976 /** Prepare collection of tested shader stages
   3977  *
   3978  */
   3979 void GPUShaderFP64Test2::prepareShaderStages()
   3980 {
   3981 	/* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
   3982 	if (0 != m_pDispatchCompute)
   3983 	{
   3984 		m_shader_stages.push_back(COMPUTE_SHADER);
   3985 	}
   3986 
   3987 	m_shader_stages.push_back(FRAGMENT_SHADER);
   3988 	m_shader_stages.push_back(GEOMETRY_SHADER);
   3989 	m_shader_stages.push_back(TESS_CTRL_SHADER);
   3990 	m_shader_stages.push_back(TESS_EVAL_SHADER);
   3991 	m_shader_stages.push_back(VERTEX_SHADER);
   3992 }
   3993 
   3994 /** Prepare source code for "tested" shader stage
   3995  *
   3996  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
   3997  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
   3998  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
   3999  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
   4000  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
   4001  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
   4002  * @param out_source_code          Shader source code
   4003  **/
   4004 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
   4005 										   const glw::GLchar* uniform_definitions,
   4006 										   const glw::GLchar* in_variable_definitions,
   4007 										   const glw::GLchar* out_variable_definitions,
   4008 										   const glw::GLchar* uniform_verification,
   4009 										   const glw::GLchar* stage_specific_main_body,
   4010 										   std::string&		  out_source_code) const
   4011 {
   4012 	/* Shader template */
   4013 	static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
   4014 														  "\n"
   4015 														  "precision highp float;\n"
   4016 														  "\n"
   4017 														  "STAGE_SPECIFIC_LAYOUT"
   4018 														  "UNIFORM_DEFINITIONS"
   4019 														  "IN_VARIABLE_DEFINITION"
   4020 														  "OUT_VARIABLE_DEFINITION"
   4021 														  "\n"
   4022 														  "void main()\n"
   4023 														  "{\n"
   4024 														  "UNIFORM_VERIFICATION"
   4025 														  "STAGE_SPECIFIC_MAIN_BODY"
   4026 														  "}\n"
   4027 														  "\n";
   4028 
   4029 	std::string string = test_shader_template_code;
   4030 
   4031 	/* Tokens */
   4032 	static const glw::GLchar* body_token	= "STAGE_SPECIFIC_MAIN_BODY";
   4033 	static const glw::GLchar* in_var_token  = "IN_VARIABLE_DEFINITION";
   4034 	static const glw::GLchar* layout_token  = "STAGE_SPECIFIC_LAYOUT";
   4035 	static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
   4036 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
   4037 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
   4038 
   4039 	size_t search_position = 0;
   4040 
   4041 	/* Replace tokens */
   4042 	Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
   4043 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
   4044 	Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
   4045 	Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
   4046 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
   4047 	Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
   4048 
   4049 	/* Store resuls */
   4050 	out_source_code = string;
   4051 }
   4052 
   4053 /** Prepare source code for "tested" compute shaders
   4054  *
   4055  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
   4056  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
   4057  * @param out_source_code      Source code
   4058  **/
   4059 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
   4060 												  const glw::GLchar* uniform_verification,
   4061 												  std::string&		 out_source_code) const
   4062 {
   4063 	/* Shader template */
   4064 	static const glw::GLchar* test_shader_template_code =
   4065 		"#version 420 core\n"
   4066 		"#extension GL_ARB_compute_shader          : require\n"
   4067 		"#extension GL_ARB_shader_image_load_store : require\n"
   4068 		"\n"
   4069 		"precision highp float;\n"
   4070 		"\n"
   4071 		"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
   4072 		"\n"
   4073 		"UNIFORM_DEFINITIONS"
   4074 		"layout(r32i) writeonly uniform iimage2D result;\n"
   4075 		"\n"
   4076 		"void main()\n"
   4077 		"{\n"
   4078 		"UNIFORM_VERIFICATION"
   4079 		"\n"
   4080 		"    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
   4081 		"}\n"
   4082 		"\n";
   4083 
   4084 	std::string string = test_shader_template_code;
   4085 
   4086 	/* Tokens */
   4087 	static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
   4088 	static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
   4089 
   4090 	size_t search_position = 0;
   4091 
   4092 	/* Replace tokens */
   4093 	Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
   4094 	Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
   4095 
   4096 	/* Store resuls */
   4097 	out_source_code = string;
   4098 }
   4099 
   4100 /** Prepare source code which defines uniforms for tested shader stage
   4101  *
   4102  * @param shader_stage    Shader stage id
   4103  * @param uniform_type    Details of uniform type
   4104  * @param out_source_code Source code
   4105  **/
   4106 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
   4107 												   std::string& out_source_code) const
   4108 {
   4109 	const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
   4110 	std::stringstream stream;
   4111 
   4112 	/*
   4113 	 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
   4114 	 * {
   4115 	 *     TYPE_NAME uniform_array[N_UNIFORMS];
   4116 	 * };
   4117 	 */
   4118 	stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
   4119 																   "{\n";
   4120 
   4121 	stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
   4122 
   4123 	stream << "};\n\n";
   4124 
   4125 	out_source_code = stream.str();
   4126 }
   4127 
   4128 /** Prepare uniform buffer for test
   4129  *
   4130  * @param shader_stage Shader stage id
   4131  * @param uniform_type Details of uniform type
   4132  * @param program_info Program object info
   4133  **/
   4134 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
   4135 										 const Utils::programInfo& program_info) const
   4136 {
   4137 	glw::GLint				  buffer_size	 = 0;
   4138 	glw::GLuint				  element_ordinal = 1;
   4139 	const glw::Functions&	 gl			  = m_context.getRenderContext().getFunctions();
   4140 	const glw::GLuint		  n_columns		  = uniform_type.m_n_columns;
   4141 	const glw::GLuint		  n_rows		  = uniform_type.m_n_rows;
   4142 	const glw::GLuint		  n_elements	  = n_columns * n_rows;
   4143 	uniformDetails			  uniform_details;
   4144 	const glw::GLuint		  program_id = program_info.m_program_object_id;
   4145 	const glw::GLint		  n_uniforms = getAmountUniforms(shader_stage, uniform_type);
   4146 	std::vector<glw::GLubyte> uniform_buffer_data;
   4147 	glw::GLuint				  uniform_block_index = 0;
   4148 
   4149 	/* Get uniform details */
   4150 	inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
   4151 
   4152 	/* Uniform offset and strides */
   4153 	const glw::GLuint array_stride   = uniform_details.m_array_stride;
   4154 	const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
   4155 	const glw::GLuint uniform_offset = uniform_details.m_offset;
   4156 
   4157 	/* Prepare storage for buffer data */
   4158 	uniform_buffer_data.resize(buffer_size);
   4159 
   4160 	/* Prepare uniform data */
   4161 	for (glw::GLint i = 0; i < n_uniforms; ++i)
   4162 	{
   4163 		const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
   4164 
   4165 		for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
   4166 		{
   4167 			const glw::GLuint   column		 = element / n_rows;
   4168 			const glw::GLuint   column_elem  = element % n_rows;
   4169 			const glw::GLdouble value		 = element_ordinal;
   4170 			const glw::GLuint   value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
   4171 																	  column_elem * sizeof(glw::GLdouble));
   4172 			glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
   4173 
   4174 			*value_dst = value;
   4175 		}
   4176 	}
   4177 
   4178 	/* Update uniform buffer with new set of data */
   4179 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
   4180 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   4181 
   4182 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
   4183 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
   4184 
   4185 	/* Bind uniform block to uniform buffer */
   4186 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
   4187 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
   4188 
   4189 	gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
   4190 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
   4191 }
   4192 
   4193 /** Prepare collection of tested uniform types
   4194  *
   4195  **/
   4196 void GPUShaderFP64Test2::prepareUniformTypes()
   4197 {
   4198 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
   4199 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
   4200 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
   4201 	m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
   4202 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
   4203 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
   4204 	m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
   4205 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
   4206 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
   4207 	m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
   4208 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
   4209 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
   4210 	m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
   4211 }
   4212 
   4213 /** Prepare source code that verifes uniform values
   4214  *
   4215  * @param shader_stage    Shader stage id
   4216  * @param uniform_type    Details of uniform type
   4217  * @param out_source_code Source code
   4218  **/
   4219 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
   4220 													std::string& out_source_code) const
   4221 {
   4222 	glw::GLuint		  element_ordinal = 1;
   4223 	const glw::GLuint n_columns		  = uniform_type.m_n_columns;
   4224 	const glw::GLuint n_rows		  = uniform_type.m_n_rows;
   4225 	const glw::GLuint n_elements	  = n_columns * n_rows;
   4226 	const glw::GLuint n_uniforms	  = getAmountUniforms(shader_stage, uniform_type);
   4227 	std::stringstream stream;
   4228 
   4229 	/*
   4230 	 * int verification_result = M_RESULT_SUCCESS;
   4231 	 *
   4232 	 * for (int i = 0; i < N_UNIFORMS; ++i)
   4233 	 * {
   4234 	 *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
   4235 	 *     {
   4236 	 *         verification_result = M_RESULT_FAILURE
   4237 	 *     }
   4238 	 * }
   4239 	 */
   4240 	stream << "    int verification_result = " << m_result_success << ";\n"
   4241 																	  "\n"
   4242 																	  "    for (int i = 0; i < "
   4243 		   << n_uniforms << "; ++i)\n"
   4244 							"    {\n"
   4245 							"        if ("
   4246 		   << uniform_type.m_type_name << "(";
   4247 
   4248 	for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
   4249 	{
   4250 		stream << "i * (" << n_elements << ") + " << element + 1;
   4251 
   4252 		if (n_elements != element + 1)
   4253 		{
   4254 			stream << ", ";
   4255 		}
   4256 	}
   4257 
   4258 	stream << ") != uniform_array[i])\n"
   4259 			  "        {\n"
   4260 			  "           verification_result = "
   4261 		   << m_result_failure << ";\n"
   4262 								  "        }\n"
   4263 								  "    }\n";
   4264 
   4265 	out_source_code = stream.str();
   4266 }
   4267 
   4268 /** Execute test for given combination of "tested" shader stage and uniform type
   4269  *
   4270  * @param shader_stage Tested shader stage id
   4271  * @param uniform_type Tested uniform type
   4272  *
   4273  * @return true if test passed, false otherwise
   4274  **/
   4275 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
   4276 {
   4277 	const glw::GLenum		draw_primitive = getDrawPrimitiveType(shader_stage);
   4278 	static const glw::GLint first_vertex   = 0;
   4279 	const glw::Functions&   gl			   = m_context.getRenderContext().getFunctions();
   4280 	const glw::GLsizei		n_vertices	 = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
   4281 	Utils::programInfo		program_info(m_context);
   4282 	bool					result = true;
   4283 
   4284 	/* Prepare program */
   4285 	prepareProgram(shader_stage, uniform_type, program_info);
   4286 
   4287 	gl.useProgram(program_info.m_program_object_id);
   4288 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
   4289 
   4290 	/* Prepare uniform buffer and bind it with uniform block */
   4291 	prepareUniforms(shader_stage, uniform_type, program_info);
   4292 
   4293 	/* Prepare storage for test results */
   4294 	testBegin(program_info.m_program_object_id, shader_stage);
   4295 
   4296 	/* Execute */
   4297 	if (COMPUTE_SHADER == shader_stage)
   4298 	{
   4299 		m_pDispatchCompute(m_texture_width, m_texture_height, 1);
   4300 		GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
   4301 	}
   4302 	else
   4303 	{
   4304 		gl.drawArrays(draw_primitive, first_vertex, n_vertices);
   4305 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
   4306 	}
   4307 
   4308 	/* Clean after test */
   4309 	testEnd(shader_stage);
   4310 
   4311 	/* Check results */
   4312 	if (false == verifyResults(shader_stage))
   4313 	{
   4314 		m_context.getTestContext().getLog()
   4315 			<< tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
   4316 			<< ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
   4317 
   4318 		result = false;
   4319 	}
   4320 
   4321 	return result;
   4322 }
   4323 
   4324 /** Prepare transform feedback buffer, framebuffer or image unit for test results
   4325  *
   4326  * @param program_id   Program object id
   4327  * @param shader_stage Tested shader stage id
   4328  **/
   4329 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
   4330 {
   4331 	std::vector<glw::GLint> buffer_data;
   4332 	const glw::GLenum		captured_primitive = getCapturedPrimitiveType(shader_stage);
   4333 	const glw::Functions&   gl				   = m_context.getRenderContext().getFunctions();
   4334 
   4335 	/* Prepare buffer filled with m_result_failure */
   4336 	buffer_data.resize(m_n_captured_results);
   4337 	for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
   4338 	{
   4339 		buffer_data[i] = m_result_failure;
   4340 	}
   4341 
   4342 	/* Prepare buffer for test results */
   4343 	switch (shader_stage)
   4344 	{
   4345 	case GEOMETRY_SHADER:
   4346 	case TESS_CTRL_SHADER:
   4347 	case TESS_EVAL_SHADER:
   4348 	case VERTEX_SHADER:
   4349 
   4350 		/* Verify getTransformFeedbackVarying results */
   4351 		{
   4352 			glw::GLsizei size = 0;
   4353 			glw::GLenum  type = 0;
   4354 			glw::GLchar  name[16];
   4355 
   4356 			gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
   4357 										   name);
   4358 			GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
   4359 
   4360 			if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
   4361 			{
   4362 				m_context.getTestContext().getLog()
   4363 					<< tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
   4364 					<< " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
   4365 					<< ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
   4366 
   4367 				TCU_FAIL("Invalid GetTransformFeedbackVarying results");
   4368 			}
   4369 		}
   4370 
   4371 		/* Create/clean transform feedback buffer */
   4372 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
   4373 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   4374 
   4375 		gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
   4376 		GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
   4377 
   4378 		/* Set up transform feedback buffer */
   4379 		gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
   4380 						   m_transform_feedback_buffer_size);
   4381 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
   4382 
   4383 		gl.beginTransformFeedback(captured_primitive);
   4384 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
   4385 
   4386 		break;
   4387 
   4388 	case FRAGMENT_SHADER:
   4389 
   4390 		/* Clean texture */
   4391 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
   4392 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   4393 
   4394 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
   4395 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
   4396 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
   4397 
   4398 		/* Set up texture as color attachment 0 */
   4399 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
   4400 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
   4401 
   4402 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
   4403 		GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
   4404 
   4405 		gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
   4406 		GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
   4407 
   4408 		break;
   4409 
   4410 	case COMPUTE_SHADER:
   4411 
   4412 		/* Clean texture */
   4413 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
   4414 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   4415 
   4416 		gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
   4417 						 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
   4418 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
   4419 
   4420 		glw::GLint location = gl.getUniformLocation(program_id, "result");
   4421 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
   4422 
   4423 		if (-1 == location)
   4424 		{
   4425 			TCU_FAIL("Inactive uniform \"result\"");
   4426 		}
   4427 
   4428 		gl.uniform1i(location, 0 /* first image unit */);
   4429 		GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
   4430 
   4431 		/* Bind texture to first image unit */
   4432 		gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
   4433 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
   4434 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
   4435 
   4436 		break;
   4437 	}
   4438 }
   4439 
   4440 /** Unbind transform feedback buffer, framebuffer or image unit
   4441  *
   4442  * @param shader_stage Tested shader stage id
   4443  **/
   4444 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
   4445 {
   4446 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4447 
   4448 	switch (shader_stage)
   4449 	{
   4450 	case GEOMETRY_SHADER:
   4451 	case TESS_CTRL_SHADER:
   4452 	case TESS_EVAL_SHADER:
   4453 	case VERTEX_SHADER:
   4454 
   4455 		gl.endTransformFeedback();
   4456 
   4457 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
   4458 
   4459 		break;
   4460 
   4461 	case FRAGMENT_SHADER:
   4462 
   4463 		gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
   4464 								0 /* level */);
   4465 
   4466 		gl.bindTexture(GL_TEXTURE_2D, 0);
   4467 
   4468 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
   4469 
   4470 		break;
   4471 
   4472 	case COMPUTE_SHADER:
   4473 
   4474 		gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
   4475 							0 /* layer */, GL_WRITE_ONLY, GL_R32I);
   4476 
   4477 		break;
   4478 	}
   4479 }
   4480 
   4481 /** Initialize OpenGL objects for test
   4482  *
   4483  **/
   4484 void GPUShaderFP64Test2::testInit()
   4485 {
   4486 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4487 
   4488 	/* The test is in 4.0 group. However:
   4489 	 * - compute_shader is core since 4.3
   4490 	 * - compute_shader require at least version 4.2 of GL */
   4491 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
   4492 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
   4493 	{
   4494 		m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
   4495 	}
   4496 
   4497 	/* Tesselation patch set up */
   4498 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
   4499 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
   4500 
   4501 	/* Generate FBO */
   4502 	gl.genFramebuffers(1, &m_framebuffer_id);
   4503 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
   4504 
   4505 	/* Prepare texture */
   4506 	gl.genTextures(1, &m_texture_id);
   4507 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
   4508 
   4509 	gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
   4510 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   4511 
   4512 	gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
   4513 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
   4514 
   4515 	/* Prepare transform feedback buffer */
   4516 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
   4517 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
   4518 
   4519 	/* Generate uniform buffer */
   4520 	gl.genBuffers(1, &m_uniform_buffer_id);
   4521 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
   4522 
   4523 	/* Prepare VAO */
   4524 	gl.genVertexArrays(1, &m_vertex_array_object_id);
   4525 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
   4526 
   4527 	gl.bindVertexArray(m_vertex_array_object_id);
   4528 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
   4529 }
   4530 
   4531 /** Result verification, expected result is that whole buffer is filled with m_result_success
   4532  *
   4533  * @param shader_stage Tested shader stage id
   4534  **/
   4535 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
   4536 {
   4537 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4538 
   4539 	if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
   4540 	{
   4541 		/* Verify contents of texture */
   4542 
   4543 		/* Prepare storage for testure data */
   4544 		std::vector<glw::GLint> image_data;
   4545 		image_data.resize(m_texture_width * m_texture_height);
   4546 
   4547 		/* Get texture contents */
   4548 		gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
   4549 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   4550 
   4551 		gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
   4552 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
   4553 
   4554 		for (glw::GLuint y = 0; y < m_texture_width; ++y)
   4555 		{
   4556 			for (glw::GLuint x = 0; x < m_texture_height; ++x)
   4557 			{
   4558 				const glw::GLuint offset = y * m_texture_width + x;
   4559 				const glw::GLint  value  = image_data[offset];
   4560 
   4561 				if (m_result_success != value)
   4562 				{
   4563 					m_context.getTestContext().getLog()
   4564 						<< tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
   4565 						<< tcu::TestLog::EndMessage;
   4566 
   4567 					return false;
   4568 				}
   4569 			}
   4570 		}
   4571 
   4572 		return true;
   4573 	}
   4574 	else
   4575 	{
   4576 		/* Verify contents of transform feedback buffer */
   4577 
   4578 		bool result = true;
   4579 
   4580 		/* Get transform feedback data */
   4581 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
   4582 		GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   4583 
   4584 		glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   4585 		GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
   4586 
   4587 		for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
   4588 		{
   4589 			const glw::GLint value = feedback_data[i];
   4590 
   4591 			if (m_result_success != value)
   4592 			{
   4593 				m_context.getTestContext().getLog() << tcu::TestLog::Message
   4594 													<< "Error. Transform feedback buffer contents are wrong at " << i
   4595 													<< tcu::TestLog::EndMessage;
   4596 
   4597 				result = false;
   4598 				break;
   4599 			}
   4600 		}
   4601 
   4602 		/* Unmap transform feedback buffer */
   4603 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   4604 		GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
   4605 
   4606 		return result;
   4607 	}
   4608 }
   4609 
   4610 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
   4611 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
   4612 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
   4613 
   4614 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name			 = "UniformBlock";
   4615 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
   4616 
   4617 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
   4618 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result	= "gs_fs_gs_result";
   4619 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
   4620 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
   4621 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result	= "gs_fs_vs_result";
   4622 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
   4623 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
   4624 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
   4625 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
   4626 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
   4627 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
   4628 
   4629 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
   4630 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset			 = -1;
   4631 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride	= -1;
   4632 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
   4633 
   4634 /** Constructor
   4635  *
   4636  * @param context Test context
   4637  **/
   4638 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
   4639 	: TestCase(context, "named_uniform_blocks",
   4640 			   "Verifies usage of \"double precision\" floats in \"named uniform block\"")
   4641 {
   4642 	/* Nothing to be done */
   4643 }
   4644 
   4645 /** Deinitialize test
   4646  *
   4647  **/
   4648 void GPUShaderFP64Test3::deinit()
   4649 {
   4650 	/* GL entry points */
   4651 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   4652 
   4653 	/* Clean programs */
   4654 	m_packed_program.deinit(m_context);
   4655 	m_shared_program.deinit(m_context);
   4656 	m_std140_program.deinit(m_context);
   4657 
   4658 	/* Clean frambuffer */
   4659 	if (0 != m_framebuffer_id)
   4660 	{
   4661 		gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
   4662 		gl.deleteFramebuffers(1, &m_framebuffer_id);
   4663 
   4664 		m_framebuffer_id = 0;
   4665 	}
   4666 
   4667 	/* Clean texture */
   4668 	if (0 != m_color_texture_id)
   4669 	{
   4670 		gl.bindTexture(GL_TEXTURE_2D, 0);
   4671 		gl.deleteTextures(1, &m_color_texture_id);
   4672 
   4673 		m_color_texture_id = 0;
   4674 	}
   4675 
   4676 	/* Clean buffers */
   4677 	if (0 != m_transform_feedback_buffer_id)
   4678 	{
   4679 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
   4680 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
   4681 
   4682 		m_transform_feedback_buffer_id = 0;
   4683 	}
   4684 
   4685 	if (0 != m_uniform_buffer_id)
   4686 	{
   4687 		gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
   4688 		gl.deleteBuffers(1, &m_uniform_buffer_id);
   4689 
   4690 		m_uniform_buffer_id = 0;
   4691 	}
   4692 
   4693 	/* Clean VAO */
   4694 	if (0 != m_vertex_array_object_id)
   4695 	{
   4696 		gl.bindVertexArray(0);
   4697 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
   4698 
   4699 		m_vertex_array_object_id = 0;
   4700 	}
   4701 }
   4702 
   4703 /** Execute test
   4704  *
   4705  * @return tcu::TestNode::STOP
   4706  **/
   4707 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
   4708 {
   4709 	bool result = true;
   4710 
   4711 	/* Check if extension is supported */
   4712 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   4713 	{
   4714 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
   4715 	}
   4716 
   4717 	/* Initialize test */
   4718 	testInit();
   4719 
   4720 	/* Test "packed" uniform buffer layout */
   4721 	if (false == test(PACKED))
   4722 	{
   4723 		result = false;
   4724 	}
   4725 
   4726 	/* Test "shared" uniform buffer layout */
   4727 	if (false == test(SHARED))
   4728 	{
   4729 		result = false;
   4730 	}
   4731 
   4732 	/* Test "std140" uniform buffer layout */
   4733 	if (false == test(STD140))
   4734 	{
   4735 		result = false;
   4736 	}
   4737 
   4738 	/* Set result */
   4739 	if (true == result)
   4740 	{
   4741 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
   4742 	}
   4743 	else
   4744 	{
   4745 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   4746 	}
   4747 
   4748 	/* Done */
   4749 	return tcu::TestNode::STOP;
   4750 }
   4751 
   4752 /** Constructor
   4753  *
   4754  **/
   4755 GPUShaderFP64Test3::programInfo::programInfo()
   4756 	: m_fragment_shader_id(0)
   4757 	, m_geometry_shader_id(0)
   4758 	, m_program_object_id(0)
   4759 	, m_tesselation_control_shader_id(0)
   4760 	, m_tesselation_evaluation_shader_id(0)
   4761 	, m_vertex_shader_id(0)
   4762 	, m_buffer_size(0)
   4763 	, m_uniform_block_index(0)
   4764 {
   4765 	/* Nothing to be done here */
   4766 }
   4767 
   4768 /** Compile shader
   4769  *
   4770  * @param context     Test context
   4771  * @param shader_id   Shader object id
   4772  * @param shader_code Shader source code
   4773  **/
   4774 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
   4775 											  const glw::GLchar* shader_code) const
   4776 {
   4777 	/* GL entry points */
   4778 	const glw::Functions& gl = context.getRenderContext().getFunctions();
   4779 
   4780 	/* Compilation status */
   4781 	glw::GLint status = GL_FALSE;
   4782 
   4783 	/* Set source code */
   4784 	gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
   4785 	GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
   4786 
   4787 	/* Compile */
   4788 	gl.compileShader(shader_id);
   4789 	GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
   4790 
   4791 	/* Get compilation status */
   4792 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
   4793 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
   4794 
   4795 	/* Log compilation error */
   4796 	if (GL_TRUE != status)
   4797 	{
   4798 		glw::GLint				 length = 0;
   4799 		std::vector<glw::GLchar> message;
   4800 
   4801 		/* Error log length */
   4802 		gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
   4803 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
   4804 
   4805 		/* Prepare storage */
   4806 		message.resize(length);
   4807 
   4808 		/* Get error log */
   4809 		gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
   4810 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
   4811 
   4812 		/* Log */
   4813 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
   4814 										  << &message[0] << "\nShader source\n"
   4815 										  << shader_code << tcu::TestLog::EndMessage;
   4816 
   4817 		TCU_FAIL("Failed to compile shader");
   4818 	}
   4819 }
   4820 
   4821 /** Cleans program and attached shaders
   4822  *
   4823  * @param context Test context
   4824  **/
   4825 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
   4826 {
   4827 	/* GL entry points */
   4828 	const glw::Functions& gl = context.getRenderContext().getFunctions();
   4829 
   4830 	/* Restore default program */
   4831 	gl.useProgram(0);
   4832 
   4833 	/* Clean program object */
   4834 	if (0 != m_program_object_id)
   4835 	{
   4836 		gl.deleteProgram(m_program_object_id);
   4837 		m_program_object_id = 0;
   4838 	}
   4839 
   4840 	/* Clean shaders */
   4841 	if (0 != m_fragment_shader_id)
   4842 	{
   4843 		gl.deleteShader(m_fragment_shader_id);
   4844 		m_fragment_shader_id = 0;
   4845 	}
   4846 
   4847 	if (0 != m_geometry_shader_id)
   4848 	{
   4849 		gl.deleteShader(m_geometry_shader_id);
   4850 		m_geometry_shader_id = 0;
   4851 	}
   4852 
   4853 	if (0 != m_tesselation_control_shader_id)
   4854 	{
   4855 		gl.deleteShader(m_tesselation_control_shader_id);
   4856 		m_tesselation_control_shader_id = 0;
   4857 	}
   4858 
   4859 	if (0 != m_tesselation_evaluation_shader_id)
   4860 	{
   4861 		gl.deleteShader(m_tesselation_evaluation_shader_id);
   4862 		m_tesselation_evaluation_shader_id = 0;
   4863 	}
   4864 
   4865 	if (0 != m_vertex_shader_id)
   4866 	{
   4867 		gl.deleteShader(m_vertex_shader_id);
   4868 		m_vertex_shader_id = 0;
   4869 	}
   4870 }
   4871 
   4872 /** Build program and query for uniform layout
   4873  *
   4874  * @param context                            Test context
   4875  * @param uniform_details                  Collection of uniform details
   4876  * @param fragment_shader_code               Fragment shader source code
   4877  * @param geometry_shader_code               Geometry shader source code
   4878  * @param tesselation_control_shader_code    Tesselation control shader source code
   4879  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
   4880  * @param vertex_shader_code                 Vertex shader source code
   4881  **/
   4882 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
   4883 										   const glw::GLchar* fragment_shader_code,
   4884 										   const glw::GLchar* geometry_shader_code,
   4885 										   const glw::GLchar* tesselation_control_shader_code,
   4886 										   const glw::GLchar* tesselation_evaluation_shader_code,
   4887 										   const glw::GLchar* vertex_shader_code)
   4888 {
   4889 	/* GL entry points */
   4890 	const glw::Functions& gl = context.getRenderContext().getFunctions();
   4891 
   4892 	/* Names of varyings to be captured with transform feedback */
   4893 	static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
   4894 												  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
   4895 	static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
   4896 
   4897 	/* Create shader objects */
   4898 	m_fragment_shader_id			   = gl.createShader(GL_FRAGMENT_SHADER);
   4899 	m_geometry_shader_id			   = gl.createShader(GL_GEOMETRY_SHADER);
   4900 	m_tesselation_control_shader_id	= gl.createShader(GL_TESS_CONTROL_SHADER);
   4901 	m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
   4902 	m_vertex_shader_id				   = gl.createShader(GL_VERTEX_SHADER);
   4903 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
   4904 
   4905 	/* Create program object */
   4906 	m_program_object_id = gl.createProgram();
   4907 	GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
   4908 
   4909 	/* Set up names of varyings to be captured with transform feedback */
   4910 	gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
   4911 	GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
   4912 
   4913 	/* Compile shaders */
   4914 	compile(context, m_fragment_shader_id, fragment_shader_code);
   4915 	compile(context, m_geometry_shader_id, geometry_shader_code);
   4916 	compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
   4917 	compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
   4918 	compile(context, m_vertex_shader_id, vertex_shader_code);
   4919 
   4920 	/* Link program */
   4921 	link(context);
   4922 
   4923 	/* Inspect program object */
   4924 	/* Get index of named uniform block */
   4925 	m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
   4926 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
   4927 
   4928 	if (GL_INVALID_INDEX == m_uniform_block_index)
   4929 	{
   4930 		TCU_FAIL("Unifom block is inactive");
   4931 	}
   4932 
   4933 	/* Get size of named uniform block */
   4934 	gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
   4935 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
   4936 
   4937 	if (0 == m_buffer_size)
   4938 	{
   4939 		TCU_FAIL("Unifom block size is 0");
   4940 	}
   4941 
   4942 	/* Get information about "double precision" uniforms */
   4943 	for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
   4944 		 end != it; ++it)
   4945 	{
   4946 		const glw::GLchar* uniform_name = 0;
   4947 		std::string		   uniform_name_str;
   4948 		std::stringstream  uniform_name_stream;
   4949 		glw::GLuint		   index		 = 0;
   4950 		glw::GLint		   offset		 = 0;
   4951 		glw::GLint		   matrix_stride = 0;
   4952 
   4953 		/* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
   4954 		uniform_name_stream << m_uniform_block_name << "." << it->m_name;
   4955 
   4956 		uniform_name_str = uniform_name_stream.str();
   4957 		uniform_name	 = uniform_name_str.c_str();
   4958 
   4959 		/* Get index of uniform */
   4960 		gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
   4961 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
   4962 
   4963 		if (GL_INVALID_INDEX == index)
   4964 		{
   4965 			TCU_FAIL("Unifom is inactive");
   4966 		}
   4967 
   4968 		/* Get offset of uniform */
   4969 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
   4970 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
   4971 
   4972 		if (m_invalid_uniform_offset == offset)
   4973 		{
   4974 			TCU_FAIL("Unifom has invalid offset");
   4975 		}
   4976 
   4977 		m_uniform_offsets.push_back(offset);
   4978 
   4979 		/* Get matrix stride of uniform */
   4980 		gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
   4981 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
   4982 
   4983 		if (m_invalid_uniform_matrix_stride == offset)
   4984 		{
   4985 			TCU_FAIL("Unifom has invalid matrix stride");
   4986 		}
   4987 
   4988 		m_uniform_matrix_strides.push_back(matrix_stride);
   4989 	}
   4990 }
   4991 
   4992 /** Attach shaders and link program
   4993  *
   4994  * @param context Test context
   4995  **/
   4996 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
   4997 {
   4998 	/* GL entry points */
   4999 	const glw::Functions& gl = context.getRenderContext().getFunctions();
   5000 
   5001 	/* Link status */
   5002 	glw::GLint status = GL_FALSE;
   5003 
   5004 	/* Attach shaders */
   5005 	gl.attachShader(m_program_object_id, m_fragment_shader_id);
   5006 	gl.attachShader(m_program_object_id, m_geometry_shader_id);
   5007 	gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
   5008 	gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
   5009 	gl.attachShader(m_program_object_id, m_vertex_shader_id);
   5010 	GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
   5011 
   5012 	/* Link */
   5013 	gl.linkProgram(m_program_object_id);
   5014 	GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
   5015 
   5016 	/* Get link status */
   5017 	gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
   5018 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
   5019 
   5020 	/* Log link error */
   5021 	if (GL_TRUE != status)
   5022 	{
   5023 		glw::GLint				 length = 0;
   5024 		std::vector<glw::GLchar> message;
   5025 
   5026 		/* Get error log length */
   5027 		gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
   5028 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
   5029 
   5030 		message.resize(length);
   5031 
   5032 		/* Get error log */
   5033 		gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
   5034 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
   5035 
   5036 		/* Log */
   5037 		context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
   5038 										  << &message[0] << tcu::TestLog::EndMessage;
   5039 
   5040 		TCU_FAIL("Failed to link program");
   5041 	}
   5042 }
   5043 
   5044 /** Returns "predefined" values that will be used to fill uniform data
   5045  *
   5046  * @param type_ordinal Ordinal number of "double precision" uniform type
   5047  * @param element      Index of element in uniform
   5048  *
   5049  * @return "Predefined" value
   5050  **/
   5051 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
   5052 {
   5053 	return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
   5054 		   ((m_base_element - (glw::GLdouble)element) / 4.0);
   5055 }
   5056 
   5057 /** Returns a reference of programInfo instance specific for given buffer layout
   5058  *
   5059  * @param uniform_data_layout Buffer layout
   5060  *
   5061  * @return Reference to an instance of programInfo
   5062  **/
   5063 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
   5064 {
   5065 	const programInfo* program_info = 0;
   5066 
   5067 	switch (uniform_data_layout)
   5068 	{
   5069 	case PACKED:
   5070 
   5071 		program_info = &m_packed_program;
   5072 
   5073 		break;
   5074 
   5075 	case SHARED:
   5076 
   5077 		program_info = &m_shared_program;
   5078 
   5079 		break;
   5080 
   5081 	case STD140:
   5082 
   5083 		program_info = &m_std140_program;
   5084 
   5085 		break;
   5086 	}
   5087 
   5088 	return *program_info;
   5089 }
   5090 
   5091 /** Get "name" of buffer layout
   5092  *
   5093  * @param uniform_data_layout Buffer layout
   5094  *
   5095  * @return "Name" of layout
   5096  **/
   5097 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
   5098 {
   5099 	const glw::GLchar* layout = "";
   5100 
   5101 	switch (uniform_data_layout)
   5102 	{
   5103 	case PACKED:
   5104 		layout = "packed";
   5105 		break;
   5106 	case SHARED:
   5107 		layout = "shared";
   5108 		break;
   5109 	case STD140:
   5110 		layout = "std140";
   5111 		break;
   5112 	}
   5113 
   5114 	return layout;
   5115 }
   5116 
   5117 /** Prepare programInfo instance for specific buffer layout
   5118  *
   5119  * @param program_info        Instance of programInfo
   5120  * @param uniform_data_layout Buffer layout
   5121  **/
   5122 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
   5123 {
   5124 	/* Storage for shader source code */
   5125 	std::stringstream fragment_shader_code;
   5126 	std::stringstream geometry_shader_code;
   5127 	std::stringstream tess_control_shader_code;
   5128 	std::stringstream tess_eval_shader_code;
   5129 	std::stringstream vertex_shader_code;
   5130 
   5131 	/* Write preambles */
   5132 	writePreamble(fragment_shader_code, FRAGMENT_SHADER);
   5133 	writePreamble(geometry_shader_code, GEOMETRY_SHADER);
   5134 	writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
   5135 	writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
   5136 	writePreamble(vertex_shader_code, VERTEX_SHADER);
   5137 
   5138 	/* Write definition of named uniform block */
   5139 	writeUniformBlock(fragment_shader_code, uniform_data_layout);
   5140 	writeUniformBlock(geometry_shader_code, uniform_data_layout);
   5141 	writeUniformBlock(tess_control_shader_code, uniform_data_layout);
   5142 	writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
   5143 	writeUniformBlock(vertex_shader_code, uniform_data_layout);
   5144 
   5145 	/* Write definitions of varyings */
   5146 	writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
   5147 	writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
   5148 	writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
   5149 	writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
   5150 	writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
   5151 
   5152 	/* Write main routine */
   5153 	writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
   5154 	writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
   5155 	writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
   5156 	writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
   5157 	writeMainBody(vertex_shader_code, VERTEX_SHADER);
   5158 
   5159 	/* Init programInfo instance */
   5160 	program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
   5161 					  geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
   5162 					  tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
   5163 }
   5164 
   5165 /** Prepare uniform buffer
   5166  *
   5167  * @param program_info   Instance of programInfo
   5168  * @param verify_offsets If uniform offsets should be verified against expected values
   5169  *
   5170  * @return false if uniform offsets verification result is failure, true otherwise
   5171  **/
   5172 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
   5173 {
   5174 	const glw::GLuint							buffer_size = program_info.m_buffer_size;
   5175 	const glw::Functions&						gl			= m_context.getRenderContext().getFunctions();
   5176 	bool										offset_verification_result = true;
   5177 	glw::GLuint									type_ordinal			   = 1;
   5178 	std::vector<uniformDetails>::const_iterator it_uniform_details		   = m_uniform_details.begin();
   5179 	std::vector<glw::GLint>::const_iterator		it_uniform_offsets		   = program_info.m_uniform_offsets.begin();
   5180 	std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
   5181 
   5182 	/* Prepare storage for uniform buffer data */
   5183 	std::vector<glw::GLubyte> buffer_data;
   5184 	buffer_data.resize(buffer_size);
   5185 
   5186 	/* For each "double precision" uniform */
   5187 	for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
   5188 		 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
   5189 	{
   5190 		const glw::GLint  matrix_stride  = *it_uniform_matrix_strides;
   5191 		const glw::GLuint n_columns		 = it_uniform_details->m_n_columns;
   5192 		const glw::GLuint n_elements	 = it_uniform_details->m_n_elements;
   5193 		const glw::GLuint column_length  = n_elements / n_columns;
   5194 		const glw::GLint  uniform_offset = *it_uniform_offsets;
   5195 
   5196 		/* For each element of uniform */
   5197 		for (glw::GLuint element = 0; element < n_elements; ++element)
   5198 		{
   5199 			const glw::GLuint   column		= element / column_length;
   5200 			const glw::GLuint   column_elem = element % column_length;
   5201 			const glw::GLdouble value		= getExpectedValue(type_ordinal, element);
   5202 			const glw::GLuint   value_offset =
   5203 				static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
   5204 
   5205 			glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
   5206 
   5207 			/* Store value */
   5208 			*value_dst = value;
   5209 		}
   5210 
   5211 		/* Uniform offset verification */
   5212 		if (true == verify_offsets)
   5213 		{
   5214 			const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
   5215 
   5216 			if (expected_offset != uniform_offset)
   5217 			{
   5218 				if (true == offset_verification_result)
   5219 				{
   5220 					m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
   5221 				}
   5222 
   5223 				m_context.getTestContext().getLog()
   5224 					<< tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
   5225 					<< " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
   5226 					<< tcu::TestLog::EndMessage;
   5227 
   5228 				offset_verification_result = false;
   5229 			}
   5230 		}
   5231 	}
   5232 
   5233 	/* Update uniform buffer with prepared data */
   5234 	gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
   5235 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   5236 
   5237 	gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
   5238 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
   5239 
   5240 	/* Bind uniform buffer as data source for named uniform block */
   5241 	gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
   5242 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
   5243 
   5244 	gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
   5245 	GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
   5246 
   5247 	/* Done */
   5248 	return offset_verification_result;
   5249 }
   5250 
   5251 /** Prepare data, execute draw call and verify results
   5252  *
   5253  * @param uniform_data_layout
   5254  *
   5255  * @return true if test pass, false otherwise
   5256  **/
   5257 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
   5258 {
   5259 	bool				  are_offsets_verified		 = (STD140 == uniform_data_layout);
   5260 	const glw::Functions& gl						 = m_context.getRenderContext().getFunctions();
   5261 	bool				  offset_verification_result = true;
   5262 	const programInfo&	program_info				 = getProgramInfo(uniform_data_layout);
   5263 	bool				  result					 = true;
   5264 
   5265 	/* Set up program */
   5266 	gl.useProgram(program_info.m_program_object_id);
   5267 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
   5268 
   5269 	/* Prepare uniform buffer */
   5270 	offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
   5271 
   5272 	if (true == are_offsets_verified && false == offset_verification_result)
   5273 	{
   5274 		/* Offsets verification failure was already reported, add info about buffer layout */
   5275 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5276 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
   5277 											<< tcu::TestLog::EndMessage;
   5278 
   5279 		result = false;
   5280 	}
   5281 
   5282 	/* Set up transform feedback buffer */
   5283 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
   5284 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
   5285 
   5286 	/* Begin transform feedback */
   5287 	gl.beginTransformFeedback(GL_POINTS);
   5288 	GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
   5289 
   5290 	/* Execute draw call for singe vertex */
   5291 	gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
   5292 	GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
   5293 
   5294 	/* Stop transform feedback */
   5295 	gl.endTransformFeedback();
   5296 	GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
   5297 
   5298 	/* Verify results */
   5299 	if (false == verifyResults())
   5300 	{
   5301 		/* Result verificatioon failure was already reported, add info about layout */
   5302 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5303 											<< "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
   5304 											<< tcu::TestLog::EndMessage;
   5305 
   5306 		result = false;
   5307 	}
   5308 
   5309 	/* Done */
   5310 	return result;
   5311 }
   5312 
   5313 void GPUShaderFP64Test3::testInit()
   5314 {
   5315 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   5316 
   5317 	/* Uniform block declaration with std140 offsets calculated
   5318 	 *                       | align | loc_req | begins | ends | offset in bytes | imp |
   5319 	 * ivec3   dummy1[3]     |     4 |      12 |      0 |   12 |               0 |     |
   5320 	 * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
   5321 	 * bool    dummy2        |     1 |       1 |     14 |   15 |              56 |     |
   5322 	 * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
   5323 	 * bvec3   dummy3        |     4 |       4 |     20 |   24 |              80 |     |
   5324 	 * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
   5325 	 * int     dummy4[3]     |     4 |      12 |     32 |   44 |             128 |     |
   5326 	 * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
   5327 	 * bool    dummy5        |     1 |       1 |     56 |   57 |             224 |     |
   5328 	 * bool    dummy6[2]     |     4 |       8 |     60 |   68 |             240 |     |
   5329 	 * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
   5330 	 * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
   5331 	 * bool    dummy7        |     1 |       1 |    104 |  105 |             416 |     |
   5332 	 * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
   5333 	 * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
   5334 	 * uvec3   dummy8        |     4 |       4 |    160 |  164 |             640 |     |
   5335 	 * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
   5336 	 * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
   5337 	 * bool    dummy9        |     1 |       1 |    196 |  197 |             784 |     |
   5338 	 * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
   5339 	 * int     dummy10       |     1 |       1 |    224 |  225 |             896 |     |
   5340 	 * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
   5341 	 * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
   5342 	 */
   5343 
   5344 	/* Prepare "double precision" unfiorms' details */
   5345 	m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
   5346 											   1 /* n_elements */, "double" /* type_name */));
   5347 	m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
   5348 											   2 /* n_elements */, "dvec2" /* type_name */));
   5349 	m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
   5350 											   3 /* n_elements */, "dvec3" /* type_name */));
   5351 	m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
   5352 											   4 /* n_elements */, "dvec4" /* type_name */));
   5353 	m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
   5354 											   4 /* n_elements */, "dmat2" /* type_name */));
   5355 	m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
   5356 											   9 /* n_elements */, "dmat3" /* type_name */));
   5357 	m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
   5358 											   16 /* n_elements */, "dmat4" /* type_name */));
   5359 	m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
   5360 											   6 /* n_elements */, "dmat2x3" /* type_name */));
   5361 	m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
   5362 											   8 /* n_elements */, "dmat2x4" /* type_name */));
   5363 	m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
   5364 											   6 /* n_elements */, "dmat3x2" /* type_name */));
   5365 	m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
   5366 											   12 /* n_elements */, "dmat3x4" /* type_name */));
   5367 	m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
   5368 											   8 /* n_elements */, "dmat4x2" /* type_name */));
   5369 	m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
   5370 											   12 /* n_elements */, "dmat4x3" /* type_name */));
   5371 
   5372 	/* Get random values for getExpectedValue */
   5373 	m_base_element		= (glw::GLdouble)(rand() % 13);
   5374 	m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
   5375 
   5376 	/* Prepare programInfos for all buffer layouts */
   5377 	prepareProgram(m_packed_program, PACKED);
   5378 	prepareProgram(m_shared_program, SHARED);
   5379 	prepareProgram(m_std140_program, STD140);
   5380 
   5381 	/* Generate buffers */
   5382 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
   5383 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
   5384 
   5385 	gl.genBuffers(1, &m_uniform_buffer_id);
   5386 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
   5387 
   5388 	/* Prepare transform feedback buffer */
   5389 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
   5390 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   5391 
   5392 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
   5393 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
   5394 
   5395 	/* Prepare texture for color attachment 0 */
   5396 	gl.genTextures(1, &m_color_texture_id);
   5397 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
   5398 
   5399 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
   5400 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   5401 
   5402 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
   5403 	GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
   5404 
   5405 	/* Prepare FBO with color attachment 0 */
   5406 	gl.genFramebuffers(1, &m_framebuffer_id);
   5407 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
   5408 
   5409 	gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
   5410 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
   5411 
   5412 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
   5413 							0 /* level */);
   5414 	GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
   5415 
   5416 	gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
   5417 	GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
   5418 
   5419 	/* Prepare VAO */
   5420 	gl.genVertexArrays(1, &m_vertex_array_object_id);
   5421 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
   5422 
   5423 	gl.bindVertexArray(m_vertex_array_object_id);
   5424 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
   5425 
   5426 	/* Tesselation patch set up */
   5427 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
   5428 	GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
   5429 }
   5430 
   5431 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
   5432  *
   5433  * @return true if all values are as expected, false otherwise
   5434  **/
   5435 bool GPUShaderFP64Test3::verifyResults() const
   5436 {
   5437 	glw::GLint*			  feedback_data			  = 0;
   5438 	bool				  fragment_shader_result  = false;
   5439 	bool				  geometry_shader_result  = false;
   5440 	const glw::Functions& gl					  = m_context.getRenderContext().getFunctions();
   5441 	bool				  tess_ctrl_shader_result = false;
   5442 	bool				  tess_eval_shader_result = false;
   5443 	bool				  vertex_shader_result	= false;
   5444 
   5445 	/* Prepare storage for testure data */
   5446 	std::vector<glw::GLint> image_data;
   5447 	image_data.resize(1);
   5448 
   5449 	/* Get texture contents */
   5450 	gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
   5451 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
   5452 
   5453 	gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
   5454 	GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
   5455 
   5456 	/* Get transform feedback data */
   5457 	feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   5458 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
   5459 
   5460 	/* Verify results */
   5461 	fragment_shader_result  = (m_result_success == image_data[0]);
   5462 	geometry_shader_result  = (m_result_success == feedback_data[0]);
   5463 	tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
   5464 	tess_eval_shader_result = (m_result_success == feedback_data[2]);
   5465 	vertex_shader_result	= (m_result_success == feedback_data[3]);
   5466 
   5467 	/* Unmap transform feedback buffer */
   5468 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   5469 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
   5470 
   5471 	/* Set result */
   5472 	if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
   5473 				 tess_eval_shader_result && vertex_shader_result))
   5474 	{
   5475 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
   5476 
   5477 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5478 											<< "Vertex shader stage result: " << vertex_shader_result
   5479 											<< tcu::TestLog::EndMessage;
   5480 
   5481 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5482 											<< "Tesselation control shader stage result: " << tess_ctrl_shader_result
   5483 											<< tcu::TestLog::EndMessage;
   5484 
   5485 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5486 											<< "Tesselation evaluation shader stage result: " << tess_eval_shader_result
   5487 											<< tcu::TestLog::EndMessage;
   5488 
   5489 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5490 											<< "Geometry shader stage result: " << geometry_shader_result
   5491 											<< tcu::TestLog::EndMessage;
   5492 
   5493 		m_context.getTestContext().getLog() << tcu::TestLog::Message
   5494 											<< "Fragment shader stage result: " << fragment_shader_result
   5495 											<< tcu::TestLog::EndMessage;
   5496 
   5497 		return false;
   5498 	}
   5499 	else
   5500 	{
   5501 		return true;
   5502 	}
   5503 }
   5504 
   5505 /** Write main routine of <shader_stage> shader to stream
   5506  *
   5507  * @param stream       Output stream with source code of shader
   5508  * @param shader_stage Shader stage
   5509  **/
   5510 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
   5511 {
   5512 	glw::GLuint		   type_ordinal = 1;
   5513 	const glw::GLchar* varying_name = "";
   5514 
   5515 	/* Select name for varying that will hold result of "that" shader_stage */
   5516 	switch (shader_stage)
   5517 	{
   5518 	case FRAGMENT_SHADER:
   5519 		varying_name = m_varying_name_fs_out_fs_result;
   5520 		break;
   5521 	case GEOMETRY_SHADER:
   5522 		varying_name = m_varying_name_gs_fs_gs_result;
   5523 		break;
   5524 	case TESS_CONTROL_SHADER:
   5525 		varying_name = m_varying_name_tcs_tes_tcs_result;
   5526 		break;
   5527 	case TESS_EVAL_SHADER:
   5528 		varying_name = m_varying_name_tes_gs_tes_result;
   5529 		break;
   5530 	case VERTEX_SHADER:
   5531 		varying_name = m_varying_name_vs_tcs_vs_result;
   5532 		break;
   5533 	}
   5534 
   5535 	/* void main() */
   5536 	stream << "void main()\n"
   5537 			  "{\n";
   5538 
   5539 	/* Tesselation levels output */
   5540 	if (TESS_CONTROL_SHADER == shader_stage)
   5541 	{
   5542 		stream << "gl_TessLevelOuter[0] = 1.0;\n"
   5543 				  "gl_TessLevelOuter[1] = 1.0;\n"
   5544 				  "gl_TessLevelOuter[2] = 1.0;\n"
   5545 				  "gl_TessLevelOuter[3] = 1.0;\n"
   5546 				  "gl_TessLevelInner[0] = 1.0;\n"
   5547 				  "gl_TessLevelInner[1] = 1.0;\n"
   5548 				  "\n";
   5549 	}
   5550 
   5551 	/* For each "double precision" uniform
   5552 	 *
   5553 	 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
   5554 	 * {
   5555 	 *     VARYING_NAME = m_result_failure;
   5556 	 * }
   5557 	 */
   5558 	for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
   5559 		 end != it; ++it, ++type_ordinal)
   5560 	{
   5561 		stream << "    ";
   5562 
   5563 		/* First comparison is done with if, next with else if */
   5564 		if (1 != type_ordinal)
   5565 		{
   5566 			stream << "else ";
   5567 		}
   5568 
   5569 		/* if (TYPE_NAME( */
   5570 		stream << "if (" << it->m_type_name << "(";
   5571 
   5572 		/* PREDIFINED_VALUES */
   5573 		for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
   5574 		{
   5575 			stream << getExpectedValue(type_ordinal, element);
   5576 
   5577 			/* Separate with comma */
   5578 			if (it->m_n_elements != element + 1)
   5579 			{
   5580 				stream << ", ";
   5581 			}
   5582 		}
   5583 
   5584 		/*
   5585 		 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
   5586 		 * {
   5587 		 *     VARYING_NAME
   5588 		 */
   5589 		stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
   5590 																				   "    {\n"
   5591 																				   "        "
   5592 			   << varying_name;
   5593 
   5594 		/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
   5595 		if (TESS_CONTROL_SHADER == shader_stage)
   5596 		{
   5597 			stream << "[gl_InvocationID]";
   5598 		}
   5599 
   5600 		/*
   5601 		 * = m_result_failure;
   5602 		 * }
   5603 		 */
   5604 		stream << " = " << m_result_failure << ";\n"
   5605 			   << "    }\n";
   5606 	}
   5607 
   5608 	/* If all comparisons are ok
   5609 	 *
   5610 	 *     else
   5611 	 *     {
   5612 	 *         VARYING_NAME = m_result_success;
   5613 	 *     }
   5614 	 */
   5615 
   5616 	/*
   5617 	 * else
   5618 	 * {
   5619 	 *     VARYING_NAME
   5620 	 */
   5621 	stream << "    else\n"
   5622 			  "    {\n"
   5623 			  "        "
   5624 		   << varying_name;
   5625 
   5626 	/* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
   5627 	if (TESS_CONTROL_SHADER == shader_stage)
   5628 	{
   5629 		stream << "[gl_InvocationID]";
   5630 	}
   5631 
   5632 	/*
   5633 	 * = m_result_success;
   5634 	 * }
   5635 	 *
   5636 	 */
   5637 	stream << " = " << m_result_success << ";\n"
   5638 		   << "    }\n"
   5639 		   << "\n";
   5640 
   5641 	/* For each pair of "input/output" varyings
   5642 	 *
   5643 	 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
   5644 	 **/
   5645 	writeVaryingPassthrough(stream, shader_stage);
   5646 
   5647 	/* Geometry shader have to emit vertex */
   5648 	if (GEOMETRY_SHADER == shader_stage)
   5649 	{
   5650 		stream << "\n"
   5651 				  "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
   5652 				  "EmitVertex();\n"
   5653 				  "EndPrimitive();\n";
   5654 	}
   5655 
   5656 	/* Close scope of main */
   5657 	stream << "}\n\n";
   5658 }
   5659 
   5660 /** Write shader preamble to stream
   5661  *
   5662  * @param stream       Output stream with source code of shader
   5663  * @param shader_stage Shader stage
   5664  **/
   5665 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
   5666 {
   5667 	stream << "#version 400 core\n"
   5668 			  "\n"
   5669 			  "precision highp float;\n"
   5670 			  "\n";
   5671 
   5672 	switch (shader_stage)
   5673 	{
   5674 	case FRAGMENT_SHADER:
   5675 		break;
   5676 	case GEOMETRY_SHADER:
   5677 		stream << "layout(points)                   in;\n"
   5678 				  "layout(points, max_vertices = 1) out;\n"
   5679 				  "\n";
   5680 		break;
   5681 	case TESS_CONTROL_SHADER:
   5682 		stream << "layout(vertices = 1) out;\n"
   5683 				  "\n";
   5684 		break;
   5685 	case TESS_EVAL_SHADER:
   5686 		stream << "layout(isolines, point_mode) in;\n"
   5687 				  "\n";
   5688 		break;
   5689 	case VERTEX_SHADER:
   5690 		break;
   5691 	}
   5692 }
   5693 
   5694 /** Write name uniform blcok definition with specific layout to stream
   5695  *
   5696  * @param stream              Output stream with source code of shader
   5697  * @param uniform_data_layout Buffer layout
   5698  **/
   5699 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
   5700 {
   5701 	const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
   5702 
   5703 	stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
   5704 																			 "{\n"
   5705 																			 "    ivec3   dummy1[3];\n"
   5706 																			 "    double  double_value;\n"
   5707 																			 "    bool    dummy2;\n"
   5708 																			 "    dvec2   dvec2_value;\n"
   5709 																			 "    bvec3   dummy3;\n"
   5710 																			 "    dvec3   dvec3_value;\n"
   5711 																			 "    int     dummy4[3];\n"
   5712 																			 "    dvec4   dvec4_value;\n"
   5713 																			 "    bool    dummy5;\n"
   5714 																			 "    bool    dummy6[2];\n"
   5715 																			 "    dmat2   dmat2_value;\n"
   5716 																			 "    dmat3   dmat3_value;\n"
   5717 																			 "    bool    dummy7;\n"
   5718 																			 "    dmat4   dmat4_value;\n"
   5719 																			 "    dmat2x3 dmat2x3_value;\n"
   5720 																			 "    uvec3   dummy8;\n"
   5721 																			 "    dmat2x4 dmat2x4_value;\n"
   5722 																			 "    dmat3x2 dmat3x2_value;\n"
   5723 																			 "    bool    dummy9;\n"
   5724 																			 "    dmat3x4 dmat3x4_value;\n"
   5725 																			 "    int     dummy10;\n"
   5726 																			 "    dmat4x2 dmat4x2_value;\n"
   5727 																			 "    dmat4x3 dmat4x3_value;\n"
   5728 																			 "} "
   5729 		   << m_uniform_block_instance_name << ";\n";
   5730 
   5731 	stream << "\n";
   5732 }
   5733 
   5734 /** Write definitions of varyings specific for given <shader_stage> to stream
   5735  *
   5736  * @param stream       Output stream with source code of shader
   5737  * @param shader_stage Shader stage
   5738  **/
   5739 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
   5740 {
   5741 	static const glw::GLchar* const varying_type = "int";
   5742 
   5743 	switch (shader_stage)
   5744 	{
   5745 	case FRAGMENT_SHADER:
   5746 
   5747 		/* In */
   5748 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
   5749 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
   5750 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
   5751 		stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
   5752 
   5753 		stream << "\n";
   5754 
   5755 		/* Out */
   5756 		stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
   5757 
   5758 		break;
   5759 
   5760 	case GEOMETRY_SHADER:
   5761 
   5762 		/* In */
   5763 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
   5764 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
   5765 		stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
   5766 
   5767 		stream << "\n";
   5768 
   5769 		/* Out */
   5770 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
   5771 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
   5772 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
   5773 		stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
   5774 
   5775 		break;
   5776 
   5777 	case TESS_CONTROL_SHADER:
   5778 
   5779 		/* In */
   5780 		stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
   5781 
   5782 		stream << "\n";
   5783 
   5784 		/* Out */
   5785 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
   5786 		stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
   5787 
   5788 		break;
   5789 
   5790 	case TESS_EVAL_SHADER:
   5791 
   5792 		/* In */
   5793 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
   5794 		stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
   5795 
   5796 		stream << "\n";
   5797 
   5798 		/* Out */
   5799 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
   5800 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
   5801 		stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
   5802 
   5803 		break;
   5804 
   5805 	case VERTEX_SHADER:
   5806 
   5807 		/* Out */
   5808 		stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
   5809 
   5810 		break;
   5811 	}
   5812 
   5813 	stream << "\n";
   5814 }
   5815 
   5816 /** Write passthrough code of "input/output" varying pairs to stream
   5817  *
   5818  * @param stream       Output stream with source code of shader
   5819  * @param shader_stage Shader stage
   5820  **/
   5821 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
   5822 {
   5823 	switch (shader_stage)
   5824 	{
   5825 	case FRAGMENT_SHADER:
   5826 		break;
   5827 
   5828 	case GEOMETRY_SHADER:
   5829 
   5830 		stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
   5831 		stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
   5832 		stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
   5833 
   5834 		break;
   5835 
   5836 	case TESS_CONTROL_SHADER:
   5837 
   5838 		stream << "    " << m_varying_name_tcs_tes_vs_result
   5839 			   << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
   5840 
   5841 		break;
   5842 
   5843 	case TESS_EVAL_SHADER:
   5844 
   5845 		stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
   5846 		stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
   5847 
   5848 		break;
   5849 
   5850 	case VERTEX_SHADER:
   5851 
   5852 		break;
   5853 	}
   5854 }
   5855 
   5856 /** Constructor. Sets all uniform locations to -1 and sets all
   5857  *  values to 0.
   5858  */
   5859 GPUShaderFP64Test4::_data::_data()
   5860 {
   5861 	memset(&uniform_double, 0, sizeof(uniform_double));
   5862 	memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
   5863 	memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
   5864 	memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
   5865 	memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
   5866 	memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
   5867 	memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
   5868 
   5869 	uniform_location_double		   = -1;
   5870 	uniform_location_double_arr[0] = -1;
   5871 	uniform_location_double_arr[1] = -1;
   5872 	uniform_location_dvec2		   = -1;
   5873 	uniform_location_dvec2_arr[0]  = -1;
   5874 	uniform_location_dvec2_arr[1]  = -1;
   5875 	uniform_location_dvec3		   = -1;
   5876 	uniform_location_dvec3_arr[0]  = -1;
   5877 	uniform_location_dvec3_arr[1]  = -1;
   5878 	uniform_location_dvec4		   = -1;
   5879 	uniform_location_dvec4_arr[0]  = -1;
   5880 	uniform_location_dvec4_arr[1]  = -1;
   5881 }
   5882 
   5883 /** Constructor
   5884  *
   5885  *  @param context Rendering context.
   5886  */
   5887 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
   5888 	: TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
   5889 									   " report correct properties of & values assigned to double-precision uniforms.")
   5890 	, m_has_test_passed(true)
   5891 	, m_uniform_name_buffer(0)
   5892 	, m_cs_id(0)
   5893 	, m_fs_id(0)
   5894 	, m_gs_id(0)
   5895 	, m_po_cs_id(0)
   5896 	, m_po_noncs_id(0)
   5897 	, m_tc_id(0)
   5898 	, m_te_id(0)
   5899 	, m_vs_id(0)
   5900 {
   5901 	/* Left blank intentionally */
   5902 }
   5903 
   5904 /** Deinitializes all GL objects, as well as releases all bufers, that may
   5905  *  have beenallocated or  created during test execution.
   5906  **/
   5907 void GPUShaderFP64Test4::deinit()
   5908 {
   5909 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   5910 
   5911 	if (m_cs_id != 0)
   5912 	{
   5913 		gl.deleteShader(m_cs_id);
   5914 
   5915 		m_cs_id = 0;
   5916 	}
   5917 
   5918 	if (m_fs_id != 0)
   5919 	{
   5920 		gl.deleteShader(m_fs_id);
   5921 
   5922 		m_fs_id = 0;
   5923 	}
   5924 
   5925 	if (m_gs_id != 0)
   5926 	{
   5927 		gl.deleteShader(m_gs_id);
   5928 
   5929 		m_gs_id = 0;
   5930 	}
   5931 
   5932 	if (m_po_cs_id != 0)
   5933 	{
   5934 		gl.deleteProgram(m_po_cs_id);
   5935 
   5936 		m_po_cs_id = 0;
   5937 	}
   5938 
   5939 	if (m_po_noncs_id != 0)
   5940 	{
   5941 		gl.deleteProgram(m_po_noncs_id);
   5942 
   5943 		m_po_noncs_id = 0;
   5944 	}
   5945 
   5946 	if (m_tc_id != 0)
   5947 	{
   5948 		gl.deleteShader(m_tc_id);
   5949 
   5950 		m_tc_id = 0;
   5951 	}
   5952 
   5953 	if (m_te_id != 0)
   5954 	{
   5955 		gl.deleteShader(m_te_id);
   5956 
   5957 		m_te_id = 0;
   5958 	}
   5959 
   5960 	if (m_uniform_name_buffer != DE_NULL)
   5961 	{
   5962 		delete[] m_uniform_name_buffer;
   5963 
   5964 		m_uniform_name_buffer = DE_NULL;
   5965 	}
   5966 
   5967 	if (m_vs_id != 0)
   5968 	{
   5969 		gl.deleteShader(m_vs_id);
   5970 
   5971 		m_vs_id = 0;
   5972 	}
   5973 }
   5974 
   5975 /** Generates double-precision values for all uniforms defined for all program objects
   5976  *  used by the test.
   5977  *
   5978  *  This function DOES NOT use any GL API. It only calculates & stores the values
   5979  *  in internal storage for further usage.
   5980  */
   5981 void GPUShaderFP64Test4::generateUniformValues()
   5982 {
   5983 	_stage_data*	   stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
   5984 	const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
   5985 
   5986 	for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
   5987 	{
   5988 		_stage_data* stage_ptr = stages[n_stage];
   5989 
   5990 		/* Iterate through all uniform components and assign them double values */
   5991 		double* double_ptrs[] = {
   5992 			&stage_ptr->uniform_structure_arrays[0].uniform_double,
   5993 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
   5994 			stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
   5995 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
   5996 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
   5997 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 2,
   5998 			stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 3,
   5999 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
   6000 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
   6001 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
   6002 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 3,
   6003 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 4,
   6004 			stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 5,
   6005 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
   6006 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
   6007 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
   6008 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
   6009 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 4,
   6010 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 5,
   6011 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 6,
   6012 			stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 7,
   6013 			&stage_ptr->uniform_structure_arrays[1].uniform_double,
   6014 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
   6015 			stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
   6016 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
   6017 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
   6018 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 2,
   6019 			stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 3,
   6020 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
   6021 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
   6022 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
   6023 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 3,
   6024 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 4,
   6025 			stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 5,
   6026 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
   6027 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
   6028 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
   6029 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
   6030 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 4,
   6031 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 5,
   6032 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 6,
   6033 			stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 7,
   6034 			&stage_ptr->uniforms.uniform_double,
   6035 			stage_ptr->uniforms.uniform_double_arr + 0,
   6036 			stage_ptr->uniforms.uniform_double_arr + 1,
   6037 			stage_ptr->uniforms.uniform_dvec2 + 0,
   6038 			stage_ptr->uniforms.uniform_dvec2 + 1,
   6039 			stage_ptr->uniforms.uniform_dvec2_arr + 0,
   6040 			stage_ptr->uniforms.uniform_dvec2_arr + 1,
   6041 			stage_ptr->uniforms.uniform_dvec2_arr + 2,
   6042 			stage_ptr->uniforms.uniform_dvec2_arr + 3,
   6043 			stage_ptr->uniforms.uniform_dvec3 + 0,
   6044 			stage_ptr->uniforms.uniform_dvec3 + 1,
   6045 			stage_ptr->uniforms.uniform_dvec3 + 2,
   6046 			stage_ptr->uniforms.uniform_dvec3_arr + 0,
   6047 			stage_ptr->uniforms.uniform_dvec3_arr + 1,
   6048 			stage_ptr->uniforms.uniform_dvec3_arr + 2,
   6049 			stage_ptr->uniforms.uniform_dvec3_arr + 3,
   6050 			stage_ptr->uniforms.uniform_dvec3_arr + 4,
   6051 			stage_ptr->uniforms.uniform_dvec3_arr + 5,
   6052 			stage_ptr->uniforms.uniform_dvec4 + 0,
   6053 			stage_ptr->uniforms.uniform_dvec4 + 1,
   6054 			stage_ptr->uniforms.uniform_dvec4 + 2,
   6055 			stage_ptr->uniforms.uniform_dvec4 + 3,
   6056 			stage_ptr->uniforms.uniform_dvec4_arr + 0,
   6057 			stage_ptr->uniforms.uniform_dvec4_arr + 1,
   6058 			stage_ptr->uniforms.uniform_dvec4_arr + 2,
   6059 			stage_ptr->uniforms.uniform_dvec4_arr + 3,
   6060 			stage_ptr->uniforms.uniform_dvec4_arr + 4,
   6061 			stage_ptr->uniforms.uniform_dvec4_arr + 5,
   6062 			stage_ptr->uniforms.uniform_dvec4_arr + 6,
   6063 			stage_ptr->uniforms.uniform_dvec4_arr + 7,
   6064 		};
   6065 		const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
   6066 
   6067 		for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
   6068 		{
   6069 			double* double_ptr = double_ptrs[n_double_ptr];
   6070 
   6071 			/* Generate the value. Use magic numbers to generate a set of double-precision
   6072 			 * floating-point numbers.
   6073 			 */
   6074 			static int seed = 16762362;
   6075 
   6076 			*double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
   6077 
   6078 			seed += 751;
   6079 		} /* for (all pointers to double variables) */
   6080 	}	 /* for (all stages) */
   6081 }
   6082 
   6083 /** Initializes all program & shader objects required to run the test. The function also
   6084  *  retrieves locations of all uniforms defined by both program objects.
   6085  **/
   6086 void GPUShaderFP64Test4::initProgramObjects()
   6087 {
   6088 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   6089 
   6090 	/* Create program & shader objects */
   6091 
   6092 	/* Compute shader support and GL 4.2 required */
   6093 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
   6094 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
   6095 	{
   6096 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
   6097 	}
   6098 
   6099 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   6100 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   6101 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
   6102 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
   6103 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   6104 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   6105 
   6106 	/* m_cs_id is initialized only if compute shaders are supported */
   6107 	if (0 != m_cs_id)
   6108 	{
   6109 		m_po_cs_id = gl.createProgram();
   6110 	}
   6111 
   6112 	m_po_noncs_id = gl.createProgram();
   6113 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
   6114 
   6115 	/* Configure compute shader body */
   6116 	const char* cs_body = "#version 420\n"
   6117 						  "#extension GL_ARB_compute_shader          : require\n"
   6118 						  "\n"
   6119 						  "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
   6120 						  "\n"
   6121 						  "layout(rgba32f) uniform image2D testImage;\n"
   6122 						  "\n"
   6123 						  "uniform double cs_double;\n"
   6124 						  "uniform dvec2  cs_dvec2;\n"
   6125 						  "uniform dvec3  cs_dvec3;\n"
   6126 						  "uniform dvec4  cs_dvec4;\n"
   6127 						  "uniform double cs_double_arr[2];\n"
   6128 						  "uniform dvec2  cs_dvec2_arr [2];\n"
   6129 						  "uniform dvec3  cs_dvec3_arr [2];\n"
   6130 						  "uniform dvec4  cs_dvec4_arr [2];\n"
   6131 						  "\n"
   6132 						  "uniform struct cs_struct\n"
   6133 						  "{\n"
   6134 						  "    double struct_double;\n"
   6135 						  "    dvec2  struct_dvec2;\n"
   6136 						  "    dvec3  struct_dvec3;\n"
   6137 						  "    dvec4  struct_dvec4;\n"
   6138 						  "} cs_array[2];\n"
   6139 						  "\n"
   6140 						  "void main()\n"
   6141 						  "{\n"
   6142 						  "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
   6143 						  "          * cs_dvec4.z                 *\n"
   6144 						  "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
   6145 						  "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
   6146 						  "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
   6147 						  "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
   6148 						  "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
   6149 						  "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
   6150 						  "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
   6151 						  "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
   6152 						  "\n"
   6153 						  "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
   6154 						  "}\n";
   6155 
   6156 	/* m_cs_id is initialized only if compute shaders are supported */
   6157 	if (0 != m_cs_id)
   6158 	{
   6159 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
   6160 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   6161 	}
   6162 
   6163 	/* Configure vertex shader body */
   6164 	const char* vs_body = "#version 400\n"
   6165 						  "\n"
   6166 						  "uniform double vs_double;\n"
   6167 						  "uniform dvec2  vs_dvec2;\n"
   6168 						  "uniform dvec3  vs_dvec3;\n"
   6169 						  "uniform dvec4  vs_dvec4;\n"
   6170 						  "uniform double vs_double_arr[2];\n"
   6171 						  "uniform dvec2  vs_dvec2_arr [2];\n"
   6172 						  "uniform dvec3  vs_dvec3_arr [2];\n"
   6173 						  "uniform dvec4  vs_dvec4_arr [2];\n"
   6174 						  "\n"
   6175 						  "uniform struct vs_struct\n"
   6176 						  "{\n"
   6177 						  "    double struct_double;\n"
   6178 						  "    dvec2  struct_dvec2;\n"
   6179 						  "    dvec3  struct_dvec3;\n"
   6180 						  "    dvec4  struct_dvec4;\n"
   6181 						  "} vs_array[2];\n"
   6182 						  "\n"
   6183 						  "void main()\n"
   6184 						  "{\n"
   6185 						  "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
   6186 						  "* vs_dvec4.x                 *\n"
   6187 						  "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
   6188 						  "* vs_dvec4_arr[0].x          *\n"
   6189 						  "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
   6190 						  "* vs_dvec4_arr[1].x          *\n"
   6191 						  "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
   6192 						  "* vs_array[0].struct_dvec4.x *\n"
   6193 						  "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
   6194 						  "* vs_array[1].struct_dvec4.x > 1.0)\n"
   6195 						  "    {\n"
   6196 						  "        gl_Position = vec4(0);\n"
   6197 						  "    }\n"
   6198 						  "    else\n"
   6199 						  "    {\n"
   6200 						  "        gl_Position = vec4(1);\n"
   6201 						  "    }\n"
   6202 						  "}\n";
   6203 
   6204 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
   6205 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   6206 
   6207 	/* Configure tessellation control shader body */
   6208 	const char* tc_body = "#version 400\n"
   6209 						  "\n"
   6210 						  "uniform double tc_double;\n"
   6211 						  "uniform dvec2  tc_dvec2;\n"
   6212 						  "uniform dvec3  tc_dvec3;\n"
   6213 						  "uniform dvec4  tc_dvec4;\n"
   6214 						  "uniform double tc_double_arr[2];\n"
   6215 						  "uniform dvec2  tc_dvec2_arr [2];\n"
   6216 						  "uniform dvec3  tc_dvec3_arr [2];\n"
   6217 						  "uniform dvec4  tc_dvec4_arr [2];\n"
   6218 						  "\n"
   6219 						  "uniform struct tc_struct\n"
   6220 						  "{\n"
   6221 						  "    double struct_double;\n"
   6222 						  "    dvec2  struct_dvec2;\n"
   6223 						  "    dvec3  struct_dvec3;\n"
   6224 						  "    dvec4  struct_dvec4;\n"
   6225 						  "} tc_array[2];\n"
   6226 						  "\n"
   6227 						  "layout(vertices = 4) out;\n"
   6228 						  "\n"
   6229 						  "void main()\n"
   6230 						  "{\n"
   6231 						  "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
   6232 						  "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
   6233 						  "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
   6234 						  "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
   6235 						  "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
   6236 						  "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
   6237 						  "\n"
   6238 						  "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
   6239 						  "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
   6240 						  "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
   6241 						  "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
   6242 						  "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
   6243 						  "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
   6244 						  "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
   6245 						  "    {\n"
   6246 						  "        gl_TessLevelInner[1] = 3.0;\n"
   6247 						  "    }\n"
   6248 						  "}\n";
   6249 
   6250 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
   6251 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   6252 
   6253 	/* Configure tessellation evaluation shader body */
   6254 	const char* te_body = "#version 400\n"
   6255 						  "\n"
   6256 						  "uniform double te_double;\n"
   6257 						  "uniform dvec2  te_dvec2;\n"
   6258 						  "uniform dvec3  te_dvec3;\n"
   6259 						  "uniform dvec4  te_dvec4;\n"
   6260 						  "uniform double te_double_arr[2];\n"
   6261 						  "uniform dvec2  te_dvec2_arr [2];\n"
   6262 						  "uniform dvec3  te_dvec3_arr [2];\n"
   6263 						  "uniform dvec4  te_dvec4_arr [2];\n"
   6264 						  "\n"
   6265 						  "uniform struct te_struct\n"
   6266 						  "{\n"
   6267 						  "    double struct_double;\n"
   6268 						  "    dvec2  struct_dvec2;\n"
   6269 						  "    dvec3  struct_dvec3;\n"
   6270 						  "    dvec4  struct_dvec4;\n"
   6271 						  "} te_array[2];\n"
   6272 						  "\n"
   6273 						  "layout(triangles) in;\n"
   6274 						  "\n"
   6275 						  "void main()\n"
   6276 						  "{\n"
   6277 						  "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
   6278 						  "* te_dvec4.x                 *\n"
   6279 						  "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
   6280 						  "* te_dvec4_arr[0].x          *\n"
   6281 						  "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
   6282 						  "* te_dvec4_arr[1].x          *\n"
   6283 						  "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
   6284 						  "* te_array[0].struct_dvec4.x *\n"
   6285 						  "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
   6286 						  "* te_array[1].struct_dvec4.x > 1.0)\n"
   6287 						  "    {\n"
   6288 						  "        gl_Position = gl_in[0].gl_Position;\n"
   6289 						  "    }\n"
   6290 						  "    else\n"
   6291 						  "    {\n"
   6292 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
   6293 						  "    }\n"
   6294 						  "}\n";
   6295 
   6296 	gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
   6297 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   6298 
   6299 	/* Configure geometry shader body */
   6300 	const char* gs_body = "#version 400\n"
   6301 						  "\n"
   6302 						  "uniform double gs_double;\n"
   6303 						  "uniform dvec2  gs_dvec2;\n"
   6304 						  "uniform dvec3  gs_dvec3;\n"
   6305 						  "uniform dvec4  gs_dvec4;\n"
   6306 						  "uniform double gs_double_arr[2];\n"
   6307 						  "uniform dvec2  gs_dvec2_arr [2];\n"
   6308 						  "uniform dvec3  gs_dvec3_arr [2];\n"
   6309 						  "uniform dvec4  gs_dvec4_arr [2];\n"
   6310 						  "\n"
   6311 						  "uniform struct gs_struct\n"
   6312 						  "{\n"
   6313 						  "    double struct_double;\n"
   6314 						  "    dvec2  struct_dvec2;\n"
   6315 						  "    dvec3  struct_dvec3;\n"
   6316 						  "    dvec4  struct_dvec4;\n"
   6317 						  "} gs_array[2];\n"
   6318 						  "\n"
   6319 						  "layout (points)                   in;\n"
   6320 						  "layout (points, max_vertices = 1) out;\n"
   6321 						  "\n"
   6322 						  "void main()\n"
   6323 						  "{\n"
   6324 						  "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
   6325 						  "* gs_dvec4.x        *\n"
   6326 						  "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
   6327 						  "* gs_dvec4_arr[0].x *\n"
   6328 						  "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
   6329 						  "* gs_dvec4_arr[1].x *\n"
   6330 						  "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
   6331 						  "* gs_array[0].struct_dvec4.x *\n"
   6332 						  "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
   6333 						  "* gs_array[1].struct_dvec4.x > 1.0)\n"
   6334 						  "    {\n"
   6335 						  "        gl_Position = gl_in[0].gl_Position;\n"
   6336 						  "    }\n"
   6337 						  "    else\n"
   6338 						  "    {\n"
   6339 						  "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
   6340 						  "    }\n"
   6341 						  "\n"
   6342 						  "    EmitVertex();\n"
   6343 						  "}\n";
   6344 
   6345 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
   6346 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   6347 
   6348 	/* Configure fragment shader body */
   6349 	const char* fs_body = "#version 400\n"
   6350 						  "\n"
   6351 						  "uniform double fs_double;\n"
   6352 						  "uniform dvec2  fs_dvec2;\n"
   6353 						  "uniform dvec3  fs_dvec3;\n"
   6354 						  "uniform dvec4  fs_dvec4;\n"
   6355 						  "uniform double fs_double_arr[2];\n"
   6356 						  "uniform dvec2  fs_dvec2_arr [2];\n"
   6357 						  "uniform dvec3  fs_dvec3_arr [2];\n"
   6358 						  "uniform dvec4  fs_dvec4_arr [2];\n"
   6359 						  "\n"
   6360 						  "uniform struct fs_struct\n"
   6361 						  "{\n"
   6362 						  "    double struct_double;\n"
   6363 						  "    dvec2  struct_dvec2;\n"
   6364 						  "    dvec3  struct_dvec3;\n"
   6365 						  "    dvec4  struct_dvec4;\n"
   6366 						  "} fs_array[2];\n"
   6367 						  "\n"
   6368 						  "out vec4 result;\n"
   6369 						  "\n"
   6370 						  "void main()\n"
   6371 						  "{\n"
   6372 						  "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
   6373 						  "* fs_dvec4.x        *\n"
   6374 						  "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
   6375 						  "* fs_dvec4_arr[0].x *\n"
   6376 						  "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
   6377 						  "* fs_dvec4_arr[1].x *\n"
   6378 						  "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
   6379 						  "* fs_array[0].struct_dvec4.x *\n"
   6380 						  "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
   6381 						  "* fs_array[1].struct_dvec4.x > 1.0)\n"
   6382 						  "    {\n"
   6383 						  "        result = vec4(0.0);\n"
   6384 						  "    }\n"
   6385 						  "    else\n"
   6386 						  "    {\n"
   6387 						  "        result = vec4(1.0);\n"
   6388 						  "    }\n"
   6389 						  "}\n";
   6390 
   6391 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
   6392 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
   6393 
   6394 	/* Compile the shaders */
   6395 	const glw::GLuint  shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
   6396 	const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
   6397 
   6398 	for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
   6399 	{
   6400 		glw::GLint  compile_status = GL_FALSE;
   6401 		glw::GLuint so_id		   = shaders[n_shader];
   6402 
   6403 		/* Skip compute shader if not supported */
   6404 		if (0 == so_id)
   6405 		{
   6406 			continue;
   6407 		}
   6408 
   6409 		gl.compileShader(so_id);
   6410 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
   6411 
   6412 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
   6413 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
   6414 
   6415 		if (compile_status != GL_TRUE)
   6416 		{
   6417 			TCU_FAIL("Shader compilation failed");
   6418 		}
   6419 
   6420 		if (so_id == m_cs_id)
   6421 		{
   6422 			gl.attachShader(m_po_cs_id, so_id);
   6423 		}
   6424 		else
   6425 		{
   6426 			gl.attachShader(m_po_noncs_id, so_id);
   6427 		}
   6428 
   6429 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
   6430 	} /* for (all shaders) */
   6431 
   6432 	/* Link the program */
   6433 	const glw::GLuint  programs[]  = { m_po_cs_id, m_po_noncs_id };
   6434 	const unsigned int n_programs  = sizeof(programs) / sizeof(programs[0]);
   6435 	glw::GLint		   link_status = GL_FALSE;
   6436 
   6437 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   6438 	{
   6439 		glw::GLuint po_id = programs[n_program];
   6440 
   6441 		/* Skip compute shader program if not supported */
   6442 		if (0 == po_id)
   6443 		{
   6444 			continue;
   6445 		}
   6446 
   6447 		gl.linkProgram(po_id);
   6448 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   6449 
   6450 		gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
   6451 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
   6452 
   6453 		if (link_status != GL_TRUE)
   6454 		{
   6455 			TCU_FAIL("Program linking failed");
   6456 		}
   6457 	} /* for (both program objects) */
   6458 
   6459 	/* Retrieve uniform locations */
   6460 	_stage_data*			  cs_stage_data[]		= { &m_data_cs };
   6461 	static const char*		  cs_uniform_prefixes[] = { "cs_" };
   6462 	static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
   6463 
   6464 	_stage_data*			  noncs_stage_data[]	   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
   6465 	static const char*		  noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
   6466 	static const unsigned int n_noncs_uniform_prefixes =
   6467 		sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
   6468 
   6469 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   6470 	{
   6471 		unsigned int  n_uniform_prefixes = DE_NULL;
   6472 		glw::GLuint   po_id				 = programs[n_program];
   6473 		_stage_data** stages_data		 = DE_NULL;
   6474 		const char**  uniform_prefixes   = DE_NULL;
   6475 
   6476 		if (n_program == 0)
   6477 		{
   6478 			stages_data		   = cs_stage_data;
   6479 			uniform_prefixes   = cs_uniform_prefixes;
   6480 			n_uniform_prefixes = n_cs_uniform_prefixes;
   6481 		}
   6482 		else
   6483 		{
   6484 			stages_data		   = noncs_stage_data;
   6485 			uniform_prefixes   = noncs_uniform_prefixes;
   6486 			n_uniform_prefixes = n_noncs_uniform_prefixes;
   6487 		}
   6488 
   6489 		/* Skip compute shader program if not supported */
   6490 		if (0 == po_id)
   6491 		{
   6492 			continue;
   6493 		}
   6494 
   6495 		/* Uniform names used by the test program consist of a prefix (different for each
   6496 		 * shader stage) and a common part.
   6497 		 */
   6498 		for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
   6499 		{
   6500 			_stage_data* stage_data				  = stages_data[n_uniform_prefix];
   6501 			std::string  uniform_prefix			  = std::string(uniform_prefixes[n_uniform_prefix]);
   6502 			std::string  uniform_double_name	  = uniform_prefix + "double";
   6503 			std::string  uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
   6504 			std::string  uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
   6505 			std::string  uniform_dvec2_name		  = uniform_prefix + "dvec2";
   6506 			std::string  uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
   6507 			std::string  uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
   6508 			std::string  uniform_dvec3_name		  = uniform_prefix + "dvec3";
   6509 			std::string  uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
   6510 			std::string  uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
   6511 			std::string  uniform_dvec4_name		  = uniform_prefix + "dvec4";
   6512 			std::string  uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
   6513 			std::string  uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
   6514 			std::string  uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
   6515 			std::string  uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
   6516 			std::string  uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
   6517 			std::string  uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
   6518 			std::string  uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
   6519 			std::string  uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
   6520 			std::string  uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
   6521 			std::string  uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
   6522 
   6523 			/* Retrieve uniform locations */
   6524 			stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
   6525 			stage_data->uniforms.uniform_location_double_arr[0] =
   6526 				gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
   6527 			stage_data->uniforms.uniform_location_double_arr[1] =
   6528 				gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
   6529 			stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
   6530 			stage_data->uniforms.uniform_location_dvec2_arr[0] =
   6531 				gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
   6532 			stage_data->uniforms.uniform_location_dvec2_arr[1] =
   6533 				gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
   6534 			stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
   6535 			stage_data->uniforms.uniform_location_dvec3_arr[0] =
   6536 				gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
   6537 			stage_data->uniforms.uniform_location_dvec3_arr[1] =
   6538 				gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
   6539 			stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
   6540 			stage_data->uniforms.uniform_location_dvec4_arr[0] =
   6541 				gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
   6542 			stage_data->uniforms.uniform_location_dvec4_arr[1] =
   6543 				gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
   6544 			stage_data->uniform_structure_arrays[0].uniform_location_double =
   6545 				gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
   6546 			stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
   6547 				gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
   6548 			stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
   6549 				gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
   6550 			stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
   6551 				gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
   6552 			stage_data->uniform_structure_arrays[1].uniform_location_double =
   6553 				gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
   6554 			stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
   6555 				gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
   6556 			stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
   6557 				gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
   6558 			stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
   6559 				gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
   6560 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
   6561 
   6562 			if (stage_data->uniforms.uniform_location_double == -1 ||
   6563 				stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
   6564 				stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
   6565 				stage_data->uniforms.uniform_location_dvec2 == -1 ||
   6566 				stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
   6567 				stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
   6568 				stage_data->uniforms.uniform_location_dvec3 == -1 ||
   6569 				stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
   6570 				stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
   6571 				stage_data->uniforms.uniform_location_dvec4 == -1 ||
   6572 				stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
   6573 				stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
   6574 				stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
   6575 				stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
   6576 				stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
   6577 				stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
   6578 				stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
   6579 				stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
   6580 				stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
   6581 				stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
   6582 			{
   6583 				TCU_FAIL("At least one uniform is considered inactive which is invalid.");
   6584 			}
   6585 
   6586 			/* Make sure locations of subsequent items in array uniforms are correct */
   6587 			if (stage_data->uniforms.uniform_location_double_arr[1] !=
   6588 					(stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
   6589 				stage_data->uniforms.uniform_location_dvec2_arr[1] !=
   6590 					(stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
   6591 				stage_data->uniforms.uniform_location_dvec3_arr[1] !=
   6592 					(stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
   6593 				stage_data->uniforms.uniform_location_dvec4_arr[1] !=
   6594 					(stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
   6595 			{
   6596 				m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
   6597 															   " double_arr[0]:"
   6598 								   << stage_data->uniforms.uniform_location_double_arr[0]
   6599 								   << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
   6600 								   << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
   6601 								   << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
   6602 								   << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
   6603 								   << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
   6604 								   << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
   6605 								   << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
   6606 								   << tcu::TestLog::EndMessage;
   6607 
   6608 				TCU_FAIL("Double-precision uniform array item locations are invalid.");
   6609 			}
   6610 		} /* for (all uniform prefixes) */
   6611 	}	 /* for (both program objects) */
   6612 }
   6613 
   6614 /** Initializes all objects required to run the test. */
   6615 void GPUShaderFP64Test4::initTest()
   6616 {
   6617 	initProgramObjects();
   6618 
   6619 	generateUniformValues();
   6620 	initUniformValues();
   6621 }
   6622 
   6623 /** Assigns values generated by generateUniformValues() to uniforms defined by
   6624  *  both program objects.
   6625  **/
   6626 void GPUShaderFP64Test4::initUniformValues()
   6627 {
   6628 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   6629 
   6630 	/* Iterate through all programs */
   6631 	_stage_data*	   cs_stages[]	= { &m_data_cs };
   6632 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
   6633 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
   6634 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
   6635 
   6636 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
   6637 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
   6638 
   6639 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   6640 	{
   6641 		glw::GLuint   po_id		 = programs[n_program];
   6642 		unsigned int  n_stages   = 0;
   6643 		_stage_data** stage_data = DE_NULL;
   6644 
   6645 		if (po_id == m_po_cs_id)
   6646 		{
   6647 			n_stages   = n_cs_stages;
   6648 			stage_data = cs_stages;
   6649 		}
   6650 		else
   6651 		{
   6652 			n_stages   = n_noncs_stages;
   6653 			stage_data = noncs_stages;
   6654 		}
   6655 
   6656 		/* Skip compute shader program if not supported */
   6657 		if (0 == po_id)
   6658 		{
   6659 			continue;
   6660 		}
   6661 
   6662 		gl.useProgram(po_id);
   6663 		GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
   6664 
   6665 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
   6666 		{
   6667 			/* Iterate through all uniforms */
   6668 			_stage_data* stage_ptr = stage_data[n_stage];
   6669 
   6670 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
   6671 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
   6672 			gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
   6673 			gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
   6674 						 stage_ptr->uniform_structure_arrays[0].uniform_double);
   6675 			gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
   6676 						 stage_ptr->uniform_structure_arrays[1].uniform_double);
   6677 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
   6678 
   6679 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
   6680 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
   6681 						  stage_ptr->uniforms.uniform_dvec2_arr + 0);
   6682 			gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
   6683 						  stage_ptr->uniforms.uniform_dvec2_arr + 2);
   6684 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
   6685 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
   6686 			gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
   6687 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
   6688 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
   6689 
   6690 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
   6691 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
   6692 						  stage_ptr->uniforms.uniform_dvec3_arr + 0);
   6693 			gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
   6694 						  stage_ptr->uniforms.uniform_dvec3_arr + 3);
   6695 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
   6696 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
   6697 			gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
   6698 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
   6699 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
   6700 
   6701 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
   6702 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
   6703 						  stage_ptr->uniforms.uniform_dvec4_arr + 0);
   6704 			gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
   6705 						  stage_ptr->uniforms.uniform_dvec4_arr + 4);
   6706 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
   6707 						  stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
   6708 			gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
   6709 						  stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
   6710 			GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
   6711 		} /* for (all shader stages) */
   6712 	}	 /* for (both program objects) */
   6713 }
   6714 
   6715 /** Executes test iteration.
   6716  *
   6717  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   6718  */
   6719 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
   6720 {
   6721 	/* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
   6722 
   6723 	/* Initialize all objects required to run the test */
   6724 	initTest();
   6725 
   6726 	/* Verify the implementation reports correct values for all stages we've configured */
   6727 	m_has_test_passed &= verifyUniformValues();
   6728 
   6729 	/* Is this also the case when "program interface query" mechanism is used? */
   6730 	if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
   6731 	{
   6732 		m_has_test_passed &= verifyProgramInterfaceQuerySupport();
   6733 	}
   6734 
   6735 	/* We're done */
   6736 	if (m_has_test_passed)
   6737 	{
   6738 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   6739 	}
   6740 	else
   6741 	{
   6742 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   6743 	}
   6744 
   6745 	return STOP;
   6746 }
   6747 
   6748 /** Verifies that:
   6749  *
   6750  *  a) glGetProgramResourceIndex()
   6751  *  b) glGetProgramResourceiv()
   6752  *  c) glGetProgramResourceName()
   6753  *
   6754  *  functions return correct values for double-precision uniforms.
   6755  *
   6756  *  @return true if the verification was passed, false otherwise.
   6757  */
   6758 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
   6759 {
   6760 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
   6761 	bool				  result = true;
   6762 
   6763 	/* Iterate through all programs */
   6764 	const char*		   cs_prefixes[]	= { "cs_" };
   6765 	_stage_data*	   cs_stages[]		= { &m_data_cs };
   6766 	const char*		   noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
   6767 	_stage_data*	   noncs_stages[]   = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
   6768 	const unsigned int n_cs_stages		= sizeof(cs_stages) / sizeof(cs_stages[0]);
   6769 	const unsigned int n_noncs_stages   = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
   6770 
   6771 	const glw::GLuint  programs[] = { m_po_cs_id, m_po_noncs_id };
   6772 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
   6773 
   6774 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   6775 	{
   6776 		glw::GLuint   po_id			 = programs[n_program];
   6777 		unsigned int  n_stages		 = 0;
   6778 		const char**  stage_prefixes = DE_NULL;
   6779 		_stage_data** stage_data	 = DE_NULL;
   6780 
   6781 		if (po_id == m_po_cs_id)
   6782 		{
   6783 			n_stages	   = n_cs_stages;
   6784 			stage_data	 = cs_stages;
   6785 			stage_prefixes = cs_prefixes;
   6786 		}
   6787 		else
   6788 		{
   6789 			n_stages	   = n_noncs_stages;
   6790 			stage_data	 = noncs_stages;
   6791 			stage_prefixes = noncs_prefixes;
   6792 		}
   6793 
   6794 		/* Skip compute shader program if not supported */
   6795 		if (0 == po_id)
   6796 		{
   6797 			continue;
   6798 		}
   6799 
   6800 		/* Determine maximum uniform name length */
   6801 		glw::GLint max_uniform_name_length = 0;
   6802 
   6803 		gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
   6804 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
   6805 
   6806 		/* Allocate a buffer we will use to hold uniform names */
   6807 		m_uniform_name_buffer = new char[max_uniform_name_length];
   6808 
   6809 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
   6810 		{
   6811 			/* Iterate through all uniforms */
   6812 			_stage_data* stage_ptr	= stage_data[n_stage];
   6813 			const char*  stage_prefix = stage_prefixes[n_stage];
   6814 
   6815 			/* Construct an array that will be used to run the test in an automated manner */
   6816 			_program_interface_query_test_item uniforms[] = {
   6817 				/* array size */ /* name */ /* type */ /* location */
   6818 				{ 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
   6819 				{ 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
   6820 				{ 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
   6821 				{ 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
   6822 				{ 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
   6823 				{ 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
   6824 				{ 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
   6825 				{ 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
   6826 				{ 1, "array[0].struct_double", GL_DOUBLE,
   6827 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
   6828 				{ 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
   6829 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
   6830 				{ 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
   6831 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
   6832 				{ 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
   6833 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
   6834 				{ 1, "array[1].struct_double", GL_DOUBLE,
   6835 				  stage_ptr->uniform_structure_arrays->uniform_location_double },
   6836 				{ 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
   6837 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
   6838 				{ 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
   6839 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
   6840 				{ 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
   6841 				  stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
   6842 			};
   6843 			const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
   6844 
   6845 			/* Prefix the names with stage-specific string */
   6846 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
   6847 			{
   6848 				_program_interface_query_test_item& current_item = uniforms[n_uniform];
   6849 
   6850 				current_item.name = std::string(stage_prefix) + current_item.name;
   6851 			} /* for (all uniform descriptors) */
   6852 
   6853 			const glw::GLenum  properties[] = { GL_ARRAY_SIZE, GL_TYPE };
   6854 			const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
   6855 
   6856 			for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
   6857 			{
   6858 				_program_interface_query_test_item& current_item		  = uniforms[n_uniform];
   6859 				glw::GLint							n_written_items		  = 0;
   6860 				glw::GLint							retrieved_array_size  = 0;
   6861 				glw::GLint							retrieved_name_length = 0;
   6862 				glw::GLenum							retrieved_type		  = GL_NONE;
   6863 				glw::GLint							temp_buffer[2]		  = { 0, GL_NONE };
   6864 
   6865 				/* Retrieve index of the iteration-specific uniform */
   6866 				glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
   6867 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
   6868 
   6869 				/* Make sure glGetProgramResourceName() returns correct values */
   6870 				memset(m_uniform_name_buffer, 0, max_uniform_name_length);
   6871 
   6872 				gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
   6873 										  resource_index, max_uniform_name_length, &retrieved_name_length,
   6874 										  m_uniform_name_buffer);
   6875 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
   6876 
   6877 				if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
   6878 					memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
   6879 				{
   6880 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
   6881 									   << resource_index << "]"
   6882 															": expected:["
   6883 									   << current_item.name << "]"
   6884 															   ", reported:["
   6885 									   << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
   6886 
   6887 					result = false;
   6888 					continue;
   6889 				}
   6890 
   6891 				/* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
   6892 				gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
   6893 										resource_index, n_properties, properties,
   6894 										sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
   6895 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
   6896 
   6897 				if (n_written_items != n_properties)
   6898 				{
   6899 					TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
   6900 				}
   6901 
   6902 				/* For clarity, copy the retrieved values to separate variables */
   6903 				retrieved_array_size = temp_buffer[0];
   6904 				retrieved_type		 = temp_buffer[1];
   6905 
   6906 				/* Verify the values */
   6907 				if (retrieved_array_size != current_item.expected_array_size)
   6908 				{
   6909 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
   6910 									   << current_item.name << "]"
   6911 									   << ": expected:[" << current_item.expected_array_size << "]"
   6912 																								", reported:["
   6913 									   << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
   6914 
   6915 					result = false;
   6916 				}
   6917 
   6918 				if (retrieved_type != current_item.expected_type)
   6919 				{
   6920 					m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
   6921 									   << current_item.name << "]"
   6922 									   << ": expected:[" << current_item.expected_type << "]"
   6923 																						  ", reported:["
   6924 									   << retrieved_type << "]" << tcu::TestLog::EndMessage;
   6925 
   6926 					result = false;
   6927 				}
   6928 			} /* for (all uniforms) */
   6929 		}	 /* for (all shader stages) */
   6930 
   6931 		/* We're now OK to release the buffer we used to hold uniform names for
   6932 		 * the program */
   6933 		if (m_uniform_name_buffer != DE_NULL)
   6934 		{
   6935 			delete[] m_uniform_name_buffer;
   6936 
   6937 			m_uniform_name_buffer = DE_NULL;
   6938 		}
   6939 	} /* for (both program objects) */
   6940 
   6941 	return result;
   6942 }
   6943 
   6944 /** Verifies glGetUniform*() calls return correct values assigned to
   6945  *  double-precision uniforms.
   6946  *
   6947  *  @return true if all values reported by OpenGL were found to be correct,
   6948  *          false otherwise.
   6949  **/
   6950 bool GPUShaderFP64Test4::verifyUniformValues()
   6951 {
   6952 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
   6953 	bool				  result = true;
   6954 
   6955 	/* Iterate through all programs */
   6956 	_stage_data*	   cs_stages[]	= { &m_data_cs };
   6957 	_stage_data*	   noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
   6958 	const unsigned int n_cs_stages	= sizeof(cs_stages) / sizeof(cs_stages[0]);
   6959 	const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
   6960 
   6961 	const glw::GLuint programs[] = {
   6962 		m_po_noncs_id, m_po_cs_id,
   6963 	};
   6964 	const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
   6965 
   6966 	/* Set up rounding for the tests */
   6967 	deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
   6968 
   6969 	for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
   6970 	{
   6971 		glw::GLuint   po_id		 = programs[n_program];
   6972 		unsigned int  n_stages   = 0;
   6973 		_stage_data** stage_data = DE_NULL;
   6974 
   6975 		if (po_id == m_po_cs_id)
   6976 		{
   6977 			n_stages   = n_cs_stages;
   6978 			stage_data = cs_stages;
   6979 		}
   6980 		else
   6981 		{
   6982 			n_stages   = n_noncs_stages;
   6983 			stage_data = noncs_stages;
   6984 		}
   6985 
   6986 		/* Skip compute shader program if not supported */
   6987 		if (0 == po_id)
   6988 		{
   6989 			continue;
   6990 		}
   6991 
   6992 		for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
   6993 		{
   6994 			/* Iterate through all uniforms */
   6995 			_stage_data* stage_ptr = stage_data[n_stage];
   6996 
   6997 			/* Set up arrays that we will guide the automated testing */
   6998 			const uniform_value_pair double_uniforms[] = {
   6999 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
   7000 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
   7001 								   stage_ptr->uniforms.uniform_double_arr + 0),
   7002 				uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
   7003 								   stage_ptr->uniforms.uniform_double_arr + 1),
   7004 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
   7005 								   &stage_ptr->uniform_structure_arrays[0].uniform_double),
   7006 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
   7007 								   &stage_ptr->uniform_structure_arrays[1].uniform_double)
   7008 			};
   7009 			const uniform_value_pair dvec2_uniforms[] = {
   7010 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
   7011 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
   7012 								   stage_ptr->uniforms.uniform_dvec2_arr + 0),
   7013 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
   7014 								   stage_ptr->uniforms.uniform_dvec2_arr + 2),
   7015 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
   7016 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
   7017 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
   7018 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
   7019 			};
   7020 			const uniform_value_pair dvec3_uniforms[] = {
   7021 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
   7022 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
   7023 								   stage_ptr->uniforms.uniform_dvec3_arr + 0),
   7024 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
   7025 								   stage_ptr->uniforms.uniform_dvec3_arr + 3),
   7026 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
   7027 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
   7028 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
   7029 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
   7030 			};
   7031 			const uniform_value_pair dvec4_uniforms[] = {
   7032 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
   7033 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
   7034 								   stage_ptr->uniforms.uniform_dvec4_arr + 0),
   7035 				uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
   7036 								   stage_ptr->uniforms.uniform_dvec4_arr + 4),
   7037 				uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
   7038 								   stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
   7039 				uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
   7040 								   stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
   7041 			};
   7042 
   7043 			/* Iterate over all uniforms and verify the values reported by the API */
   7044 			double		 returned_double_data[4];
   7045 			float		 returned_float_data[4];
   7046 			int			 returned_int_data[4];
   7047 			unsigned int returned_uint_data[4];
   7048 
   7049 			for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
   7050 			{
   7051 				const uniform_value_pair* current_uv_pairs  = NULL;
   7052 				const unsigned int		  n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
   7053 				unsigned int			  n_pairs			= 0;
   7054 
   7055 				switch (n_type)
   7056 				{
   7057 				case 0: /* double */
   7058 				{
   7059 					current_uv_pairs = double_uniforms;
   7060 					n_pairs			 = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
   7061 
   7062 					break;
   7063 				}
   7064 
   7065 				case 1: /* dvec2 */
   7066 				{
   7067 					current_uv_pairs = dvec2_uniforms;
   7068 					n_pairs			 = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
   7069 
   7070 					break;
   7071 				}
   7072 
   7073 				case 2: /* dvec3 */
   7074 				{
   7075 					current_uv_pairs = dvec3_uniforms;
   7076 					n_pairs			 = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
   7077 
   7078 					break;
   7079 				}
   7080 
   7081 				case 3: /* dvec4 */
   7082 				{
   7083 					current_uv_pairs = dvec4_uniforms;
   7084 					n_pairs			 = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
   7085 
   7086 					break;
   7087 				}
   7088 
   7089 				default:
   7090 				{
   7091 					TCU_FAIL("Invalid type index requested");
   7092 				}
   7093 				} /* switch (n_type) */
   7094 
   7095 				for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
   7096 				{
   7097 					const uniform_value_pair& current_uv_pair  = current_uv_pairs[n_pair];
   7098 					glw::GLint				  uniform_location = current_uv_pair.first;
   7099 					const double*			  uniform_value	= current_uv_pair.second;
   7100 
   7101 					/* Retrieve the values from the GL implementation*/
   7102 					gl.getUniformdv(po_id, uniform_location, returned_double_data);
   7103 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
   7104 
   7105 					gl.getUniformfv(po_id, uniform_location, returned_float_data);
   7106 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
   7107 
   7108 					gl.getUniformiv(po_id, uniform_location, returned_int_data);
   7109 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
   7110 
   7111 					gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
   7112 					GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
   7113 
   7114 					/* Make sure the values reported match the reference values */
   7115 					bool		can_continue = true;
   7116 					const float epsilon		 = 1e-5f;
   7117 
   7118 					for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
   7119 					{
   7120 						if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
   7121 						{
   7122 							m_testCtx.getLog()
   7123 								<< tcu::TestLog::Message
   7124 								<< "Invalid uniform value reported by glGetUniformdv() for uniform location ["
   7125 								<< uniform_location << "]"
   7126 													   " and component ["
   7127 								<< n_component << "]"
   7128 												  ": retrieved:["
   7129 								<< returned_double_data[n_component] << "]"
   7130 																		", expected:["
   7131 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
   7132 
   7133 							result = false;
   7134 						}
   7135 
   7136 						if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
   7137 						{
   7138 							m_testCtx.getLog()
   7139 								<< tcu::TestLog::Message
   7140 								<< "Invalid uniform value reported by glGetUniformfv() for uniform location ["
   7141 								<< uniform_location << "]"
   7142 													   " and component ["
   7143 								<< n_component << "]"
   7144 												  ": retrieved:["
   7145 								<< returned_float_data[n_component] << "]"
   7146 																	   ", expected:["
   7147 								<< uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
   7148 
   7149 							result = false;
   7150 						}
   7151 
   7152 						/* ints */
   7153 						int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
   7154 						unsigned int rounded_uniform_value_uint =
   7155 							(unsigned int)(uniform_value[n_component] > 0.0) ?
   7156 								((unsigned int)deFloatRound((float)uniform_value[n_component])) :
   7157 								0;
   7158 
   7159 						if (returned_int_data[n_component] != rounded_uniform_value_sint)
   7160 						{
   7161 							m_testCtx.getLog()
   7162 								<< tcu::TestLog::Message
   7163 								<< "Invalid uniform value reported by glGetUniformiv() for uniform location ["
   7164 								<< uniform_location << "]"
   7165 													   " and component ["
   7166 								<< n_component << "]"
   7167 												  ": retrieved:["
   7168 								<< returned_int_data[n_component] << "]"
   7169 																	 ", expected:["
   7170 								<< rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
   7171 
   7172 							result = false;
   7173 						}
   7174 
   7175 						if (returned_uint_data[n_component] != rounded_uniform_value_uint)
   7176 						{
   7177 							m_testCtx.getLog()
   7178 								<< tcu::TestLog::Message
   7179 								<< "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
   7180 								<< uniform_location << "]"
   7181 													   " and component ["
   7182 								<< n_component << "]"
   7183 												  ": retrieved:["
   7184 								<< returned_uint_data[n_component] << "]"
   7185 																	  ", expected:["
   7186 								<< rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
   7187 
   7188 							result = false;
   7189 						}
   7190 					} /* for (all components) */
   7191 				}	 /* for (all uniform+value pairs) */
   7192 			}		  /* for (all 4 uniform types) */
   7193 		}			  /* for (all shader stages) */
   7194 	}				  /* for (both program objects) */
   7195 
   7196 	/* All done! */
   7197 	return result;
   7198 }
   7199 
   7200 /** Constructor
   7201  *
   7202  *  @param context Rendering context.
   7203  */
   7204 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
   7205 	: TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
   7206 									   " floating-point variables work correctly")
   7207 	, m_base_value_bo_data(DE_NULL)
   7208 	, m_base_value_bo_id(0)
   7209 	, m_has_test_passed(true)
   7210 	, m_po_base_value_attribute_location(-1)
   7211 	, m_po_id(0)
   7212 	, m_vao_id(0)
   7213 	, m_vs_id(0)
   7214 	, m_xfb_bo_id(0)
   7215 	, m_xfb_bo_size(0)
   7216 {
   7217 	/* Set up base value array (as per test spec) */
   7218 	m_base_values[0] = -25.12065f;
   7219 	m_base_values[1] = 0.0f;
   7220 	m_base_values[2] = 0.001f;
   7221 	m_base_values[3] = 1.0f;
   7222 	m_base_values[4] = 256.78901f;
   7223 
   7224 	/* Set up swizzle matrix */
   7225 	m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
   7226 	m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
   7227 	m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
   7228 	m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
   7229 	m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
   7230 	m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
   7231 	m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
   7232 	m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
   7233 	m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
   7234 	m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
   7235 	m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
   7236 	m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
   7237 	m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
   7238 	m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
   7239 	m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
   7240 	m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
   7241 }
   7242 
   7243 void GPUShaderFP64Test5::deinit()
   7244 {
   7245 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   7246 
   7247 	if (m_base_value_bo_data != DE_NULL)
   7248 	{
   7249 		delete[] m_base_value_bo_data;
   7250 
   7251 		m_base_value_bo_data = DE_NULL;
   7252 	}
   7253 
   7254 	if (m_base_value_bo_id != 0)
   7255 	{
   7256 		gl.deleteBuffers(1, &m_base_value_bo_id);
   7257 
   7258 		m_base_value_bo_id = 0;
   7259 	}
   7260 
   7261 	if (m_vao_id != 0)
   7262 	{
   7263 		gl.deleteVertexArrays(1, &m_vao_id);
   7264 
   7265 		m_vao_id = 0;
   7266 	}
   7267 
   7268 	if (m_xfb_bo_id != 0)
   7269 	{
   7270 		gl.deleteBuffers(1, &m_xfb_bo_id);
   7271 
   7272 		m_xfb_bo_id = 0;
   7273 	}
   7274 
   7275 	/* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
   7276 	 * take care of it here
   7277 	 */
   7278 	deinitInteration();
   7279 }
   7280 
   7281 /** Deinitializes all buffers and GL objects that may have been generated
   7282  *  during test execution.
   7283  **/
   7284 void GPUShaderFP64Test5::deinitInteration()
   7285 {
   7286 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   7287 
   7288 	if (m_po_id != 0)
   7289 	{
   7290 		gl.deleteProgram(m_po_id);
   7291 
   7292 		m_po_id = 0;
   7293 	}
   7294 
   7295 	if (m_vs_id != 0)
   7296 	{
   7297 		gl.deleteShader(m_vs_id);
   7298 
   7299 		m_vs_id = 0;
   7300 	}
   7301 }
   7302 
   7303 /** Executes a single test case iteration using user-provided test case descriptor.
   7304  *
   7305  *  This function may throw a TestError exception if GL implementation misbehaves.
   7306  *
   7307  *  @param test_case Test case descriptor to use.
   7308  *
   7309  *  @return true if the values returned by GL implementation were found to be valid,
   7310  *          false otherwise.
   7311  **/
   7312 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
   7313 {
   7314 	bool result = true;
   7315 
   7316 	/* Convert the base values array to the type of input attribute we'll be using
   7317 	 * for the iteration.
   7318 	 */
   7319 	Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
   7320 
   7321 	if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
   7322 	{
   7323 		/* bools are actually represented by ints, since bool varyings are not allowed */
   7324 		base_value_type = Utils::VARIABLE_TYPE_INT;
   7325 	}
   7326 
   7327 	const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
   7328 	const unsigned int n_base_values			 = sizeof(m_base_values) / sizeof(m_base_values[0]);
   7329 
   7330 	m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
   7331 
   7332 	unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
   7333 
   7334 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
   7335 	{
   7336 		switch (base_value_type)
   7337 		{
   7338 		case Utils::VARIABLE_TYPE_DOUBLE:
   7339 			*((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
   7340 			break;
   7341 		case Utils::VARIABLE_TYPE_FLOAT:
   7342 			*((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
   7343 			break;
   7344 		case Utils::VARIABLE_TYPE_INT:
   7345 			*((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
   7346 			break;
   7347 		case Utils::VARIABLE_TYPE_UINT:
   7348 			*((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
   7349 			break;
   7350 
   7351 		default:
   7352 		{
   7353 			TCU_FAIL("Unrecognized base value type");
   7354 		}
   7355 		}
   7356 
   7357 		base_value_traveller_ptr += base_value_component_size;
   7358 	} /* for (all base values) */
   7359 
   7360 	/* Update buffer object storage with the data we've just finished preparing. */
   7361 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   7362 
   7363 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
   7364 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   7365 
   7366 	gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
   7367 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
   7368 
   7369 	/* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
   7370 	 * new data is interpreted correctly.
   7371 	 */
   7372 	if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
   7373 	{
   7374 		gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,							  /* size */
   7375 							   Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
   7376 							   0,																  /* stride */
   7377 							   DE_NULL);														  /* pointer */
   7378 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
   7379 	}
   7380 	else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
   7381 	{
   7382 		gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,						/* size */
   7383 								Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
   7384 								DE_NULL);													/* pointer */
   7385 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
   7386 	}
   7387 	else
   7388 	{
   7389 		DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
   7390 
   7391 		gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
   7392 								GL_DOUBLE, 0,						   /* stride */
   7393 								DE_NULL);							   /* pointer */
   7394 		GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
   7395 	}
   7396 
   7397 	gl.enableVertexAttribArray(m_po_base_value_attribute_location);
   7398 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
   7399 
   7400 	/* Execute the draw call */
   7401 	gl.useProgram(m_po_id);
   7402 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   7403 
   7404 	gl.beginTransformFeedback(GL_POINTS);
   7405 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
   7406 	{
   7407 		gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
   7408 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
   7409 	}
   7410 	gl.endTransformFeedback();
   7411 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
   7412 
   7413 	/* Map the XFB buffer object into process space */
   7414 	void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   7415 
   7416 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
   7417 	DE_ASSERT(xfb_data_ptr != NULL);
   7418 
   7419 	/* Verify the data */
   7420 	result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
   7421 
   7422 	/* Unmap the XFB BO */
   7423 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   7424 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   7425 
   7426 	/** Good to release the data buffer at this point */
   7427 	if (m_base_value_bo_data != DE_NULL)
   7428 	{
   7429 		delete[] m_base_value_bo_data;
   7430 
   7431 		m_base_value_bo_data = DE_NULL;
   7432 	}
   7433 
   7434 	/* All done */
   7435 	return result;
   7436 }
   7437 
   7438 /** Returns properties of a swizzle operator described by @param type swizzle type.
   7439  *
   7440  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
   7441  *                             corresponding to the specific swizzle operator.
   7442  *                             Must not be NULL.
   7443  *  @param out_n_components    Deref will be used to store the amount of components
   7444  *                             used by the operator. Must not be NULL.
   7445  *  @param out_component_order Deref will be used to store up to 4 integer values,
   7446  *                             corresponding to component indices described by the
   7447  *                             operator for a particular position.  Must not be NULL.
   7448  **/
   7449 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
   7450 												  unsigned int* out_n_components, unsigned int* out_component_order)
   7451 {
   7452 	unsigned int result_component_order[4] = { 0 };
   7453 	unsigned int result_n_components	   = 0;
   7454 	std::string  result_swizzle_string;
   7455 
   7456 	switch (type)
   7457 	{
   7458 	case SWIZZLE_TYPE_NONE:
   7459 	{
   7460 		result_swizzle_string = "";
   7461 		result_n_components   = 0;
   7462 
   7463 		break;
   7464 	}
   7465 
   7466 	case SWIZZLE_TYPE_XWZY:
   7467 	{
   7468 		result_swizzle_string	 = "xwzy";
   7469 		result_n_components		  = 4;
   7470 		result_component_order[0] = 0;
   7471 		result_component_order[1] = 3;
   7472 		result_component_order[2] = 2;
   7473 		result_component_order[3] = 1;
   7474 
   7475 		break;
   7476 	}
   7477 
   7478 	case SWIZZLE_TYPE_XZXY:
   7479 	{
   7480 		result_swizzle_string	 = "xzxy";
   7481 		result_n_components		  = 4;
   7482 		result_component_order[0] = 0;
   7483 		result_component_order[1] = 2;
   7484 		result_component_order[2] = 0;
   7485 		result_component_order[3] = 1;
   7486 
   7487 		break;
   7488 	}
   7489 
   7490 	case SWIZZLE_TYPE_XZY:
   7491 	{
   7492 		result_swizzle_string	 = "xzy";
   7493 		result_n_components		  = 3;
   7494 		result_component_order[0] = 0;
   7495 		result_component_order[1] = 2;
   7496 		result_component_order[2] = 1;
   7497 
   7498 		break;
   7499 	}
   7500 
   7501 	case SWIZZLE_TYPE_XZYW:
   7502 	{
   7503 		result_swizzle_string	 = "xzyw";
   7504 		result_n_components		  = 4;
   7505 		result_component_order[0] = 0;
   7506 		result_component_order[1] = 2;
   7507 		result_component_order[2] = 1;
   7508 		result_component_order[3] = 3;
   7509 
   7510 		break;
   7511 	}
   7512 
   7513 	case SWIZZLE_TYPE_Y:
   7514 	{
   7515 		result_swizzle_string	 = "y";
   7516 		result_n_components		  = 1;
   7517 		result_component_order[0] = 1;
   7518 
   7519 		break;
   7520 	}
   7521 
   7522 	case SWIZZLE_TYPE_YX:
   7523 	{
   7524 		result_swizzle_string	 = "yx";
   7525 		result_n_components		  = 2;
   7526 		result_component_order[0] = 1;
   7527 		result_component_order[1] = 0;
   7528 
   7529 		break;
   7530 	}
   7531 
   7532 	case SWIZZLE_TYPE_YXX:
   7533 	{
   7534 		result_swizzle_string	 = "yxx";
   7535 		result_n_components		  = 3;
   7536 		result_component_order[0] = 1;
   7537 		result_component_order[1] = 0;
   7538 		result_component_order[2] = 0;
   7539 
   7540 		break;
   7541 	}
   7542 
   7543 	case SWIZZLE_TYPE_YXXY:
   7544 	{
   7545 		result_swizzle_string	 = "yxxy";
   7546 		result_n_components		  = 4;
   7547 		result_component_order[0] = 1;
   7548 		result_component_order[1] = 0;
   7549 		result_component_order[2] = 0;
   7550 		result_component_order[3] = 1;
   7551 
   7552 		break;
   7553 	}
   7554 
   7555 	case SWIZZLE_TYPE_Z:
   7556 	{
   7557 		result_swizzle_string	 = "z";
   7558 		result_n_components		  = 1;
   7559 		result_component_order[0] = 2;
   7560 
   7561 		break;
   7562 	}
   7563 
   7564 	case SWIZZLE_TYPE_ZY:
   7565 	{
   7566 		result_swizzle_string	 = "zy";
   7567 		result_n_components		  = 2;
   7568 		result_component_order[0] = 2;
   7569 		result_component_order[1] = 1;
   7570 
   7571 		break;
   7572 	}
   7573 
   7574 	case SWIZZLE_TYPE_W:
   7575 	{
   7576 		result_swizzle_string	 = "w";
   7577 		result_n_components		  = 1;
   7578 		result_component_order[0] = 3;
   7579 
   7580 		break;
   7581 	}
   7582 
   7583 	case SWIZZLE_TYPE_WX:
   7584 	{
   7585 		result_swizzle_string	 = "wx";
   7586 		result_n_components		  = 2;
   7587 		result_component_order[0] = 3;
   7588 		result_component_order[1] = 0;
   7589 
   7590 		break;
   7591 	}
   7592 
   7593 	default:
   7594 	{
   7595 		TCU_FAIL("Unrecognized swizzle type");
   7596 	}
   7597 	} /* switch (type) */
   7598 
   7599 	if (out_swizzle_string != DE_NULL)
   7600 	{
   7601 		*out_swizzle_string = result_swizzle_string;
   7602 	}
   7603 
   7604 	if (out_n_components != DE_NULL)
   7605 	{
   7606 		*out_n_components = result_n_components;
   7607 	}
   7608 
   7609 	if (out_component_order != DE_NULL)
   7610 	{
   7611 		memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
   7612 	}
   7613 }
   7614 
   7615 /** Returns body of a vertex shader that should be used for particular test case,
   7616  *  given user-specified test case descriptor.
   7617  *
   7618  *  @param test_case Descriptor to use for the query.
   7619  *
   7620  *  @return Requested data.
   7621  **/
   7622 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
   7623 {
   7624 	std::stringstream  result;
   7625 	const std::string  base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
   7626 	const std::string  dst_type_string  = Utils::getVariableTypeString(test_case.dst_type);
   7627 	const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
   7628 	const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
   7629 	const std::string  src_type_string  = Utils::getVariableTypeString(test_case.src_type);
   7630 
   7631 	/* Add version preamble */
   7632 	result << "#version 420\n"
   7633 			  "\n";
   7634 
   7635 	/* Declare output variables. Note that boolean output variables are not supported, so we need
   7636 	 * to handle that special case correctly */
   7637 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
   7638 	{
   7639 		result << "out int result;\n";
   7640 	}
   7641 	else
   7642 	{
   7643 		result << "out " << dst_type_string << " result;\n";
   7644 	}
   7645 
   7646 	/* Declare input variables. Handle the bool case exclusively. */
   7647 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
   7648 	{
   7649 		/* Use ints for bools. We will cast them to bool in the code later. */
   7650 		result << "in int base_value;\n";
   7651 	}
   7652 	else
   7653 	{
   7654 		result << "in " << base_type_string << " base_value;\n";
   7655 	}
   7656 
   7657 	/* Declare main() and construct the value we will be casting from.
   7658 	 *
   7659 	 * Note: Addition operations on bool values cause an implicit conversion to int
   7660 	 *       which is not allowed. Hence, we skip these operations for this special
   7661 	 *       case.
   7662 	 */
   7663 	result << "void main()\n"
   7664 			  "{\n"
   7665 		   << src_type_string << " lside_value = ";
   7666 
   7667 	if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
   7668 	{
   7669 		result << src_type_string << "(0 != ";
   7670 	}
   7671 	else
   7672 	{
   7673 		result << src_type_string << "(";
   7674 	}
   7675 
   7676 	if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
   7677 	{
   7678 		for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
   7679 		{
   7680 			result << "base_value + " << n_component;
   7681 
   7682 			if (n_component != (n_src_components - 1))
   7683 			{
   7684 				result << ", ";
   7685 			}
   7686 		} /* for (all components) */
   7687 	}
   7688 	else
   7689 	{
   7690 		DE_ASSERT(n_src_components == 1);
   7691 
   7692 		result << "base_value";
   7693 	}
   7694 
   7695 	result << ");\n";
   7696 
   7697 	/* Perform the casting operation. Add swizzle operator if possible. */
   7698 	if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
   7699 	{
   7700 		/* Handle the bool case exclusively */
   7701 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
   7702 		{
   7703 			result << "result = (bool(lside_value) == false) ? 0 : 1";
   7704 		}
   7705 		else
   7706 		{
   7707 			result << "result = (lside_value == false) ? 0 : 1";
   7708 		}
   7709 	}
   7710 	else
   7711 	{
   7712 		if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
   7713 		{
   7714 			result << "result = " << dst_type_string << "(lside_value)";
   7715 		}
   7716 		else
   7717 		{
   7718 			result << "result = lside_value";
   7719 		}
   7720 	}
   7721 
   7722 	if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
   7723 	{
   7724 		/* Add a swizzle operator  */
   7725 		DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
   7726 		DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
   7727 
   7728 		unsigned int  swizzle_component_order[4] = { 0 };
   7729 		unsigned int  swizzle_n_components		 = 0;
   7730 		_swizzle_type swizzle_operator			 = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
   7731 		std::string   swizzle_string;
   7732 
   7733 		getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
   7734 
   7735 		if (swizzle_n_components > 0)
   7736 		{
   7737 			result << "." << swizzle_string;
   7738 		}
   7739 	}
   7740 
   7741 	/* Close the shader implementation. */
   7742 	result << ";\n"
   7743 			  "}\n";
   7744 
   7745 	return result.str();
   7746 }
   7747 
   7748 /** Initializes program & shader objects needed to run the iteration, given
   7749  *  user-specified test case descriptor.
   7750  *
   7751  *  This function can throw a TestError exception if a GL error is detected
   7752  *  during execution.
   7753  *
   7754  *  @param test_case Descriptor to use for the iteration.
   7755  **/
   7756 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
   7757 {
   7758 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   7759 
   7760 	/* Create program & shader objects */
   7761 	m_po_id = gl.createProgram();
   7762 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   7763 
   7764 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   7765 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
   7766 
   7767 	/* Configure shader body */
   7768 	std::string body		 = getVertexShaderBody(test_case);
   7769 	const char* body_raw_ptr = body.c_str();
   7770 
   7771 	gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
   7772 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   7773 
   7774 	/* Store it in the test case descriptor for logging purposes */
   7775 	test_case.shader_body = body;
   7776 
   7777 	/* Compile the shader */
   7778 	glw::GLint compile_status = GL_FALSE;
   7779 
   7780 	gl.compileShader(m_vs_id);
   7781 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
   7782 
   7783 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
   7784 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
   7785 
   7786 	if (compile_status != GL_TRUE)
   7787 	{
   7788 		TCU_FAIL("Shader compilation failed");
   7789 	}
   7790 
   7791 	/* Attach the shader to the program obejct */
   7792 	gl.attachShader(m_po_id, m_vs_id);
   7793 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
   7794 
   7795 	/* Configure XFB for the program object */
   7796 	const char* xfb_varying_name = "result";
   7797 
   7798 	gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
   7799 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
   7800 
   7801 	/* Link the program object */
   7802 	glw::GLint link_status = GL_FALSE;
   7803 
   7804 	gl.linkProgram(m_po_id);
   7805 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   7806 
   7807 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
   7808 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   7809 
   7810 	if (link_status != GL_TRUE)
   7811 	{
   7812 		TCU_FAIL("Program linking failed");
   7813 	}
   7814 
   7815 	/* Retrieve attribute locations */
   7816 	m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
   7817 	GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
   7818 
   7819 	if (m_po_base_value_attribute_location == -1)
   7820 	{
   7821 		TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
   7822 	}
   7823 }
   7824 
   7825 /** Initializes GL objects used by all test cases.
   7826  *
   7827  *  This function may throw a TestError exception if GL implementation reports
   7828  *  an error at any point.
   7829  **/
   7830 void GPUShaderFP64Test5::initTest()
   7831 {
   7832 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   7833 
   7834 	/* Generate buffer object IDs */
   7835 	gl.genBuffers(1, &m_base_value_bo_id);
   7836 	gl.genBuffers(1, &m_xfb_bo_id);
   7837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
   7838 
   7839 	/* Allocate buffer object storage for 'base_value' input attribute data. All iterations
   7840 	 * will never eat up more than 1 double (as per test spec) and we will be drawing
   7841 	 * as many points in a single draw call as there are defined in m_base_values array.
   7842 	 */
   7843 	const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
   7844 
   7845 	gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
   7846 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   7847 
   7848 	gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
   7849 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   7850 
   7851 	/* Allocate buffer object storage for XFB data. For each iteratiom we will be using
   7852 	 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
   7853 	 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
   7854 	 */
   7855 	const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
   7856 
   7857 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
   7858 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   7859 
   7860 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
   7861 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
   7862 
   7863 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
   7864 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   7865 
   7866 	/* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
   7867 	m_xfb_bo_size = xfb_bo_size;
   7868 
   7869 	/* Generate a vertex array object we will need to use for the draw calls */
   7870 	gl.genVertexArrays(1, &m_vao_id);
   7871 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   7872 
   7873 	gl.bindVertexArray(m_vao_id);
   7874 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   7875 }
   7876 
   7877 /** Executes test iteration.
   7878  *
   7879  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   7880  */
   7881 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
   7882 {
   7883 	/* Do not execute the test if GL_ARB_texture_view is not supported */
   7884 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   7885 	{
   7886 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
   7887 	}
   7888 
   7889 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
   7890 	{
   7891 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
   7892 	}
   7893 
   7894 	/* Initialize GL objects needed to run the tests */
   7895 	initTest();
   7896 
   7897 	/* Build iteration array to run the tests in an automated manner */
   7898 	_test_case test_cases[] = {
   7899 		/* test case type */ /* source type */ /* destination type */
   7900 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7901 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
   7902 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
   7903 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
   7904 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7905 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
   7906 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
   7907 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
   7908 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7909 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
   7910 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
   7911 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
   7912 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
   7913 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
   7914 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
   7915 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
   7916 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
   7917 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
   7918 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
   7919 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
   7920 		{ TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
   7921 
   7922 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7923 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7924 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
   7925 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
   7926 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
   7927 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
   7928 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
   7929 		{ TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
   7930 	};
   7931 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
   7932 
   7933 	/* Execute all iterations */
   7934 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
   7935 	{
   7936 		_test_case& test_case = test_cases[n_test_case];
   7937 
   7938 		/* Initialize a program object we will use to perform the casting */
   7939 		initIteration(test_case);
   7940 
   7941 		/* Use the program object to XFB the results */
   7942 		m_has_test_passed &= executeIteration(test_case);
   7943 
   7944 		/* Release the GL Resource for this sub test */
   7945 		deinitInteration();
   7946 
   7947 	} /* for (all test cases) */
   7948 	/* We're done */
   7949 	if (m_has_test_passed)
   7950 	{
   7951 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   7952 	}
   7953 	else
   7954 	{
   7955 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   7956 	}
   7957 
   7958 	return STOP;
   7959 }
   7960 
   7961 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
   7962  *  for which the data have been generated.
   7963  *
   7964  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
   7965  *  @param test_case Descriptor of the test case, for which the vertex shader was
   7966  *                   generated.
   7967  *
   7968  *  @return true if the data were found to be valid, false otherwise.
   7969  **/
   7970 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
   7971 {
   7972 	const Utils::_variable_type base_dst_type		= Utils::getBaseVariableType(test_case.dst_type);
   7973 	const Utils::_variable_type base_src_type		= Utils::getBaseVariableType(test_case.src_type);
   7974 	const float					epsilon				= 1e-5f;
   7975 	const unsigned int			n_base_values		= sizeof(m_base_values) / sizeof(m_base_values[0]);
   7976 	const unsigned int			n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
   7977 	const unsigned int			n_src_components	= Utils::getNumberOfComponentsForVariableType(test_case.src_type);
   7978 	bool						result				= true;
   7979 	_swizzle_type				swizzle_operator	= SWIZZLE_TYPE_NONE;
   7980 	unsigned int				swizzle_order[4]	= { 0 };
   7981 	const unsigned char*		traveller_ptr		= data_ptr;
   7982 
   7983 	if (!Utils::isMatrixVariableType(test_case.src_type))
   7984 	{
   7985 		DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
   7986 		DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
   7987 
   7988 		swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
   7989 
   7990 		getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
   7991 								 DE_NULL,					/* out_n_components */
   7992 								 swizzle_order);
   7993 	}
   7994 
   7995 	for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
   7996 	{
   7997 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
   7998 		{
   7999 			unsigned int n_swizzled_component = n_result_component;
   8000 
   8001 			if (swizzle_operator != SWIZZLE_TYPE_NONE)
   8002 			{
   8003 				n_swizzled_component =
   8004 					(n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
   8005 			}
   8006 
   8007 			switch (base_dst_type)
   8008 			{
   8009 			case Utils::VARIABLE_TYPE_BOOL:
   8010 			case Utils::VARIABLE_TYPE_INT:
   8011 			{
   8012 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
   8013 				double expected_value	 = ref_expected_value;
   8014 				int	result_value		  = *((int*)traveller_ptr);
   8015 
   8016 				if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
   8017 				{
   8018 					if (expected_value != 0.0)
   8019 					{
   8020 						expected_value = 1.0;
   8021 					}
   8022 				}
   8023 
   8024 				if (result_value != (int)expected_value)
   8025 				{
   8026 					m_testCtx.getLog() << tcu::TestLog::Message
   8027 									   << "Invalid boolean/integer value obtained when doing an "
   8028 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
   8029 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
   8030 									   << "]"
   8031 										  ", component index: ["
   8032 									   << n_swizzled_component << "]"
   8033 																  ", value: ["
   8034 									   << ref_expected_value << "]"
   8035 																" to GLSL type ["
   8036 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
   8037 																							  ", retrieved value: ["
   8038 									   << result_value << "]"
   8039 														  ", expected value: ["
   8040 									   << (int)expected_value << "]"
   8041 																 ", shader used:\n"
   8042 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
   8043 
   8044 					result = false;
   8045 				}
   8046 
   8047 				traveller_ptr += sizeof(int);
   8048 				break;
   8049 			} /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
   8050 
   8051 			case Utils::VARIABLE_TYPE_DOUBLE:
   8052 			{
   8053 				double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
   8054 				double expected_value	 = ref_expected_value;
   8055 				double result_value		  = *((double*)traveller_ptr);
   8056 
   8057 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
   8058 				{
   8059 					expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
   8060 				}
   8061 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
   8062 				{
   8063 					expected_value = (int)expected_value;
   8064 				}
   8065 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
   8066 				{
   8067 					// Negative values in base values array when converted to unsigned int will be ZERO
   8068 					// Addition operations done inside the shader in such cases will operate on ZERO rather
   8069 					// than the negative value being passed.
   8070 					// Replicate the sequence of conversion and addition operations done on the
   8071 					// shader input, to calculate the expected values in XFB data in the
   8072 					// problematic cases.
   8073 					if (expected_value < 0)
   8074 					{
   8075 						expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
   8076 					}
   8077 					expected_value = (unsigned int)expected_value;
   8078 				}
   8079 
   8080 				traveller_ptr += sizeof(double);
   8081 				if (de::abs(result_value - expected_value) > epsilon)
   8082 				{
   8083 					m_testCtx.getLog() << tcu::TestLog::Message
   8084 									   << "Invalid double-precision floating-point value obtained when doing an "
   8085 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
   8086 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
   8087 									   << "]"
   8088 										  ", component index: ["
   8089 									   << n_swizzled_component << "]"
   8090 																  ", value: ["
   8091 									   << ref_expected_value << "]"
   8092 																" to GLSL type ["
   8093 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
   8094 																							  ", retrieved value: ["
   8095 									   << std::setprecision(16) << result_value << "]"
   8096 																				   ", expected value: ["
   8097 									   << std::setprecision(16) << expected_value << "]"
   8098 																					 ", shader used:\n"
   8099 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
   8100 
   8101 					result = false;
   8102 				}
   8103 
   8104 				break;
   8105 			} /* VARIABLE_TYPE_DOUBLE case */
   8106 
   8107 			case Utils::VARIABLE_TYPE_FLOAT:
   8108 			{
   8109 				float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
   8110 				float expected_value	 = ref_expected_value;
   8111 				float result_value		 = *((float*)traveller_ptr);
   8112 
   8113 				if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
   8114 				{
   8115 					expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
   8116 				}
   8117 				else if (base_src_type == Utils::VARIABLE_TYPE_INT)
   8118 				{
   8119 					expected_value = (float)((int)expected_value);
   8120 				}
   8121 				else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
   8122 				{
   8123 					expected_value = (float)((unsigned int)expected_value);
   8124 				}
   8125 
   8126 				traveller_ptr += sizeof(float);
   8127 				if (de::abs(result_value - expected_value) > epsilon)
   8128 				{
   8129 					m_testCtx.getLog() << tcu::TestLog::Message
   8130 									   << "Invalid single-precision floating-point value obtained when doing an "
   8131 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
   8132 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
   8133 									   << "]"
   8134 										  ", component index: ["
   8135 									   << n_swizzled_component << "]"
   8136 																  ", value: ["
   8137 									   << ref_expected_value << "]"
   8138 																" to GLSL type ["
   8139 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
   8140 																							  ", retrieved value: ["
   8141 									   << std::setprecision(16) << result_value << "]"
   8142 																				   ", expected value: ["
   8143 									   << std::setprecision(16) << expected_value << "]"
   8144 																					 ", shader used:\n"
   8145 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
   8146 
   8147 					result = false;
   8148 				}
   8149 
   8150 				break;
   8151 			} /* VARIABLE_TYPE_FLOAT case */
   8152 
   8153 			case Utils::VARIABLE_TYPE_UINT:
   8154 			{
   8155 				double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
   8156 				double expected_value	 = ref_expected_value;
   8157 				unsigned int result_value = *((unsigned int*)traveller_ptr);
   8158 
   8159 				traveller_ptr += sizeof(unsigned int);
   8160 				if (result_value != (unsigned int)expected_value)
   8161 				{
   8162 					if (expected_value < 0.0)
   8163 					{
   8164 						// It is undefined to convert a negative floating-point value to an uint.
   8165 						break;
   8166 					}
   8167 
   8168 					m_testCtx.getLog() << tcu::TestLog::Message
   8169 									   << "Invalid unsigned integer value obtained when doing an "
   8170 									   << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
   8171 									   << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
   8172 									   << "]"
   8173 										  ", component index: ["
   8174 									   << n_swizzled_component << "]"
   8175 																  ", value: ["
   8176 									   << ref_expected_value << "]"
   8177 																" to GLSL type ["
   8178 									   << Utils::getVariableTypeString(test_case.dst_type) << "]"
   8179 																							  ", retrieved value: ["
   8180 									   << result_value << "]"
   8181 														  ", expected value: ["
   8182 									   << (unsigned int)expected_value << "]"
   8183 																		  ", shader used:\n"
   8184 									   << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
   8185 
   8186 					result = false;
   8187 				}
   8188 
   8189 				break;
   8190 			} /* VARIABLE_TYPE_UINT case */
   8191 
   8192 			default:
   8193 			{
   8194 				TCU_FAIL("Unrecognized variable type");
   8195 			}
   8196 			} /* switch (test_case.dst_type) */
   8197 		}	 /* for (all result components) */
   8198 	}		  /* for (all base values) */
   8199 
   8200 	return result;
   8201 }
   8202 
   8203 /** Constructor
   8204  *
   8205  *  @param context Rendering context.
   8206  */
   8207 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
   8208 	: TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
   8209 											   "during compilation time.")
   8210 	, m_cs_id(0)
   8211 	, m_fs_id(0)
   8212 	, m_gs_id(0)
   8213 	, m_tc_id(0)
   8214 	, m_te_id(0)
   8215 	, m_vs_id(0)
   8216 	, m_has_test_passed(true)
   8217 {
   8218 }
   8219 
   8220 /** Deinitializes all buffers and GL objects that may have been generated
   8221  *  during test execution.
   8222  **/
   8223 void GPUShaderFP64Test6::deinit()
   8224 {
   8225 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   8226 
   8227 	if (m_cs_id != 0)
   8228 	{
   8229 		gl.deleteShader(m_cs_id);
   8230 
   8231 		m_cs_id = 0;
   8232 	}
   8233 
   8234 	if (m_fs_id != 0)
   8235 	{
   8236 		gl.deleteShader(m_fs_id);
   8237 
   8238 		m_fs_id = 0;
   8239 	}
   8240 
   8241 	if (m_gs_id != 0)
   8242 	{
   8243 		gl.deleteShader(m_gs_id);
   8244 
   8245 		m_gs_id = 0;
   8246 	}
   8247 
   8248 	if (m_tc_id != 0)
   8249 	{
   8250 		gl.deleteShader(m_tc_id);
   8251 
   8252 		m_tc_id = 0;
   8253 	}
   8254 
   8255 	if (m_te_id != 0)
   8256 	{
   8257 		gl.deleteShader(m_te_id);
   8258 
   8259 		m_te_id = 0;
   8260 	}
   8261 
   8262 	if (m_vs_id != 0)
   8263 	{
   8264 		gl.deleteShader(m_vs_id);
   8265 
   8266 		m_vs_id = 0;
   8267 	}
   8268 }
   8269 
   8270 /** Executes a single test case.
   8271  *
   8272  *  This function can throw TestError exceptions if GL implementation reports
   8273  *  an error.
   8274  *
   8275  *  @param test_case Test case descriptor.
   8276  *
   8277  *  @return true if test case passed, false otherwise.
   8278  **/
   8279 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
   8280 {
   8281 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
   8282 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
   8283 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
   8284 	bool				  result	 = true;
   8285 	const char*			  stage_body = NULL;
   8286 	const char*			  stage_name = NULL;
   8287 
   8288 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
   8289 	{
   8290 		const glw::GLuint so_id = so_ids[n_so_id];
   8291 
   8292 		/* Skip compute shader if it is not supported */
   8293 		if (0 == so_id)
   8294 		{
   8295 			continue;
   8296 		}
   8297 
   8298 		/* Compile the shader */
   8299 		gl.compileShader(so_id);
   8300 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
   8301 
   8302 		/* Has the compilation failed as expected? */
   8303 		glw::GLint compile_status = GL_TRUE;
   8304 
   8305 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
   8306 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
   8307 
   8308 		if (compile_status == GL_TRUE)
   8309 		{
   8310 			/* What is the current stage's name? */
   8311 			if (so_id == m_cs_id)
   8312 			{
   8313 				stage_body = test_case.cs_shader_body.c_str();
   8314 				stage_name = "Compute shader";
   8315 			}
   8316 			else if (so_id == m_fs_id)
   8317 			{
   8318 				stage_body = test_case.fs_shader_body.c_str();
   8319 				stage_name = "Fragment shader";
   8320 			}
   8321 			else if (so_id == m_gs_id)
   8322 			{
   8323 				stage_body = test_case.gs_shader_body.c_str();
   8324 				stage_name = "Geometry shader";
   8325 			}
   8326 			else if (so_id == m_tc_id)
   8327 			{
   8328 				stage_body = test_case.tc_shader_body.c_str();
   8329 				stage_name = "Tessellation control shader";
   8330 			}
   8331 			else if (so_id == m_te_id)
   8332 			{
   8333 				stage_body = test_case.te_shader_body.c_str();
   8334 				stage_name = "Tessellation evaluation shader";
   8335 			}
   8336 			else if (so_id == m_vs_id)
   8337 			{
   8338 				stage_body = test_case.vs_shader_body.c_str();
   8339 				stage_name = "Vertex shader";
   8340 			}
   8341 			else
   8342 			{
   8343 				/* Doesn't make much sense to throw exceptions here so.. */
   8344 				stage_body = "";
   8345 				stage_name = "[?]";
   8346 			}
   8347 
   8348 			/* This shader should have never compiled successfully! */
   8349 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
   8350 							   << " has been compiled successfully, even though the shader was malformed."
   8351 								  " Following is shader body:\n"
   8352 							   << stage_body << tcu::TestLog::EndMessage;
   8353 
   8354 			result = false;
   8355 		}
   8356 	} /* for (all shader objects) */
   8357 
   8358 	return result;
   8359 }
   8360 
   8361 /** Retrieves body of a compute shader that should be used for the purpose of
   8362  *  user-specified test case.
   8363  *
   8364  *  @param test_case Test case descriptor to use.
   8365  *
   8366  *  @return Requested string.
   8367  **/
   8368 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
   8369 {
   8370 	std::stringstream result_sstream;
   8371 
   8372 	/* Add pre-amble */
   8373 	result_sstream << "#version 420\n"
   8374 					  "#extension GL_ARB_compute_shader          : require\n"
   8375 					  "\n"
   8376 					  "layout(local_size_x = 6) in;\n"
   8377 					  "\n"
   8378 					  "void main()\n"
   8379 					  "{\n";
   8380 
   8381 	/* Add local variable declarations */
   8382 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8383 
   8384 	if (test_case.src_array_size > 1)
   8385 	{
   8386 		result_sstream << "[" << test_case.src_array_size << "]";
   8387 	}
   8388 
   8389 	result_sstream << ";\n";
   8390 
   8391 	if (test_case.wrap_dst_type_in_structure)
   8392 	{
   8393 		result_sstream << "struct\n"
   8394 						  "{\n"
   8395 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8396 	}
   8397 	else
   8398 	{
   8399 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8400 	}
   8401 
   8402 	result_sstream << ";\n";
   8403 
   8404 	if (test_case.wrap_dst_type_in_structure)
   8405 	{
   8406 		result_sstream << "\n} dst;\n";
   8407 	}
   8408 
   8409 	/* Add actual body */
   8410 	result_sstream << "dst = src;\n"
   8411 					  "}\n";
   8412 
   8413 	/* Return the body */
   8414 	return result_sstream.str();
   8415 }
   8416 
   8417 /** Retrieves body of a fragment shader that should be used for the purpose of
   8418  *  user-specified test case.
   8419  *
   8420  *  @param test_case Test case descriptor to use.
   8421  *
   8422  *  @return Requested string.
   8423  **/
   8424 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
   8425 {
   8426 	std::stringstream result_sstream;
   8427 
   8428 	/* Add pre-amble */
   8429 	result_sstream << "#version 420\n"
   8430 					  "\n"
   8431 					  "void main()\n"
   8432 					  "{\n";
   8433 
   8434 	/* Add local variable declarations */
   8435 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8436 
   8437 	if (test_case.src_array_size > 1)
   8438 	{
   8439 		result_sstream << "[" << test_case.src_array_size << "]";
   8440 	}
   8441 
   8442 	result_sstream << ";\n";
   8443 
   8444 	if (test_case.wrap_dst_type_in_structure)
   8445 	{
   8446 		result_sstream << "struct\n"
   8447 						  "{\n"
   8448 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8449 	}
   8450 	else
   8451 	{
   8452 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8453 	}
   8454 
   8455 	result_sstream << ";\n";
   8456 
   8457 	if (test_case.wrap_dst_type_in_structure)
   8458 	{
   8459 		result_sstream << "\n} dst;\n";
   8460 	}
   8461 
   8462 	/* Add actual body */
   8463 	result_sstream << "dst = src;\n"
   8464 					  "}\n";
   8465 
   8466 	/* Return the body */
   8467 	return result_sstream.str();
   8468 }
   8469 
   8470 /** Retrieves body of a geometry shader that should be used for the purpose of
   8471  *  user-specified test case.
   8472  *
   8473  *  @param test_case Test case descriptor to use.
   8474  *
   8475  *  @return Requested string.
   8476  **/
   8477 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
   8478 {
   8479 	std::stringstream result_sstream;
   8480 
   8481 	/* Add preamble */
   8482 	result_sstream << "#version 420\n"
   8483 					  "\n"
   8484 					  "layout(points)                 in;\n"
   8485 					  "layout(max_vertices=1, points) out;\n"
   8486 					  "\n"
   8487 					  "void main()\n"
   8488 					  "{\n";
   8489 
   8490 	/* Add local variable declarations */
   8491 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8492 
   8493 	if (test_case.src_array_size > 1)
   8494 	{
   8495 		result_sstream << "[" << test_case.src_array_size << "]";
   8496 	}
   8497 
   8498 	result_sstream << ";\n";
   8499 
   8500 	if (test_case.wrap_dst_type_in_structure)
   8501 	{
   8502 		result_sstream << "struct\n"
   8503 						  "{\n"
   8504 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8505 	}
   8506 	else
   8507 	{
   8508 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8509 	}
   8510 
   8511 	result_sstream << ";\n"
   8512 					  "\n";
   8513 
   8514 	if (test_case.wrap_dst_type_in_structure)
   8515 	{
   8516 		result_sstream << "} dst;\n";
   8517 	}
   8518 
   8519 	/* Add actual body */
   8520 	result_sstream << "dst = src;\n"
   8521 					  "}\n";
   8522 
   8523 	/* We're done! */
   8524 	return result_sstream.str();
   8525 }
   8526 
   8527 /** Retrieves body of a tesellation control shader that should be used for the purpose of
   8528  *  user-specified test case.
   8529  *
   8530  *  @param test_case Test case descriptor to use.
   8531  *
   8532  *  @return Requested string.
   8533  **/
   8534 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
   8535 {
   8536 	std::stringstream result_sstream;
   8537 
   8538 	/* Add preamble */
   8539 	result_sstream << "#version 420\n"
   8540 					  "\n"
   8541 					  "layout(vertices=4) out;\n"
   8542 					  "\n"
   8543 					  "void main()\n"
   8544 					  "{\n";
   8545 
   8546 	/* Add local variable declarations. */
   8547 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8548 
   8549 	if (test_case.src_array_size > 1)
   8550 	{
   8551 		result_sstream << "[" << test_case.src_array_size << "]";
   8552 	}
   8553 
   8554 	result_sstream << ";\n";
   8555 
   8556 	if (test_case.wrap_dst_type_in_structure)
   8557 	{
   8558 		result_sstream << "struct\n"
   8559 						  "{\n"
   8560 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8561 	}
   8562 	else
   8563 	{
   8564 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8565 	}
   8566 
   8567 	if (test_case.wrap_dst_type_in_structure)
   8568 	{
   8569 		result_sstream << ";\n"
   8570 						  "} dst;\n";
   8571 	}
   8572 	else
   8573 	{
   8574 		result_sstream << ";\n";
   8575 	}
   8576 
   8577 	/* Continue with the actual body. */
   8578 	result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
   8579 					  "gl_TessLevelOuter[1] = 1.0;\n"
   8580 					  "dst                  = src;\n"
   8581 					  "}\n";
   8582 
   8583 	/* Return the body */
   8584 	return result_sstream.str();
   8585 }
   8586 
   8587 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
   8588  *  user-specified test case.
   8589  *
   8590  *  @param test_case Test case descriptor to use.
   8591  *
   8592  *  @return Requested string.
   8593  **/
   8594 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
   8595 {
   8596 	std::stringstream result_sstream;
   8597 
   8598 	/* Add preamble */
   8599 	result_sstream << "#version 420\n"
   8600 					  "\n"
   8601 					  "layout(isolines) in;\n"
   8602 					  "\n"
   8603 					  "void main()\n"
   8604 					  "{\n";
   8605 
   8606 	/* Add local variable declarations */
   8607 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8608 
   8609 	if (test_case.src_array_size > 1)
   8610 	{
   8611 		result_sstream << "[" << test_case.src_array_size << "]";
   8612 	}
   8613 
   8614 	result_sstream << ";\n";
   8615 
   8616 	if (test_case.wrap_dst_type_in_structure)
   8617 	{
   8618 		result_sstream << "struct\n"
   8619 						  "{\n"
   8620 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8621 	}
   8622 	else
   8623 	{
   8624 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8625 	}
   8626 
   8627 	if (test_case.wrap_dst_type_in_structure)
   8628 	{
   8629 		result_sstream << ";\n"
   8630 						  "} dst;\n";
   8631 	}
   8632 	else
   8633 	{
   8634 		result_sstream << ";\n";
   8635 	}
   8636 
   8637 	/* Continue with the actual body. */
   8638 	result_sstream << "dst = src;\n";
   8639 
   8640 	/* Complete the body */
   8641 	result_sstream << "}\n";
   8642 
   8643 	/* Return the body */
   8644 	return result_sstream.str();
   8645 }
   8646 
   8647 /** Retrieves body of a vertex shader that should be used for the purpose of
   8648  *  user-specified test case.
   8649  *
   8650  *  @param test_case Test case descriptor to use.
   8651  *
   8652  *  @return Requested string.
   8653  **/
   8654 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
   8655 {
   8656 	std::stringstream result_sstream;
   8657 
   8658 	/* Add preamble */
   8659 	result_sstream << "#version 420\n"
   8660 					  "\n"
   8661 					  "void main()\n"
   8662 					  "{\n";
   8663 
   8664 	/* Add local variables */
   8665 	result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
   8666 
   8667 	if (test_case.src_array_size > 1)
   8668 	{
   8669 		result_sstream << "[" << test_case.src_array_size << "]";
   8670 	}
   8671 
   8672 	result_sstream << ";\n";
   8673 
   8674 	if (test_case.wrap_dst_type_in_structure)
   8675 	{
   8676 		result_sstream << "struct\n"
   8677 						  "{\n"
   8678 					   << Utils::getVariableTypeString(test_case.dst_type) << " member";
   8679 	}
   8680 	else
   8681 	{
   8682 		result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
   8683 	}
   8684 
   8685 	if (test_case.wrap_dst_type_in_structure)
   8686 	{
   8687 		result_sstream << ";\n"
   8688 						  "} dst;\n";
   8689 	}
   8690 	else
   8691 	{
   8692 		result_sstream << ";\n";
   8693 	}
   8694 
   8695 	/* Start actual body */
   8696 	result_sstream << "dst         = src;\n"
   8697 					  "gl_Position = vec4(1.0);\n"
   8698 					  "}";
   8699 
   8700 	return result_sstream.str();
   8701 }
   8702 
   8703 /** Initializes shader objects required to run the test. */
   8704 void GPUShaderFP64Test6::initTest()
   8705 {
   8706 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   8707 
   8708 	/* Generate shader objects */
   8709 
   8710 	/* Compute shader support and GL 4.2 required */
   8711 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
   8712 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
   8713 	{
   8714 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
   8715 	}
   8716 
   8717 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   8718 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   8719 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
   8720 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
   8721 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   8722 
   8723 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   8724 }
   8725 
   8726 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
   8727  *
   8728  *  @param test_case Test case descriptor to generate the shader bodies for.
   8729  **/
   8730 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
   8731 {
   8732 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   8733 
   8734 	test_case.cs_shader_body = getComputeShaderBody(test_case);
   8735 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
   8736 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
   8737 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
   8738 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
   8739 	test_case.vs_shader_body = getVertexShaderBody(test_case);
   8740 
   8741 	/* Assign the bodies to relevant shaders */
   8742 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
   8743 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
   8744 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
   8745 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
   8746 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
   8747 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
   8748 
   8749 	/* m_cs_id is initialized only if compute_shader is supported */
   8750 	if (0 != m_cs_id)
   8751 	{
   8752 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
   8753 	}
   8754 
   8755 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
   8756 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
   8757 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
   8758 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
   8759 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
   8760 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
   8761 }
   8762 
   8763 /** Executes test iteration.
   8764  *
   8765  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   8766  */
   8767 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
   8768 {
   8769 	/* Do not execute the test if GL_ARB_texture_view is not supported */
   8770 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   8771 	{
   8772 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
   8773 	}
   8774 
   8775 	/* Initialize GL objects needed to run the tests */
   8776 	initTest();
   8777 
   8778 	/* Build iteration array to run the tests in an automated manner */
   8779 	_test_case test_cases[] = {
   8780 		/* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
   8781 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
   8782 		{ 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
   8783 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
   8784 		{ 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
   8785 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
   8786 		{ 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
   8787 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
   8788 		{ 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
   8789 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
   8790 		{ 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
   8791 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
   8792 		{ 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
   8793 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
   8794 		{ 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
   8795 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
   8796 		{ 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
   8797 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
   8798 		{ 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
   8799 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
   8800 		{ 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
   8801 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
   8802 		{ 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
   8803 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
   8804 		{ 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
   8805 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
   8806 		{ 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
   8807 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
   8808 		{ 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
   8809 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
   8810 		{ 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
   8811 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
   8812 		{ 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
   8813 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
   8814 		{ 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
   8815 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
   8816 		{ 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
   8817 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
   8818 		{ 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
   8819 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
   8820 		{ 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
   8821 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
   8822 		{ 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
   8823 	};
   8824 	const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
   8825 
   8826 	/* Execute all iterations */
   8827 	for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
   8828 	{
   8829 		_test_case& test_case = test_cases[n_test_case];
   8830 
   8831 		/* Initialize a program object we will use to perform the casting */
   8832 		initIteration(test_case);
   8833 
   8834 		/* Use the program object to XFB the results */
   8835 		m_has_test_passed &= executeIteration(test_case);
   8836 
   8837 	} /* for (all test cases) */
   8838 
   8839 	/* We're done */
   8840 	if (m_has_test_passed)
   8841 	{
   8842 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   8843 	}
   8844 	else
   8845 	{
   8846 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   8847 	}
   8848 
   8849 	return STOP;
   8850 }
   8851 
   8852 /** Constructor
   8853  *
   8854  *  @param context Rendering context.
   8855  */
   8856 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
   8857 	: TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
   8858 									"in all shader stages.")
   8859 	, m_are_double_inputs_supported(false)
   8860 	, m_fbo_id(0)
   8861 	, m_fs_id(0)
   8862 	, m_gs_id(0)
   8863 	, m_has_test_passed(true)
   8864 	, m_n_max_components_per_stage(0)
   8865 	, m_n_xfb_varyings(0)
   8866 	, m_po_id(0)
   8867 	, m_tc_id(0)
   8868 	, m_te_id(0)
   8869 	, m_to_id(0)
   8870 	, m_to_data(NULL)
   8871 	, m_to_height(4)
   8872 	, m_to_width(4)
   8873 	, m_xfb_bo_id(0)
   8874 	, m_xfb_varyings(NULL)
   8875 	, m_vao_id(0)
   8876 	, m_vs_id(0)
   8877 {
   8878 }
   8879 
   8880 /** Compiles all shaders attached to test program object and links it.
   8881  *
   8882  *  @param variables
   8883  *
   8884  *  @return true if the process was executed successfully, false otherwise.
   8885  */
   8886 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
   8887 {
   8888 	std::string			  fs_body = getFragmentShaderBody(variables);
   8889 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
   8890 	std::string			  gs_body = getGeometryShaderBody(variables);
   8891 	std::string			  tc_body = getTessellationControlShaderBody(variables);
   8892 	std::string			  te_body = getTessellationEvaluationShaderBody(variables);
   8893 	std::string			  vs_body = getVertexShaderBody(variables);
   8894 	bool				  result  = false;
   8895 
   8896 	/* Try to link the program object */
   8897 	glw::GLint link_status = GL_FALSE;
   8898 
   8899 	/* Compile the shaders */
   8900 	if (!compileShader(m_fs_id, fs_body))
   8901 	{
   8902 		m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
   8903 
   8904 		goto end;
   8905 	}
   8906 
   8907 	if (!compileShader(m_gs_id, gs_body))
   8908 	{
   8909 		m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
   8910 
   8911 		goto end;
   8912 	}
   8913 
   8914 	if (!compileShader(m_tc_id, tc_body))
   8915 	{
   8916 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
   8917 						   << tcu::TestLog::EndMessage;
   8918 
   8919 		goto end;
   8920 	}
   8921 
   8922 	if (!compileShader(m_te_id, te_body))
   8923 	{
   8924 		m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
   8925 						   << tcu::TestLog::EndMessage;
   8926 
   8927 		goto end;
   8928 	}
   8929 
   8930 	if (!compileShader(m_vs_id, vs_body))
   8931 	{
   8932 		m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
   8933 
   8934 		goto end;
   8935 	}
   8936 
   8937 	/* Configure XFB */
   8938 	releaseXFBVaryingNames();
   8939 	generateXFBVaryingNames(variables);
   8940 
   8941 	gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
   8942 
   8943 	gl.linkProgram(m_po_id);
   8944 
   8945 	/* Have we succeeded? */
   8946 	GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
   8947 
   8948 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
   8949 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   8950 
   8951 	if (link_status != GL_TRUE)
   8952 	{
   8953 		m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
   8954 						   << tcu::TestLog::EndMessage;
   8955 
   8956 		goto end;
   8957 	}
   8958 
   8959 	/* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
   8960 	if (m_are_double_inputs_supported)
   8961 	{
   8962 		const size_t n_variables = variables.size();
   8963 
   8964 		for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
   8965 		{
   8966 			_variable&		  current_variable = variables[n_variable];
   8967 			std::stringstream attribute_name_sstream;
   8968 
   8969 			attribute_name_sstream << "in_vs_variable" << n_variable;
   8970 
   8971 			if (current_variable.array_size > 1)
   8972 			{
   8973 				attribute_name_sstream << "[0]";
   8974 			}
   8975 
   8976 			current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
   8977 
   8978 			if (current_variable.attribute_location == -1)
   8979 			{
   8980 				m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
   8981 								   << attribute_name_sstream.str().c_str()
   8982 								   << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
   8983 
   8984 				m_has_test_passed = false;
   8985 				goto end;
   8986 			}
   8987 		} /* for (all test variables) */
   8988 	}	 /* if (m_are_double_inputs_supported) */
   8989 
   8990 	m_current_fs_body = fs_body;
   8991 	m_current_gs_body = gs_body;
   8992 	m_current_tc_body = tc_body;
   8993 	m_current_te_body = te_body;
   8994 	m_current_vs_body = vs_body;
   8995 
   8996 	result = true;
   8997 
   8998 end:
   8999 	return result;
   9000 }
   9001 
   9002 /** Updates shader object's body and then compiles the shader.
   9003  *
   9004  *  @param body Body to use for the shader.
   9005  *
   9006  *  @return true if the shader compiled successfully, false otherwise.
   9007  **/
   9008 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
   9009 {
   9010 	const char*			  body_raw_ptr   = body.c_str();
   9011 	glw::GLint			  compile_status = GL_FALSE;
   9012 	const glw::Functions& gl			 = m_context.getRenderContext().getFunctions();
   9013 
   9014 	gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
   9015 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   9016 
   9017 	gl.compileShader(shader_id);
   9018 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
   9019 
   9020 	gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
   9021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
   9022 
   9023 	return (compile_status == GL_TRUE);
   9024 }
   9025 
   9026 /** Configure storage of a buffer object used for capturing XFB data.
   9027  *
   9028  *  @param variables Holds descriptor for all variables used for the iteration the
   9029  *                   BO is being configured for. Storage size will be directly related
   9030  *                   to the number of the variables and their type.
   9031  */
   9032 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
   9033 {
   9034 	DE_ASSERT(m_n_xfb_varyings != 0);
   9035 
   9036 	/* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
   9037 	 * The test only draws a single patch, and triangles are caught by transform feed-back.
   9038 	 * Let's initialize the storage, according to the list of variables that will be used
   9039 	 * for the test run.
   9040 	 */
   9041 	unsigned int bo_size = 0;
   9042 
   9043 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
   9044 		 variables_iterator++)
   9045 	{
   9046 		const _variable& variable		= *variables_iterator;
   9047 		unsigned int	 n_bytes_needed = static_cast<unsigned int>(
   9048 			Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
   9049 
   9050 		bo_size += n_bytes_needed;
   9051 	} /* for (all variables) */
   9052 
   9053 	bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
   9054 
   9055 	/* Set up the BO storage */
   9056 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   9057 
   9058 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
   9059 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   9060 }
   9061 
   9062 /** Deinitializes all buffers and GL objects that may have been generated
   9063  *  during test execution.
   9064  **/
   9065 void GPUShaderFP64Test7::deinit()
   9066 {
   9067 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   9068 
   9069 	if (m_fbo_id != 0)
   9070 	{
   9071 		gl.deleteFramebuffers(1, &m_fbo_id);
   9072 
   9073 		m_fbo_id = 0;
   9074 	}
   9075 
   9076 	if (m_fs_id != 0)
   9077 	{
   9078 		gl.deleteShader(m_fs_id);
   9079 
   9080 		m_fs_id = 0;
   9081 	}
   9082 
   9083 	if (m_gs_id != 0)
   9084 	{
   9085 		gl.deleteShader(m_gs_id);
   9086 
   9087 		m_gs_id = 0;
   9088 	}
   9089 
   9090 	if (m_po_id != 0)
   9091 	{
   9092 		gl.deleteProgram(m_po_id);
   9093 
   9094 		m_po_id = 0;
   9095 	}
   9096 
   9097 	if (m_tc_id != 0)
   9098 	{
   9099 		gl.deleteShader(m_tc_id);
   9100 
   9101 		m_tc_id = 0;
   9102 	}
   9103 
   9104 	if (m_te_id != 0)
   9105 	{
   9106 		gl.deleteShader(m_te_id);
   9107 
   9108 		m_te_id = 0;
   9109 	}
   9110 
   9111 	if (m_to_data != NULL)
   9112 	{
   9113 		delete[] m_to_data;
   9114 
   9115 		m_to_data = NULL;
   9116 	}
   9117 
   9118 	if (m_to_id != 0)
   9119 	{
   9120 		gl.deleteTextures(1, &m_to_id);
   9121 
   9122 		m_to_id = 0;
   9123 	}
   9124 
   9125 	if (m_xfb_bo_id != 0)
   9126 	{
   9127 		gl.deleteBuffers(1, &m_xfb_bo_id);
   9128 
   9129 		m_xfb_bo_id = 0;
   9130 	}
   9131 
   9132 	if (m_xfb_varyings != DE_NULL)
   9133 	{
   9134 		releaseXFBVaryingNames();
   9135 	}
   9136 
   9137 	if (m_vao_id != 0)
   9138 	{
   9139 		gl.deleteVertexArrays(1, &m_vao_id);
   9140 
   9141 		m_vao_id = 0;
   9142 	}
   9143 
   9144 	if (m_vs_id != 0)
   9145 	{
   9146 		gl.deleteShader(m_vs_id);
   9147 
   9148 		m_vs_id = 0;
   9149 	}
   9150 }
   9151 
   9152 /** Executes the functional part of the test (case a) from the test spec)
   9153  *
   9154  *  @param variables Vector of variable descriptors defining properties of
   9155  *                   variables that should be used for the iteration.
   9156  *
   9157  *  @return true if the test passed, false otherwise.
   9158  **/
   9159 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
   9160 {
   9161 	bool result = true;
   9162 
   9163 	/* Build the test program */
   9164 	if (!buildTestProgram(variables))
   9165 	{
   9166 		return false;
   9167 	}
   9168 
   9169 	/* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
   9170 	if (m_are_double_inputs_supported)
   9171 	{
   9172 		setInputAttributeValues(variables);
   9173 	}
   9174 
   9175 	/* Set up buffer object to hold XFB data. The data will be used for logging purposes
   9176 	 * only, if a data mismatch is detected.
   9177 	 */
   9178 	configureXFBBuffer(variables);
   9179 
   9180 	/* Issue a draw call using the test program */
   9181 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   9182 
   9183 	gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
   9184 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
   9185 
   9186 	gl.clear(GL_COLOR_BUFFER_BIT);
   9187 	GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
   9188 
   9189 	gl.useProgram(m_po_id);
   9190 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   9191 
   9192 	gl.viewport(0, /* x */
   9193 				0, /* y */
   9194 				m_to_width, m_to_height);
   9195 	GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
   9196 
   9197 	gl.beginTransformFeedback(GL_TRIANGLES);
   9198 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
   9199 	{
   9200 		gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
   9201 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
   9202 	}
   9203 	gl.endTransformFeedback();
   9204 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
   9205 
   9206 	/* Verify color attachment contents */
   9207 	const float epsilon = 1.0f / 255.0f;
   9208 
   9209 	gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
   9210 	GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
   9211 
   9212 	for (unsigned int y = 0; y < m_to_height; ++y)
   9213 	{
   9214 		const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
   9215 
   9216 		for (unsigned int x = 0; x < m_to_width; ++x)
   9217 		{
   9218 			const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
   9219 
   9220 			if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
   9221 				de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
   9222 			{
   9223 				m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
   9224 								   << ")"
   9225 									  "; expected:(0, 255, 0, 0), found: ("
   9226 								   << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
   9227 								   << ", " << (int)pixel_ptr[3]
   9228 								   << "), with the following variable types used as varyings:"
   9229 								   << tcu::TestLog::EndMessage;
   9230 
   9231 				/* List the variable types that failed the test */
   9232 				const size_t n_variables = variables.size();
   9233 
   9234 				for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
   9235 				{
   9236 					m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
   9237 									   << Utils::getVariableTypeString(variables[n_variable].type)
   9238 									   << " (array size:" << variables[n_variable].array_size << ")"
   9239 									   << tcu::TestLog::EndMessage;
   9240 				} /* for (all variable types) */
   9241 
   9242 				/* Log the variable contents */
   9243 				logVariableContents(variables);
   9244 
   9245 				/* Log shaders used for the iteration */
   9246 				m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
   9247 															   "\n"
   9248 															   "(VS):\n"
   9249 								   << m_current_vs_body.c_str() << "\n"
   9250 								   << "(TC):\n"
   9251 									  "\n"
   9252 								   << m_current_tc_body.c_str() << "\n"
   9253 																   "(TE):\n"
   9254 																   "\n"
   9255 								   << m_current_te_body.c_str() << "\n"
   9256 																   "(GS):\n"
   9257 								   << m_current_gs_body.c_str() << "\n"
   9258 																   "(FS):\n"
   9259 																   "\n"
   9260 								   << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
   9261 
   9262 				result = false;
   9263 
   9264 				goto end;
   9265 			}
   9266 		} /* for (all columns) */
   9267 	}	 /* for (all rows) */
   9268 
   9269 /* All done! */
   9270 end:
   9271 	return result;
   9272 }
   9273 
   9274 /** Takes user-input vector of test variables and allocates & fills an array of strings
   9275  *  holding names of geometry shader stage varyings that should be captured during
   9276  *  transform feedback operation. The array will be stored in m_xfb_varyings.
   9277  *
   9278  *  @param variables Holds all test variable descriptors to be used for the iteration.
   9279  */
   9280 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
   9281 {
   9282 	unsigned int n_variable = 0;
   9283 	unsigned int n_varying  = 0;
   9284 	unsigned int n_varyings = 0;
   9285 
   9286 	if (m_xfb_varyings != NULL)
   9287 	{
   9288 		releaseXFBVaryingNames();
   9289 	}
   9290 
   9291 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
   9292 		 ++variables_iterator)
   9293 	{
   9294 		const _variable& variable = *variables_iterator;
   9295 
   9296 		n_varyings += variable.array_size;
   9297 	}
   9298 
   9299 	m_xfb_varyings = new glw::GLchar*[n_varyings];
   9300 
   9301 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
   9302 		 ++variables_iterator, ++n_variable)
   9303 	{
   9304 		const _variable& variable = *variables_iterator;
   9305 
   9306 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
   9307 		{
   9308 			std::stringstream varying_sstream;
   9309 			size_t			  varying_length;
   9310 
   9311 			varying_sstream << "gs_variable" << n_variable;
   9312 
   9313 			if (variable.array_size > 1)
   9314 			{
   9315 				varying_sstream << "[" << array_index << "]";
   9316 			}
   9317 
   9318 			/* Store the varying name */
   9319 			varying_length			  = varying_sstream.str().length();
   9320 			m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
   9321 
   9322 			memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
   9323 			m_xfb_varyings[n_varying][varying_length] = 0;
   9324 		} /* for (all array indices) */
   9325 	}	 /* for (all varyings) */
   9326 
   9327 	m_n_xfb_varyings = n_varyings;
   9328 }
   9329 
   9330 /** Retrieves body of a shader that defines input variable of user-specified type & array size
   9331  *  without using the "flat" keyword. (case c) )
   9332  *
   9333  *  @param input_variable_type Variable type to use for input variable declaration.
   9334  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
   9335  *                             of the arrayed variable.
   9336  *
   9337  *  @return Requested string.
   9338  **/
   9339 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
   9340 	Utils::_variable_type input_variable_type, unsigned int array_size)
   9341 {
   9342 	std::stringstream result_sstream;
   9343 	std::stringstream array_index_stringstream;
   9344 	std::stringstream array_size_stringstream;
   9345 
   9346 	if (array_size > 1)
   9347 	{
   9348 		array_index_stringstream << "[0]";
   9349 		array_size_stringstream << "[" << array_size << "]";
   9350 	}
   9351 
   9352 	if (Utils::isMatrixVariableType(input_variable_type))
   9353 	{
   9354 		array_index_stringstream << "[0].x";
   9355 	}
   9356 	else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
   9357 	{
   9358 		array_index_stringstream << "[0]";
   9359 	}
   9360 
   9361 	result_sstream << "#version 400\n"
   9362 					  "\n"
   9363 					  "in "
   9364 				   << Utils::getVariableTypeString(input_variable_type) << " test_input"
   9365 				   << array_size_stringstream.str() << ";\n"
   9366 													   "\n"
   9367 													   "out float test_output;\n"
   9368 													   "\n"
   9369 													   "void main()\n"
   9370 													   "{\n"
   9371 													   "    if (test_input"
   9372 				   << array_index_stringstream.str() << " > 2.0)\n"
   9373 														"    {\n"
   9374 														"        test_output = 1.0;\n"
   9375 														"    }\n"
   9376 														"    else\n"
   9377 														"    {\n"
   9378 														"        test_output = 3.0;\n"
   9379 														"    }\n"
   9380 														"}\n";
   9381 
   9382 	return result_sstream.str();
   9383 }
   9384 
   9385 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
   9386  *
   9387  *  @param input_variable_type Variable type to use for input variable declaration.
   9388  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
   9389  *                             of the arrayed variable.
   9390  *
   9391  *  @return Requested string.
   9392  **/
   9393 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
   9394 	Utils::_variable_type output_variable_type, unsigned int array_size)
   9395 {
   9396 	std::stringstream array_index_sstream;
   9397 	std::stringstream array_size_sstream;
   9398 	std::stringstream result_sstream;
   9399 	std::string		  output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
   9400 
   9401 	if (array_size > 1)
   9402 	{
   9403 		array_index_sstream << "[0]";
   9404 		array_size_sstream << "[" << array_size << "]";
   9405 	}
   9406 
   9407 	result_sstream << "#version 400\n"
   9408 					  "\n"
   9409 					  "out "
   9410 				   << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
   9411 																								   "\n"
   9412 																								   "void main()\n"
   9413 																								   "{\n"
   9414 																								   "    test_output"
   9415 				   << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
   9416 																						   "}\n";
   9417 
   9418 	return result_sstream.str();
   9419 }
   9420 
   9421 /** Retrieves body of a fragment shader that uses user-specified set of variables
   9422  *  to declare contents of input & output block.
   9423  *
   9424  *  @param variables As per description.
   9425  *
   9426  *  @return Requested string.
   9427  **/
   9428 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
   9429 {
   9430 	std::stringstream result_sstream;
   9431 
   9432 	/* Form the pre-amble */
   9433 	result_sstream << "#version 400\n"
   9434 					  "\n"
   9435 
   9436 				   /* Add input block */
   9437 				   << "in GS_DATA\n"
   9438 					  "{\n"
   9439 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
   9440 																		  "\n"
   9441 
   9442 				   /* Add output variable */
   9443 				   << "out vec4 result;\n"
   9444 					  "\n"
   9445 
   9446 					  /* Add main() definition */
   9447 					  "void main()\n"
   9448 					  "{\n"
   9449 					  "const double epsilon = 1e-5;\n"
   9450 					  "\n"
   9451 					  "result = vec4(1, 0, 0, 0);\n"
   9452 					  "\n";
   9453 
   9454 	/* Determine expected values first */
   9455 	unsigned int base_counter = 1;
   9456 	const size_t n_variables  = variables.size();
   9457 
   9458 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9459 	{
   9460 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
   9461 		Utils::_variable_type variable_type				 = variables[n_variable].type;
   9462 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
   9463 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
   9464 
   9465 		std::stringstream array_size_sstream;
   9466 
   9467 		if (variable_array_size > 1)
   9468 		{
   9469 			array_size_sstream << "[" << variable_array_size << "]";
   9470 		}
   9471 
   9472 		/* Local variable declaration */
   9473 		result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
   9474 					   << ";\n"
   9475 						  "\n";
   9476 
   9477 		/* Set expected values */
   9478 		for (unsigned int index = 0; index < variable_array_size; ++index)
   9479 		{
   9480 			std::stringstream array_index_sstream;
   9481 
   9482 			if (variable_array_size > 1)
   9483 			{
   9484 				array_index_sstream << "[" << index << "]";
   9485 			}
   9486 
   9487 			result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
   9488 						   << variable_type_string << "(";
   9489 
   9490 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9491 			{
   9492 				unsigned int expected_value =
   9493 					(base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
   9494 
   9495 				if (m_are_double_inputs_supported)
   9496 				{
   9497 					/* VS input attributes */
   9498 					//expected_value += (base_counter + 6);
   9499 					expected_value -= 1;
   9500 				}
   9501 
   9502 				result_sstream << expected_value;
   9503 
   9504 				if (n_component != (n_variable_type_components - 1))
   9505 				{
   9506 					result_sstream << ", ";
   9507 				}
   9508 
   9509 				++base_counter;
   9510 			} /* for (all components) */
   9511 
   9512 			result_sstream << ");\n";
   9513 		} /* for (all array indices) */
   9514 
   9515 		result_sstream << "\n";
   9516 	} /* for (all variable types) */
   9517 
   9518 	/* Now that we know the expected values, do a huge conditional check to verify if all
   9519 	 * input variables carry correct information.
   9520 	 */
   9521 	result_sstream << "if (";
   9522 
   9523 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9524 	{
   9525 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
   9526 		Utils::_variable_type variable_type				 = variables[n_variable].type;
   9527 		bool				  is_variable_type_matrix	= Utils::isMatrixVariableType(variable_type);
   9528 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
   9529 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
   9530 
   9531 		for (unsigned int index = 0; index < variable_array_size; ++index)
   9532 		{
   9533 			std::stringstream array_index_sstream;
   9534 
   9535 			if (variable_array_size > 1)
   9536 			{
   9537 				array_index_sstream << "[" << index << "]";
   9538 			}
   9539 
   9540 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9541 			{
   9542 				std::stringstream component_index_sstream;
   9543 
   9544 				if (n_variable_type_components > 1)
   9545 				{
   9546 					component_index_sstream << "[" << n_component << "]";
   9547 				}
   9548 
   9549 				result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
   9550 
   9551 				if (is_variable_type_matrix)
   9552 				{
   9553 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
   9554 					const unsigned int column	= n_component % n_columns;
   9555 					const unsigned int row		 = n_component / n_columns;
   9556 
   9557 					result_sstream << "[" << column << "]"
   9558 													   "."
   9559 								   << Utils::getComponentAtIndex(row);
   9560 				}
   9561 				else
   9562 				{
   9563 					result_sstream << component_index_sstream.str();
   9564 				}
   9565 
   9566 				result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
   9567 
   9568 				if (is_variable_type_matrix)
   9569 				{
   9570 					const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
   9571 					const unsigned int column	= n_component % n_columns;
   9572 					const unsigned int row		 = n_component / n_columns;
   9573 
   9574 					result_sstream << "[" << column << "]"
   9575 													   "."
   9576 								   << Utils::getComponentAtIndex(row);
   9577 				}
   9578 				else
   9579 				{
   9580 					result_sstream << component_index_sstream.str();
   9581 				}
   9582 
   9583 				result_sstream << ") <= epsilon &&";
   9584 			} /* for (all components) */
   9585 		}	 /* for (all array indices) */
   9586 	}		  /* for (all variable types) */
   9587 
   9588 	result_sstream << "true)\n"
   9589 					  "{\n"
   9590 					  "    result = vec4(0, 1, 0, 0);\n"
   9591 					  "}\n"
   9592 					  "}\n";
   9593 
   9594 	/* All done */
   9595 	return result_sstream.str();
   9596 }
   9597 
   9598 /** Retrieves body of a geometry shader that uses user-specified set of variables
   9599  *  to declare contents of input & output block.
   9600  *
   9601  *  @param variables As per description.
   9602  *
   9603  *  @return Requested string.
   9604  **/
   9605 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
   9606 {
   9607 	std::stringstream result_sstream;
   9608 
   9609 	/* Form the pre-amble */
   9610 	result_sstream << "#version 400\n"
   9611 					  "\n"
   9612 					  "layout(triangles)                      in;\n"
   9613 					  "layout(triangle_strip, max_vertices=4) out;\n"
   9614 					  "\n"
   9615 
   9616 					  /* Add the input block */
   9617 					  "in TE_DATA\n"
   9618 					  "{\n"
   9619 				   << getVariableDeclarations("te", variables) << "} in_data[];\n"
   9620 																  "\n"
   9621 
   9622 																  /* Add the output block */
   9623 																  "out GS_DATA\n"
   9624 																  "{\n"
   9625 				   << getVariableDeclarations("gs", variables, "flat") << "};\n"
   9626 																		  "\n"
   9627 
   9628 																		  /* Declare main() function */
   9629 																		  "void main()\n"
   9630 																		  "{\n";
   9631 
   9632 	/* Take input variables, add a predefined value and forward them to output variables */
   9633 	const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
   9634 									1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f };
   9635 	const unsigned int n_quad_vertices =
   9636 		sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
   9637 	const size_t n_variables = variables.size();
   9638 
   9639 	for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
   9640 	{
   9641 		unsigned int counter			 = 4;
   9642 		const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
   9643 
   9644 		for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9645 		{
   9646 			unsigned int		  variable_array_size = variables[n_variable].array_size;
   9647 			Utils::_variable_type variable_type		  = variables[n_variable].type;
   9648 			unsigned int n_variable_type_components   = Utils::getNumberOfComponentsForVariableType(variable_type);
   9649 			std::string  variable_type_string		  = Utils::getVariableTypeString(variable_type);
   9650 
   9651 			for (unsigned int index = 0; index < variable_array_size; ++index)
   9652 			{
   9653 				std::stringstream array_index_sstream;
   9654 
   9655 				if (variable_array_size > 1)
   9656 				{
   9657 					array_index_sstream << "[" << index << "]";
   9658 				}
   9659 
   9660 				result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
   9661 							   << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
   9662 							   << variable_type_string << "(";
   9663 
   9664 				for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9665 				{
   9666 					result_sstream << (counter++);
   9667 
   9668 					if (n_component != (n_variable_type_components - 1))
   9669 					{
   9670 						result_sstream << ", ";
   9671 					}
   9672 				} /* for (all components) */
   9673 
   9674 				result_sstream << ");\n";
   9675 			} /* for (all array indices) */
   9676 		}	 /* for (all variable types) */
   9677 
   9678 		result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
   9679 					   << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
   9680 																					  "EmitVertex();\n";
   9681 	} /* for (all emitted quad vertices) */
   9682 
   9683 	result_sstream << "EndPrimitive();\n"
   9684 					  "}\n";
   9685 
   9686 	/* All done */
   9687 	return result_sstream.str();
   9688 }
   9689 
   9690 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
   9691  *  to declare contents of input & output block.
   9692  *
   9693  *  @param variables As per description.
   9694  *
   9695  *  @return Requested string.
   9696  **/
   9697 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
   9698 {
   9699 	std::stringstream result_sstream;
   9700 
   9701 	/* Form the pre-amble */
   9702 	result_sstream << "#version 400\n"
   9703 					  "\n"
   9704 					  "layout (vertices=4) out;\n"
   9705 
   9706 					  /* Declare input block */
   9707 					  "in VS_DATA\n"
   9708 					  "{\n"
   9709 				   << getVariableDeclarations("vs", variables) << "} in_data[];\n"
   9710 
   9711 																  /* Declare output block */
   9712 																  "out TC_DATA\n"
   9713 																  "{\n"
   9714 				   << getVariableDeclarations("tc", variables) << "} out_data[];\n"
   9715 																  "\n"
   9716 
   9717 																  /* Define main() */
   9718 																  "void main()\n"
   9719 																  "{\n"
   9720 																  "    gl_TessLevelInner[0] = 1;\n"
   9721 																  "    gl_TessLevelInner[1] = 1;\n"
   9722 																  "    gl_TessLevelOuter[0] = 1;\n"
   9723 																  "    gl_TessLevelOuter[1] = 1;\n"
   9724 																  "    gl_TessLevelOuter[2] = 1;\n"
   9725 																  "    gl_TessLevelOuter[3] = 1;\n"
   9726 																  "\n";
   9727 
   9728 	/* Take input variables, add a predefined value and forward them to output variables */
   9729 	const size_t n_variables = variables.size();
   9730 	unsigned int counter	 = 2;
   9731 
   9732 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9733 	{
   9734 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
   9735 		Utils::_variable_type variable_type				 = variables[n_variable].type;
   9736 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
   9737 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
   9738 
   9739 		for (unsigned int index = 0; index < variable_array_size; ++index)
   9740 		{
   9741 			std::stringstream array_index_sstream;
   9742 
   9743 			if (variable_array_size > 1)
   9744 			{
   9745 				array_index_sstream << "[" << index << "]";
   9746 			}
   9747 
   9748 			result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
   9749 						   << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
   9750 						   << variable_type_string << "(";
   9751 
   9752 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9753 			{
   9754 				result_sstream << (counter++);
   9755 
   9756 				if (n_component != (n_variable_type_components - 1))
   9757 				{
   9758 					result_sstream << ", ";
   9759 				}
   9760 			}
   9761 
   9762 			result_sstream << ");\n";
   9763 		} /* for (all array indices) */
   9764 	}	 /* for (all variable types) */
   9765 
   9766 	result_sstream << "}\n";
   9767 
   9768 	/* We're done */
   9769 	return result_sstream.str();
   9770 }
   9771 
   9772 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
   9773  *  to declare contents of input & output block.
   9774  *
   9775  *  @param variables As per description.
   9776  *
   9777  *  @return Requested string.
   9778  **/
   9779 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
   9780 {
   9781 	std::stringstream result_sstream;
   9782 
   9783 	/* Form the pre-amble */
   9784 	result_sstream << "#version 400\n"
   9785 					  "\n"
   9786 					  "layout(quads) in;\n"
   9787 					  "\n"
   9788 
   9789 					  /* Define input block */
   9790 					  "in TC_DATA\n"
   9791 					  "{\n"
   9792 				   << getVariableDeclarations("tc", variables) << "} in_data[];\n"
   9793 																  "\n"
   9794 
   9795 																  /* Define output block */
   9796 																  "out TE_DATA\n"
   9797 																  "{\n"
   9798 				   << getVariableDeclarations("te", variables) << "};\n"
   9799 																  "\n"
   9800 
   9801 																  /* Define main() */
   9802 																  "void main()\n"
   9803 																  "{\n";
   9804 
   9805 	/* Take input variables, add a predefined value and forward them to output variables */
   9806 	const size_t n_variables = variables.size();
   9807 	unsigned int counter	 = 3;
   9808 
   9809 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9810 	{
   9811 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
   9812 		Utils::_variable_type variable_type				 = variables[n_variable].type;
   9813 		unsigned int		  n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
   9814 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
   9815 
   9816 		for (unsigned int index = 0; index < variable_array_size; ++index)
   9817 		{
   9818 			std::stringstream array_index_sstream;
   9819 
   9820 			if (variable_array_size > 1)
   9821 			{
   9822 				array_index_sstream << "[" << index << "]";
   9823 			}
   9824 
   9825 			result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
   9826 						   << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
   9827 
   9828 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9829 			{
   9830 				result_sstream << (counter++);
   9831 
   9832 				if (n_component != (n_variable_type_components - 1))
   9833 				{
   9834 					result_sstream << ", ";
   9835 				}
   9836 			} /* for (all components) */
   9837 
   9838 			result_sstream << ");\n";
   9839 		} /* for (all array indices) */
   9840 	}	 /* for (all variable types) */
   9841 
   9842 	result_sstream << "}\n";
   9843 
   9844 	/* All done */
   9845 	return result_sstream.str();
   9846 }
   9847 
   9848 /** Returns a string containing declarations of user-specified set of variables.
   9849  *  Each declaration can optionally use a layot qualifier requested by the caller.
   9850  *
   9851  *  @param prefix             Prefix to use for variable names.
   9852  *  @param variables          List of variables to declare in the result string.
   9853  *  @param explicit_locations true if each declaration should explicitly define location
   9854  *                            of the variable ( eg. (layout location=X) )
   9855  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
   9856  *                            be NULL.
   9857  *
   9858  *  @return Requested string.
   9859  **/
   9860 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
   9861 														const char* layout_qualifier)
   9862 {
   9863 	std::stringstream result_sstream;
   9864 
   9865 	/* Define output variables */
   9866 	const size_t n_variables = variables.size();
   9867 
   9868 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9869 	{
   9870 		unsigned int		  variable_array_size  = variables[n_variable].array_size;
   9871 		Utils::_variable_type variable_type		   = variables[n_variable].type;
   9872 		std::string			  variable_type_string = Utils::getVariableTypeString(variable_type);
   9873 
   9874 		result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
   9875 
   9876 		if (variable_array_size > 1)
   9877 		{
   9878 			result_sstream << "[" << variable_array_size << "]";
   9879 		}
   9880 
   9881 		result_sstream << ";\n";
   9882 	} /* for (all user-specified variable types) */
   9883 
   9884 	return result_sstream.str();
   9885 }
   9886 
   9887 /** Retrieves body of a vertex shader that uses user-specified set of variables
   9888  *  to declare contents of input & output block.
   9889  *
   9890  *  @param variables As per description.
   9891  *
   9892  *  @return Requested string.
   9893  **/
   9894 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
   9895 {
   9896 	std::stringstream result_sstream;
   9897 
   9898 	/* Form pre-amble */
   9899 	result_sstream << "#version 400\n"
   9900 					  "\n";
   9901 
   9902 	/* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
   9903 	if (m_are_double_inputs_supported)
   9904 	{
   9905 		result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
   9906 					   << getVariableDeclarations("in_vs", variables, "in");
   9907 	}
   9908 
   9909 	/* Define output variables */
   9910 	result_sstream << "out VS_DATA\n"
   9911 					  "{\n"
   9912 				   << getVariableDeclarations("vs", variables);
   9913 
   9914 	/* Define main() */
   9915 	result_sstream << "};\n"
   9916 					  "\n"
   9917 					  "void main()\n"
   9918 					  "{\n";
   9919 
   9920 	/* Set output variable values */
   9921 	unsigned int counter	 = 1;
   9922 	const size_t n_variables = variables.size();
   9923 
   9924 	for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
   9925 	{
   9926 		unsigned int		  variable_array_size		 = variables[n_variable].array_size;
   9927 		Utils::_variable_type variable_type				 = variables[n_variable].type;
   9928 		const unsigned int	n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
   9929 		std::string			  variable_type_string		 = Utils::getVariableTypeString(variable_type);
   9930 
   9931 		for (unsigned int index = 0; index < variable_array_size; ++index)
   9932 		{
   9933 			if (variable_array_size == 1)
   9934 			{
   9935 				result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
   9936 			}
   9937 			else
   9938 			{
   9939 				result_sstream << "vs_variable" << n_variable << "[" << index << "]"
   9940 							   << " = " << variable_type_string << "(";
   9941 			}
   9942 
   9943 			for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
   9944 			{
   9945 				result_sstream << (double)(counter++);
   9946 
   9947 				/* Use input attributes, if available */
   9948 				if (m_are_double_inputs_supported)
   9949 				{
   9950 					result_sstream << " + in_vs_variable" << n_variable;
   9951 
   9952 					if (variable_array_size > 1)
   9953 					{
   9954 						result_sstream << "[" << index << "]";
   9955 					}
   9956 
   9957 					if (Utils::isMatrixVariableType(variables[n_variable].type))
   9958 					{
   9959 						const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
   9960 						const unsigned int column	= n_component % n_columns;
   9961 						const unsigned int row		 = n_component / n_columns;
   9962 
   9963 						result_sstream << "[" << (column) << "]"
   9964 															 "."
   9965 									   << Utils::getComponentAtIndex(row);
   9966 					}
   9967 					else if (n_variable_type_components > 1)
   9968 					{
   9969 						result_sstream << "[" << n_component << "]";
   9970 					}
   9971 				}
   9972 
   9973 				if (n_component != (n_variable_type_components - 1))
   9974 				{
   9975 					result_sstream << ", ";
   9976 				}
   9977 			} /* for (all components) */
   9978 
   9979 			result_sstream << ");\n";
   9980 		}
   9981 	} /* for (all variable types) */
   9982 
   9983 	/* We will be using geometry shader to lay out the actual vertices so
   9984 	 * the only thing we need to make sure is that the vertex never gets
   9985 	 * culled.
   9986 	 */
   9987 	result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
   9988 					  "}\n";
   9989 
   9990 	/* That's it */
   9991 	return result_sstream.str();
   9992 }
   9993 
   9994 /** Initializes shader objects required to run the test. */
   9995 void GPUShaderFP64Test7::initTest()
   9996 {
   9997 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   9998 
   9999 	/* Are double-precision input variables supported? */
   10000 	m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
   10001 
   10002 	/* Create a vertex array object */
   10003 	gl.genVertexArrays(1, &m_vao_id);
   10004 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   10005 
   10006 	gl.bindVertexArray(m_vao_id);
   10007 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   10008 
   10009 	/* Create a texture object we will use as FBO's color attachment */
   10010 	gl.genTextures(1, &m_to_id);
   10011 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
   10012 
   10013 	gl.bindTexture(GL_TEXTURE_2D, m_to_id);
   10014 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
   10015 
   10016 	gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
   10017 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
   10018 
   10019 	/* Allocate temporary buffer to hold the texture data we will be reading
   10020 	 * from color attachment. */
   10021 	m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
   10022 
   10023 	/* Create and set up a framebuffer object */
   10024 	gl.genFramebuffers(1, &m_fbo_id);
   10025 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
   10026 
   10027 	gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
   10028 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
   10029 
   10030 	gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
   10031 	GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
   10032 
   10033 	/* Create all shader objects */
   10034 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   10035 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   10036 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
   10037 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
   10038 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   10039 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   10040 
   10041 	/* Create test program object */
   10042 	m_po_id = gl.createProgram();
   10043 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
   10044 
   10045 	/* Attach the shaders to the program object */
   10046 	gl.attachShader(m_po_id, m_fs_id);
   10047 	gl.attachShader(m_po_id, m_gs_id);
   10048 	gl.attachShader(m_po_id, m_tc_id);
   10049 	gl.attachShader(m_po_id, m_te_id);
   10050 	gl.attachShader(m_po_id, m_vs_id);
   10051 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
   10052 
   10053 	/* The test passes double-precision values through the whole rendering pipeline.
   10054 	 * This translates to a notable amount of components that we would need to transfer
   10055 	 * all values in one fell swoop. The number is large enough to exceed minimum
   10056 	 * capabilities as described for OpenGL 4.0 implementations.
   10057 	 * For that reason, the test executes in turns. Each turn is allocated as many
   10058 	 * double-precision scalar/matrix values as supported by the tested GL implementation.
   10059 	 */
   10060 	glw::GLint gl_max_fragment_input_components_value				  = 0;
   10061 	glw::GLint gl_max_geometry_input_components_value				  = 0;
   10062 	glw::GLint gl_max_geometry_output_components_value				  = 0;
   10063 	glw::GLint gl_max_tess_control_input_components_value			  = 0;
   10064 	glw::GLint gl_max_tess_control_output_components_value			  = 0;
   10065 	glw::GLint gl_max_tess_evaluation_input_components_value		  = 0;
   10066 	glw::GLint gl_max_tess_evaluation_output_components_value		  = 0;
   10067 	glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
   10068 	glw::GLint gl_max_vertex_output_components_value				  = 0;
   10069 
   10070 	gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
   10071 	gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
   10072 	gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
   10073 	gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
   10074 	gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
   10075 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
   10076 	gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
   10077 	gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
   10078 				   &gl_max_transform_feedback_interleaved_components_value);
   10079 	gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
   10080 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
   10081 
   10082 	m_n_max_components_per_stage =
   10083 		de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
   10084 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
   10085 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
   10086 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
   10087 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
   10088 	m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
   10089 	m_n_max_components_per_stage =
   10090 		de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
   10091 	m_n_max_components_per_stage =
   10092 		de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
   10093 
   10094 	/* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
   10095 	 * the input patch */
   10096 	gl.patchParameteri(GL_PATCH_VERTICES, 1);
   10097 
   10098 	GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
   10099 
   10100 	/* Initialize a BO we will use to hold XFB data */
   10101 	gl.genBuffers(1, &m_xfb_bo_id);
   10102 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   10103 
   10104 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
   10105 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   10106 
   10107 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
   10108 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
   10109 }
   10110 
   10111 /** Executes test iteration.
   10112  *
   10113  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   10114  */
   10115 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
   10116 {
   10117 	/* Do not execute the test if GL_ARB_texture_view is not supported */
   10118 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   10119 	{
   10120 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
   10121 	}
   10122 
   10123 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
   10124 	{
   10125 		throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
   10126 	}
   10127 
   10128 	/* Initialize GL objects required to run the test */
   10129 	initTest();
   10130 
   10131 	/* Check the negative cases first */
   10132 	const Utils::_variable_type double_variable_types[] = {
   10133 		Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
   10134 		Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
   10135 		Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
   10136 		Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
   10137 		Utils::VARIABLE_TYPE_DMAT4X3,
   10138 	};
   10139 	const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
   10140 
   10141 	for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
   10142 		 ++n_double_variable_type)
   10143 	{
   10144 		for (unsigned int array_size = 1; array_size < 3; ++array_size)
   10145 		{
   10146 			Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
   10147 
   10148 			if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
   10149 			{
   10150 				m_testCtx.getLog() << tcu::TestLog::Message
   10151 								   << "A fragment shader with double-precision output variable compiled successfully."
   10152 								   << tcu::TestLog::EndMessage;
   10153 
   10154 				m_has_test_passed = false;
   10155 			}
   10156 
   10157 			if (compileShader(m_fs_id,
   10158 							  getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
   10159 			{
   10160 				m_testCtx.getLog()
   10161 					<< tcu::TestLog::Message
   10162 					<< "A fragment shader with double-precision input variables lacking flat layout qualifier"
   10163 					   " compiled successfully."
   10164 					<< tcu::TestLog::EndMessage;
   10165 
   10166 				m_has_test_passed = false;
   10167 			}
   10168 		}
   10169 	} /* for (all variable types) */
   10170 
   10171 	/* Execute functional test. Split the run into as many iterations as necessary
   10172 	 * so that we do not exceed GL implementation's capabilities. */
   10173 	unsigned int n_tested_variables = 0;
   10174 	_variables   variables_to_test;
   10175 
   10176 	while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
   10177 	{
   10178 		glw::GLint total_n_used_components = 0;
   10179 
   10180 		/* Use as many variables as possible for the iterations. Do not exceed maximum amount
   10181 		 * of varying components that can be used for all shadr stages.
   10182 		 */
   10183 		while (total_n_used_components < m_n_max_components_per_stage &&
   10184 			   n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
   10185 		{
   10186 			_variable	new_variable;
   10187 			unsigned int n_type_components = 0;
   10188 			glw::GLint   n_used_components = 0;
   10189 
   10190 			new_variable.array_size =
   10191 				((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
   10192 			new_variable.type = double_variable_types[n_tested_variables / 2];
   10193 
   10194 			/* Double-precision varyings can use twice as many components as single-precision FPs */
   10195 			n_type_components = 4 /* components per location */ *
   10196 								Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
   10197 			n_used_components = n_type_components * new_variable.array_size * 2;
   10198 
   10199 			/* Do we have enough space? */
   10200 			if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
   10201 			{
   10202 				if (n_used_components > m_n_max_components_per_stage)
   10203 				{ //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
   10204 					n_tested_variables++;
   10205 				}
   10206 				break;
   10207 			}
   10208 
   10209 			/* We can safely test the type in current iteration */
   10210 			total_n_used_components += n_used_components;
   10211 			n_tested_variables++;
   10212 
   10213 			variables_to_test.push_back(new_variable);
   10214 		}
   10215 
   10216 		if (variables_to_test.size() > 0)
   10217 		{
   10218 			m_has_test_passed &= executeFunctionalTest(variables_to_test);
   10219 
   10220 			variables_to_test.clear();
   10221 		}
   10222 	}
   10223 
   10224 	/* We're done */
   10225 	if (m_has_test_passed)
   10226 	{
   10227 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   10228 	}
   10229 	else
   10230 	{
   10231 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   10232 	}
   10233 
   10234 	return STOP;
   10235 }
   10236 
   10237 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
   10238 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
   10239 {
   10240 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   10241 	std::stringstream	 log_sstream;
   10242 
   10243 	log_sstream << "Test variable values as retrieved from geometry shader:\n";
   10244 
   10245 	/* Map the XFB BO contents into process space */
   10246 	const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   10247 
   10248 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
   10249 
   10250 	/* Read the variable contents. We only care about the set of varyings emitted
   10251 	 * for first vertex in the geometry shader */
   10252 	unsigned int		 n_varying	 = 0;
   10253 	const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
   10254 
   10255 	for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
   10256 		 ++variables_iterator, ++n_varying)
   10257 	{
   10258 		const _variable&			 variable			= *variables_iterator;
   10259 		const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
   10260 		const unsigned int			 n_components		= Utils::getNumberOfComponentsForVariableType(variable.type);
   10261 
   10262 		for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
   10263 		{
   10264 			log_sstream << "gs_variable" << n_varying;
   10265 
   10266 			if (variable.array_size > 1)
   10267 			{
   10268 				log_sstream << "[" << array_index << "]";
   10269 			}
   10270 
   10271 			log_sstream << ": (";
   10272 
   10273 			for (unsigned int n_component = 0; n_component < n_components; ++n_component)
   10274 			{
   10275 				log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
   10276 
   10277 				if (n_component != (n_components - 1))
   10278 				{
   10279 					log_sstream << ", ";
   10280 				}
   10281 
   10282 				traveller_ptr += sizeof(double);
   10283 			}
   10284 
   10285 			log_sstream << ")\n";
   10286 		} /* for (all array indices) */
   10287 	}	 /* for (all variables) */
   10288 
   10289 	/* Unmap the BO */
   10290 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   10291 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   10292 
   10293 	/* Pass the logged stream into the framework */
   10294 	m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
   10295 }
   10296 
   10297 /** De-allocates an arary holding strings representing names of varyings that
   10298  *  should be used for transform feed-back.
   10299  **/
   10300 void GPUShaderFP64Test7::releaseXFBVaryingNames()
   10301 {
   10302 	for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
   10303 	{
   10304 		delete[] m_xfb_varyings[n_varying];
   10305 	}
   10306 
   10307 	delete m_xfb_varyings;
   10308 	m_xfb_varyings = DE_NULL;
   10309 
   10310 	m_n_xfb_varyings = 0;
   10311 }
   10312 
   10313 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
   10314  *  Takes a list of test variables used for current iteration and assigns increasing values
   10315  *  to subsequent input attributes of the test program.
   10316  *
   10317  *  @param variables Test variables of the current iteration.
   10318  */
   10319 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
   10320 {
   10321 	const glw::Functions& gl	  = m_context.getRenderContext().getFunctions();
   10322 	unsigned int		  counter = 6;
   10323 
   10324 	for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
   10325 		 variable_iterator++)
   10326 	{
   10327 		const _variable&   variable			  = *variable_iterator;
   10328 		const bool		   is_matrix_type	 = Utils::isMatrixVariableType(variable.type);
   10329 		const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
   10330 		unsigned int	   n_components		  = 0;
   10331 		unsigned int	   n_columns		  = 1;
   10332 
   10333 		if (is_matrix_type)
   10334 		{
   10335 			n_columns	= Utils::getNumberOfColumnsForVariableType(variable.type);
   10336 			n_components = n_total_components / n_columns;
   10337 
   10338 			DE_ASSERT(n_total_components % n_columns == 0);
   10339 		}
   10340 		else
   10341 		{
   10342 			n_components = n_total_components;
   10343 		}
   10344 
   10345 		DE_ASSERT(n_components >= 1 && n_components <= 4);
   10346 
   10347 		for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
   10348 		{
   10349 			const double data[] = { -1, -1, -1, -1 };
   10350 
   10351 			switch (n_components)
   10352 			{
   10353 			case 1:
   10354 			{
   10355 				gl.vertexAttribL1dv(variable.attribute_location + index, data);
   10356 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
   10357 
   10358 				break;
   10359 			}
   10360 
   10361 			case 2:
   10362 			{
   10363 				gl.vertexAttribL2dv(variable.attribute_location + index, data);
   10364 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
   10365 
   10366 				break;
   10367 			}
   10368 
   10369 			case 3:
   10370 			{
   10371 				gl.vertexAttribL3dv(variable.attribute_location + index, data);
   10372 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
   10373 
   10374 				break;
   10375 			}
   10376 
   10377 			case 4:
   10378 			{
   10379 				gl.vertexAttribL4dv(variable.attribute_location + index, data);
   10380 				GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
   10381 
   10382 				break;
   10383 			}
   10384 
   10385 			default:
   10386 			{
   10387 				TCU_FAIL("Unrecognized number of components");
   10388 			}
   10389 			} /* switch (n_components) */
   10390 
   10391 			/* Make sure VAAs are disabled */
   10392 			gl.disableVertexAttribArray(variable.attribute_location + index);
   10393 			GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
   10394 
   10395 			counter += n_components;
   10396 		} /* for (all array indices) */
   10397 	}	 /* for (all variables) */
   10398 }
   10399 
   10400 /** Constructor
   10401  *
   10402  *  @param context Rendering context.
   10403  */
   10404 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
   10405 	: TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
   10406 											  "are accepted during compilation stage")
   10407 	, m_cs_id(0)
   10408 	, m_fs_id(0)
   10409 	, m_gs_id(0)
   10410 	, m_tc_id(0)
   10411 	, m_te_id(0)
   10412 	, m_vs_id(0)
   10413 	, m_has_test_passed(true)
   10414 {
   10415 }
   10416 
   10417 /** Deinitializes all buffers and GL objects that may have been generated
   10418  *  during test execution.
   10419  **/
   10420 void GPUShaderFP64Test8::deinit()
   10421 {
   10422 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   10423 
   10424 	if (m_cs_id != 0)
   10425 	{
   10426 		gl.deleteShader(m_cs_id);
   10427 
   10428 		m_cs_id = 0;
   10429 	}
   10430 
   10431 	if (m_fs_id != 0)
   10432 	{
   10433 		gl.deleteShader(m_fs_id);
   10434 
   10435 		m_fs_id = 0;
   10436 	}
   10437 
   10438 	if (m_gs_id != 0)
   10439 	{
   10440 		gl.deleteShader(m_gs_id);
   10441 
   10442 		m_gs_id = 0;
   10443 	}
   10444 
   10445 	if (m_tc_id != 0)
   10446 	{
   10447 		gl.deleteShader(m_tc_id);
   10448 
   10449 		m_tc_id = 0;
   10450 	}
   10451 
   10452 	if (m_te_id != 0)
   10453 	{
   10454 		gl.deleteShader(m_te_id);
   10455 
   10456 		m_te_id = 0;
   10457 	}
   10458 
   10459 	if (m_vs_id != 0)
   10460 	{
   10461 		gl.deleteShader(m_vs_id);
   10462 
   10463 		m_vs_id = 0;
   10464 	}
   10465 }
   10466 
   10467 /** Executes a single test case.
   10468  *
   10469  *  This function can throw TestError exceptions if GL implementation reports
   10470  *  an error.
   10471  *
   10472  *  @param test_case Test case descriptor.
   10473  *
   10474  *  @return true if test case passed, false otherwise.
   10475  **/
   10476 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
   10477 {
   10478 	const glw::Functions& gl		 = m_context.getRenderContext().getFunctions();
   10479 	const glw::GLuint	 so_ids[]   = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
   10480 	const unsigned int	n_so_ids   = sizeof(so_ids) / sizeof(so_ids[0]);
   10481 	bool				  result	 = true;
   10482 	const char*			  stage_body = NULL;
   10483 	const char*			  stage_name = NULL;
   10484 
   10485 	for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
   10486 	{
   10487 		const glw::GLuint so_id = so_ids[n_so_id];
   10488 
   10489 		/* Skip compute shader if it is not supported */
   10490 		if (0 == so_id)
   10491 		{
   10492 			continue;
   10493 		}
   10494 
   10495 		/* Compile the shader */
   10496 		gl.compileShader(so_id);
   10497 		GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
   10498 
   10499 		/* Has the compilation succeeded as expected? */
   10500 		glw::GLint compile_status = GL_FALSE;
   10501 
   10502 		gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
   10503 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
   10504 
   10505 		if (compile_status == GL_FALSE)
   10506 		{
   10507 			/* What is the current stage's name? */
   10508 			if (so_id == m_cs_id)
   10509 			{
   10510 				stage_body = test_case.cs_shader_body.c_str();
   10511 				stage_name = "Compute shader";
   10512 			}
   10513 			else if (so_id == m_fs_id)
   10514 			{
   10515 				stage_body = test_case.fs_shader_body.c_str();
   10516 				stage_name = "Fragment shader";
   10517 			}
   10518 			else if (so_id == m_gs_id)
   10519 			{
   10520 				stage_body = test_case.gs_shader_body.c_str();
   10521 				stage_name = "Geometry shader";
   10522 			}
   10523 			else if (so_id == m_tc_id)
   10524 			{
   10525 				stage_body = test_case.tc_shader_body.c_str();
   10526 				stage_name = "Tessellation control shader";
   10527 			}
   10528 			else if (so_id == m_te_id)
   10529 			{
   10530 				stage_body = test_case.te_shader_body.c_str();
   10531 				stage_name = "Tessellation evaluation shader";
   10532 			}
   10533 			else if (so_id == m_vs_id)
   10534 			{
   10535 				stage_body = test_case.vs_shader_body.c_str();
   10536 				stage_name = "Vertex shader";
   10537 			}
   10538 			else
   10539 			{
   10540 				/* Doesn't make much sense to throw exceptions here so.. */
   10541 				stage_body = "";
   10542 				stage_name = "[?]";
   10543 			}
   10544 
   10545 			/* This shader should have never failed to compile! */
   10546 			m_testCtx.getLog() << tcu::TestLog::Message << stage_name
   10547 							   << " has not compiled successfully, even though the shader is valid."
   10548 								  " Following is shader's body:\n"
   10549 							   << stage_body << tcu::TestLog::EndMessage;
   10550 
   10551 			result = false;
   10552 		}
   10553 	} /* for (all shader objects) */
   10554 
   10555 	return result;
   10556 }
   10557 
   10558 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
   10559  *  type.
   10560  *
   10561  *  @param variable_type Variable type to return valid argument lists for.
   10562  **/
   10563 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
   10564 	const Utils::_variable_type& variable_type)
   10565 {
   10566 	const Utils::_variable_type matrix_types[] = {
   10567 		Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
   10568 		Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
   10569 		Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
   10570 	};
   10571 	const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
   10572 												   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
   10573 	const unsigned int n_matrix_types	 = sizeof(matrix_types) / sizeof(matrix_types[0]);
   10574 	const unsigned int n_scalar_types	 = sizeof(scalar_types) / sizeof(scalar_types[0]);
   10575 	const int		   n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
   10576 
   10577 	/* Construct the argument list tree root. Each node carries a counter that tells how many components
   10578 	 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
   10579 	 * any children. Otherwise, each node is assigned as many children, as there are types that could be
   10580 	 * used to define a subsequent argument, and its counter is increased by the amount of components
   10581 	 * described by the type.
   10582 	 */
   10583 	_argument_list_tree_node root;
   10584 
   10585 	root.n_components_used = 0;
   10586 	root.parent			   = NULL;
   10587 	root.type			   = variable_type;
   10588 
   10589 	/* Fill till all leaves use up all available components */
   10590 	_argument_list_tree_node_queue nodes_queue;
   10591 
   10592 	nodes_queue.push(&root);
   10593 
   10594 	do
   10595 	{
   10596 		/* Pop the first item in the queue */
   10597 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
   10598 		nodes_queue.pop();
   10599 
   10600 		/* Matrix variable types can be defined by a combination of non-matrix variable types OR
   10601 		 * a single matrix variable type.
   10602 		 *
   10603 		 * Let's handle the latter case first.
   10604 		 */
   10605 		const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
   10606 
   10607 		if (Utils::isMatrixVariableType(current_node_ptr->type))
   10608 		{
   10609 			/* Iterate through all known matrix types. All the types can be used
   10610 			 * as a constructor, assuming only one value is used to define new matrix's
   10611 			 * contents. */
   10612 			for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
   10613 			{
   10614 				Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
   10615 
   10616 				/* Construct a new child node. Since GLSL spec clearly states we must not use more
   10617 				 * than one constructor argument if the only argument is a matrix type, mark the node
   10618 				 * as if it defined all available components.
   10619 				 */
   10620 				_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
   10621 
   10622 				new_subnode->n_components_used = n_total_components;
   10623 				new_subnode->parent			   = current_node_ptr;
   10624 				new_subnode->type			   = new_argument_type;
   10625 
   10626 				/* Add the descriptor to node list but do not add it to the queue. This would be
   10627 				 * a redundant operation, since no new children nodes would have been assigned to
   10628 				 * this node anyway.
   10629 				 */
   10630 				current_node_ptr->children.push_back(new_subnode);
   10631 			} /* for (all matrix types) */
   10632 		}	 /* if (current node's type is a matrix) */
   10633 
   10634 		/* Now for a combination of non-matrix variable types.. */
   10635 		if (!Utils::isMatrixVariableType(current_node_ptr->type))
   10636 		{
   10637 			/* Iterate through all known scalar types */
   10638 			for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
   10639 			{
   10640 				Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
   10641 				const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
   10642 
   10643 				/* Only use the scalar type if we don't exceed the amount of components we can define
   10644 				 * for requested type.
   10645 				 */
   10646 				if (n_new_argument_components <= n_components_remaining)
   10647 				{
   10648 					/* Form new node descriptor */
   10649 					_argument_list_tree_node* new_subnode = new _argument_list_tree_node;
   10650 
   10651 					new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
   10652 					new_subnode->parent			   = current_node_ptr;
   10653 					new_subnode->type			   = new_argument_type;
   10654 
   10655 					current_node_ptr->children.push_back(new_subnode);
   10656 					nodes_queue.push(new_subnode);
   10657 				}
   10658 			} /* for (all scalar types) */
   10659 		}	 /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
   10660 	} while (nodes_queue.size() > 0);
   10661 
   10662 	/* To construct the argument lists, traverse the tree. Each path from root to child
   10663 	 * gives us a single argument list.
   10664 	 *
   10665 	 * First, identify leaf nodes.
   10666 	 */
   10667 	_argument_list_tree_nodes leaf_nodes;
   10668 
   10669 	nodes_queue.push(&root);
   10670 
   10671 	do
   10672 	{
   10673 		_argument_list_tree_node* current_node_ptr = nodes_queue.front();
   10674 		nodes_queue.pop();
   10675 
   10676 		if (current_node_ptr->children.size() == 0)
   10677 		{
   10678 			/* This is a leaf node !*/
   10679 			leaf_nodes.push_back(current_node_ptr);
   10680 		}
   10681 		else
   10682 		{
   10683 			/* Throw all children nodes to the queue */
   10684 			const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
   10685 
   10686 			for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
   10687 			{
   10688 				nodes_queue.push(current_node_ptr->children[n_children_node]);
   10689 			} /* for (all children nodes) */
   10690 		}
   10691 	} while (nodes_queue.size() > 0);
   10692 
   10693 	/* For all leaf nodes, move up the tree and construct the argument lists. */
   10694 	const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
   10695 	_argument_lists	result;
   10696 
   10697 	for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
   10698 	{
   10699 		_argument_list			  argument_list;
   10700 		_argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
   10701 
   10702 		do
   10703 		{
   10704 			if (current_node_ptr != &root)
   10705 			{
   10706 				if (argument_list.size() == 0)
   10707 				{
   10708 					argument_list.push_back(current_node_ptr->type);
   10709 				}
   10710 				else
   10711 				{
   10712 					argument_list.insert(argument_list.begin(), current_node_ptr->type);
   10713 				}
   10714 			}
   10715 
   10716 			current_node_ptr = current_node_ptr->parent;
   10717 		} while (current_node_ptr != NULL);
   10718 
   10719 		result.push_back(argument_list);
   10720 	} /* for (all leaf nodes) */
   10721 
   10722 	return result;
   10723 }
   10724 
   10725 /** Retrieves body of a compute shader that should be used for the purpose of
   10726  *  user-specified test case.
   10727  *
   10728  *  @param test_case Test case descriptor to use.
   10729  *
   10730  *  @return Requested string.
   10731  **/
   10732 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
   10733 {
   10734 	std::stringstream result_sstream;
   10735 
   10736 	/* Form the body */
   10737 	result_sstream << "#version 420\n"
   10738 					  "#extension GL_ARB_compute_shader          : require\n"
   10739 					  "\n"
   10740 					  "layout(local_size_x = 1) in;\n"
   10741 					  "\n"
   10742 					  "void main()\n"
   10743 					  "{\n"
   10744 				   << getGeneralBody(test_case) << "}\n";
   10745 
   10746 	/* Return the body */
   10747 	return result_sstream.str();
   10748 }
   10749 
   10750 /** Retrieves body of a fragment shader that should be used for the purpose of
   10751  *  user-specified test case.
   10752  *
   10753  *  @param test_case Test case descriptor to use.
   10754  *
   10755  *  @return Requested string.
   10756  **/
   10757 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
   10758 {
   10759 	std::stringstream result_sstream;
   10760 
   10761 	/* Form the body */
   10762 	result_sstream << "#version 420\n"
   10763 					  "\n"
   10764 					  "void main()\n"
   10765 					  "{\n"
   10766 				   << getGeneralBody(test_case) << "}\n"
   10767 												   "\n";
   10768 
   10769 	/* Return the body */
   10770 	return result_sstream.str();
   10771 }
   10772 
   10773 /** Returns a GLSL line that defines and initializes a variable as described by
   10774  *  user-specified test case descriptor.
   10775  *
   10776  *  @param test_case Test case descriptor to use for the query.
   10777  *
   10778  *  @return As per description
   10779  **/
   10780 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
   10781 {
   10782 	std::stringstream result_sstream;
   10783 
   10784 	/* Form the body */
   10785 	std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
   10786 
   10787 	result_sstream << variable_type_string << " src = " << variable_type_string << "(";
   10788 
   10789 	for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
   10790 		 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
   10791 	{
   10792 		const Utils::_variable_type argument_variable_type = *argument_list_iterator;
   10793 		std::string		   argument_variable_type_string   = Utils::getVariableTypeString(argument_variable_type);
   10794 		const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
   10795 
   10796 		if (argument_list_iterator != test_case.argument_list.begin())
   10797 		{
   10798 			result_sstream << ", ";
   10799 		}
   10800 
   10801 		result_sstream << argument_variable_type_string << "(";
   10802 
   10803 		for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
   10804 		{
   10805 			result_sstream << (double)(n_component + 1);
   10806 
   10807 			if (n_component != (argument_n_components - 1))
   10808 			{
   10809 				result_sstream << ", ";
   10810 			}
   10811 		} /* for (all argument components) */
   10812 
   10813 		result_sstream << ")";
   10814 	} /* for (all arguments) */
   10815 
   10816 	result_sstream << ");\n";
   10817 
   10818 	return result_sstream.str();
   10819 }
   10820 
   10821 /** Retrieves body of a geometry shader that should be used for the purpose of
   10822  *  user-specified test case.
   10823  *
   10824  *  @param test_case Test case descriptor to use.
   10825  *
   10826  *  @return Requested string.
   10827  **/
   10828 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
   10829 {
   10830 	std::stringstream result_sstream;
   10831 
   10832 	/* Form the body */
   10833 	result_sstream << "#version 420\n"
   10834 					  "\n"
   10835 					  "layout(points)                 in;\n"
   10836 					  "layout(max_vertices=1, points) out;\n"
   10837 					  "\n"
   10838 					  "void main()\n"
   10839 					  "{\n"
   10840 				   << getGeneralBody(test_case) << "}\n"
   10841 												   "\n";
   10842 
   10843 	/* We're done! */
   10844 	return result_sstream.str();
   10845 }
   10846 
   10847 /** Retrieves body of a tesellation control shader that should be used for the purpose of
   10848  *  user-specified test case.
   10849  *
   10850  *  @param test_case Test case descriptor to use.
   10851  *
   10852  *  @return Requested string.
   10853  **/
   10854 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
   10855 {
   10856 	std::stringstream result_sstream;
   10857 
   10858 	/* Form the body */
   10859 	result_sstream << "#version 420\n"
   10860 					  "\n"
   10861 					  "layout(vertices=4) out;\n"
   10862 					  "\n"
   10863 					  "void main()\n"
   10864 					  "{\n"
   10865 				   << getGeneralBody(test_case) << "}\n"
   10866 												   "\n";
   10867 
   10868 	/* Return the body */
   10869 	return result_sstream.str();
   10870 }
   10871 
   10872 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
   10873  *  user-specified test case.
   10874  *
   10875  *  @param test_case Test case descriptor to use.
   10876  *
   10877  *  @return Requested string.
   10878  **/
   10879 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
   10880 {
   10881 	std::stringstream result_sstream;
   10882 
   10883 	/* Form the body */
   10884 	result_sstream << "#version 420\n"
   10885 					  "\n"
   10886 					  "layout(isolines) in;\n"
   10887 					  "\n"
   10888 					  "void main()\n"
   10889 					  "{\n"
   10890 				   << getGeneralBody(test_case) << "}\n"
   10891 												   "\n";
   10892 
   10893 	/* Return the body */
   10894 	return result_sstream.str();
   10895 }
   10896 
   10897 /** Retrieves body of a vertex shader that should be used for the purpose of
   10898  *  user-specified test case.
   10899  *
   10900  *  @param test_case Test case descriptor to use.
   10901  *
   10902  *  @return Requested string.
   10903  **/
   10904 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
   10905 {
   10906 	std::stringstream result_sstream;
   10907 
   10908 	/* Form the body */
   10909 	result_sstream << "#version 420\n"
   10910 					  "\n"
   10911 					  "void main()\n"
   10912 					  "{\n"
   10913 				   << getGeneralBody(test_case) << "}\n"
   10914 												   "\n";
   10915 
   10916 	return result_sstream.str();
   10917 }
   10918 
   10919 /** Initializes shader objects required to run the test. */
   10920 void GPUShaderFP64Test8::initTest()
   10921 {
   10922 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   10923 
   10924 	/* Generate shader objects */
   10925 
   10926 	/* Compute shader support and GL 4.2 required */
   10927 	if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
   10928 		(true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
   10929 	{
   10930 		m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
   10931 	}
   10932 
   10933 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
   10934 	m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
   10935 	m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
   10936 	m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
   10937 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   10938 
   10939 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
   10940 }
   10941 
   10942 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
   10943  *
   10944  *  @param test_case Test case descriptor to generate the shader bodies for.
   10945  **/
   10946 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
   10947 {
   10948 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   10949 
   10950 	test_case.cs_shader_body = getComputeShaderBody(test_case);
   10951 	test_case.fs_shader_body = getFragmentShaderBody(test_case);
   10952 	test_case.gs_shader_body = getGeometryShaderBody(test_case);
   10953 	test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
   10954 	test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
   10955 	test_case.vs_shader_body = getVertexShaderBody(test_case);
   10956 
   10957 	/* Assign the bodies to relevant shaders */
   10958 	const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
   10959 	const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
   10960 	const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
   10961 	const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
   10962 	const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
   10963 	const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
   10964 
   10965 	/* m_cs_id is initialized only if compute_shader is supported */
   10966 	if (0 != m_cs_id)
   10967 	{
   10968 		gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
   10969 	}
   10970 
   10971 	gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
   10972 	gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
   10973 	gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
   10974 	gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
   10975 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
   10976 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
   10977 }
   10978 
   10979 /** Executes test iteration.
   10980  *
   10981  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   10982  */
   10983 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
   10984 {
   10985 	/* Do not execute the test if GL_ARB_texture_view is not supported */
   10986 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   10987 	{
   10988 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
   10989 	}
   10990 
   10991 	/* Initialize GL objects needed to run the tests */
   10992 	initTest();
   10993 
   10994 	/* Build iteration array to run the tests in an automated manner */
   10995 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
   10996 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
   10997 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
   10998 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
   10999 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
   11000 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
   11001 													 Utils::VARIABLE_TYPE_DVEC4 };
   11002 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
   11003 
   11004 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
   11005 	{
   11006 		const Utils::_variable_type variable_type = variable_types[n_variable_type];
   11007 
   11008 		/* Construct a set of argument lists valid for the variable type considered */
   11009 		_argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
   11010 
   11011 		for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
   11012 			 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
   11013 		{
   11014 			/* Constructor thwe test case descriptor */
   11015 			_test_case test_case;
   11016 
   11017 			test_case.argument_list = *argument_list_iterator;
   11018 			test_case.type			= variable_type;
   11019 
   11020 			/* Initialize a program object we will use to perform the casting */
   11021 			initIteration(test_case);
   11022 
   11023 			/* See if the shader compiles. */
   11024 			m_has_test_passed &= executeIteration(test_case);
   11025 		} /* for (all argument lists) */
   11026 	}	 /* for (all variable types) */
   11027 
   11028 	/* We're done */
   11029 	if (m_has_test_passed)
   11030 	{
   11031 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   11032 	}
   11033 	else
   11034 	{
   11035 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   11036 	}
   11037 
   11038 	return STOP;
   11039 }
   11040 
   11041 /** Constructor.
   11042  *
   11043  *  @param context Rendering context.
   11044  *
   11045  **/
   11046 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
   11047 	: TestCase(context, "operators", "Verifies that general and relational operators work "
   11048 									 "correctly when used against double-precision floating-"
   11049 									 "point types.")
   11050 	, m_has_test_passed(true)
   11051 	, m_po_id(0)
   11052 	, m_xfb_bo_id(0)
   11053 	, m_vao_id(0)
   11054 	, m_vs_id(0)
   11055 {
   11056 	/* Left blank intentionally */
   11057 }
   11058 
   11059 /** Deinitializes all ES objects that may have been created during
   11060  *  test execution.
   11061  **/
   11062 void GPUShaderFP64Test9::deinit()
   11063 {
   11064 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   11065 
   11066 	if (m_po_id != 0)
   11067 	{
   11068 		gl.deleteProgram(m_po_id);
   11069 
   11070 		m_po_id = 0;
   11071 	}
   11072 
   11073 	if (m_xfb_bo_id != 0)
   11074 	{
   11075 		gl.deleteBuffers(1, &m_xfb_bo_id);
   11076 
   11077 		m_xfb_bo_id = 0;
   11078 	}
   11079 
   11080 	if (m_vao_id != 0)
   11081 	{
   11082 		gl.deleteVertexArrays(1, &m_vao_id);
   11083 
   11084 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
   11085 	}
   11086 
   11087 	if (m_vs_id != 0)
   11088 	{
   11089 		gl.deleteShader(m_vs_id);
   11090 
   11091 		m_vs_id = 0;
   11092 	}
   11093 }
   11094 
   11095 /** Executes a single test iteration using user-specified test case properties.
   11096  *
   11097  *  @param test_case Test case descriptor.
   11098  *
   11099  *  @return true if the pass was successful, false if the test should fail.
   11100  **/
   11101 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
   11102 {
   11103 	const glw::Functions& gl	 = m_context.getRenderContext().getFunctions();
   11104 	bool				  result = true;
   11105 
   11106 	/* Activate the test program object */
   11107 	gl.useProgram(m_po_id);
   11108 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
   11109 
   11110 	/* Draw a single point with XFB enabled */
   11111 	gl.beginTransformFeedback(GL_POINTS);
   11112 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
   11113 	{
   11114 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
   11115 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
   11116 	}
   11117 	gl.endTransformFeedback();
   11118 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
   11119 
   11120 	/* Map the XFB BO into process space */
   11121 	const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   11122 
   11123 	GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
   11124 
   11125 	result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
   11126 
   11127 	/* Unmap the BO */
   11128 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   11129 	GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
   11130 
   11131 	return result;
   11132 }
   11133 
   11134 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
   11135  *  under user-specified location.
   11136  *
   11137  *  @param matrix_a_type  Type of the l-side matrix.
   11138  *  @param matrix_a_data  Row-ordered data of l-side matrix.
   11139  *  @param matrix_b_type  Type of the r-side matrix.
   11140  *  @param matrix_b_data  Row-ordered data of r-side matrix.
   11141  *  @param out_result_ptr Deref to be used to store the multiplication result.
   11142  **/
   11143 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
   11144 													   const std::vector<double>&   matrix_a_data,
   11145 													   const Utils::_variable_type& matrix_b_type,
   11146 													   const std::vector<double>& matrix_b_data, double* out_result_ptr)
   11147 {
   11148 	(void)matrix_b_type;
   11149 	using namespace tcu;
   11150 	/* To keep the code maintainable, we only consider cases relevant for this test */
   11151 	switch (matrix_a_type)
   11152 	{
   11153 	case Utils::VARIABLE_TYPE_DMAT2:
   11154 	{
   11155 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
   11156 
   11157 		tcu::Matrix2d matrix_a(&matrix_a_data[0]);
   11158 		tcu::Matrix2d matrix_b(&matrix_b_data[0]);
   11159 		tcu::Matrix2d result;
   11160 
   11161 		matrix_a = transpose(matrix_a);
   11162 		matrix_b = transpose(matrix_b);
   11163 		result   = matrix_a * matrix_b;
   11164 
   11165 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
   11166 		break;
   11167 	}
   11168 
   11169 	case Utils::VARIABLE_TYPE_DMAT2X3:
   11170 	{
   11171 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
   11172 
   11173 		tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
   11174 		tcu::Matrix<double, 3, 2> matrix_a_transposed;
   11175 		tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
   11176 		tcu::Matrix<double, 2, 3> matrix_b_transposed;
   11177 		tcu::Matrix<double, 3, 3> result;
   11178 
   11179 		matrix_a_transposed = transpose(matrix_a);
   11180 		matrix_b_transposed = transpose(matrix_b);
   11181 		result				= matrix_a_transposed * matrix_b_transposed;
   11182 
   11183 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
   11184 		break;
   11185 	}
   11186 
   11187 	case Utils::VARIABLE_TYPE_DMAT2X4:
   11188 	{
   11189 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
   11190 
   11191 		tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
   11192 		tcu::Matrix<double, 4, 2> matrix_a_transposed;
   11193 		tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
   11194 		tcu::Matrix<double, 2, 4> matrix_b_transposed;
   11195 		tcu::Matrix<double, 4, 4> result;
   11196 
   11197 		matrix_a_transposed = transpose(matrix_a);
   11198 		matrix_b_transposed = transpose(matrix_b);
   11199 		result				= matrix_a_transposed * matrix_b_transposed;
   11200 
   11201 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
   11202 		break;
   11203 	}
   11204 
   11205 	case Utils::VARIABLE_TYPE_DMAT3:
   11206 	{
   11207 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
   11208 
   11209 		tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
   11210 		tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
   11211 		tcu::Matrix<double, 3, 3> result;
   11212 
   11213 		matrix_a = transpose(matrix_a);
   11214 		matrix_b = transpose(matrix_b);
   11215 		result   = matrix_a * matrix_b;
   11216 
   11217 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
   11218 		break;
   11219 	}
   11220 
   11221 	case Utils::VARIABLE_TYPE_DMAT3X2:
   11222 	{
   11223 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
   11224 
   11225 		tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
   11226 		tcu::Matrix<double, 2, 3> matrix_a_transposed;
   11227 		tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
   11228 		tcu::Matrix<double, 3, 2> matrix_b_transposed;
   11229 		tcu::Matrix<double, 2, 2> result;
   11230 
   11231 		matrix_a_transposed = transpose(matrix_a);
   11232 		matrix_b_transposed = transpose(matrix_b);
   11233 		result				= matrix_a_transposed * matrix_b_transposed;
   11234 
   11235 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
   11236 		break;
   11237 	}
   11238 
   11239 	case Utils::VARIABLE_TYPE_DMAT3X4:
   11240 	{
   11241 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
   11242 
   11243 		tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
   11244 		tcu::Matrix<double, 4, 3> matrix_a_transposed;
   11245 		tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
   11246 		tcu::Matrix<double, 3, 4> matrix_b_transposed;
   11247 		tcu::Matrix<double, 4, 4> result;
   11248 
   11249 		matrix_a_transposed = transpose(matrix_a);
   11250 		matrix_b_transposed = transpose(matrix_b);
   11251 		result				= matrix_a_transposed * matrix_b_transposed;
   11252 
   11253 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
   11254 		break;
   11255 	}
   11256 
   11257 	case Utils::VARIABLE_TYPE_DMAT4:
   11258 	{
   11259 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
   11260 
   11261 		tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
   11262 		tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
   11263 		tcu::Matrix<double, 4, 4> result;
   11264 
   11265 		matrix_a = transpose(matrix_a);
   11266 		matrix_b = transpose(matrix_b);
   11267 		result   = matrix_a * matrix_b;
   11268 
   11269 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
   11270 		break;
   11271 	}
   11272 
   11273 	case Utils::VARIABLE_TYPE_DMAT4X2:
   11274 	{
   11275 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
   11276 
   11277 		tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
   11278 		tcu::Matrix<double, 2, 4> matrix_a_transposed;
   11279 		tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
   11280 		tcu::Matrix<double, 4, 2> matrix_b_transposed;
   11281 		tcu::Matrix<double, 2, 2> result;
   11282 
   11283 		matrix_a_transposed = transpose(matrix_a);
   11284 		matrix_b_transposed = transpose(matrix_b);
   11285 		result				= matrix_a_transposed * matrix_b_transposed;
   11286 
   11287 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
   11288 		break;
   11289 	}
   11290 
   11291 	case Utils::VARIABLE_TYPE_DMAT4X3:
   11292 	{
   11293 		DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
   11294 
   11295 		tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
   11296 		tcu::Matrix<double, 3, 4> matrix_a_transposed;
   11297 		tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
   11298 		tcu::Matrix<double, 4, 3> matrix_b_transposed;
   11299 		tcu::Matrix<double, 3, 3> result;
   11300 
   11301 		matrix_a_transposed = transpose(matrix_a);
   11302 		matrix_b_transposed = transpose(matrix_b);
   11303 		result				= matrix_a_transposed * matrix_b_transposed;
   11304 
   11305 		memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
   11306 		break;
   11307 	}
   11308 
   11309 	default:
   11310 	{
   11311 		TCU_FAIL("Unrecognized matrix A type");
   11312 	}
   11313 	} /* switch (matrix_a_type) */
   11314 }
   11315 
   11316 /** Returns GLSL operator representation of the user-specified operation.
   11317  *
   11318  *  @param operation_type Internal operation type to retrieve the operator for.
   11319  *
   11320  *  @return As per description.
   11321  **/
   11322 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
   11323 {
   11324 	const char* result = NULL;
   11325 
   11326 	switch (operation_type)
   11327 	{
   11328 	case OPERATION_TYPE_ADDITION:
   11329 		result = "+";
   11330 		break;
   11331 	case OPERATION_TYPE_DIVISION:
   11332 		result = "/";
   11333 		break;
   11334 	case OPERATION_TYPE_MULTIPLICATION:
   11335 		result = "*";
   11336 		break;
   11337 	case OPERATION_TYPE_SUBTRACTION:
   11338 		result = "-";
   11339 		break;
   11340 
   11341 	case OPERATION_TYPE_PRE_DECREMENTATION:
   11342 	case OPERATION_TYPE_POST_DECREMENTATION:
   11343 	{
   11344 		result = "--";
   11345 
   11346 		break;
   11347 	}
   11348 
   11349 	case OPERATION_TYPE_PRE_INCREMENTATION:
   11350 	case OPERATION_TYPE_POST_INCREMENTATION:
   11351 	{
   11352 		result = "++";
   11353 
   11354 		break;
   11355 	}
   11356 
   11357 	default:
   11358 	{
   11359 		TCU_FAIL("Unrecognized operation type");
   11360 	}
   11361 	} /* switch(operation_type) */
   11362 
   11363 	return result;
   11364 }
   11365 
   11366 /** Returns a string representing user-specified operation type.
   11367  *
   11368  *  @param operation_type Operation type to return the literal for.
   11369  *
   11370  *  @return Requested string.
   11371  **/
   11372 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
   11373 {
   11374 	std::string result = "[?]";
   11375 
   11376 	switch (operation_type)
   11377 	{
   11378 	case OPERATION_TYPE_ADDITION:
   11379 		result = "addition";
   11380 		break;
   11381 	case OPERATION_TYPE_DIVISION:
   11382 		result = "division";
   11383 		break;
   11384 	case OPERATION_TYPE_MULTIPLICATION:
   11385 		result = "multiplication";
   11386 		break;
   11387 	case OPERATION_TYPE_SUBTRACTION:
   11388 		result = "subtraction";
   11389 		break;
   11390 	case OPERATION_TYPE_PRE_DECREMENTATION:
   11391 		result = "pre-decrementation";
   11392 		break;
   11393 	case OPERATION_TYPE_PRE_INCREMENTATION:
   11394 		result = "pre-incrementation";
   11395 		break;
   11396 	case OPERATION_TYPE_POST_DECREMENTATION:
   11397 		result = "post-decrementation";
   11398 		break;
   11399 	case OPERATION_TYPE_POST_INCREMENTATION:
   11400 		result = "post-incrementation";
   11401 		break;
   11402 
   11403 	default:
   11404 	{
   11405 		TCU_FAIL("Unrecognized operation type");
   11406 	}
   11407 	}
   11408 
   11409 	return result;
   11410 }
   11411 
   11412 /** Returns body of a vertex shader that should be used for user-specified test case
   11413  *  descriptor.
   11414  *
   11415  *  @param test_case Test case descriptor.
   11416  *
   11417  *  @return Requested GLSL shader body.
   11418  **/
   11419 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
   11420 {
   11421 	std::stringstream  result_sstream;
   11422 	std::string		   result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
   11423 	std::string		   variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
   11424 	std::string		   variable_type_string	= Utils::getVariableTypeString(test_case.variable_type);
   11425 	const unsigned int n_variable_components   = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
   11426 
   11427 	/* If we are to multiply matrices, we will need to use a different type
   11428 	 * for the result variable if either of the matrices is not square.
   11429 	 */
   11430 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
   11431 		Utils::isMatrixVariableType(test_case.variable_type))
   11432 	{
   11433 		Utils::_variable_type result_variable_type;
   11434 		Utils::_variable_type transposed_matrix_variable_type =
   11435 			Utils::getTransposedMatrixVariableType(test_case.variable_type);
   11436 
   11437 		result_variable_type =
   11438 			Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
   11439 		result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
   11440 
   11441 		test_case.result_variable_type = result_variable_type;
   11442 	}
   11443 
   11444 	/* Form the pre-amble */
   11445 	result_sstream << "#version 400\n"
   11446 					  "\n"
   11447 
   11448 					  /* Add output variables */
   11449 					  "out "
   11450 				   << result_variable_type_string << " result;\n"
   11451 													 "out ivec2 result_lt;\n"
   11452 													 "out ivec2 result_lte;\n"
   11453 													 "out ivec2 result_gt;\n"
   11454 													 "out ivec2 result_gte;\n"
   11455 													 "void main()\n"
   11456 													 "{\n";
   11457 
   11458 	/* Form reference values */
   11459 	result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
   11460 
   11461 	for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
   11462 	{
   11463 		result_sstream << (n_variable_component + 1);
   11464 
   11465 		if (n_variable_component != (n_variable_components - 1))
   11466 		{
   11467 			result_sstream << ", ";
   11468 		}
   11469 	} /* for (all variable components) */
   11470 
   11471 	result_sstream << ");\n";
   11472 
   11473 	for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
   11474 		 ++n_ref2_case)
   11475 	{
   11476 		Utils::_variable_type compatible_variable_type = test_case.variable_type;
   11477 
   11478 		if (Utils::isMatrixVariableType(compatible_variable_type) &&
   11479 			test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
   11480 		{
   11481 			compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
   11482 		}
   11483 
   11484 		std::string ref2_variable_type_fp_string =
   11485 			Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
   11486 		std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
   11487 		std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
   11488 		std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
   11489 
   11490 		result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
   11491 
   11492 		for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
   11493 			 ++n_variable_component)
   11494 		{
   11495 			result_sstream << (n_variable_components - (n_variable_component + 1));
   11496 
   11497 			if (n_variable_component != (n_variable_components - 1))
   11498 			{
   11499 				result_sstream << ", ";
   11500 			}
   11501 		} /* for (all variable components) */
   11502 
   11503 		result_sstream << ");\n";
   11504 	} /* for (both reference2 declarations) */
   11505 
   11506 	/* Add actual body */
   11507 	result_sstream << "\n"
   11508 					  "result = ";
   11509 
   11510 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
   11511 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
   11512 	{
   11513 		result_sstream << getOperatorForOperationType(test_case.operation_type);
   11514 	}
   11515 
   11516 	result_sstream << "reference1 ";
   11517 
   11518 	if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
   11519 		test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
   11520 		test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
   11521 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
   11522 	{
   11523 		if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
   11524 			test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
   11525 		{
   11526 			result_sstream << getOperatorForOperationType(test_case.operation_type);
   11527 		}
   11528 	}
   11529 	else
   11530 	{
   11531 		result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
   11532 	}
   11533 
   11534 	result_sstream << ";\n";
   11535 
   11536 	if (Utils::isScalarVariableType(test_case.variable_type))
   11537 	{
   11538 		result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
   11539 						  "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
   11540 						  "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
   11541 						  "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
   11542 						  "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
   11543 						  "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
   11544 						  "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
   11545 						  "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
   11546 	}
   11547 	else
   11548 	{
   11549 		result_sstream << "result_lt [0] = 1;\n"
   11550 						  "result_lt [1] = 1;\n"
   11551 						  "result_lte[0] = 1;\n"
   11552 						  "result_lte[1] = 1;\n"
   11553 						  "result_gt [0] = 1;\n"
   11554 						  "result_gt [1] = 1;\n"
   11555 						  "result_gte[0] = 1;\n"
   11556 						  "result_gte[1] = 1;\n";
   11557 	}
   11558 
   11559 	result_sstream << "}\n";
   11560 
   11561 	/* All done */
   11562 	return result_sstream.str();
   11563 }
   11564 
   11565 /** Initializes all GL objects required to run the test.
   11566  *
   11567  *  This function can throw a TestError exception if the implementation misbehaves.
   11568  */
   11569 void GPUShaderFP64Test9::initTest()
   11570 {
   11571 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   11572 
   11573 	/* Create program & vertex shader objects */
   11574 	m_po_id = gl.createProgram();
   11575 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
   11576 
   11577 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
   11578 
   11579 	/* Attach the shader to the program */
   11580 	gl.attachShader(m_po_id, m_vs_id);
   11581 	GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
   11582 
   11583 	/* Set up a buffer object */
   11584 	gl.genBuffers(1, &m_xfb_bo_id);
   11585 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
   11586 
   11587 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
   11588 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
   11589 
   11590 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
   11591 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
   11592 
   11593 	/* Set up a vertex array object */
   11594 	gl.genVertexArrays(1, &m_vao_id);
   11595 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
   11596 
   11597 	gl.bindVertexArray(m_vao_id);
   11598 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
   11599 }
   11600 
   11601 /** Initializes all GL objects required to run an iteration described by
   11602  *  user-specified test case descriptor.
   11603  *
   11604  *  @param test_case Test case descriptor to use for the initialization.
   11605  **/
   11606 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
   11607 {
   11608 	const glw::Functions& gl			  = m_context.getRenderContext().getFunctions();
   11609 	std::string			  vs_body		  = getVertexShaderBody(test_case);
   11610 	const char*			  vs_body_raw_ptr = vs_body.c_str();
   11611 
   11612 	/* Store the shader's body */
   11613 	test_case.vs_body = vs_body;
   11614 
   11615 	/* Try to compile the shader */
   11616 	glw::GLint compile_status = GL_FALSE;
   11617 
   11618 	gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
   11619 	GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
   11620 
   11621 	gl.compileShader(m_vs_id);
   11622 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
   11623 
   11624 	gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
   11625 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
   11626 
   11627 	if (compile_status != GL_TRUE)
   11628 	{
   11629 		TCU_FAIL("Test shader compilation failed.");
   11630 	}
   11631 
   11632 	/* Configure XFB */
   11633 	const char*		   xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
   11634 	const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
   11635 
   11636 	gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
   11637 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
   11638 
   11639 	/* Try to link the program */
   11640 	glw::GLint link_status = GL_FALSE;
   11641 
   11642 	gl.linkProgram(m_po_id);
   11643 	GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
   11644 
   11645 	gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
   11646 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
   11647 
   11648 	if (link_status != GL_TRUE)
   11649 	{
   11650 		TCU_FAIL("Test program linking failure");
   11651 	}
   11652 
   11653 	/* Set up XFB BO data storage */
   11654 	const unsigned int result_variable_size = static_cast<unsigned int>(
   11655 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
   11656 	const unsigned int xfb_bo_size = static_cast<unsigned int>(
   11657 		result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
   11658 
   11659 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
   11660 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
   11661 }
   11662 
   11663 /** Executes test iteration.
   11664  *
   11665  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
   11666  */
   11667 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
   11668 {
   11669 	/* Do not execute the test if GL_ARB_texture_view is not supported */
   11670 	if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   11671 	{
   11672 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
   11673 	}
   11674 
   11675 	/* Initialize all ES objects required to run all the checks */
   11676 	initTest();
   11677 
   11678 	/* Iterate through all variable types we want to test */
   11679 	const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2,   Utils::VARIABLE_TYPE_DMAT2X3,
   11680 													 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
   11681 													 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
   11682 													 Utils::VARIABLE_TYPE_DMAT4,   Utils::VARIABLE_TYPE_DMAT4X2,
   11683 													 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
   11684 													 Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
   11685 													 Utils::VARIABLE_TYPE_DVEC4 };
   11686 	const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
   11687 
   11688 	for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
   11689 	{
   11690 		/* Iterate through all operation types we want to check */
   11691 		for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
   11692 		{
   11693 			_operation_type				 operation_type = (_operation_type)n_operation_type;
   11694 			const Utils::_variable_type& variable_type  = variable_types[n_variable_type];
   11695 
   11696 			/* Construct test case descriptor */
   11697 			_test_case test_case;
   11698 
   11699 			test_case.operation_type	   = operation_type;
   11700 			test_case.result_variable_type = variable_type;
   11701 			test_case.variable_type		   = variable_type;
   11702 
   11703 			/* Run the iteration */
   11704 			initTestIteration(test_case);
   11705 
   11706 			m_has_test_passed &= executeTestIteration(test_case);
   11707 		} /* for (all operation types) */
   11708 	}	 /* for (all variable types) */
   11709 
   11710 	/* All done. */
   11711 	if (m_has_test_passed)
   11712 	{
   11713 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
   11714 	}
   11715 	else
   11716 	{
   11717 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   11718 	}
   11719 
   11720 	return STOP;
   11721 }
   11722 
   11723 /** Verifies data XFBed out by the draw call for user-specified test case
   11724  *  descriptor.
   11725  *
   11726  *  @param test_case Test case descriptor
   11727  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
   11728  *                   Must not be NULL.
   11729  *
   11730  *  @return true if the data was found to be correct, false otherwise.
   11731  **/
   11732 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
   11733 {
   11734 	const double	   epsilon = 1e-5;
   11735 	const unsigned int n_result_components =
   11736 		Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
   11737 	bool		  result			  = true;
   11738 	const double* xfb_data_result	 = (const double*)xfb_data;
   11739 	const int*	xfb_data_result_lt  = (const int*)(xfb_data_result + n_result_components);
   11740 	const int*	xfb_data_result_lte = (const int*)xfb_data_result_lt + 2;  /* cast/non-cast cases */
   11741 	const int*	xfb_data_result_gt  = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
   11742 	const int*	xfb_data_result_gte = (const int*)xfb_data_result_gt + 2;  /* cast/non-cast cases */
   11743 
   11744 	/* Prepare reference values */
   11745 	int					modifier;
   11746 	std::vector<double> reference1;
   11747 	std::vector<double> reference2;
   11748 
   11749 	if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
   11750 		test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
   11751 	{
   11752 		modifier = 1;
   11753 	}
   11754 	else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
   11755 			 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
   11756 	{
   11757 		modifier = -1;
   11758 	}
   11759 	else
   11760 	{
   11761 		modifier = 0;
   11762 	}
   11763 
   11764 	if (Utils::isMatrixVariableType(test_case.variable_type))
   11765 	{
   11766 		/* Matrices may be of different sizes so we need to compute the
   11767 		 * reference values separately for each matrix
   11768 		 */
   11769 		const Utils::_variable_type matrix_a_type = test_case.variable_type;
   11770 		const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
   11771 		const unsigned int			n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
   11772 		const unsigned int			n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
   11773 
   11774 		for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
   11775 		{
   11776 			reference1.push_back(modifier + n_component + 1);
   11777 		}
   11778 
   11779 		for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
   11780 		{
   11781 			reference2.push_back(n_matrix_b_components - (n_component + 1));
   11782 		}
   11783 	} /* if (Utils::isMatrixVariableType(test_case.variable_type) */
   11784 	else
   11785 	{
   11786 		/* Generate as many components as will be expected for the result variable */
   11787 		for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
   11788 		{
   11789 			reference1.push_back(modifier + n_result_component + 1);
   11790 			reference2.push_back(n_result_components - (n_result_component + 1));
   11791 		}
   11792 	}
   11793 
   11794 	/* Verify the result value(s) */
   11795 	if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
   11796 		Utils::isMatrixVariableType(test_case.variable_type))
   11797 	{
   11798 		/* Matrix multiplication */
   11799 		double				  expected_result_data[4 * 4];
   11800 		Utils::_variable_type matrix_a_type = test_case.variable_type;
   11801 		Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
   11802 
   11803 		getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
   11804 
   11805 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
   11806 		{
   11807 			if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
   11808 			{
   11809 				std::stringstream log_sstream;
   11810 
   11811 				log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
   11812 							<< Utils::getVariableTypeString(matrix_b_type)
   11813 							<< " matrix multiplication was incorrect; expected:(";
   11814 
   11815 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
   11816 					 ++n_logged_component)
   11817 				{
   11818 					log_sstream << expected_result_data[n_logged_component];
   11819 
   11820 					if (n_logged_component != (n_result_components - 1))
   11821 					{
   11822 						log_sstream << ", ";
   11823 					}
   11824 				} /* for (all components to be logged) */
   11825 
   11826 				log_sstream << "), retrieved:(";
   11827 
   11828 				for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
   11829 					 ++n_logged_component)
   11830 				{
   11831 					log_sstream << xfb_data_result[n_logged_component];
   11832 
   11833 					if (n_logged_component != (n_result_components - 1))
   11834 					{
   11835 						log_sstream << ", ";
   11836 					}
   11837 				} /* for (all components to be logged) */
   11838 
   11839 				log_sstream << ")";
   11840 
   11841 				m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
   11842 
   11843 				result = false;
   11844 				break;
   11845 			}
   11846 		} /* for (all result components) */
   11847 	}	 /* if (dealing with matrix multiplication) */
   11848 	else
   11849 	{
   11850 		for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
   11851 		{
   11852 			double expected_value = reference1[n_component];
   11853 
   11854 			switch (test_case.operation_type)
   11855 			{
   11856 			case OPERATION_TYPE_ADDITION:
   11857 				expected_value += reference2[n_component];
   11858 				break;
   11859 			case OPERATION_TYPE_DIVISION:
   11860 				expected_value /= reference2[n_component];
   11861 				break;
   11862 			case OPERATION_TYPE_MULTIPLICATION:
   11863 				expected_value *= reference2[n_component];
   11864 				break;
   11865 			case OPERATION_TYPE_SUBTRACTION:
   11866 				expected_value -= reference2[n_component];
   11867 				break;
   11868 
   11869 			case OPERATION_TYPE_PRE_DECREMENTATION:
   11870 			case OPERATION_TYPE_PRE_INCREMENTATION:
   11871 			{
   11872 				/* Modifier already applied */
   11873 				break;
   11874 			}
   11875 
   11876 			case OPERATION_TYPE_POST_DECREMENTATION:
   11877 			case OPERATION_TYPE_POST_INCREMENTATION:
   11878 			{
   11879 				/* Need to reverse the modification for the purpose of the following check */
   11880 				expected_value -= modifier;
   11881 
   11882 				break;
   11883 			}
   11884 
   11885 			default:
   11886 			{
   11887 				TCU_FAIL("Unrecognized operation type");
   11888 			}
   11889 			} /* switch (test_case.operation_type) */
   11890 
   11891 			if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
   11892 			{
   11893 				std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   11894 				std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   11895 
   11896 				m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
   11897 								   << variable_type_string << "]"
   11898 															  " and operation type ["
   11899 								   << operation_type_string << "]"
   11900 															   " were found invalid."
   11901 								   << tcu::TestLog::EndMessage;
   11902 
   11903 				result = false;
   11904 				break;
   11905 			} /* if (test case failed) */
   11906 		}	 /* for (all components) */
   11907 	}
   11908 
   11909 	/* Verify the comparison operation results */
   11910 	if (Utils::isScalarVariableType(test_case.variable_type))
   11911 	{
   11912 		DE_ASSERT(n_result_components == 1);
   11913 
   11914 		const bool expected_result_lt[2]  = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
   11915 		const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
   11916 		const bool expected_result_gt[2]  = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
   11917 		const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
   11918 
   11919 		if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
   11920 			(xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
   11921 		{
   11922 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   11923 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   11924 
   11925 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
   11926 														   "variable type ["
   11927 							   << variable_type_string << "]"
   11928 														  "and operation type ["
   11929 							   << operation_type_string << "]"
   11930 														   "was found invalid; expected:("
   11931 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
   11932 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
   11933 							   << tcu::TestLog::EndMessage;
   11934 
   11935 			result = false;
   11936 		}
   11937 
   11938 		if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
   11939 			(xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
   11940 		{
   11941 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   11942 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   11943 
   11944 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
   11945 														   "variable type ["
   11946 							   << variable_type_string << "]"
   11947 														  "and operation type ["
   11948 							   << operation_type_string << "]"
   11949 														   "was found invalid; expected:("
   11950 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
   11951 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
   11952 							   << tcu::TestLog::EndMessage;
   11953 
   11954 			result = false;
   11955 		}
   11956 
   11957 		if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
   11958 			(xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
   11959 		{
   11960 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   11961 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   11962 
   11963 			m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
   11964 														   "variable type ["
   11965 							   << variable_type_string << "]"
   11966 														  "and operation type ["
   11967 							   << operation_type_string << "]"
   11968 														   "was found invalid; expected:("
   11969 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
   11970 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
   11971 							   << tcu::TestLog::EndMessage;
   11972 
   11973 			result = false;
   11974 		}
   11975 
   11976 		if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
   11977 			(xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
   11978 		{
   11979 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   11980 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   11981 
   11982 			m_testCtx.getLog() << tcu::TestLog::Message
   11983 							   << "Values reported for greater-than-or-equal operator used for "
   11984 								  "variable type ["
   11985 							   << variable_type_string << "]"
   11986 														  "and operation type ["
   11987 							   << operation_type_string << "]"
   11988 														   "was found invalid; expected:("
   11989 							   << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
   11990 							   << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
   11991 							   << tcu::TestLog::EndMessage;
   11992 
   11993 			result = false;
   11994 		}
   11995 	} /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
   11996 	else
   11997 	{
   11998 		if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
   11999 			xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
   12000 			xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
   12001 		{
   12002 			std::string operation_type_string = getOperationTypeString(test_case.operation_type);
   12003 			std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
   12004 
   12005 			m_testCtx.getLog() << tcu::TestLog::Message
   12006 							   << "Invalid value was reported for matrix variable type, for which "
   12007 								  " operator checks are not executed; variable type ["
   12008 							   << variable_type_string << "]"
   12009 														  "and operation type ["
   12010 							   << operation_type_string << "]" << tcu::TestLog::EndMessage;
   12011 
   12012 			result = false;
   12013 		}
   12014 	}
   12015 
   12016 	return result;
   12017 }
   12018 
   12019 namespace TypeHelpers
   12020 {
   12021 /** Get base type for reference types
   12022  *
   12023  * @tparam T type
   12024  **/
   12025 template <typename T>
   12026 class referenceToType
   12027 {
   12028 public:
   12029 	typedef T result;
   12030 };
   12031 
   12032 template <typename T>
   12033 class referenceToType<const T&>
   12034 {
   12035 public:
   12036 	typedef T result;
   12037 };
   12038 
   12039 /** Maps variable type with enumeration Utils::_variable_type
   12040  *
   12041  * @tparam T type
   12042  **/
   12043 template <typename T>
   12044 class typeInfo;
   12045 
   12046 template <>
   12047 class typeInfo<glw::GLboolean>
   12048 {
   12049 public:
   12050 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
   12051 };
   12052 
   12053 template <>
   12054 class typeInfo<glw::GLdouble>
   12055 {
   12056 public:
   12057 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
   12058 };
   12059 
   12060 template <>
   12061 class typeInfo<tcu::UVec2>
   12062 {
   12063 public:
   12064 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
   12065 };
   12066 
   12067 template <>
   12068 class typeInfo<tcu::UVec3>
   12069 {
   12070 public:
   12071 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
   12072 };
   12073 
   12074 template <>
   12075 class typeInfo<tcu::UVec4>
   12076 {
   12077 public:
   12078 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
   12079 };
   12080 
   12081 template <>
   12082 class typeInfo<tcu::DVec2>
   12083 {
   12084 public:
   12085 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
   12086 };
   12087 
   12088 template <>
   12089 class typeInfo<tcu::DVec3>
   12090 {
   12091 public:
   12092 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
   12093 };
   12094 
   12095 template <>
   12096 class typeInfo<tcu::DVec4>
   12097 {
   12098 public:
   12099 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
   12100 };
   12101 
   12102 template <>
   12103 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
   12104 {
   12105 public:
   12106 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
   12107 };
   12108 
   12109 template <>
   12110 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
   12111 {
   12112 public:
   12113 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
   12114 };
   12115 
   12116 template <>
   12117 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
   12118 {
   12119 public:
   12120 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
   12121 };
   12122 
   12123 template <>
   12124 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
   12125 {
   12126 public:
   12127 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
   12128 };
   12129 
   12130 template <>
   12131 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
   12132 {
   12133 public:
   12134 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
   12135 };
   12136 
   12137 template <>
   12138 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
   12139 {
   12140 public:
   12141 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
   12142 };
   12143 
   12144 template <>
   12145 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
   12146 {
   12147 public:
   12148 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
   12149 };
   12150 
   12151 template <>
   12152 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
   12153 {
   12154 public:
   12155 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
   12156 };
   12157 
   12158 template <>
   12159 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
   12160 {
   12161 public:
   12162 	static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
   12163 };
   12164 } /* TypeHelpers */
   12165 
   12166 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
   12167  *
   12168  **/
   12169 namespace Math
   12170 {
   12171 template <typename T>
   12172 static T clamp(T x, T minVal, T maxVal);
   12173 
   12174 template <int Size>
   12175 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
   12176 
   12177 template <int Size>
   12178 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
   12179 
   12180 template <typename T>
   12181 static T determinant(T val);
   12182 
   12183 template <typename T>
   12184 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
   12185 
   12186 template <typename T>
   12187 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
   12188 
   12189 template <typename T>
   12190 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
   12191 
   12192 template <int Size>
   12193 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
   12194 																glw::GLuint column, glw::GLuint row);
   12195 
   12196 template <int Size>
   12197 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
   12198 											const tcu::Vector<glw::GLdouble, Size>& right);
   12199 
   12200 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
   12201 
   12202 static glw::GLdouble fract(glw::GLdouble val);
   12203 
   12204 template <typename T>
   12205 static T frexp(T val, glw::GLint& exp);
   12206 
   12207 template <int Size>
   12208 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
   12209 												  const tcu::Vector<glw::GLdouble, Size>& right);
   12210 
   12211 template <int Size>
   12212 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12213 													   const tcu::Vector<glw::GLdouble, Size>& right);
   12214 
   12215 template <int Size>
   12216 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
   12217 
   12218 static glw::GLdouble inverseSqrt(glw::GLdouble val);
   12219 
   12220 static glw::GLuint isinf_impl(glw::GLdouble val);
   12221 
   12222 static glw::GLuint isnan_impl(glw::GLdouble val);
   12223 
   12224 template <typename T>
   12225 static T ldexp(T val, glw::GLint exp);
   12226 
   12227 template <int Size>
   12228 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
   12229 											   const tcu::Vector<glw::GLdouble, Size>& right);
   12230 
   12231 template <int Size>
   12232 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12233 													const tcu::Vector<glw::GLdouble, Size>& right);
   12234 
   12235 template <typename T>
   12236 static T max(T left, T right);
   12237 
   12238 template <typename T>
   12239 static T min(T left, T right);
   12240 
   12241 template <int		 Size>
   12242 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
   12243 								glw::GLuint row);
   12244 
   12245 template <typename T>
   12246 static T mix(T left, T right, T weight);
   12247 
   12248 template <typename T>
   12249 static T mod(T left, T right);
   12250 
   12251 template <typename T>
   12252 static T modf(T val, T& integer);
   12253 
   12254 template <typename T>
   12255 static T multiply(T left, T right);
   12256 
   12257 template <int Size>
   12258 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12259 											   const tcu::Vector<glw::GLdouble, Size>& right);
   12260 
   12261 template <int Cols, int Rows>
   12262 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
   12263 														   const tcu::Vector<glw::GLdouble, Cols>& right);
   12264 
   12265 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
   12266 
   12267 template <typename T>
   12268 static T round(T t);
   12269 
   12270 template <typename T>
   12271 static T roundEven(T t);
   12272 
   12273 template <typename T>
   12274 static T sign(T t);
   12275 
   12276 template <typename T>
   12277 static T smoothStep(T e0, T e1, T val);
   12278 
   12279 template <typename T>
   12280 static T step(T edge, T val);
   12281 
   12282 template <typename T, int Rows, int Cols>
   12283 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
   12284 
   12285 template <typename T>
   12286 static T trunc(T t);
   12287 
   12288 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
   12289 
   12290 template <typename T>
   12291 static T clamp(T x, T minVal, T maxVal)
   12292 {
   12293 	return min(max(x, minVal), maxVal);
   12294 }
   12295 
   12296 template <int Size>
   12297 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
   12298 {
   12299 	tcu::Matrix<glw::GLdouble, Size, Size> result;
   12300 
   12301 	for (glw::GLuint c = 0; c < Size; ++c)
   12302 	{
   12303 		for (glw::GLuint r = 0; r < Size; ++r)
   12304 		{
   12305 			const glw::GLdouble minor_value = minor_impl(matrix, c, r);
   12306 
   12307 			result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
   12308 		}
   12309 	}
   12310 
   12311 	return result;
   12312 }
   12313 
   12314 template <int Size>
   12315 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
   12316 {
   12317 	tcu::Vector<glw::GLuint, Size> result;
   12318 
   12319 	for (glw::GLint i = 0; i < Size; ++i)
   12320 	{
   12321 		if (GL_FALSE != src[i])
   12322 		{
   12323 			result[i] = 1;
   12324 		}
   12325 		else
   12326 		{
   12327 			result[i] = 0;
   12328 		}
   12329 	}
   12330 
   12331 	return result;
   12332 }
   12333 
   12334 template <typename T>
   12335 static T det2(T _00, T _10, T _01, T _11)
   12336 {
   12337 	return _00 * _11 - _01 * _10;
   12338 }
   12339 
   12340 template <typename T>
   12341 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
   12342 {
   12343 	return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
   12344 }
   12345 
   12346 template <typename T>
   12347 static T det4(T _00, T _10, T _20, T _30, T _01, T _11, T _21, T _31, T _02, T _12, T _22, T _32, T _03, T _13, T _23,
   12348 			  T _33)
   12349 {
   12350 	return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
   12351 		   _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
   12352 		   _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
   12353 		   _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
   12354 }
   12355 
   12356 template <typename T>
   12357 static T determinant(T val)
   12358 {
   12359 	return val;
   12360 }
   12361 
   12362 template <typename T>
   12363 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
   12364 {
   12365 	return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
   12366 }
   12367 
   12368 template <typename T>
   12369 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
   12370 {
   12371 	return det3(mat(0, 0), mat(0, 1), mat(0, 2), mat(1, 0), mat(1, 1), mat(1, 2), mat(2, 0), mat(2, 1), mat(2, 2));
   12372 }
   12373 
   12374 template <typename T>
   12375 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
   12376 {
   12377 	return det4(mat(0, 0), mat(0, 1), mat(0, 2), mat(0, 3), mat(1, 0), mat(1, 1), mat(1, 2), mat(1, 3), mat(2, 0),
   12378 				mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
   12379 }
   12380 
   12381 template <int Size>
   12382 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
   12383 																glw::GLuint column, glw::GLuint row)
   12384 {
   12385 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
   12386 
   12387 	for (glw::GLuint c = 0; c < Size; ++c)
   12388 	{
   12389 		/* Skip eliminated column */
   12390 		if (column == c)
   12391 		{
   12392 			continue;
   12393 		}
   12394 
   12395 		for (glw::GLuint r = 0; r < Size; ++r)
   12396 		{
   12397 			/* Skip eliminated row */
   12398 			if (row == r)
   12399 			{
   12400 				continue;
   12401 			}
   12402 
   12403 			const glw::GLint r_offset = (r > row) ? -1 : 0;
   12404 			const glw::GLint c_offset = (c > column) ? -1 : 0;
   12405 
   12406 			result(r + r_offset, c + c_offset) = matrix(r, c);
   12407 		}
   12408 	}
   12409 
   12410 	return result;
   12411 }
   12412 
   12413 template <int Size>
   12414 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
   12415 											const tcu::Vector<glw::GLdouble, Size>& right)
   12416 {
   12417 	return convertBvecToUvec(tcu::equal(left, right));
   12418 }
   12419 
   12420 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
   12421 {
   12422 	return a * b + c;
   12423 }
   12424 
   12425 static glw::GLdouble fract(glw::GLdouble val)
   12426 {
   12427 	return val - floor(val);
   12428 }
   12429 
   12430 template <typename T>
   12431 static T frexp(T val, glw::GLint& exp)
   12432 {
   12433 	return ::frexp(val, &exp);
   12434 }
   12435 
   12436 template <int Size>
   12437 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
   12438 												  const tcu::Vector<glw::GLdouble, Size>& right)
   12439 {
   12440 	return convertBvecToUvec(tcu::greaterThan(left, right));
   12441 }
   12442 
   12443 template <int Size>
   12444 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12445 													   const tcu::Vector<glw::GLdouble, Size>& right)
   12446 {
   12447 	return convertBvecToUvec(tcu::greaterThanEqual(left, right));
   12448 }
   12449 
   12450 template <int Size>
   12451 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
   12452 {
   12453 	const tcu::Matrix<glw::GLdouble, Size, Size> cof	  = cofactors(matrix);
   12454 	const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
   12455 	const glw::GLdouble det		= determinant(matrix);
   12456 	const glw::GLdouble inv_det = 1.0 / det;
   12457 
   12458 	tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
   12459 
   12460 	return result;
   12461 }
   12462 
   12463 static glw::GLdouble inverseSqrt(glw::GLdouble val)
   12464 {
   12465 	const glw::GLdouble root = sqrt(val);
   12466 
   12467 	return (1.0 / root);
   12468 }
   12469 
   12470 static glw::GLuint isinf_impl(glw::GLdouble val)
   12471 {
   12472 	const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
   12473 
   12474 	return ((infinity == val) || (-infinity == val));
   12475 }
   12476 
   12477 static glw::GLuint isnan_impl(glw::GLdouble val)
   12478 {
   12479 	return val != val;
   12480 }
   12481 
   12482 template <typename T>
   12483 static T ldexp(T val, glw::GLint exp)
   12484 {
   12485 	return ::ldexp(val, exp);
   12486 }
   12487 
   12488 template <int Size>
   12489 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
   12490 											   const tcu::Vector<glw::GLdouble, Size>& right)
   12491 {
   12492 	return convertBvecToUvec(tcu::lessThan(left, right));
   12493 }
   12494 
   12495 template <int Size>
   12496 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12497 													const tcu::Vector<glw::GLdouble, Size>& right)
   12498 {
   12499 	return convertBvecToUvec(tcu::lessThanEqual(left, right));
   12500 }
   12501 
   12502 template <typename T>
   12503 static T max(T left, T right)
   12504 {
   12505 	return (left >= right) ? left : right;
   12506 }
   12507 
   12508 template <typename T>
   12509 static T min(T left, T right)
   12510 {
   12511 	return (left <= right) ? left : right;
   12512 }
   12513 
   12514 template <int		 Size>
   12515 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
   12516 								glw::GLuint row)
   12517 {
   12518 	tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
   12519 
   12520 	return determinant(eliminated);
   12521 }
   12522 
   12523 template <>
   12524 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
   12525 {
   12526 	const glw::GLuint r = (0 == row) ? 1 : 0;
   12527 	const glw::GLuint c = (0 == column) ? 1 : 0;
   12528 
   12529 	return matrix(r, c);
   12530 }
   12531 
   12532 template <typename T>
   12533 static T mix(T left, T right, T weight)
   12534 {
   12535 	return left * (1 - weight) + right * (weight);
   12536 }
   12537 
   12538 template <typename T>
   12539 static T mod(T left, T right)
   12540 {
   12541 	const T div_res = left / right;
   12542 	const T floored = floor(div_res);
   12543 
   12544 	return left - right * floored;
   12545 }
   12546 
   12547 template <typename T>
   12548 static T modf(T val, T& integer)
   12549 {
   12550 	return ::modf(val, &integer);
   12551 }
   12552 
   12553 template <typename T>
   12554 static T multiply(T left, T right)
   12555 {
   12556 	T result = left * right;
   12557 
   12558 	return result;
   12559 }
   12560 
   12561 template <int Size>
   12562 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
   12563 											   const tcu::Vector<glw::GLdouble, Size>& right)
   12564 {
   12565 	return convertBvecToUvec(tcu::notEqual(left, right));
   12566 }
   12567 
   12568 template <int Cols, int Rows>
   12569 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
   12570 														   const tcu::Vector<glw::GLdouble, Cols>& right)
   12571 {
   12572 	tcu::Matrix<glw::GLdouble, Rows, 1>	left_mat;
   12573 	tcu::Matrix<glw::GLdouble, 1, Cols>	right_mat;
   12574 	tcu::Matrix<glw::GLdouble, Rows, Cols> result;
   12575 
   12576 	for (glw::GLuint i = 0; i < Rows; ++i)
   12577 	{
   12578 		left_mat(i, 0) = left[i];
   12579 	}
   12580 
   12581 	for (glw::GLuint i = 0; i < Cols; ++i)
   12582 	{
   12583 		right_mat(0, i) = right[i];
   12584 	}
   12585 
   12586 	result = left_mat * right_mat;
   12587 
   12588 	return result;
   12589 }
   12590 
   12591 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
   12592 {
   12593 	const glw::GLuint buffer[2] = { in[0], in[1] };
   12594 	glw::GLdouble	 result;
   12595 	memcpy(&result, buffer, sizeof(result));
   12596 	return result;
   12597 }
   12598 
   12599 template <typename T>
   12600 static T round(T t)
   12601 {
   12602 	T frac = fract(t);
   12603 	T res  = t - frac;
   12604 
   12605 	if (((T)0.5) < frac)
   12606 	{
   12607 		res += ((T)1.0);
   12608 	}
   12609 
   12610 	return res;
   12611 }
   12612 
   12613 template <typename T>
   12614 static T roundEven(T t)
   12615 {
   12616 	T frac = fract(t);
   12617 	T res  = t - frac;
   12618 
   12619 	if (((T)0.5) < frac)
   12620 	{
   12621 		res += ((T)1.0);
   12622 	}
   12623 	else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
   12624 	{
   12625 		res += ((T)1.0);
   12626 	}
   12627 
   12628 	return res;
   12629 }
   12630 
   12631 template <typename T>
   12632 static T sign(T t)
   12633 {
   12634 	if (0 > t)
   12635 	{
   12636 		return -1;
   12637 	}
   12638 	else if (0 == t)
   12639 	{
   12640 		return 0;
   12641 	}
   12642 	else
   12643 	{
   12644 		return 1;
   12645 	}
   12646 }
   12647 
   12648 template <typename T>
   12649 static T smoothStep(T e0, T e1, T val)
   12650 {
   12651 	if (e0 >= val)
   12652 	{
   12653 		return 0;
   12654 	}
   12655 
   12656 	if (e1 <= val)
   12657 	{
   12658 		return 1;
   12659 	}
   12660 
   12661 	T temp = (val - e0) / (e1 - e0);
   12662 
   12663 	T result = temp * temp * (3 - 2 * temp);
   12664 
   12665 	return result;
   12666 }
   12667 
   12668 template <typename T>
   12669 static T step(T edge, T val)
   12670 {
   12671 	if (edge > val)
   12672 	{
   12673 		return 0;
   12674 	}
   12675 	else
   12676 	{
   12677 		return 1;
   12678 	}
   12679 }
   12680 
   12681 template <typename T, int Rows, int Cols>
   12682 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
   12683 {
   12684 	tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
   12685 
   12686 	return result;
   12687 }
   12688 
   12689 template <typename T>
   12690 static T trunc(T t)
   12691 {
   12692 	const T abs_value	= de::abs(t);
   12693 	const T result_value = floor(abs_value);
   12694 
   12695 	const T result = sign(t) * result_value;
   12696 
   12697 	return result;
   12698 }
   12699 
   12700 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
   12701 {
   12702 	glw::GLuint* ptr = (glw::GLuint*)&val;
   12703 	tcu::UVec2   result(ptr[0], ptr[1]);
   12704 
   12705 	return result;
   12706 }
   12707 } /* Math */
   12708 
   12709 /** Enumeration of tested functions
   12710  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
   12711  * For example "max" can be called for (dvec3, double).
   12712  **/
   12713 enum FunctionEnum
   12714 {
   12715 	FUNCTION_ABS = 0,
   12716 	FUNCTION_CEIL,
   12717 	FUNCTION_CLAMP,
   12718 	FUNCTION_CLAMP_AGAINST_SCALAR,
   12719 	FUNCTION_CROSS,
   12720 	FUNCTION_DETERMINANT,
   12721 	FUNCTION_DISTANCE,
   12722 	FUNCTION_DOT,
   12723 	FUNCTION_EQUAL,
   12724 	FUNCTION_FACEFORWARD,
   12725 	FUNCTION_FLOOR,
   12726 	FUNCTION_FMA,
   12727 	FUNCTION_FRACT,
   12728 	FUNCTION_FREXP,
   12729 	FUNCTION_GREATERTHAN,
   12730 	FUNCTION_GREATERTHANEQUAL,
   12731 	FUNCTION_INVERSE,
   12732 	FUNCTION_INVERSESQRT,
   12733 	FUNCTION_LDEXP,
   12734 	FUNCTION_LESSTHAN,
   12735 	FUNCTION_LESSTHANEQUAL,
   12736 	FUNCTION_LENGTH,
   12737 	FUNCTION_MATRIXCOMPMULT,
   12738 	FUNCTION_MAX,
   12739 	FUNCTION_MAX_AGAINST_SCALAR,
   12740 	FUNCTION_MIN,
   12741 	FUNCTION_MIN_AGAINST_SCALAR,
   12742 	FUNCTION_MIX,
   12743 	FUNCTION_MOD,
   12744 	FUNCTION_MOD_AGAINST_SCALAR,
   12745 	FUNCTION_MODF,
   12746 	FUNCTION_NORMALIZE,
   12747 	FUNCTION_NOTEQUAL,
   12748 	FUNCTION_OUTERPRODUCT,
   12749 	FUNCTION_PACKDOUBLE2X32,
   12750 	FUNCTION_REFLECT,
   12751 	FUNCTION_REFRACT,
   12752 	FUNCTION_ROUND,
   12753 	FUNCTION_ROUNDEVEN,
   12754 	FUNCTION_SIGN,
   12755 	FUNCTION_SMOOTHSTEP,
   12756 	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
   12757 	FUNCTION_SQRT,
   12758 	FUNCTION_STEP,
   12759 	FUNCTION_STEP_AGAINST_SCALAR,
   12760 	FUNCTION_TRANSPOSE,
   12761 	FUNCTION_TRUNC,
   12762 	FUNCTION_UNPACKDOUBLE2X32,
   12763 	FUNCTION_ISNAN,
   12764 	FUNCTION_ISINF,
   12765 };
   12766 
   12767 struct TypeDefinition
   12768 {
   12769 	std::string name;
   12770 	glw::GLuint n_columns;
   12771 	glw::GLuint n_rows;
   12772 };
   12773 
   12774 /** Implementation of BuiltinFunctionTest test, description follows:
   12775  *
   12776  *  Verify double-precision support in common functions works correctly.
   12777  *  All double-precision types that apply for particular cases should
   12778  *  be tested for the following functions:
   12779  *
   12780  *  - abs();
   12781  *  - ceil();
   12782  *  - clamp();
   12783  *  - cross();
   12784  *  - determinant();
   12785  *  - distance();
   12786  *  - dot();
   12787  *  - equal();
   12788  *  - faceforward();
   12789  *  - floor();
   12790  *  - fma();
   12791  *  - fract();
   12792  *  - frexp();
   12793  *  - greaterThan();
   12794  *  - greaterThanEqual();
   12795  *  - inverse();
   12796  *  - inversesqrt();
   12797  *  - ldexp();
   12798  *  - lessThan();
   12799  *  - lessThanEqual();
   12800  *  - length();
   12801  *  - matrixCompMult();
   12802  *  - max();
   12803  *  - min();
   12804  *  - mix();
   12805  *  - mod();
   12806  *  - modf();
   12807  *  - normalize();
   12808  *  - notEqual();
   12809  *  - outerProduct();
   12810  *  - packDouble2x32();
   12811  *  - reflect();
   12812  *  - refract();
   12813  *  - round();
   12814  *  - roundEven();
   12815  *  - sign();
   12816  *  - smoothstep();
   12817  *  - sqrt();
   12818  *  - step();
   12819  *  - transpose();
   12820  *  - trunc();
   12821  *  - unpackDouble2x32();
   12822  *  - isnan();
   12823  *  - isinf();
   12824  *
   12825  *  The test should work by creating a program object (for each case
   12826  *  considered), to which a vertex shader should be attached. The
   12827  *  shader should define input variables that should be used as
   12828  *  arguments for the function in question. The result of the
   12829  *  operation should then be XFBed back to the test, where the
   12830  *  value should be verified.
   12831  *
   12832  *  Reference function implementation from pre-DEQP CTS framework
   12833  *  should be ported to C for verification purposes where available.
   12834  *
   12835  *  The test should use 1024 different scalar/vector/matrix argument
   12836  *  combinations. It should pass if all functions are determined
   12837  *  to work correctly for all argument combinations used.
   12838  **/
   12839 class BuiltinFunctionTest : public deqp::TestCase
   12840 {
   12841 public:
   12842 	/* Public methods */
   12843 	BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
   12844 						TypeDefinition typeDefinition);
   12845 
   12846 	virtual void						 deinit();
   12847 	virtual tcu::TestNode::IterateResult iterate();
   12848 
   12849 	/** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
   12850 	 *
   12851 	 **/
   12852 	class functionObject
   12853 	{
   12854 	public:
   12855 		functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
   12856 					   Utils::_variable_type result_type);
   12857 
   12858 		virtual ~functionObject()
   12859 		{
   12860 		}
   12861 
   12862 		virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
   12863 
   12864 		virtual glw::GLuint			  getArgumentCount() const					  = 0;
   12865 		virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
   12866 		glw::GLuint getArgumentComponents(glw::GLuint argument) const;
   12867 		glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
   12868 		glw::GLuint getArgumentOffset(glw::GLuint argument) const;
   12869 		glw::GLuint getArgumentStride() const;
   12870 		glw::GLuint getArgumentStride(glw::GLuint argument) const;
   12871 		FunctionEnum	   getFunctionEnum() const;
   12872 		const glw::GLchar* getName() const;
   12873 		glw::GLuint getResultComponents(glw::GLuint result) const;
   12874 		virtual glw::GLuint getResultCount() const;
   12875 		glw::GLuint getResultOffset(glw::GLuint result) const;
   12876 		virtual Utils::_variable_type getResultType(glw::GLuint result) const;
   12877 		glw::GLuint getResultStride(glw::GLuint result) const;
   12878 		glw::GLuint getBaseTypeSize(glw::GLuint result) const;
   12879 		glw::GLuint getResultStride() const;
   12880 
   12881 	protected:
   12882 		const FunctionEnum			m_function_enum;
   12883 		const glw::GLchar*			m_function_name;
   12884 		const glw::GLvoid*			m_p_function;
   12885 		const Utils::_variable_type m_res_type;
   12886 	};
   12887 
   12888 private:
   12889 	/* Private types */
   12890 	/** General type enumeration
   12891 	 *
   12892 	 **/
   12893 	enum generalType
   12894 	{
   12895 		SCALAR = 0,
   12896 		VECTOR,
   12897 		MATRIX,
   12898 	};
   12899 
   12900 	/** Details of variable type
   12901 	 *
   12902 	 **/
   12903 	struct typeDetails
   12904 	{
   12905 		typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
   12906 
   12907 		generalType m_general_type;
   12908 		glw::GLuint m_n_columns;
   12909 		glw::GLuint m_n_rows;
   12910 		glw::GLenum m_type;
   12911 		std::string m_type_name;
   12912 	};
   12913 
   12914 	/* Typedefs for gl.uniform* function pointers */
   12915 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
   12916 																	   const glw::GLdouble*);
   12917 	typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
   12918 	typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
   12919 	typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
   12920 
   12921 	/* Private methods */
   12922 	bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
   12923 
   12924 	functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
   12925 
   12926 	uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint		   argument,
   12927 														 const functionObject& function_object) const;
   12928 
   12929 	uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint		   argument,
   12930 														 const functionObject& function_object) const;
   12931 
   12932 	uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint		   argument,
   12933 														 const functionObject& function_object) const;
   12934 
   12935 	uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint		   argument,
   12936 														 const functionObject& function_object) const;
   12937 
   12938 	const glw::GLchar* getUniformName(glw::GLuint argument) const;
   12939 	const glw::GLchar* getVaryingName(glw::GLuint argument) const;
   12940 
   12941 	bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
   12942 
   12943 	void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
   12944 
   12945 	void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
   12946 
   12947 	void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
   12948 						   glw::GLubyte* buffer);
   12949 
   12950 	void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
   12951 
   12952 	void prepareTestData(const functionObject& function_object);
   12953 	void prepareVertexShaderCode(const functionObject& function_object);
   12954 
   12955 	bool test(FunctionEnum function, const typeDetails& type);
   12956 
   12957 	void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
   12958 
   12959 	void testInit();
   12960 
   12961 	bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
   12962 						  const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
   12963 						  const glw::GLvoid* result_src);
   12964 
   12965 	bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
   12966 
   12967 	/* Private constants */
   12968 	static const glw::GLdouble m_epsilon;
   12969 	static const glw::GLuint   m_n_veritces;
   12970 
   12971 	/* Private fields */
   12972 	glw::GLuint m_transform_feedback_buffer_id;
   12973 	glw::GLuint m_vertex_array_object_id;
   12974 
   12975 	std::vector<glw::GLubyte> m_expected_results_data;
   12976 	FunctionEnum			  m_function;
   12977 	TypeDefinition			  m_typeDefinition;
   12978 	std::vector<glw::GLubyte> m_argument_data;
   12979 	std::string				  m_vertex_shader_code;
   12980 };
   12981 
   12982 /* Constants used by BuiltinFunctionTest */
   12983 /** Khronos Bug #14010
   12984  *  Using an epsilon value for comparing floating points is error prone.
   12985  *  Rather than writing a new floating point comparison function, I am
   12986  *  increasing the epsilon value to allow greater orders of magnitude
   12987  *  of floating point values.
   12988  **/
   12989 const glw::GLdouble BuiltinFunctionTest::m_epsilon	= 0.00002;
   12990 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
   12991 
   12992 /** Implementations of function objects required by "BuiltinFunctionTest"
   12993  *
   12994  **/
   12995 namespace FunctionObject
   12996 {
   12997 /** Maps variable type with enumeration Utils::_variable_type
   12998  *
   12999  * @tparam T type
   13000  **/
   13001 template <typename T>
   13002 class typeInfo
   13003 {
   13004 public:
   13005 	static const Utils::_variable_type variable_type =
   13006 		TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
   13007 };
   13008 
   13009 /** Place data from <in> into <buffer>
   13010  *
   13011  * @param buffer Buffer
   13012  * @param in     Input data
   13013  **/
   13014 template <typename T>
   13015 class pack
   13016 {
   13017 public:
   13018 	static void set(glw::GLvoid* buffer, const T& in)
   13019 	{
   13020 		*(T*)buffer = in;
   13021 	}
   13022 };
   13023 
   13024 /** Place tcu::Matrix data from <in> into <buffer>
   13025  *
   13026  * @param buffer Buffer
   13027  * @param in     Input data
   13028  **/
   13029 template <int Cols, int Rows>
   13030 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
   13031 {
   13032 public:
   13033 	static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
   13034 	{
   13035 		glw::GLdouble* data = (glw::GLdouble*)buffer;
   13036 
   13037 		for (glw::GLint column = 0; column < Cols; ++column)
   13038 		{
   13039 			for (glw::GLint row = 0; row < Rows; ++row)
   13040 			{
   13041 				glw::GLint index = column * Rows + row;
   13042 
   13043 				data[index] = in(row, column);
   13044 			}
   13045 		}
   13046 	}
   13047 };
   13048 
   13049 /** Get data of <out> from <buffer>
   13050  *
   13051  * @param buffer Buffer
   13052  * @param out    Output data
   13053  **/
   13054 template <typename T>
   13055 class unpack
   13056 {
   13057 public:
   13058 	static void get(const glw::GLvoid* buffer, T& out)
   13059 	{
   13060 		out = *(T*)buffer;
   13061 	}
   13062 };
   13063 
   13064 /** Get tcu::Matrix data from <buffer>
   13065  *
   13066  * @param buffer Buffer
   13067  * @param out    Output data
   13068  **/
   13069 template <int Cols, int Rows>
   13070 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
   13071 {
   13072 public:
   13073 	static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
   13074 	{
   13075 		const glw::GLdouble* data = (glw::GLdouble*)buffer;
   13076 
   13077 		for (glw::GLint column = 0; column < Cols; ++column)
   13078 		{
   13079 			for (glw::GLint row = 0; row < Rows; ++row)
   13080 			{
   13081 				glw::GLint index = column * Rows + row;
   13082 
   13083 				out(row, column) = data[index];
   13084 			}
   13085 		}
   13086 	}
   13087 };
   13088 
   13089 /** Base of unary function classes
   13090  *
   13091  **/
   13092 class unaryBase : public BuiltinFunctionTest::functionObject
   13093 {
   13094 public:
   13095 	unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
   13096 			  const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
   13097 		: functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
   13098 	{
   13099 	}
   13100 
   13101 	virtual glw::GLuint getArgumentCount() const
   13102 	{
   13103 		return 1;
   13104 	}
   13105 
   13106 	virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
   13107 	{
   13108 		return m_arg_type;
   13109 	}
   13110 
   13111 protected:
   13112 	const Utils::_variable_type m_arg_type;
   13113 };
   13114 
   13115 /** Unary function class. It treats input argument as one variable.
   13116  *
   13117  * @tparam ResT Type of result
   13118  * @tparam ArgT Type of argument
   13119  **/
   13120 template <typename ResT, typename ArgT>
   13121 class unary : public unaryBase
   13122 {
   13123 public:
   13124 	typedef ResT (*functionPointer)(const ArgT&);
   13125 
   13126 	unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
   13127 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
   13128 					typeInfo<ArgT>::variable_type)
   13129 	{
   13130 	}
   13131 
   13132 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13133 	{
   13134 		ResT result;
   13135 		ArgT arg;
   13136 
   13137 		unpack<ArgT>::get(argument_src, arg);
   13138 
   13139 		functionPointer p_function = (functionPointer)m_p_function;
   13140 
   13141 		result = p_function(arg);
   13142 
   13143 		pack<ResT>::set(result_dst, result);
   13144 	}
   13145 };
   13146 
   13147 /** Unary function class. It treats input argument as separate components.
   13148  *
   13149  * @tparam ResT Type of result
   13150  **/
   13151 template <typename ResT>
   13152 class unaryByComponent : public unaryBase
   13153 {
   13154 public:
   13155 	typedef ResT (*functionPointer)(glw::GLdouble);
   13156 
   13157 	unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
   13158 					 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
   13159 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
   13160 	{
   13161 	}
   13162 
   13163 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13164 	{
   13165 		glw::GLuint	n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
   13166 		ResT*		   p_result		= (ResT*)result_dst;
   13167 		glw::GLdouble* p_arg		= (glw::GLdouble*)argument_src;
   13168 
   13169 		functionPointer p_function = (functionPointer)m_p_function;
   13170 
   13171 		for (glw::GLuint component = 0; component < n_components; ++component)
   13172 		{
   13173 			p_result[component] = p_function(p_arg[component]);
   13174 		}
   13175 	}
   13176 };
   13177 
   13178 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
   13179  *
   13180  * @tparam ResT Type of result
   13181  * @tparam ArgT Type of argument
   13182  * @tparam OutT Type of output parameter
   13183  **/
   13184 template <typename ResT, typename ArgT, typename OutT>
   13185 class unaryWithOutputByComponent : public unaryBase
   13186 {
   13187 public:
   13188 	typedef ResT (*functionPointer)(ArgT, OutT&);
   13189 
   13190 	unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
   13191 							   functionPointer function_pointer, const Utils::_variable_type res_type,
   13192 							   const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
   13193 		: unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
   13194 		, m_out_type(out_type)
   13195 	{
   13196 	}
   13197 
   13198 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13199 	{
   13200 		ResT* p_result = (ResT*)result_dst;
   13201 		OutT* p_out	= (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
   13202 		ArgT* p_arg	= (ArgT*)argument_src;
   13203 
   13204 		const glw::GLuint n_components_0 = getArgumentComponents(0);
   13205 		const glw::GLuint n_components_1 = getResultComponents(1);
   13206 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
   13207 
   13208 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
   13209 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
   13210 
   13211 		functionPointer p_function = (functionPointer)m_p_function;
   13212 
   13213 		for (glw::GLuint component = 0; component < n_components; ++component)
   13214 		{
   13215 			const ArgT first_arg  = p_arg[component * component_step_0];
   13216 			OutT&	  second_arg = p_out[component * component_step_1];
   13217 
   13218 			p_result[component] = p_function(first_arg, second_arg);
   13219 		}
   13220 	}
   13221 
   13222 	glw::GLuint getResultCount() const
   13223 	{
   13224 		return 2;
   13225 	}
   13226 
   13227 	Utils::_variable_type getResultType(glw::GLuint result) const
   13228 	{
   13229 		Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
   13230 
   13231 		switch (result)
   13232 		{
   13233 		case 0:
   13234 			type = m_res_type;
   13235 			break;
   13236 		case 1:
   13237 			type = m_out_type;
   13238 			break;
   13239 		default:
   13240 			TCU_FAIL("Not implemented");
   13241 			break;
   13242 		}
   13243 
   13244 		return type;
   13245 	}
   13246 
   13247 protected:
   13248 	const Utils::_variable_type m_out_type;
   13249 };
   13250 
   13251 /** Base of binary function classes.
   13252  *
   13253  **/
   13254 class binaryBase : public BuiltinFunctionTest::functionObject
   13255 {
   13256 public:
   13257 	binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
   13258 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
   13259 			   const Utils::_variable_type arg_2_type)
   13260 		: functionObject(function_enum, function_name, function_pointer, res_type)
   13261 		, m_arg_1_type(arg_1_type)
   13262 		, m_arg_2_type(arg_2_type)
   13263 	{
   13264 	}
   13265 
   13266 	virtual glw::GLuint getArgumentCount() const
   13267 	{
   13268 		return 2;
   13269 	}
   13270 
   13271 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
   13272 	{
   13273 		switch (argument)
   13274 		{
   13275 		case 0:
   13276 			return m_arg_1_type;
   13277 			break;
   13278 		case 1:
   13279 			return m_arg_2_type;
   13280 			break;
   13281 		default:
   13282 			return Utils::VARIABLE_TYPE_UNKNOWN;
   13283 			break;
   13284 		}
   13285 	}
   13286 
   13287 protected:
   13288 	const Utils::_variable_type m_arg_1_type;
   13289 	const Utils::_variable_type m_arg_2_type;
   13290 };
   13291 
   13292 /** Binary function class. It treats input arguments as two variables.
   13293  *
   13294  * @param ResT  Type of result
   13295  * @param Arg1T Type of first argument
   13296  * @param Arg2T Type of second argument
   13297  **/
   13298 template <typename ResT, typename Arg1T, typename Arg2T>
   13299 class binary : public binaryBase
   13300 {
   13301 public:
   13302 	typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
   13303 
   13304 	binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
   13305 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
   13306 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
   13307 	{
   13308 	}
   13309 
   13310 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13311 	{
   13312 		const glw::GLuint argument_1_stride = getArgumentStride(0);
   13313 
   13314 		functionPointer p_function = (functionPointer)m_p_function;
   13315 
   13316 		Arg1T arg_1;
   13317 		Arg2T arg_2;
   13318 		ResT  result;
   13319 
   13320 		unpack<Arg1T>::get(argument_src, arg_1);
   13321 		unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
   13322 
   13323 		result = p_function(arg_1, arg_2);
   13324 
   13325 		pack<ResT>::set(result_dst, result);
   13326 	}
   13327 };
   13328 
   13329 /** Binary function class. It treats input arguments as separate components.
   13330  *
   13331  * @param ResT  Type of result
   13332  * @param Arg1T Type of first argument
   13333  * @param Arg2T Type of second argument
   13334  **/
   13335 template <typename ResT, typename Arg1T, typename Arg2T>
   13336 class binaryByComponent : public binaryBase
   13337 {
   13338 public:
   13339 	typedef ResT (*functionPointer)(Arg1T, Arg2T);
   13340 
   13341 	binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
   13342 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
   13343 					  const Utils::_variable_type arg_2_type)
   13344 		: binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
   13345 	{
   13346 	}
   13347 
   13348 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13349 	{
   13350 		ResT*  p_result = (ResT*)result_dst;
   13351 		Arg1T* p_arg_1  = (Arg1T*)argument_src;
   13352 		Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
   13353 
   13354 		const glw::GLuint n_components_0 = getArgumentComponents(0);
   13355 		const glw::GLuint n_components_1 = getArgumentComponents(1);
   13356 		const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
   13357 
   13358 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
   13359 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
   13360 
   13361 		functionPointer p_function = (functionPointer)m_p_function;
   13362 
   13363 		for (glw::GLuint component = 0; component < n_components; ++component)
   13364 		{
   13365 			const Arg1T first_arg  = p_arg_1[component * component_step_0];
   13366 			const Arg2T second_arg = p_arg_2[component * component_step_1];
   13367 
   13368 			p_result[component] = p_function(first_arg, second_arg);
   13369 		}
   13370 	}
   13371 };
   13372 
   13373 /** Base of tenary function classes.
   13374  *
   13375  **/
   13376 class tenaryBase : public BuiltinFunctionTest::functionObject
   13377 {
   13378 public:
   13379 	tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
   13380 			   const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
   13381 			   const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
   13382 		: functionObject(function_enum, function_name, function_pointer, res_type)
   13383 		, m_arg_1_type(arg_1_type)
   13384 		, m_arg_2_type(arg_2_type)
   13385 		, m_arg_3_type(arg_3_type)
   13386 	{
   13387 	}
   13388 
   13389 	virtual glw::GLuint getArgumentCount() const
   13390 	{
   13391 		return 3;
   13392 	}
   13393 
   13394 	virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
   13395 	{
   13396 		switch (argument)
   13397 		{
   13398 		case 0:
   13399 			return m_arg_1_type;
   13400 			break;
   13401 		case 1:
   13402 			return m_arg_2_type;
   13403 			break;
   13404 		case 2:
   13405 			return m_arg_3_type;
   13406 			break;
   13407 		default:
   13408 			return Utils::VARIABLE_TYPE_UNKNOWN;
   13409 			break;
   13410 		}
   13411 	}
   13412 
   13413 protected:
   13414 	const Utils::_variable_type m_arg_1_type;
   13415 	const Utils::_variable_type m_arg_2_type;
   13416 	const Utils::_variable_type m_arg_3_type;
   13417 };
   13418 
   13419 /** Tenary function class. It treats input arguments as three variables.
   13420  *
   13421  * @param ResT  Type of result
   13422  * @param Arg1T Type of first argument
   13423  * @param Arg2T Type of second argument
   13424  * @param Arg3T Type of third argument
   13425  **/
   13426 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
   13427 class tenary : public tenaryBase
   13428 {
   13429 public:
   13430 	typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
   13431 	typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
   13432 	typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
   13433 	typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
   13434 
   13435 	tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
   13436 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
   13437 					 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
   13438 	{
   13439 	}
   13440 
   13441 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13442 	{
   13443 		const glw::GLuint argument_2_offset = getArgumentOffset(1);
   13444 		const glw::GLuint argument_3_offset = getArgumentOffset(2);
   13445 
   13446 		functionPointer p_function = (functionPointer)m_p_function;
   13447 
   13448 		arg1T arg_1;
   13449 		arg2T arg_2;
   13450 		arg3T arg_3;
   13451 		ResT  result;
   13452 
   13453 		unpack<arg1T>::get(argument_src, arg_1);
   13454 		unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
   13455 		unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
   13456 
   13457 		result = p_function(arg_1, arg_2, arg_3);
   13458 
   13459 		pack<ResT>::set(result_dst, result);
   13460 	}
   13461 };
   13462 
   13463 /** Tenary function class. It treats input arguments as separate components.
   13464  *
   13465 
   13466  **/
   13467 class tenaryByComponent : public tenaryBase
   13468 {
   13469 public:
   13470 	typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
   13471 
   13472 	tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
   13473 					  const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
   13474 					  const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
   13475 		: tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
   13476 					 arg_3_type)
   13477 	{
   13478 	}
   13479 
   13480 	virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
   13481 	{
   13482 		glw::GLdouble*		 p_result = (glw::GLdouble*)result_dst;
   13483 		const glw::GLdouble* p_arg	= (const glw::GLdouble*)argument_src;
   13484 
   13485 		const glw::GLuint n_components_0 = getArgumentComponents(0);
   13486 		const glw::GLuint n_components_1 = getArgumentComponents(1);
   13487 		const glw::GLuint n_components_2 = getArgumentComponents(2);
   13488 		const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
   13489 
   13490 		const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
   13491 		const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
   13492 		const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
   13493 
   13494 		functionPointer p_function = (functionPointer)m_p_function;
   13495 
   13496 		for (glw::GLuint component = 0; component < n_components; ++component)
   13497 		{
   13498 			const glw::GLdouble first_arg  = p_arg[component * component_step_0];
   13499 			const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
   13500 			const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
   13501 
   13502 			p_result[component] = p_function(first_arg, second_arg, third_arg);
   13503 		}
   13504 	}
   13505 };
   13506 } /* FunctionObject */
   13507 
   13508 /** Constructor.
   13509  *
   13510  *  @param context Rendering context.
   13511  **/
   13512 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
   13513 										 TypeDefinition typeDefinition)
   13514 	: TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
   13515 	, m_transform_feedback_buffer_id(0)
   13516 	, m_vertex_array_object_id(0)
   13517 	, m_function(function)
   13518 	, m_typeDefinition(typeDefinition)
   13519 {
   13520 	/* Nothing to be done here */
   13521 }
   13522 
   13523 /** Deinitializes all GL objects that may have been created during test execution.
   13524  *
   13525  **/
   13526 void BuiltinFunctionTest::deinit()
   13527 {
   13528 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   13529 
   13530 	/* Clean buffers */
   13531 	if (0 != m_transform_feedback_buffer_id)
   13532 	{
   13533 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
   13534 		gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
   13535 		m_transform_feedback_buffer_id = 0;
   13536 	}
   13537 
   13538 	/* Clean VAO */
   13539 	if (0 != m_vertex_array_object_id)
   13540 	{
   13541 		gl.bindVertexArray(0);
   13542 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
   13543 		m_vertex_array_object_id = 0;
   13544 	}
   13545 }
   13546 
   13547 /** Execute test
   13548  *
   13549  * @return tcu::TestNode::STOP
   13550  **/
   13551 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
   13552 {
   13553 	/* Check if extension is supported */
   13554 	if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
   13555 	{
   13556 		throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
   13557 	}
   13558 
   13559 	testInit();
   13560 
   13561 	/* Verify result */
   13562 	typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
   13563 	if (test(m_function, type))
   13564 	{
   13565 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
   13566 	}
   13567 	else
   13568 	{
   13569 		m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   13570 	}
   13571 
   13572 	/* Done */
   13573 	return tcu::TestNode::STOP;
   13574 }
   13575 
   13576 /** Constructor
   13577  *
   13578  * @param function_enum    Function enumeration
   13579  * @param function_name    Function name
   13580  * @param function_pointer Pointer to routine that wiil be executed
   13581  * @param result_type      Type of result
   13582  **/
   13583 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
   13584 													glw::GLvoid* function_pointer, Utils::_variable_type result_type)
   13585 	: m_function_enum(function_enum)
   13586 	, m_function_name(function_name)
   13587 	, m_p_function(function_pointer)
   13588 	, m_res_type(result_type)
   13589 {
   13590 	/* Nothing to be done here */
   13591 }
   13592 
   13593 /** Get number of components for <argument>
   13594  *
   13595  * @param argument Argument ordinal, starts with 0
   13596  *
   13597  * @return Number of components
   13598  **/
   13599 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
   13600 {
   13601 	const Utils::_variable_type type		  = getArgumentType(argument);
   13602 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
   13603 
   13604 	return n_components;
   13605 }
   13606 
   13607 /** Get size in bytes of single component of <argument>
   13608  *
   13609  * @param argument Argument ordinal, starts with 0
   13610  *
   13611  * @return Size of component
   13612  **/
   13613 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
   13614 {
   13615 	const Utils::_variable_type type		   = getArgumentType(argument);
   13616 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
   13617 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
   13618 
   13619 	return base_type_size;
   13620 }
   13621 
   13622 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
   13623  *
   13624  * @param argument Argument ordinal, starts with 0
   13625  *
   13626  * @return Offset of arguemnt's data
   13627  **/
   13628 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
   13629 {
   13630 	glw::GLuint result = 0;
   13631 
   13632 	for (glw::GLuint i = 0; i < argument; ++i)
   13633 	{
   13634 		result += getArgumentStride(i);
   13635 	}
   13636 
   13637 	return result;
   13638 }
   13639 
   13640 /** Get stride in bytes of all arguments
   13641  *
   13642  * @return Stride of all arguments
   13643  **/
   13644 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
   13645 {
   13646 	const glw::GLuint n_args = getArgumentCount();
   13647 	glw::GLuint		  result = 0;
   13648 
   13649 	for (glw::GLuint i = 0; i < n_args; ++i)
   13650 	{
   13651 		result += getArgumentStride(i);
   13652 	}
   13653 
   13654 	return result;
   13655 }
   13656 
   13657 /** Get stride in bytes of <argument>
   13658  *
   13659  * @param argument Argument ordinal, starts with 0
   13660  *
   13661  * @return Stride of argument
   13662  **/
   13663 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
   13664 {
   13665 	const glw::GLuint component_size = getArgumentComponentSize(argument);
   13666 	const glw::GLuint n_components   = getArgumentComponents(argument);
   13667 
   13668 	return n_components * component_size;
   13669 }
   13670 
   13671 /** Get function enumeration
   13672  *
   13673  * @return Function enumeration
   13674  **/
   13675 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
   13676 {
   13677 	return m_function_enum;
   13678 }
   13679 
   13680 /** Get function name
   13681  *
   13682  * @return Function name
   13683  **/
   13684 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
   13685 {
   13686 	return m_function_name;
   13687 }
   13688 
   13689 /** Get number of components for <result>
   13690  *
   13691  * @param result Result ordinal, starts with 0
   13692  *
   13693  * @return Number of components
   13694  **/
   13695 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
   13696 {
   13697 	const Utils::_variable_type type		  = getResultType(result);
   13698 	const glw::GLuint			n_components  = Utils::getNumberOfComponentsForVariableType(type);
   13699 
   13700 	return n_components;
   13701 }
   13702 
   13703 /** Get number of results
   13704  *
   13705  * @return Number of results
   13706  **/
   13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
   13708 {
   13709 	return 1;
   13710 }
   13711 
   13712 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
   13713  *
   13714  * @param result Result ordinal, starts with 0
   13715  *
   13716  * @return Offset
   13717  **/
   13718 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
   13719 {
   13720 	glw::GLuint offset = 0;
   13721 
   13722 	for (glw::GLuint i = 0; i < result; ++i)
   13723 	{
   13724 		offset += getResultStride(i);
   13725 		offset = deAlign32(offset, getBaseTypeSize(i));
   13726 	}
   13727 
   13728 	return offset;
   13729 }
   13730 
   13731 /** Get stride in bytes of <result>.
   13732  *
   13733  * @param result Result ordinal, starts with 0
   13734  *
   13735  * @return Stride
   13736  **/
   13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
   13738 {
   13739 	const Utils::_variable_type type		   = getResultType(result);
   13740 	const glw::GLuint			n_components   = Utils::getNumberOfComponentsForVariableType(type);
   13741 
   13742 	return n_components * getBaseTypeSize(result);
   13743 }
   13744 
   13745 /** Get size in bytes of <result> base component.
   13746  *
   13747  * @param result Result ordinal, starts with 0
   13748  *
   13749  * @return Alignment
   13750  **/
   13751 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
   13752 {
   13753 	const Utils::_variable_type type		   = getResultType(result);
   13754 	const Utils::_variable_type base_type	  = Utils::getBaseVariableType(type);
   13755 	const glw::GLuint			base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
   13756 
   13757 	return base_type_size;
   13758 }
   13759 
   13760 /** Get stride in bytes of all results.
   13761  *
   13762  * @return Stride
   13763  **/
   13764 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
   13765 {
   13766 	const glw::GLuint n_results	= getResultCount();
   13767 	glw::GLuint		  stride	   = 0;
   13768 	glw::GLuint		  maxAlignment = 0;
   13769 
   13770 	for (glw::GLuint i = 0; i < n_results; ++i)
   13771 	{
   13772 		const glw::GLuint alignment = getBaseTypeSize(i);
   13773 		stride += getResultStride(i);
   13774 		stride		 = deAlign32(stride, alignment);
   13775 		maxAlignment = deMaxu32(maxAlignment, alignment);
   13776 	}
   13777 
   13778 	// The stride of all results must also be aligned,
   13779 	// so results for next vertex are aligned.
   13780 	return deAlign32(stride, maxAlignment);
   13781 }
   13782 
   13783 /** Get type of <result>.
   13784  *
   13785  * @param result Result ordinal, starts with 0
   13786  *
   13787  * @return Type
   13788  **/
   13789 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
   13790 {
   13791 	return m_res_type;
   13792 }
   13793 
   13794 /** Constructor
   13795  *
   13796  * @param n_columns Number of columns
   13797  * @param n_rows    Number of rows
   13798  **/
   13799 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
   13800 	: m_n_columns(n_columns), m_n_rows(n_rows)
   13801 {
   13802 	Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
   13803 	m_type					   = Utils::getGLDataTypeOfVariableType(type);
   13804 	m_type_name				   = Utils::getVariableTypeString(type);
   13805 
   13806 	if (1 == m_n_columns)
   13807 	{
   13808 		if (1 == m_n_rows)
   13809 		{
   13810 			m_general_type = SCALAR;
   13811 		}
   13812 		else
   13813 		{
   13814 			m_general_type = VECTOR;
   13815 		}
   13816 	}
   13817 	else
   13818 	{
   13819 		m_general_type = MATRIX;
   13820 	}
   13821 }
   13822 
   13823 /** Compare two values
   13824  *
   13825  * @param type  Type of values
   13826  * @param left  Pointer to left value
   13827  * @param right Pointer to right value
   13828  *
   13829  * @return true if values are equal, false otherwise
   13830  **/
   13831 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
   13832 {
   13833 	bool result = true;
   13834 
   13835 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
   13836 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
   13837 
   13838 	switch (base_type)
   13839 	{
   13840 	case Utils::VARIABLE_TYPE_DOUBLE:
   13841 
   13842 	{
   13843 		const glw::GLdouble* left_values  = (glw::GLdouble*)left;
   13844 		const glw::GLdouble* right_values = (glw::GLdouble*)right;
   13845 
   13846 		for (glw::GLuint component = 0; component < n_components; ++component)
   13847 		{
   13848 			const glw::GLdouble left_value  = left_values[component];
   13849 			const glw::GLdouble right_value = right_values[component];
   13850 
   13851 			if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
   13852 				(0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
   13853 			{
   13854 				result = false;
   13855 				break;
   13856 			}
   13857 		}
   13858 	}
   13859 
   13860 	break;
   13861 
   13862 	case Utils::VARIABLE_TYPE_INT:
   13863 
   13864 	{
   13865 		const glw::GLint* left_values  = (glw::GLint*)left;
   13866 		const glw::GLint* right_values = (glw::GLint*)right;
   13867 
   13868 		for (glw::GLuint component = 0; component < n_components; ++component)
   13869 		{
   13870 			const glw::GLint left_value  = left_values[component];
   13871 			const glw::GLint right_value = right_values[component];
   13872 
   13873 			if (left_value != right_value)
   13874 			{
   13875 				result = false;
   13876 				break;
   13877 			}
   13878 		}
   13879 	}
   13880 
   13881 	break;
   13882 
   13883 	case Utils::VARIABLE_TYPE_UINT:
   13884 
   13885 	{
   13886 		const glw::GLuint* left_values  = (glw::GLuint*)left;
   13887 		const glw::GLuint* right_values = (glw::GLuint*)right;
   13888 
   13889 		for (glw::GLuint component = 0; component < n_components; ++component)
   13890 		{
   13891 			const glw::GLuint left_value  = left_values[component];
   13892 			const glw::GLuint right_value = right_values[component];
   13893 
   13894 			if (left_value != right_value)
   13895 			{
   13896 				result = false;
   13897 				break;
   13898 			}
   13899 		}
   13900 	}
   13901 
   13902 	break;
   13903 
   13904 	default:
   13905 
   13906 		TCU_FAIL("Not implemented");
   13907 
   13908 		break;
   13909 	}
   13910 
   13911 	return result;
   13912 }
   13913 
   13914 /** Create instance of function object for given function enumeration and type
   13915  *
   13916  * @param function Function enumeration
   13917  * @param type     Type details
   13918  *
   13919  * @return Create object
   13920  **/
   13921 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum	   function,
   13922 																			const typeDetails& type)
   13923 {
   13924 	typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
   13925 	typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
   13926 	typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
   13927 	typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
   13928 	typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
   13929 	typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
   13930 	typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
   13931 	typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
   13932 	typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
   13933 
   13934 	const glw::GLuint			n_columns	 = type.m_n_columns;
   13935 	const glw::GLuint			n_rows		  = type.m_n_rows;
   13936 	const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
   13937 	const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
   13938 	const Utils::_variable_type uint_type	 = Utils::getUintVariableType(1, n_rows);
   13939 	const Utils::_variable_type int_type	  = Utils::getIntVariableType(1, n_rows);
   13940 
   13941 	switch (function)
   13942 	{
   13943 	case FUNCTION_ABS:
   13944 
   13945 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   13946 			function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
   13947 
   13948 		break;
   13949 
   13950 	case FUNCTION_CEIL:
   13951 
   13952 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   13953 			function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
   13954 
   13955 		break;
   13956 
   13957 	case FUNCTION_CLAMP:
   13958 
   13959 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
   13960 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
   13961 													 variable_type /* arg3_type */);
   13962 		break;
   13963 
   13964 	case FUNCTION_CLAMP_AGAINST_SCALAR:
   13965 
   13966 		return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
   13967 													 variable_type /* arg1_type */, scalar_type /* arg2_type */,
   13968 													 scalar_type /* arg3_type */);
   13969 		break;
   13970 
   13971 	case FUNCTION_CROSS:
   13972 
   13973 		return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   13974 			function, "cross", tcu::cross);
   13975 
   13976 		break;
   13977 
   13978 	case FUNCTION_DETERMINANT:
   13979 
   13980 		switch (variable_type)
   13981 		{
   13982 		case Utils::VARIABLE_TYPE_DMAT2:
   13983 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
   13984 																						 Math::determinant);
   13985 		case Utils::VARIABLE_TYPE_DMAT3:
   13986 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
   13987 																						 Math::determinant);
   13988 		case Utils::VARIABLE_TYPE_DMAT4:
   13989 			return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
   13990 																						 Math::determinant);
   13991 		default:
   13992 			TCU_FAIL("Not implemented");
   13993 			break;
   13994 		}
   13995 
   13996 		break;
   13997 
   13998 	case FUNCTION_DISTANCE:
   13999 
   14000 		switch (variable_type)
   14001 		{
   14002 		case Utils::VARIABLE_TYPE_DVEC2:
   14003 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14004 				function, "distance", tcu::distance);
   14005 			break;
   14006 		case Utils::VARIABLE_TYPE_DVEC3:
   14007 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14008 				function, "distance", tcu::distance);
   14009 			break;
   14010 		case Utils::VARIABLE_TYPE_DVEC4:
   14011 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14012 				function, "distance", tcu::distance);
   14013 			break;
   14014 		default:
   14015 			break;
   14016 		}
   14017 
   14018 		break;
   14019 
   14020 	case FUNCTION_DOT:
   14021 
   14022 		switch (variable_type)
   14023 		{
   14024 		case Utils::VARIABLE_TYPE_DVEC2:
   14025 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14026 				function, "dot", tcu::dot);
   14027 			break;
   14028 		case Utils::VARIABLE_TYPE_DVEC3:
   14029 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14030 				function, "dot", tcu::dot);
   14031 			break;
   14032 		case Utils::VARIABLE_TYPE_DVEC4:
   14033 			return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14034 				function, "dot", tcu::dot);
   14035 			break;
   14036 		default:
   14037 			break;
   14038 		}
   14039 
   14040 		break;
   14041 
   14042 	case FUNCTION_EQUAL:
   14043 
   14044 		switch (variable_type)
   14045 		{
   14046 		case Utils::VARIABLE_TYPE_DVEC2:
   14047 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14048 				function, "equal", Math::equal);
   14049 			break;
   14050 		case Utils::VARIABLE_TYPE_DVEC3:
   14051 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14052 				function, "equal", Math::equal);
   14053 			break;
   14054 		case Utils::VARIABLE_TYPE_DVEC4:
   14055 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14056 				function, "equal", Math::equal);
   14057 			break;
   14058 		default:
   14059 			break;
   14060 		}
   14061 
   14062 		break;
   14063 
   14064 	case FUNCTION_FACEFORWARD:
   14065 
   14066 		switch (variable_type)
   14067 		{
   14068 		case Utils::VARIABLE_TYPE_DVEC2:
   14069 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
   14070 											  const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
   14071 				function, "faceforward", tcu::faceForward);
   14072 			break;
   14073 		case Utils::VARIABLE_TYPE_DVEC3:
   14074 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
   14075 											  const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
   14076 				function, "faceforward", tcu::faceForward);
   14077 			break;
   14078 		case Utils::VARIABLE_TYPE_DVEC4:
   14079 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
   14080 											  const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
   14081 				function, "faceforward", tcu::faceForward);
   14082 			break;
   14083 		default:
   14084 			break;
   14085 		}
   14086 
   14087 		break;
   14088 
   14089 	case FUNCTION_FLOOR:
   14090 
   14091 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14092 			function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
   14093 
   14094 		break;
   14095 
   14096 	case FUNCTION_FMA:
   14097 
   14098 		return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
   14099 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
   14100 													 variable_type /* arg3_type */);
   14101 
   14102 		break;
   14103 
   14104 	case FUNCTION_FRACT:
   14105 
   14106 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14107 			function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
   14108 
   14109 		break;
   14110 
   14111 	case FUNCTION_FREXP:
   14112 
   14113 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
   14114 															  glw::GLint /* OutT */>(
   14115 			function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
   14116 			int_type /* out_type */);
   14117 
   14118 		break;
   14119 
   14120 	case FUNCTION_GREATERTHAN:
   14121 
   14122 		switch (variable_type)
   14123 		{
   14124 		case Utils::VARIABLE_TYPE_DVEC2:
   14125 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14126 				function, "greaterThan", Math::greaterThan);
   14127 			break;
   14128 		case Utils::VARIABLE_TYPE_DVEC3:
   14129 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14130 				function, "greaterThan", Math::greaterThan);
   14131 			break;
   14132 		case Utils::VARIABLE_TYPE_DVEC4:
   14133 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14134 				function, "greaterThan", Math::greaterThan);
   14135 			break;
   14136 		default:
   14137 			break;
   14138 		}
   14139 
   14140 		break;
   14141 
   14142 	case FUNCTION_GREATERTHANEQUAL:
   14143 
   14144 		switch (variable_type)
   14145 		{
   14146 		case Utils::VARIABLE_TYPE_DVEC2:
   14147 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14148 				function, "greaterThanEqual", Math::greaterThanEqual);
   14149 			break;
   14150 		case Utils::VARIABLE_TYPE_DVEC3:
   14151 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14152 				function, "greaterThanEqual", Math::greaterThanEqual);
   14153 			break;
   14154 		case Utils::VARIABLE_TYPE_DVEC4:
   14155 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14156 				function, "greaterThanEqual", Math::greaterThanEqual);
   14157 			break;
   14158 		default:
   14159 			break;
   14160 		}
   14161 
   14162 		break;
   14163 
   14164 	case FUNCTION_INVERSE:
   14165 
   14166 		switch (variable_type)
   14167 		{
   14168 		case Utils::VARIABLE_TYPE_DMAT2:
   14169 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
   14170 			break;
   14171 		case Utils::VARIABLE_TYPE_DMAT3:
   14172 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
   14173 			break;
   14174 		case Utils::VARIABLE_TYPE_DMAT4:
   14175 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
   14176 			break;
   14177 		default:
   14178 			break;
   14179 		}
   14180 
   14181 		break;
   14182 
   14183 	case FUNCTION_INVERSESQRT:
   14184 
   14185 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14186 			function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
   14187 
   14188 		break;
   14189 
   14190 	case FUNCTION_LDEXP:
   14191 
   14192 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14193 													 glw::GLint /* Arg2T */>(
   14194 			function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
   14195 			int_type /* arg2_type */);
   14196 
   14197 		break;
   14198 
   14199 	case FUNCTION_LESSTHAN:
   14200 
   14201 		switch (variable_type)
   14202 		{
   14203 		case Utils::VARIABLE_TYPE_DVEC2:
   14204 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14205 				function, "lessThan", Math::lessThan);
   14206 			break;
   14207 		case Utils::VARIABLE_TYPE_DVEC3:
   14208 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14209 				function, "lessThan", Math::lessThan);
   14210 			break;
   14211 		case Utils::VARIABLE_TYPE_DVEC4:
   14212 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14213 				function, "lessThan", Math::lessThan);
   14214 			break;
   14215 		default:
   14216 			break;
   14217 		}
   14218 
   14219 		break;
   14220 
   14221 	case FUNCTION_LESSTHANEQUAL:
   14222 
   14223 		switch (variable_type)
   14224 		{
   14225 		case Utils::VARIABLE_TYPE_DVEC2:
   14226 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14227 				function, "lessThanEqual", Math::lessThanEqual);
   14228 			break;
   14229 		case Utils::VARIABLE_TYPE_DVEC3:
   14230 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14231 				function, "lessThanEqual", Math::lessThanEqual);
   14232 			break;
   14233 		case Utils::VARIABLE_TYPE_DVEC4:
   14234 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14235 				function, "lessThanEqual", Math::lessThanEqual);
   14236 			break;
   14237 		default:
   14238 			break;
   14239 		}
   14240 
   14241 		break;
   14242 
   14243 	case FUNCTION_LENGTH:
   14244 
   14245 		switch (variable_type)
   14246 		{
   14247 		case Utils::VARIABLE_TYPE_DVEC2:
   14248 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
   14249 																							  tcu::length);
   14250 			break;
   14251 		case Utils::VARIABLE_TYPE_DVEC3:
   14252 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
   14253 																							  tcu::length);
   14254 			break;
   14255 		case Utils::VARIABLE_TYPE_DVEC4:
   14256 			return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
   14257 																							  tcu::length);
   14258 			break;
   14259 		default:
   14260 			break;
   14261 		}
   14262 
   14263 		break;
   14264 
   14265 	case FUNCTION_MATRIXCOMPMULT:
   14266 
   14267 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14268 													 glw::GLdouble /* Arg2T */>(
   14269 			function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
   14270 			variable_type /* arg2_type */);
   14271 
   14272 		break;
   14273 
   14274 	case FUNCTION_MAX:
   14275 
   14276 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14277 													 glw::GLdouble /* Arg2T */>(
   14278 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
   14279 			variable_type /* arg2_type */);
   14280 
   14281 		break;
   14282 
   14283 	case FUNCTION_MAX_AGAINST_SCALAR:
   14284 
   14285 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14286 													 glw::GLdouble /* Arg2T */>(
   14287 			function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
   14288 			scalar_type /* arg2_type */);
   14289 
   14290 		break;
   14291 
   14292 	case FUNCTION_MIN:
   14293 
   14294 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14295 													 glw::GLdouble /* Arg2T */>(
   14296 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
   14297 			variable_type /* arg2_type */);
   14298 
   14299 		break;
   14300 
   14301 	case FUNCTION_MIN_AGAINST_SCALAR:
   14302 
   14303 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14304 													 glw::GLdouble /* Arg2T */>(
   14305 			function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
   14306 			scalar_type /* arg2_type */);
   14307 
   14308 		break;
   14309 
   14310 	case FUNCTION_MIX:
   14311 
   14312 		return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
   14313 													 variable_type /* arg1_type */, variable_type /* arg2_type */,
   14314 													 variable_type /* arg3_type */);
   14315 
   14316 		break;
   14317 
   14318 	case FUNCTION_MOD:
   14319 
   14320 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14321 													 glw::GLdouble /* Arg2T */>(
   14322 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
   14323 			variable_type /* arg2_type */);
   14324 
   14325 		break;
   14326 
   14327 	case FUNCTION_MOD_AGAINST_SCALAR:
   14328 
   14329 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14330 													 glw::GLdouble /* Arg2T */>(
   14331 			function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
   14332 			scalar_type /* arg2_type */);
   14333 
   14334 		break;
   14335 
   14336 	case FUNCTION_MODF:
   14337 
   14338 		return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
   14339 															  glw::GLdouble /* OutT */>(
   14340 			function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
   14341 			variable_type /* out_type */);
   14342 
   14343 		break;
   14344 
   14345 	case FUNCTION_NORMALIZE:
   14346 
   14347 		switch (variable_type)
   14348 		{
   14349 		case Utils::VARIABLE_TYPE_DVEC2:
   14350 			return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
   14351 																						   tcu::normalize);
   14352 			break;
   14353 		case Utils::VARIABLE_TYPE_DVEC3:
   14354 			return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
   14355 																						   tcu::normalize);
   14356 			break;
   14357 		case Utils::VARIABLE_TYPE_DVEC4:
   14358 			return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
   14359 																						   tcu::normalize);
   14360 			break;
   14361 		default:
   14362 			break;
   14363 		}
   14364 
   14365 		break;
   14366 
   14367 	case FUNCTION_NOTEQUAL:
   14368 
   14369 		switch (variable_type)
   14370 		{
   14371 		case Utils::VARIABLE_TYPE_DVEC2:
   14372 			return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14373 				function, "notEqual", Math::notEqual);
   14374 			break;
   14375 		case Utils::VARIABLE_TYPE_DVEC3:
   14376 			return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14377 				function, "notEqual", Math::notEqual);
   14378 			break;
   14379 		case Utils::VARIABLE_TYPE_DVEC4:
   14380 			return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14381 				function, "notEqual", Math::notEqual);
   14382 			break;
   14383 		default:
   14384 			break;
   14385 		}
   14386 
   14387 		break;
   14388 
   14389 	case FUNCTION_OUTERPRODUCT:
   14390 
   14391 		switch (variable_type)
   14392 		{
   14393 		case Utils::VARIABLE_TYPE_DMAT2:
   14394 			return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14395 				function, "outerProduct", Math::outerProduct);
   14396 			break;
   14397 		case Utils::VARIABLE_TYPE_DMAT2X3:
   14398 			return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14399 				function, "outerProduct", Math::outerProduct);
   14400 			break;
   14401 		case Utils::VARIABLE_TYPE_DMAT2X4:
   14402 			return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14403 				function, "outerProduct", Math::outerProduct);
   14404 			break;
   14405 		case Utils::VARIABLE_TYPE_DMAT3:
   14406 			return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14407 				function, "outerProduct", Math::outerProduct);
   14408 			break;
   14409 		case Utils::VARIABLE_TYPE_DMAT3X2:
   14410 			return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14411 				function, "outerProduct", Math::outerProduct);
   14412 			break;
   14413 		case Utils::VARIABLE_TYPE_DMAT3X4:
   14414 			return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14415 				function, "outerProduct", Math::outerProduct);
   14416 			break;
   14417 		case Utils::VARIABLE_TYPE_DMAT4:
   14418 			return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14419 				function, "outerProduct", Math::outerProduct);
   14420 			break;
   14421 		case Utils::VARIABLE_TYPE_DMAT4X2:
   14422 			return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14423 				function, "outerProduct", Math::outerProduct);
   14424 			break;
   14425 		case Utils::VARIABLE_TYPE_DMAT4X3:
   14426 			return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14427 				function, "outerProduct", Math::outerProduct);
   14428 			break;
   14429 		default:
   14430 			break;
   14431 		}
   14432 
   14433 		break;
   14434 
   14435 	case FUNCTION_PACKDOUBLE2X32:
   14436 
   14437 		return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
   14438 																						  Math::packDouble2x32);
   14439 
   14440 		break;
   14441 
   14442 	case FUNCTION_REFLECT:
   14443 
   14444 		switch (variable_type)
   14445 		{
   14446 		case Utils::VARIABLE_TYPE_DVEC2:
   14447 			return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
   14448 				function, "reflect", tcu::reflect);
   14449 			break;
   14450 		case Utils::VARIABLE_TYPE_DVEC3:
   14451 			return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
   14452 				function, "reflect", tcu::reflect);
   14453 			break;
   14454 		case Utils::VARIABLE_TYPE_DVEC4:
   14455 			return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
   14456 				function, "reflect", tcu::reflect);
   14457 			break;
   14458 		default:
   14459 			break;
   14460 		}
   14461 
   14462 		break;
   14463 
   14464 	case FUNCTION_REFRACT:
   14465 
   14466 		switch (variable_type)
   14467 		{
   14468 		case Utils::VARIABLE_TYPE_DVEC2:
   14469 			return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
   14470 											  const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
   14471 				function, "refract", tcu::refract);
   14472 			break;
   14473 		case Utils::VARIABLE_TYPE_DVEC3:
   14474 			return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
   14475 											  const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
   14476 				function, "refract", tcu::refract);
   14477 			break;
   14478 		case Utils::VARIABLE_TYPE_DVEC4:
   14479 			return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
   14480 											  const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
   14481 				function, "refract", tcu::refract);
   14482 			break;
   14483 		default:
   14484 			break;
   14485 		}
   14486 
   14487 		break;
   14488 
   14489 	case FUNCTION_ROUND:
   14490 
   14491 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14492 			function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
   14493 
   14494 		break;
   14495 
   14496 	case FUNCTION_ROUNDEVEN:
   14497 
   14498 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14499 			function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
   14500 
   14501 		break;
   14502 
   14503 	case FUNCTION_SIGN:
   14504 
   14505 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14506 			function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
   14507 
   14508 		break;
   14509 
   14510 	case FUNCTION_SMOOTHSTEP:
   14511 
   14512 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
   14513 													 variable_type /* res_type  */, variable_type /* arg1_type */,
   14514 													 variable_type /* arg2_type */, variable_type /* arg3_type */);
   14515 
   14516 		break;
   14517 
   14518 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
   14519 
   14520 		return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
   14521 													 variable_type /* res_type  */, scalar_type /* arg1_type */,
   14522 													 scalar_type /* arg2_type */, variable_type /* arg3_type */);
   14523 
   14524 		break;
   14525 
   14526 	case FUNCTION_SQRT:
   14527 
   14528 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14529 			function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
   14530 
   14531 		break;
   14532 
   14533 	case FUNCTION_STEP:
   14534 
   14535 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14536 													 glw::GLdouble /* Arg2T */>(
   14537 			function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
   14538 			variable_type /* arg2_type */);
   14539 
   14540 		break;
   14541 
   14542 	case FUNCTION_STEP_AGAINST_SCALAR:
   14543 
   14544 		return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
   14545 													 glw::GLdouble /* Arg2T */>(
   14546 			function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
   14547 			variable_type /* arg2_type */);
   14548 
   14549 		break;
   14550 
   14551 	case FUNCTION_TRANSPOSE:
   14552 
   14553 		switch (variable_type)
   14554 		{
   14555 		case Utils::VARIABLE_TYPE_DMAT2:
   14556 			return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
   14557 																				 Math::transpose);
   14558 			break;
   14559 		case Utils::VARIABLE_TYPE_DMAT2X3:
   14560 			return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
   14561 																					 Math::transpose);
   14562 			break;
   14563 		case Utils::VARIABLE_TYPE_DMAT2X4:
   14564 			return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
   14565 																					 Math::transpose);
   14566 			break;
   14567 		case Utils::VARIABLE_TYPE_DMAT3:
   14568 			return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
   14569 																				 Math::transpose);
   14570 			break;
   14571 		case Utils::VARIABLE_TYPE_DMAT3X2:
   14572 			return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
   14573 																					 Math::transpose);
   14574 			break;
   14575 		case Utils::VARIABLE_TYPE_DMAT3X4:
   14576 			return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
   14577 																					 Math::transpose);
   14578 			break;
   14579 		case Utils::VARIABLE_TYPE_DMAT4:
   14580 			return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
   14581 																				 Math::transpose);
   14582 			break;
   14583 		case Utils::VARIABLE_TYPE_DMAT4X2:
   14584 			return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
   14585 																					 Math::transpose);
   14586 			break;
   14587 		case Utils::VARIABLE_TYPE_DMAT4X3:
   14588 			return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
   14589 																					 Math::transpose);
   14590 			break;
   14591 		default:
   14592 			break;
   14593 		}
   14594 
   14595 		break;
   14596 
   14597 	case FUNCTION_TRUNC:
   14598 
   14599 		return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
   14600 			function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
   14601 
   14602 		break;
   14603 
   14604 	case FUNCTION_UNPACKDOUBLE2X32:
   14605 
   14606 		return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
   14607 																						  Math::unpackDouble2x32);
   14608 
   14609 		break;
   14610 
   14611 	case FUNCTION_ISNAN:
   14612 
   14613 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
   14614 			function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
   14615 
   14616 		break;
   14617 
   14618 	case FUNCTION_ISINF:
   14619 
   14620 		return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
   14621 			function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
   14622 
   14623 		break;
   14624 
   14625 	default:
   14626 		TCU_FAIL("Not implemented");
   14627 		return 0;
   14628 		break;
   14629 	}
   14630 
   14631 	TCU_FAIL("Not implemented");
   14632 	return 0;
   14633 }
   14634 
   14635 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
   14636  *
   14637  * @param argument        Argument index
   14638  * @param function_object Function object
   14639  *
   14640  * @return Function pointer
   14641  **/
   14642 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
   14643 	glw::GLuint argument, const functionObject& function_object) const
   14644 {
   14645 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
   14646 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
   14647 
   14648 	switch (argument_type)
   14649 	{
   14650 	case Utils::VARIABLE_TYPE_DMAT2:
   14651 		return gl.uniformMatrix2dv;
   14652 		break;
   14653 	case Utils::VARIABLE_TYPE_DMAT2X3:
   14654 		return gl.uniformMatrix2x3dv;
   14655 		break;
   14656 	case Utils::VARIABLE_TYPE_DMAT2X4:
   14657 		return gl.uniformMatrix2x4dv;
   14658 		break;
   14659 	case Utils::VARIABLE_TYPE_DMAT3:
   14660 		return gl.uniformMatrix3dv;
   14661 		break;
   14662 	case Utils::VARIABLE_TYPE_DMAT3X2:
   14663 		return gl.uniformMatrix3x2dv;
   14664 		break;
   14665 	case Utils::VARIABLE_TYPE_DMAT3X4:
   14666 		return gl.uniformMatrix3x4dv;
   14667 		break;
   14668 	case Utils::VARIABLE_TYPE_DMAT4:
   14669 		return gl.uniformMatrix4dv;
   14670 		break;
   14671 	case Utils::VARIABLE_TYPE_DMAT4X2:
   14672 		return gl.uniformMatrix4x2dv;
   14673 		break;
   14674 	case Utils::VARIABLE_TYPE_DMAT4X3:
   14675 		return gl.uniformMatrix4x3dv;
   14676 		break;
   14677 	default:
   14678 		break;
   14679 	}
   14680 
   14681 	TCU_FAIL("Not implemented");
   14682 	return 0;
   14683 }
   14684 
   14685 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
   14686  *
   14687  * @param argument        Argument index
   14688  * @param function_object Function object
   14689  *
   14690  * @return Function pointer
   14691  **/
   14692 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
   14693 	glw::GLuint argument, const functionObject& function_object) const
   14694 {
   14695 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
   14696 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
   14697 
   14698 	switch (argument_type)
   14699 	{
   14700 	case Utils::VARIABLE_TYPE_DOUBLE:
   14701 		return gl.uniform1dv;
   14702 		break;
   14703 	case Utils::VARIABLE_TYPE_DVEC2:
   14704 		return gl.uniform2dv;
   14705 		break;
   14706 	case Utils::VARIABLE_TYPE_DVEC3:
   14707 		return gl.uniform3dv;
   14708 		break;
   14709 	case Utils::VARIABLE_TYPE_DVEC4:
   14710 		return gl.uniform4dv;
   14711 		break;
   14712 	default:
   14713 		TCU_FAIL("Not implemented");
   14714 		break;
   14715 	}
   14716 
   14717 	return 0;
   14718 }
   14719 
   14720 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
   14721  *
   14722  * @param argument        Argument index
   14723  * @param function_object Function object
   14724  *
   14725  * @return Function pointer
   14726  **/
   14727 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
   14728 	glw::GLuint argument, const functionObject& function_object) const
   14729 {
   14730 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
   14731 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
   14732 
   14733 	switch (argument_type)
   14734 	{
   14735 	case Utils::VARIABLE_TYPE_INT:
   14736 		return gl.uniform1iv;
   14737 		break;
   14738 	case Utils::VARIABLE_TYPE_IVEC2:
   14739 		return gl.uniform2iv;
   14740 		break;
   14741 	case Utils::VARIABLE_TYPE_IVEC3:
   14742 		return gl.uniform3iv;
   14743 		break;
   14744 	case Utils::VARIABLE_TYPE_IVEC4:
   14745 		return gl.uniform4iv;
   14746 		break;
   14747 	default:
   14748 		TCU_FAIL("Not implemented");
   14749 		break;
   14750 	}
   14751 
   14752 	return 0;
   14753 }
   14754 
   14755 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
   14756  *
   14757  * @param argument        Argument index
   14758  * @param function_object Function object
   14759  *
   14760  * @return Function pointer
   14761  **/
   14762 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
   14763 	glw::GLuint argument, const functionObject& function_object) const
   14764 {
   14765 	const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
   14766 	const glw::Functions&		gl			  = m_context.getRenderContext().getFunctions();
   14767 
   14768 	switch (argument_type)
   14769 	{
   14770 	case Utils::VARIABLE_TYPE_UVEC2:
   14771 		return gl.uniform2uiv;
   14772 		break;
   14773 	default:
   14774 		TCU_FAIL("Not implemented");
   14775 		break;
   14776 	}
   14777 
   14778 	return 0;
   14779 }
   14780 
   14781 /** Get name of uniform that will be used as <argument>.
   14782  *
   14783  * @param argument Argument index
   14784  *
   14785  * @return Name of uniform
   14786  **/
   14787 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
   14788 {
   14789 	switch (argument)
   14790 	{
   14791 	case 0:
   14792 		return "uniform_0";
   14793 		break;
   14794 	case 1:
   14795 		return "uniform_1";
   14796 		break;
   14797 	case 2:
   14798 		return "uniform_2";
   14799 		break;
   14800 	default:
   14801 		TCU_FAIL("Not implemented");
   14802 		return 0;
   14803 		break;
   14804 	}
   14805 }
   14806 
   14807 /** Get name of varying that will be used as <result>.
   14808  *
   14809  * @param result Result index
   14810  *
   14811  * @return Name of varying
   14812  **/
   14813 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
   14814 {
   14815 	switch (result)
   14816 	{
   14817 	case 0:
   14818 		return "result_0";
   14819 		break;
   14820 	case 1:
   14821 		return "result_1";
   14822 		break;
   14823 	case 2:
   14824 		return "result_2";
   14825 		break;
   14826 	default:
   14827 		TCU_FAIL("Not implemented");
   14828 		return 0;
   14829 		break;
   14830 	}
   14831 }
   14832 
   14833 /** Check if given combination of function and type is implemented
   14834  *
   14835  * @param function Function enumeration
   14836  * @param type     Type details
   14837  *
   14838  * @return true if function is available for given type, false otherwise
   14839  **/
   14840 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
   14841 {
   14842 	static const bool look_up_table[][3] = {
   14843 		/* SCALAR, VECTOR, MATRIX */
   14844 		/* FUNCTION_ABS:                       */ { true, true, false },
   14845 		/* FUNCTION_CEIL:                      */ { true, true, false },
   14846 		/* FUNCTION_CLAMP:                     */ { true, true, false },
   14847 		/* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
   14848 		/* FUNCTION_CROSS:                     */ { false, true, false },
   14849 		/* FUNCTION_DETERMINANT:               */ { false, false, true },
   14850 		/* FUNCTION_DISTANCE:                  */ { false, true, false },
   14851 		/* FUNCTION_DOT:                       */ { false, true, false },
   14852 		/* FUNCTION_EQUAL:                     */ { false, true, false },
   14853 		/* FUNCTION_FACEFORWARD:               */ { false, true, false },
   14854 		/* FUNCTION_FLOOR:                     */ { true, true, false },
   14855 		/* FUNCTION_FMA:                       */ { true, true, false },
   14856 		/* FUNCTION_FRACT:                     */ { true, true, false },
   14857 		/* FUNCTION_FREXP:                     */ { true, true, false },
   14858 		/* FUNCTION_GREATERTHAN:               */ { false, true, false },
   14859 		/* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
   14860 		/* FUNCTION_INVERSE:                   */ { false, false, true },
   14861 		/* FUNCTION_INVERSESQRT:               */ { true, true, false },
   14862 		/* FUNCTION_LDEXP:                     */ { true, true, false },
   14863 		/* FUNCTION_LESSTHAN:                  */ { false, true, false },
   14864 		/* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
   14865 		/* FUNCTION_LENGTH:                    */ { false, true, false },
   14866 		/* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
   14867 		/* FUNCTION_MAX:                       */ { true, true, false },
   14868 		/* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
   14869 		/* FUNCTION_MIN:                       */ { true, true, false },
   14870 		/* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
   14871 		/* FUNCTION_MIX:                       */ { true, true, false },
   14872 		/* FUNCTION_MOD:                       */ { true, true, false },
   14873 		/* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
   14874 		/* FUNCTION_MODF:                      */ { true, true, false },
   14875 		/* FUNCTION_NORMALIZE:                 */ { false, true, false },
   14876 		/* FUNCTION_NOTEQUAL:                  */ { false, true, false },
   14877 		/* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
   14878 		/* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
   14879 		/* FUNCTION_REFLECT:                   */ { false, true, false },
   14880 		/* FUNCTION_REFRACT:                   */ { false, true, false },
   14881 		/* FUNCTION_ROUND:                     */ { true, true, false },
   14882 		/* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
   14883 		/* FUNCTION_SIGN:                      */ { true, false, false },
   14884 		/* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
   14885 		/* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
   14886 		/* FUNCTION_SQRT:                      */ { true, true, false },
   14887 		/* FUNCTION_STEP:                      */ { true, true, false },
   14888 		/* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
   14889 		/* FUNCTION_TRANSPOSE:                 */ { false, false, false },
   14890 		/* FUNCTION_TRUNC:                     */ { true, true, false },
   14891 		/* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
   14892 		/* FUNCTION_ISNAN:                     */ { true, true, false },
   14893 		/* FUNCTION_ISINF:                     */ { true, true, false },
   14894 	};
   14895 
   14896 	bool result = look_up_table[function][type.m_general_type];
   14897 
   14898 	if (true == result)
   14899 	{
   14900 		switch (function)
   14901 		{
   14902 		case FUNCTION_CROSS: /* Only 3 element vectors */
   14903 			result = (3 == type.m_n_rows);
   14904 			break;
   14905 		case FUNCTION_DETERMINANT: /* Only square matrices */
   14906 		case FUNCTION_INVERSE:
   14907 			result = (type.m_n_columns == type.m_n_rows);
   14908 			break;
   14909 		default:
   14910 			break;
   14911 		}
   14912 	}
   14913 
   14914 	return result;
   14915 }
   14916 
   14917 /** Logs variable of given type: name (type) [values]
   14918  *
   14919  * @param buffer Source of data
   14920  * @param name   Name of variable
   14921  * @param type   Type of variable
   14922  **/
   14923 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
   14924 										  Utils::_variable_type type) const
   14925 {
   14926 	const Utils::_variable_type base_type	= Utils::getBaseVariableType(type);
   14927 	const glw::GLuint			n_components = Utils::getNumberOfComponentsForVariableType(type);
   14928 	tcu::MessageBuilder			message		 = m_context.getTestContext().getLog() << tcu::TestLog::Message;
   14929 
   14930 	message << name << " (" << Utils::getVariableTypeString(type) << ") [";
   14931 
   14932 	for (glw::GLuint component = 0; component < n_components; ++component)
   14933 	{
   14934 		if (0 != component)
   14935 		{
   14936 			message << ", ";
   14937 		}
   14938 
   14939 		switch (base_type)
   14940 		{
   14941 		case Utils::VARIABLE_TYPE_DOUBLE:
   14942 			message << ((glw::GLdouble*)buffer)[component];
   14943 			break;
   14944 		case Utils::VARIABLE_TYPE_INT:
   14945 			message << ((glw::GLint*)buffer)[component];
   14946 			break;
   14947 		case Utils::VARIABLE_TYPE_UINT:
   14948 			message << ((glw::GLuint*)buffer)[component];
   14949 			break;
   14950 		default:
   14951 			TCU_FAIL("Not implemented");
   14952 		}
   14953 	}
   14954 
   14955 	message << "]" << tcu::TestLog::EndMessage;
   14956 }
   14957 
   14958 /** Prepare input arguments, data are stored in <buffer>
   14959  *
   14960  * @param function_object Function object
   14961  * @param vertex          Vertex index
   14962  * @param buffer          Buffer pointer
   14963  **/
   14964 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
   14965 										  glw::GLubyte* buffer)
   14966 {
   14967 	const glw::GLuint n_arguments = function_object.getArgumentCount();
   14968 
   14969 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
   14970 	{
   14971 		const glw::GLuint offset = function_object.getArgumentOffset(argument);
   14972 
   14973 		prepareComponents(function_object, vertex, argument, buffer + offset);
   14974 	}
   14975 }
   14976 
   14977 /** Prepare components for given <function_object>, <vertex> and <argument>
   14978  *
   14979  * @param function_object Function object
   14980  * @param vertex          Vertex index
   14981  * @param argument        Argument index
   14982  * @param buffer          Buffer pointer
   14983  **/
   14984 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
   14985 											glw::GLuint argument, glw::GLubyte* buffer)
   14986 {
   14987 	glw::GLuint					argument_index[3]		 = { 0 };
   14988 	glw::GLuint					argument_reset[3]		 = { 0 };
   14989 	glw::GLuint					argument_step[3]		 = { 0 };
   14990 	glw::GLdouble				double_argument_start[3] = { 0.0 };
   14991 	const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
   14992 	glw::GLuint					int_argument_start  = -4;
   14993 	const glw::GLuint			n_arguments			= function_object.getArgumentCount();
   14994 	const glw::GLuint			n_components		= function_object.getArgumentComponents(argument);
   14995 	glw::GLuint					uint_argument_start = 0;
   14996 
   14997 	switch (n_arguments)
   14998 	{
   14999 	case 1:
   15000 		argument_step[0]		 = 1;
   15001 		argument_reset[0]		 = 1024;
   15002 		double_argument_start[0] = -511.5;
   15003 		break;
   15004 	case 2:
   15005 		argument_step[0]		 = 32;
   15006 		argument_step[1]		 = 1;
   15007 		argument_reset[0]		 = 32;
   15008 		argument_reset[1]		 = 32;
   15009 		double_argument_start[0] = -15.5;
   15010 		double_argument_start[1] = -15.5;
   15011 		break;
   15012 	case 3:
   15013 		argument_step[0]		 = 64;
   15014 		argument_step[1]		 = 8;
   15015 		argument_step[2]		 = 1;
   15016 		argument_reset[0]		 = 16;
   15017 		argument_reset[1]		 = 8;
   15018 		argument_reset[2]		 = 8;
   15019 		double_argument_start[0] = -7.5;
   15020 		double_argument_start[1] = -3.5;
   15021 		double_argument_start[2] = -3.5;
   15022 		break;
   15023 	default:
   15024 		TCU_FAIL("Not implemented");
   15025 		return;
   15026 		break;
   15027 	};
   15028 
   15029 	switch (function_object.getFunctionEnum())
   15030 	{
   15031 	case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
   15032 	case FUNCTION_CLAMP_AGAINST_SCALAR:
   15033 		double_argument_start[2] = 4.5;
   15034 		break;
   15035 	case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
   15036 		double_argument_start[0] = 16.5;
   15037 		break;
   15038 	case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
   15039 	case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
   15040 		argument_step[0]		 = 1;
   15041 		argument_step[1]		 = 8;
   15042 		argument_step[2]		 = 64;
   15043 		argument_reset[0]		 = 8;
   15044 		argument_reset[1]		 = 8;
   15045 		argument_reset[2]		 = 16;
   15046 		double_argument_start[0] = -3.5;
   15047 		double_argument_start[1] = 4.5;
   15048 		double_argument_start[2] = -7.5;
   15049 		break;
   15050 	default:
   15051 		break;
   15052 	}
   15053 
   15054 	for (glw::GLuint i = 0; i < n_arguments; ++i)
   15055 	{
   15056 		argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
   15057 	}
   15058 
   15059 	switch (base_arg_type)
   15060 	{
   15061 	case Utils::VARIABLE_TYPE_DOUBLE:
   15062 	{
   15063 		glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
   15064 
   15065 		double_argument_start[argument] += argument_index[argument];
   15066 
   15067 		for (glw::GLuint component = 0; component < n_components; ++component)
   15068 		{
   15069 			glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
   15070 
   15071 			switch (function_object.getFunctionEnum())
   15072 			{
   15073 			case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
   15074 				if (0.5 == Math::fract(value))
   15075 				{
   15076 					value += 0.01;
   15077 				}
   15078 				break;
   15079 			default:
   15080 				break;
   15081 			}
   15082 
   15083 			argument_dst[component] = value;
   15084 		}
   15085 	}
   15086 	break;
   15087 	case Utils::VARIABLE_TYPE_INT:
   15088 	{
   15089 		glw::GLint* argument_dst = (glw::GLint*)buffer;
   15090 
   15091 		uint_argument_start += argument_index[argument];
   15092 
   15093 		for (glw::GLuint component = 0; component < n_components; ++component)
   15094 		{
   15095 			const glw::GLint value = int_argument_start + component;
   15096 
   15097 			argument_dst[component] = value;
   15098 		}
   15099 	}
   15100 	break;
   15101 	case Utils::VARIABLE_TYPE_UINT:
   15102 	{
   15103 		glw::GLuint* argument_dst = (glw::GLuint*)buffer;
   15104 
   15105 		uint_argument_start += argument_index[argument];
   15106 
   15107 		for (glw::GLuint component = 0; component < n_components; ++component)
   15108 		{
   15109 			const glw::GLuint value = uint_argument_start + component;
   15110 
   15111 			argument_dst[component] = value;
   15112 		}
   15113 	}
   15114 	break;
   15115 	default:
   15116 		TCU_FAIL("Not implemented");
   15117 		return;
   15118 		break;
   15119 	}
   15120 }
   15121 
   15122 /** Prepare programInfo for given functionObject
   15123  *
   15124  * @param function_object  Function object
   15125  * @param out_program_info Program info
   15126  **/
   15127 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
   15128 {
   15129 	const glw::GLuint		  n_varying_names  = function_object.getResultCount();
   15130 	static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
   15131 
   15132 	prepareVertexShaderCode(function_object);
   15133 
   15134 	out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
   15135 						   varying_names, n_varying_names);
   15136 }
   15137 
   15138 /** Prepare input data and expected results for given function object
   15139  *
   15140  * @param function_object Function object
   15141  **/
   15142 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
   15143 {
   15144 	const glw::GLuint result_stride		   = function_object.getResultStride();
   15145 	const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
   15146 	const glw::GLuint argument_stride	  = function_object.getArgumentStride();
   15147 	const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
   15148 
   15149 	m_argument_data.clear();
   15150 	m_expected_results_data.clear();
   15151 
   15152 	m_argument_data.resize(argument_buffer_size);
   15153 	m_expected_results_data.resize(result_buffer_size);
   15154 
   15155 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
   15156 	{
   15157 		const glw::GLuint result_offset   = vertex * result_stride;
   15158 		glw::GLdouble*	result_dst	  = (glw::GLdouble*)&m_expected_results_data[result_offset];
   15159 		const glw::GLuint argument_offset = vertex * argument_stride;
   15160 		glw::GLubyte*	 argument_dst	= &m_argument_data[argument_offset];
   15161 
   15162 		prepareArgument(function_object, vertex, argument_dst);
   15163 		function_object.call(result_dst, argument_dst);
   15164 	}
   15165 }
   15166 
   15167 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
   15168  *
   15169  * @param function_object Function object
   15170  **/
   15171 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
   15172 {
   15173 	static const glw::GLchar* shader_template_code = "#version 400 core\n"
   15174 													 "\n"
   15175 													 "precision highp float;\n"
   15176 													 "\n"
   15177 													 "ARGUMENT_DEFINITION"
   15178 													 "\n"
   15179 													 "RESULT_DEFINITION"
   15180 													 "\n"
   15181 													 "void main()\n"
   15182 													 "{\n"
   15183 													 "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
   15184 													 "}\n"
   15185 													 "\n";
   15186 
   15187 	static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
   15188 	static const glw::GLchar* argument_token			= "ARGUMENT";
   15189 	static const glw::GLchar* function_name_token		= "FUNCTION_NAME";
   15190 	static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
   15191 	static const glw::GLchar* result_name_token			= "RESULT_NAME";
   15192 	static const glw::GLchar* result_type_token			= "RESULT_TYPE";
   15193 	static const glw::GLchar* uniform_name_token		= "UNIFORM_NAME";
   15194 	static const glw::GLchar* uniform_type_token		= "UNIFORM_TYPE";
   15195 
   15196 	static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
   15197 	static const glw::GLchar* argument_str		  = ", UNIFORM_NAMEARGUMENT";
   15198 	static const glw::GLchar* first_argument	  = "UNIFORM_NAMEARGUMENT";
   15199 	static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
   15200 
   15201 	const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
   15202 	const glw::GLuint first_argument_length		 = (glw::GLuint)strlen(first_argument);
   15203 	const glw::GLuint n_arguments				 = function_object.getArgumentCount();
   15204 	const glw::GLuint n_results					 = function_object.getResultCount();
   15205 	const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
   15206 	std::string		  result_type				 = Utils::getVariableTypeString(function_object.getResultType(0));
   15207 
   15208 	size_t		search_position = 0;
   15209 	std::string string			= shader_template_code;
   15210 
   15211 	/* Replace ARGUMENT_DEFINITION with definitions */
   15212 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
   15213 	{
   15214 		Utils::_variable_type argument_type = function_object.getArgumentType(argument);
   15215 		const glw::GLchar*	uniform_name  = getUniformName(argument);
   15216 		std::string			  uniform_type  = Utils::getVariableTypeString(argument_type);
   15217 
   15218 		Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
   15219 
   15220 		search_position -= argument_definition_length;
   15221 
   15222 		Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
   15223 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
   15224 	}
   15225 
   15226 	/* Remove ARGUMENT_DEFINITION */
   15227 	Utils::replaceToken(argument_definition_token, search_position, "", string);
   15228 
   15229 	/* Replace RESULT_DEFINITION with definitions */
   15230 	for (glw::GLuint result = 0; result < n_results; ++result)
   15231 	{
   15232 		Utils::_variable_type variable_type = function_object.getResultType(result);
   15233 		const glw::GLchar*	varying_name  = getVaryingName(result);
   15234 		std::string			  varying_type  = Utils::getVariableTypeString(variable_type);
   15235 
   15236 		Utils::replaceToken(result_definition_token, search_position, result_definition, string);
   15237 
   15238 		search_position -= result_definition_length;
   15239 
   15240 		Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
   15241 		Utils::replaceToken(result_name_token, search_position, varying_name, string);
   15242 	}
   15243 
   15244 	/* Remove RESULT_DEFINITION */
   15245 	Utils::replaceToken(result_definition_token, search_position, "", string);
   15246 
   15247 	/* Replace RESULT_NAME */
   15248 	Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
   15249 
   15250 	/* Replace RESULT_TYPE */
   15251 	Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
   15252 
   15253 	/* Replace FUNCTION_NAME */
   15254 	Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
   15255 
   15256 	/* Replace ARGUMENT with list of arguments */
   15257 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
   15258 	{
   15259 		const glw::GLchar* uniform_name = getUniformName(argument);
   15260 
   15261 		if (0 == argument)
   15262 		{
   15263 			Utils::replaceToken(argument_token, search_position, first_argument, string);
   15264 		}
   15265 		else
   15266 		{
   15267 			Utils::replaceToken(argument_token, search_position, argument_str, string);
   15268 		}
   15269 
   15270 		search_position -= first_argument_length;
   15271 
   15272 		Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
   15273 	}
   15274 
   15275 	for (glw::GLuint result = 1; result < n_results; ++result)
   15276 	{
   15277 		const glw::GLchar* varying_name = getVaryingName(result);
   15278 
   15279 		Utils::replaceToken(argument_token, search_position, argument_str, string);
   15280 
   15281 		search_position -= first_argument_length;
   15282 
   15283 		Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
   15284 	}
   15285 
   15286 	/* Remove ARGUMENT */
   15287 	Utils::replaceToken(argument_token, search_position, "", string);
   15288 
   15289 	m_vertex_shader_code = string;
   15290 }
   15291 
   15292 /** Test single function with one type
   15293  *
   15294  * param function Function enumeration
   15295  * param type     Type details
   15296  *
   15297  * @return true if test pass (or function is not available for <type>), false otherwise
   15298  **/
   15299 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
   15300 {
   15301 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   15302 
   15303 	/* Skip if function is not implemented for type */
   15304 	if (false == isFunctionImplemented(function, type))
   15305 	{
   15306 		return true;
   15307 	}
   15308 
   15309 	Utils::programInfo			  program(m_context);
   15310 	de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
   15311 
   15312 	prepareProgram(*function_object, program);
   15313 	prepareTestData(*function_object);
   15314 
   15315 	/* Set up program */
   15316 	gl.useProgram(program.m_program_object_id);
   15317 	GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
   15318 
   15319 	for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
   15320 	{
   15321 		testBegin(*function_object, program.m_program_object_id, vertex);
   15322 
   15323 		gl.beginTransformFeedback(GL_POINTS);
   15324 		GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
   15325 
   15326 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
   15327 		GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
   15328 
   15329 		gl.endTransformFeedback();
   15330 		GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
   15331 
   15332 		if (false == verifyResults(*function_object, vertex))
   15333 		{
   15334 			return false;
   15335 		}
   15336 	}
   15337 
   15338 	return true;
   15339 }
   15340 
   15341 /** Update transform feedback buffer and uniforms
   15342  *
   15343  * @param function_object Function object
   15344  * @param program_id      Program object id
   15345  * @param vertex          Vertex index
   15346  **/
   15347 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
   15348 {
   15349 	const glw::GLuint	 arguments_stride   = function_object.getArgumentStride();
   15350 	const glw::Functions& gl				 = m_context.getRenderContext().getFunctions();
   15351 	const glw::GLuint	 n_arguments		 = function_object.getArgumentCount();
   15352 	const glw::GLuint	 result_buffer_size = function_object.getResultStride();
   15353 	const glw::GLuint	 vertex_offset		 = arguments_stride * vertex;
   15354 
   15355 	/* Update transform feedback buffer */
   15356 	std::vector<glw::GLubyte> transform_feedback_buffer_data;
   15357 	transform_feedback_buffer_data.resize(result_buffer_size);
   15358 
   15359 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
   15360 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   15361 
   15362 	gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
   15363 				  GL_DYNAMIC_COPY);
   15364 	GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
   15365 
   15366 	gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
   15367 					   result_buffer_size);
   15368 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
   15369 
   15370 	/* Update VAO */
   15371 	gl.bindVertexArray(m_vertex_array_object_id);
   15372 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
   15373 
   15374 	for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
   15375 	{
   15376 		const glw::GLuint			argument_offset  = function_object.getArgumentOffset(argument);
   15377 		const Utils::_variable_type argument_type	= function_object.getArgumentType(argument);
   15378 		const glw::GLuint			n_columns		 = Utils::getNumberOfColumnsForVariableType(argument_type);
   15379 		const glw::GLchar*			uniform_name	 = getUniformName(argument);
   15380 		const glw::GLint			uniform_location = gl.getUniformLocation(program_id, uniform_name);
   15381 		const glw::GLdouble*		uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
   15382 
   15383 		GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
   15384 
   15385 		if (-1 == uniform_location)
   15386 		{
   15387 			TCU_FAIL("Inactive uniform");
   15388 		}
   15389 
   15390 		if (1 == n_columns)
   15391 		{
   15392 			switch (Utils::getBaseVariableType(argument_type))
   15393 			{
   15394 			case Utils::VARIABLE_TYPE_DOUBLE:
   15395 			{
   15396 				uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
   15397 
   15398 				p_uniform_function(uniform_location, 1 /* count */, uniform_src);
   15399 			}
   15400 			break;
   15401 			case Utils::VARIABLE_TYPE_UINT:
   15402 			{
   15403 				uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
   15404 
   15405 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
   15406 			}
   15407 			break;
   15408 			case Utils::VARIABLE_TYPE_INT:
   15409 			{
   15410 				uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
   15411 
   15412 				p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
   15413 			}
   15414 			break;
   15415 			default:
   15416 				TCU_FAIL("Not implemented");
   15417 				break;
   15418 			}
   15419 		}
   15420 		else
   15421 		{
   15422 			uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
   15423 
   15424 			p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
   15425 		}
   15426 	}
   15427 }
   15428 
   15429 /** Init GL obejcts
   15430  *
   15431  **/
   15432 void BuiltinFunctionTest::testInit()
   15433 {
   15434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
   15435 
   15436 	gl.genBuffers(1, &m_transform_feedback_buffer_id);
   15437 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
   15438 
   15439 	gl.genVertexArrays(1, &m_vertex_array_object_id);
   15440 	GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
   15441 
   15442 	gl.enable(GL_RASTERIZER_DISCARD);
   15443 }
   15444 
   15445 /** Checks if function result is an acceptable edge case
   15446  *
   15447  * @param function_object Function object
   15448  * @param vertex          Vertex index
   15449  *
   15450  * @return true if all results are as expected, false otherwise
   15451  **/
   15452 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
   15453 										   const Utils::_variable_type result_type,
   15454 										   const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
   15455 {
   15456 	FunctionEnum function_type = function_object.getFunctionEnum();
   15457 	switch (function_type)
   15458 	{
   15459 	// mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
   15460 	// allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
   15461 	// In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
   15462 	case FUNCTION_MOD:
   15463 	case FUNCTION_MOD_AGAINST_SCALAR:
   15464 	{
   15465 		const glw::GLuint	arguments_stride   = function_object.getArgumentStride();
   15466 		const glw::GLuint	vertex_offset	   = arguments_stride * vertex;
   15467 		const glw::GLuint	argument_1_offset  = function_object.getArgumentOffset(0);
   15468 		const glw::GLuint	argument_2_offset  = function_object.getArgumentOffset(1);
   15469 		const glw::GLuint	argument_1_index   = argument_1_offset + vertex_offset;
   15470 		const glw::GLuint	argument_2_index   = argument_2_offset + vertex_offset;
   15471 		const glw::GLubyte*  argument_1_bytes  = &m_argument_data[argument_1_index];
   15472 		const glw::GLubyte*  argument_2_bytes  = &m_argument_data[argument_2_index];
   15473 		const glw::GLdouble* argument_1		   = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
   15474 		const glw::GLdouble* argument_2		   = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
   15475 		const glw::GLdouble* expected_result   = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
   15476 		const glw::GLdouble* actual_result	   = reinterpret_cast<const glw::GLdouble*>(result_src);
   15477 		bool				 edge_case_present = false;
   15478 		bool				 recheck		   = false;
   15479 
   15480 		// verify if there is a mod(a, a) case and prepare new expected result
   15481 		const glw::GLuint		   n_components = Utils::getNumberOfComponentsForVariableType(result_type);
   15482 		std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
   15483 		for (glw::GLuint component = 0; component < n_components; ++component)
   15484 		{
   15485 			glw::GLdouble expected_result_component = expected_result[component];
   15486 			glw::GLdouble actual_result_component   = actual_result[component];
   15487 			glw::GLdouble argument_1_component		= argument_1[component];
   15488 			glw::GLdouble argument_2_component		= argument_2[(function_type == FUNCTION_MOD) ? component : 0];
   15489 
   15490 			// if coresponding components of arguments are equal and if component of first argument
   15491 			// and component of result are equal then expected result must be corrected
   15492 			edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) &&
   15493 								(m_epsilon > de::abs(argument_1_component - actual_result_component));
   15494 			recheck |= edge_case_present;
   15495 			corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component;
   15496 		}
   15497 
   15498 		// recheck test result with corrected expected result
   15499 		return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
   15500 	}
   15501 	default:
   15502 		return false;
   15503 	}
   15504 }
   15505 
   15506 /** Compare contents of transform feedback buffer with expected results
   15507  *
   15508  * @param function_object Function object
   15509  * @param vertex          Vertex index
   15510  *
   15511  * @return true if all results are as expected, false otherwise
   15512  **/
   15513 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
   15514 {
   15515 	const glw::Functions& gl			   = m_context.getRenderContext().getFunctions();
   15516 	bool				  test_result	  = true;
   15517 	const glw::GLuint	 n_results		   = function_object.getResultCount();
   15518 	const glw::GLuint	 results_stride   = function_object.getResultStride();
   15519 	const glw::GLuint	 results_offset   = vertex * results_stride;
   15520 	const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
   15521 
   15522 	/* Get transform feedback data */
   15523 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
   15524 	GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
   15525 
   15526 	glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
   15527 	GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
   15528 
   15529 	for (glw::GLuint result = 0; result < n_results; ++result)
   15530 	{
   15531 		const Utils::_variable_type result_type   = function_object.getResultType(result);
   15532 		const glw::GLuint			result_offset = function_object.getResultOffset(result);
   15533 
   15534 		const glw::GLvoid* expected_result_src = expected_results + result_offset;
   15535 		const glw::GLvoid* result_src		   = feedback_data + result_offset;
   15536 
   15537 		if (compare(result_type, expected_result_src, result_src))
   15538 			continue;
   15539 
   15540 		if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
   15541 		{
   15542 			test_result = false;
   15543 			break;
   15544 		}
   15545 	}
   15546 
   15547 	/* Unmap transform feedback buffer */
   15548 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
   15549 	GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
   15550 
   15551 	if (false == test_result)
   15552 	{
   15553 		const glw::GLuint argument_stride  = function_object.getArgumentStride();
   15554 		const glw::GLuint arguments_offset = vertex * argument_stride;
   15555 
   15556 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
   15557 											<< tcu::TestLog::EndMessage;
   15558 
   15559 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
   15560 											<< tcu::TestLog::EndMessage;
   15561 
   15562 		for (glw::GLuint result = 0; result < n_results; ++result)
   15563 		{
   15564 			const Utils::_variable_type result_type   = function_object.getResultType(result);
   15565 			const glw::GLuint			result_offset = function_object.getResultOffset(result);
   15566 
   15567 			const glw::GLvoid* expected_result_src = expected_results + result_offset;
   15568 			const glw::GLvoid* result_src		   = feedback_data + result_offset;
   15569 
   15570 			logVariableType(result_src, "Result", result_type);
   15571 			logVariableType(expected_result_src, "Expected result", result_type);
   15572 		}
   15573 
   15574 		for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
   15575 		{
   15576 			const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
   15577 			const glw::GLubyte* argument_src	= &m_argument_data[arguments_offset + argument_offset];
   15578 
   15579 			logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
   15580 		}
   15581 
   15582 		m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
   15583 											<< m_vertex_shader_code << tcu::TestLog::EndMessage;
   15584 	}
   15585 
   15586 	return test_result;
   15587 }
   15588 
   15589 /** Constructor.
   15590  *
   15591  *  @param context Rendering context.
   15592  **/
   15593 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
   15594 	: TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
   15595 {
   15596 	/* Left blank on purpose */
   15597 }
   15598 
   15599 /** Initializes a texture_storage_multisample test group.
   15600  *
   15601  **/
   15602 void GPUShaderFP64Tests::init(void)
   15603 {
   15604 	TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
   15605 	fp64->addChild(new GPUShaderFP64Test1(m_context));
   15606 	fp64->addChild(new GPUShaderFP64Test2(m_context));
   15607 	fp64->addChild(new GPUShaderFP64Test3(m_context));
   15608 	fp64->addChild(new GPUShaderFP64Test4(m_context));
   15609 	fp64->addChild(new GPUShaderFP64Test5(m_context));
   15610 	fp64->addChild(new GPUShaderFP64Test6(m_context));
   15611 	fp64->addChild(new GPUShaderFP64Test7(m_context));
   15612 	fp64->addChild(new GPUShaderFP64Test8(m_context));
   15613 	fp64->addChild(new GPUShaderFP64Test9(m_context));
   15614 	addChild(fp64);
   15615 
   15616 	TypeDefinition typeDefinition[] =
   15617 	{
   15618 		{ "double",  1, 1 },
   15619 		{ "dvec2",   1, 2 },
   15620 		{ "dvec3",   1, 3 },
   15621 		{ "dvec4",   1, 4 },
   15622 		{ "dmat2",   2, 2 },
   15623 		{ "dmat2x3", 2, 3 },
   15624 		{ "dmat2x4", 2, 4 },
   15625 		{ "dmat3x2", 3, 2 },
   15626 		{ "dmat3",   3, 3 },
   15627 		{ "dmat3x4", 3, 4 },
   15628 		{ "dmat4x2", 4, 2 },
   15629 		{ "dmat4x3", 4, 3 },
   15630 		{ "dmat4",   4, 4 }
   15631 	};
   15632 
   15633 	struct BuiltinFunctions
   15634 	{
   15635 		std::string  name;
   15636 		FunctionEnum function;
   15637 	} builtinFunctions[] = {
   15638 		{ "abs",						FUNCTION_ABS },
   15639 		{ "ceil",						FUNCTION_CEIL },
   15640 		{ "clamp",						FUNCTION_CLAMP },
   15641 		{ "clamp_against_scalar",		FUNCTION_CLAMP_AGAINST_SCALAR },
   15642 		{ "cross",						FUNCTION_CROSS },
   15643 		{ "determinant",				FUNCTION_DETERMINANT },
   15644 		{ "distance",					FUNCTION_DISTANCE },
   15645 		{ "dot",						FUNCTION_DOT },
   15646 		{ "equal",						FUNCTION_EQUAL },
   15647 		{ "faceforward",				FUNCTION_FACEFORWARD },
   15648 		{ "floor",						FUNCTION_FLOOR },
   15649 		{ "fma",						FUNCTION_FMA },
   15650 		{ "fract",						FUNCTION_FRACT },
   15651 		{ "frexp",						FUNCTION_FREXP },
   15652 		{ "greaterthan",				FUNCTION_GREATERTHAN },
   15653 		{ "greaterthanequal",			FUNCTION_GREATERTHANEQUAL },
   15654 		{ "inverse",					FUNCTION_INVERSE },
   15655 		{ "inversesqrt",				FUNCTION_INVERSESQRT },
   15656 		{ "ldexp",						FUNCTION_LDEXP },
   15657 		{ "lessthan",					FUNCTION_LESSTHAN },
   15658 		{ "lessthanequal",				FUNCTION_LESSTHANEQUAL },
   15659 		{ "length",						FUNCTION_LENGTH },
   15660 		{ "matrixcompmult",				FUNCTION_MATRIXCOMPMULT },
   15661 		{ "max",						FUNCTION_MAX },
   15662 		{ "max_against_scalar",			FUNCTION_MAX_AGAINST_SCALAR },
   15663 		{ "min",						FUNCTION_MIN },
   15664 		{ "min_against_scalar",			FUNCTION_MIN_AGAINST_SCALAR },
   15665 		{ "mix",						FUNCTION_MIX },
   15666 		{ "mod",						FUNCTION_MOD },
   15667 		{ "mod_against_scalar",			FUNCTION_MOD_AGAINST_SCALAR },
   15668 		{ "modf",						FUNCTION_MODF },
   15669 		{ "normalize",					FUNCTION_NORMALIZE },
   15670 		{ "notequal",					FUNCTION_NOTEQUAL },
   15671 		{ "outerproduct",				FUNCTION_OUTERPRODUCT },
   15672 		{ "packdouble2x32",				FUNCTION_PACKDOUBLE2X32 },
   15673 		{ "reflect",					FUNCTION_REFLECT },
   15674 		{ "refract",					FUNCTION_REFRACT },
   15675 		{ "round",						FUNCTION_ROUND },
   15676 		{ "roundeven",					FUNCTION_ROUNDEVEN },
   15677 		{ "sign",						FUNCTION_SIGN },
   15678 		{ "smoothstep",					FUNCTION_SMOOTHSTEP },
   15679 		{ "smoothstep_against_scalar",	FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
   15680 		{ "sqrt",						FUNCTION_SQRT },
   15681 		{ "step",						FUNCTION_STEP },
   15682 		{ "step_against_scalar",		FUNCTION_STEP_AGAINST_SCALAR },
   15683 		{ "transpose",					FUNCTION_TRANSPOSE },
   15684 		{ "trunc",						FUNCTION_TRUNC },
   15685 		{ "unpackdouble2x32",			FUNCTION_UNPACKDOUBLE2X32 },
   15686 		{ "isnan",						FUNCTION_ISNAN },
   15687 		{ "isinf",						FUNCTION_ISINF }
   15688 	};
   15689 
   15690 	TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
   15691 	for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
   15692 	{
   15693 		const BuiltinFunctions& bf = builtinFunctions[i];
   15694 		for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
   15695 		{
   15696 			std::string caseName = bf.name + "_" + typeDefinition[j].name;
   15697 			builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
   15698 		}
   15699 	}
   15700 	addChild(builin);
   15701 }
   15702 
   15703 } /* glcts namespace */
   15704