Split built_in_functions into separate test
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl4cGPUShaderFP64Tests.cpp
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 = (const 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 = (const 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 verifyResults(const functionObject& function_object, glw::GLuint vertex);
12962
12963         /* Private constants */
12964         static const glw::GLdouble m_epsilon;
12965         static const glw::GLuint   m_n_veritces;
12966
12967         /* Private fields */
12968         glw::GLuint m_transform_feedback_buffer_id;
12969         glw::GLuint m_vertex_array_object_id;
12970
12971         std::vector<glw::GLubyte> m_expected_results_data;
12972         FunctionEnum                      m_function;
12973         TypeDefinition                    m_typeDefinition;
12974         std::vector<glw::GLubyte> m_argument_data;
12975         std::string                               m_vertex_shader_code;
12976 };
12977
12978 /* Constants used by BuiltinFunctionTest */
12979 /** Khronos Bug #14010
12980  *  Using an epsilon value for comparing floating points is error prone.
12981  *  Rather than writing a new floating point comparison function, I am
12982  *  increasing the epsilon value to allow greater orders of magnitude
12983  *  of floating point values.
12984  **/
12985 const glw::GLdouble BuiltinFunctionTest::m_epsilon      = 0.00002;
12986 const glw::GLuint   BuiltinFunctionTest::m_n_veritces = 1024;
12987
12988 /** Implementations of function objects required by "BuiltinFunctionTest"
12989  *
12990  **/
12991 namespace FunctionObject
12992 {
12993 /** Maps variable type with enumeration Utils::_variable_type
12994  *
12995  * @tparam T type
12996  **/
12997 template <typename T>
12998 class typeInfo
12999 {
13000 public:
13001         static const Utils::_variable_type variable_type =
13002                 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
13003 };
13004
13005 /** Place data from <in> into <buffer>
13006  *
13007  * @param buffer Buffer
13008  * @param in     Input data
13009  **/
13010 template <typename T>
13011 class pack
13012 {
13013 public:
13014         static void set(glw::GLvoid* buffer, const T& in)
13015         {
13016                 *(T*)buffer = in;
13017         }
13018 };
13019
13020 /** Place tcu::Matrix data from <in> into <buffer>
13021  *
13022  * @param buffer Buffer
13023  * @param in     Input data
13024  **/
13025 template <int Cols, int Rows>
13026 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13027 {
13028 public:
13029         static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13030         {
13031                 glw::GLdouble* data = (glw::GLdouble*)buffer;
13032
13033                 for (glw::GLint column = 0; column < Cols; ++column)
13034                 {
13035                         for (glw::GLint row = 0; row < Rows; ++row)
13036                         {
13037                                 glw::GLint index = column * Rows + row;
13038
13039                                 data[index] = in(row, column);
13040                         }
13041                 }
13042         }
13043 };
13044
13045 /** Get data of <out> from <buffer>
13046  *
13047  * @param buffer Buffer
13048  * @param out    Output data
13049  **/
13050 template <typename T>
13051 class unpack
13052 {
13053 public:
13054         static void get(const glw::GLvoid* buffer, T& out)
13055         {
13056                 out = *(T*)buffer;
13057         }
13058 };
13059
13060 /** Get tcu::Matrix data from <buffer>
13061  *
13062  * @param buffer Buffer
13063  * @param out    Output data
13064  **/
13065 template <int Cols, int Rows>
13066 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13067 {
13068 public:
13069         static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13070         {
13071                 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13072
13073                 for (glw::GLint column = 0; column < Cols; ++column)
13074                 {
13075                         for (glw::GLint row = 0; row < Rows; ++row)
13076                         {
13077                                 glw::GLint index = column * Rows + row;
13078
13079                                 out(row, column) = data[index];
13080                         }
13081                 }
13082         }
13083 };
13084
13085 /** Base of unary function classes
13086  *
13087  **/
13088 class unaryBase : public BuiltinFunctionTest::functionObject
13089 {
13090 public:
13091         unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13092                           const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13093                 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13094         {
13095         }
13096
13097         virtual glw::GLuint getArgumentCount() const
13098         {
13099                 return 1;
13100         }
13101
13102         virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13103         {
13104                 return m_arg_type;
13105         }
13106
13107 protected:
13108         const Utils::_variable_type m_arg_type;
13109 };
13110
13111 /** Unary function class. It treats input argument as one variable.
13112  *
13113  * @tparam ResT Type of result
13114  * @tparam ArgT Type of argument
13115  **/
13116 template <typename ResT, typename ArgT>
13117 class unary : public unaryBase
13118 {
13119 public:
13120         typedef ResT (*functionPointer)(const ArgT&);
13121
13122         unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13123                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13124                                         typeInfo<ArgT>::variable_type)
13125         {
13126         }
13127
13128         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13129         {
13130                 ResT result;
13131                 ArgT arg;
13132
13133                 unpack<ArgT>::get(argument_src, arg);
13134
13135                 functionPointer p_function = (functionPointer)m_p_function;
13136
13137                 result = p_function(arg);
13138
13139                 pack<ResT>::set(result_dst, result);
13140         }
13141 };
13142
13143 /** Unary function class. It treats input argument as separate components.
13144  *
13145  * @tparam ResT Type of result
13146  **/
13147 template <typename ResT>
13148 class unaryByComponent : public unaryBase
13149 {
13150 public:
13151         typedef ResT (*functionPointer)(glw::GLdouble);
13152
13153         unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13154                                          const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13155                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13156         {
13157         }
13158
13159         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13160         {
13161                 glw::GLuint     n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13162                 ResT*              p_result             = (ResT*)result_dst;
13163                 glw::GLdouble* p_arg            = (glw::GLdouble*)argument_src;
13164
13165                 functionPointer p_function = (functionPointer)m_p_function;
13166
13167                 for (glw::GLuint component = 0; component < n_components; ++component)
13168                 {
13169                         p_result[component] = p_function(p_arg[component]);
13170                 }
13171         }
13172 };
13173
13174 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13175  *
13176  * @tparam ResT Type of result
13177  * @tparam ArgT Type of argument
13178  * @tparam OutT Type of output parameter
13179  **/
13180 template <typename ResT, typename ArgT, typename OutT>
13181 class unaryWithOutputByComponent : public unaryBase
13182 {
13183 public:
13184         typedef ResT (*functionPointer)(ArgT, OutT&);
13185
13186         unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13187                                                            functionPointer function_pointer, const Utils::_variable_type res_type,
13188                                                            const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13189                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13190                 , m_out_type(out_type)
13191         {
13192         }
13193
13194         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13195         {
13196                 ResT* p_result = (ResT*)result_dst;
13197                 OutT* p_out     = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13198                 ArgT* p_arg     = (ArgT*)argument_src;
13199
13200                 const glw::GLuint n_components_0 = getArgumentComponents(0);
13201                 const glw::GLuint n_components_1 = getResultComponents(1);
13202                 const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13203
13204                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13205                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13206
13207                 functionPointer p_function = (functionPointer)m_p_function;
13208
13209                 for (glw::GLuint component = 0; component < n_components; ++component)
13210                 {
13211                         const ArgT first_arg  = p_arg[component * component_step_0];
13212                         OutT&     second_arg = p_out[component * component_step_1];
13213
13214                         p_result[component] = p_function(first_arg, second_arg);
13215                 }
13216         }
13217
13218         glw::GLuint getResultCount() const
13219         {
13220                 return 2;
13221         }
13222
13223         Utils::_variable_type getResultType(glw::GLuint result) const
13224         {
13225                 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13226
13227                 switch (result)
13228                 {
13229                 case 0:
13230                         type = m_res_type;
13231                         break;
13232                 case 1:
13233                         type = m_out_type;
13234                         break;
13235                 default:
13236                         TCU_FAIL("Not implemented");
13237                         break;
13238                 }
13239
13240                 return type;
13241         }
13242
13243 protected:
13244         const Utils::_variable_type m_out_type;
13245 };
13246
13247 /** Base of binary function classes.
13248  *
13249  **/
13250 class binaryBase : public BuiltinFunctionTest::functionObject
13251 {
13252 public:
13253         binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13254                            const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13255                            const Utils::_variable_type arg_2_type)
13256                 : functionObject(function_enum, function_name, function_pointer, res_type)
13257                 , m_arg_1_type(arg_1_type)
13258                 , m_arg_2_type(arg_2_type)
13259         {
13260         }
13261
13262         virtual glw::GLuint getArgumentCount() const
13263         {
13264                 return 2;
13265         }
13266
13267         virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13268         {
13269                 switch (argument)
13270                 {
13271                 case 0:
13272                         return m_arg_1_type;
13273                         break;
13274                 case 1:
13275                         return m_arg_2_type;
13276                         break;
13277                 default:
13278                         return Utils::VARIABLE_TYPE_UNKNOWN;
13279                         break;
13280                 }
13281         }
13282
13283 protected:
13284         const Utils::_variable_type m_arg_1_type;
13285         const Utils::_variable_type m_arg_2_type;
13286 };
13287
13288 /** Binary function class. It treats input arguments as two variables.
13289  *
13290  * @param ResT  Type of result
13291  * @param Arg1T Type of first argument
13292  * @param Arg2T Type of second argument
13293  **/
13294 template <typename ResT, typename Arg1T, typename Arg2T>
13295 class binary : public binaryBase
13296 {
13297 public:
13298         typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13299
13300         binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13301                 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13302                                          typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13303         {
13304         }
13305
13306         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13307         {
13308                 const glw::GLuint argument_1_stride = getArgumentStride(0);
13309
13310                 functionPointer p_function = (functionPointer)m_p_function;
13311
13312                 Arg1T arg_1;
13313                 Arg2T arg_2;
13314                 ResT  result;
13315
13316                 unpack<Arg1T>::get(argument_src, arg_1);
13317                 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13318
13319                 result = p_function(arg_1, arg_2);
13320
13321                 pack<ResT>::set(result_dst, result);
13322         }
13323 };
13324
13325 /** Binary function class. It treats input arguments as separate components.
13326  *
13327  * @param ResT  Type of result
13328  * @param Arg1T Type of first argument
13329  * @param Arg2T Type of second argument
13330  **/
13331 template <typename ResT, typename Arg1T, typename Arg2T>
13332 class binaryByComponent : public binaryBase
13333 {
13334 public:
13335         typedef ResT (*functionPointer)(Arg1T, Arg2T);
13336
13337         binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13338                                           const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13339                                           const Utils::_variable_type arg_2_type)
13340                 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13341         {
13342         }
13343
13344         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13345         {
13346                 ResT*  p_result = (ResT*)result_dst;
13347                 Arg1T* p_arg_1  = (Arg1T*)argument_src;
13348                 Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13349
13350                 const glw::GLuint n_components_0 = getArgumentComponents(0);
13351                 const glw::GLuint n_components_1 = getArgumentComponents(1);
13352                 const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13353
13354                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13355                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13356
13357                 functionPointer p_function = (functionPointer)m_p_function;
13358
13359                 for (glw::GLuint component = 0; component < n_components; ++component)
13360                 {
13361                         const Arg1T first_arg  = p_arg_1[component * component_step_0];
13362                         const Arg2T second_arg = p_arg_2[component * component_step_1];
13363
13364                         p_result[component] = p_function(first_arg, second_arg);
13365                 }
13366         }
13367 };
13368
13369 /** Base of tenary function classes.
13370  *
13371  **/
13372 class tenaryBase : public BuiltinFunctionTest::functionObject
13373 {
13374 public:
13375         tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13376                            const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13377                            const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13378                 : functionObject(function_enum, function_name, function_pointer, res_type)
13379                 , m_arg_1_type(arg_1_type)
13380                 , m_arg_2_type(arg_2_type)
13381                 , m_arg_3_type(arg_3_type)
13382         {
13383         }
13384
13385         virtual glw::GLuint getArgumentCount() const
13386         {
13387                 return 3;
13388         }
13389
13390         virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13391         {
13392                 switch (argument)
13393                 {
13394                 case 0:
13395                         return m_arg_1_type;
13396                         break;
13397                 case 1:
13398                         return m_arg_2_type;
13399                         break;
13400                 case 2:
13401                         return m_arg_3_type;
13402                         break;
13403                 default:
13404                         return Utils::VARIABLE_TYPE_UNKNOWN;
13405                         break;
13406                 }
13407         }
13408
13409 protected:
13410         const Utils::_variable_type m_arg_1_type;
13411         const Utils::_variable_type m_arg_2_type;
13412         const Utils::_variable_type m_arg_3_type;
13413 };
13414
13415 /** Tenary function class. It treats input arguments as three variables.
13416  *
13417  * @param ResT  Type of result
13418  * @param Arg1T Type of first argument
13419  * @param Arg2T Type of second argument
13420  * @param Arg3T Type of third argument
13421  **/
13422 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13423 class tenary : public tenaryBase
13424 {
13425 public:
13426         typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13427         typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13428         typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13429         typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13430
13431         tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13432                 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13433                                          typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13434         {
13435         }
13436
13437         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13438         {
13439                 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13440                 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13441
13442                 functionPointer p_function = (functionPointer)m_p_function;
13443
13444                 arg1T arg_1;
13445                 arg2T arg_2;
13446                 arg3T arg_3;
13447                 ResT  result;
13448
13449                 unpack<arg1T>::get(argument_src, arg_1);
13450                 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13451                 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13452
13453                 result = p_function(arg_1, arg_2, arg_3);
13454
13455                 pack<ResT>::set(result_dst, result);
13456         }
13457 };
13458
13459 /** Tenary function class. It treats input arguments as separate components.
13460  *
13461
13462  **/
13463 class tenaryByComponent : public tenaryBase
13464 {
13465 public:
13466         typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13467
13468         tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13469                                           const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13470                                           const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13471                 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13472                                          arg_3_type)
13473         {
13474         }
13475
13476         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13477         {
13478                 glw::GLdouble*           p_result = (glw::GLdouble*)result_dst;
13479                 const glw::GLdouble* p_arg      = (const glw::GLdouble*)argument_src;
13480
13481                 const glw::GLuint n_components_0 = getArgumentComponents(0);
13482                 const glw::GLuint n_components_1 = getArgumentComponents(1);
13483                 const glw::GLuint n_components_2 = getArgumentComponents(2);
13484                 const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13485
13486                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13487                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13488                 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13489
13490                 functionPointer p_function = (functionPointer)m_p_function;
13491
13492                 for (glw::GLuint component = 0; component < n_components; ++component)
13493                 {
13494                         const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13495                         const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13496                         const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13497
13498                         p_result[component] = p_function(first_arg, second_arg, third_arg);
13499                 }
13500         }
13501 };
13502 } /* FunctionObject */
13503
13504 /** Constructor.
13505  *
13506  *  @param context Rendering context.
13507  **/
13508 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13509                                                                                  TypeDefinition typeDefinition)
13510         : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13511         , m_transform_feedback_buffer_id(0)
13512         , m_vertex_array_object_id(0)
13513         , m_function(function)
13514         , m_typeDefinition(typeDefinition)
13515 {
13516         /* Nothing to be done here */
13517 }
13518
13519 /** Deinitializes all GL objects that may have been created during test execution.
13520  *
13521  **/
13522 void BuiltinFunctionTest::deinit()
13523 {
13524         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13525
13526         /* Clean buffers */
13527         if (0 != m_transform_feedback_buffer_id)
13528         {
13529                 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13530                 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13531                 m_transform_feedback_buffer_id = 0;
13532         }
13533
13534         /* Clean VAO */
13535         if (0 != m_vertex_array_object_id)
13536         {
13537                 gl.bindVertexArray(0);
13538                 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13539                 m_vertex_array_object_id = 0;
13540         }
13541 }
13542
13543 /** Execute test
13544  *
13545  * @return tcu::TestNode::STOP
13546  **/
13547 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13548 {
13549         /* Check if extension is supported */
13550         if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13551         {
13552                 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13553         }
13554
13555         testInit();
13556
13557         /* Verify result */
13558         typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13559         if (test(m_function, type))
13560         {
13561                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13562         }
13563         else
13564         {
13565                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13566         }
13567
13568         /* Done */
13569         return tcu::TestNode::STOP;
13570 }
13571
13572 /** Constructor
13573  *
13574  * @param function_enum    Function enumeration
13575  * @param function_name    Function name
13576  * @param function_pointer Pointer to routine that wiil be executed
13577  * @param result_type      Type of result
13578  **/
13579 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13580                                                                                                         glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13581         : m_function_enum(function_enum)
13582         , m_function_name(function_name)
13583         , m_p_function(function_pointer)
13584         , m_res_type(result_type)
13585 {
13586         /* Nothing to be done here */
13587 }
13588
13589 /** Get number of components for <argument>
13590  *
13591  * @param argument Argument ordinal, starts with 0
13592  *
13593  * @return Number of components
13594  **/
13595 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13596 {
13597         const Utils::_variable_type type                  = getArgumentType(argument);
13598         const glw::GLuint                       n_components  = Utils::getNumberOfComponentsForVariableType(type);
13599
13600         return n_components;
13601 }
13602
13603 /** Get size in bytes of single component of <argument>
13604  *
13605  * @param argument Argument ordinal, starts with 0
13606  *
13607  * @return Size of component
13608  **/
13609 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13610 {
13611         const Utils::_variable_type type                   = getArgumentType(argument);
13612         const Utils::_variable_type base_type     = Utils::getBaseVariableType(type);
13613         const glw::GLuint                       base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13614
13615         return base_type_size;
13616 }
13617
13618 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13619  *
13620  * @param argument Argument ordinal, starts with 0
13621  *
13622  * @return Offset of arguemnt's data
13623  **/
13624 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13625 {
13626         glw::GLuint result = 0;
13627
13628         for (glw::GLuint i = 0; i < argument; ++i)
13629         {
13630                 result += getArgumentStride(i);
13631         }
13632
13633         return result;
13634 }
13635
13636 /** Get stride in bytes of all arguments
13637  *
13638  * @return Stride of all arguments
13639  **/
13640 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13641 {
13642         const glw::GLuint n_args = getArgumentCount();
13643         glw::GLuint               result = 0;
13644
13645         for (glw::GLuint i = 0; i < n_args; ++i)
13646         {
13647                 result += getArgumentStride(i);
13648         }
13649
13650         return result;
13651 }
13652
13653 /** Get stride in bytes of <argument>
13654  *
13655  * @param argument Argument ordinal, starts with 0
13656  *
13657  * @return Stride of argument
13658  **/
13659 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13660 {
13661         const glw::GLuint component_size = getArgumentComponentSize(argument);
13662         const glw::GLuint n_components   = getArgumentComponents(argument);
13663
13664         return n_components * component_size;
13665 }
13666
13667 /** Get function enumeration
13668  *
13669  * @return Function enumeration
13670  **/
13671 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13672 {
13673         return m_function_enum;
13674 }
13675
13676 /** Get function name
13677  *
13678  * @return Function name
13679  **/
13680 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13681 {
13682         return m_function_name;
13683 }
13684
13685 /** Get number of components for <result>
13686  *
13687  * @param result Result ordinal, starts with 0
13688  *
13689  * @return Number of components
13690  **/
13691 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13692 {
13693         const Utils::_variable_type type                  = getResultType(result);
13694         const glw::GLuint                       n_components  = Utils::getNumberOfComponentsForVariableType(type);
13695
13696         return n_components;
13697 }
13698
13699 /** Get number of results
13700  *
13701  * @return Number of results
13702  **/
13703 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13704 {
13705         return 1;
13706 }
13707
13708 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13709  *
13710  * @param result Result ordinal, starts with 0
13711  *
13712  * @return Offset
13713  **/
13714 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13715 {
13716         glw::GLuint offset = 0;
13717
13718         for (glw::GLuint i = 0; i < result; ++i)
13719         {
13720                 offset += getResultStride(i);
13721                 offset = deAlign32(offset, getBaseTypeSize(i));
13722         }
13723
13724         return offset;
13725 }
13726
13727 /** Get stride in bytes of <result>.
13728  *
13729  * @param result Result ordinal, starts with 0
13730  *
13731  * @return Stride
13732  **/
13733 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13734 {
13735         const Utils::_variable_type type                   = getResultType(result);
13736         const glw::GLuint                       n_components   = Utils::getNumberOfComponentsForVariableType(type);
13737
13738         return n_components * getBaseTypeSize(result);
13739 }
13740
13741 /** Get size in bytes of <result> base component.
13742  *
13743  * @param result Result ordinal, starts with 0
13744  *
13745  * @return Alignment
13746  **/
13747 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13748 {
13749         const Utils::_variable_type type                   = getResultType(result);
13750         const Utils::_variable_type base_type     = Utils::getBaseVariableType(type);
13751         const glw::GLuint                       base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13752
13753         return base_type_size;
13754 }
13755
13756 /** Get stride in bytes of all results.
13757  *
13758  * @return Stride
13759  **/
13760 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13761 {
13762         const glw::GLuint n_results     = getResultCount();
13763         glw::GLuint               stride           = 0;
13764         glw::GLuint               maxAlignment = 0;
13765
13766         for (glw::GLuint i = 0; i < n_results; ++i)
13767         {
13768                 const glw::GLuint alignment = getBaseTypeSize(i);
13769                 stride += getResultStride(i);
13770                 stride           = deAlign32(stride, alignment);
13771                 maxAlignment = deMaxu32(maxAlignment, alignment);
13772         }
13773
13774         // The stride of all results must also be aligned,
13775         // so results for next vertex are aligned.
13776         return deAlign32(stride, maxAlignment);
13777 }
13778
13779 /** Get type of <result>.
13780  *
13781  * @param result Result ordinal, starts with 0
13782  *
13783  * @return Type
13784  **/
13785 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13786 {
13787         return m_res_type;
13788 }
13789
13790 /** Constructor
13791  *
13792  * @param n_columns Number of columns
13793  * @param n_rows    Number of rows
13794  **/
13795 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13796         : m_n_columns(n_columns), m_n_rows(n_rows)
13797 {
13798         Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13799         m_type                                     = Utils::getGLDataTypeOfVariableType(type);
13800         m_type_name                                = Utils::getVariableTypeString(type);
13801
13802         if (1 == m_n_columns)
13803         {
13804                 if (1 == m_n_rows)
13805                 {
13806                         m_general_type = SCALAR;
13807                 }
13808                 else
13809                 {
13810                         m_general_type = VECTOR;
13811                 }
13812         }
13813         else
13814         {
13815                 m_general_type = MATRIX;
13816         }
13817 }
13818
13819 /** Compare two values
13820  *
13821  * @param type  Type of values
13822  * @param left  Pointer to left value
13823  * @param right Pointer to right value
13824  *
13825  * @return true if values are equal, false otherwise
13826  **/
13827 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13828 {
13829         bool result = true;
13830
13831         const glw::GLuint                       n_components = Utils::getNumberOfComponentsForVariableType(type);
13832         const Utils::_variable_type base_type   = Utils::getBaseVariableType(type);
13833
13834         switch (base_type)
13835         {
13836         case Utils::VARIABLE_TYPE_DOUBLE:
13837
13838         {
13839                 const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13840                 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13841
13842                 for (glw::GLuint component = 0; component < n_components; ++component)
13843                 {
13844                         const glw::GLdouble left_value  = left_values[component];
13845                         const glw::GLdouble right_value = right_values[component];
13846
13847                         if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13848                                 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13849                         {
13850                                 result = false;
13851                                 break;
13852                         }
13853                 }
13854         }
13855
13856         break;
13857
13858         case Utils::VARIABLE_TYPE_INT:
13859
13860         {
13861                 const glw::GLint* left_values  = (glw::GLint*)left;
13862                 const glw::GLint* right_values = (glw::GLint*)right;
13863
13864                 for (glw::GLuint component = 0; component < n_components; ++component)
13865                 {
13866                         const glw::GLint left_value  = left_values[component];
13867                         const glw::GLint right_value = right_values[component];
13868
13869                         if (left_value != right_value)
13870                         {
13871                                 result = false;
13872                                 break;
13873                         }
13874                 }
13875         }
13876
13877         break;
13878
13879         case Utils::VARIABLE_TYPE_UINT:
13880
13881         {
13882                 const glw::GLuint* left_values  = (glw::GLuint*)left;
13883                 const glw::GLuint* right_values = (glw::GLuint*)right;
13884
13885                 for (glw::GLuint component = 0; component < n_components; ++component)
13886                 {
13887                         const glw::GLuint left_value  = left_values[component];
13888                         const glw::GLuint right_value = right_values[component];
13889
13890                         if (left_value != right_value)
13891                         {
13892                                 result = false;
13893                                 break;
13894                         }
13895                 }
13896         }
13897
13898         break;
13899
13900         default:
13901
13902                 TCU_FAIL("Not implemented");
13903
13904                 break;
13905         }
13906
13907         return result;
13908 }
13909
13910 /** Create instance of function object for given function enumeration and type
13911  *
13912  * @param function Function enumeration
13913  * @param type     Type details
13914  *
13915  * @return Create object
13916  **/
13917 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum           function,
13918                                                                                                                                                         const typeDetails& type)
13919 {
13920         typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13921         typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13922         typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13923         typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13924         typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13925         typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13926         typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13927         typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13928         typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13929
13930         const glw::GLuint                       n_columns        = type.m_n_columns;
13931         const glw::GLuint                       n_rows            = type.m_n_rows;
13932         const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13933         const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13934         const Utils::_variable_type uint_type    = Utils::getUintVariableType(1, n_rows);
13935         const Utils::_variable_type int_type      = Utils::getIntVariableType(1, n_rows);
13936
13937         switch (function)
13938         {
13939         case FUNCTION_ABS:
13940
13941                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13942                         function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13943
13944                 break;
13945
13946         case FUNCTION_CEIL:
13947
13948                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13949                         function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13950
13951                 break;
13952
13953         case FUNCTION_CLAMP:
13954
13955                 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13956                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
13957                                                                                                          variable_type /* arg3_type */);
13958                 break;
13959
13960         case FUNCTION_CLAMP_AGAINST_SCALAR:
13961
13962                 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13963                                                                                                          variable_type /* arg1_type */, scalar_type /* arg2_type */,
13964                                                                                                          scalar_type /* arg3_type */);
13965                 break;
13966
13967         case FUNCTION_CROSS:
13968
13969                 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13970                         function, "cross", tcu::cross);
13971
13972                 break;
13973
13974         case FUNCTION_DETERMINANT:
13975
13976                 switch (variable_type)
13977                 {
13978                 case Utils::VARIABLE_TYPE_DMAT2:
13979                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13980                                                                                                                                                                                  Math::determinant);
13981                 case Utils::VARIABLE_TYPE_DMAT3:
13982                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13983                                                                                                                                                                                  Math::determinant);
13984                 case Utils::VARIABLE_TYPE_DMAT4:
13985                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13986                                                                                                                                                                                  Math::determinant);
13987                 default:
13988                         TCU_FAIL("Not implemented");
13989                         break;
13990                 }
13991
13992                 break;
13993
13994         case FUNCTION_DISTANCE:
13995
13996                 switch (variable_type)
13997                 {
13998                 case Utils::VARIABLE_TYPE_DVEC2:
13999                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14000                                 function, "distance", tcu::distance);
14001                         break;
14002                 case Utils::VARIABLE_TYPE_DVEC3:
14003                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14004                                 function, "distance", tcu::distance);
14005                         break;
14006                 case Utils::VARIABLE_TYPE_DVEC4:
14007                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14008                                 function, "distance", tcu::distance);
14009                         break;
14010                 default:
14011                         break;
14012                 }
14013
14014                 break;
14015
14016         case FUNCTION_DOT:
14017
14018                 switch (variable_type)
14019                 {
14020                 case Utils::VARIABLE_TYPE_DVEC2:
14021                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14022                                 function, "dot", tcu::dot);
14023                         break;
14024                 case Utils::VARIABLE_TYPE_DVEC3:
14025                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14026                                 function, "dot", tcu::dot);
14027                         break;
14028                 case Utils::VARIABLE_TYPE_DVEC4:
14029                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14030                                 function, "dot", tcu::dot);
14031                         break;
14032                 default:
14033                         break;
14034                 }
14035
14036                 break;
14037
14038         case FUNCTION_EQUAL:
14039
14040                 switch (variable_type)
14041                 {
14042                 case Utils::VARIABLE_TYPE_DVEC2:
14043                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14044                                 function, "equal", Math::equal);
14045                         break;
14046                 case Utils::VARIABLE_TYPE_DVEC3:
14047                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14048                                 function, "equal", Math::equal);
14049                         break;
14050                 case Utils::VARIABLE_TYPE_DVEC4:
14051                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14052                                 function, "equal", Math::equal);
14053                         break;
14054                 default:
14055                         break;
14056                 }
14057
14058                 break;
14059
14060         case FUNCTION_FACEFORWARD:
14061
14062                 switch (variable_type)
14063                 {
14064                 case Utils::VARIABLE_TYPE_DVEC2:
14065                         return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14066                                                                                           const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14067                                 function, "faceforward", tcu::faceForward);
14068                         break;
14069                 case Utils::VARIABLE_TYPE_DVEC3:
14070                         return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14071                                                                                           const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14072                                 function, "faceforward", tcu::faceForward);
14073                         break;
14074                 case Utils::VARIABLE_TYPE_DVEC4:
14075                         return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14076                                                                                           const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14077                                 function, "faceforward", tcu::faceForward);
14078                         break;
14079                 default:
14080                         break;
14081                 }
14082
14083                 break;
14084
14085         case FUNCTION_FLOOR:
14086
14087                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14088                         function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14089
14090                 break;
14091
14092         case FUNCTION_FMA:
14093
14094                 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14095                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
14096                                                                                                          variable_type /* arg3_type */);
14097
14098                 break;
14099
14100         case FUNCTION_FRACT:
14101
14102                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14103                         function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14104
14105                 break;
14106
14107         case FUNCTION_FREXP:
14108
14109                 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14110                                                                                                                           glw::GLint /* OutT */>(
14111                         function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14112                         int_type /* out_type */);
14113
14114                 break;
14115
14116         case FUNCTION_GREATERTHAN:
14117
14118                 switch (variable_type)
14119                 {
14120                 case Utils::VARIABLE_TYPE_DVEC2:
14121                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14122                                 function, "greaterThan", Math::greaterThan);
14123                         break;
14124                 case Utils::VARIABLE_TYPE_DVEC3:
14125                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14126                                 function, "greaterThan", Math::greaterThan);
14127                         break;
14128                 case Utils::VARIABLE_TYPE_DVEC4:
14129                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14130                                 function, "greaterThan", Math::greaterThan);
14131                         break;
14132                 default:
14133                         break;
14134                 }
14135
14136                 break;
14137
14138         case FUNCTION_GREATERTHANEQUAL:
14139
14140                 switch (variable_type)
14141                 {
14142                 case Utils::VARIABLE_TYPE_DVEC2:
14143                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14144                                 function, "greaterThanEqual", Math::greaterThanEqual);
14145                         break;
14146                 case Utils::VARIABLE_TYPE_DVEC3:
14147                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14148                                 function, "greaterThanEqual", Math::greaterThanEqual);
14149                         break;
14150                 case Utils::VARIABLE_TYPE_DVEC4:
14151                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14152                                 function, "greaterThanEqual", Math::greaterThanEqual);
14153                         break;
14154                 default:
14155                         break;
14156                 }
14157
14158                 break;
14159
14160         case FUNCTION_INVERSE:
14161
14162                 switch (variable_type)
14163                 {
14164                 case Utils::VARIABLE_TYPE_DMAT2:
14165                         return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14166                         break;
14167                 case Utils::VARIABLE_TYPE_DMAT3:
14168                         return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14169                         break;
14170                 case Utils::VARIABLE_TYPE_DMAT4:
14171                         return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14172                         break;
14173                 default:
14174                         break;
14175                 }
14176
14177                 break;
14178
14179         case FUNCTION_INVERSESQRT:
14180
14181                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14182                         function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14183
14184                 break;
14185
14186         case FUNCTION_LDEXP:
14187
14188                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14189                                                                                                          glw::GLint /* Arg2T */>(
14190                         function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14191                         int_type /* arg2_type */);
14192
14193                 break;
14194
14195         case FUNCTION_LESSTHAN:
14196
14197                 switch (variable_type)
14198                 {
14199                 case Utils::VARIABLE_TYPE_DVEC2:
14200                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14201                                 function, "lessThan", Math::lessThan);
14202                         break;
14203                 case Utils::VARIABLE_TYPE_DVEC3:
14204                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14205                                 function, "lessThan", Math::lessThan);
14206                         break;
14207                 case Utils::VARIABLE_TYPE_DVEC4:
14208                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14209                                 function, "lessThan", Math::lessThan);
14210                         break;
14211                 default:
14212                         break;
14213                 }
14214
14215                 break;
14216
14217         case FUNCTION_LESSTHANEQUAL:
14218
14219                 switch (variable_type)
14220                 {
14221                 case Utils::VARIABLE_TYPE_DVEC2:
14222                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14223                                 function, "lessThanEqual", Math::lessThanEqual);
14224                         break;
14225                 case Utils::VARIABLE_TYPE_DVEC3:
14226                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14227                                 function, "lessThanEqual", Math::lessThanEqual);
14228                         break;
14229                 case Utils::VARIABLE_TYPE_DVEC4:
14230                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14231                                 function, "lessThanEqual", Math::lessThanEqual);
14232                         break;
14233                 default:
14234                         break;
14235                 }
14236
14237                 break;
14238
14239         case FUNCTION_LENGTH:
14240
14241                 switch (variable_type)
14242                 {
14243                 case Utils::VARIABLE_TYPE_DVEC2:
14244                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14245                                                                                                                                                                                           tcu::length);
14246                         break;
14247                 case Utils::VARIABLE_TYPE_DVEC3:
14248                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14249                                                                                                                                                                                           tcu::length);
14250                         break;
14251                 case Utils::VARIABLE_TYPE_DVEC4:
14252                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14253                                                                                                                                                                                           tcu::length);
14254                         break;
14255                 default:
14256                         break;
14257                 }
14258
14259                 break;
14260
14261         case FUNCTION_MATRIXCOMPMULT:
14262
14263                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14264                                                                                                          glw::GLdouble /* Arg2T */>(
14265                         function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14266                         variable_type /* arg2_type */);
14267
14268                 break;
14269
14270         case FUNCTION_MAX:
14271
14272                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14273                                                                                                          glw::GLdouble /* Arg2T */>(
14274                         function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14275                         variable_type /* arg2_type */);
14276
14277                 break;
14278
14279         case FUNCTION_MAX_AGAINST_SCALAR:
14280
14281                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14282                                                                                                          glw::GLdouble /* Arg2T */>(
14283                         function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14284                         scalar_type /* arg2_type */);
14285
14286                 break;
14287
14288         case FUNCTION_MIN:
14289
14290                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14291                                                                                                          glw::GLdouble /* Arg2T */>(
14292                         function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14293                         variable_type /* arg2_type */);
14294
14295                 break;
14296
14297         case FUNCTION_MIN_AGAINST_SCALAR:
14298
14299                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14300                                                                                                          glw::GLdouble /* Arg2T */>(
14301                         function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14302                         scalar_type /* arg2_type */);
14303
14304                 break;
14305
14306         case FUNCTION_MIX:
14307
14308                 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14309                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
14310                                                                                                          variable_type /* arg3_type */);
14311
14312                 break;
14313
14314         case FUNCTION_MOD:
14315
14316                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14317                                                                                                          glw::GLdouble /* Arg2T */>(
14318                         function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14319                         variable_type /* arg2_type */);
14320
14321                 break;
14322
14323         case FUNCTION_MOD_AGAINST_SCALAR:
14324
14325                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14326                                                                                                          glw::GLdouble /* Arg2T */>(
14327                         function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14328                         scalar_type /* arg2_type */);
14329
14330                 break;
14331
14332         case FUNCTION_MODF:
14333
14334                 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14335                                                                                                                           glw::GLdouble /* OutT */>(
14336                         function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14337                         variable_type /* out_type */);
14338
14339                 break;
14340
14341         case FUNCTION_NORMALIZE:
14342
14343                 switch (variable_type)
14344                 {
14345                 case Utils::VARIABLE_TYPE_DVEC2:
14346                         return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14347                                                                                                                                                                                    tcu::normalize);
14348                         break;
14349                 case Utils::VARIABLE_TYPE_DVEC3:
14350                         return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14351                                                                                                                                                                                    tcu::normalize);
14352                         break;
14353                 case Utils::VARIABLE_TYPE_DVEC4:
14354                         return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14355                                                                                                                                                                                    tcu::normalize);
14356                         break;
14357                 default:
14358                         break;
14359                 }
14360
14361                 break;
14362
14363         case FUNCTION_NOTEQUAL:
14364
14365                 switch (variable_type)
14366                 {
14367                 case Utils::VARIABLE_TYPE_DVEC2:
14368                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14369                                 function, "notEqual", Math::notEqual);
14370                         break;
14371                 case Utils::VARIABLE_TYPE_DVEC3:
14372                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14373                                 function, "notEqual", Math::notEqual);
14374                         break;
14375                 case Utils::VARIABLE_TYPE_DVEC4:
14376                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14377                                 function, "notEqual", Math::notEqual);
14378                         break;
14379                 default:
14380                         break;
14381                 }
14382
14383                 break;
14384
14385         case FUNCTION_OUTERPRODUCT:
14386
14387                 switch (variable_type)
14388                 {
14389                 case Utils::VARIABLE_TYPE_DMAT2:
14390                         return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14391                                 function, "outerProduct", Math::outerProduct);
14392                         break;
14393                 case Utils::VARIABLE_TYPE_DMAT2X3:
14394                         return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14395                                 function, "outerProduct", Math::outerProduct);
14396                         break;
14397                 case Utils::VARIABLE_TYPE_DMAT2X4:
14398                         return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14399                                 function, "outerProduct", Math::outerProduct);
14400                         break;
14401                 case Utils::VARIABLE_TYPE_DMAT3:
14402                         return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14403                                 function, "outerProduct", Math::outerProduct);
14404                         break;
14405                 case Utils::VARIABLE_TYPE_DMAT3X2:
14406                         return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14407                                 function, "outerProduct", Math::outerProduct);
14408                         break;
14409                 case Utils::VARIABLE_TYPE_DMAT3X4:
14410                         return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14411                                 function, "outerProduct", Math::outerProduct);
14412                         break;
14413                 case Utils::VARIABLE_TYPE_DMAT4:
14414                         return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14415                                 function, "outerProduct", Math::outerProduct);
14416                         break;
14417                 case Utils::VARIABLE_TYPE_DMAT4X2:
14418                         return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14419                                 function, "outerProduct", Math::outerProduct);
14420                         break;
14421                 case Utils::VARIABLE_TYPE_DMAT4X3:
14422                         return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14423                                 function, "outerProduct", Math::outerProduct);
14424                         break;
14425                 default:
14426                         break;
14427                 }
14428
14429                 break;
14430
14431         case FUNCTION_PACKDOUBLE2X32:
14432
14433                 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14434                                                                                                                                                                                   Math::packDouble2x32);
14435
14436                 break;
14437
14438         case FUNCTION_REFLECT:
14439
14440                 switch (variable_type)
14441                 {
14442                 case Utils::VARIABLE_TYPE_DVEC2:
14443                         return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14444                                 function, "reflect", tcu::reflect);
14445                         break;
14446                 case Utils::VARIABLE_TYPE_DVEC3:
14447                         return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14448                                 function, "reflect", tcu::reflect);
14449                         break;
14450                 case Utils::VARIABLE_TYPE_DVEC4:
14451                         return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14452                                 function, "reflect", tcu::reflect);
14453                         break;
14454                 default:
14455                         break;
14456                 }
14457
14458                 break;
14459
14460         case FUNCTION_REFRACT:
14461
14462                 switch (variable_type)
14463                 {
14464                 case Utils::VARIABLE_TYPE_DVEC2:
14465                         return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14466                                                                                           const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14467                                 function, "refract", tcu::refract);
14468                         break;
14469                 case Utils::VARIABLE_TYPE_DVEC3:
14470                         return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14471                                                                                           const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14472                                 function, "refract", tcu::refract);
14473                         break;
14474                 case Utils::VARIABLE_TYPE_DVEC4:
14475                         return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14476                                                                                           const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14477                                 function, "refract", tcu::refract);
14478                         break;
14479                 default:
14480                         break;
14481                 }
14482
14483                 break;
14484
14485         case FUNCTION_ROUND:
14486
14487                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14488                         function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14489
14490                 break;
14491
14492         case FUNCTION_ROUNDEVEN:
14493
14494                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14495                         function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14496
14497                 break;
14498
14499         case FUNCTION_SIGN:
14500
14501                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14502                         function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14503
14504                 break;
14505
14506         case FUNCTION_SMOOTHSTEP:
14507
14508                 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14509                                                                                                          variable_type /* res_type  */, variable_type /* arg1_type */,
14510                                                                                                          variable_type /* arg2_type */, variable_type /* arg3_type */);
14511
14512                 break;
14513
14514         case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14515
14516                 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14517                                                                                                          variable_type /* res_type  */, scalar_type /* arg1_type */,
14518                                                                                                          scalar_type /* arg2_type */, variable_type /* arg3_type */);
14519
14520                 break;
14521
14522         case FUNCTION_SQRT:
14523
14524                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14525                         function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14526
14527                 break;
14528
14529         case FUNCTION_STEP:
14530
14531                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14532                                                                                                          glw::GLdouble /* Arg2T */>(
14533                         function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14534                         variable_type /* arg2_type */);
14535
14536                 break;
14537
14538         case FUNCTION_STEP_AGAINST_SCALAR:
14539
14540                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14541                                                                                                          glw::GLdouble /* Arg2T */>(
14542                         function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14543                         variable_type /* arg2_type */);
14544
14545                 break;
14546
14547         case FUNCTION_TRANSPOSE:
14548
14549                 switch (variable_type)
14550                 {
14551                 case Utils::VARIABLE_TYPE_DMAT2:
14552                         return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14553                                                                                                                                                                  Math::transpose);
14554                         break;
14555                 case Utils::VARIABLE_TYPE_DMAT2X3:
14556                         return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14557                                                                                                                                                                          Math::transpose);
14558                         break;
14559                 case Utils::VARIABLE_TYPE_DMAT2X4:
14560                         return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14561                                                                                                                                                                          Math::transpose);
14562                         break;
14563                 case Utils::VARIABLE_TYPE_DMAT3:
14564                         return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14565                                                                                                                                                                  Math::transpose);
14566                         break;
14567                 case Utils::VARIABLE_TYPE_DMAT3X2:
14568                         return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14569                                                                                                                                                                          Math::transpose);
14570                         break;
14571                 case Utils::VARIABLE_TYPE_DMAT3X4:
14572                         return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14573                                                                                                                                                                          Math::transpose);
14574                         break;
14575                 case Utils::VARIABLE_TYPE_DMAT4:
14576                         return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14577                                                                                                                                                                  Math::transpose);
14578                         break;
14579                 case Utils::VARIABLE_TYPE_DMAT4X2:
14580                         return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14581                                                                                                                                                                          Math::transpose);
14582                         break;
14583                 case Utils::VARIABLE_TYPE_DMAT4X3:
14584                         return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14585                                                                                                                                                                          Math::transpose);
14586                         break;
14587                 default:
14588                         break;
14589                 }
14590
14591                 break;
14592
14593         case FUNCTION_TRUNC:
14594
14595                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14596                         function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14597
14598                 break;
14599
14600         case FUNCTION_UNPACKDOUBLE2X32:
14601
14602                 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14603                                                                                                                                                                                   Math::unpackDouble2x32);
14604
14605                 break;
14606
14607         case FUNCTION_ISNAN:
14608
14609                 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14610                         function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14611
14612                 break;
14613
14614         case FUNCTION_ISINF:
14615
14616                 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14617                         function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14618
14619                 break;
14620
14621         default:
14622                 TCU_FAIL("Not implemented");
14623                 return 0;
14624                 break;
14625         }
14626
14627         TCU_FAIL("Not implemented");
14628         return 0;
14629 }
14630
14631 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14632  *
14633  * @param argument        Argument index
14634  * @param function_object Function object
14635  *
14636  * @return Function pointer
14637  **/
14638 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14639         glw::GLuint argument, const functionObject& function_object) const
14640 {
14641         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14642         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14643
14644         switch (argument_type)
14645         {
14646         case Utils::VARIABLE_TYPE_DMAT2:
14647                 return gl.uniformMatrix2dv;
14648                 break;
14649         case Utils::VARIABLE_TYPE_DMAT2X3:
14650                 return gl.uniformMatrix2x3dv;
14651                 break;
14652         case Utils::VARIABLE_TYPE_DMAT2X4:
14653                 return gl.uniformMatrix2x4dv;
14654                 break;
14655         case Utils::VARIABLE_TYPE_DMAT3:
14656                 return gl.uniformMatrix3dv;
14657                 break;
14658         case Utils::VARIABLE_TYPE_DMAT3X2:
14659                 return gl.uniformMatrix3x2dv;
14660                 break;
14661         case Utils::VARIABLE_TYPE_DMAT3X4:
14662                 return gl.uniformMatrix3x4dv;
14663                 break;
14664         case Utils::VARIABLE_TYPE_DMAT4:
14665                 return gl.uniformMatrix4dv;
14666                 break;
14667         case Utils::VARIABLE_TYPE_DMAT4X2:
14668                 return gl.uniformMatrix4x2dv;
14669                 break;
14670         case Utils::VARIABLE_TYPE_DMAT4X3:
14671                 return gl.uniformMatrix4x3dv;
14672                 break;
14673         default:
14674                 break;
14675         }
14676
14677         TCU_FAIL("Not implemented");
14678         return 0;
14679 }
14680
14681 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14682  *
14683  * @param argument        Argument index
14684  * @param function_object Function object
14685  *
14686  * @return Function pointer
14687  **/
14688 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14689         glw::GLuint argument, const functionObject& function_object) const
14690 {
14691         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14692         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14693
14694         switch (argument_type)
14695         {
14696         case Utils::VARIABLE_TYPE_DOUBLE:
14697                 return gl.uniform1dv;
14698                 break;
14699         case Utils::VARIABLE_TYPE_DVEC2:
14700                 return gl.uniform2dv;
14701                 break;
14702         case Utils::VARIABLE_TYPE_DVEC3:
14703                 return gl.uniform3dv;
14704                 break;
14705         case Utils::VARIABLE_TYPE_DVEC4:
14706                 return gl.uniform4dv;
14707                 break;
14708         default:
14709                 TCU_FAIL("Not implemented");
14710                 break;
14711         }
14712
14713         return 0;
14714 }
14715
14716 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14717  *
14718  * @param argument        Argument index
14719  * @param function_object Function object
14720  *
14721  * @return Function pointer
14722  **/
14723 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14724         glw::GLuint argument, const functionObject& function_object) const
14725 {
14726         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14727         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14728
14729         switch (argument_type)
14730         {
14731         case Utils::VARIABLE_TYPE_INT:
14732                 return gl.uniform1iv;
14733                 break;
14734         case Utils::VARIABLE_TYPE_IVEC2:
14735                 return gl.uniform2iv;
14736                 break;
14737         case Utils::VARIABLE_TYPE_IVEC3:
14738                 return gl.uniform3iv;
14739                 break;
14740         case Utils::VARIABLE_TYPE_IVEC4:
14741                 return gl.uniform4iv;
14742                 break;
14743         default:
14744                 TCU_FAIL("Not implemented");
14745                 break;
14746         }
14747
14748         return 0;
14749 }
14750
14751 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14752  *
14753  * @param argument        Argument index
14754  * @param function_object Function object
14755  *
14756  * @return Function pointer
14757  **/
14758 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14759         glw::GLuint argument, const functionObject& function_object) const
14760 {
14761         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14762         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14763
14764         switch (argument_type)
14765         {
14766         case Utils::VARIABLE_TYPE_UVEC2:
14767                 return gl.uniform2uiv;
14768                 break;
14769         default:
14770                 TCU_FAIL("Not implemented");
14771                 break;
14772         }
14773
14774         return 0;
14775 }
14776
14777 /** Get name of uniform that will be used as <argument>.
14778  *
14779  * @param argument Argument index
14780  *
14781  * @return Name of uniform
14782  **/
14783 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14784 {
14785         switch (argument)
14786         {
14787         case 0:
14788                 return "uniform_0";
14789                 break;
14790         case 1:
14791                 return "uniform_1";
14792                 break;
14793         case 2:
14794                 return "uniform_2";
14795                 break;
14796         default:
14797                 TCU_FAIL("Not implemented");
14798                 return 0;
14799                 break;
14800         }
14801 }
14802
14803 /** Get name of varying that will be used as <result>.
14804  *
14805  * @param result Result index
14806  *
14807  * @return Name of varying
14808  **/
14809 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14810 {
14811         switch (result)
14812         {
14813         case 0:
14814                 return "result_0";
14815                 break;
14816         case 1:
14817                 return "result_1";
14818                 break;
14819         case 2:
14820                 return "result_2";
14821                 break;
14822         default:
14823                 TCU_FAIL("Not implemented");
14824                 return 0;
14825                 break;
14826         }
14827 }
14828
14829 /** Check if given combination of function and type is implemented
14830  *
14831  * @param function Function enumeration
14832  * @param type     Type details
14833  *
14834  * @return true if function is available for given type, false otherwise
14835  **/
14836 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14837 {
14838         static const bool look_up_table[][3] = {
14839                 /* SCALAR, VECTOR, MATRIX */
14840                 /* FUNCTION_ABS:                       */ { true, true, false },
14841                 /* FUNCTION_CEIL:                      */ { true, true, false },
14842                 /* FUNCTION_CLAMP:                     */ { true, true, false },
14843                 /* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14844                 /* FUNCTION_CROSS:                     */ { false, true, false },
14845                 /* FUNCTION_DETERMINANT:               */ { false, false, true },
14846                 /* FUNCTION_DISTANCE:                  */ { false, true, false },
14847                 /* FUNCTION_DOT:                       */ { false, true, false },
14848                 /* FUNCTION_EQUAL:                     */ { false, true, false },
14849                 /* FUNCTION_FACEFORWARD:               */ { false, true, false },
14850                 /* FUNCTION_FLOOR:                     */ { true, true, false },
14851                 /* FUNCTION_FMA:                       */ { true, true, false },
14852                 /* FUNCTION_FRACT:                     */ { true, true, false },
14853                 /* FUNCTION_FREXP:                     */ { true, true, false },
14854                 /* FUNCTION_GREATERTHAN:               */ { false, true, false },
14855                 /* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14856                 /* FUNCTION_INVERSE:                   */ { false, false, true },
14857                 /* FUNCTION_INVERSESQRT:               */ { true, true, false },
14858                 /* FUNCTION_LDEXP:                     */ { true, true, false },
14859                 /* FUNCTION_LESSTHAN:                  */ { false, true, false },
14860                 /* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14861                 /* FUNCTION_LENGTH:                    */ { false, true, false },
14862                 /* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14863                 /* FUNCTION_MAX:                       */ { true, true, false },
14864                 /* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14865                 /* FUNCTION_MIN:                       */ { true, true, false },
14866                 /* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14867                 /* FUNCTION_MIX:                       */ { true, true, false },
14868                 /* FUNCTION_MOD:                       */ { true, true, false },
14869                 /* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14870                 /* FUNCTION_MODF:                      */ { true, true, false },
14871                 /* FUNCTION_NORMALIZE:                 */ { false, true, false },
14872                 /* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14873                 /* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14874                 /* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14875                 /* FUNCTION_REFLECT:                   */ { false, true, false },
14876                 /* FUNCTION_REFRACT:                   */ { false, true, false },
14877                 /* FUNCTION_ROUND:                     */ { true, true, false },
14878                 /* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14879                 /* FUNCTION_SIGN:                      */ { true, false, false },
14880                 /* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14881                 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14882                 /* FUNCTION_SQRT:                      */ { true, true, false },
14883                 /* FUNCTION_STEP:                      */ { true, true, false },
14884                 /* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14885                 /* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14886                 /* FUNCTION_TRUNC:                     */ { true, true, false },
14887                 /* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14888                 /* FUNCTION_ISNAN:                     */ { true, true, false },
14889                 /* FUNCTION_ISINF:                     */ { true, true, false },
14890         };
14891
14892         bool result = look_up_table[function][type.m_general_type];
14893
14894         if (true == result)
14895         {
14896                 switch (function)
14897                 {
14898                 case FUNCTION_CROSS: /* Only 3 element vectors */
14899                         result = (3 == type.m_n_rows);
14900                         break;
14901                 case FUNCTION_DETERMINANT: /* Only square matrices */
14902                 case FUNCTION_INVERSE:
14903                         result = (type.m_n_columns == type.m_n_rows);
14904                         break;
14905                 default:
14906                         break;
14907                 }
14908         }
14909
14910         return result;
14911 }
14912
14913 /** Logs variable of given type: name (type) [values]
14914  *
14915  * @param buffer Source of data
14916  * @param name   Name of variable
14917  * @param type   Type of variable
14918  **/
14919 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14920                                                                                   Utils::_variable_type type) const
14921 {
14922         const Utils::_variable_type base_type   = Utils::getBaseVariableType(type);
14923         const glw::GLuint                       n_components = Utils::getNumberOfComponentsForVariableType(type);
14924         tcu::MessageBuilder                     message          = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14925
14926         message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14927
14928         for (glw::GLuint component = 0; component < n_components; ++component)
14929         {
14930                 if (0 != component)
14931                 {
14932                         message << ", ";
14933                 }
14934
14935                 switch (base_type)
14936                 {
14937                 case Utils::VARIABLE_TYPE_DOUBLE:
14938                         message << ((glw::GLdouble*)buffer)[component];
14939                         break;
14940                 case Utils::VARIABLE_TYPE_INT:
14941                         message << ((glw::GLint*)buffer)[component];
14942                         break;
14943                 case Utils::VARIABLE_TYPE_UINT:
14944                         message << ((glw::GLuint*)buffer)[component];
14945                         break;
14946                 default:
14947                         TCU_FAIL("Not implemented");
14948                 }
14949         }
14950
14951         message << "]" << tcu::TestLog::EndMessage;
14952 }
14953
14954 /** Prepare input arguments, data are stored in <buffer>
14955  *
14956  * @param function_object Function object
14957  * @param vertex          Vertex index
14958  * @param buffer          Buffer pointer
14959  **/
14960 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14961                                                                                   glw::GLubyte* buffer)
14962 {
14963         const glw::GLuint n_arguments = function_object.getArgumentCount();
14964
14965         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14966         {
14967                 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14968
14969                 prepareComponents(function_object, vertex, argument, buffer + offset);
14970         }
14971 }
14972
14973 /** Prepare components for given <function_object>, <vertex> and <argument>
14974  *
14975  * @param function_object Function object
14976  * @param vertex          Vertex index
14977  * @param argument        Argument index
14978  * @param buffer          Buffer pointer
14979  **/
14980 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14981                                                                                         glw::GLuint argument, glw::GLubyte* buffer)
14982 {
14983         glw::GLuint                                     argument_index[3]                = { 0 };
14984         glw::GLuint                                     argument_reset[3]                = { 0 };
14985         glw::GLuint                                     argument_step[3]                 = { 0 };
14986         glw::GLdouble                           double_argument_start[3] = { 0.0 };
14987         const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14988         glw::GLuint                                     int_argument_start  = -4;
14989         const glw::GLuint                       n_arguments                     = function_object.getArgumentCount();
14990         const glw::GLuint                       n_components            = function_object.getArgumentComponents(argument);
14991         glw::GLuint                                     uint_argument_start = 0;
14992
14993         switch (n_arguments)
14994         {
14995         case 1:
14996                 argument_step[0]                 = 1;
14997                 argument_reset[0]                = 1024;
14998                 double_argument_start[0] = -511.5;
14999                 break;
15000         case 2:
15001                 argument_step[0]                 = 32;
15002                 argument_step[1]                 = 1;
15003                 argument_reset[0]                = 32;
15004                 argument_reset[1]                = 32;
15005                 double_argument_start[0] = -15.5;
15006                 double_argument_start[1] = -15.5;
15007                 break;
15008         case 3:
15009                 argument_step[0]                 = 64;
15010                 argument_step[1]                 = 8;
15011                 argument_step[2]                 = 1;
15012                 argument_reset[0]                = 16;
15013                 argument_reset[1]                = 8;
15014                 argument_reset[2]                = 8;
15015                 double_argument_start[0] = -7.5;
15016                 double_argument_start[1] = -3.5;
15017                 double_argument_start[2] = -3.5;
15018                 break;
15019         default:
15020                 TCU_FAIL("Not implemented");
15021                 return;
15022                 break;
15023         };
15024
15025         switch (function_object.getFunctionEnum())
15026         {
15027         case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
15028         case FUNCTION_CLAMP_AGAINST_SCALAR:
15029                 double_argument_start[2] = 4.5;
15030                 break;
15031         case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
15032                 double_argument_start[0] = 16.5;
15033                 break;
15034         case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
15035         case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
15036                 argument_step[0]                 = 1;
15037                 argument_step[1]                 = 8;
15038                 argument_step[2]                 = 64;
15039                 argument_reset[0]                = 8;
15040                 argument_reset[1]                = 8;
15041                 argument_reset[2]                = 16;
15042                 double_argument_start[0] = -3.5;
15043                 double_argument_start[1] = 4.5;
15044                 double_argument_start[2] = -7.5;
15045                 break;
15046         default:
15047                 break;
15048         }
15049
15050         for (glw::GLuint i = 0; i < n_arguments; ++i)
15051         {
15052                 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
15053         }
15054
15055         switch (base_arg_type)
15056         {
15057         case Utils::VARIABLE_TYPE_DOUBLE:
15058         {
15059                 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
15060
15061                 double_argument_start[argument] += argument_index[argument];
15062
15063                 for (glw::GLuint component = 0; component < n_components; ++component)
15064                 {
15065                         glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
15066
15067                         switch (function_object.getFunctionEnum())
15068                         {
15069                         case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
15070                                 if (0.5 == Math::fract(value))
15071                                 {
15072                                         value += 0.01;
15073                                 }
15074                                 break;
15075                         default:
15076                                 break;
15077                         }
15078
15079                         argument_dst[component] = value;
15080                 }
15081         }
15082         break;
15083         case Utils::VARIABLE_TYPE_INT:
15084         {
15085                 glw::GLint* argument_dst = (glw::GLint*)buffer;
15086
15087                 uint_argument_start += argument_index[argument];
15088
15089                 for (glw::GLuint component = 0; component < n_components; ++component)
15090                 {
15091                         const glw::GLint value = int_argument_start + component;
15092
15093                         argument_dst[component] = value;
15094                 }
15095         }
15096         break;
15097         case Utils::VARIABLE_TYPE_UINT:
15098         {
15099                 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
15100
15101                 uint_argument_start += argument_index[argument];
15102
15103                 for (glw::GLuint component = 0; component < n_components; ++component)
15104                 {
15105                         const glw::GLuint value = uint_argument_start + component;
15106
15107                         argument_dst[component] = value;
15108                 }
15109         }
15110         break;
15111         default:
15112                 TCU_FAIL("Not implemented");
15113                 return;
15114                 break;
15115         }
15116 }
15117
15118 /** Prepare programInfo for given functionObject
15119  *
15120  * @param function_object  Function object
15121  * @param out_program_info Program info
15122  **/
15123 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
15124 {
15125         const glw::GLuint                 n_varying_names  = function_object.getResultCount();
15126         static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
15127
15128         prepareVertexShaderCode(function_object);
15129
15130         out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
15131                                                    varying_names, n_varying_names);
15132 }
15133
15134 /** Prepare input data and expected results for given function object
15135  *
15136  * @param function_object Function object
15137  **/
15138 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
15139 {
15140         const glw::GLuint result_stride            = function_object.getResultStride();
15141         const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
15142         const glw::GLuint argument_stride         = function_object.getArgumentStride();
15143         const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
15144
15145         m_argument_data.clear();
15146         m_expected_results_data.clear();
15147
15148         m_argument_data.resize(argument_buffer_size);
15149         m_expected_results_data.resize(result_buffer_size);
15150
15151         for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15152         {
15153                 const glw::GLuint result_offset   = vertex * result_stride;
15154                 glw::GLdouble*  result_dst        = (glw::GLdouble*)&m_expected_results_data[result_offset];
15155                 const glw::GLuint argument_offset = vertex * argument_stride;
15156                 glw::GLubyte*    argument_dst   = &m_argument_data[argument_offset];
15157
15158                 prepareArgument(function_object, vertex, argument_dst);
15159                 function_object.call(result_dst, argument_dst);
15160         }
15161 }
15162
15163 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
15164  *
15165  * @param function_object Function object
15166  **/
15167 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
15168 {
15169         static const glw::GLchar* shader_template_code = "#version 400 core\n"
15170                                                                                                          "\n"
15171                                                                                                          "precision highp float;\n"
15172                                                                                                          "\n"
15173                                                                                                          "ARGUMENT_DEFINITION"
15174                                                                                                          "\n"
15175                                                                                                          "RESULT_DEFINITION"
15176                                                                                                          "\n"
15177                                                                                                          "void main()\n"
15178                                                                                                          "{\n"
15179                                                                                                          "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
15180                                                                                                          "}\n"
15181                                                                                                          "\n";
15182
15183         static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15184         static const glw::GLchar* argument_token                        = "ARGUMENT";
15185         static const glw::GLchar* function_name_token           = "FUNCTION_NAME";
15186         static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15187         static const glw::GLchar* result_name_token                     = "RESULT_NAME";
15188         static const glw::GLchar* result_type_token                     = "RESULT_TYPE";
15189         static const glw::GLchar* uniform_name_token            = "UNIFORM_NAME";
15190         static const glw::GLchar* uniform_type_token            = "UNIFORM_TYPE";
15191
15192         static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15193         static const glw::GLchar* argument_str            = ", UNIFORM_NAMEARGUMENT";
15194         static const glw::GLchar* first_argument          = "UNIFORM_NAMEARGUMENT";
15195         static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15196
15197         const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15198         const glw::GLuint first_argument_length          = (glw::GLuint)strlen(first_argument);
15199         const glw::GLuint n_arguments                            = function_object.getArgumentCount();
15200         const glw::GLuint n_results                                      = function_object.getResultCount();
15201         const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15202         std::string               result_type                            = Utils::getVariableTypeString(function_object.getResultType(0));
15203
15204         size_t          search_position = 0;
15205         std::string string                      = shader_template_code;
15206
15207         /* Replace ARGUMENT_DEFINITION with definitions */
15208         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15209         {
15210                 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15211                 const glw::GLchar*      uniform_name  = getUniformName(argument);
15212                 std::string                       uniform_type  = Utils::getVariableTypeString(argument_type);
15213
15214                 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15215
15216                 search_position -= argument_definition_length;
15217
15218                 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15219                 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15220         }
15221
15222         /* Remove ARGUMENT_DEFINITION */
15223         Utils::replaceToken(argument_definition_token, search_position, "", string);
15224
15225         /* Replace RESULT_DEFINITION with definitions */
15226         for (glw::GLuint result = 0; result < n_results; ++result)
15227         {
15228                 Utils::_variable_type variable_type = function_object.getResultType(result);
15229                 const glw::GLchar*      varying_name  = getVaryingName(result);
15230                 std::string                       varying_type  = Utils::getVariableTypeString(variable_type);
15231
15232                 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15233
15234                 search_position -= result_definition_length;
15235
15236                 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15237                 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15238         }
15239
15240         /* Remove RESULT_DEFINITION */
15241         Utils::replaceToken(result_definition_token, search_position, "", string);
15242
15243         /* Replace RESULT_NAME */
15244         Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15245
15246         /* Replace RESULT_TYPE */
15247         Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15248
15249         /* Replace FUNCTION_NAME */
15250         Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15251
15252         /* Replace ARGUMENT with list of arguments */
15253         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15254         {
15255                 const glw::GLchar* uniform_name = getUniformName(argument);
15256
15257                 if (0 == argument)
15258                 {
15259                         Utils::replaceToken(argument_token, search_position, first_argument, string);
15260                 }
15261                 else
15262                 {
15263                         Utils::replaceToken(argument_token, search_position, argument_str, string);
15264                 }
15265
15266                 search_position -= first_argument_length;
15267
15268                 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15269         }
15270
15271         for (glw::GLuint result = 1; result < n_results; ++result)
15272         {
15273                 const glw::GLchar* varying_name = getVaryingName(result);
15274
15275                 Utils::replaceToken(argument_token, search_position, argument_str, string);
15276
15277                 search_position -= first_argument_length;
15278
15279                 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15280         }
15281
15282         /* Remove ARGUMENT */
15283         Utils::replaceToken(argument_token, search_position, "", string);
15284
15285         m_vertex_shader_code = string;
15286 }
15287
15288 /** Test single function with one type
15289  *
15290  * param function Function enumeration
15291  * param type     Type details
15292  *
15293  * @return true if test pass (or function is not available for <type>), false otherwise
15294  **/
15295 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15296 {
15297         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15298
15299         /* Skip if function is not implemented for type */
15300         if (false == isFunctionImplemented(function, type))
15301         {
15302                 return true;
15303         }
15304
15305         Utils::programInfo                        program(m_context);
15306         de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15307
15308         prepareProgram(*function_object, program);
15309         prepareTestData(*function_object);
15310
15311         /* Set up program */
15312         gl.useProgram(program.m_program_object_id);
15313         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15314
15315         for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15316         {
15317                 testBegin(*function_object, program.m_program_object_id, vertex);
15318
15319                 gl.beginTransformFeedback(GL_POINTS);
15320                 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15321
15322                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15323                 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15324
15325                 gl.endTransformFeedback();
15326                 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15327
15328                 if (false == verifyResults(*function_object, vertex))
15329                 {
15330                         return false;
15331                 }
15332         }
15333
15334         return true;
15335 }
15336
15337 /** Update transform feedback buffer and uniforms
15338  *
15339  * @param function_object Function object
15340  * @param program_id      Program object id
15341  * @param vertex          Vertex index
15342  **/
15343 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15344 {
15345         const glw::GLuint        arguments_stride   = function_object.getArgumentStride();
15346         const glw::Functions& gl                                 = m_context.getRenderContext().getFunctions();
15347         const glw::GLuint        n_arguments             = function_object.getArgumentCount();
15348         const glw::GLuint        result_buffer_size = function_object.getResultStride();
15349         const glw::GLuint        vertex_offset           = arguments_stride * vertex;
15350
15351         /* Update transform feedback buffer */
15352         std::vector<glw::GLubyte> transform_feedback_buffer_data;
15353         transform_feedback_buffer_data.resize(result_buffer_size);
15354
15355         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15356         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15357
15358         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15359                                   GL_DYNAMIC_COPY);
15360         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15361
15362         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15363                                            result_buffer_size);
15364         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15365
15366         /* Update VAO */
15367         gl.bindVertexArray(m_vertex_array_object_id);
15368         GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15369
15370         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15371         {
15372                 const glw::GLuint                       argument_offset  = function_object.getArgumentOffset(argument);
15373                 const Utils::_variable_type argument_type       = function_object.getArgumentType(argument);
15374                 const glw::GLuint                       n_columns                = Utils::getNumberOfColumnsForVariableType(argument_type);
15375                 const glw::GLchar*                      uniform_name     = getUniformName(argument);
15376                 const glw::GLint                        uniform_location = gl.getUniformLocation(program_id, uniform_name);
15377                 const glw::GLdouble*            uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15378
15379                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15380
15381                 if (-1 == uniform_location)
15382                 {
15383                         TCU_FAIL("Inactive uniform");
15384                 }
15385
15386                 if (1 == n_columns)
15387                 {
15388                         switch (Utils::getBaseVariableType(argument_type))
15389                         {
15390                         case Utils::VARIABLE_TYPE_DOUBLE:
15391                         {
15392                                 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15393
15394                                 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15395                         }
15396                         break;
15397                         case Utils::VARIABLE_TYPE_UINT:
15398                         {
15399                                 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15400
15401                                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15402                         }
15403                         break;
15404                         case Utils::VARIABLE_TYPE_INT:
15405                         {
15406                                 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15407
15408                                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15409                         }
15410                         break;
15411                         default:
15412                                 TCU_FAIL("Not implemented");
15413                                 break;
15414                         }
15415                 }
15416                 else
15417                 {
15418                         uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15419
15420                         p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15421                 }
15422         }
15423 }
15424
15425 /** Init GL obejcts
15426  *
15427  **/
15428 void BuiltinFunctionTest::testInit()
15429 {
15430         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15431
15432         gl.genBuffers(1, &m_transform_feedback_buffer_id);
15433         GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15434
15435         gl.genVertexArrays(1, &m_vertex_array_object_id);
15436         GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15437
15438         gl.enable(GL_RASTERIZER_DISCARD);
15439 }
15440
15441 /** Compare contents of transform feedback buffer with expected results
15442  *
15443  * @param function_object Function object
15444  * @param vertex          Vertex index
15445  *
15446  * @return true if all results are as expected, false otherwise
15447  **/
15448 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15449 {
15450         const glw::Functions& gl                           = m_context.getRenderContext().getFunctions();
15451         bool                              test_result     = true;
15452         const glw::GLuint        n_results                 = function_object.getResultCount();
15453         const glw::GLuint        results_stride   = function_object.getResultStride();
15454         const glw::GLuint        results_offset   = vertex * results_stride;
15455         const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15456
15457         /* Get transform feedback data */
15458         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15459         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15460
15461         glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15462         GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15463
15464         for (glw::GLuint result = 0; result < n_results; ++result)
15465         {
15466                 const Utils::_variable_type result_type   = function_object.getResultType(result);
15467                 const glw::GLuint                       result_offset = function_object.getResultOffset(result);
15468
15469                 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15470                 const glw::GLvoid* result_src              = feedback_data + result_offset;
15471
15472                 if (false == compare(result_type, expected_result_src, result_src))
15473                 {
15474                         test_result = false;
15475                         break;
15476                 }
15477         }
15478
15479         /* Unmap transform feedback buffer */
15480         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15481         GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15482
15483         if (false == test_result)
15484         {
15485                 const glw::GLuint argument_stride  = function_object.getArgumentStride();
15486                 const glw::GLuint arguments_offset = vertex * argument_stride;
15487
15488                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15489                                                                                         << tcu::TestLog::EndMessage;
15490
15491                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15492                                                                                         << tcu::TestLog::EndMessage;
15493
15494                 for (glw::GLuint result = 0; result < n_results; ++result)
15495                 {
15496                         const Utils::_variable_type result_type   = function_object.getResultType(result);
15497                         const glw::GLuint                       result_offset = function_object.getResultOffset(result);
15498
15499                         const glw::GLvoid* expected_result_src = expected_results + result_offset;
15500                         const glw::GLvoid* result_src              = feedback_data + result_offset;
15501
15502                         logVariableType(result_src, "Result", result_type);
15503                         logVariableType(expected_result_src, "Expected result", result_type);
15504                 }
15505
15506                 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15507                 {
15508                         const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15509                         const glw::GLubyte* argument_src        = &m_argument_data[arguments_offset + argument_offset];
15510
15511                         logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15512                 }
15513
15514                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15515                                                                                         << m_vertex_shader_code << tcu::TestLog::EndMessage;
15516         }
15517
15518         return test_result;
15519 }
15520
15521 /** Constructor.
15522  *
15523  *  @param context Rendering context.
15524  **/
15525 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15526         : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15527 {
15528         /* Left blank on purpose */
15529 }
15530
15531 /** Initializes a texture_storage_multisample test group.
15532  *
15533  **/
15534 void GPUShaderFP64Tests::init(void)
15535 {
15536         TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15537         fp64->addChild(new GPUShaderFP64Test1(m_context));
15538         fp64->addChild(new GPUShaderFP64Test2(m_context));
15539         fp64->addChild(new GPUShaderFP64Test3(m_context));
15540         fp64->addChild(new GPUShaderFP64Test4(m_context));
15541         fp64->addChild(new GPUShaderFP64Test5(m_context));
15542         fp64->addChild(new GPUShaderFP64Test6(m_context));
15543         fp64->addChild(new GPUShaderFP64Test7(m_context));
15544         fp64->addChild(new GPUShaderFP64Test8(m_context));
15545         fp64->addChild(new GPUShaderFP64Test9(m_context));
15546         addChild(fp64);
15547
15548         TypeDefinition typeDefinition[] =
15549         {
15550                 { "double",  1, 1 },
15551                 { "dvec2",   1, 2 },
15552                 { "dvec3",   1, 3 },
15553                 { "dvec4",   1, 4 },
15554                 { "dmat2",   2, 2 },
15555                 { "dmat2x3", 2, 3 },
15556                 { "dmat2x4", 2, 4 },
15557                 { "dmat3x2", 3, 2 },
15558                 { "dmat3",   3, 3 },
15559                 { "dmat3x4", 3, 4 },
15560                 { "dmat4x2", 4, 2 },
15561                 { "dmat4x3", 4, 3 },
15562                 { "dmat4",   4, 4 }
15563         };
15564
15565         struct BuiltinFunctions
15566         {
15567                 std::string  name;
15568                 FunctionEnum function;
15569         } builtinFunctions[] = {
15570                 { "abs",                                                FUNCTION_ABS },
15571                 { "ceil",                                               FUNCTION_CEIL },
15572                 { "clamp",                                              FUNCTION_CLAMP },
15573                 { "clamp_against_scalar",               FUNCTION_CLAMP_AGAINST_SCALAR },
15574                 { "cross",                                              FUNCTION_CROSS },
15575                 { "determinant",                                FUNCTION_DETERMINANT },
15576                 { "distance",                                   FUNCTION_DISTANCE },
15577                 { "dot",                                                FUNCTION_DOT },
15578                 { "equal",                                              FUNCTION_EQUAL },
15579                 { "faceforward",                                FUNCTION_FACEFORWARD },
15580                 { "floor",                                              FUNCTION_FLOOR },
15581                 { "fma",                                                FUNCTION_FMA },
15582                 { "fract",                                              FUNCTION_FRACT },
15583                 { "frexp",                                              FUNCTION_FREXP },
15584                 { "greaterthan",                                FUNCTION_GREATERTHAN },
15585                 { "greaterthanequal",                   FUNCTION_GREATERTHANEQUAL },
15586                 { "inverse",                                    FUNCTION_INVERSE },
15587                 { "inversesqrt",                                FUNCTION_INVERSESQRT },
15588                 { "ldexp",                                              FUNCTION_LDEXP },
15589                 { "lessthan",                                   FUNCTION_LESSTHAN },
15590                 { "lessthanequal",                              FUNCTION_LESSTHANEQUAL },
15591                 { "length",                                             FUNCTION_LENGTH },
15592                 { "matrixcompmult",                             FUNCTION_MATRIXCOMPMULT },
15593                 { "max",                                                FUNCTION_MAX },
15594                 { "max_against_scalar",                 FUNCTION_MAX_AGAINST_SCALAR },
15595                 { "min",                                                FUNCTION_MIN },
15596                 { "min_against_scalar",                 FUNCTION_MIN_AGAINST_SCALAR },
15597                 { "mix",                                                FUNCTION_MIX },
15598                 { "mod",                                                FUNCTION_MOD },
15599                 { "mod_against_scalar",                 FUNCTION_MOD_AGAINST_SCALAR },
15600                 { "modf",                                               FUNCTION_MODF },
15601                 { "normalize",                                  FUNCTION_NORMALIZE },
15602                 { "notequal",                                   FUNCTION_NOTEQUAL },
15603                 { "outerproduct",                               FUNCTION_OUTERPRODUCT },
15604                 { "packdouble2x32",                             FUNCTION_PACKDOUBLE2X32 },
15605                 { "reflect",                                    FUNCTION_REFLECT },
15606                 { "refract",                                    FUNCTION_REFRACT },
15607                 { "round",                                              FUNCTION_ROUND },
15608                 { "roundeven",                                  FUNCTION_ROUNDEVEN },
15609                 { "sign",                                               FUNCTION_SIGN },
15610                 { "smoothstep",                                 FUNCTION_SMOOTHSTEP },
15611                 { "smoothstep_against_scalar",  FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15612                 { "sqrt",                                               FUNCTION_SQRT },
15613                 { "step",                                               FUNCTION_STEP },
15614                 { "step_against_scalar",                FUNCTION_STEP_AGAINST_SCALAR },
15615                 { "transpose",                                  FUNCTION_TRANSPOSE },
15616                 { "trunc",                                              FUNCTION_TRUNC },
15617                 { "unpackdouble2x32",                   FUNCTION_UNPACKDOUBLE2X32 },
15618                 { "isnan",                                              FUNCTION_ISNAN },
15619                 { "isinf",                                              FUNCTION_ISINF }
15620         };
15621
15622         TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15623         for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15624         {
15625                 const BuiltinFunctions& bf = builtinFunctions[i];
15626                 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15627                 {
15628                         std::string caseName = bf.name + "_" + typeDefinition[j].name;
15629                         builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15630                 }
15631         }
15632         addChild(builin);
15633 }
15634
15635 } /* glcts namespace */