5705435c91bdcbe94689442906b03108ed11c0da
[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 function objects required by "GPUShaderFP64Test10"
12167  *
12168  **/
12169 namespace FunctionObject
12170 {
12171 /** Maps variable type with enumeration Utils::_variable_type
12172  *
12173  * @tparam T type
12174  **/
12175 template <typename T>
12176 class typeInfo
12177 {
12178 public:
12179         static const Utils::_variable_type variable_type =
12180                 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12181 };
12182
12183 /** Place data from <in> into <buffer>
12184  *
12185  * @param buffer Buffer
12186  * @param in     Input data
12187  **/
12188 template <typename T>
12189 class pack
12190 {
12191 public:
12192         static void set(glw::GLvoid* buffer, const T& in)
12193         {
12194                 *(T*)buffer = in;
12195         }
12196 };
12197
12198 /** Place tcu::Matrix data from <in> into <buffer>
12199  *
12200  * @param buffer Buffer
12201  * @param in     Input data
12202  **/
12203 template <int Cols, int Rows>
12204 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
12205 {
12206 public:
12207         static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
12208         {
12209                 glw::GLdouble* data = (glw::GLdouble*)buffer;
12210
12211                 for (glw::GLint column = 0; column < Cols; ++column)
12212                 {
12213                         for (glw::GLint row = 0; row < Rows; ++row)
12214                         {
12215                                 glw::GLint index = column * Rows + row;
12216
12217                                 data[index] = in(row, column);
12218                         }
12219                 }
12220         }
12221 };
12222
12223 /** Get data of <out> from <buffer>
12224  *
12225  * @param buffer Buffer
12226  * @param out    Output data
12227  **/
12228 template <typename T>
12229 class unpack
12230 {
12231 public:
12232         static void get(const glw::GLvoid* buffer, T& out)
12233         {
12234                 out = *(T*)buffer;
12235         }
12236 };
12237
12238 /** Get tcu::Matrix data from <buffer>
12239  *
12240  * @param buffer Buffer
12241  * @param out    Output data
12242  **/
12243 template <int Cols, int Rows>
12244 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
12245 {
12246 public:
12247         static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
12248         {
12249                 const glw::GLdouble* data = (glw::GLdouble*)buffer;
12250
12251                 for (glw::GLint column = 0; column < Cols; ++column)
12252                 {
12253                         for (glw::GLint row = 0; row < Rows; ++row)
12254                         {
12255                                 glw::GLint index = column * Rows + row;
12256
12257                                 out(row, column) = data[index];
12258                         }
12259                 }
12260         }
12261 };
12262
12263 /** Base of unary function classes
12264  *
12265  **/
12266 class unaryBase : public GPUShaderFP64Test10::functionObject
12267 {
12268 public:
12269         unaryBase(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12270                           glw::GLvoid* function_pointer, const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
12271                 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
12272         {
12273         }
12274
12275         virtual glw::GLuint getArgumentCount() const
12276         {
12277                 return 1;
12278         }
12279
12280         virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
12281         {
12282                 return m_arg_type;
12283         }
12284
12285 protected:
12286         const Utils::_variable_type m_arg_type;
12287 };
12288
12289 /** Unary function class. It treats input argument as one variable.
12290  *
12291  * @tparam ResT Type of result
12292  * @tparam ArgT Type of argument
12293  **/
12294 template <typename ResT, typename ArgT>
12295 class unary : public unaryBase
12296 {
12297 public:
12298         typedef ResT (*functionPointer)(const ArgT&);
12299
12300         unary(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12301                   functionPointer function_pointer)
12302                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
12303                                         typeInfo<ArgT>::variable_type)
12304         {
12305         }
12306
12307         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12308         {
12309                 ResT result;
12310                 ArgT arg;
12311
12312                 unpack<ArgT>::get(argument_src, arg);
12313
12314                 functionPointer p_function = (functionPointer)m_p_function;
12315
12316                 result = p_function(arg);
12317
12318                 pack<ResT>::set(result_dst, result);
12319         }
12320 };
12321
12322 /** Unary function class. It treats input argument as separate components.
12323  *
12324  * @tparam ResT Type of result
12325  **/
12326 template <typename ResT>
12327 class unaryByComponent : public unaryBase
12328 {
12329 public:
12330         typedef ResT (*functionPointer)(glw::GLdouble);
12331
12332         unaryByComponent(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12333                                          functionPointer function_pointer, const Utils::_variable_type res_type,
12334                                          const Utils::_variable_type arg_type)
12335                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
12336         {
12337         }
12338
12339         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12340         {
12341                 glw::GLuint     n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
12342                 ResT*              p_result             = (ResT*)result_dst;
12343                 glw::GLdouble* p_arg            = (glw::GLdouble*)argument_src;
12344
12345                 functionPointer p_function = (functionPointer)m_p_function;
12346
12347                 for (glw::GLuint component = 0; component < n_components; ++component)
12348                 {
12349                         p_result[component] = p_function(p_arg[component]);
12350                 }
12351         }
12352 };
12353
12354 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
12355  *
12356  * @tparam ResT Type of result
12357  * @tparam ArgT Type of argument
12358  * @tparam OutT Type of output parameter
12359  **/
12360 template <typename ResT, typename ArgT, typename OutT>
12361 class unaryWithOutputByComponent : public unaryBase
12362 {
12363 public:
12364         typedef ResT (*functionPointer)(ArgT, OutT&);
12365
12366         unaryWithOutputByComponent(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12367                                                            functionPointer function_pointer, const Utils::_variable_type res_type,
12368                                                            const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
12369                 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
12370                 , m_out_type(out_type)
12371         {
12372         }
12373
12374         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12375         {
12376                 ResT* p_result = (ResT*)result_dst;
12377                 OutT* p_out     = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
12378                 ArgT* p_arg     = (ArgT*)argument_src;
12379
12380                 const glw::GLuint n_components_0 = getArgumentComponents(0);
12381                 const glw::GLuint n_components_1 = getResultComponents(1);
12382                 const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
12383
12384                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
12385                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
12386
12387                 functionPointer p_function = (functionPointer)m_p_function;
12388
12389                 for (glw::GLuint component = 0; component < n_components; ++component)
12390                 {
12391                         const ArgT first_arg  = p_arg[component * component_step_0];
12392                         OutT&     second_arg = p_out[component * component_step_1];
12393
12394                         p_result[component] = p_function(first_arg, second_arg);
12395                 }
12396         }
12397
12398         glw::GLuint getResultCount() const
12399         {
12400                 return 2;
12401         }
12402
12403         Utils::_variable_type getResultType(glw::GLuint result) const
12404         {
12405                 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
12406
12407                 switch (result)
12408                 {
12409                 case 0:
12410                         type = m_res_type;
12411                         break;
12412                 case 1:
12413                         type = m_out_type;
12414                         break;
12415                 default:
12416                         TCU_FAIL("Not implemented");
12417                         break;
12418                 }
12419
12420                 return type;
12421         }
12422
12423 protected:
12424         const Utils::_variable_type m_out_type;
12425 };
12426
12427 /** Base of binary function classes.
12428  *
12429  **/
12430 class binaryBase : public GPUShaderFP64Test10::functionObject
12431 {
12432 public:
12433         binaryBase(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12434                            glw::GLvoid* function_pointer, const Utils::_variable_type res_type,
12435                            const Utils::_variable_type arg_1_type, const Utils::_variable_type arg_2_type)
12436                 : functionObject(function_enum, function_name, function_pointer, res_type)
12437                 , m_arg_1_type(arg_1_type)
12438                 , m_arg_2_type(arg_2_type)
12439         {
12440         }
12441
12442         virtual glw::GLuint getArgumentCount() const
12443         {
12444                 return 2;
12445         }
12446
12447         virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
12448         {
12449                 switch (argument)
12450                 {
12451                 case 0:
12452                         return m_arg_1_type;
12453                         break;
12454                 case 1:
12455                         return m_arg_2_type;
12456                         break;
12457                 default:
12458                         return Utils::VARIABLE_TYPE_UNKNOWN;
12459                         break;
12460                 }
12461         }
12462
12463 protected:
12464         const Utils::_variable_type m_arg_1_type;
12465         const Utils::_variable_type m_arg_2_type;
12466 };
12467
12468 /** Binary function class. It treats input arguments as two variables.
12469  *
12470  * @param ResT  Type of result
12471  * @param Arg1T Type of first argument
12472  * @param Arg2T Type of second argument
12473  **/
12474 template <typename ResT, typename Arg1T, typename Arg2T>
12475 class binary : public binaryBase
12476 {
12477 public:
12478         typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
12479
12480         binary(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12481                    functionPointer function_pointer)
12482                 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
12483                                          typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
12484         {
12485         }
12486
12487         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12488         {
12489                 const glw::GLuint argument_1_stride = getArgumentStride(0);
12490
12491                 functionPointer p_function = (functionPointer)m_p_function;
12492
12493                 Arg1T arg_1;
12494                 Arg2T arg_2;
12495                 ResT  result;
12496
12497                 unpack<Arg1T>::get(argument_src, arg_1);
12498                 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
12499
12500                 result = p_function(arg_1, arg_2);
12501
12502                 pack<ResT>::set(result_dst, result);
12503         }
12504 };
12505
12506 /** Binary function class. It treats input arguments as separate components.
12507  *
12508  * @param ResT  Type of result
12509  * @param Arg1T Type of first argument
12510  * @param Arg2T Type of second argument
12511  **/
12512 template <typename ResT, typename Arg1T, typename Arg2T>
12513 class binaryByComponent : public binaryBase
12514 {
12515 public:
12516         typedef ResT (*functionPointer)(Arg1T, Arg2T);
12517
12518         binaryByComponent(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12519                                           functionPointer function_pointer, const Utils::_variable_type res_type,
12520                                           const Utils::_variable_type arg_1_type, const Utils::_variable_type arg_2_type)
12521                 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
12522         {
12523         }
12524
12525         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12526         {
12527                 ResT*  p_result = (ResT*)result_dst;
12528                 Arg1T* p_arg_1  = (Arg1T*)argument_src;
12529                 Arg2T* p_arg_2  = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
12530
12531                 const glw::GLuint n_components_0 = getArgumentComponents(0);
12532                 const glw::GLuint n_components_1 = getArgumentComponents(1);
12533                 const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
12534
12535                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
12536                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
12537
12538                 functionPointer p_function = (functionPointer)m_p_function;
12539
12540                 for (glw::GLuint component = 0; component < n_components; ++component)
12541                 {
12542                         const Arg1T first_arg  = p_arg_1[component * component_step_0];
12543                         const Arg2T second_arg = p_arg_2[component * component_step_1];
12544
12545                         p_result[component] = p_function(first_arg, second_arg);
12546                 }
12547         }
12548 };
12549
12550 /** Base of tenary function classes.
12551  *
12552  **/
12553 class tenaryBase : public GPUShaderFP64Test10::functionObject
12554 {
12555 public:
12556         tenaryBase(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12557                            glw::GLvoid* function_pointer, const Utils::_variable_type res_type,
12558                            const Utils::_variable_type arg_1_type, const Utils::_variable_type arg_2_type,
12559                            const Utils::_variable_type arg_3_type)
12560                 : functionObject(function_enum, function_name, function_pointer, res_type)
12561                 , m_arg_1_type(arg_1_type)
12562                 , m_arg_2_type(arg_2_type)
12563                 , m_arg_3_type(arg_3_type)
12564         {
12565         }
12566
12567         virtual glw::GLuint getArgumentCount() const
12568         {
12569                 return 3;
12570         }
12571
12572         virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
12573         {
12574                 switch (argument)
12575                 {
12576                 case 0:
12577                         return m_arg_1_type;
12578                         break;
12579                 case 1:
12580                         return m_arg_2_type;
12581                         break;
12582                 case 2:
12583                         return m_arg_3_type;
12584                         break;
12585                 default:
12586                         return Utils::VARIABLE_TYPE_UNKNOWN;
12587                         break;
12588                 }
12589         }
12590
12591 protected:
12592         const Utils::_variable_type m_arg_1_type;
12593         const Utils::_variable_type m_arg_2_type;
12594         const Utils::_variable_type m_arg_3_type;
12595 };
12596
12597 /** Tenary function class. It treats input arguments as three variables.
12598  *
12599  * @param ResT  Type of result
12600  * @param Arg1T Type of first argument
12601  * @param Arg2T Type of second argument
12602  * @param Arg3T Type of third argument
12603  **/
12604 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
12605 class tenary : public tenaryBase
12606 {
12607 public:
12608         typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
12609         typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
12610         typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
12611         typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
12612
12613         tenary(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12614                    functionPointer function_pointer)
12615                 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
12616                                          typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
12617         {
12618         }
12619
12620         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12621         {
12622                 const glw::GLuint argument_2_offset = getArgumentOffset(1);
12623                 const glw::GLuint argument_3_offset = getArgumentOffset(2);
12624
12625                 functionPointer p_function = (functionPointer)m_p_function;
12626
12627                 arg1T arg_1;
12628                 arg2T arg_2;
12629                 arg3T arg_3;
12630                 ResT  result;
12631
12632                 unpack<arg1T>::get(argument_src, arg_1);
12633                 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
12634                 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
12635
12636                 result = p_function(arg_1, arg_2, arg_3);
12637
12638                 pack<ResT>::set(result_dst, result);
12639         }
12640 };
12641
12642 /** Tenary function class. It treats input arguments as separate components.
12643  *
12644
12645  **/
12646 class tenaryByComponent : public tenaryBase
12647 {
12648 public:
12649         typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
12650
12651         tenaryByComponent(GPUShaderFP64Test10::functionEnum function_enum, const glw::GLchar* function_name,
12652                                           functionPointer function_pointer, const Utils::_variable_type res_type,
12653                                           const Utils::_variable_type arg_1_type, const Utils::_variable_type arg_2_type,
12654                                           const Utils::_variable_type arg_3_type)
12655                 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
12656                                          arg_3_type)
12657         {
12658         }
12659
12660         virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
12661         {
12662                 glw::GLdouble*           p_result = (glw::GLdouble*)result_dst;
12663                 const glw::GLdouble* p_arg      = (const glw::GLdouble*)argument_src;
12664
12665                 const glw::GLuint n_components_0 = getArgumentComponents(0);
12666                 const glw::GLuint n_components_1 = getArgumentComponents(1);
12667                 const glw::GLuint n_components_2 = getArgumentComponents(2);
12668                 const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
12669
12670                 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
12671                 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
12672                 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
12673
12674                 functionPointer p_function = (functionPointer)m_p_function;
12675
12676                 for (glw::GLuint component = 0; component < n_components; ++component)
12677                 {
12678                         const glw::GLdouble first_arg  = p_arg[component * component_step_0];
12679                         const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
12680                         const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
12681
12682                         p_result[component] = p_function(first_arg, second_arg, third_arg);
12683                 }
12684         }
12685 };
12686 } /* FunctionObject */
12687
12688 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12689  *
12690  **/
12691 namespace Math
12692 {
12693 template <typename T>
12694 static T clamp(T x, T minVal, T maxVal);
12695
12696 template <int Size>
12697 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12698
12699 template <int Size>
12700 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12701
12702 template <typename T>
12703 static T determinant(T val);
12704
12705 template <typename T>
12706 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12707
12708 template <typename T>
12709 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12710
12711 template <typename T>
12712 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12713
12714 template <int Size>
12715 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12716                                                                                                                                 glw::GLuint column, glw::GLuint row);
12717
12718 template <int Size>
12719 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12720                                                                                         const tcu::Vector<glw::GLdouble, Size>& right);
12721
12722 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12723
12724 static glw::GLdouble fract(glw::GLdouble val);
12725
12726 template <typename T>
12727 static T frexp(T val, glw::GLint& exp);
12728
12729 template <int Size>
12730 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12731                                                                                                   const tcu::Vector<glw::GLdouble, Size>& right);
12732
12733 template <int Size>
12734 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12735                                                                                                            const tcu::Vector<glw::GLdouble, Size>& right);
12736
12737 template <int Size>
12738 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12739
12740 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12741
12742 static glw::GLuint isinf_impl(glw::GLdouble val);
12743
12744 static glw::GLuint isnan_impl(glw::GLdouble val);
12745
12746 template <typename T>
12747 static T ldexp(T val, glw::GLint exp);
12748
12749 template <int Size>
12750 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12751                                                                                            const tcu::Vector<glw::GLdouble, Size>& right);
12752
12753 template <int Size>
12754 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12755                                                                                                         const tcu::Vector<glw::GLdouble, Size>& right);
12756
12757 template <typename T>
12758 static T max(T left, T right);
12759
12760 template <typename T>
12761 static T min(T left, T right);
12762
12763 template <int            Size>
12764 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12765                                                                 glw::GLuint row);
12766
12767 template <typename T>
12768 static T mix(T left, T right, T weight);
12769
12770 template <typename T>
12771 static T mod(T left, T right);
12772
12773 template <typename T>
12774 static T modf(T val, T& integer);
12775
12776 template <typename T>
12777 static T multiply(T left, T right);
12778
12779 template <int Size>
12780 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12781                                                                                            const tcu::Vector<glw::GLdouble, Size>& right);
12782
12783 template <int Cols, int Rows>
12784 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12785                                                                                                                    const tcu::Vector<glw::GLdouble, Cols>& right);
12786
12787 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12788
12789 template <typename T>
12790 static T round(T t);
12791
12792 template <typename T>
12793 static T roundEven(T t);
12794
12795 template <typename T>
12796 static T sign(T t);
12797
12798 template <typename T>
12799 static T smoothStep(T e0, T e1, T val);
12800
12801 template <typename T>
12802 static T step(T edge, T val);
12803
12804 template <typename T, int Rows, int Cols>
12805 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12806
12807 template <typename T>
12808 static T trunc(T t);
12809
12810 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12811
12812 template <typename T>
12813 static T clamp(T x, T minVal, T maxVal)
12814 {
12815         return min(max(x, minVal), maxVal);
12816 }
12817
12818 template <int Size>
12819 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12820 {
12821         tcu::Matrix<glw::GLdouble, Size, Size> result;
12822
12823         for (glw::GLuint c = 0; c < Size; ++c)
12824         {
12825                 for (glw::GLuint r = 0; r < Size; ++r)
12826                 {
12827                         const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12828
12829                         result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12830                 }
12831         }
12832
12833         return result;
12834 }
12835
12836 template <int Size>
12837 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12838 {
12839         tcu::Vector<glw::GLuint, Size> result;
12840
12841         for (glw::GLint i = 0; i < Size; ++i)
12842         {
12843                 if (GL_FALSE != src[i])
12844                 {
12845                         result[i] = 1;
12846                 }
12847                 else
12848                 {
12849                         result[i] = 0;
12850                 }
12851         }
12852
12853         return result;
12854 }
12855
12856 template <typename T>
12857 static T det2(T _00, T _10, T _01, T _11)
12858 {
12859         return _00 * _11 - _01 * _10;
12860 }
12861
12862 template <typename T>
12863 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12864 {
12865         return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12866 }
12867
12868 template <typename T>
12869 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,
12870                           T _33)
12871 {
12872         return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12873                    _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12874                    _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12875                    _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12876 }
12877
12878 template <typename T>
12879 static T determinant(T val)
12880 {
12881         return val;
12882 }
12883
12884 template <typename T>
12885 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12886 {
12887         return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12888 }
12889
12890 template <typename T>
12891 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12892 {
12893         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));
12894 }
12895
12896 template <typename T>
12897 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12898 {
12899         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),
12900                                 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12901 }
12902
12903 template <int Size>
12904 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12905                                                                                                                                 glw::GLuint column, glw::GLuint row)
12906 {
12907         tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12908
12909         for (glw::GLuint c = 0; c < Size; ++c)
12910         {
12911                 /* Skip eliminated column */
12912                 if (column == c)
12913                 {
12914                         continue;
12915                 }
12916
12917                 for (glw::GLuint r = 0; r < Size; ++r)
12918                 {
12919                         /* Skip eliminated row */
12920                         if (row == r)
12921                         {
12922                                 continue;
12923                         }
12924
12925                         const glw::GLint r_offset = (r > row) ? -1 : 0;
12926                         const glw::GLint c_offset = (c > column) ? -1 : 0;
12927
12928                         result(r + r_offset, c + c_offset) = matrix(r, c);
12929                 }
12930         }
12931
12932         return result;
12933 }
12934
12935 template <int Size>
12936 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12937                                                                                         const tcu::Vector<glw::GLdouble, Size>& right)
12938 {
12939         return convertBvecToUvec(tcu::equal(left, right));
12940 }
12941
12942 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12943 {
12944         return a * b + c;
12945 }
12946
12947 static glw::GLdouble fract(glw::GLdouble val)
12948 {
12949         return val - floor(val);
12950 }
12951
12952 template <typename T>
12953 static T frexp(T val, glw::GLint& exp)
12954 {
12955         return ::frexp(val, &exp);
12956 }
12957
12958 template <int Size>
12959 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12960                                                                                                   const tcu::Vector<glw::GLdouble, Size>& right)
12961 {
12962         return convertBvecToUvec(tcu::greaterThan(left, right));
12963 }
12964
12965 template <int Size>
12966 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12967                                                                                                            const tcu::Vector<glw::GLdouble, Size>& right)
12968 {
12969         return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12970 }
12971
12972 template <int Size>
12973 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12974 {
12975         const tcu::Matrix<glw::GLdouble, Size, Size> cof          = cofactors(matrix);
12976         const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12977         const glw::GLdouble det         = determinant(matrix);
12978         const glw::GLdouble inv_det = 1.0 / det;
12979
12980         tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12981
12982         return result;
12983 }
12984
12985 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12986 {
12987         const glw::GLdouble root = sqrt(val);
12988
12989         return (1.0 / root);
12990 }
12991
12992 static glw::GLuint isinf_impl(glw::GLdouble val)
12993 {
12994         const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12995
12996         return ((infinity == val) || (-infinity == val));
12997 }
12998
12999 static glw::GLuint isnan_impl(glw::GLdouble val)
13000 {
13001         return val != val;
13002 }
13003
13004 template <typename T>
13005 static T ldexp(T val, glw::GLint exp)
13006 {
13007         return ::ldexp(val, exp);
13008 }
13009
13010 template <int Size>
13011 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
13012                                                                                            const tcu::Vector<glw::GLdouble, Size>& right)
13013 {
13014         return convertBvecToUvec(tcu::lessThan(left, right));
13015 }
13016
13017 template <int Size>
13018 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
13019                                                                                                         const tcu::Vector<glw::GLdouble, Size>& right)
13020 {
13021         return convertBvecToUvec(tcu::lessThanEqual(left, right));
13022 }
13023
13024 template <typename T>
13025 static T max(T left, T right)
13026 {
13027         return (left >= right) ? left : right;
13028 }
13029
13030 template <typename T>
13031 static T min(T left, T right)
13032 {
13033         return (left <= right) ? left : right;
13034 }
13035
13036 template <int            Size>
13037 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
13038                                                                 glw::GLuint row)
13039 {
13040         tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
13041
13042         return determinant(eliminated);
13043 }
13044
13045 template <>
13046 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
13047 {
13048         const glw::GLuint r = (0 == row) ? 1 : 0;
13049         const glw::GLuint c = (0 == column) ? 1 : 0;
13050
13051         return matrix(r, c);
13052 }
13053
13054 template <typename T>
13055 static T mix(T left, T right, T weight)
13056 {
13057         return left * (1 - weight) + right * (weight);
13058 }
13059
13060 template <typename T>
13061 static T mod(T left, T right)
13062 {
13063         const T div_res = left / right;
13064         const T floored = floor(div_res);
13065
13066         return left - right * floored;
13067 }
13068
13069 template <typename T>
13070 static T modf(T val, T& integer)
13071 {
13072         return ::modf(val, &integer);
13073 }
13074
13075 template <typename T>
13076 static T multiply(T left, T right)
13077 {
13078         T result = left * right;
13079
13080         return result;
13081 }
13082
13083 template <int Size>
13084 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
13085                                                                                            const tcu::Vector<glw::GLdouble, Size>& right)
13086 {
13087         return convertBvecToUvec(tcu::notEqual(left, right));
13088 }
13089
13090 template <int Cols, int Rows>
13091 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
13092                                                                                                                    const tcu::Vector<glw::GLdouble, Cols>& right)
13093 {
13094         tcu::Matrix<glw::GLdouble, Rows, 1>     left_mat;
13095         tcu::Matrix<glw::GLdouble, 1, Cols>     right_mat;
13096         tcu::Matrix<glw::GLdouble, Rows, Cols> result;
13097
13098         for (glw::GLuint i = 0; i < Rows; ++i)
13099         {
13100                 left_mat(i, 0) = left[i];
13101         }
13102
13103         for (glw::GLuint i = 0; i < Cols; ++i)
13104         {
13105                 right_mat(0, i) = right[i];
13106         }
13107
13108         result = left_mat * right_mat;
13109
13110         return result;
13111 }
13112
13113 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
13114 {
13115         const glw::GLuint buffer[2] = { in[0], in[1] };
13116         glw::GLdouble    result;
13117         memcpy(&result, buffer, sizeof(result));
13118         return result;
13119 }
13120
13121 template <typename T>
13122 static T round(T t)
13123 {
13124         T frac = fract(t);
13125         T res  = t - frac;
13126
13127         if (((T)0.5) < frac)
13128         {
13129                 res += ((T)1.0);
13130         }
13131
13132         return res;
13133 }
13134
13135 template <typename T>
13136 static T roundEven(T t)
13137 {
13138         T frac = fract(t);
13139         T res  = t - frac;
13140
13141         if (((T)0.5) < frac)
13142         {
13143                 res += ((T)1.0);
13144         }
13145         else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
13146         {
13147                 res += ((T)1.0);
13148         }
13149
13150         return res;
13151 }
13152
13153 template <typename T>
13154 static T sign(T t)
13155 {
13156         if (0 > t)
13157         {
13158                 return -1;
13159         }
13160         else if (0 == t)
13161         {
13162                 return 0;
13163         }
13164         else
13165         {
13166                 return 1;
13167         }
13168 }
13169
13170 template <typename T>
13171 static T smoothStep(T e0, T e1, T val)
13172 {
13173         if (e0 >= val)
13174         {
13175                 return 0;
13176         }
13177
13178         if (e1 <= val)
13179         {
13180                 return 1;
13181         }
13182
13183         T temp = (val - e0) / (e1 - e0);
13184
13185         T result = temp * temp * (3 - 2 * temp);
13186
13187         return result;
13188 }
13189
13190 template <typename T>
13191 static T step(T edge, T val)
13192 {
13193         if (edge > val)
13194         {
13195                 return 0;
13196         }
13197         else
13198         {
13199                 return 1;
13200         }
13201 }
13202
13203 template <typename T, int Rows, int Cols>
13204 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
13205 {
13206         tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
13207
13208         return result;
13209 }
13210
13211 template <typename T>
13212 static T trunc(T t)
13213 {
13214         const T abs_value       = de::abs(t);
13215         const T result_value = floor(abs_value);
13216
13217         const T result = sign(t) * result_value;
13218
13219         return result;
13220 }
13221
13222 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
13223 {
13224         glw::GLuint* ptr = (glw::GLuint*)&val;
13225         tcu::UVec2   result(ptr[0], ptr[1]);
13226
13227         return result;
13228 }
13229 } /* Math */
13230
13231 /* Constants used by GPUShaderFP64Test10 */
13232 /** Khronos Bug #14010
13233  *  Using an epsilon value for comparing floating points is error prone.
13234  *  Rather than writing a new floating point comparison function, I am
13235  *  increasing the epsilon value to allow greater orders of magnitude
13236  *  of floating point values.
13237  **/
13238 const glw::GLdouble GPUShaderFP64Test10::m_epsilon      = 0.00002;
13239 const glw::GLuint   GPUShaderFP64Test10::m_n_veritces = 1024;
13240
13241 /** Constructor.
13242  *
13243  *  @param context Rendering context.
13244  **/
13245 GPUShaderFP64Test10::GPUShaderFP64Test10(deqp::Context& context)
13246         : TestCase(context, "built_in_functions", "Verify that built-in functions support double-precision types")
13247         , m_transform_feedback_buffer_id(0)
13248         , m_vertex_array_object_id(0)
13249 {
13250         /* Nothing to be done here */
13251 }
13252
13253 /** Deinitializes all GL objects that may have been created during test execution.
13254  *
13255  **/
13256 void GPUShaderFP64Test10::deinit()
13257 {
13258         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13259
13260         /* Clean buffers */
13261         if (0 != m_transform_feedback_buffer_id)
13262         {
13263                 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13264                 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13265                 m_transform_feedback_buffer_id = 0;
13266         }
13267
13268         /* Clean VAO */
13269         if (0 != m_vertex_array_object_id)
13270         {
13271                 gl.bindVertexArray(0);
13272                 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13273                 m_vertex_array_object_id = 0;
13274         }
13275 }
13276
13277 /** Execute test
13278  *
13279  * @return tcu::TestNode::STOP
13280  **/
13281 tcu::TestNode::IterateResult GPUShaderFP64Test10::iterate()
13282 {
13283         bool result = true;
13284
13285         /* Check if extension is supported */
13286         if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13287         {
13288                 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13289         }
13290
13291         testInit();
13292
13293         /* For each combination of function and type */
13294         for (std::vector<typeDetails>::const_iterator type = m_types.begin(); m_types.end() != type; ++type)
13295         {
13296                 for (std::vector<functionEnum>::const_iterator function = m_functions.begin(); m_functions.end() != function;
13297                          ++function)
13298                 {
13299                         if (false == test(*function, *type))
13300                         {
13301                                 result = false;
13302                         }
13303                 }
13304         }
13305
13306         /* Set result */
13307         if (true == result)
13308         {
13309                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13310         }
13311         else
13312         {
13313                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13314         }
13315
13316         /* Done */
13317         return tcu::TestNode::STOP;
13318 }
13319
13320 /** Constructor
13321  *
13322  * @param function_enum    Function enumeration
13323  * @param function_name    Function name
13324  * @param function_pointer Pointer to routine that wiil be executed
13325  * @param result_type      Type of result
13326  **/
13327 GPUShaderFP64Test10::functionObject::functionObject(functionEnum function_enum, const glw::GLchar* function_name,
13328                                                                                                         glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13329         : m_function_enum(function_enum)
13330         , m_function_name(function_name)
13331         , m_p_function(function_pointer)
13332         , m_res_type(result_type)
13333 {
13334         /* Nothing to be done here */
13335 }
13336
13337 /** Get number of components for <argument>
13338  *
13339  * @param argument Argument ordinal, starts with 0
13340  *
13341  * @return Number of components
13342  **/
13343 glw::GLuint GPUShaderFP64Test10::functionObject::getArgumentComponents(glw::GLuint argument) const
13344 {
13345         const Utils::_variable_type type                  = getArgumentType(argument);
13346         const glw::GLuint                       n_components  = Utils::getNumberOfComponentsForVariableType(type);
13347
13348         return n_components;
13349 }
13350
13351 /** Get size in bytes of single component of <argument>
13352  *
13353  * @param argument Argument ordinal, starts with 0
13354  *
13355  * @return Size of component
13356  **/
13357 glw::GLuint GPUShaderFP64Test10::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13358 {
13359         const Utils::_variable_type type                   = getArgumentType(argument);
13360         const Utils::_variable_type base_type     = Utils::getBaseVariableType(type);
13361         const glw::GLuint                       base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13362
13363         return base_type_size;
13364 }
13365
13366 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13367  *
13368  * @param argument Argument ordinal, starts with 0
13369  *
13370  * @return Offset of arguemnt's data
13371  **/
13372 glw::GLuint GPUShaderFP64Test10::functionObject::getArgumentOffset(glw::GLuint argument) const
13373 {
13374         glw::GLuint result = 0;
13375
13376         for (glw::GLuint i = 0; i < argument; ++i)
13377         {
13378                 result += getArgumentStride(i);
13379         }
13380
13381         return result;
13382 }
13383
13384 /** Get stride in bytes of all arguments
13385  *
13386  * @return Stride of all arguments
13387  **/
13388 glw::GLuint GPUShaderFP64Test10::functionObject::getArgumentStride() const
13389 {
13390         const glw::GLuint n_args = getArgumentCount();
13391         glw::GLuint               result = 0;
13392
13393         for (glw::GLuint i = 0; i < n_args; ++i)
13394         {
13395                 result += getArgumentStride(i);
13396         }
13397
13398         return result;
13399 }
13400
13401 /** Get stride in bytes of <argument>
13402  *
13403  * @param argument Argument ordinal, starts with 0
13404  *
13405  * @return Stride of argument
13406  **/
13407 glw::GLuint GPUShaderFP64Test10::functionObject::getArgumentStride(glw::GLuint argument) const
13408 {
13409         const glw::GLuint component_size = getArgumentComponentSize(argument);
13410         const glw::GLuint n_components   = getArgumentComponents(argument);
13411
13412         return n_components * component_size;
13413 }
13414
13415 /** Get function enumeration
13416  *
13417  * @return Function enumeration
13418  **/
13419 GPUShaderFP64Test10::functionEnum GPUShaderFP64Test10::functionObject::getFunctionEnum() const
13420 {
13421         return m_function_enum;
13422 }
13423
13424 /** Get function name
13425  *
13426  * @return Function name
13427  **/
13428 const glw::GLchar* GPUShaderFP64Test10::functionObject::getName() const
13429 {
13430         return m_function_name;
13431 }
13432
13433 /** Get number of components for <result>
13434  *
13435  * @param result Result ordinal, starts with 0
13436  *
13437  * @return Number of components
13438  **/
13439 glw::GLuint GPUShaderFP64Test10::functionObject::getResultComponents(glw::GLuint result) const
13440 {
13441         const Utils::_variable_type type                  = getResultType(result);
13442         const glw::GLuint                       n_components  = Utils::getNumberOfComponentsForVariableType(type);
13443
13444         return n_components;
13445 }
13446
13447 /** Get number of results
13448  *
13449  * @return Number of results
13450  **/
13451 glw::GLuint GPUShaderFP64Test10::functionObject::getResultCount() const
13452 {
13453         return 1;
13454 }
13455
13456 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13457  *
13458  * @param result Result ordinal, starts with 0
13459  *
13460  * @return Offset
13461  **/
13462 glw::GLuint GPUShaderFP64Test10::functionObject::getResultOffset(glw::GLuint result) const
13463 {
13464         glw::GLuint offset = 0;
13465
13466         for (glw::GLuint i = 0; i < result; ++i)
13467         {
13468                 offset += getResultStride(i);
13469                 offset = deAlign32(offset, getBaseTypeSize(i));
13470         }
13471
13472         return offset;
13473 }
13474
13475 /** Get stride in bytes of <result>.
13476  *
13477  * @param result Result ordinal, starts with 0
13478  *
13479  * @return Stride
13480  **/
13481 glw::GLuint GPUShaderFP64Test10::functionObject::getResultStride(glw::GLuint result) const
13482 {
13483         const Utils::_variable_type type                   = getResultType(result);
13484         const glw::GLuint                       n_components   = Utils::getNumberOfComponentsForVariableType(type);
13485
13486         return n_components * getBaseTypeSize(result);
13487 }
13488
13489 /** Get size in bytes of <result> base component.
13490  *
13491  * @param result Result ordinal, starts with 0
13492  *
13493  * @return Alignment
13494  **/
13495 glw::GLuint GPUShaderFP64Test10::functionObject::getBaseTypeSize(glw::GLuint result) const
13496 {
13497         const Utils::_variable_type type                   = getResultType(result);
13498         const Utils::_variable_type base_type     = Utils::getBaseVariableType(type);
13499         const glw::GLuint                       base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13500
13501         return base_type_size;
13502 }
13503
13504 /** Get stride in bytes of all results.
13505  *
13506  * @return Stride
13507  **/
13508 glw::GLuint GPUShaderFP64Test10::functionObject::getResultStride() const
13509 {
13510         const glw::GLuint n_results     = getResultCount();
13511         glw::GLuint               stride           = 0;
13512         glw::GLuint               maxAlignment = 0;
13513
13514         for (glw::GLuint i = 0; i < n_results; ++i)
13515         {
13516                 const glw::GLuint alignment = getBaseTypeSize(i);
13517                 stride += getResultStride(i);
13518                 stride           = deAlign32(stride, alignment);
13519                 maxAlignment = deMaxu32(maxAlignment, alignment);
13520         }
13521
13522         // The stride of all results must also be aligned,
13523         // so results for next vertex are aligned.
13524         return deAlign32(stride, maxAlignment);
13525 }
13526
13527 /** Get type of <result>.
13528  *
13529  * @param result Result ordinal, starts with 0
13530  *
13531  * @return Type
13532  **/
13533 Utils::_variable_type GPUShaderFP64Test10::functionObject::getResultType(glw::GLuint /* result */) const
13534 {
13535         return m_res_type;
13536 }
13537
13538 /** Constructor
13539  *
13540  * @param n_columns Number of columns
13541  * @param n_rows    Number of rows
13542  **/
13543 GPUShaderFP64Test10::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13544         : m_n_columns(n_columns), m_n_rows(n_rows)
13545 {
13546         Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13547         m_type                                     = Utils::getGLDataTypeOfVariableType(type);
13548         m_type_name                                = Utils::getVariableTypeString(type);
13549
13550         if (1 == m_n_columns)
13551         {
13552                 if (1 == m_n_rows)
13553                 {
13554                         m_general_type = SCALAR;
13555                 }
13556                 else
13557                 {
13558                         m_general_type = VECTOR;
13559                 }
13560         }
13561         else
13562         {
13563                 m_general_type = MATRIX;
13564         }
13565 }
13566
13567 /** Compare two values
13568  *
13569  * @param type  Type of values
13570  * @param left  Pointer to left value
13571  * @param right Pointer to right value
13572  *
13573  * @return true if values are equal, false otherwise
13574  **/
13575 bool GPUShaderFP64Test10::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13576 {
13577         bool result = true;
13578
13579         const glw::GLuint                       n_components = Utils::getNumberOfComponentsForVariableType(type);
13580         const Utils::_variable_type base_type   = Utils::getBaseVariableType(type);
13581
13582         switch (base_type)
13583         {
13584         case Utils::VARIABLE_TYPE_DOUBLE:
13585
13586         {
13587                 const glw::GLdouble* left_values  = (glw::GLdouble*)left;
13588                 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13589
13590                 for (glw::GLuint component = 0; component < n_components; ++component)
13591                 {
13592                         const glw::GLdouble left_value  = left_values[component];
13593                         const glw::GLdouble right_value = right_values[component];
13594
13595                         if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13596                                 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13597                         {
13598                                 result = false;
13599                                 break;
13600                         }
13601                 }
13602         }
13603
13604         break;
13605
13606         case Utils::VARIABLE_TYPE_INT:
13607
13608         {
13609                 const glw::GLint* left_values  = (glw::GLint*)left;
13610                 const glw::GLint* right_values = (glw::GLint*)right;
13611
13612                 for (glw::GLuint component = 0; component < n_components; ++component)
13613                 {
13614                         const glw::GLint left_value  = left_values[component];
13615                         const glw::GLint right_value = right_values[component];
13616
13617                         if (left_value != right_value)
13618                         {
13619                                 result = false;
13620                                 break;
13621                         }
13622                 }
13623         }
13624
13625         break;
13626
13627         case Utils::VARIABLE_TYPE_UINT:
13628
13629         {
13630                 const glw::GLuint* left_values  = (glw::GLuint*)left;
13631                 const glw::GLuint* right_values = (glw::GLuint*)right;
13632
13633                 for (glw::GLuint component = 0; component < n_components; ++component)
13634                 {
13635                         const glw::GLuint left_value  = left_values[component];
13636                         const glw::GLuint right_value = right_values[component];
13637
13638                         if (left_value != right_value)
13639                         {
13640                                 result = false;
13641                                 break;
13642                         }
13643                 }
13644         }
13645
13646         break;
13647
13648         default:
13649
13650                 TCU_FAIL("Not implemented");
13651
13652                 break;
13653         }
13654
13655         return result;
13656 }
13657
13658 /** Create instance of function object for given function enumeration and type
13659  *
13660  * @param function Function enumeration
13661  * @param type     Type details
13662  *
13663  * @return Create object
13664  **/
13665 GPUShaderFP64Test10::functionObject* GPUShaderFP64Test10::getFunctionObject(functionEnum           function,
13666                                                                                                                                                         const typeDetails& type)
13667 {
13668         typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13669         typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13670         typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13671         typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13672         typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13673         typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13674         typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13675         typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13676         typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13677
13678         const glw::GLuint                       n_columns        = type.m_n_columns;
13679         const glw::GLuint                       n_rows            = type.m_n_rows;
13680         const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
13681         const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13682         const Utils::_variable_type uint_type    = Utils::getUintVariableType(1, n_rows);
13683         const Utils::_variable_type int_type      = Utils::getIntVariableType(1, n_rows);
13684
13685         switch (function)
13686         {
13687         case FUNCTION_ABS:
13688
13689                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13690                         function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13691
13692                 break;
13693
13694         case FUNCTION_CEIL:
13695
13696                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13697                         function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13698
13699                 break;
13700
13701         case FUNCTION_CLAMP:
13702
13703                 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13704                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
13705                                                                                                          variable_type /* arg3_type */);
13706                 break;
13707
13708         case FUNCTION_CLAMP_AGAINST_SCALAR:
13709
13710                 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
13711                                                                                                          variable_type /* arg1_type */, scalar_type /* arg2_type */,
13712                                                                                                          scalar_type /* arg3_type */);
13713                 break;
13714
13715         case FUNCTION_CROSS:
13716
13717                 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13718                         function, "cross", tcu::cross);
13719
13720                 break;
13721
13722         case FUNCTION_DETERMINANT:
13723
13724                 switch (variable_type)
13725                 {
13726                 case Utils::VARIABLE_TYPE_DMAT2:
13727                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13728                                                                                                                                                                                  Math::determinant);
13729                 case Utils::VARIABLE_TYPE_DMAT3:
13730                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13731                                                                                                                                                                                  Math::determinant);
13732                 case Utils::VARIABLE_TYPE_DMAT4:
13733                         return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13734                                                                                                                                                                                  Math::determinant);
13735                 default:
13736                         TCU_FAIL("Not implemented");
13737                         break;
13738                 }
13739
13740                 break;
13741
13742         case FUNCTION_DISTANCE:
13743
13744                 switch (variable_type)
13745                 {
13746                 case Utils::VARIABLE_TYPE_DVEC2:
13747                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13748                                 function, "distance", tcu::distance);
13749                         break;
13750                 case Utils::VARIABLE_TYPE_DVEC3:
13751                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13752                                 function, "distance", tcu::distance);
13753                         break;
13754                 case Utils::VARIABLE_TYPE_DVEC4:
13755                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13756                                 function, "distance", tcu::distance);
13757                         break;
13758                 default:
13759                         break;
13760                 }
13761
13762                 break;
13763
13764         case FUNCTION_DOT:
13765
13766                 switch (variable_type)
13767                 {
13768                 case Utils::VARIABLE_TYPE_DVEC2:
13769                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13770                                 function, "dot", tcu::dot);
13771                         break;
13772                 case Utils::VARIABLE_TYPE_DVEC3:
13773                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13774                                 function, "dot", tcu::dot);
13775                         break;
13776                 case Utils::VARIABLE_TYPE_DVEC4:
13777                         return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13778                                 function, "dot", tcu::dot);
13779                         break;
13780                 default:
13781                         break;
13782                 }
13783
13784                 break;
13785
13786         case FUNCTION_EQUAL:
13787
13788                 switch (variable_type)
13789                 {
13790                 case Utils::VARIABLE_TYPE_DVEC2:
13791                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13792                                 function, "equal", Math::equal);
13793                         break;
13794                 case Utils::VARIABLE_TYPE_DVEC3:
13795                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13796                                 function, "equal", Math::equal);
13797                         break;
13798                 case Utils::VARIABLE_TYPE_DVEC4:
13799                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13800                                 function, "equal", Math::equal);
13801                         break;
13802                 default:
13803                         break;
13804                 }
13805
13806                 break;
13807
13808         case FUNCTION_FACEFORWARD:
13809
13810                 switch (variable_type)
13811                 {
13812                 case Utils::VARIABLE_TYPE_DVEC2:
13813                         return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
13814                                                                                           const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
13815                                 function, "faceforward", tcu::faceForward);
13816                         break;
13817                 case Utils::VARIABLE_TYPE_DVEC3:
13818                         return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
13819                                                                                           const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
13820                                 function, "faceforward", tcu::faceForward);
13821                         break;
13822                 case Utils::VARIABLE_TYPE_DVEC4:
13823                         return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
13824                                                                                           const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
13825                                 function, "faceforward", tcu::faceForward);
13826                         break;
13827                 default:
13828                         break;
13829                 }
13830
13831                 break;
13832
13833         case FUNCTION_FLOOR:
13834
13835                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13836                         function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
13837
13838                 break;
13839
13840         case FUNCTION_FMA:
13841
13842                 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
13843                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
13844                                                                                                          variable_type /* arg3_type */);
13845
13846                 break;
13847
13848         case FUNCTION_FRACT:
13849
13850                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13851                         function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
13852
13853                 break;
13854
13855         case FUNCTION_FREXP:
13856
13857                 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
13858                                                                                                                           glw::GLint /* OutT */>(
13859                         function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
13860                         int_type /* out_type */);
13861
13862                 break;
13863
13864         case FUNCTION_GREATERTHAN:
13865
13866                 switch (variable_type)
13867                 {
13868                 case Utils::VARIABLE_TYPE_DVEC2:
13869                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13870                                 function, "greaterThan", Math::greaterThan);
13871                         break;
13872                 case Utils::VARIABLE_TYPE_DVEC3:
13873                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13874                                 function, "greaterThan", Math::greaterThan);
13875                         break;
13876                 case Utils::VARIABLE_TYPE_DVEC4:
13877                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13878                                 function, "greaterThan", Math::greaterThan);
13879                         break;
13880                 default:
13881                         break;
13882                 }
13883
13884                 break;
13885
13886         case FUNCTION_GREATERTHANEQUAL:
13887
13888                 switch (variable_type)
13889                 {
13890                 case Utils::VARIABLE_TYPE_DVEC2:
13891                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13892                                 function, "greaterThanEqual", Math::greaterThanEqual);
13893                         break;
13894                 case Utils::VARIABLE_TYPE_DVEC3:
13895                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13896                                 function, "greaterThanEqual", Math::greaterThanEqual);
13897                         break;
13898                 case Utils::VARIABLE_TYPE_DVEC4:
13899                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13900                                 function, "greaterThanEqual", Math::greaterThanEqual);
13901                         break;
13902                 default:
13903                         break;
13904                 }
13905
13906                 break;
13907
13908         case FUNCTION_INVERSE:
13909
13910                 switch (variable_type)
13911                 {
13912                 case Utils::VARIABLE_TYPE_DMAT2:
13913                         return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
13914                         break;
13915                 case Utils::VARIABLE_TYPE_DMAT3:
13916                         return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
13917                         break;
13918                 case Utils::VARIABLE_TYPE_DMAT4:
13919                         return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
13920                         break;
13921                 default:
13922                         break;
13923                 }
13924
13925                 break;
13926
13927         case FUNCTION_INVERSESQRT:
13928
13929                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13930                         function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
13931
13932                 break;
13933
13934         case FUNCTION_LDEXP:
13935
13936                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
13937                                                                                                          glw::GLint /* Arg2T */>(
13938                         function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
13939                         int_type /* arg2_type */);
13940
13941                 break;
13942
13943         case FUNCTION_LESSTHAN:
13944
13945                 switch (variable_type)
13946                 {
13947                 case Utils::VARIABLE_TYPE_DVEC2:
13948                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13949                                 function, "lessThan", Math::lessThan);
13950                         break;
13951                 case Utils::VARIABLE_TYPE_DVEC3:
13952                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13953                                 function, "lessThan", Math::lessThan);
13954                         break;
13955                 case Utils::VARIABLE_TYPE_DVEC4:
13956                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13957                                 function, "lessThan", Math::lessThan);
13958                         break;
13959                 default:
13960                         break;
13961                 }
13962
13963                 break;
13964
13965         case FUNCTION_LESSTHANEQUAL:
13966
13967                 switch (variable_type)
13968                 {
13969                 case Utils::VARIABLE_TYPE_DVEC2:
13970                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13971                                 function, "lessThanEqual", Math::lessThanEqual);
13972                         break;
13973                 case Utils::VARIABLE_TYPE_DVEC3:
13974                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13975                                 function, "lessThanEqual", Math::lessThanEqual);
13976                         break;
13977                 case Utils::VARIABLE_TYPE_DVEC4:
13978                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13979                                 function, "lessThanEqual", Math::lessThanEqual);
13980                         break;
13981                 default:
13982                         break;
13983                 }
13984
13985                 break;
13986
13987         case FUNCTION_LENGTH:
13988
13989                 switch (variable_type)
13990                 {
13991                 case Utils::VARIABLE_TYPE_DVEC2:
13992                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
13993                                                                                                                                                                                           tcu::length);
13994                         break;
13995                 case Utils::VARIABLE_TYPE_DVEC3:
13996                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
13997                                                                                                                                                                                           tcu::length);
13998                         break;
13999                 case Utils::VARIABLE_TYPE_DVEC4:
14000                         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14001                                                                                                                                                                                           tcu::length);
14002                         break;
14003                 default:
14004                         break;
14005                 }
14006
14007                 break;
14008
14009         case FUNCTION_MATRIXCOMPMULT:
14010
14011                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14012                                                                                                          glw::GLdouble /* Arg2T */>(
14013                         function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14014                         variable_type /* arg2_type */);
14015
14016                 break;
14017
14018         case FUNCTION_MAX:
14019
14020                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14021                                                                                                          glw::GLdouble /* Arg2T */>(
14022                         function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14023                         variable_type /* arg2_type */);
14024
14025                 break;
14026
14027         case FUNCTION_MAX_AGAINST_SCALAR:
14028
14029                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14030                                                                                                          glw::GLdouble /* Arg2T */>(
14031                         function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14032                         scalar_type /* arg2_type */);
14033
14034                 break;
14035
14036         case FUNCTION_MIN:
14037
14038                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14039                                                                                                          glw::GLdouble /* Arg2T */>(
14040                         function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14041                         variable_type /* arg2_type */);
14042
14043                 break;
14044
14045         case FUNCTION_MIN_AGAINST_SCALAR:
14046
14047                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14048                                                                                                          glw::GLdouble /* Arg2T */>(
14049                         function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14050                         scalar_type /* arg2_type */);
14051
14052                 break;
14053
14054         case FUNCTION_MIX:
14055
14056                 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14057                                                                                                          variable_type /* arg1_type */, variable_type /* arg2_type */,
14058                                                                                                          variable_type /* arg3_type */);
14059
14060                 break;
14061
14062         case FUNCTION_MOD:
14063
14064                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14065                                                                                                          glw::GLdouble /* Arg2T */>(
14066                         function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14067                         variable_type /* arg2_type */);
14068
14069                 break;
14070
14071         case FUNCTION_MOD_AGAINST_SCALAR:
14072
14073                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14074                                                                                                          glw::GLdouble /* Arg2T */>(
14075                         function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14076                         scalar_type /* arg2_type */);
14077
14078                 break;
14079
14080         case FUNCTION_MODF:
14081
14082                 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14083                                                                                                                           glw::GLdouble /* OutT */>(
14084                         function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14085                         variable_type /* out_type */);
14086
14087                 break;
14088
14089         case FUNCTION_NORMALIZE:
14090
14091                 switch (variable_type)
14092                 {
14093                 case Utils::VARIABLE_TYPE_DVEC2:
14094                         return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14095                                                                                                                                                                                    tcu::normalize);
14096                         break;
14097                 case Utils::VARIABLE_TYPE_DVEC3:
14098                         return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14099                                                                                                                                                                                    tcu::normalize);
14100                         break;
14101                 case Utils::VARIABLE_TYPE_DVEC4:
14102                         return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14103                                                                                                                                                                                    tcu::normalize);
14104                         break;
14105                 default:
14106                         break;
14107                 }
14108
14109                 break;
14110
14111         case FUNCTION_NOTEQUAL:
14112
14113                 switch (variable_type)
14114                 {
14115                 case Utils::VARIABLE_TYPE_DVEC2:
14116                         return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14117                                 function, "notEqual", Math::notEqual);
14118                         break;
14119                 case Utils::VARIABLE_TYPE_DVEC3:
14120                         return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14121                                 function, "notEqual", Math::notEqual);
14122                         break;
14123                 case Utils::VARIABLE_TYPE_DVEC4:
14124                         return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14125                                 function, "notEqual", Math::notEqual);
14126                         break;
14127                 default:
14128                         break;
14129                 }
14130
14131                 break;
14132
14133         case FUNCTION_OUTERPRODUCT:
14134
14135                 switch (variable_type)
14136                 {
14137                 case Utils::VARIABLE_TYPE_DMAT2:
14138                         return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14139                                 function, "outerProduct", Math::outerProduct);
14140                         break;
14141                 case Utils::VARIABLE_TYPE_DMAT2X3:
14142                         return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14143                                 function, "outerProduct", Math::outerProduct);
14144                         break;
14145                 case Utils::VARIABLE_TYPE_DMAT2X4:
14146                         return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14147                                 function, "outerProduct", Math::outerProduct);
14148                         break;
14149                 case Utils::VARIABLE_TYPE_DMAT3:
14150                         return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14151                                 function, "outerProduct", Math::outerProduct);
14152                         break;
14153                 case Utils::VARIABLE_TYPE_DMAT3X2:
14154                         return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14155                                 function, "outerProduct", Math::outerProduct);
14156                         break;
14157                 case Utils::VARIABLE_TYPE_DMAT3X4:
14158                         return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14159                                 function, "outerProduct", Math::outerProduct);
14160                         break;
14161                 case Utils::VARIABLE_TYPE_DMAT4:
14162                         return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14163                                 function, "outerProduct", Math::outerProduct);
14164                         break;
14165                 case Utils::VARIABLE_TYPE_DMAT4X2:
14166                         return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14167                                 function, "outerProduct", Math::outerProduct);
14168                         break;
14169                 case Utils::VARIABLE_TYPE_DMAT4X3:
14170                         return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14171                                 function, "outerProduct", Math::outerProduct);
14172                         break;
14173                 default:
14174                         break;
14175                 }
14176
14177                 break;
14178
14179         case FUNCTION_PACKDOUBLE2X32:
14180
14181                 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14182                                                                                                                                                                                   Math::packDouble2x32);
14183
14184                 break;
14185
14186         case FUNCTION_REFLECT:
14187
14188                 switch (variable_type)
14189                 {
14190                 case Utils::VARIABLE_TYPE_DVEC2:
14191                         return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14192                                 function, "reflect", tcu::reflect);
14193                         break;
14194                 case Utils::VARIABLE_TYPE_DVEC3:
14195                         return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14196                                 function, "reflect", tcu::reflect);
14197                         break;
14198                 case Utils::VARIABLE_TYPE_DVEC4:
14199                         return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14200                                 function, "reflect", tcu::reflect);
14201                         break;
14202                 default:
14203                         break;
14204                 }
14205
14206                 break;
14207
14208         case FUNCTION_REFRACT:
14209
14210                 switch (variable_type)
14211                 {
14212                 case Utils::VARIABLE_TYPE_DVEC2:
14213                         return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14214                                                                                           const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14215                                 function, "refract", tcu::refract);
14216                         break;
14217                 case Utils::VARIABLE_TYPE_DVEC3:
14218                         return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14219                                                                                           const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14220                                 function, "refract", tcu::refract);
14221                         break;
14222                 case Utils::VARIABLE_TYPE_DVEC4:
14223                         return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14224                                                                                           const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14225                                 function, "refract", tcu::refract);
14226                         break;
14227                 default:
14228                         break;
14229                 }
14230
14231                 break;
14232
14233         case FUNCTION_ROUND:
14234
14235                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14236                         function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14237
14238                 break;
14239
14240         case FUNCTION_ROUNDEVEN:
14241
14242                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14243                         function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14244
14245                 break;
14246
14247         case FUNCTION_SIGN:
14248
14249                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14250                         function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14251
14252                 break;
14253
14254         case FUNCTION_SMOOTHSTEP:
14255
14256                 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14257                                                                                                          variable_type /* res_type  */, variable_type /* arg1_type */,
14258                                                                                                          variable_type /* arg2_type */, variable_type /* arg3_type */);
14259
14260                 break;
14261
14262         case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14263
14264                 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14265                                                                                                          variable_type /* res_type  */, scalar_type /* arg1_type */,
14266                                                                                                          scalar_type /* arg2_type */, variable_type /* arg3_type */);
14267
14268                 break;
14269
14270         case FUNCTION_SQRT:
14271
14272                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14273                         function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14274
14275                 break;
14276
14277         case FUNCTION_STEP:
14278
14279                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14280                                                                                                          glw::GLdouble /* Arg2T */>(
14281                         function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14282                         variable_type /* arg2_type */);
14283
14284                 break;
14285
14286         case FUNCTION_STEP_AGAINST_SCALAR:
14287
14288                 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14289                                                                                                          glw::GLdouble /* Arg2T */>(
14290                         function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14291                         variable_type /* arg2_type */);
14292
14293                 break;
14294
14295         case FUNCTION_TRANSPOSE:
14296
14297                 switch (variable_type)
14298                 {
14299                 case Utils::VARIABLE_TYPE_DMAT2:
14300                         return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14301                                                                                                                                                                  Math::transpose);
14302                         break;
14303                 case Utils::VARIABLE_TYPE_DMAT2X3:
14304                         return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14305                                                                                                                                                                          Math::transpose);
14306                         break;
14307                 case Utils::VARIABLE_TYPE_DMAT2X4:
14308                         return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14309                                                                                                                                                                          Math::transpose);
14310                         break;
14311                 case Utils::VARIABLE_TYPE_DMAT3:
14312                         return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14313                                                                                                                                                                  Math::transpose);
14314                         break;
14315                 case Utils::VARIABLE_TYPE_DMAT3X2:
14316                         return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14317                                                                                                                                                                          Math::transpose);
14318                         break;
14319                 case Utils::VARIABLE_TYPE_DMAT3X4:
14320                         return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14321                                                                                                                                                                          Math::transpose);
14322                         break;
14323                 case Utils::VARIABLE_TYPE_DMAT4:
14324                         return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14325                                                                                                                                                                  Math::transpose);
14326                         break;
14327                 case Utils::VARIABLE_TYPE_DMAT4X2:
14328                         return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14329                                                                                                                                                                          Math::transpose);
14330                         break;
14331                 case Utils::VARIABLE_TYPE_DMAT4X3:
14332                         return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14333                                                                                                                                                                          Math::transpose);
14334                         break;
14335                 default:
14336                         break;
14337                 }
14338
14339                 break;
14340
14341         case FUNCTION_TRUNC:
14342
14343                 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14344                         function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14345
14346                 break;
14347
14348         case FUNCTION_UNPACKDOUBLE2X32:
14349
14350                 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14351                                                                                                                                                                                   Math::unpackDouble2x32);
14352
14353                 break;
14354
14355         case FUNCTION_ISNAN:
14356
14357                 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14358                         function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14359
14360                 break;
14361
14362         case FUNCTION_ISINF:
14363
14364                 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14365                         function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14366
14367                 break;
14368
14369         default:
14370                 TCU_FAIL("Not implemented");
14371                 return 0;
14372                 break;
14373         }
14374
14375         TCU_FAIL("Not implemented");
14376         return 0;
14377 }
14378
14379 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14380  *
14381  * @param argument        Argument index
14382  * @param function_object Function object
14383  *
14384  * @return Function pointer
14385  **/
14386 GPUShaderFP64Test10::uniformDMatFunctionPointer GPUShaderFP64Test10::getUniformFunctionForDMat(
14387         glw::GLuint argument, const functionObject& function_object) const
14388 {
14389         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14390         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14391
14392         switch (argument_type)
14393         {
14394         case Utils::VARIABLE_TYPE_DMAT2:
14395                 return gl.uniformMatrix2dv;
14396                 break;
14397         case Utils::VARIABLE_TYPE_DMAT2X3:
14398                 return gl.uniformMatrix2x3dv;
14399                 break;
14400         case Utils::VARIABLE_TYPE_DMAT2X4:
14401                 return gl.uniformMatrix2x4dv;
14402                 break;
14403         case Utils::VARIABLE_TYPE_DMAT3:
14404                 return gl.uniformMatrix3dv;
14405                 break;
14406         case Utils::VARIABLE_TYPE_DMAT3X2:
14407                 return gl.uniformMatrix3x2dv;
14408                 break;
14409         case Utils::VARIABLE_TYPE_DMAT3X4:
14410                 return gl.uniformMatrix3x4dv;
14411                 break;
14412         case Utils::VARIABLE_TYPE_DMAT4:
14413                 return gl.uniformMatrix4dv;
14414                 break;
14415         case Utils::VARIABLE_TYPE_DMAT4X2:
14416                 return gl.uniformMatrix4x2dv;
14417                 break;
14418         case Utils::VARIABLE_TYPE_DMAT4X3:
14419                 return gl.uniformMatrix4x3dv;
14420                 break;
14421         default:
14422                 break;
14423         }
14424
14425         TCU_FAIL("Not implemented");
14426         return 0;
14427 }
14428
14429 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14430  *
14431  * @param argument        Argument index
14432  * @param function_object Function object
14433  *
14434  * @return Function pointer
14435  **/
14436 GPUShaderFP64Test10::uniformDVecFunctionPointer GPUShaderFP64Test10::getUniformFunctionForDVec(
14437         glw::GLuint argument, const functionObject& function_object) const
14438 {
14439         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14440         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14441
14442         switch (argument_type)
14443         {
14444         case Utils::VARIABLE_TYPE_DOUBLE:
14445                 return gl.uniform1dv;
14446                 break;
14447         case Utils::VARIABLE_TYPE_DVEC2:
14448                 return gl.uniform2dv;
14449                 break;
14450         case Utils::VARIABLE_TYPE_DVEC3:
14451                 return gl.uniform3dv;
14452                 break;
14453         case Utils::VARIABLE_TYPE_DVEC4:
14454                 return gl.uniform4dv;
14455                 break;
14456         default:
14457                 TCU_FAIL("Not implemented");
14458                 break;
14459         }
14460
14461         return 0;
14462 }
14463
14464 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14465  *
14466  * @param argument        Argument index
14467  * @param function_object Function object
14468  *
14469  * @return Function pointer
14470  **/
14471 GPUShaderFP64Test10::uniformIVecFunctionPointer GPUShaderFP64Test10::getUniformFunctionForIVec(
14472         glw::GLuint argument, const functionObject& function_object) const
14473 {
14474         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14475         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14476
14477         switch (argument_type)
14478         {
14479         case Utils::VARIABLE_TYPE_INT:
14480                 return gl.uniform1iv;
14481                 break;
14482         case Utils::VARIABLE_TYPE_IVEC2:
14483                 return gl.uniform2iv;
14484                 break;
14485         case Utils::VARIABLE_TYPE_IVEC3:
14486                 return gl.uniform3iv;
14487                 break;
14488         case Utils::VARIABLE_TYPE_IVEC4:
14489                 return gl.uniform4iv;
14490                 break;
14491         default:
14492                 TCU_FAIL("Not implemented");
14493                 break;
14494         }
14495
14496         return 0;
14497 }
14498
14499 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14500  *
14501  * @param argument        Argument index
14502  * @param function_object Function object
14503  *
14504  * @return Function pointer
14505  **/
14506 GPUShaderFP64Test10::uniformUVecFunctionPointer GPUShaderFP64Test10::getUniformFunctionForUVec(
14507         glw::GLuint argument, const functionObject& function_object) const
14508 {
14509         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14510         const glw::Functions&           gl                        = m_context.getRenderContext().getFunctions();
14511
14512         switch (argument_type)
14513         {
14514         case Utils::VARIABLE_TYPE_UVEC2:
14515                 return gl.uniform2uiv;
14516                 break;
14517         default:
14518                 TCU_FAIL("Not implemented");
14519                 break;
14520         }
14521
14522         return 0;
14523 }
14524
14525 /** Get name of uniform that will be used as <argument>.
14526  *
14527  * @param argument Argument index
14528  *
14529  * @return Name of uniform
14530  **/
14531 const glw::GLchar* GPUShaderFP64Test10::getUniformName(glw::GLuint argument) const
14532 {
14533         switch (argument)
14534         {
14535         case 0:
14536                 return "uniform_0";
14537                 break;
14538         case 1:
14539                 return "uniform_1";
14540                 break;
14541         case 2:
14542                 return "uniform_2";
14543                 break;
14544         default:
14545                 TCU_FAIL("Not implemented");
14546                 return 0;
14547                 break;
14548         }
14549 }
14550
14551 /** Get name of varying that will be used as <result>.
14552  *
14553  * @param result Result index
14554  *
14555  * @return Name of varying
14556  **/
14557 const glw::GLchar* GPUShaderFP64Test10::getVaryingName(glw::GLuint result) const
14558 {
14559         switch (result)
14560         {
14561         case 0:
14562                 return "result_0";
14563                 break;
14564         case 1:
14565                 return "result_1";
14566                 break;
14567         case 2:
14568                 return "result_2";
14569                 break;
14570         default:
14571                 TCU_FAIL("Not implemented");
14572                 return 0;
14573                 break;
14574         }
14575 }
14576
14577 /** Check if given combination of function and type is implemented
14578  *
14579  * @param function Function enumeration
14580  * @param type     Type details
14581  *
14582  * @return true if function is available for given type, false otherwise
14583  **/
14584 bool GPUShaderFP64Test10::isFunctionImplemented(functionEnum function, const typeDetails& type) const
14585 {
14586         static const bool look_up_table[][3] = {
14587                 /* SCALAR, VECTOR, MATRIX */
14588                 /* FUNCTION_ABS:                       */ { true, true, false },
14589                 /* FUNCTION_CEIL:                      */ { true, true, false },
14590                 /* FUNCTION_CLAMP:                     */ { true, true, false },
14591                 /* FUNCTION_CLAMP_AGAINST_SCALAR:      */ { false, true, false },
14592                 /* FUNCTION_CROSS:                     */ { false, true, false },
14593                 /* FUNCTION_DETERMINANT:               */ { false, false, true },
14594                 /* FUNCTION_DISTANCE:                  */ { false, true, false },
14595                 /* FUNCTION_DOT:                       */ { false, true, false },
14596                 /* FUNCTION_EQUAL:                     */ { false, true, false },
14597                 /* FUNCTION_FACEFORWARD:               */ { false, true, false },
14598                 /* FUNCTION_FLOOR:                     */ { true, true, false },
14599                 /* FUNCTION_FMA:                       */ { true, true, false },
14600                 /* FUNCTION_FRACT:                     */ { true, true, false },
14601                 /* FUNCTION_FREXP:                     */ { true, true, false },
14602                 /* FUNCTION_GREATERTHAN:               */ { false, true, false },
14603                 /* FUNCTION_GREATERTHANEQUAL:          */ { false, true, false },
14604                 /* FUNCTION_INVERSE:                   */ { false, false, true },
14605                 /* FUNCTION_INVERSESQRT:               */ { true, true, false },
14606                 /* FUNCTION_LDEXP:                     */ { true, true, false },
14607                 /* FUNCTION_LESSTHAN:                  */ { false, true, false },
14608                 /* FUNCTION_LESSTHANEQUAL:             */ { false, true, false },
14609                 /* FUNCTION_LENGTH:                    */ { false, true, false },
14610                 /* FUNCTION_MATRIXCOMPMULT:            */ { false, false, true },
14611                 /* FUNCTION_MAX:                       */ { true, true, false },
14612                 /* FUNCTION_MAX_AGAINST_SCALAR:        */ { false, true, false },
14613                 /* FUNCTION_MIN:                       */ { true, true, false },
14614                 /* FUNCTION_MIN_AGAINST_SCALAR:        */ { false, true, false },
14615                 /* FUNCTION_MIX:                       */ { true, true, false },
14616                 /* FUNCTION_MOD:                       */ { true, true, false },
14617                 /* FUNCTION_MOD_AGAINST_SCALAR:        */ { false, true, false },
14618                 /* FUNCTION_MODF:                      */ { true, true, false },
14619                 /* FUNCTION_NORMALIZE:                 */ { false, true, false },
14620                 /* FUNCTION_NOTEQUAL:                  */ { false, true, false },
14621                 /* FUNCTION_OUTERPRODUCT:              */ { false, false, true },
14622                 /* FUNCTION_PACKDOUBLE2X32:            */ { true, false, false },
14623                 /* FUNCTION_REFLECT:                   */ { false, true, false },
14624                 /* FUNCTION_REFRACT:                   */ { false, true, false },
14625                 /* FUNCTION_ROUND:                     */ { true, true, false },
14626                 /* FUNCTION_ROUNDEVEN:                 */ { true, true, false },
14627                 /* FUNCTION_SIGN:                      */ { true, false, false },
14628                 /* FUNCTION_SMOOTHSTEP:                */ { true, true, false },
14629                 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14630                 /* FUNCTION_SQRT:                      */ { true, true, false },
14631                 /* FUNCTION_STEP:                      */ { true, true, false },
14632                 /* FUNCTION_STEP_AGAINST_SCALAR:       */ { false, true, false },
14633                 /* FUNCTION_TRANSPOSE:                 */ { false, false, false },
14634                 /* FUNCTION_TRUNC:                     */ { true, true, false },
14635                 /* FUNCTION_UNPACKDOUBLE2X32:          */ { true, false, false },
14636                 /* FUNCTION_ISNAN:                     */ { true, true, false },
14637                 /* FUNCTION_ISINF:                     */ { true, true, false },
14638         };
14639
14640         bool result = look_up_table[function][type.m_general_type];
14641
14642         if (true == result)
14643         {
14644                 switch (function)
14645                 {
14646                 case FUNCTION_CROSS: /* Only 3 element vectors */
14647                         result = (3 == type.m_n_rows);
14648                         break;
14649                 case FUNCTION_DETERMINANT: /* Only square matrices */
14650                 case FUNCTION_INVERSE:
14651                         result = (type.m_n_columns == type.m_n_rows);
14652                         break;
14653                 default:
14654                         break;
14655                 }
14656         }
14657
14658         return result;
14659 }
14660
14661 /** Logs variable of given type: name (type) [values]
14662  *
14663  * @param buffer Source of data
14664  * @param name   Name of variable
14665  * @param type   Type of variable
14666  **/
14667 void GPUShaderFP64Test10::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14668                                                                                   Utils::_variable_type type) const
14669 {
14670         const Utils::_variable_type base_type   = Utils::getBaseVariableType(type);
14671         const glw::GLuint                       n_components = Utils::getNumberOfComponentsForVariableType(type);
14672         tcu::MessageBuilder                     message          = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14673
14674         message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14675
14676         for (glw::GLuint component = 0; component < n_components; ++component)
14677         {
14678                 if (0 != component)
14679                 {
14680                         message << ", ";
14681                 }
14682
14683                 switch (base_type)
14684                 {
14685                 case Utils::VARIABLE_TYPE_DOUBLE:
14686                         message << ((glw::GLdouble*)buffer)[component];
14687                         break;
14688                 case Utils::VARIABLE_TYPE_INT:
14689                         message << ((glw::GLint*)buffer)[component];
14690                         break;
14691                 case Utils::VARIABLE_TYPE_UINT:
14692                         message << ((glw::GLuint*)buffer)[component];
14693                         break;
14694                 default:
14695                         TCU_FAIL("Not implemented");
14696                 }
14697         }
14698
14699         message << "]" << tcu::TestLog::EndMessage;
14700 }
14701
14702 /** Prepare input arguments, data are stored in <buffer>
14703  *
14704  * @param function_object Function object
14705  * @param vertex          Vertex index
14706  * @param buffer          Buffer pointer
14707  **/
14708 void GPUShaderFP64Test10::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14709                                                                                   glw::GLubyte* buffer)
14710 {
14711         const glw::GLuint n_arguments = function_object.getArgumentCount();
14712
14713         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14714         {
14715                 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14716
14717                 prepareComponents(function_object, vertex, argument, buffer + offset);
14718         }
14719 }
14720
14721 /** Prepare components for given <function_object>, <vertex> and <argument>
14722  *
14723  * @param function_object Function object
14724  * @param vertex          Vertex index
14725  * @param argument        Argument index
14726  * @param buffer          Buffer pointer
14727  **/
14728 void GPUShaderFP64Test10::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14729                                                                                         glw::GLuint argument, glw::GLubyte* buffer)
14730 {
14731         glw::GLuint                                     argument_index[3]                = { 0 };
14732         glw::GLuint                                     argument_reset[3]                = { 0 };
14733         glw::GLuint                                     argument_step[3]                 = { 0 };
14734         glw::GLdouble                           double_argument_start[3] = { 0.0 };
14735         const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14736         glw::GLuint                                     int_argument_start  = -4;
14737         const glw::GLuint                       n_arguments                     = function_object.getArgumentCount();
14738         const glw::GLuint                       n_components            = function_object.getArgumentComponents(argument);
14739         glw::GLuint                                     uint_argument_start = 0;
14740
14741         switch (n_arguments)
14742         {
14743         case 1:
14744                 argument_step[0]                 = 1;
14745                 argument_reset[0]                = 1024;
14746                 double_argument_start[0] = -511.5;
14747                 break;
14748         case 2:
14749                 argument_step[0]                 = 32;
14750                 argument_step[1]                 = 1;
14751                 argument_reset[0]                = 32;
14752                 argument_reset[1]                = 32;
14753                 double_argument_start[0] = -15.5;
14754                 double_argument_start[1] = -15.5;
14755                 break;
14756         case 3:
14757                 argument_step[0]                 = 64;
14758                 argument_step[1]                 = 8;
14759                 argument_step[2]                 = 1;
14760                 argument_reset[0]                = 16;
14761                 argument_reset[1]                = 8;
14762                 argument_reset[2]                = 8;
14763                 double_argument_start[0] = -7.5;
14764                 double_argument_start[1] = -3.5;
14765                 double_argument_start[2] = -3.5;
14766                 break;
14767         default:
14768                 TCU_FAIL("Not implemented");
14769                 return;
14770                 break;
14771         };
14772
14773         switch (function_object.getFunctionEnum())
14774         {
14775         case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14776         case FUNCTION_CLAMP_AGAINST_SCALAR:
14777                 double_argument_start[2] = 4.5;
14778                 break;
14779         case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14780                 double_argument_start[0] = 16.5;
14781                 break;
14782         case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14783         case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14784                 argument_step[0]                 = 1;
14785                 argument_step[1]                 = 8;
14786                 argument_step[2]                 = 64;
14787                 argument_reset[0]                = 8;
14788                 argument_reset[1]                = 8;
14789                 argument_reset[2]                = 16;
14790                 double_argument_start[0] = -3.5;
14791                 double_argument_start[1] = 4.5;
14792                 double_argument_start[2] = -7.5;
14793                 break;
14794         default:
14795                 break;
14796         }
14797
14798         for (glw::GLuint i = 0; i < n_arguments; ++i)
14799         {
14800                 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14801         }
14802
14803         switch (base_arg_type)
14804         {
14805         case Utils::VARIABLE_TYPE_DOUBLE:
14806         {
14807                 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14808
14809                 double_argument_start[argument] += argument_index[argument];
14810
14811                 for (glw::GLuint component = 0; component < n_components; ++component)
14812                 {
14813                         glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14814
14815                         switch (function_object.getFunctionEnum())
14816                         {
14817                         case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14818                                 if (0.5 == Math::fract(value))
14819                                 {
14820                                         value += 0.01;
14821                                 }
14822                                 break;
14823                         default:
14824                                 break;
14825                         }
14826
14827                         argument_dst[component] = value;
14828                 }
14829         }
14830         break;
14831         case Utils::VARIABLE_TYPE_INT:
14832         {
14833                 glw::GLint* argument_dst = (glw::GLint*)buffer;
14834
14835                 uint_argument_start += argument_index[argument];
14836
14837                 for (glw::GLuint component = 0; component < n_components; ++component)
14838                 {
14839                         const glw::GLint value = int_argument_start + component;
14840
14841                         argument_dst[component] = value;
14842                 }
14843         }
14844         break;
14845         case Utils::VARIABLE_TYPE_UINT:
14846         {
14847                 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14848
14849                 uint_argument_start += argument_index[argument];
14850
14851                 for (glw::GLuint component = 0; component < n_components; ++component)
14852                 {
14853                         const glw::GLuint value = uint_argument_start + component;
14854
14855                         argument_dst[component] = value;
14856                 }
14857         }
14858         break;
14859         default:
14860                 TCU_FAIL("Not implemented");
14861                 return;
14862                 break;
14863         }
14864 }
14865
14866 /** Prepare collection of function enumerations
14867  *
14868  **/
14869 void GPUShaderFP64Test10::prepareFunctions()
14870 {
14871         m_functions.push_back(FUNCTION_ABS);
14872         m_functions.push_back(FUNCTION_CEIL);
14873         m_functions.push_back(FUNCTION_CLAMP);
14874         m_functions.push_back(FUNCTION_CLAMP_AGAINST_SCALAR);
14875         m_functions.push_back(FUNCTION_CROSS);
14876         m_functions.push_back(FUNCTION_DETERMINANT);
14877         m_functions.push_back(FUNCTION_DISTANCE);
14878         m_functions.push_back(FUNCTION_DOT);
14879         m_functions.push_back(FUNCTION_EQUAL);
14880         m_functions.push_back(FUNCTION_FACEFORWARD);
14881         m_functions.push_back(FUNCTION_FLOOR);
14882         m_functions.push_back(FUNCTION_FMA);
14883         m_functions.push_back(FUNCTION_FRACT);
14884         m_functions.push_back(FUNCTION_FREXP);
14885         m_functions.push_back(FUNCTION_GREATERTHAN);
14886         m_functions.push_back(FUNCTION_GREATERTHANEQUAL);
14887         m_functions.push_back(FUNCTION_INVERSE);
14888         m_functions.push_back(FUNCTION_INVERSESQRT);
14889         m_functions.push_back(FUNCTION_LDEXP);
14890         m_functions.push_back(FUNCTION_LESSTHAN);
14891         m_functions.push_back(FUNCTION_LESSTHANEQUAL);
14892         m_functions.push_back(FUNCTION_LENGTH);
14893         m_functions.push_back(FUNCTION_MATRIXCOMPMULT);
14894         m_functions.push_back(FUNCTION_MAX);
14895         m_functions.push_back(FUNCTION_MAX_AGAINST_SCALAR);
14896         m_functions.push_back(FUNCTION_MIN);
14897         m_functions.push_back(FUNCTION_MIN_AGAINST_SCALAR);
14898         m_functions.push_back(FUNCTION_MIX);
14899         m_functions.push_back(FUNCTION_MOD);
14900         m_functions.push_back(FUNCTION_MOD_AGAINST_SCALAR);
14901         m_functions.push_back(FUNCTION_MODF);
14902         m_functions.push_back(FUNCTION_NORMALIZE);
14903         m_functions.push_back(FUNCTION_NOTEQUAL);
14904         m_functions.push_back(FUNCTION_OUTERPRODUCT);
14905         m_functions.push_back(FUNCTION_PACKDOUBLE2X32);
14906         m_functions.push_back(FUNCTION_REFLECT);
14907         m_functions.push_back(FUNCTION_REFRACT);
14908         m_functions.push_back(FUNCTION_ROUND);
14909         m_functions.push_back(FUNCTION_ROUNDEVEN);
14910         m_functions.push_back(FUNCTION_SIGN);
14911         m_functions.push_back(FUNCTION_SMOOTHSTEP);
14912         m_functions.push_back(FUNCTION_SMOOTHSTEP_AGAINST_SCALAR);
14913         m_functions.push_back(FUNCTION_SQRT);
14914         m_functions.push_back(FUNCTION_STEP);
14915         m_functions.push_back(FUNCTION_STEP_AGAINST_SCALAR);
14916         m_functions.push_back(FUNCTION_TRANSPOSE);
14917         m_functions.push_back(FUNCTION_TRUNC);
14918         m_functions.push_back(FUNCTION_UNPACKDOUBLE2X32);
14919         m_functions.push_back(FUNCTION_ISNAN);
14920         m_functions.push_back(FUNCTION_ISINF);
14921 }
14922
14923 /** Prepare programInfo for given functionObject
14924  *
14925  * @param function_object  Function object
14926  * @param out_program_info Program info
14927  **/
14928 void GPUShaderFP64Test10::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14929 {
14930         const glw::GLuint                 n_varying_names  = function_object.getResultCount();
14931         static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14932
14933         prepareVertexShaderCode(function_object);
14934
14935         out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14936                                                    varying_names, n_varying_names);
14937 }
14938
14939 /** Prepare input data and expected results for given function object
14940  *
14941  * @param function_object Function object
14942  **/
14943 void GPUShaderFP64Test10::prepareTestData(const functionObject& function_object)
14944 {
14945         const glw::GLuint result_stride            = function_object.getResultStride();
14946         const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
14947         const glw::GLuint argument_stride         = function_object.getArgumentStride();
14948         const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14949
14950         m_argument_data.clear();
14951         m_expected_results_data.clear();
14952
14953         m_argument_data.resize(argument_buffer_size);
14954         m_expected_results_data.resize(result_buffer_size);
14955
14956         for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14957         {
14958                 const glw::GLuint result_offset   = vertex * result_stride;
14959                 glw::GLdouble*  result_dst        = (glw::GLdouble*)&m_expected_results_data[result_offset];
14960                 const glw::GLuint argument_offset = vertex * argument_stride;
14961                 glw::GLubyte*    argument_dst   = &m_argument_data[argument_offset];
14962
14963                 prepareArgument(function_object, vertex, argument_dst);
14964                 function_object.call(result_dst, argument_dst);
14965         }
14966 }
14967
14968 /** Prepare collection of types
14969  *
14970  **/
14971 void GPUShaderFP64Test10::prepareTypes()
14972 {
14973         m_types.push_back(typeDetails(1 /* n_columns */, 1 /* n_rows */));
14974         m_types.push_back(typeDetails(1 /* n_columns */, 2 /* n_rows */));
14975         m_types.push_back(typeDetails(1 /* n_columns */, 3 /* n_rows */));
14976         m_types.push_back(typeDetails(1 /* n_columns */, 4 /* n_rows */));
14977         m_types.push_back(typeDetails(2 /* n_columns */, 2 /* n_rows */));
14978         m_types.push_back(typeDetails(2 /* n_columns */, 3 /* n_rows */));
14979         m_types.push_back(typeDetails(2 /* n_columns */, 4 /* n_rows */));
14980         m_types.push_back(typeDetails(3 /* n_columns */, 2 /* n_rows */));
14981         m_types.push_back(typeDetails(3 /* n_columns */, 3 /* n_rows */));
14982         m_types.push_back(typeDetails(3 /* n_columns */, 4 /* n_rows */));
14983         m_types.push_back(typeDetails(4 /* n_columns */, 2 /* n_rows */));
14984         m_types.push_back(typeDetails(4 /* n_columns */, 3 /* n_rows */));
14985         m_types.push_back(typeDetails(4 /* n_columns */, 4 /* n_rows */));
14986 }
14987
14988 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14989  *
14990  * @param function_object Function object
14991  **/
14992 void GPUShaderFP64Test10::prepareVertexShaderCode(const functionObject& function_object)
14993 {
14994         static const glw::GLchar* shader_template_code = "#version 400 core\n"
14995                                                                                                          "\n"
14996                                                                                                          "precision highp float;\n"
14997                                                                                                          "\n"
14998                                                                                                          "ARGUMENT_DEFINITION"
14999                                                                                                          "\n"
15000                                                                                                          "RESULT_DEFINITION"
15001                                                                                                          "\n"
15002                                                                                                          "void main()\n"
15003                                                                                                          "{\n"
15004                                                                                                          "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
15005                                                                                                          "}\n"
15006                                                                                                          "\n";
15007
15008         static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15009         static const glw::GLchar* argument_token                        = "ARGUMENT";
15010         static const glw::GLchar* function_name_token           = "FUNCTION_NAME";
15011         static const glw::GLchar* result_definition_token   = "RESULT_DEFINITION";
15012         static const glw::GLchar* result_name_token                     = "RESULT_NAME";
15013         static const glw::GLchar* result_type_token                     = "RESULT_TYPE";
15014         static const glw::GLchar* uniform_name_token            = "UNIFORM_NAME";
15015         static const glw::GLchar* uniform_type_token            = "UNIFORM_TYPE";
15016
15017         static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15018         static const glw::GLchar* argument_str            = ", UNIFORM_NAMEARGUMENT";
15019         static const glw::GLchar* first_argument          = "UNIFORM_NAMEARGUMENT";
15020         static const glw::GLchar* result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15021
15022         const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15023         const glw::GLuint first_argument_length          = (glw::GLuint)strlen(first_argument);
15024         const glw::GLuint n_arguments                            = function_object.getArgumentCount();
15025         const glw::GLuint n_results                                      = function_object.getResultCount();
15026         const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15027         std::string               result_type                            = Utils::getVariableTypeString(function_object.getResultType(0));
15028
15029         size_t          search_position = 0;
15030         std::string string                      = shader_template_code;
15031
15032         /* Replace ARGUMENT_DEFINITION with definitions */
15033         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15034         {
15035                 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15036                 const glw::GLchar*      uniform_name  = getUniformName(argument);
15037                 std::string                       uniform_type  = Utils::getVariableTypeString(argument_type);
15038
15039                 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15040
15041                 search_position -= argument_definition_length;
15042
15043                 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15044                 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15045         }
15046
15047         /* Remove ARGUMENT_DEFINITION */
15048         Utils::replaceToken(argument_definition_token, search_position, "", string);
15049
15050         /* Replace RESULT_DEFINITION with definitions */
15051         for (glw::GLuint result = 0; result < n_results; ++result)
15052         {
15053                 Utils::_variable_type variable_type = function_object.getResultType(result);
15054                 const glw::GLchar*      varying_name  = getVaryingName(result);
15055                 std::string                       varying_type  = Utils::getVariableTypeString(variable_type);
15056
15057                 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15058
15059                 search_position -= result_definition_length;
15060
15061                 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15062                 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15063         }
15064
15065         /* Remove RESULT_DEFINITION */
15066         Utils::replaceToken(result_definition_token, search_position, "", string);
15067
15068         /* Replace RESULT_NAME */
15069         Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15070
15071         /* Replace RESULT_TYPE */
15072         Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15073
15074         /* Replace FUNCTION_NAME */
15075         Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15076
15077         /* Replace ARGUMENT with list of arguments */
15078         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15079         {
15080                 const glw::GLchar* uniform_name = getUniformName(argument);
15081
15082                 if (0 == argument)
15083                 {
15084                         Utils::replaceToken(argument_token, search_position, first_argument, string);
15085                 }
15086                 else
15087                 {
15088                         Utils::replaceToken(argument_token, search_position, argument_str, string);
15089                 }
15090
15091                 search_position -= first_argument_length;
15092
15093                 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15094         }
15095
15096         for (glw::GLuint result = 1; result < n_results; ++result)
15097         {
15098                 const glw::GLchar* varying_name = getVaryingName(result);
15099
15100                 Utils::replaceToken(argument_token, search_position, argument_str, string);
15101
15102                 search_position -= first_argument_length;
15103
15104                 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15105         }
15106
15107         /* Remove ARGUMENT */
15108         Utils::replaceToken(argument_token, search_position, "", string);
15109
15110         m_vertex_shader_code = string;
15111 }
15112
15113 /** Test single function with one type
15114  *
15115  * param function Function enumeration
15116  * param type     Type details
15117  *
15118  * @return true if test pass (or function is not available for <type>), false otherwise
15119  **/
15120 bool GPUShaderFP64Test10::test(functionEnum function, const typeDetails& type)
15121 {
15122         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15123
15124         /* Skip if function is not implemented for type */
15125         if (false == isFunctionImplemented(function, type))
15126         {
15127                 return true;
15128         }
15129
15130         Utils::programInfo                        program(m_context);
15131         de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15132
15133         prepareProgram(*function_object, program);
15134         prepareTestData(*function_object);
15135
15136         /* Set up program */
15137         gl.useProgram(program.m_program_object_id);
15138         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15139
15140         for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15141         {
15142                 testBegin(*function_object, program.m_program_object_id, vertex);
15143
15144                 gl.beginTransformFeedback(GL_POINTS);
15145                 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15146
15147                 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15148                 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15149
15150                 gl.endTransformFeedback();
15151                 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15152
15153                 if (false == verifyResults(*function_object, vertex))
15154                 {
15155                         return false;
15156                 }
15157         }
15158
15159         return true;
15160 }
15161
15162 /** Update transform feedback buffer and uniforms
15163  *
15164  * @param function_object Function object
15165  * @param program_id      Program object id
15166  * @param vertex          Vertex index
15167  **/
15168 void GPUShaderFP64Test10::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15169 {
15170         const glw::GLuint        arguments_stride   = function_object.getArgumentStride();
15171         const glw::Functions& gl                                 = m_context.getRenderContext().getFunctions();
15172         const glw::GLuint        n_arguments             = function_object.getArgumentCount();
15173         const glw::GLuint        result_buffer_size = function_object.getResultStride();
15174         const glw::GLuint        vertex_offset           = arguments_stride * vertex;
15175
15176         /* Update transform feedback buffer */
15177         std::vector<glw::GLubyte> transform_feedback_buffer_data;
15178         transform_feedback_buffer_data.resize(result_buffer_size);
15179
15180         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15181         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15182
15183         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15184                                   GL_DYNAMIC_COPY);
15185         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15186
15187         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15188                                            result_buffer_size);
15189         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15190
15191         /* Update VAO */
15192         gl.bindVertexArray(m_vertex_array_object_id);
15193         GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15194
15195         for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15196         {
15197                 const glw::GLuint                       argument_offset  = function_object.getArgumentOffset(argument);
15198                 const Utils::_variable_type argument_type       = function_object.getArgumentType(argument);
15199                 const glw::GLuint                       n_columns                = Utils::getNumberOfColumnsForVariableType(argument_type);
15200                 const glw::GLchar*                      uniform_name     = getUniformName(argument);
15201                 const glw::GLint                        uniform_location = gl.getUniformLocation(program_id, uniform_name);
15202                 const glw::GLdouble*            uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15203
15204                 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15205
15206                 if (-1 == uniform_location)
15207                 {
15208                         TCU_FAIL("Inactive uniform");
15209                 }
15210
15211                 if (1 == n_columns)
15212                 {
15213                         switch (Utils::getBaseVariableType(argument_type))
15214                         {
15215                         case Utils::VARIABLE_TYPE_DOUBLE:
15216                         {
15217                                 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15218
15219                                 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15220                         }
15221                         break;
15222                         case Utils::VARIABLE_TYPE_UINT:
15223                         {
15224                                 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15225
15226                                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15227                         }
15228                         break;
15229                         case Utils::VARIABLE_TYPE_INT:
15230                         {
15231                                 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15232
15233                                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15234                         }
15235                         break;
15236                         default:
15237                                 TCU_FAIL("Not implemented");
15238                                 break;
15239                         }
15240                 }
15241                 else
15242                 {
15243                         uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15244
15245                         p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15246                 }
15247         }
15248 }
15249
15250 /** Init GL obejcts
15251  *
15252  **/
15253 void GPUShaderFP64Test10::testInit()
15254 {
15255         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15256
15257         prepareFunctions();
15258         prepareTypes();
15259
15260         gl.genBuffers(1, &m_transform_feedback_buffer_id);
15261         GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15262
15263         gl.genVertexArrays(1, &m_vertex_array_object_id);
15264         GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15265
15266         gl.enable(GL_RASTERIZER_DISCARD);
15267 }
15268
15269 /** Compare contents of transform feedback buffer with expected results
15270  *
15271  * @param function_object Function object
15272  * @param vertex          Vertex index
15273  *
15274  * @return true if all results are as expected, false otherwise
15275  **/
15276 bool GPUShaderFP64Test10::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15277 {
15278         const glw::Functions& gl                           = m_context.getRenderContext().getFunctions();
15279         bool                              test_result     = true;
15280         const glw::GLuint        n_results                 = function_object.getResultCount();
15281         const glw::GLuint        results_stride   = function_object.getResultStride();
15282         const glw::GLuint        results_offset   = vertex * results_stride;
15283         const glw::GLubyte*   expected_results = &m_expected_results_data[results_offset];
15284
15285         /* Get transform feedback data */
15286         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15287         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15288
15289         glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15290         GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15291
15292         for (glw::GLuint result = 0; result < n_results; ++result)
15293         {
15294                 const Utils::_variable_type result_type   = function_object.getResultType(result);
15295                 const glw::GLuint                       result_offset = function_object.getResultOffset(result);
15296
15297                 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15298                 const glw::GLvoid* result_src              = feedback_data + result_offset;
15299
15300                 if (false == compare(result_type, expected_result_src, result_src))
15301                 {
15302                         test_result = false;
15303                         break;
15304                 }
15305         }
15306
15307         /* Unmap transform feedback buffer */
15308         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15309         GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15310
15311         if (false == test_result)
15312         {
15313                 const glw::GLuint argument_stride  = function_object.getArgumentStride();
15314                 const glw::GLuint arguments_offset = vertex * argument_stride;
15315
15316                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15317                                                                                         << tcu::TestLog::EndMessage;
15318
15319                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15320                                                                                         << tcu::TestLog::EndMessage;
15321
15322                 for (glw::GLuint result = 0; result < n_results; ++result)
15323                 {
15324                         const Utils::_variable_type result_type   = function_object.getResultType(result);
15325                         const glw::GLuint                       result_offset = function_object.getResultOffset(result);
15326
15327                         const glw::GLvoid* expected_result_src = expected_results + result_offset;
15328                         const glw::GLvoid* result_src              = feedback_data + result_offset;
15329
15330                         logVariableType(result_src, "Result", result_type);
15331                         logVariableType(expected_result_src, "Expected result", result_type);
15332                 }
15333
15334                 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15335                 {
15336                         const glw::GLuint   argument_offset = function_object.getArgumentOffset(argument);
15337                         const glw::GLubyte* argument_src        = &m_argument_data[arguments_offset + argument_offset];
15338
15339                         logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15340                 }
15341
15342                 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15343                                                                                         << m_vertex_shader_code << tcu::TestLog::EndMessage;
15344         }
15345
15346         return test_result;
15347 }
15348
15349 /** Constructor.
15350  *
15351  *  @param context Rendering context.
15352  **/
15353 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15354         : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15355 {
15356         /* Left blank on purpose */
15357 }
15358
15359 /** Initializes a texture_storage_multisample test group.
15360  *
15361  **/
15362 void GPUShaderFP64Tests::init(void)
15363 {
15364         addChild(new GPUShaderFP64Test1(m_context));
15365         addChild(new GPUShaderFP64Test2(m_context));
15366         addChild(new GPUShaderFP64Test3(m_context));
15367         addChild(new GPUShaderFP64Test4(m_context));
15368         addChild(new GPUShaderFP64Test5(m_context));
15369         addChild(new GPUShaderFP64Test6(m_context));
15370         addChild(new GPUShaderFP64Test7(m_context));
15371         addChild(new GPUShaderFP64Test8(m_context));
15372         addChild(new GPUShaderFP64Test9(m_context));
15373         addChild(new GPUShaderFP64Test10(m_context));
15374 }
15375
15376 } /* glcts namespace */