xref: /aosp_15_r20/external/deqp/external/openglcts/modules/gl/gl4cGPUShaderFP64Tests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  * \file  gl4GPUShaderFP64Tests.cpp
26  * \brief Implements conformance tests for "GPU Shader FP64" functionality.
27  */ /*-------------------------------------------------------------------*/
28 
29 #include "gl4cGPUShaderFP64Tests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuTestLog.hpp"
34 
35 #include <iomanip>
36 
37 #include "deMath.h"
38 #include "deUniquePtr.hpp"
39 #include "tcuMatrixUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 
42 #include <cstdlib>
43 #include <cstring>
44 #include <limits>
45 #include <memory>
46 
47 namespace gl4cts
48 {
49 
50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9;
51 
52 /** Constructor
53  *
54  * @param context Test context
55  **/
programInfo(deqp::Context & context)56 Utils::programInfo::programInfo(deqp::Context &context)
57     : m_context(context)
58     , m_compute_shader_id(0)
59     , m_fragment_shader_id(0)
60     , m_geometry_shader_id(0)
61     , m_program_object_id(0)
62     , m_tesselation_control_shader_id(0)
63     , m_tesselation_evaluation_shader_id(0)
64     , m_vertex_shader_id(0)
65 {
66     /* Nothing to be done here */
67 }
68 
69 /** Destructor
70  *
71  **/
~programInfo()72 Utils::programInfo::~programInfo()
73 {
74     /* GL entry points */
75     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
76 
77     /* Make sure program object is no longer used by GL */
78     gl.useProgram(0);
79 
80     /* Clean program object */
81     if (0 != m_program_object_id)
82     {
83         gl.deleteProgram(m_program_object_id);
84         m_program_object_id = 0;
85     }
86 
87     /* Clean shaders */
88     if (0 != m_compute_shader_id)
89     {
90         gl.deleteShader(m_compute_shader_id);
91         m_compute_shader_id = 0;
92     }
93 
94     if (0 != m_fragment_shader_id)
95     {
96         gl.deleteShader(m_fragment_shader_id);
97         m_fragment_shader_id = 0;
98     }
99 
100     if (0 != m_geometry_shader_id)
101     {
102         gl.deleteShader(m_geometry_shader_id);
103         m_geometry_shader_id = 0;
104     }
105 
106     if (0 != m_tesselation_control_shader_id)
107     {
108         gl.deleteShader(m_tesselation_control_shader_id);
109         m_tesselation_control_shader_id = 0;
110     }
111 
112     if (0 != m_tesselation_evaluation_shader_id)
113     {
114         gl.deleteShader(m_tesselation_evaluation_shader_id);
115         m_tesselation_evaluation_shader_id = 0;
116     }
117 
118     if (0 != m_vertex_shader_id)
119     {
120         gl.deleteShader(m_vertex_shader_id);
121         m_vertex_shader_id = 0;
122     }
123 }
124 
125 /** Build program
126  *
127  * @param compute_shader_code                Compute shader source code
128  * @param fragment_shader_code               Fragment shader source code
129  * @param geometry_shader_code               Geometry shader source code
130  * @param tesselation_control_shader_code    Tesselation control shader source code
131  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
132  * @param vertex_shader_code                 Vertex shader source code
133  * @param varying_names                      Array of strings containing names of varyings to be captured with transfrom feedback
134  * @param n_varying_names                    Number of varyings to be captured with transfrom feedback
135  **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names)136 void Utils::programInfo::build(const glw::GLchar *compute_shader_code, const glw::GLchar *fragment_shader_code,
137                                const glw::GLchar *geometry_shader_code,
138                                const glw::GLchar *tesselation_control_shader_code,
139                                const glw::GLchar *tesselation_evaluation_shader_code,
140                                const glw::GLchar *vertex_shader_code, const glw::GLchar *const *varying_names,
141                                glw::GLuint n_varying_names)
142 {
143     /* GL entry points */
144     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
145 
146     /* Create shader objects and compile */
147     if (0 != compute_shader_code)
148     {
149         m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
150         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
151 
152         compile(m_compute_shader_id, compute_shader_code);
153     }
154 
155     if (0 != fragment_shader_code)
156     {
157         m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
158         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
159 
160         compile(m_fragment_shader_id, fragment_shader_code);
161     }
162 
163     if (0 != geometry_shader_code)
164     {
165         m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
166         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
167 
168         compile(m_geometry_shader_id, geometry_shader_code);
169     }
170 
171     if (0 != tesselation_control_shader_code)
172     {
173         m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
174         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
175 
176         compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
177     }
178 
179     if (0 != tesselation_evaluation_shader_code)
180     {
181         m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
182         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
183 
184         compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
185     }
186 
187     if (0 != vertex_shader_code)
188     {
189         m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
190         GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
191 
192         compile(m_vertex_shader_id, vertex_shader_code);
193     }
194 
195     /* Create program object */
196     m_program_object_id = gl.createProgram();
197     GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
198 
199     /* Set up captyured varyings' names */
200     if (0 != n_varying_names)
201     {
202         gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
203         GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
204     }
205 
206     /* Link program */
207     link();
208 }
209 
210 /** Compile shader
211  *
212  * @param shader_id   Shader object id
213  * @param shader_code Shader source code
214  **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar *shader_code) const
216 {
217     /* GL entry points */
218     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
219 
220     /* Compilation status */
221     glw::GLint status = GL_FALSE;
222 
223     /* Set source code */
224     gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
225     GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
226 
227     /* Compile */
228     gl.compileShader(shader_id);
229     GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
230 
231     /* Get compilation status */
232     gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
233     GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
234 
235     /* Log compilation error */
236     if (GL_TRUE != status)
237     {
238         glw::GLint length = 0;
239         std::vector<glw::GLchar> message;
240 
241         /* Error log length */
242         gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
243         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
244 
245         /* Prepare storage */
246         message.resize(length);
247 
248         /* Get error log */
249         gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
250         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
251 
252         /* Log */
253         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
254                                             << &message[0] << "\nShader source\n"
255                                             << shader_code << tcu::TestLog::EndMessage;
256 
257         TCU_FAIL("Failed to compile shader");
258     }
259 }
260 
261 /** Attach shaders and link program
262  *
263  **/
link() const264 void Utils::programInfo::link() const
265 {
266     /* GL entry points */
267     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
268 
269     /* Link status */
270     glw::GLint status = GL_FALSE;
271 
272     /* Attach shaders */
273     if (0 != m_compute_shader_id)
274     {
275         gl.attachShader(m_program_object_id, m_compute_shader_id);
276         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
277     }
278 
279     if (0 != m_fragment_shader_id)
280     {
281         gl.attachShader(m_program_object_id, m_fragment_shader_id);
282         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
283     }
284 
285     if (0 != m_geometry_shader_id)
286     {
287         gl.attachShader(m_program_object_id, m_geometry_shader_id);
288         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
289     }
290 
291     if (0 != m_tesselation_control_shader_id)
292     {
293         gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
294         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
295     }
296 
297     if (0 != m_tesselation_evaluation_shader_id)
298     {
299         gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
300         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
301     }
302 
303     if (0 != m_vertex_shader_id)
304     {
305         gl.attachShader(m_program_object_id, m_vertex_shader_id);
306         GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
307     }
308 
309     /* Link */
310     gl.linkProgram(m_program_object_id);
311     GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
312 
313     /* Get link status */
314     gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
315     GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
316 
317     /* Log link error */
318     if (GL_TRUE != status)
319     {
320         glw::GLint length = 0;
321         std::vector<glw::GLchar> message;
322 
323         /* Get error log length */
324         gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
325         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
326 
327         message.resize(length);
328 
329         /* Get error log */
330         gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
331         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
332 
333         /* Log */
334         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
335                                             << &message[0] << tcu::TestLog::EndMessage;
336 
337         TCU_FAIL("Failed to link program");
338     }
339 }
340 
341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision
342  *  matrix types.
343  *
344  *  @param type Variable type to return base type for.
345  *
346  *  @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized.
347  **/
getBaseVariableType(_variable_type type)348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type)
349 {
350     _variable_type result = VARIABLE_TYPE_UNKNOWN;
351 
352     switch (type)
353     {
354     case VARIABLE_TYPE_BOOL:
355     {
356         result = VARIABLE_TYPE_BOOL;
357 
358         break;
359     }
360 
361     case VARIABLE_TYPE_DOUBLE:
362     case VARIABLE_TYPE_DMAT2:
363     case VARIABLE_TYPE_DMAT2X3:
364     case VARIABLE_TYPE_DMAT2X4:
365     case VARIABLE_TYPE_DMAT3:
366     case VARIABLE_TYPE_DMAT3X2:
367     case VARIABLE_TYPE_DMAT3X4:
368     case VARIABLE_TYPE_DMAT4:
369     case VARIABLE_TYPE_DMAT4X2:
370     case VARIABLE_TYPE_DMAT4X3:
371     case VARIABLE_TYPE_DVEC2:
372     case VARIABLE_TYPE_DVEC3:
373     case VARIABLE_TYPE_DVEC4:
374     {
375         result = VARIABLE_TYPE_DOUBLE;
376 
377         break;
378     }
379 
380     case VARIABLE_TYPE_INT:
381     case VARIABLE_TYPE_IVEC2:
382     case VARIABLE_TYPE_IVEC3:
383     case VARIABLE_TYPE_IVEC4:
384     {
385         result = VARIABLE_TYPE_INT;
386 
387         break;
388     }
389 
390     case VARIABLE_TYPE_UINT:
391     case VARIABLE_TYPE_UVEC2:
392     case VARIABLE_TYPE_UVEC3:
393     case VARIABLE_TYPE_UVEC4:
394     {
395         result = VARIABLE_TYPE_UINT;
396 
397         break;
398     }
399 
400     case VARIABLE_TYPE_FLOAT:
401     case VARIABLE_TYPE_MAT2:
402     case VARIABLE_TYPE_MAT2X3:
403     case VARIABLE_TYPE_MAT2X4:
404     case VARIABLE_TYPE_MAT3:
405     case VARIABLE_TYPE_MAT3X2:
406     case VARIABLE_TYPE_MAT3X4:
407     case VARIABLE_TYPE_MAT4:
408     case VARIABLE_TYPE_MAT4X2:
409     case VARIABLE_TYPE_MAT4X3:
410     case VARIABLE_TYPE_VEC2:
411     case VARIABLE_TYPE_VEC3:
412     case VARIABLE_TYPE_VEC4:
413     {
414         result = VARIABLE_TYPE_FLOAT;
415 
416         break;
417     }
418 
419     default:
420     {
421         TCU_FAIL("Unrecognized variable type");
422     }
423     } /* switch (type) */
424 
425     return result;
426 }
427 
428 /** Returns size (in bytes) of a single component of a base variable type.
429  *
430  *  @param type Base variable type to use for the query.
431  *
432  *  @return Requested value or 0 if @param type was not recognized.
433  **/
getBaseVariableTypeComponentSize(_variable_type type)434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type)
435 {
436     unsigned int result = 0;
437 
438     switch (type)
439     {
440     case VARIABLE_TYPE_BOOL:
441         result = sizeof(bool);
442         break;
443     case VARIABLE_TYPE_DOUBLE:
444         result = sizeof(double);
445         break;
446     case VARIABLE_TYPE_FLOAT:
447         result = sizeof(float);
448         break;
449     case VARIABLE_TYPE_INT:
450         result = sizeof(int);
451         break;
452     case VARIABLE_TYPE_UINT:
453         result = sizeof(unsigned int);
454         break;
455 
456     default:
457     {
458         TCU_FAIL("Unrecognized variable type");
459     }
460     } /* switch (type) */
461 
462     return result;
463 }
464 
465 /** Returns component, corresponding to user-specified index
466  *  (eg. index:0 corresponds to 'x', index:1 corresponds to 'y',
467  *  and so on.
468  *
469  *  @param index Component index.
470  *
471  *  @return As per description.
472  **/
getComponentAtIndex(unsigned int index)473 unsigned char Utils::getComponentAtIndex(unsigned int index)
474 {
475     unsigned char result = '?';
476 
477     switch (index)
478     {
479     case 0:
480         result = 'x';
481         break;
482     case 1:
483         result = 'y';
484         break;
485     case 2:
486         result = 'z';
487         break;
488     case 3:
489         result = 'w';
490         break;
491 
492     default:
493     {
494         TCU_FAIL("Unrecognized component index");
495     }
496     }
497 
498     return result;
499 }
500 
501 /** Get _variable_type representing double-precision type with given dimmensions
502  *
503  * @param n_columns Number of columns
504  * @param n_row     Number of rows
505  *
506  * @return Corresponding _variable_type
507  **/
getDoubleVariableType(glw::GLuint n_columns,glw::GLuint n_rows)508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
509 {
510     Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
511 
512     static const _variable_type types[4][4] = {
513         {VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4},
514         {VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4},
515         {VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4},
516         {VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4}};
517 
518     type = types[n_columns - 1][n_rows - 1];
519 
520     return type;
521 }
522 
523 /** Returns a single-precision equivalent of a double-precision floating-point variable
524  *  type.
525  *
526  *  @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
527  *              are accepted.
528  *
529  *  @return Requested GLSL type.
530  **/
getFPVariableTypeStringForVariableType(_variable_type type)531 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
532 {
533     std::string result = "[?]";
534 
535     switch (type)
536     {
537     case VARIABLE_TYPE_DOUBLE:
538         result = "float";
539         break;
540     case VARIABLE_TYPE_DMAT2:
541         result = "mat2";
542         break;
543     case VARIABLE_TYPE_DMAT2X3:
544         result = "mat2x3";
545         break;
546     case VARIABLE_TYPE_DMAT2X4:
547         result = "mat2x4";
548         break;
549     case VARIABLE_TYPE_DMAT3:
550         result = "mat3";
551         break;
552     case VARIABLE_TYPE_DMAT3X2:
553         result = "mat3x2";
554         break;
555     case VARIABLE_TYPE_DMAT3X4:
556         result = "mat3x4";
557         break;
558     case VARIABLE_TYPE_DMAT4:
559         result = "mat4";
560         break;
561     case VARIABLE_TYPE_DMAT4X2:
562         result = "mat4x2";
563         break;
564     case VARIABLE_TYPE_DMAT4X3:
565         result = "mat4x3";
566         break;
567     case VARIABLE_TYPE_DVEC2:
568         result = "vec2";
569         break;
570     case VARIABLE_TYPE_DVEC3:
571         result = "vec3";
572         break;
573     case VARIABLE_TYPE_DVEC4:
574         result = "vec4";
575         break;
576 
577     default:
578     {
579         TCU_FAIL("Unrecognized variable type");
580     }
581     } /* switch (type) */
582 
583     return result;
584 }
585 
586 /** Returns GL data type enum corresponding to user-provided base variable type.
587  *
588  *  @param type Base variable type to return corresponding GLenum value for.
589  *
590  *  @return Corresponding GLenum value or GL_NONE if the input value was not
591  *          recognized.
592  **/
getGLDataTypeOfBaseVariableType(_variable_type type)593 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
594 {
595     glw::GLenum result = GL_NONE;
596 
597     switch (type)
598     {
599     case VARIABLE_TYPE_BOOL:
600         result = GL_BOOL;
601         break;
602     case VARIABLE_TYPE_DOUBLE:
603         result = GL_DOUBLE;
604         break;
605     case VARIABLE_TYPE_FLOAT:
606         result = GL_FLOAT;
607         break;
608     case VARIABLE_TYPE_INT:
609         result = GL_INT;
610         break;
611     case VARIABLE_TYPE_UINT:
612         result = GL_UNSIGNED_INT;
613         break;
614 
615     default:
616     {
617         TCU_FAIL("Unrecognized variable type");
618     }
619     }
620 
621     return result;
622 }
623 
624 /** Return GLenum representing given <type>
625  *
626  * @param type Type of variable
627  *
628  * @return GL enumeration
629  **/
getGLDataTypeOfVariableType(_variable_type type)630 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
631 {
632     glw::GLenum result = GL_NONE;
633 
634     switch (type)
635     {
636     case VARIABLE_TYPE_BOOL:
637         result = GL_BOOL;
638         break;
639     case VARIABLE_TYPE_DOUBLE:
640         result = GL_DOUBLE;
641         break;
642     case VARIABLE_TYPE_DMAT2:
643         result = GL_DOUBLE_MAT2;
644         break;
645     case VARIABLE_TYPE_DMAT2X3:
646         result = GL_DOUBLE_MAT2x3;
647         break;
648     case VARIABLE_TYPE_DMAT2X4:
649         result = GL_DOUBLE_MAT2x4;
650         break;
651     case VARIABLE_TYPE_DMAT3:
652         result = GL_DOUBLE_MAT3;
653         break;
654     case VARIABLE_TYPE_DMAT3X2:
655         result = GL_DOUBLE_MAT3x2;
656         break;
657     case VARIABLE_TYPE_DMAT3X4:
658         result = GL_DOUBLE_MAT3x4;
659         break;
660     case VARIABLE_TYPE_DMAT4:
661         result = GL_DOUBLE_MAT4;
662         break;
663     case VARIABLE_TYPE_DMAT4X2:
664         result = GL_DOUBLE_MAT4x2;
665         break;
666     case VARIABLE_TYPE_DMAT4X3:
667         result = GL_DOUBLE_MAT4x3;
668         break;
669     case VARIABLE_TYPE_DVEC2:
670         result = GL_DOUBLE_VEC2;
671         break;
672     case VARIABLE_TYPE_DVEC3:
673         result = GL_DOUBLE_VEC3;
674         break;
675     case VARIABLE_TYPE_DVEC4:
676         result = GL_DOUBLE_VEC4;
677         break;
678     case VARIABLE_TYPE_FLOAT:
679         result = GL_FLOAT;
680         break;
681     case VARIABLE_TYPE_INT:
682         result = GL_INT;
683         break;
684     case VARIABLE_TYPE_IVEC2:
685         result = GL_INT_VEC2;
686         break;
687     case VARIABLE_TYPE_IVEC3:
688         result = GL_INT_VEC3;
689         break;
690     case VARIABLE_TYPE_IVEC4:
691         result = GL_INT_VEC4;
692         break;
693     case VARIABLE_TYPE_MAT2:
694         result = GL_FLOAT_MAT2;
695         break;
696     case VARIABLE_TYPE_MAT2X3:
697         result = GL_FLOAT_MAT2x3;
698         break;
699     case VARIABLE_TYPE_MAT2X4:
700         result = GL_FLOAT_MAT2x4;
701         break;
702     case VARIABLE_TYPE_MAT3:
703         result = GL_FLOAT_MAT3;
704         break;
705     case VARIABLE_TYPE_MAT3X2:
706         result = GL_FLOAT_MAT3x2;
707         break;
708     case VARIABLE_TYPE_MAT3X4:
709         result = GL_FLOAT_MAT3x4;
710         break;
711     case VARIABLE_TYPE_MAT4:
712         result = GL_FLOAT_MAT4;
713         break;
714     case VARIABLE_TYPE_MAT4X2:
715         result = GL_FLOAT_MAT4x2;
716         break;
717     case VARIABLE_TYPE_MAT4X3:
718         result = GL_FLOAT_MAT4x3;
719         break;
720     case VARIABLE_TYPE_UINT:
721         result = GL_UNSIGNED_INT;
722         break;
723     case VARIABLE_TYPE_UVEC2:
724         result = GL_UNSIGNED_INT_VEC2;
725         break;
726     case VARIABLE_TYPE_UVEC3:
727         result = GL_UNSIGNED_INT_VEC3;
728         break;
729     case VARIABLE_TYPE_UVEC4:
730         result = GL_UNSIGNED_INT_VEC4;
731         break;
732     case VARIABLE_TYPE_VEC2:
733         result = GL_FLOAT_VEC2;
734         break;
735     case VARIABLE_TYPE_VEC3:
736         result = GL_FLOAT_VEC3;
737         break;
738     case VARIABLE_TYPE_VEC4:
739         result = GL_FLOAT_VEC4;
740         break;
741 
742     default:
743     {
744         TCU_FAIL("Unrecognized variable type");
745     }
746     }
747 
748     return result;
749 }
750 
751 /** Get _variable_type representing integer type with given dimmensions
752  *
753  * @param n_columns Number of columns
754  * @param n_row     Number of rows
755  *
756  * @return Corresponding _variable_type
757  **/
getIntVariableType(glw::GLuint n_columns,glw::GLuint n_rows)758 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
759 {
760     Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
761 
762     static const _variable_type types[4] = {VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
763                                             VARIABLE_TYPE_IVEC4};
764 
765     if (1 != n_columns)
766     {
767         TCU_FAIL("Not implemented");
768     }
769     else
770     {
771         type = types[n_rows - 1];
772     }
773 
774     return type;
775 }
776 
777 /** Returns te number of components that variables defined with user-specified type
778  *  support. For matrix types, total amount of values accessible for the type will be
779  *  returned.
780  *
781  *  @param type Variable type to return the described vale for.
782  *
783  *  @return As per description or 0 if @param type was not recognized.
784  */
getNumberOfComponentsForVariableType(_variable_type type)785 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
786 {
787     unsigned int result = 0;
788 
789     switch (type)
790     {
791     case VARIABLE_TYPE_BOOL:
792     case VARIABLE_TYPE_DOUBLE:
793     case VARIABLE_TYPE_FLOAT:
794     case VARIABLE_TYPE_INT:
795     case VARIABLE_TYPE_UINT:
796     {
797         result = 1;
798 
799         break;
800     }
801 
802     case VARIABLE_TYPE_DVEC2:
803     case VARIABLE_TYPE_IVEC2:
804     case VARIABLE_TYPE_UVEC2:
805     case VARIABLE_TYPE_VEC2:
806     {
807         result = 2;
808 
809         break;
810     }
811 
812     case VARIABLE_TYPE_DVEC3:
813     case VARIABLE_TYPE_IVEC3:
814     case VARIABLE_TYPE_UVEC3:
815     case VARIABLE_TYPE_VEC3:
816     {
817         result = 3;
818 
819         break;
820     }
821 
822     case VARIABLE_TYPE_DVEC4:
823     case VARIABLE_TYPE_IVEC4:
824     case VARIABLE_TYPE_UVEC4:
825     case VARIABLE_TYPE_VEC4:
826     {
827         result = 4;
828 
829         break;
830     }
831 
832     case VARIABLE_TYPE_DMAT2:
833     case VARIABLE_TYPE_MAT2:
834     {
835         result = 2 * 2;
836 
837         break;
838     }
839 
840     case VARIABLE_TYPE_DMAT2X3:
841     case VARIABLE_TYPE_DMAT3X2:
842     case VARIABLE_TYPE_MAT2X3:
843     case VARIABLE_TYPE_MAT3X2:
844     {
845         result = 2 * 3;
846 
847         break;
848     }
849 
850     case VARIABLE_TYPE_DMAT2X4:
851     case VARIABLE_TYPE_DMAT4X2:
852     case VARIABLE_TYPE_MAT2X4:
853     case VARIABLE_TYPE_MAT4X2:
854     {
855         result = 2 * 4;
856 
857         break;
858     }
859 
860     case VARIABLE_TYPE_DMAT3:
861     case VARIABLE_TYPE_MAT3:
862     {
863         result = 3 * 3;
864 
865         break;
866     }
867 
868     case VARIABLE_TYPE_DMAT3X4:
869     case VARIABLE_TYPE_DMAT4X3:
870     case VARIABLE_TYPE_MAT3X4:
871     case VARIABLE_TYPE_MAT4X3:
872     {
873         result = 3 * 4;
874 
875         break;
876     }
877 
878     case VARIABLE_TYPE_DMAT4:
879     case VARIABLE_TYPE_MAT4:
880     {
881         result = 4 * 4;
882 
883         break;
884     }
885 
886     default:
887     {
888         TCU_FAIL("Unrecognized type");
889     }
890     } /* switch (type) */
891 
892     return result;
893 }
894 
895 /** Returns number of columns user-specified matrix variable type describes.
896  *
897  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
898  *              values are valid.
899  *
900  *  @return As per description.
901  **/
getNumberOfColumnsForVariableType(_variable_type type)902 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
903 {
904     unsigned int result = 0;
905 
906     switch (type)
907     {
908     case VARIABLE_TYPE_BOOL:
909     case VARIABLE_TYPE_DOUBLE:
910     case VARIABLE_TYPE_FLOAT:
911     case VARIABLE_TYPE_INT:
912     case VARIABLE_TYPE_UINT:
913     case VARIABLE_TYPE_DVEC2:
914     case VARIABLE_TYPE_IVEC2:
915     case VARIABLE_TYPE_UVEC2:
916     case VARIABLE_TYPE_VEC2:
917     case VARIABLE_TYPE_DVEC3:
918     case VARIABLE_TYPE_IVEC3:
919     case VARIABLE_TYPE_UVEC3:
920     case VARIABLE_TYPE_VEC3:
921     case VARIABLE_TYPE_DVEC4:
922     case VARIABLE_TYPE_IVEC4:
923     case VARIABLE_TYPE_UVEC4:
924     case VARIABLE_TYPE_VEC4:
925     {
926         result = 1;
927 
928         break;
929     }
930 
931     case VARIABLE_TYPE_DMAT2:
932     case VARIABLE_TYPE_DMAT2X3:
933     case VARIABLE_TYPE_DMAT2X4:
934     case VARIABLE_TYPE_MAT2:
935     case VARIABLE_TYPE_MAT2X3:
936     case VARIABLE_TYPE_MAT2X4:
937     {
938         result = 2;
939 
940         break;
941     }
942 
943     case VARIABLE_TYPE_DMAT3:
944     case VARIABLE_TYPE_DMAT3X2:
945     case VARIABLE_TYPE_DMAT3X4:
946     case VARIABLE_TYPE_MAT3:
947     case VARIABLE_TYPE_MAT3X2:
948     case VARIABLE_TYPE_MAT3X4:
949     {
950         result = 3;
951 
952         break;
953     }
954 
955     case VARIABLE_TYPE_DMAT4:
956     case VARIABLE_TYPE_DMAT4X2:
957     case VARIABLE_TYPE_DMAT4X3:
958     case VARIABLE_TYPE_MAT4:
959     case VARIABLE_TYPE_MAT4X2:
960     case VARIABLE_TYPE_MAT4X3:
961     {
962         result = 4;
963 
964         break;
965     }
966 
967     default:
968     {
969         TCU_FAIL("Unrecognized type");
970     }
971     } /* switch (type) */
972 
973     return result;
974 }
975 
976 /** Returns maximum number of uniform locations taken by user-specified double-precision
977  *  variable type.
978  *
979  *  @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
980  *
981  *  @return As per description.
982  **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)983 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
984 {
985     unsigned int result = 0;
986 
987     switch (type)
988     {
989     case VARIABLE_TYPE_DOUBLE:
990         result = 1;
991         break;
992     case VARIABLE_TYPE_DVEC2:
993         result = 1;
994         break;
995     case VARIABLE_TYPE_DVEC3:
996         result = 2;
997         break;
998     case VARIABLE_TYPE_DVEC4:
999         result = 2;
1000         break;
1001     case VARIABLE_TYPE_DMAT2:
1002         result = 2;
1003         break;
1004     case VARIABLE_TYPE_DMAT2X3:
1005         result = 6;
1006         break;
1007     case VARIABLE_TYPE_DMAT2X4:
1008         result = 8;
1009         break;
1010     case VARIABLE_TYPE_DMAT3:
1011         result = 6;
1012         break;
1013     case VARIABLE_TYPE_DMAT3X2:
1014         result = 4;
1015         break;
1016     case VARIABLE_TYPE_DMAT3X4:
1017         result = 8;
1018         break;
1019     case VARIABLE_TYPE_DMAT4:
1020         result = 8;
1021         break;
1022     case VARIABLE_TYPE_DMAT4X2:
1023         result = 4;
1024         break;
1025     case VARIABLE_TYPE_DMAT4X3:
1026         result = 6;
1027         break;
1028 
1029     default:
1030     {
1031         TCU_FAIL("Unrecognized type");
1032     }
1033     } /* switch (type) */
1034 
1035     return result;
1036 }
1037 
1038 /** Get number of rows for given variable type
1039  *
1040  * @param type Type of variable
1041  *
1042  * @return Number of rows
1043  **/
getNumberOfRowsForVariableType(_variable_type type)1044 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1045 {
1046     unsigned int result = 0;
1047 
1048     switch (type)
1049     {
1050     case VARIABLE_TYPE_BOOL:
1051     case VARIABLE_TYPE_DOUBLE:
1052     case VARIABLE_TYPE_FLOAT:
1053     case VARIABLE_TYPE_INT:
1054     case VARIABLE_TYPE_UINT:
1055     {
1056         result = 1;
1057 
1058         break;
1059     }
1060 
1061     case VARIABLE_TYPE_DVEC2:
1062     case VARIABLE_TYPE_IVEC2:
1063     case VARIABLE_TYPE_UVEC2:
1064     case VARIABLE_TYPE_VEC2:
1065     case VARIABLE_TYPE_DMAT2:
1066     case VARIABLE_TYPE_DMAT3X2:
1067     case VARIABLE_TYPE_DMAT4X2:
1068     case VARIABLE_TYPE_MAT2:
1069     case VARIABLE_TYPE_MAT3X2:
1070     case VARIABLE_TYPE_MAT4X2:
1071     {
1072         result = 2;
1073 
1074         break;
1075     }
1076 
1077     case VARIABLE_TYPE_DVEC3:
1078     case VARIABLE_TYPE_IVEC3:
1079     case VARIABLE_TYPE_UVEC3:
1080     case VARIABLE_TYPE_VEC3:
1081     case VARIABLE_TYPE_DMAT2X3:
1082     case VARIABLE_TYPE_DMAT3:
1083     case VARIABLE_TYPE_DMAT4X3:
1084     case VARIABLE_TYPE_MAT2X3:
1085     case VARIABLE_TYPE_MAT3:
1086     case VARIABLE_TYPE_MAT4X3:
1087     {
1088         result = 3;
1089 
1090         break;
1091     }
1092 
1093     case VARIABLE_TYPE_DVEC4:
1094     case VARIABLE_TYPE_IVEC4:
1095     case VARIABLE_TYPE_UVEC4:
1096     case VARIABLE_TYPE_VEC4:
1097     case VARIABLE_TYPE_DMAT2X4:
1098     case VARIABLE_TYPE_DMAT3X4:
1099     case VARIABLE_TYPE_DMAT4:
1100     case VARIABLE_TYPE_MAT2X4:
1101     case VARIABLE_TYPE_MAT3X4:
1102     case VARIABLE_TYPE_MAT4:
1103     {
1104         result = 4;
1105 
1106         break;
1107     }
1108 
1109     default:
1110     {
1111         TCU_FAIL("Unrecognized type");
1112     }
1113     } /* switch (type) */
1114 
1115     return result;
1116 }
1117 
1118 /** Returns variable type of a matrix constructed by multiplying two matrices.
1119  *
1120  *  @param type_matrix_a L-side matrix type.
1121  *  @param type_matrix_b R-side matrix type.
1122  *
1123  *  @return As per description.
1124  **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,_variable_type type_matrix_b)1125 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1126                                                                      _variable_type type_matrix_b)
1127 {
1128     const unsigned int n_a_columns      = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1129     const unsigned int n_a_components   = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1130     const unsigned int n_a_rows         = n_a_components / n_a_columns;
1131     const unsigned int n_b_columns      = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1132     const unsigned int n_result_columns = n_b_columns;
1133     const unsigned int n_result_rows    = n_a_rows;
1134     Utils::_variable_type result;
1135 
1136     switch (n_result_columns)
1137     {
1138     case 2:
1139     {
1140         switch (n_result_rows)
1141         {
1142         case 2:
1143             result = VARIABLE_TYPE_DMAT2;
1144             break;
1145         case 3:
1146             result = VARIABLE_TYPE_DMAT2X3;
1147             break;
1148         case 4:
1149             result = VARIABLE_TYPE_DMAT2X4;
1150             break;
1151 
1152         default:
1153         {
1154             TCU_FAIL("Unrecognized amount of rows in result variable");
1155         }
1156         } /* switch (n_result_rows) */
1157 
1158         break;
1159     } /* case 2: */
1160 
1161     case 3:
1162     {
1163         switch (n_result_rows)
1164         {
1165         case 2:
1166             result = VARIABLE_TYPE_DMAT3X2;
1167             break;
1168         case 3:
1169             result = VARIABLE_TYPE_DMAT3;
1170             break;
1171         case 4:
1172             result = VARIABLE_TYPE_DMAT3X4;
1173             break;
1174 
1175         default:
1176         {
1177             TCU_FAIL("Unrecognized amount of rows in result variable");
1178         }
1179         } /* switch (n_result_rows) */
1180 
1181         break;
1182     } /* case 3: */
1183 
1184     case 4:
1185     {
1186         switch (n_result_rows)
1187         {
1188         case 2:
1189             result = VARIABLE_TYPE_DMAT4X2;
1190             break;
1191         case 3:
1192             result = VARIABLE_TYPE_DMAT4X3;
1193             break;
1194         case 4:
1195             result = VARIABLE_TYPE_DMAT4;
1196             break;
1197 
1198         default:
1199         {
1200             TCU_FAIL("Unrecognized amount of rows in result variable");
1201         }
1202         } /* switch (n_result_rows) */
1203 
1204         break;
1205     } /* case 4: */
1206 
1207     default:
1208     {
1209         TCU_FAIL("Unrecognized amount of columns in result variable");
1210     }
1211     } /* switch (n_result_columns) */
1212 
1213     /* Done */
1214     return result;
1215 }
1216 
1217 /** Returns a string holding the value represented by user-provided variable, for which
1218  *  the data are represented in @param type variable type.
1219  *
1220  *  @return As per description.
1221  **/
getStringForVariableTypeValue(_variable_type type,const unsigned char * data_ptr)1222 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char *data_ptr)
1223 {
1224     std::stringstream result_sstream;
1225 
1226     switch (type)
1227     {
1228     case VARIABLE_TYPE_BOOL:
1229         result_sstream << *((bool *)data_ptr);
1230         break;
1231     case VARIABLE_TYPE_DOUBLE:
1232         result_sstream << *((double *)data_ptr);
1233         break;
1234     case VARIABLE_TYPE_FLOAT:
1235         result_sstream << *((float *)data_ptr);
1236         break;
1237     case VARIABLE_TYPE_INT:
1238         result_sstream << *((int *)data_ptr);
1239         break;
1240     case VARIABLE_TYPE_UINT:
1241         result_sstream << *((unsigned int *)data_ptr);
1242         break;
1243 
1244     default:
1245     {
1246         TCU_FAIL("Unrecognized variable type requested");
1247     }
1248     } /* switch (type) */
1249 
1250     return result_sstream.str();
1251 }
1252 
1253 /** Returns variable type of a transposed matrix of user-specified variable type.
1254  *
1255  *  @param type Variable type of the matrix to be transposed.
1256  *
1257  *  @return Transposed matrix variable type.
1258  **/
getTransposedMatrixVariableType(Utils::_variable_type type)1259 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1260 {
1261     Utils::_variable_type result;
1262 
1263     switch (type)
1264     {
1265     case VARIABLE_TYPE_DMAT2:
1266         result = VARIABLE_TYPE_DMAT2;
1267         break;
1268     case VARIABLE_TYPE_DMAT2X3:
1269         result = VARIABLE_TYPE_DMAT3X2;
1270         break;
1271     case VARIABLE_TYPE_DMAT2X4:
1272         result = VARIABLE_TYPE_DMAT4X2;
1273         break;
1274     case VARIABLE_TYPE_DMAT3:
1275         result = VARIABLE_TYPE_DMAT3;
1276         break;
1277     case VARIABLE_TYPE_DMAT3X2:
1278         result = VARIABLE_TYPE_DMAT2X3;
1279         break;
1280     case VARIABLE_TYPE_DMAT3X4:
1281         result = VARIABLE_TYPE_DMAT4X3;
1282         break;
1283     case VARIABLE_TYPE_DMAT4:
1284         result = VARIABLE_TYPE_DMAT4;
1285         break;
1286     case VARIABLE_TYPE_DMAT4X2:
1287         result = VARIABLE_TYPE_DMAT2X4;
1288         break;
1289     case VARIABLE_TYPE_DMAT4X3:
1290         result = VARIABLE_TYPE_DMAT3X4;
1291         break;
1292 
1293     default:
1294     {
1295         TCU_FAIL("Unrecognized double-precision matrix variable type.");
1296     }
1297     } /* switch (type) */
1298 
1299     return result;
1300 }
1301 
1302 /** Get _variable_type representing unsigned integer type with given dimmensions
1303  *
1304  * @param n_columns Number of columns
1305  * @param n_row     Number of rows
1306  *
1307  * @return Corresponding _variable_type
1308  **/
getUintVariableType(glw::GLuint n_columns,glw::GLuint n_rows)1309 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1310 {
1311     Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1312 
1313     static const _variable_type types[4] = {VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1314                                             VARIABLE_TYPE_UVEC4};
1315 
1316     if (1 != n_columns)
1317     {
1318         TCU_FAIL("Not implemented");
1319     }
1320     else
1321     {
1322         type = types[n_rows - 1];
1323     }
1324 
1325     return type;
1326 }
1327 
1328 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1329  *  variable type.
1330  *
1331  *  @param type Variable type to use for the query.
1332  *
1333  *  @return Requested GLSL keyword or [?] if @param type was not recognized.
1334  **/
getVariableTypeString(_variable_type type)1335 std::string Utils::getVariableTypeString(_variable_type type)
1336 {
1337     std::string result = "[?]";
1338 
1339     switch (type)
1340     {
1341     case VARIABLE_TYPE_BOOL:
1342         result = "bool";
1343         break;
1344     case VARIABLE_TYPE_BVEC2:
1345         result = "bvec2";
1346         break;
1347     case VARIABLE_TYPE_BVEC3:
1348         result = "bvec3";
1349         break;
1350     case VARIABLE_TYPE_BVEC4:
1351         result = "bvec4";
1352         break;
1353     case VARIABLE_TYPE_DOUBLE:
1354         result = "double";
1355         break;
1356     case VARIABLE_TYPE_DMAT2:
1357         result = "dmat2";
1358         break;
1359     case VARIABLE_TYPE_DMAT2X3:
1360         result = "dmat2x3";
1361         break;
1362     case VARIABLE_TYPE_DMAT2X4:
1363         result = "dmat2x4";
1364         break;
1365     case VARIABLE_TYPE_DMAT3:
1366         result = "dmat3";
1367         break;
1368     case VARIABLE_TYPE_DMAT3X2:
1369         result = "dmat3x2";
1370         break;
1371     case VARIABLE_TYPE_DMAT3X4:
1372         result = "dmat3x4";
1373         break;
1374     case VARIABLE_TYPE_DMAT4:
1375         result = "dmat4";
1376         break;
1377     case VARIABLE_TYPE_DMAT4X2:
1378         result = "dmat4x2";
1379         break;
1380     case VARIABLE_TYPE_DMAT4X3:
1381         result = "dmat4x3";
1382         break;
1383     case VARIABLE_TYPE_DVEC2:
1384         result = "dvec2";
1385         break;
1386     case VARIABLE_TYPE_DVEC3:
1387         result = "dvec3";
1388         break;
1389     case VARIABLE_TYPE_DVEC4:
1390         result = "dvec4";
1391         break;
1392     case VARIABLE_TYPE_FLOAT:
1393         result = "float";
1394         break;
1395     case VARIABLE_TYPE_INT:
1396         result = "int";
1397         break;
1398     case VARIABLE_TYPE_IVEC2:
1399         result = "ivec2";
1400         break;
1401     case VARIABLE_TYPE_IVEC3:
1402         result = "ivec3";
1403         break;
1404     case VARIABLE_TYPE_IVEC4:
1405         result = "ivec4";
1406         break;
1407     case VARIABLE_TYPE_MAT2:
1408         result = "mat2";
1409         break;
1410     case VARIABLE_TYPE_MAT2X3:
1411         result = "mat2x3";
1412         break;
1413     case VARIABLE_TYPE_MAT2X4:
1414         result = "mat2x4";
1415         break;
1416     case VARIABLE_TYPE_MAT3:
1417         result = "mat3";
1418         break;
1419     case VARIABLE_TYPE_MAT3X2:
1420         result = "mat3x2";
1421         break;
1422     case VARIABLE_TYPE_MAT3X4:
1423         result = "mat3x4";
1424         break;
1425     case VARIABLE_TYPE_MAT4:
1426         result = "mat4";
1427         break;
1428     case VARIABLE_TYPE_MAT4X2:
1429         result = "mat4x2";
1430         break;
1431     case VARIABLE_TYPE_MAT4X3:
1432         result = "mat4x3";
1433         break;
1434     case VARIABLE_TYPE_UINT:
1435         result = "uint";
1436         break;
1437     case VARIABLE_TYPE_UVEC2:
1438         result = "uvec2";
1439         break;
1440     case VARIABLE_TYPE_UVEC3:
1441         result = "uvec3";
1442         break;
1443     case VARIABLE_TYPE_UVEC4:
1444         result = "uvec4";
1445         break;
1446     case VARIABLE_TYPE_VEC2:
1447         result = "vec2";
1448         break;
1449     case VARIABLE_TYPE_VEC3:
1450         result = "vec3";
1451         break;
1452     case VARIABLE_TYPE_VEC4:
1453         result = "vec4";
1454         break;
1455 
1456     default:
1457     {
1458         TCU_FAIL("Unrecognized variable type");
1459     }
1460     } /* switch (type) */
1461 
1462     return result;
1463 }
1464 
1465 /** Check if GL context meets version requirements
1466  *
1467  * @param gl             Functions
1468  * @param required_major Minimum required MAJOR_VERSION
1469  * @param required_minor Minimum required MINOR_VERSION
1470  *
1471  * @return true if GL context version is at least as requested, false otherwise
1472  **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)1473 bool Utils::isGLVersionAtLeast(const glw::Functions &gl, glw::GLint required_major, glw::GLint required_minor)
1474 {
1475     glw::GLint major = 0;
1476     glw::GLint minor = 0;
1477 
1478     gl.getIntegerv(GL_MAJOR_VERSION, &major);
1479     gl.getIntegerv(GL_MINOR_VERSION, &minor);
1480 
1481     GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1482 
1483     if (major > required_major)
1484     {
1485         /* Major is higher than required one */
1486         return true;
1487     }
1488     else if (major == required_major)
1489     {
1490         if (minor >= required_minor)
1491         {
1492             /* Major is equal to required one */
1493             /* Minor is higher than or equal to required one */
1494             return true;
1495         }
1496         else
1497         {
1498             /* Major is equal to required one */
1499             /* Minor is lower than required one */
1500             return false;
1501         }
1502     }
1503     else
1504     {
1505         /* Major is lower than required one */
1506         return false;
1507     }
1508 }
1509 
1510 /** Tells whether user-specified variable type corresponds to a matrix type.
1511  *
1512  *  @param type Variable type to use for the query.
1513  *
1514  *  @return true if the variable type describes a matrix, false otherwise.
1515  **/
isMatrixVariableType(_variable_type type)1516 bool Utils::isMatrixVariableType(_variable_type type)
1517 {
1518     return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1519             type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1520             type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1521             type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1522             type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1523             type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1524 }
1525 
1526 /** Tells whether user-specified variable type is scalar.
1527  *
1528  *  @return true if @param type is a scalar variable type, false otherwise.
1529  **/
isScalarVariableType(_variable_type type)1530 bool Utils::isScalarVariableType(_variable_type type)
1531 {
1532     bool result = false;
1533 
1534     switch (type)
1535     {
1536     case VARIABLE_TYPE_BOOL:
1537         result = true;
1538         break;
1539     case VARIABLE_TYPE_DOUBLE:
1540         result = true;
1541         break;
1542     case VARIABLE_TYPE_FLOAT:
1543         result = true;
1544         break;
1545     case VARIABLE_TYPE_INT:
1546         result = true;
1547         break;
1548     case VARIABLE_TYPE_UINT:
1549         result = true;
1550         break;
1551     default:
1552         break;
1553     } /* switch (type) */
1554 
1555     return result;
1556 }
1557 
1558 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1559  *
1560  * @param token           Token string
1561  * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1562  * @param text            String that will be used as replacement for <token>
1563  * @param string          String to work on
1564  **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)1565 void Utils::replaceToken(const glw::GLchar *token, size_t &search_position, const glw::GLchar *text,
1566                          std::string &string)
1567 {
1568     const size_t text_length    = strlen(text);
1569     const size_t token_length   = strlen(token);
1570     const size_t token_position = string.find(token, search_position);
1571 
1572     string.replace(token_position, token_length, text, text_length);
1573 
1574     search_position = token_position + text_length;
1575 }
1576 
1577 /** Constructor.
1578  *
1579  *  @param context Rendering context.
1580  *
1581  **/
GPUShaderFP64Test1(deqp::Context & context)1582 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context &context)
1583     : TestCase(context, "errors",
1584                "Verifies that various erroneous conditions related to double-precision "
1585                "float uniform support & glUniform*() / glUniformMatrix*() API "
1586                " are reported correctly.")
1587     , m_has_test_passed(true)
1588     , m_po_bool_arr_uniform_location(0)
1589     , m_po_bool_uniform_location(0)
1590     , m_po_bvec2_arr_uniform_location(0)
1591     , m_po_bvec2_uniform_location(0)
1592     , m_po_bvec3_arr_uniform_location(0)
1593     , m_po_bvec3_uniform_location(0)
1594     , m_po_bvec4_arr_uniform_location(0)
1595     , m_po_bvec4_uniform_location(0)
1596     , m_po_dmat2_arr_uniform_location(0)
1597     , m_po_dmat2_uniform_location(0)
1598     , m_po_dmat2x3_arr_uniform_location(0)
1599     , m_po_dmat2x3_uniform_location(0)
1600     , m_po_dmat2x4_arr_uniform_location(0)
1601     , m_po_dmat2x4_uniform_location(0)
1602     , m_po_dmat3_arr_uniform_location(0)
1603     , m_po_dmat3_uniform_location(0)
1604     , m_po_dmat3x2_arr_uniform_location(0)
1605     , m_po_dmat3x2_uniform_location(0)
1606     , m_po_dmat3x4_arr_uniform_location(0)
1607     , m_po_dmat3x4_uniform_location(0)
1608     , m_po_dmat4_arr_uniform_location(0)
1609     , m_po_dmat4_uniform_location(0)
1610     , m_po_dmat4x2_arr_uniform_location(0)
1611     , m_po_dmat4x2_uniform_location(0)
1612     , m_po_dmat4x3_arr_uniform_location(0)
1613     , m_po_dmat4x3_uniform_location(0)
1614     , m_po_double_arr_uniform_location(0)
1615     , m_po_double_uniform_location(0)
1616     , m_po_dvec2_arr_uniform_location(0)
1617     , m_po_dvec2_uniform_location(0)
1618     , m_po_dvec3_arr_uniform_location(0)
1619     , m_po_dvec3_uniform_location(0)
1620     , m_po_dvec4_arr_uniform_location(0)
1621     , m_po_dvec4_uniform_location(0)
1622     , m_po_float_arr_uniform_location(0)
1623     , m_po_float_uniform_location(0)
1624     , m_po_int_arr_uniform_location(0)
1625     , m_po_int_uniform_location(0)
1626     , m_po_ivec2_arr_uniform_location(0)
1627     , m_po_ivec2_uniform_location(0)
1628     , m_po_ivec3_arr_uniform_location(0)
1629     , m_po_ivec3_uniform_location(0)
1630     , m_po_ivec4_arr_uniform_location(0)
1631     , m_po_ivec4_uniform_location(0)
1632     , m_po_sampler_uniform_location(0)
1633     , m_po_uint_arr_uniform_location(0)
1634     , m_po_uint_uniform_location(0)
1635     , m_po_uvec2_arr_uniform_location(0)
1636     , m_po_uvec2_uniform_location(0)
1637     , m_po_uvec3_arr_uniform_location(0)
1638     , m_po_uvec3_uniform_location(0)
1639     , m_po_uvec4_arr_uniform_location(0)
1640     , m_po_uvec4_uniform_location(0)
1641     , m_po_vec2_arr_uniform_location(0)
1642     , m_po_vec2_uniform_location(0)
1643     , m_po_vec3_arr_uniform_location(0)
1644     , m_po_vec3_uniform_location(0)
1645     , m_po_vec4_arr_uniform_location(0)
1646     , m_po_vec4_uniform_location(0)
1647     , m_po_id(0)
1648     , m_vs_id(0)
1649 {
1650     /* Left blank intentionally */
1651 }
1652 
1653 /** Deinitializes all GL objects that may have been created during
1654  *  test execution.
1655  **/
deinit()1656 void GPUShaderFP64Test1::deinit()
1657 {
1658     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1659 
1660     if (m_po_id != 0)
1661     {
1662         gl.deleteProgram(m_po_id);
1663 
1664         m_po_id = 0;
1665     }
1666 
1667     if (m_vs_id != 0)
1668     {
1669         gl.deleteShader(m_vs_id);
1670 
1671         m_vs_id = 0;
1672     }
1673 }
1674 
1675 /** Returns a string describing GL API function represented by user-provided enum.
1676  *
1677  *  @param func Uniform function to return the string for.
1678  *
1679  *  @return As per description. [?] will be returned if the function was not recognized.
1680  **/
getUniformFunctionString(_uniform_function func)1681 const char *GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func)
1682 {
1683     const char *result = "[?]";
1684 
1685     switch (func)
1686     {
1687     case UNIFORM_FUNCTION_1D:
1688         result = "glUniform1d";
1689         break;
1690     case UNIFORM_FUNCTION_1DV:
1691         result = "glUniform1dv";
1692         break;
1693     case UNIFORM_FUNCTION_2D:
1694         result = "glUniform2d";
1695         break;
1696     case UNIFORM_FUNCTION_2DV:
1697         result = "glUniform2dv";
1698         break;
1699     case UNIFORM_FUNCTION_3D:
1700         result = "glUniform3d";
1701         break;
1702     case UNIFORM_FUNCTION_3DV:
1703         result = "glUniform3dv";
1704         break;
1705     case UNIFORM_FUNCTION_4D:
1706         result = "glUniform4d";
1707         break;
1708     case UNIFORM_FUNCTION_4DV:
1709         result = "glUniform4dv";
1710         break;
1711     case UNIFORM_FUNCTION_MATRIX2DV:
1712         result = "glUniformMatrix2dv";
1713         break;
1714     case UNIFORM_FUNCTION_MATRIX2X3DV:
1715         result = "glUniformMatrix2x3dv";
1716         break;
1717     case UNIFORM_FUNCTION_MATRIX2X4DV:
1718         result = "glUniformMatrix2x4dv";
1719         break;
1720     case UNIFORM_FUNCTION_MATRIX3DV:
1721         result = "glUniformMatrix3dv";
1722         break;
1723     case UNIFORM_FUNCTION_MATRIX3X2DV:
1724         result = "glUniformMatrix3x2dv";
1725         break;
1726     case UNIFORM_FUNCTION_MATRIX3X4DV:
1727         result = "glUniformMatrix3x4dv";
1728         break;
1729     case UNIFORM_FUNCTION_MATRIX4DV:
1730         result = "glUniformMatrix4dv";
1731         break;
1732     case UNIFORM_FUNCTION_MATRIX4X2DV:
1733         result = "glUniformMatrix4x2dv";
1734         break;
1735     case UNIFORM_FUNCTION_MATRIX4X3DV:
1736         result = "glUniformMatrix4x3dv";
1737         break;
1738     default:
1739         break;
1740     }
1741 
1742     return result;
1743 }
1744 
1745 /** Returns name of an uniform bound to user-provided location.
1746  *
1747  *  @param location Location of the uniform to return the name for.
1748  *
1749  *  @return As per description. [?] will be returned if the location was not
1750  *          recognized.
1751  **/
getUniformNameForLocation(glw::GLint location)1752 const char *GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location)
1753 {
1754     const char *result = "[?]";
1755 
1756     if (location == m_po_bool_arr_uniform_location)
1757         result = "uniform_bool_arr";
1758     else if (location == m_po_bool_uniform_location)
1759         result = "uniform_bool";
1760     else if (location == m_po_bvec2_arr_uniform_location)
1761         result = "uniform_bvec2_arr";
1762     else if (location == m_po_bvec2_uniform_location)
1763         result = "uniform_bvec2";
1764     else if (location == m_po_bvec3_arr_uniform_location)
1765         result = "uniform_bvec3_arr";
1766     else if (location == m_po_bvec3_uniform_location)
1767         result = "uniform_bvec3";
1768     else if (location == m_po_bvec4_arr_uniform_location)
1769         result = "uniform_bvec4_arr";
1770     else if (location == m_po_bvec4_uniform_location)
1771         result = "uniform_bvec4";
1772     else if (location == m_po_dmat2_arr_uniform_location)
1773         result = "uniform_dmat2_arr";
1774     else if (location == m_po_dmat2_uniform_location)
1775         result = "uniform_dmat2";
1776     else if (location == m_po_dmat2x3_arr_uniform_location)
1777         result = "uniform_dmat2x3_arr";
1778     else if (location == m_po_dmat2x3_uniform_location)
1779         result = "uniform_dmat2x3";
1780     else if (location == m_po_dmat2x4_arr_uniform_location)
1781         result = "uniform_dmat2x4_arr";
1782     else if (location == m_po_dmat2x4_uniform_location)
1783         result = "uniform_dmat2x4";
1784     else if (location == m_po_dmat3_arr_uniform_location)
1785         result = "uniform_dmat3_arr";
1786     else if (location == m_po_dmat3_uniform_location)
1787         result = "uniform_dmat3";
1788     else if (location == m_po_dmat3x2_arr_uniform_location)
1789         result = "uniform_dmat3x2_arr";
1790     else if (location == m_po_dmat3x2_uniform_location)
1791         result = "uniform_dmat3x2";
1792     else if (location == m_po_dmat3x4_arr_uniform_location)
1793         result = "uniform_dmat3x4_arr";
1794     else if (location == m_po_dmat3x4_uniform_location)
1795         result = "uniform_dmat3x4";
1796     else if (location == m_po_dmat4_arr_uniform_location)
1797         result = "uniform_dmat4_arr";
1798     else if (location == m_po_dmat4_uniform_location)
1799         result = "uniform_dmat4";
1800     else if (location == m_po_dmat4x2_arr_uniform_location)
1801         result = "uniform_dmat4x2_arr";
1802     else if (location == m_po_dmat4x2_uniform_location)
1803         result = "uniform_dmat4x2";
1804     else if (location == m_po_dmat4x3_arr_uniform_location)
1805         result = "uniform_dmat4x3_arr";
1806     else if (location == m_po_dmat4x3_uniform_location)
1807         result = "uniform_dmat4x3";
1808     else if (location == m_po_double_arr_uniform_location)
1809         result = "uniform_double_arr";
1810     else if (location == m_po_double_uniform_location)
1811         result = "uniform_double";
1812     else if (location == m_po_dvec2_arr_uniform_location)
1813         result = "uniform_dvec2_arr";
1814     else if (location == m_po_dvec2_uniform_location)
1815         result = "uniform_dvec2";
1816     else if (location == m_po_dvec3_arr_uniform_location)
1817         result = "uniform_dvec3_arr";
1818     else if (location == m_po_dvec3_uniform_location)
1819         result = "uniform_dvec3";
1820     else if (location == m_po_dvec4_arr_uniform_location)
1821         result = "uniform_dvec4_arr";
1822     else if (location == m_po_dvec4_uniform_location)
1823         result = "uniform_dvec4";
1824     else if (location == m_po_float_arr_uniform_location)
1825         result = "uniform_float_arr";
1826     else if (location == m_po_float_uniform_location)
1827         result = "uniform_float";
1828     else if (location == m_po_int_arr_uniform_location)
1829         result = "uniform_int_arr";
1830     else if (location == m_po_int_uniform_location)
1831         result = "uniform_int";
1832     else if (location == m_po_ivec2_arr_uniform_location)
1833         result = "uniform_ivec2_arr";
1834     else if (location == m_po_ivec2_uniform_location)
1835         result = "uniform_ivec2";
1836     else if (location == m_po_ivec3_arr_uniform_location)
1837         result = "uniform_ivec3_arr";
1838     else if (location == m_po_ivec3_uniform_location)
1839         result = "uniform_ivec3";
1840     else if (location == m_po_ivec4_arr_uniform_location)
1841         result = "uniform_ivec4_arr";
1842     else if (location == m_po_ivec4_uniform_location)
1843         result = "uniform_ivec4";
1844     else if (location == m_po_uint_arr_uniform_location)
1845         result = "uniform_uint_arr";
1846     else if (location == m_po_uint_uniform_location)
1847         result = "uniform_uint";
1848     else if (location == m_po_uvec2_arr_uniform_location)
1849         result = "uniform_uvec2_arr";
1850     else if (location == m_po_uvec2_uniform_location)
1851         result = "uniform_uvec2";
1852     else if (location == m_po_uvec3_arr_uniform_location)
1853         result = "uniform_uvec3_arr";
1854     else if (location == m_po_uvec3_uniform_location)
1855         result = "uniform_uvec3";
1856     else if (location == m_po_uvec4_arr_uniform_location)
1857         result = "uniform_uvec4_arr";
1858     else if (location == m_po_uvec4_uniform_location)
1859         result = "uniform_uvec4";
1860     else if (location == m_po_vec2_arr_uniform_location)
1861         result = "uniform_vec2_arr";
1862     else if (location == m_po_vec2_uniform_location)
1863         result = "uniform_vec2";
1864     else if (location == m_po_vec3_arr_uniform_location)
1865         result = "uniform_vec3_arr";
1866     else if (location == m_po_vec3_uniform_location)
1867         result = "uniform_vec3";
1868     else if (location == m_po_vec4_arr_uniform_location)
1869         result = "uniform_vec4_arr";
1870     else if (location == m_po_vec4_uniform_location)
1871         result = "uniform_vec4";
1872 
1873     return result;
1874 }
1875 
1876 /** Initializes all GL objects required to run the test. Also extracts locations of all
1877  *  uniforms used by the test.
1878  *
1879  *  This function can throw a TestError exception if the implementation misbehaves.
1880  */
initTest()1881 void GPUShaderFP64Test1::initTest()
1882 {
1883     glw::GLint compile_status = GL_FALSE;
1884     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
1885     glw::GLint link_status    = GL_FALSE;
1886 
1887     /* Set up a program object using all new double-precision types */
1888     const char *vs_body =
1889         "#version 400\n"
1890         "\n"
1891         "uniform bool      uniform_bool;\n"
1892         "uniform bvec2     uniform_bvec2;\n"
1893         "uniform bvec3     uniform_bvec3;\n"
1894         "uniform bvec4     uniform_bvec4;\n"
1895         "uniform dmat2     uniform_dmat2;\n"
1896         "uniform dmat2x3   uniform_dmat2x3;\n"
1897         "uniform dmat2x4   uniform_dmat2x4;\n"
1898         "uniform dmat3     uniform_dmat3;\n"
1899         "uniform dmat3x2   uniform_dmat3x2;\n"
1900         "uniform dmat3x4   uniform_dmat3x4;\n"
1901         "uniform dmat4     uniform_dmat4;\n"
1902         "uniform dmat4x2   uniform_dmat4x2;\n"
1903         "uniform dmat4x3   uniform_dmat4x3;\n"
1904         "uniform double    uniform_double;\n"
1905         "uniform dvec2     uniform_dvec2;\n"
1906         "uniform dvec3     uniform_dvec3;\n"
1907         "uniform dvec4     uniform_dvec4;\n"
1908         "uniform float     uniform_float;\n"
1909         "uniform int       uniform_int;\n"
1910         "uniform ivec2     uniform_ivec2;\n"
1911         "uniform ivec3     uniform_ivec3;\n"
1912         "uniform ivec4     uniform_ivec4;\n"
1913         "uniform sampler2D uniform_sampler;\n"
1914         "uniform uint      uniform_uint;\n"
1915         "uniform uvec2     uniform_uvec2;\n"
1916         "uniform uvec3     uniform_uvec3;\n"
1917         "uniform uvec4     uniform_uvec4;\n"
1918         "uniform vec2      uniform_vec2;\n"
1919         "uniform vec3      uniform_vec3;\n"
1920         "uniform vec4      uniform_vec4;\n"
1921         "uniform bool      uniform_bool_arr   [2];\n"
1922         "uniform bvec2     uniform_bvec2_arr  [2];\n"
1923         "uniform bvec3     uniform_bvec3_arr  [2];\n"
1924         "uniform bvec4     uniform_bvec4_arr  [2];\n"
1925         "uniform dmat2     uniform_dmat2_arr  [2];\n"
1926         "uniform dmat2x3   uniform_dmat2x3_arr[2];\n"
1927         "uniform dmat2x4   uniform_dmat2x4_arr[2];\n"
1928         "uniform dmat3     uniform_dmat3_arr  [2];\n"
1929         "uniform dmat3x2   uniform_dmat3x2_arr[2];\n"
1930         "uniform dmat3x4   uniform_dmat3x4_arr[2];\n"
1931         "uniform dmat4     uniform_dmat4_arr  [2];\n"
1932         "uniform dmat4x2   uniform_dmat4x2_arr[2];\n"
1933         "uniform dmat4x3   uniform_dmat4x3_arr[2];\n"
1934         "uniform double    uniform_double_arr [2];\n"
1935         "uniform dvec2     uniform_dvec2_arr  [2];\n"
1936         "uniform dvec3     uniform_dvec3_arr  [2];\n"
1937         "uniform dvec4     uniform_dvec4_arr  [2];\n"
1938         "uniform float     uniform_float_arr  [2];\n"
1939         "uniform int       uniform_int_arr    [2];\n"
1940         "uniform ivec2     uniform_ivec2_arr  [2];\n"
1941         "uniform ivec3     uniform_ivec3_arr  [2];\n"
1942         "uniform ivec4     uniform_ivec4_arr  [2];\n"
1943         "uniform uint      uniform_uint_arr   [2];\n"
1944         "uniform uvec2     uniform_uvec2_arr  [2];\n"
1945         "uniform uvec3     uniform_uvec3_arr  [2];\n"
1946         "uniform uvec4     uniform_uvec4_arr  [2];\n"
1947         "uniform vec2      uniform_vec2_arr   [2];\n"
1948         "uniform vec3      uniform_vec3_arr   [2];\n"
1949         "uniform vec4      uniform_vec4_arr   [2];\n"
1950         "\n"
1951         "void main()\n"
1952         "{\n"
1953         "    gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n"
1954         "\n"
1955         "    if (uniform_bool        && uniform_bvec2.y        && uniform_bvec3.z        && uniform_bvec4.w        &&\n"
1956         "        uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n"
1957         "    {\n"
1958         "        double sum = uniform_dmat2       [0].x + uniform_dmat2x3       [0].x + uniform_dmat2x4       [0].x +\n"
1959         "                     uniform_dmat3       [0].x + uniform_dmat3x2       [0].x + uniform_dmat3x4       [0].x +\n"
1960         "                     uniform_dmat4       [0].x + uniform_dmat4x2       [0].x + uniform_dmat4x3       [0].x +\n"
1961         "                     uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n"
1962         "                     uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n"
1963         "                     uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n"
1964         "                     uniform_double            + uniform_double_arr [0]      +\n"
1965         "                     uniform_dvec2.x           + uniform_dvec3.x             + uniform_dvec4.x        +\n"
1966         "                     uniform_dvec2_arr[0].x    + uniform_dvec3_arr[0].x      + uniform_dvec4_arr[0].x;\n"
1967         "        int   sum2 = uniform_int               + uniform_ivec2.x             + uniform_ivec3.x        +\n"
1968         "                     uniform_ivec4.x           + uniform_ivec2_arr[0].x      + uniform_ivec3_arr[0].x +\n"
1969         "                     uniform_ivec4_arr[0].x    + uniform_int_arr[0];\n"
1970         "        uint  sum3 = uniform_uint              + uniform_uvec2.x             + uniform_uvec3.x        +\n"
1971         "                     uniform_uvec4.x           + uniform_uint_arr[0]         + uniform_uvec2_arr[0].x +\n"
1972         "                     uniform_uvec3_arr[0].x    + uniform_uvec4_arr[0].x;\n"
1973         "        float sum4 = uniform_float             + uniform_float_arr[0]  + \n"
1974         "                     uniform_vec2.x            + uniform_vec2_arr[0].x + \n"
1975         "                     uniform_vec3.x            + uniform_vec3_arr[0].x + \n"
1976         "                     uniform_vec4.x            + uniform_vec4_arr[0].x;\n"
1977         "\n"
1978         "        if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n"
1979         "        {\n"
1980         "            gl_Position = vec4(1);\n"
1981         "        }\n"
1982         "    }\n"
1983         "}\n";
1984 
1985     m_po_id = gl.createProgram();
1986     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1987 
1988     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1989     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
1990 
1991     gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
1992     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1993 
1994     gl.compileShader(m_vs_id);
1995     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1996 
1997     gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1998     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1999 
2000     if (compile_status != GL_TRUE)
2001     {
2002         TCU_FAIL("Shader compilation failed.");
2003     }
2004 
2005     gl.attachShader(m_po_id, m_vs_id);
2006     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
2007 
2008     gl.linkProgram(m_po_id);
2009     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2010 
2011     gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
2012     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2013 
2014     if (link_status != GL_TRUE)
2015     {
2016         TCU_FAIL("Program linking failed.");
2017     }
2018 
2019     m_po_bool_arr_uniform_location    = gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]");
2020     m_po_bool_uniform_location        = gl.getUniformLocation(m_po_id, "uniform_bool");
2021     m_po_bvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]");
2022     m_po_bvec2_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_bvec2");
2023     m_po_bvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]");
2024     m_po_bvec3_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_bvec3");
2025     m_po_bvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]");
2026     m_po_bvec4_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_bvec4");
2027     m_po_dmat2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]");
2028     m_po_dmat2_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dmat2");
2029     m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]");
2030     m_po_dmat2x3_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat2x3");
2031     m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]");
2032     m_po_dmat2x4_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat2x4");
2033     m_po_dmat3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]");
2034     m_po_dmat3_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dmat3");
2035     m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]");
2036     m_po_dmat3x2_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat3x2");
2037     m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]");
2038     m_po_dmat3x4_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat3x4");
2039     m_po_dmat4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]");
2040     m_po_dmat4_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dmat4");
2041     m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]");
2042     m_po_dmat4x2_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat4x2");
2043     m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]");
2044     m_po_dmat4x3_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_dmat4x3");
2045     m_po_double_arr_uniform_location  = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]");
2046     m_po_double_uniform_location      = gl.getUniformLocation(m_po_id, "uniform_double");
2047     m_po_dvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]");
2048     m_po_dvec2_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dvec2");
2049     m_po_dvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]");
2050     m_po_dvec3_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dvec3");
2051     m_po_dvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]");
2052     m_po_dvec4_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_dvec4");
2053     m_po_float_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]");
2054     m_po_float_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_float");
2055     m_po_int_arr_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]");
2056     m_po_int_uniform_location         = gl.getUniformLocation(m_po_id, "uniform_int");
2057     m_po_ivec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]");
2058     m_po_ivec2_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_ivec2");
2059     m_po_ivec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]");
2060     m_po_ivec3_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_ivec3");
2061     m_po_ivec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]");
2062     m_po_ivec4_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_ivec4");
2063     m_po_sampler_uniform_location     = gl.getUniformLocation(m_po_id, "uniform_sampler");
2064     m_po_uint_arr_uniform_location    = gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]");
2065     m_po_uint_uniform_location        = gl.getUniformLocation(m_po_id, "uniform_uint");
2066     m_po_uvec2_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]");
2067     m_po_uvec2_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_uvec2");
2068     m_po_uvec3_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]");
2069     m_po_uvec3_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_uvec3");
2070     m_po_uvec4_arr_uniform_location   = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]");
2071     m_po_uvec4_uniform_location       = gl.getUniformLocation(m_po_id, "uniform_uvec4");
2072     m_po_vec2_arr_uniform_location    = gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]");
2073     m_po_vec2_uniform_location        = gl.getUniformLocation(m_po_id, "uniform_vec2");
2074     m_po_vec3_arr_uniform_location    = gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]");
2075     m_po_vec3_uniform_location        = gl.getUniformLocation(m_po_id, "uniform_vec3");
2076     m_po_vec4_arr_uniform_location    = gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]");
2077     m_po_vec4_uniform_location        = gl.getUniformLocation(m_po_id, "uniform_vec4");
2078     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
2079 
2080     if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 ||
2081         m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 ||
2082         m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 ||
2083         m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 ||
2084         m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 ||
2085         m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 ||
2086         m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 ||
2087         m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 ||
2088         m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 ||
2089         m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 ||
2090         m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 ||
2091         m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 ||
2092         m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 ||
2093         m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 ||
2094         m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 ||
2095         m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 ||
2096         m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 ||
2097         m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 ||
2098         m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 ||
2099         m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 ||
2100         m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 ||
2101         m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 ||
2102         m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 ||
2103         m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 ||
2104         m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 ||
2105         m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 ||
2106         m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 ||
2107         m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 ||
2108         m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1)
2109     {
2110         TCU_FAIL("At last one of the required uniforms is considered inactive.");
2111     }
2112 }
2113 
2114 /** Tells wheter uniform at user-specified location represents a double-precision
2115  *  matrix uniform.
2116  *
2117  *  @param uniform_location Location of the uniform to use for the query.
2118  *
2119  *  @return Requested information.
2120  **/
isMatrixUniform(glw::GLint uniform_location)2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location)
2122 {
2123     return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location ||
2124             uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location ||
2125             uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location ||
2126             uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location ||
2127             uniform_location == m_po_dmat4x3_uniform_location);
2128 }
2129 
2130 /** Tells whether user-specified uniform function corresponds to one of the
2131  *  functions in glUniformMatrix*() class.
2132  *
2133  *  @param func Uniform function enum to use for the query.
2134  *
2135  *  @return true if the specified enum represents one of the glUniformMatrix*() functions,
2136  *          false otherwise.
2137  **/
isMatrixUniformFunction(_uniform_function func)2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func)
2139 {
2140     return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV ||
2141             func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV ||
2142             func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV ||
2143             func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV ||
2144             func == UNIFORM_FUNCTION_MATRIX4X3DV);
2145 }
2146 
2147 /** Executes test iteration.
2148  *
2149  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2150  */
iterate()2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate()
2152 {
2153     /* Do not execute the test if GL_ARB_texture_view is not supported */
2154     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
2155     {
2156         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
2157     }
2158 
2159     /* Initialize all ES objects required to run all the checks */
2160     initTest();
2161 
2162     /* Make sure GL_INVALID_OPERATION is generated by glUniform*() and
2163      * glUniformMatrix*() functions if there is no current program object.
2164      */
2165     m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO();
2166 
2167     /* Make sure GL_INVALID_OPERATION is generated by glUniform*() if
2168      * the size of the uniform variable declared in the shader does not
2169      * match the size indicated by the command.
2170      */
2171     m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions();
2172 
2173     /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2174      * glUniformMatrix*() are used to load a uniform variable of type
2175      * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4,
2176      * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array
2177      * of these.
2178      */
2179     m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions();
2180 
2181     /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2182      * glUniformMatrix*() are used to load incompatible double-typed
2183      * uniforms, as presented below:
2184      *
2185      * I.    double-typed uniform configured by glUniform2d();
2186      * II.   double-typed uniform configured by glUniform3d();
2187      * III.  double-typed uniform configured by glUniform4d();
2188      * IV.   double-typed uniform configured by glUniformMatrix*();
2189      * V.    dvec2-typed  uniform configured by glUniform1d();
2190      * VI.   dvec2-typed  uniform configured by glUniform3d();
2191      * VII.  dvec2-typed  uniform configured by glUniform4d();
2192      * VIII. dvec2-typed  uniform configured by glUniformMatrix*();
2193      *
2194      *                          (etc.)
2195      *
2196      */
2197     m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions();
2198 
2199     /* Make sure GL_INVALID_OPERATION is generated if <location> of
2200      * glUniform*() and glUniformMatrix*() is an invalid uniform
2201      * location for the current program object and location is not
2202      * equal to -1.
2203      */
2204     m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation();
2205 
2206     /* Make sure GL_INVALID_VALUE is generated if <count> of
2207      * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2208      * negative.
2209      */
2210     m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount();
2211 
2212     /* Make sure GL_INVALID_OPERATION is generated if <count> of
2213      * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2214      * greater than 1 and the indicated uniform variable is not an
2215      * array variable.
2216      */
2217     m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount();
2218 
2219     /* Make sure GL_INVALID_OPERATION is generated if a sampler is
2220      * loaded by glUniform*() and glUniformMatrix*().
2221      */
2222     m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers();
2223 
2224     /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2225      * glUniformMatrix*() is used to load values for uniforms of
2226      * boolean types.
2227      */
2228     m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans();
2229 
2230     if (m_has_test_passed)
2231     {
2232         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2233     }
2234     else
2235     {
2236         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2237     }
2238 
2239     return STOP;
2240 }
2241 
2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2243  *  glUniformMatrix*dv() functions is used to load a boolean uniform.
2244  *
2245  *  @return true if the implementation was found to behave as expected, false otherwise.
2246  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()
2248 {
2249     const double double_data[]             = {1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2250                                               9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
2251     const glw::Functions &gl               = m_context.getRenderContext().getFunctions();
2252     bool result                            = true;
2253     glw::GLint uniform_locations[]         = {m_po_bool_arr_uniform_location,  m_po_bool_uniform_location,
2254                                               m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2255                                               m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2256                                               m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location};
2257     const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2258 
2259     for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2260          ++n_uniform_function)
2261     {
2262         const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2263 
2264         for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2265         {
2266             const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2267 
2268             switch (uniform_function)
2269             {
2270             case UNIFORM_FUNCTION_1D:
2271                 gl.uniform1d(uniform_location, 0.0);
2272                 break;
2273             case UNIFORM_FUNCTION_2D:
2274                 gl.uniform2d(uniform_location, 0.0, 1.0);
2275                 break;
2276             case UNIFORM_FUNCTION_3D:
2277                 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2278                 break;
2279             case UNIFORM_FUNCTION_4D:
2280                 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2281                 break;
2282 
2283             case UNIFORM_FUNCTION_1DV:
2284                 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2285                 break;
2286             case UNIFORM_FUNCTION_2DV:
2287                 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2288                 break;
2289             case UNIFORM_FUNCTION_3DV:
2290                 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2291                 break;
2292             case UNIFORM_FUNCTION_4DV:
2293                 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2294                 break;
2295 
2296             case UNIFORM_FUNCTION_MATRIX2DV:
2297                 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2298                 break;
2299             case UNIFORM_FUNCTION_MATRIX2X3DV:
2300                 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2301                 break;
2302             case UNIFORM_FUNCTION_MATRIX2X4DV:
2303                 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2304                 break;
2305             case UNIFORM_FUNCTION_MATRIX3DV:
2306                 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2307                 break;
2308             case UNIFORM_FUNCTION_MATRIX3X2DV:
2309                 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2310                 break;
2311             case UNIFORM_FUNCTION_MATRIX3X4DV:
2312                 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2313                 break;
2314             case UNIFORM_FUNCTION_MATRIX4DV:
2315                 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2316                 break;
2317             case UNIFORM_FUNCTION_MATRIX4X2DV:
2318                 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2319                 break;
2320             case UNIFORM_FUNCTION_MATRIX4X3DV:
2321                 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2322                 break;
2323 
2324             default:
2325             {
2326                 TCU_FAIL("Unrecognized uniform function");
2327             }
2328             }
2329 
2330             /* Make sure GL_INVALID_OPERATION was generated by the call */
2331             const glw::GLenum error_code = gl.getError();
2332 
2333             if (error_code != GL_INVALID_OPERATION)
2334             {
2335                 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2336                                    << "() did not generate an error"
2337                                       " when applied against a boolean uniform."
2338                                    << tcu::TestLog::EndMessage;
2339 
2340                 result = false;
2341             }
2342         } /* for (all bool uniforms) */
2343     }     /* for (all uniform functions) */
2344 
2345     return result;
2346 }
2347 
2348 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2349  *  glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2350  *
2351  *  @return true if the implementation was found to behave as expected, false otherwise.
2352  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2353 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2354 {
2355     const double double_data[] = {1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2356                                   9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
2357     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
2358     bool result                = true;
2359 
2360     for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2361          ++n_uniform_function)
2362     {
2363         _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2364 
2365         switch (uniform_function)
2366         {
2367         case UNIFORM_FUNCTION_1D:
2368             gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2369             break;
2370         case UNIFORM_FUNCTION_2D:
2371             gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2372             break;
2373         case UNIFORM_FUNCTION_3D:
2374             gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2375             break;
2376         case UNIFORM_FUNCTION_4D:
2377             gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2378             break;
2379 
2380         case UNIFORM_FUNCTION_1DV:
2381             gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2382             break;
2383         case UNIFORM_FUNCTION_2DV:
2384             gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2385             break;
2386         case UNIFORM_FUNCTION_3DV:
2387             gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2388             break;
2389         case UNIFORM_FUNCTION_4DV:
2390             gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2391             break;
2392 
2393         case UNIFORM_FUNCTION_MATRIX2DV:
2394             gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2395             break;
2396         case UNIFORM_FUNCTION_MATRIX2X3DV:
2397             gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2398             break;
2399         case UNIFORM_FUNCTION_MATRIX2X4DV:
2400             gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2401             break;
2402         case UNIFORM_FUNCTION_MATRIX3DV:
2403             gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2404             break;
2405         case UNIFORM_FUNCTION_MATRIX3X2DV:
2406             gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2407             break;
2408         case UNIFORM_FUNCTION_MATRIX3X4DV:
2409             gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2410             break;
2411         case UNIFORM_FUNCTION_MATRIX4DV:
2412             gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2413             break;
2414         case UNIFORM_FUNCTION_MATRIX4X2DV:
2415             gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2416             break;
2417         case UNIFORM_FUNCTION_MATRIX4X3DV:
2418             gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2419             break;
2420 
2421         default:
2422         {
2423             TCU_FAIL("Unrecognized uniform function");
2424         }
2425         }
2426 
2427         /* Make sure GL_INVALID_OPERATION was generated by the call */
2428         const glw::GLenum error_code = gl.getError();
2429 
2430         if (error_code != GL_INVALID_OPERATION)
2431         {
2432             m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2433                                << "() did not generate an error"
2434                                   " when applied against a sampler uniform."
2435                                << tcu::TestLog::EndMessage;
2436 
2437             result = false;
2438         }
2439     } /* for (all uniform functions) */
2440 
2441     return result;
2442 }
2443 
2444 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2445  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2446  *  invalid <count> argument.
2447  *
2448  *  @return true if the implementation was found to behave as expected, false otherwise.
2449  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2450 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2451 {
2452     const glw::GLdouble double_values[16]       = {1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2453                                                    9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
2454     const glw::Functions &gl                    = m_context.getRenderContext().getFunctions();
2455     bool result                                 = true;
2456     const _uniform_function uniform_functions[] = {
2457         UNIFORM_FUNCTION_1DV,         UNIFORM_FUNCTION_2DV,       UNIFORM_FUNCTION_3DV,
2458         UNIFORM_FUNCTION_4DV,         UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2459         UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, UNIFORM_FUNCTION_MATRIX3X2DV,
2460         UNIFORM_FUNCTION_MATRIX3X4DV, UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2461         UNIFORM_FUNCTION_MATRIX4X3DV};
2462     const glw::GLint uniforms[] = {
2463         m_po_bool_uniform_location,    m_po_bvec2_uniform_location,  m_po_bvec3_uniform_location,
2464         m_po_bvec4_uniform_location,   m_po_dmat2_uniform_location,  m_po_dmat2x3_uniform_location,
2465         m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,  m_po_dmat3x2_uniform_location,
2466         m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location,  m_po_dmat4x2_uniform_location,
2467         m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2468         m_po_dvec3_uniform_location,   m_po_dvec4_uniform_location,  m_po_float_uniform_location,
2469         m_po_int_uniform_location,     m_po_ivec2_uniform_location,  m_po_ivec3_uniform_location,
2470         m_po_ivec4_uniform_location,   m_po_uint_uniform_location,   m_po_uvec2_uniform_location,
2471         m_po_uvec3_uniform_location,   m_po_uvec4_uniform_location,  m_po_vec2_uniform_location,
2472         m_po_vec3_uniform_location,    m_po_vec4_uniform_location};
2473 
2474     const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2475     const unsigned int n_uniforms          = sizeof(uniforms) / sizeof(uniforms[0]);
2476 
2477     for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2478     {
2479         _uniform_function uniform_function = uniform_functions[n_uniform_function];
2480 
2481         for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2482         {
2483             glw::GLint uniform_location = uniforms[n_uniform];
2484 
2485             /* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2486              * and glUniform*() functions with vector uniforms.
2487              */
2488             bool is_matrix_uniform = isMatrixUniform(uniform_location);
2489 
2490             if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2491                 ((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2492             {
2493                 continue;
2494             }
2495 
2496             /* Issue the call with an invalid <count> argument */
2497             switch (uniform_function)
2498             {
2499             case UNIFORM_FUNCTION_1DV:
2500                 gl.uniform1dv(uniform_location, 2, double_values);
2501                 break;
2502             case UNIFORM_FUNCTION_2DV:
2503                 gl.uniform2dv(uniform_location, 2, double_values);
2504                 break;
2505             case UNIFORM_FUNCTION_3DV:
2506                 gl.uniform3dv(uniform_location, 2, double_values);
2507                 break;
2508             case UNIFORM_FUNCTION_4DV:
2509                 gl.uniform4dv(uniform_location, 2, double_values);
2510                 break;
2511             case UNIFORM_FUNCTION_MATRIX2DV:
2512                 gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2513                 break;
2514             case UNIFORM_FUNCTION_MATRIX2X3DV:
2515                 gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2516                 break;
2517             case UNIFORM_FUNCTION_MATRIX2X4DV:
2518                 gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2519                 break;
2520             case UNIFORM_FUNCTION_MATRIX3DV:
2521                 gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2522                 break;
2523             case UNIFORM_FUNCTION_MATRIX3X2DV:
2524                 gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2525                 break;
2526             case UNIFORM_FUNCTION_MATRIX3X4DV:
2527                 gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2528                 break;
2529             case UNIFORM_FUNCTION_MATRIX4DV:
2530                 gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2531                 break;
2532             case UNIFORM_FUNCTION_MATRIX4X2DV:
2533                 gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2534                 break;
2535             case UNIFORM_FUNCTION_MATRIX4X3DV:
2536                 gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2537                 break;
2538 
2539             default:
2540             {
2541                 TCU_FAIL("Unrecognized uniform function");
2542             }
2543             } /* switch (uniform_function) */
2544 
2545             /* Make sure GL_INVALID_VALUE was generated */
2546             glw::GLenum error_code = gl.getError();
2547 
2548             if (error_code != GL_INVALID_OPERATION)
2549             {
2550                 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2551                                    << "() "
2552                                       "was called with an invalid count argument but did not generate a "
2553                                       "GL_INVALID_OPERATION error"
2554                                    << tcu::TestLog::EndMessage;
2555 
2556                 result = false;
2557             }
2558         } /* for (all non-arrayed uniforms) */
2559     }     /* for (all uniform functions) */
2560 
2561     return result;
2562 }
2563 
2564 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2565  *  glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2566  *
2567  *  @return true if the implementation was found to behave as expected, false otherwise.
2568  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2569 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2570 {
2571     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2572     bool result              = true;
2573 
2574     /* Find the largest valid uniform location */
2575     const glw::GLint uniform_locations[] = {
2576         m_po_bool_arr_uniform_location,    m_po_bool_uniform_location,        m_po_bvec2_arr_uniform_location,
2577         m_po_bvec2_uniform_location,       m_po_bvec3_arr_uniform_location,   m_po_bvec3_uniform_location,
2578         m_po_bvec4_arr_uniform_location,   m_po_bvec4_uniform_location,       m_po_dmat2_arr_uniform_location,
2579         m_po_dmat2_uniform_location,       m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2580         m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location,     m_po_dmat3_arr_uniform_location,
2581         m_po_dmat3_uniform_location,       m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2582         m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location,     m_po_dmat4_arr_uniform_location,
2583         m_po_dmat4_uniform_location,       m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2584         m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location,     m_po_double_arr_uniform_location,
2585         m_po_double_uniform_location,      m_po_dvec2_arr_uniform_location,   m_po_dvec2_uniform_location,
2586         m_po_dvec3_arr_uniform_location,   m_po_dvec3_uniform_location,       m_po_dvec4_arr_uniform_location,
2587         m_po_dvec4_uniform_location,       m_po_float_arr_uniform_location,   m_po_float_uniform_location,
2588         m_po_int_arr_uniform_location,     m_po_int_uniform_location,         m_po_ivec2_arr_uniform_location,
2589         m_po_ivec2_uniform_location,       m_po_ivec3_arr_uniform_location,   m_po_ivec3_uniform_location,
2590         m_po_ivec4_arr_uniform_location,   m_po_ivec4_uniform_location,       m_po_uint_arr_uniform_location,
2591         m_po_uint_uniform_location,        m_po_uvec2_arr_uniform_location,   m_po_uvec2_uniform_location,
2592         m_po_uvec3_arr_uniform_location,   m_po_uvec3_uniform_location,       m_po_uvec4_arr_uniform_location,
2593         m_po_uvec4_uniform_location,       m_po_vec2_arr_uniform_location,    m_po_vec2_uniform_location,
2594         m_po_vec3_arr_uniform_location,    m_po_vec3_uniform_location,        m_po_vec4_arr_uniform_location,
2595         m_po_vec4_uniform_location};
2596     const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2597     glw::GLint valid_uniform_location      = -1;
2598 
2599     for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2600     {
2601         glw::GLint uniform_location = uniform_locations[n_uniform_location];
2602 
2603         if (uniform_location > valid_uniform_location)
2604         {
2605             valid_uniform_location = uniform_location;
2606         }
2607     } /* for (all  uniform locations) */
2608 
2609     /* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2610      * for invalid uniform location that is != -1
2611      */
2612     const double double_data[]                = {1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2613                                                  9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
2614     const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2615 
2616     for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2617          ++n_uniform_function)
2618     {
2619         _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2620 
2621         switch (uniform_function)
2622         {
2623         case UNIFORM_FUNCTION_1D:
2624             gl.uniform1d(invalid_uniform_location, 0.0);
2625             break;
2626         case UNIFORM_FUNCTION_2D:
2627             gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2628             break;
2629         case UNIFORM_FUNCTION_3D:
2630             gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2631             break;
2632         case UNIFORM_FUNCTION_4D:
2633             gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2634             break;
2635 
2636         case UNIFORM_FUNCTION_1DV:
2637             gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2638             break;
2639         case UNIFORM_FUNCTION_2DV:
2640             gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2641             break;
2642         case UNIFORM_FUNCTION_3DV:
2643             gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2644             break;
2645         case UNIFORM_FUNCTION_4DV:
2646             gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2647             break;
2648 
2649         case UNIFORM_FUNCTION_MATRIX2DV:
2650             gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2651             break;
2652         case UNIFORM_FUNCTION_MATRIX2X3DV:
2653             gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2654             break;
2655         case UNIFORM_FUNCTION_MATRIX2X4DV:
2656             gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657             break;
2658         case UNIFORM_FUNCTION_MATRIX3DV:
2659             gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660             break;
2661         case UNIFORM_FUNCTION_MATRIX3X2DV:
2662             gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663             break;
2664         case UNIFORM_FUNCTION_MATRIX3X4DV:
2665             gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666             break;
2667         case UNIFORM_FUNCTION_MATRIX4DV:
2668             gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669             break;
2670         case UNIFORM_FUNCTION_MATRIX4X2DV:
2671             gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672             break;
2673         case UNIFORM_FUNCTION_MATRIX4X3DV:
2674             gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675             break;
2676 
2677         default:
2678         {
2679             TCU_FAIL("Unrecognized uniform function");
2680         }
2681         }
2682 
2683         const glw::GLenum error_code = gl.getError();
2684 
2685         if (error_code != GL_INVALID_OPERATION)
2686         {
2687             m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2688                                << "() did not generate an error"
2689                                   " when passed an invalid uniform location different from -1."
2690                                << tcu::TestLog::EndMessage;
2691 
2692             result = false;
2693         }
2694     } /* for (all uniform functions) */
2695 
2696     return result;
2697 }
2698 
2699 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2700  *  glUniformMatrix*dv() functions is used to load a compatible uniform using an
2701  *  invalid <count> argument of -1.
2702  *
2703  *  @return true if the implementation was found to behave as expected, false otherwise.
2704  **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2705 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2706 {
2707     const glw::GLdouble double_values[16]       = {1.0, 2.0,  3.0,  4.0,  5.0,  6.0,  7.0,  8.0,
2708                                                    9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0};
2709     const glw::Functions &gl                    = m_context.getRenderContext().getFunctions();
2710     bool result                                 = true;
2711     const _uniform_function uniform_functions[] = {
2712         UNIFORM_FUNCTION_1DV,         UNIFORM_FUNCTION_2DV,       UNIFORM_FUNCTION_3DV,
2713         UNIFORM_FUNCTION_4DV,         UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2714         UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV, UNIFORM_FUNCTION_MATRIX3X2DV,
2715         UNIFORM_FUNCTION_MATRIX3X4DV, UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2716         UNIFORM_FUNCTION_MATRIX4X3DV};
2717     const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2718 
2719     for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2720     {
2721         _uniform_function uniform_function = uniform_functions[n_uniform_function];
2722 
2723         switch (uniform_function)
2724         {
2725         case UNIFORM_FUNCTION_1DV:
2726             gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2727             break;
2728         case UNIFORM_FUNCTION_2DV:
2729             gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2730             break;
2731         case UNIFORM_FUNCTION_3DV:
2732             gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2733             break;
2734         case UNIFORM_FUNCTION_4DV:
2735             gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2736             break;
2737         case UNIFORM_FUNCTION_MATRIX2DV:
2738             gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2739             break;
2740         case UNIFORM_FUNCTION_MATRIX2X3DV:
2741             gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2742             break;
2743         case UNIFORM_FUNCTION_MATRIX2X4DV:
2744             gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2745             break;
2746         case UNIFORM_FUNCTION_MATRIX3DV:
2747             gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2748             break;
2749         case UNIFORM_FUNCTION_MATRIX3X2DV:
2750             gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2751             break;
2752         case UNIFORM_FUNCTION_MATRIX3X4DV:
2753             gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2754             break;
2755         case UNIFORM_FUNCTION_MATRIX4DV:
2756             gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2757             break;
2758         case UNIFORM_FUNCTION_MATRIX4X2DV:
2759             gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2760             break;
2761         case UNIFORM_FUNCTION_MATRIX4X3DV:
2762             gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2763             break;
2764 
2765         default:
2766         {
2767             TCU_FAIL("Unrecognized uniform function");
2768         }
2769         } /* switch (uniform_function) */
2770 
2771         /* Make sure GL_INVALID_VALUE was generated */
2772         glw::GLenum error_code = gl.getError();
2773 
2774         if (error_code != GL_INVALID_VALUE)
2775         {
2776             m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2777                                << "() "
2778                                   "was called with a negative count argument but did not generate a "
2779                                   "GL_INVALID_VALUE error"
2780                                << tcu::TestLog::EndMessage;
2781 
2782             result = false;
2783         }
2784     } /* for (all uniform functions) */
2785 
2786     return result;
2787 }
2788 
2789 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2790  *  glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2791  *  function (as per spec).
2792  *
2793  *  @return true if the implementation was found to behave as expected, false otherwise.
2794  **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2795 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2796 {
2797     const double double_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
2798     glw::GLenum error_code     = GL_NO_ERROR;
2799     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
2800     bool result                = true;
2801 
2802     const glw::GLint double_uniform_locations[] = {
2803         m_po_dmat2_uniform_location,  m_po_dmat2x3_uniform_location, m_po_dmat2x4_uniform_location,
2804         m_po_dmat3_uniform_location,  m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2805         m_po_dmat4_uniform_location,  m_po_dmat4x2_uniform_location, m_po_dmat4x3_uniform_location,
2806         m_po_double_uniform_location, m_po_dvec2_uniform_location,   m_po_dvec3_uniform_location,
2807         m_po_dvec4_uniform_location};
2808     const unsigned int n_double_uniform_locations =
2809         sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2810 
2811     gl.useProgram(m_po_id);
2812     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2813 
2814     for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2815     {
2816         glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2817 
2818         for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2819              function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2820         {
2821             _uniform_function e_function = static_cast<_uniform_function>(function);
2822             /* Exclude valid combinations */
2823             if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2824                 ((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2825                 ((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2826                 ((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2827                 ((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2828                 ((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2829                 ((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2830                 ((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2831                 ((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2832                 ((uniform_location == m_po_double_uniform_location) &&
2833                  ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2834                 ((uniform_location == m_po_dvec2_uniform_location) &&
2835                  ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2836                 ((uniform_location == m_po_dvec3_uniform_location) &&
2837                  ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2838                 ((uniform_location == m_po_dvec4_uniform_location) &&
2839                  ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2840             {
2841                 continue;
2842             }
2843 
2844             switch (e_function)
2845             {
2846             case UNIFORM_FUNCTION_1D:
2847             {
2848                 gl.uniform1d(uniform_location, double_data[0]);
2849 
2850                 break;
2851             }
2852 
2853             case UNIFORM_FUNCTION_2D:
2854             {
2855                 gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2856 
2857                 break;
2858             }
2859 
2860             case UNIFORM_FUNCTION_3D:
2861             {
2862                 gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2863 
2864                 break;
2865             }
2866 
2867             case UNIFORM_FUNCTION_4D:
2868             {
2869                 gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2870 
2871                 break;
2872             }
2873 
2874             case UNIFORM_FUNCTION_1DV:
2875                 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2876                 break;
2877             case UNIFORM_FUNCTION_2DV:
2878                 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2879                 break;
2880             case UNIFORM_FUNCTION_3DV:
2881                 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2882                 break;
2883             case UNIFORM_FUNCTION_4DV:
2884                 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2885                 break;
2886             case UNIFORM_FUNCTION_MATRIX2DV:
2887                 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2888                 break;
2889             case UNIFORM_FUNCTION_MATRIX2X3DV:
2890                 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2891                 break;
2892             case UNIFORM_FUNCTION_MATRIX2X4DV:
2893                 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2894                 break;
2895             case UNIFORM_FUNCTION_MATRIX3DV:
2896                 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2897                 break;
2898             case UNIFORM_FUNCTION_MATRIX3X2DV:
2899                 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2900                 break;
2901             case UNIFORM_FUNCTION_MATRIX3X4DV:
2902                 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2903                 break;
2904             case UNIFORM_FUNCTION_MATRIX4DV:
2905                 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2906                 break;
2907             case UNIFORM_FUNCTION_MATRIX4X2DV:
2908                 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2909                 break;
2910             case UNIFORM_FUNCTION_MATRIX4X3DV:
2911                 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2912                 break;
2913 
2914             default:
2915             {
2916                 TCU_FAIL("Unrecognized function");
2917             }
2918             } /* switch (function) */
2919 
2920             /* Make sure GL_INVALID_OPERATION error was generated */
2921             error_code = gl.getError();
2922 
2923             if (error_code != GL_INVALID_OPERATION)
2924             {
2925                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2926                                    << "] was generated when a mismatched "
2927                                       "double-precision uniform function "
2928                                    << getUniformFunctionString(e_function) << "() was used to configure uniform "
2929                                    << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2930 
2931                 result = false;
2932             }
2933         } /* for (all uniform functions) */
2934     }     /* for (all uniform locations) */
2935 
2936     return result;
2937 }
2938 
2939 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2940  *  glUniform*dv() functions is used to load an uniform, size of which is incompatible
2941  *  with the function.
2942  *
2943  *  @return true if the implementation was found to behave as expected, false otherwise.
2944  **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2945 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2946 {
2947     const double double_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
2948     glw::GLenum error_code     = GL_NO_ERROR;
2949     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
2950     bool result                = true;
2951 
2952     const int data[] = {
2953         /* API function */ /* Uniform location */ /* Count (dv functions only) */
2954         (int)UNIFORM_FUNCTION_2D,
2955         m_po_double_uniform_location,
2956         0,
2957         (int)UNIFORM_FUNCTION_2DV,
2958         m_po_double_uniform_location,
2959         2,
2960         (int)UNIFORM_FUNCTION_3D,
2961         m_po_double_uniform_location,
2962         0,
2963         (int)UNIFORM_FUNCTION_3DV,
2964         m_po_double_uniform_location,
2965         2,
2966         (int)UNIFORM_FUNCTION_4D,
2967         m_po_double_uniform_location,
2968         0,
2969         (int)UNIFORM_FUNCTION_4DV,
2970         m_po_double_uniform_location,
2971         2,
2972         (int)UNIFORM_FUNCTION_1D,
2973         m_po_dvec2_uniform_location,
2974         0,
2975         (int)UNIFORM_FUNCTION_1DV,
2976         m_po_dvec2_uniform_location,
2977         2,
2978         (int)UNIFORM_FUNCTION_3D,
2979         m_po_dvec2_uniform_location,
2980         0,
2981         (int)UNIFORM_FUNCTION_3DV,
2982         m_po_dvec2_uniform_location,
2983         2,
2984         (int)UNIFORM_FUNCTION_4D,
2985         m_po_dvec2_uniform_location,
2986         0,
2987         (int)UNIFORM_FUNCTION_4DV,
2988         m_po_dvec2_uniform_location,
2989         2,
2990         (int)UNIFORM_FUNCTION_1D,
2991         m_po_dvec3_uniform_location,
2992         0,
2993         (int)UNIFORM_FUNCTION_1DV,
2994         m_po_dvec3_uniform_location,
2995         2,
2996         (int)UNIFORM_FUNCTION_2D,
2997         m_po_dvec3_uniform_location,
2998         0,
2999         (int)UNIFORM_FUNCTION_2DV,
3000         m_po_dvec3_uniform_location,
3001         2,
3002         (int)UNIFORM_FUNCTION_4D,
3003         m_po_dvec3_uniform_location,
3004         0,
3005         (int)UNIFORM_FUNCTION_4DV,
3006         m_po_dvec3_uniform_location,
3007         2,
3008         (int)UNIFORM_FUNCTION_1D,
3009         m_po_dvec4_uniform_location,
3010         0,
3011         (int)UNIFORM_FUNCTION_1DV,
3012         m_po_dvec4_uniform_location,
3013         2,
3014         (int)UNIFORM_FUNCTION_2D,
3015         m_po_dvec4_uniform_location,
3016         0,
3017         (int)UNIFORM_FUNCTION_2DV,
3018         m_po_dvec4_uniform_location,
3019         2,
3020         (int)UNIFORM_FUNCTION_3D,
3021         m_po_dvec4_uniform_location,
3022         0,
3023         (int)UNIFORM_FUNCTION_3DV,
3024         m_po_dvec4_uniform_location,
3025         2,
3026     };
3027     const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
3028 
3029     gl.useProgram(m_po_id);
3030     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3031 
3032     for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
3033     {
3034         _uniform_function function = (_uniform_function)data[n_check * 3 + 0];
3035         int uniform_location       = data[n_check * 3 + 1];
3036         int uniform_count          = data[n_check * 3 + 2];
3037 
3038         switch (function)
3039         {
3040         case UNIFORM_FUNCTION_1D:
3041             gl.uniform1d(uniform_location, 0.0);
3042             break;
3043         case UNIFORM_FUNCTION_1DV:
3044             gl.uniform1dv(uniform_location, uniform_count, double_data);
3045             break;
3046         case UNIFORM_FUNCTION_2D:
3047             gl.uniform2d(uniform_location, 0.0, 1.0);
3048             break;
3049         case UNIFORM_FUNCTION_2DV:
3050             gl.uniform2dv(uniform_location, uniform_count, double_data);
3051             break;
3052         case UNIFORM_FUNCTION_3D:
3053             gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3054             break;
3055         case UNIFORM_FUNCTION_3DV:
3056             gl.uniform3dv(uniform_location, uniform_count, double_data);
3057             break;
3058         case UNIFORM_FUNCTION_4D:
3059             gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3060             break;
3061         case UNIFORM_FUNCTION_4DV:
3062             gl.uniform4dv(uniform_location, uniform_count, double_data);
3063             break;
3064 
3065         default:
3066         {
3067             DE_ASSERT(false);
3068         }
3069         } /* switch (function) */
3070 
3071         error_code = gl.getError();
3072         if (error_code != GL_INVALID_OPERATION)
3073         {
3074             m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3075                                << "() function did not generate GL_INVALID_OPERATION error when called for"
3076                                   " a uniform of incompatible size. (check index: "
3077                                << n_check << ")" << tcu::TestLog::EndMessage;
3078 
3079             result = false;
3080         }
3081     } /* for (all checks) */
3082 
3083     return result;
3084 }
3085 
3086 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3087  *  glUniform*dv() functions is used to load an uniform, type of which is incompatible
3088  *  with the function.
3089  *
3090  *  @return true if the implementation was found to behave as expected, false otherwise.
3091  **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3092 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3093 {
3094     const double double_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
3095     glw::GLenum error_code     = GL_NO_ERROR;
3096     const glw::Functions &gl   = m_context.getRenderContext().getFunctions();
3097     bool result                = true;
3098 
3099     const glw::GLint nondouble_uniform_locations[] = {
3100         m_po_bool_uniform_location,  m_po_bvec2_uniform_location, m_po_bvec3_uniform_location,
3101         m_po_bvec4_uniform_location, m_po_float_uniform_location, m_po_int_uniform_location,
3102         m_po_ivec2_uniform_location, m_po_ivec3_uniform_location, m_po_ivec4_uniform_location,
3103         m_po_uint_uniform_location,  m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3104         m_po_uvec4_uniform_location, m_po_vec2_uniform_location,  m_po_vec3_uniform_location,
3105         m_po_vec4_uniform_location};
3106     const unsigned int n_nondouble_uniform_locations =
3107         sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3108 
3109     gl.useProgram(m_po_id);
3110     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3111 
3112     for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3113     {
3114         glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3115 
3116         for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3117              function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3118         {
3119             switch (static_cast<_uniform_function>(function))
3120             {
3121             case UNIFORM_FUNCTION_1D:
3122                 gl.uniform1d(uniform_location, 0.0);
3123                 break;
3124             case UNIFORM_FUNCTION_1DV:
3125                 gl.uniform1dv(uniform_location, 1, double_data);
3126                 break;
3127             case UNIFORM_FUNCTION_2D:
3128                 gl.uniform2d(uniform_location, 0.0, 1.0);
3129                 break;
3130             case UNIFORM_FUNCTION_2DV:
3131                 gl.uniform2dv(uniform_location, 1, double_data);
3132                 break;
3133             case UNIFORM_FUNCTION_3D:
3134                 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3135                 break;
3136             case UNIFORM_FUNCTION_3DV:
3137                 gl.uniform3dv(uniform_location, 1, double_data);
3138                 break;
3139             case UNIFORM_FUNCTION_4D:
3140                 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3141                 break;
3142             case UNIFORM_FUNCTION_4DV:
3143                 gl.uniform4dv(uniform_location, 1, double_data);
3144                 break;
3145 
3146             case UNIFORM_FUNCTION_MATRIX2DV:
3147                 gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3148                 break;
3149             case UNIFORM_FUNCTION_MATRIX2X3DV:
3150                 gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3151                 break;
3152             case UNIFORM_FUNCTION_MATRIX2X4DV:
3153                 gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3154                 break;
3155             case UNIFORM_FUNCTION_MATRIX3DV:
3156                 gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3157                 break;
3158             case UNIFORM_FUNCTION_MATRIX3X2DV:
3159                 gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3160                 break;
3161             case UNIFORM_FUNCTION_MATRIX3X4DV:
3162                 gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3163                 break;
3164             case UNIFORM_FUNCTION_MATRIX4DV:
3165                 gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3166                 break;
3167             case UNIFORM_FUNCTION_MATRIX4X2DV:
3168                 gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3169                 break;
3170             case UNIFORM_FUNCTION_MATRIX4X3DV:
3171                 gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3172                 break;
3173 
3174             default:
3175             {
3176                 DE_ASSERT(false);
3177             }
3178             } /* switch (function) */
3179 
3180             error_code = gl.getError();
3181             if (error_code != GL_INVALID_OPERATION)
3182             {
3183                 m_testCtx.getLog() << tcu::TestLog::Message
3184                                    << getUniformFunctionString(static_cast<_uniform_function>(function))
3185                                    << "() function did not generate GL_INVALID_OPERATION error when called for"
3186                                       " a uniform of incompatible type."
3187                                    << tcu::TestLog::EndMessage;
3188 
3189                 result = false;
3190             }
3191         }
3192     } /* for (all checks) */
3193 
3194     return result;
3195 }
3196 
3197 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3198  *  glUniform*dv() functions are called without a bound program object.
3199  *
3200  *  @return true if the implementation was found to behave as expected, false otherwise.
3201  **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3202 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3203 {
3204     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3205     bool result              = true;
3206 
3207     for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3208          function++)
3209     {
3210         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};
3211 
3212         switch (static_cast<_uniform_function>(function))
3213         {
3214         case UNIFORM_FUNCTION_1D:
3215             gl.uniform1d(m_po_double_uniform_location, 0.0);
3216             break;
3217         case UNIFORM_FUNCTION_1DV:
3218             gl.uniform1dv(m_po_double_uniform_location, 1, data);
3219             break;
3220         case UNIFORM_FUNCTION_2D:
3221             gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3222             break;
3223         case UNIFORM_FUNCTION_2DV:
3224             gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3225             break;
3226         case UNIFORM_FUNCTION_3D:
3227             gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3228             break;
3229         case UNIFORM_FUNCTION_3DV:
3230             gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3231             break;
3232         case UNIFORM_FUNCTION_4D:
3233             gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3234             break;
3235         case UNIFORM_FUNCTION_4DV:
3236             gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3237             break;
3238 
3239         case UNIFORM_FUNCTION_MATRIX2DV:
3240             gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3241             break;
3242         case UNIFORM_FUNCTION_MATRIX2X3DV:
3243             gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3244             break;
3245         case UNIFORM_FUNCTION_MATRIX2X4DV:
3246             gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3247             break;
3248         case UNIFORM_FUNCTION_MATRIX3DV:
3249             gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3250             break;
3251         case UNIFORM_FUNCTION_MATRIX3X2DV:
3252             gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3253             break;
3254         case UNIFORM_FUNCTION_MATRIX3X4DV:
3255             gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3256             break;
3257         case UNIFORM_FUNCTION_MATRIX4DV:
3258             gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3259             break;
3260         case UNIFORM_FUNCTION_MATRIX4X2DV:
3261             gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3262             break;
3263         case UNIFORM_FUNCTION_MATRIX4X3DV:
3264             gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3265             break;
3266 
3267         default:
3268         {
3269             TCU_FAIL("Unrecognized uniform function");
3270         }
3271         } /* switch (func) */
3272 
3273         /* Query the error code */
3274         glw::GLenum error_code = gl.getError();
3275 
3276         if (error_code != GL_INVALID_OPERATION)
3277         {
3278             m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3279                                << getUniformFunctionString(static_cast<_uniform_function>(function))
3280                                << "() was called without an active program object" << tcu::TestLog::EndMessage;
3281 
3282             result = false;
3283         }
3284     } /* for (all uniform functions) */
3285 
3286     return result;
3287 }
3288 
3289 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3290 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3291 const glw::GLint GPUShaderFP64Test2::m_result_failure      = 2;
3292 const glw::GLint GPUShaderFP64Test2::m_result_success      = 1;
3293 const glw::GLuint GPUShaderFP64Test2::m_texture_width      = 32;
3294 const glw::GLuint GPUShaderFP64Test2::m_texture_height     = m_n_captured_results / m_texture_width;
3295 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3296     m_n_captured_results * sizeof(captured_varying_type);
3297 const glw::GLchar *GPUShaderFP64Test2::m_uniform_block_name              = "UniformBlock";
3298 const glw::GLenum GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3299 
3300 /** Constructor
3301  *
3302  * @param context Test context
3303  **/
GPUShaderFP64Test2(deqp::Context & context)3304 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context &context)
3305     : TestCase(context, "max_uniform_components",
3306                "Verifies that maximum allowed uniform components can be used as double-precision float types")
3307     , m_pDispatchCompute(0)
3308     , m_framebuffer_id(0)
3309     , m_texture_id(0)
3310     , m_transform_feedback_buffer_id(0)
3311     , m_uniform_buffer_id(0)
3312     , m_vertex_array_object_id(0)
3313 {
3314     /* Nothing to be done */
3315 }
3316 
3317 /** Deinitialize test
3318  *
3319  **/
deinit()3320 void GPUShaderFP64Test2::deinit()
3321 {
3322     /* GL entry points */
3323     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
3324 
3325     /* Clean frambuffer */
3326     if (0 != m_framebuffer_id)
3327     {
3328         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3329         gl.deleteFramebuffers(1, &m_framebuffer_id);
3330         m_framebuffer_id = 0;
3331     }
3332 
3333     /* Clean texture */
3334     if (0 != m_texture_id)
3335     {
3336         gl.bindTexture(GL_TEXTURE_2D, 0);
3337         gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3338                             GL_READ_ONLY, GL_RGBA8);
3339         gl.deleteTextures(1, &m_texture_id);
3340         m_texture_id = 0;
3341     }
3342 
3343     /* Clean buffers */
3344     if (0 != m_transform_feedback_buffer_id)
3345     {
3346         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3347         gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3348         m_transform_feedback_buffer_id = 0;
3349     }
3350 
3351     if (0 != m_uniform_buffer_id)
3352     {
3353         gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3354         gl.deleteBuffers(1, &m_uniform_buffer_id);
3355         m_uniform_buffer_id = 0;
3356     }
3357 
3358     /* Clean VAO */
3359     if (0 != m_vertex_array_object_id)
3360     {
3361         gl.bindVertexArray(0);
3362         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3363         m_vertex_array_object_id = 0;
3364     }
3365 }
3366 
3367 /** Execute test
3368  *
3369  * @return tcu::TestNode::STOP
3370  **/
iterate()3371 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3372 {
3373     bool result = true;
3374 
3375     /* Check if extension is supported */
3376     if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3377     {
3378         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3379     }
3380 
3381     /* Initialize test */
3382     testInit();
3383 
3384     prepareShaderStages();
3385     prepareUniformTypes();
3386 
3387     /* For all shaders and uniform type combinations */
3388     for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3389          m_shader_stages.end() != shader_stage; ++shader_stage)
3390     {
3391         for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3392              m_uniform_types.end() != uniform_type; ++uniform_type)
3393         {
3394             /* Execute test */
3395             if (false == test(*shader_stage, *uniform_type))
3396             {
3397                 result = false;
3398             }
3399         }
3400     }
3401 
3402     /* Set result */
3403     if (true == result)
3404     {
3405         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3406     }
3407     else
3408     {
3409         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3410     }
3411 
3412     /* Done */
3413     return tcu::TestNode::STOP;
3414 }
3415 
3416 /** Constructor
3417  *
3418  * @param n_columns Number of columns
3419  * @param n_rows    Number of rows
3420  **/
uniformTypeDetails(glw::GLuint n_columns,glw::GLuint n_rows)3421 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3422     : m_n_columns(n_columns)
3423     , m_n_rows(n_rows)
3424 {
3425     Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3426 
3427     m_type_name = Utils::getVariableTypeString(type);
3428     m_type      = Utils::getGLDataTypeOfVariableType(type);
3429 }
3430 
3431 /** Get primitive type captured with transform feedback
3432  *
3433  * @param shader_stage Tested shader stage id
3434  *
3435  * @return Primitive type
3436  **/
getCapturedPrimitiveType(shaderStage shader_stage) const3437 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3438 {
3439     switch (shader_stage)
3440     {
3441     case GEOMETRY_SHADER:
3442     case TESS_CTRL_SHADER:
3443     case TESS_EVAL_SHADER:
3444     case VERTEX_SHADER:
3445         return GL_POINTS;
3446 
3447     default:
3448         return GL_NONE;
3449     }
3450 }
3451 
3452 /** Get primitive type drawn with DrawArrays
3453  *
3454  * @param shader_stage Tested shader stage id
3455  *
3456  * @return Primitive type
3457  **/
getDrawPrimitiveType(shaderStage shader_stage) const3458 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3459 {
3460     switch (shader_stage)
3461     {
3462     case FRAGMENT_SHADER:
3463         return GL_TRIANGLE_FAN;
3464 
3465     case GEOMETRY_SHADER:
3466     case VERTEX_SHADER:
3467         return GL_POINTS;
3468 
3469     case TESS_CTRL_SHADER:
3470     case TESS_EVAL_SHADER:
3471         return GL_PATCHES;
3472 
3473     default:
3474         return GL_NONE;
3475     }
3476 }
3477 
3478 /** Get maximum allowed number of uniform components
3479  *
3480  * @param shader_stage Tested shader stage id
3481  *
3482  * @return Maxmimum uniform components
3483  **/
getMaxUniformComponents(shaderStage shader_stage) const3484 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3485 {
3486     const glw::Functions &gl          = m_context.getRenderContext().getFunctions();
3487     glw::GLint max_uniform_components = 0;
3488     glw::GLenum pname                 = 0;
3489 
3490     switch (shader_stage)
3491     {
3492     case COMPUTE_SHADER:
3493         pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3494         break;
3495     case FRAGMENT_SHADER:
3496         pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3497         break;
3498     case GEOMETRY_SHADER:
3499         pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3500         break;
3501     case TESS_CTRL_SHADER:
3502         pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3503         break;
3504     case TESS_EVAL_SHADER:
3505         pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3506         break;
3507     case VERTEX_SHADER:
3508         pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3509         break;
3510     }
3511 
3512     gl.getIntegerv(pname, &max_uniform_components);
3513     GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3514 
3515     return max_uniform_components;
3516 }
3517 
3518 /** Get maximum size allowed for an uniform block
3519  *
3520  * @return Maxmimum uniform block size
3521  **/
getMaxUniformBlockSize() const3522 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3523 {
3524     const glw::Functions &gl          = m_context.getRenderContext().getFunctions();
3525     glw::GLint max_uniform_block_size = 0;
3526 
3527     gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3528     GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3529 
3530     return max_uniform_block_size;
3531 }
3532 
3533 /** Get number of components required to store single uniform of given type
3534  *
3535  * @param uniform_type Tested uniform type
3536  *
3537  * @return Number of components
3538  **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3539 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails &uniform_type) const
3540 {
3541     static const glw::GLuint type_size = 2; /* double takes 2 N */
3542     const glw::GLuint column_length    = uniform_type.m_n_rows;
3543 
3544     if (1 == uniform_type.m_n_columns)
3545     {
3546         return type_size * column_length;
3547     }
3548     else
3549     {
3550         const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3551 
3552         return alignment * uniform_type.m_n_columns;
3553     }
3554 }
3555 
3556 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3557  *
3558  * @param uniform_type Tested uniform type
3559  *
3560  * @return Size of a single member
3561  **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3562 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails &uniform_type) const
3563 {
3564     static const glw::GLuint vec4_size = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3565     const glw::GLuint column_length    = uniform_type.m_n_rows;
3566 
3567     /** Size for a layout(std140, column_major) uniform_type uniform[] **/
3568     return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3569 }
3570 
3571 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3572  *
3573  * @param shader_stage Tested shader stage id
3574  * @param uniform_type Tested uniform type
3575  *
3576  * @return Number of components
3577  **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3578 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage shader_stage,
3579                                                   const uniformTypeDetails &uniform_type) const
3580 {
3581     const glw::GLuint max_uniform_components   = getMaxUniformComponents(shader_stage);
3582     const glw::GLuint required_components      = getRequiredComponentsNumber(uniform_type);
3583     const glw::GLuint n_uniforms               = max_uniform_components / required_components;
3584     const glw::GLuint max_uniform_block_size   = getMaxUniformBlockSize();
3585     const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3586     const glw::GLuint max_uniforms             = max_uniform_block_size / uniform_type_member_size;
3587 
3588     return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3589 }
3590 
3591 /** Get name of shader stage
3592  *
3593  * @param shader_stage Tested shader stage id
3594  *
3595  * @return Name
3596  **/
getShaderStageName(shaderStage shader_stage) const3597 const glw::GLchar *GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3598 {
3599     switch (shader_stage)
3600     {
3601     case COMPUTE_SHADER:
3602         return "compute shader";
3603     case FRAGMENT_SHADER:
3604         return "fragment shader";
3605     case GEOMETRY_SHADER:
3606         return "geometry shader";
3607     case TESS_CTRL_SHADER:
3608         return "tesselation control shader";
3609     case TESS_EVAL_SHADER:
3610         return "tesselation evaluation shader";
3611     case VERTEX_SHADER:
3612         return "vertex shader";
3613     }
3614 
3615     return 0;
3616 }
3617 
3618 /** Inspect program to get: buffer_size, offset, strides and block index
3619  *
3620  * @param program_id          Program id
3621  * @param out_buffer_size     Size of uniform buffer
3622  * @param out_uniform_details Uniform offset and strides
3623  * @param uniform_block_index Uniform block index
3624  **/
inspectProgram(glw::GLuint program_id,glw::GLint n_uniforms,const uniformTypeDetails & uniform_type,glw::GLint & out_buffer_size,uniformDetails & out_uniform_details,glw::GLuint & uniform_block_index) const3625 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3626                                         const uniformTypeDetails &uniform_type, glw::GLint &out_buffer_size,
3627                                         uniformDetails &out_uniform_details, glw::GLuint &uniform_block_index) const
3628 {
3629     glw::GLint array_stride = 0;
3630     std::vector<glw::GLchar> extracted_uniform_name;
3631     const glw::Functions &gl        = m_context.getRenderContext().getFunctions();
3632     glw::GLuint index               = 0;
3633     glw::GLint matrix_stride        = 0;
3634     glw::GLint offset               = 0;
3635     glw::GLsizei size               = 0;
3636     glw::GLenum type                = 0;
3637     const glw::GLchar *uniform_name = 0;
3638     std::string uniform_name_str;
3639     std::stringstream uniform_name_stream;
3640 
3641     /* Get index of uniform block */
3642     uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3643     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3644 
3645     if (GL_INVALID_INDEX == uniform_block_index)
3646     {
3647         TCU_FAIL("Unifom block is inactive");
3648     }
3649 
3650     /* Get size of uniform block */
3651     gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3652     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3653 
3654     if (0 == out_buffer_size)
3655     {
3656         TCU_FAIL("Unifom block size is 0");
3657     }
3658 
3659     /* Prepare uniform name */
3660     uniform_name_stream << "uniform_array";
3661 
3662     uniform_name_str = uniform_name_stream.str();
3663     uniform_name     = uniform_name_str.c_str();
3664 
3665     /* Get index of uniform */
3666     gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3667     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3668 
3669     if (GL_INVALID_INDEX == index)
3670     {
3671         TCU_FAIL("Unifom is inactive");
3672     }
3673 
3674     /* Verify getActiveUniform results */
3675     extracted_uniform_name.resize(uniform_name_str.length() * 2);
3676 
3677     gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3678                         &extracted_uniform_name[0]);
3679     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3680 
3681     if ((n_uniforms != size) || (uniform_type.m_type != type))
3682     {
3683         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3684                                             << " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3685                                             << " expected: " << uniform_type.m_type
3686                                             << ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3687 
3688         TCU_FAIL("Invalid GetActiveUniform results");
3689     }
3690 
3691     /* Get offset of uniform */
3692     gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3693     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3694 
3695     if (-1 == offset)
3696     {
3697         TCU_FAIL("Unifom has invalid offset");
3698     }
3699 
3700     out_uniform_details.m_offset = offset;
3701 
3702     /* Get matrix stride of uniform */
3703     gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3704     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3705 
3706     if (-1 == matrix_stride)
3707     {
3708         TCU_FAIL("Unifom has invalid matrix stride");
3709     }
3710 
3711     out_uniform_details.m_matrix_stride = matrix_stride;
3712 
3713     /* Get array stride of uniform */
3714     gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3715     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3716 
3717     if (-1 == matrix_stride)
3718     {
3719         TCU_FAIL("Unifom has invalid matrix stride");
3720     }
3721 
3722     out_uniform_details.m_array_stride = array_stride;
3723 }
3724 
3725 /** Prepare source code for "boilerplate" shaders
3726  *
3727  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
3728  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3729  * @param out_source_code          Source code
3730  **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3731 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar *stage_specific_layout,
3732                                                   const glw::GLchar *stage_specific_main_body,
3733                                                   std::string &out_source_code) const
3734 {
3735     /* Shader template */
3736     static const glw::GLchar *boilerplate_shader_template_code = "#version 400 core\n"
3737                                                                  "\n"
3738                                                                  "precision highp float;\n"
3739                                                                  "\n"
3740                                                                  "STAGE_SPECIFIC_LAYOUT"
3741                                                                  "void main()\n"
3742                                                                  "{\n"
3743                                                                  "STAGE_SPECIFIC_MAIN_BODY"
3744                                                                  "}\n"
3745                                                                  "\n";
3746 
3747     std::string string = boilerplate_shader_template_code;
3748 
3749     /* Tokens */
3750     static const glw::GLchar *body_token   = "STAGE_SPECIFIC_MAIN_BODY";
3751     static const glw::GLchar *layout_token = "STAGE_SPECIFIC_LAYOUT";
3752 
3753     size_t search_position = 0;
3754 
3755     /* Replace tokens */
3756     Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3757     Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3758 
3759     /* Store resuls */
3760     out_source_code = string;
3761 }
3762 
3763 /** Prepare program for given combination of shader stage and uniform type
3764  *
3765  * @param shader_stage     Shader stage
3766  * @param uniform_type     Uniform type
3767  * @param out_program_info Instance of programInfo
3768  **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3769 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails &uniform_type,
3770                                         Utils::programInfo &out_program_info) const
3771 {
3772     /* Stage specific layouts */
3773     static const glw::GLchar *geometry_shader_layout_code = "layout(points)                   in;\n"
3774                                                             "layout(points, max_vertices = 1) out;\n"
3775                                                             "\n";
3776 
3777     static const glw::GLchar *tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3778                                                              "\n";
3779 
3780     static const glw::GLchar *tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3781                                                              "\n";
3782 
3783     /* Stage specific main body */
3784     static const glw::GLchar *boilerplate_fragment_shader_body_code = "    discard;\n";
3785 
3786     static const glw::GLchar *boilerplate_tess_ctrl_shader_body_code = "    gl_TessLevelOuter[0] = 1.0;\n"
3787                                                                        "    gl_TessLevelOuter[1] = 1.0;\n"
3788                                                                        "    gl_TessLevelOuter[2] = 1.0;\n"
3789                                                                        "    gl_TessLevelOuter[3] = 1.0;\n"
3790                                                                        "    gl_TessLevelInner[0] = 1.0;\n"
3791                                                                        "    gl_TessLevelInner[1] = 1.0;\n";
3792 
3793     static const glw::GLchar *boilerplate_vertex_shader_body_code = "    gl_Position = vec4(1, 0, 0, 1);\n";
3794 
3795     static const glw::GLchar *corner_vertex_shader_body_code = "    if (0 == gl_VertexID)\n"
3796                                                                "    {\n"
3797                                                                "        gl_Position = vec4(-1, -1, 0, 1);\n"
3798                                                                "    }\n"
3799                                                                "    else if (1 == gl_VertexID)\n"
3800                                                                "    {\n"
3801                                                                "        gl_Position = vec4(-1, 1, 0, 1);\n"
3802                                                                "    }\n"
3803                                                                "    else if (2 == gl_VertexID)\n"
3804                                                                "    {\n"
3805                                                                "        gl_Position = vec4(1, 1, 0, 1);\n"
3806                                                                "    }\n"
3807                                                                "    else if (3 == gl_VertexID)\n"
3808                                                                "    {\n"
3809                                                                "        gl_Position = vec4(1, -1, 0, 1);\n"
3810                                                                "    }\n";
3811 
3812     static const glw::GLchar *passthrough_tess_eval_shader_body_code = "    result = tcs_tes_result[0];\n";
3813 
3814     static const glw::GLchar *test_shader_body_code = "\n    result = verification_result;\n";
3815 
3816     static const glw::GLchar *test_geometry_shader_body_code = "\n    result = verification_result;\n"
3817                                                                "\n"
3818                                                                "    EmitVertex();\n"
3819                                                                "    EndPrimitive();\n";
3820 
3821     static const glw::GLchar *test_tess_ctrl_shader_body_code =
3822         "\n    tcs_tes_result[gl_InvocationID] = verification_result;\n"
3823         "\n"
3824         "    gl_TessLevelOuter[0] = 1.0;\n"
3825         "    gl_TessLevelOuter[1] = 1.0;\n"
3826         "    gl_TessLevelOuter[2] = 1.0;\n"
3827         "    gl_TessLevelOuter[3] = 1.0;\n"
3828         "    gl_TessLevelInner[0] = 1.0;\n"
3829         "    gl_TessLevelInner[1] = 1.0;\n";
3830 
3831     /* In variables */
3832     static const glw::GLchar *test_tess_ctrl_shader_in_variable = "in  int tcs_tes_result[];\n";
3833 
3834     /* Out variables */
3835     static const glw::GLchar *test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3836 
3837     static const glw::GLchar *test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3838 
3839     static const glw::GLchar *test_shader_out_variable = "out int result;\n";
3840 
3841     /* Varying name */
3842     static const glw::GLchar *varying_name = "result";
3843     glw::GLuint n_varyings                 = 1;
3844 
3845     /* Storage for ready shaders */
3846     std::string compute_shader_code;
3847     std::string fragment_shader_code;
3848     std::string geometry_shader_code;
3849     std::string tess_ctrl_shader_code;
3850     std::string tess_eval_shader_code;
3851     std::string vertex_shader_code;
3852 
3853     /* Storage for uniform definition and verification code */
3854     std::string uniform_definitions;
3855     std::string uniform_verification;
3856 
3857     /* Get uniform definition and verification code */
3858     prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3859     prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3860 
3861     /* Prepare vertex shader */
3862     switch (shader_stage)
3863     {
3864     case FRAGMENT_SHADER:
3865 
3866         prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3867 
3868         break;
3869 
3870     case GEOMETRY_SHADER:
3871     case TESS_CTRL_SHADER:
3872     case TESS_EVAL_SHADER:
3873 
3874         prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3875 
3876         break;
3877 
3878     case VERTEX_SHADER:
3879 
3880         prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3881                           test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3882                           test_shader_body_code /* body */, vertex_shader_code);
3883 
3884         break;
3885 
3886     default:
3887         break;
3888     }
3889 
3890     /* Prepare fragment shader */
3891     switch (shader_stage)
3892     {
3893     case FRAGMENT_SHADER:
3894 
3895         prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3896                           test_fragment_shader_out_variable /* out var */,
3897                           uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3898                           fragment_shader_code);
3899 
3900         break;
3901 
3902     case GEOMETRY_SHADER:
3903     case TESS_CTRL_SHADER:
3904     case TESS_EVAL_SHADER:
3905     case VERTEX_SHADER:
3906 
3907         prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3908                                  fragment_shader_code);
3909 
3910         break;
3911 
3912     default:
3913         break;
3914     }
3915 
3916     /* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3917     switch (shader_stage)
3918     {
3919     case COMPUTE_SHADER:
3920 
3921         prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3922 
3923         break;
3924 
3925     case GEOMETRY_SHADER:
3926 
3927         prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3928                           "" /* in var */, test_shader_out_variable /* out var */,
3929                           uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3930                           geometry_shader_code);
3931 
3932         break;
3933 
3934     case TESS_CTRL_SHADER:
3935 
3936         prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3937                           "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3938                           uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3939                           tess_ctrl_shader_code);
3940 
3941         prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3942                           test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3943                           "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3944                           tess_eval_shader_code);
3945 
3946         break;
3947 
3948     case TESS_EVAL_SHADER:
3949 
3950         prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3951                                  boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3952 
3953         prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3954                           "" /* in var */, test_shader_out_variable /* out var */,
3955                           uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3956                           tess_eval_shader_code);
3957 
3958         break;
3959 
3960     default:
3961         break;
3962     }
3963 
3964     /* Select shaders that will be used by program */
3965     const glw::GLchar *cs_c_str  = 0;
3966     const glw::GLchar *fs_c_str  = 0;
3967     const glw::GLchar *gs_c_str  = 0;
3968     const glw::GLchar *tcs_c_str = 0;
3969     const glw::GLchar *tes_c_str = 0;
3970     const glw::GLchar *vs_c_str  = 0;
3971 
3972     if (false == compute_shader_code.empty())
3973     {
3974         cs_c_str = compute_shader_code.c_str();
3975     }
3976 
3977     if (false == fragment_shader_code.empty())
3978     {
3979         fs_c_str = fragment_shader_code.c_str();
3980     }
3981 
3982     if (false == geometry_shader_code.empty())
3983     {
3984         gs_c_str = geometry_shader_code.c_str();
3985     }
3986 
3987     if (false == tess_ctrl_shader_code.empty())
3988     {
3989         tcs_c_str = tess_ctrl_shader_code.c_str();
3990     }
3991 
3992     if (false == tess_eval_shader_code.empty())
3993     {
3994         tes_c_str = tess_eval_shader_code.c_str();
3995     }
3996 
3997     if (false == vertex_shader_code.empty())
3998     {
3999         vs_c_str = vertex_shader_code.c_str();
4000     }
4001 
4002     /* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
4003     if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
4004     {
4005         n_varyings = 0;
4006     }
4007 
4008     /* Build */
4009     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);
4010 }
4011 
4012 /** Prepare collection of tested shader stages
4013  *
4014  */
prepareShaderStages()4015 void GPUShaderFP64Test2::prepareShaderStages()
4016 {
4017     /* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
4018     if (0 != m_pDispatchCompute)
4019     {
4020         m_shader_stages.push_back(COMPUTE_SHADER);
4021     }
4022 
4023     m_shader_stages.push_back(FRAGMENT_SHADER);
4024     m_shader_stages.push_back(GEOMETRY_SHADER);
4025     m_shader_stages.push_back(TESS_CTRL_SHADER);
4026     m_shader_stages.push_back(TESS_EVAL_SHADER);
4027     m_shader_stages.push_back(VERTEX_SHADER);
4028 }
4029 
4030 /** Prepare source code for "tested" shader stage
4031  *
4032  * @param stage_specific_layout    String that will replace STAGE_SPECIFIC_LAYOUT token
4033  * @param uniform_definitions      String that will replace UNIFORM_DEFINITIONS token
4034  * @param in_variable_definitions  String that will replace IN_VARIABLE_DEFINITION token
4035  * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
4036  * @param uniform_verification     String that will replace UNIFORM_VERIFICATION token
4037  * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
4038  * @param out_source_code          Shader source code
4039  **/
prepareTestShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * uniform_definitions,const glw::GLchar * in_variable_definitions,const glw::GLchar * out_variable_definitions,const glw::GLchar * uniform_verification,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const4040 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar *stage_specific_layout,
4041                                            const glw::GLchar *uniform_definitions,
4042                                            const glw::GLchar *in_variable_definitions,
4043                                            const glw::GLchar *out_variable_definitions,
4044                                            const glw::GLchar *uniform_verification,
4045                                            const glw::GLchar *stage_specific_main_body,
4046                                            std::string &out_source_code) const
4047 {
4048     /* Shader template */
4049     static const glw::GLchar *test_shader_template_code = "#version 400 core\n"
4050                                                           "\n"
4051                                                           "precision highp float;\n"
4052                                                           "\n"
4053                                                           "STAGE_SPECIFIC_LAYOUT"
4054                                                           "UNIFORM_DEFINITIONS"
4055                                                           "IN_VARIABLE_DEFINITION"
4056                                                           "OUT_VARIABLE_DEFINITION"
4057                                                           "\n"
4058                                                           "void main()\n"
4059                                                           "{\n"
4060                                                           "UNIFORM_VERIFICATION"
4061                                                           "STAGE_SPECIFIC_MAIN_BODY"
4062                                                           "}\n"
4063                                                           "\n";
4064 
4065     std::string string = test_shader_template_code;
4066 
4067     /* Tokens */
4068     static const glw::GLchar *body_token    = "STAGE_SPECIFIC_MAIN_BODY";
4069     static const glw::GLchar *in_var_token  = "IN_VARIABLE_DEFINITION";
4070     static const glw::GLchar *layout_token  = "STAGE_SPECIFIC_LAYOUT";
4071     static const glw::GLchar *out_var_token = "OUT_VARIABLE_DEFINITION";
4072     static const glw::GLchar *uni_def_token = "UNIFORM_DEFINITIONS";
4073     static const glw::GLchar *uni_ver_token = "UNIFORM_VERIFICATION";
4074 
4075     size_t search_position = 0;
4076 
4077     /* Replace tokens */
4078     Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4079     Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4080     Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4081     Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4082     Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083     Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4084 
4085     /* Store resuls */
4086     out_source_code = string;
4087 }
4088 
4089 /** Prepare source code for "tested" compute shaders
4090  *
4091  * @param uniform_definitions  String that will replace UNIFORM_DEFINITIONS token
4092  * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4093  * @param out_source_code      Source code
4094  **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4095 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar *uniform_definitions,
4096                                                   const glw::GLchar *uniform_verification,
4097                                                   std::string &out_source_code) const
4098 {
4099     /* Shader template */
4100     static const glw::GLchar *test_shader_template_code =
4101         "#version 420 core\n"
4102         "#extension GL_ARB_compute_shader          : require\n"
4103         "#extension GL_ARB_shader_image_load_store : require\n"
4104         "\n"
4105         "precision highp float;\n"
4106         "\n"
4107         "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4108         "\n"
4109         "UNIFORM_DEFINITIONS"
4110         "layout(r32i) writeonly uniform iimage2D result;\n"
4111         "\n"
4112         "void main()\n"
4113         "{\n"
4114         "UNIFORM_VERIFICATION"
4115         "\n"
4116         "    imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4117         "}\n"
4118         "\n";
4119 
4120     std::string string = test_shader_template_code;
4121 
4122     /* Tokens */
4123     static const glw::GLchar *uni_def_token = "UNIFORM_DEFINITIONS";
4124     static const glw::GLchar *uni_ver_token = "UNIFORM_VERIFICATION";
4125 
4126     size_t search_position = 0;
4127 
4128     /* Replace tokens */
4129     Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4130     Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4131 
4132     /* Store resuls */
4133     out_source_code = string;
4134 }
4135 
4136 /** Prepare source code which defines uniforms for tested shader stage
4137  *
4138  * @param shader_stage    Shader stage id
4139  * @param uniform_type    Details of uniform type
4140  * @param out_source_code Source code
4141  **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4142 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails &uniform_type,
4143                                                    std::string &out_source_code) const
4144 {
4145     const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4146     std::stringstream stream;
4147 
4148     /*
4149      * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4150      * {
4151      *     TYPE_NAME uniform_array[N_UNIFORMS];
4152      * };
4153      */
4154     stream << "layout(std140) uniform " << m_uniform_block_name
4155            << "\n"
4156               "{\n";
4157 
4158     stream << "    " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4159 
4160     stream << "};\n\n";
4161 
4162     out_source_code = stream.str();
4163 }
4164 
4165 /** Prepare uniform buffer for test
4166  *
4167  * @param shader_stage Shader stage id
4168  * @param uniform_type Details of uniform type
4169  * @param program_info Program object info
4170  **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4171 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails &uniform_type,
4172                                          const Utils::programInfo &program_info) const
4173 {
4174     glw::GLint buffer_size       = 0;
4175     glw::GLuint element_ordinal  = 1;
4176     const glw::Functions &gl     = m_context.getRenderContext().getFunctions();
4177     const glw::GLuint n_columns  = uniform_type.m_n_columns;
4178     const glw::GLuint n_rows     = uniform_type.m_n_rows;
4179     const glw::GLuint n_elements = n_columns * n_rows;
4180     uniformDetails uniform_details;
4181     const glw::GLuint program_id = program_info.m_program_object_id;
4182     const glw::GLint n_uniforms  = getAmountUniforms(shader_stage, uniform_type);
4183     std::vector<glw::GLubyte> uniform_buffer_data;
4184     glw::GLuint uniform_block_index = 0;
4185 
4186     /* Get uniform details */
4187     inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4188 
4189     /* Uniform offset and strides */
4190     const glw::GLuint array_stride   = uniform_details.m_array_stride;
4191     const glw::GLuint matrix_stride  = uniform_details.m_matrix_stride;
4192     const glw::GLuint uniform_offset = uniform_details.m_offset;
4193 
4194     /* Prepare storage for buffer data */
4195     uniform_buffer_data.resize(buffer_size);
4196 
4197     /* Prepare uniform data */
4198     for (glw::GLint i = 0; i < n_uniforms; ++i)
4199     {
4200         const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4201 
4202         for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4203         {
4204             const glw::GLuint column       = element / n_rows;
4205             const glw::GLuint column_elem  = element % n_rows;
4206             const glw::GLdouble value      = element_ordinal;
4207             const glw::GLuint value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4208                                                                       column_elem * sizeof(glw::GLdouble));
4209             glw::GLdouble *value_dst       = (glw::GLdouble *)&uniform_buffer_data[value_offset];
4210 
4211             *value_dst = value;
4212         }
4213     }
4214 
4215     /* Update uniform buffer with new set of data */
4216     gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4217     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4218 
4219     gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4220     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4221 
4222     /* Bind uniform block to uniform buffer */
4223     gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4224     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4225 
4226     gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4227     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4228 }
4229 
4230 /** Prepare collection of tested uniform types
4231  *
4232  **/
prepareUniformTypes()4233 void GPUShaderFP64Test2::prepareUniformTypes()
4234 {
4235     m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4236     m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4237     m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4238     m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4239     m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4240     m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4241     m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4242     m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4243     m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4244     m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4245     m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4246     m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4247     m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4248 }
4249 
4250 /** Prepare source code that verifes uniform values
4251  *
4252  * @param shader_stage    Shader stage id
4253  * @param uniform_type    Details of uniform type
4254  * @param out_source_code Source code
4255  **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4256 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails &uniform_type,
4257                                                     std::string &out_source_code) const
4258 {
4259     glw::GLuint element_ordinal  = 1;
4260     const glw::GLuint n_columns  = uniform_type.m_n_columns;
4261     const glw::GLuint n_rows     = uniform_type.m_n_rows;
4262     const glw::GLuint n_elements = n_columns * n_rows;
4263     const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4264     std::stringstream stream;
4265 
4266     /*
4267      * int verification_result = M_RESULT_SUCCESS;
4268      *
4269      * for (int i = 0; i < N_UNIFORMS; ++i)
4270      * {
4271      *     if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4272      *     {
4273      *         verification_result = M_RESULT_FAILURE
4274      *     }
4275      * }
4276      */
4277     stream << "    int verification_result = " << m_result_success
4278            << ";\n"
4279               "\n"
4280               "    for (int i = 0; i < "
4281            << n_uniforms
4282            << "; ++i)\n"
4283               "    {\n"
4284               "        if ("
4285            << uniform_type.m_type_name << "(";
4286 
4287     for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4288     {
4289         stream << "i * (" << n_elements << ") + " << element + 1;
4290 
4291         if (n_elements != element + 1)
4292         {
4293             stream << ", ";
4294         }
4295     }
4296 
4297     stream << ") != uniform_array[i])\n"
4298               "        {\n"
4299               "           verification_result = "
4300            << m_result_failure
4301            << ";\n"
4302               "        }\n"
4303               "    }\n";
4304 
4305     out_source_code = stream.str();
4306 }
4307 
4308 /** Execute test for given combination of "tested" shader stage and uniform type
4309  *
4310  * @param shader_stage Tested shader stage id
4311  * @param uniform_type Tested uniform type
4312  *
4313  * @return true if test passed, false otherwise
4314  **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4315 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails &uniform_type) const
4316 {
4317     const glw::GLenum draw_primitive     = getDrawPrimitiveType(shader_stage);
4318     static const glw::GLint first_vertex = 0;
4319     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
4320     const glw::GLsizei n_vertices        = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4321     Utils::programInfo program_info(m_context);
4322     bool result = true;
4323 
4324     /* Prepare program */
4325     prepareProgram(shader_stage, uniform_type, program_info);
4326 
4327     gl.useProgram(program_info.m_program_object_id);
4328     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4329 
4330     /* Prepare uniform buffer and bind it with uniform block */
4331     prepareUniforms(shader_stage, uniform_type, program_info);
4332 
4333     /* Prepare storage for test results */
4334     testBegin(program_info.m_program_object_id, shader_stage);
4335 
4336     /* Execute */
4337     if (COMPUTE_SHADER == shader_stage)
4338     {
4339         m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4340         GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4341     }
4342     else
4343     {
4344         gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4345         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4346     }
4347 
4348     /* Clean after test */
4349     testEnd(shader_stage);
4350 
4351     /* Check results */
4352     if (false == verifyResults(shader_stage))
4353     {
4354         m_context.getTestContext().getLog()
4355             << tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4356             << ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4357 
4358         result = false;
4359     }
4360 
4361     return result;
4362 }
4363 
4364 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4365  *
4366  * @param program_id   Program object id
4367  * @param shader_stage Tested shader stage id
4368  **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4369 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4370 {
4371     std::vector<glw::GLint> buffer_data;
4372     const glw::GLenum captured_primitive = getCapturedPrimitiveType(shader_stage);
4373     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
4374 
4375     /* Prepare buffer filled with m_result_failure */
4376     buffer_data.resize(m_n_captured_results);
4377     for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4378     {
4379         buffer_data[i] = m_result_failure;
4380     }
4381 
4382     /* Prepare buffer for test results */
4383     switch (shader_stage)
4384     {
4385     case GEOMETRY_SHADER:
4386     case TESS_CTRL_SHADER:
4387     case TESS_EVAL_SHADER:
4388     case VERTEX_SHADER:
4389 
4390         /* Verify getTransformFeedbackVarying results */
4391         {
4392             glw::GLsizei size = 0;
4393             glw::GLenum type  = 0;
4394             glw::GLchar name[16];
4395 
4396             gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4397                                            name);
4398             GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4399 
4400             if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4401             {
4402                 m_context.getTestContext().getLog()
4403                     << tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4404                     << " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4405                     << ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4406 
4407                 TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4408             }
4409         }
4410 
4411         /* Create/clean transform feedback buffer */
4412         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4413         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4414 
4415         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4416         GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4417 
4418         /* Set up transform feedback buffer */
4419         gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4420                            m_transform_feedback_buffer_size);
4421         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4422 
4423         gl.beginTransformFeedback(captured_primitive);
4424         GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4425 
4426         break;
4427 
4428     case FRAGMENT_SHADER:
4429 
4430         /* Clean texture */
4431         gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4432         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4433 
4434         gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4435                          GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4436         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4437 
4438         /* Set up texture as color attachment 0 */
4439         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4440         GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4441 
4442         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4443         GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4444 
4445         gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4446         GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4447 
4448         break;
4449 
4450     case COMPUTE_SHADER:
4451 
4452         /* Clean texture */
4453         gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4454         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4455 
4456         gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4457                          GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4458         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4459 
4460         glw::GLint location = gl.getUniformLocation(program_id, "result");
4461         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4462 
4463         if (-1 == location)
4464         {
4465             TCU_FAIL("Inactive uniform \"result\"");
4466         }
4467 
4468         gl.uniform1i(location, 0 /* first image unit */);
4469         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4470 
4471         /* Bind texture to first image unit */
4472         gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4473                             0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4474         GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4475 
4476         break;
4477     }
4478 }
4479 
4480 /** Unbind transform feedback buffer, framebuffer or image unit
4481  *
4482  * @param shader_stage Tested shader stage id
4483  **/
testEnd(shaderStage shader_stage) const4484 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4485 {
4486     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4487 
4488     switch (shader_stage)
4489     {
4490     case GEOMETRY_SHADER:
4491     case TESS_CTRL_SHADER:
4492     case TESS_EVAL_SHADER:
4493     case VERTEX_SHADER:
4494 
4495         gl.endTransformFeedback();
4496 
4497         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4498 
4499         break;
4500 
4501     case FRAGMENT_SHADER:
4502 
4503         gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4504                                 0 /* level */);
4505 
4506         gl.bindTexture(GL_TEXTURE_2D, 0);
4507 
4508         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4509 
4510         break;
4511 
4512     case COMPUTE_SHADER:
4513 
4514         gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4515                             0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4516 
4517         break;
4518     }
4519 }
4520 
4521 /** Initialize OpenGL objects for test
4522  *
4523  **/
testInit()4524 void GPUShaderFP64Test2::testInit()
4525 {
4526     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4527 
4528     /* The test is in 4.0 group. However:
4529      * - compute_shader is core since 4.3
4530      * - compute_shader require at least version 4.2 of GL */
4531     if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4532         (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4533     {
4534         m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4535     }
4536 
4537     /* Tesselation patch set up */
4538     gl.patchParameteri(GL_PATCH_VERTICES, 1);
4539     GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4540 
4541     /* Generate FBO */
4542     gl.genFramebuffers(1, &m_framebuffer_id);
4543     GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4544 
4545     /* Prepare texture */
4546     gl.genTextures(1, &m_texture_id);
4547     GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4548 
4549     gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4550     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4551 
4552     gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4553     GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4554 
4555     /* Prepare transform feedback buffer */
4556     gl.genBuffers(1, &m_transform_feedback_buffer_id);
4557     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4558 
4559     /* Generate uniform buffer */
4560     gl.genBuffers(1, &m_uniform_buffer_id);
4561     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4562 
4563     /* Prepare VAO */
4564     gl.genVertexArrays(1, &m_vertex_array_object_id);
4565     GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4566 
4567     gl.bindVertexArray(m_vertex_array_object_id);
4568     GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4569 }
4570 
4571 /** Result verification, expected result is that whole buffer is filled with m_result_success
4572  *
4573  * @param shader_stage Tested shader stage id
4574  **/
verifyResults(shaderStage shader_stage) const4575 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4576 {
4577     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4578 
4579     if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4580     {
4581         /* Verify contents of texture */
4582 
4583         /* Prepare storage for testure data */
4584         std::vector<glw::GLint> image_data;
4585         image_data.resize(m_texture_width * m_texture_height);
4586 
4587         /* Get texture contents */
4588         gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4589         GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4590 
4591         gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4592         GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4593 
4594         for (glw::GLuint y = 0; y < m_texture_width; ++y)
4595         {
4596             for (glw::GLuint x = 0; x < m_texture_height; ++x)
4597             {
4598                 const glw::GLuint offset = y * m_texture_width + x;
4599                 const glw::GLint value   = image_data[offset];
4600 
4601                 if (m_result_success != value)
4602                 {
4603                     m_context.getTestContext().getLog()
4604                         << tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4605                         << tcu::TestLog::EndMessage;
4606 
4607                     return false;
4608                 }
4609             }
4610         }
4611 
4612         return true;
4613     }
4614     else
4615     {
4616         /* Verify contents of transform feedback buffer */
4617 
4618         bool result = true;
4619 
4620         /* Get transform feedback data */
4621         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4622         GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4623 
4624         glw::GLint *feedback_data = (glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4625         GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4626 
4627         for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4628         {
4629             const glw::GLint value = feedback_data[i];
4630 
4631             if (m_result_success != value)
4632             {
4633                 m_context.getTestContext().getLog()
4634                     << tcu::TestLog::Message << "Error. Transform feedback buffer contents are wrong at " << i
4635                     << tcu::TestLog::EndMessage;
4636 
4637                 result = false;
4638                 break;
4639             }
4640         }
4641 
4642         /* Unmap transform feedback buffer */
4643         gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4644         GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4645 
4646         return result;
4647     }
4648 }
4649 
4650 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4651 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4652 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4653 
4654 const glw::GLchar *GPUShaderFP64Test3::m_uniform_block_name          = "UniformBlock";
4655 const glw::GLchar *GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4656 
4657 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_fs_out_fs_result   = "fs_out_fs_result";
4658 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result    = "gs_fs_gs_result";
4659 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result   = "gs_fs_tcs_result";
4660 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result   = "gs_fs_tes_result";
4661 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result    = "gs_fs_vs_result";
4662 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4663 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result  = "tcs_tes_vs_result";
4664 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result  = "tes_gs_tcs_result";
4665 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result  = "tes_gs_tes_result";
4666 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result   = "tes_gs_vs_result";
4667 const glw::GLchar *GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result   = "vs_tcs_vs_result";
4668 
4669 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4670 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset           = -1;
4671 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride    = -1;
4672 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4673 
4674 /** Constructor
4675  *
4676  * @param context Test context
4677  **/
GPUShaderFP64Test3(deqp::Context & context)4678 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context &context)
4679     : TestCase(context, "named_uniform_blocks",
4680                "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4681 {
4682     /* Nothing to be done */
4683 }
4684 
4685 /** Deinitialize test
4686  *
4687  **/
deinit()4688 void GPUShaderFP64Test3::deinit()
4689 {
4690     /* GL entry points */
4691     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
4692 
4693     /* Clean programs */
4694     m_packed_program.deinit(m_context);
4695     m_shared_program.deinit(m_context);
4696     m_std140_program.deinit(m_context);
4697 
4698     /* Clean frambuffer */
4699     if (0 != m_framebuffer_id)
4700     {
4701         gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4702         gl.deleteFramebuffers(1, &m_framebuffer_id);
4703 
4704         m_framebuffer_id = 0;
4705     }
4706 
4707     /* Clean texture */
4708     if (0 != m_color_texture_id)
4709     {
4710         gl.bindTexture(GL_TEXTURE_2D, 0);
4711         gl.deleteTextures(1, &m_color_texture_id);
4712 
4713         m_color_texture_id = 0;
4714     }
4715 
4716     /* Clean buffers */
4717     if (0 != m_transform_feedback_buffer_id)
4718     {
4719         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4720         gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4721 
4722         m_transform_feedback_buffer_id = 0;
4723     }
4724 
4725     if (0 != m_uniform_buffer_id)
4726     {
4727         gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4728         gl.deleteBuffers(1, &m_uniform_buffer_id);
4729 
4730         m_uniform_buffer_id = 0;
4731     }
4732 
4733     /* Clean VAO */
4734     if (0 != m_vertex_array_object_id)
4735     {
4736         gl.bindVertexArray(0);
4737         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4738 
4739         m_vertex_array_object_id = 0;
4740     }
4741 }
4742 
4743 /** Execute test
4744  *
4745  * @return tcu::TestNode::STOP
4746  **/
iterate()4747 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4748 {
4749     bool result = true;
4750 
4751     /* Check if extension is supported */
4752     if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4753     {
4754         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4755     }
4756 
4757     /* Initialize test */
4758     testInit();
4759 
4760     /* Test "packed" uniform buffer layout */
4761     if (false == test(PACKED))
4762     {
4763         result = false;
4764     }
4765 
4766     /* Test "shared" uniform buffer layout */
4767     if (false == test(SHARED))
4768     {
4769         result = false;
4770     }
4771 
4772     /* Test "std140" uniform buffer layout */
4773     if (false == test(STD140))
4774     {
4775         result = false;
4776     }
4777 
4778     /* Set result */
4779     if (true == result)
4780     {
4781         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4782     }
4783     else
4784     {
4785         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4786     }
4787 
4788     /* Done */
4789     return tcu::TestNode::STOP;
4790 }
4791 
4792 /** Constructor
4793  *
4794  **/
programInfo()4795 GPUShaderFP64Test3::programInfo::programInfo()
4796     : m_fragment_shader_id(0)
4797     , m_geometry_shader_id(0)
4798     , m_program_object_id(0)
4799     , m_tesselation_control_shader_id(0)
4800     , m_tesselation_evaluation_shader_id(0)
4801     , m_vertex_shader_id(0)
4802     , m_buffer_size(0)
4803     , m_uniform_block_index(0)
4804 {
4805     /* Nothing to be done here */
4806 }
4807 
4808 /** Compile shader
4809  *
4810  * @param context     Test context
4811  * @param shader_id   Shader object id
4812  * @param shader_code Shader source code
4813  **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4814 void GPUShaderFP64Test3::programInfo::compile(deqp::Context &context, glw::GLuint shader_id,
4815                                               const glw::GLchar *shader_code) const
4816 {
4817     /* GL entry points */
4818     const glw::Functions &gl = context.getRenderContext().getFunctions();
4819 
4820     /* Compilation status */
4821     glw::GLint status = GL_FALSE;
4822 
4823     /* Set source code */
4824     gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4825     GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4826 
4827     /* Compile */
4828     gl.compileShader(shader_id);
4829     GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4830 
4831     /* Get compilation status */
4832     gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4833     GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4834 
4835     /* Log compilation error */
4836     if (GL_TRUE != status)
4837     {
4838         glw::GLint length = 0;
4839         std::vector<glw::GLchar> message;
4840 
4841         /* Error log length */
4842         gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4843         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4844 
4845         /* Prepare storage */
4846         message.resize(length);
4847 
4848         /* Get error log */
4849         gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4850         GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4851 
4852         /* Log */
4853         context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4854                                           << &message[0] << "\nShader source\n"
4855                                           << shader_code << tcu::TestLog::EndMessage;
4856 
4857         TCU_FAIL("Failed to compile shader");
4858     }
4859 }
4860 
4861 /** Cleans program and attached shaders
4862  *
4863  * @param context Test context
4864  **/
deinit(deqp::Context & context)4865 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context &context)
4866 {
4867     /* GL entry points */
4868     const glw::Functions &gl = context.getRenderContext().getFunctions();
4869 
4870     /* Restore default program */
4871     gl.useProgram(0);
4872 
4873     /* Clean program object */
4874     if (0 != m_program_object_id)
4875     {
4876         gl.deleteProgram(m_program_object_id);
4877         m_program_object_id = 0;
4878     }
4879 
4880     /* Clean shaders */
4881     if (0 != m_fragment_shader_id)
4882     {
4883         gl.deleteShader(m_fragment_shader_id);
4884         m_fragment_shader_id = 0;
4885     }
4886 
4887     if (0 != m_geometry_shader_id)
4888     {
4889         gl.deleteShader(m_geometry_shader_id);
4890         m_geometry_shader_id = 0;
4891     }
4892 
4893     if (0 != m_tesselation_control_shader_id)
4894     {
4895         gl.deleteShader(m_tesselation_control_shader_id);
4896         m_tesselation_control_shader_id = 0;
4897     }
4898 
4899     if (0 != m_tesselation_evaluation_shader_id)
4900     {
4901         gl.deleteShader(m_tesselation_evaluation_shader_id);
4902         m_tesselation_evaluation_shader_id = 0;
4903     }
4904 
4905     if (0 != m_vertex_shader_id)
4906     {
4907         gl.deleteShader(m_vertex_shader_id);
4908         m_vertex_shader_id = 0;
4909     }
4910 }
4911 
4912 /** Build program and query for uniform layout
4913  *
4914  * @param context                            Test context
4915  * @param uniform_details                  Collection of uniform details
4916  * @param fragment_shader_code               Fragment shader source code
4917  * @param geometry_shader_code               Geometry shader source code
4918  * @param tesselation_control_shader_code    Tesselation control shader source code
4919  * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4920  * @param vertex_shader_code                 Vertex shader source code
4921  **/
init(deqp::Context & context,const std::vector<uniformDetails> uniform_details,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code)4922 void GPUShaderFP64Test3::programInfo::init(deqp::Context &context, const std::vector<uniformDetails> uniform_details,
4923                                            const glw::GLchar *fragment_shader_code,
4924                                            const glw::GLchar *geometry_shader_code,
4925                                            const glw::GLchar *tesselation_control_shader_code,
4926                                            const glw::GLchar *tesselation_evaluation_shader_code,
4927                                            const glw::GLchar *vertex_shader_code)
4928 {
4929     /* GL entry points */
4930     const glw::Functions &gl = context.getRenderContext().getFunctions();
4931 
4932     /* Names of varyings to be captured with transform feedback */
4933     static const glw::GLchar *varying_names[] = {m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4934                                                  m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result};
4935     static const glw::GLuint n_varying_names  = sizeof(varying_names) / sizeof(varying_names[0]);
4936 
4937     /* Create shader objects */
4938     m_fragment_shader_id               = gl.createShader(GL_FRAGMENT_SHADER);
4939     m_geometry_shader_id               = gl.createShader(GL_GEOMETRY_SHADER);
4940     m_tesselation_control_shader_id    = gl.createShader(GL_TESS_CONTROL_SHADER);
4941     m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4942     m_vertex_shader_id                 = gl.createShader(GL_VERTEX_SHADER);
4943     GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4944 
4945     /* Create program object */
4946     m_program_object_id = gl.createProgram();
4947     GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4948 
4949     /* Set up names of varyings to be captured with transform feedback */
4950     gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4951     GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4952 
4953     /* Compile shaders */
4954     compile(context, m_fragment_shader_id, fragment_shader_code);
4955     compile(context, m_geometry_shader_id, geometry_shader_code);
4956     compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4957     compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4958     compile(context, m_vertex_shader_id, vertex_shader_code);
4959 
4960     /* Link program */
4961     link(context);
4962 
4963     /* Inspect program object */
4964     /* Get index of named uniform block */
4965     m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4966     GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4967 
4968     if (GL_INVALID_INDEX == m_uniform_block_index)
4969     {
4970         TCU_FAIL("Unifom block is inactive");
4971     }
4972 
4973     /* Get size of named uniform block */
4974     gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4975     GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4976 
4977     if (0 == m_buffer_size)
4978     {
4979         TCU_FAIL("Unifom block size is 0");
4980     }
4981 
4982     /* Get information about "double precision" uniforms */
4983     for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4984          end != it; ++it)
4985     {
4986         const glw::GLchar *uniform_name = 0;
4987         std::string uniform_name_str;
4988         std::stringstream uniform_name_stream;
4989         glw::GLuint index        = 0;
4990         glw::GLint offset        = 0;
4991         glw::GLint matrix_stride = 0;
4992 
4993         /* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4994         uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4995 
4996         uniform_name_str = uniform_name_stream.str();
4997         uniform_name     = uniform_name_str.c_str();
4998 
4999         /* Get index of uniform */
5000         gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
5001         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
5002 
5003         if (GL_INVALID_INDEX == index)
5004         {
5005             TCU_FAIL("Unifom is inactive");
5006         }
5007 
5008         /* Get offset of uniform */
5009         gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
5010         GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
5011 
5012         if (m_invalid_uniform_offset == offset)
5013         {
5014             TCU_FAIL("Unifom has invalid offset");
5015         }
5016 
5017         m_uniform_offsets.push_back(offset);
5018 
5019         /* Get matrix stride of uniform */
5020         gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
5021         GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
5022 
5023         if (m_invalid_uniform_matrix_stride == offset)
5024         {
5025             TCU_FAIL("Unifom has invalid matrix stride");
5026         }
5027 
5028         m_uniform_matrix_strides.push_back(matrix_stride);
5029     }
5030 }
5031 
5032 /** Attach shaders and link program
5033  *
5034  * @param context Test context
5035  **/
link(deqp::Context & context) const5036 void GPUShaderFP64Test3::programInfo::link(deqp::Context &context) const
5037 {
5038     /* GL entry points */
5039     const glw::Functions &gl = context.getRenderContext().getFunctions();
5040 
5041     /* Link status */
5042     glw::GLint status = GL_FALSE;
5043 
5044     /* Attach shaders */
5045     gl.attachShader(m_program_object_id, m_fragment_shader_id);
5046     gl.attachShader(m_program_object_id, m_geometry_shader_id);
5047     gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
5048     gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
5049     gl.attachShader(m_program_object_id, m_vertex_shader_id);
5050     GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
5051 
5052     /* Link */
5053     gl.linkProgram(m_program_object_id);
5054     GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5055 
5056     /* Get link status */
5057     gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5058     GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5059 
5060     /* Log link error */
5061     if (GL_TRUE != status)
5062     {
5063         glw::GLint length = 0;
5064         std::vector<glw::GLchar> message;
5065 
5066         /* Get error log length */
5067         gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5068         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5069 
5070         message.resize(length);
5071 
5072         /* Get error log */
5073         gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5074         GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5075 
5076         /* Log */
5077         context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5078                                           << &message[0] << tcu::TestLog::EndMessage;
5079 
5080         TCU_FAIL("Failed to link program");
5081     }
5082 }
5083 
5084 /** Returns "predefined" values that will be used to fill uniform data
5085  *
5086  * @param type_ordinal Ordinal number of "double precision" uniform type
5087  * @param element      Index of element in uniform
5088  *
5089  * @return "Predefined" value
5090  **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5091 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5092 {
5093     return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5094            ((m_base_element - (glw::GLdouble)element) / 4.0);
5095 }
5096 
5097 /** Returns a reference of programInfo instance specific for given buffer layout
5098  *
5099  * @param uniform_data_layout Buffer layout
5100  *
5101  * @return Reference to an instance of programInfo
5102  **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5103 const GPUShaderFP64Test3::programInfo &GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5104 {
5105     const programInfo *program_info = 0;
5106 
5107     switch (uniform_data_layout)
5108     {
5109     case PACKED:
5110 
5111         program_info = &m_packed_program;
5112 
5113         break;
5114 
5115     case SHARED:
5116 
5117         program_info = &m_shared_program;
5118 
5119         break;
5120 
5121     case STD140:
5122 
5123         program_info = &m_std140_program;
5124 
5125         break;
5126     }
5127 
5128     return *program_info;
5129 }
5130 
5131 /** Get "name" of buffer layout
5132  *
5133  * @param uniform_data_layout Buffer layout
5134  *
5135  * @return "Name" of layout
5136  **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5137 const glw::GLchar *GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5138 {
5139     const glw::GLchar *layout = "";
5140 
5141     switch (uniform_data_layout)
5142     {
5143     case PACKED:
5144         layout = "packed";
5145         break;
5146     case SHARED:
5147         layout = "shared";
5148         break;
5149     case STD140:
5150         layout = "std140";
5151         break;
5152     }
5153 
5154     return layout;
5155 }
5156 
5157 /** Prepare programInfo instance for specific buffer layout
5158  *
5159  * @param program_info        Instance of programInfo
5160  * @param uniform_data_layout Buffer layout
5161  **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5162 void GPUShaderFP64Test3::prepareProgram(programInfo &program_info, uniformDataLayout uniform_data_layout) const
5163 {
5164     /* Storage for shader source code */
5165     std::stringstream fragment_shader_code;
5166     std::stringstream geometry_shader_code;
5167     std::stringstream tess_control_shader_code;
5168     std::stringstream tess_eval_shader_code;
5169     std::stringstream vertex_shader_code;
5170 
5171     /* Write preambles */
5172     writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5173     writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5174     writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5175     writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5176     writePreamble(vertex_shader_code, VERTEX_SHADER);
5177 
5178     /* Write definition of named uniform block */
5179     writeUniformBlock(fragment_shader_code, uniform_data_layout);
5180     writeUniformBlock(geometry_shader_code, uniform_data_layout);
5181     writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5182     writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5183     writeUniformBlock(vertex_shader_code, uniform_data_layout);
5184 
5185     /* Write definitions of varyings */
5186     writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5187     writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5188     writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5189     writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5190     writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5191 
5192     /* Write main routine */
5193     writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5194     writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5195     writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5196     writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5197     writeMainBody(vertex_shader_code, VERTEX_SHADER);
5198 
5199     /* Init programInfo instance */
5200     program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5201                       geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5202                       tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5203 }
5204 
5205 /** Prepare uniform buffer
5206  *
5207  * @param program_info   Instance of programInfo
5208  * @param verify_offsets If uniform offsets should be verified against expected values
5209  *
5210  * @return false if uniform offsets verification result is failure, true otherwise
5211  **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5212 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo &program_info, bool verify_offsets) const
5213 {
5214     const glw::GLuint buffer_size                                     = program_info.m_buffer_size;
5215     const glw::Functions &gl                                          = m_context.getRenderContext().getFunctions();
5216     bool offset_verification_result                                   = true;
5217     glw::GLuint type_ordinal                                          = 1;
5218     std::vector<uniformDetails>::const_iterator it_uniform_details    = m_uniform_details.begin();
5219     std::vector<glw::GLint>::const_iterator it_uniform_offsets        = program_info.m_uniform_offsets.begin();
5220     std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5221 
5222     /* Prepare storage for uniform buffer data */
5223     std::vector<glw::GLubyte> buffer_data;
5224     buffer_data.resize(buffer_size);
5225 
5226     /* For each "double precision" uniform */
5227     for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5228          ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5229     {
5230         const glw::GLint matrix_stride  = *it_uniform_matrix_strides;
5231         const glw::GLuint n_columns     = it_uniform_details->m_n_columns;
5232         const glw::GLuint n_elements    = it_uniform_details->m_n_elements;
5233         const glw::GLuint column_length = n_elements / n_columns;
5234         const glw::GLint uniform_offset = *it_uniform_offsets;
5235 
5236         /* For each element of uniform */
5237         for (glw::GLuint element = 0; element < n_elements; ++element)
5238         {
5239             const glw::GLuint column      = element / column_length;
5240             const glw::GLuint column_elem = element % column_length;
5241             const glw::GLdouble value     = getExpectedValue(type_ordinal, element);
5242             const glw::GLuint value_offset =
5243                 static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5244 
5245             glw::GLdouble *value_dst = (glw::GLdouble *)&buffer_data[value_offset];
5246 
5247             /* Store value */
5248             *value_dst = value;
5249         }
5250 
5251         /* Uniform offset verification */
5252         if (true == verify_offsets)
5253         {
5254             const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5255 
5256             if (expected_offset != uniform_offset)
5257             {
5258                 if (true == offset_verification_result)
5259                 {
5260                     m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5261                 }
5262 
5263                 m_context.getTestContext().getLog()
5264                     << tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5265                     << " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5266                     << tcu::TestLog::EndMessage;
5267 
5268                 offset_verification_result = false;
5269             }
5270         }
5271     }
5272 
5273     /* Update uniform buffer with prepared data */
5274     gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5275     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5276 
5277     gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5278     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5279 
5280     /* Bind uniform buffer as data source for named uniform block */
5281     gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5282     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5283 
5284     gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5285     GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5286 
5287     /* Done */
5288     return offset_verification_result;
5289 }
5290 
5291 /** Prepare data, execute draw call and verify results
5292  *
5293  * @param uniform_data_layout
5294  *
5295  * @return true if test pass, false otherwise
5296  **/
test(uniformDataLayout uniform_data_layout) const5297 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5298 {
5299     bool are_offsets_verified       = (STD140 == uniform_data_layout);
5300     const glw::Functions &gl        = m_context.getRenderContext().getFunctions();
5301     bool offset_verification_result = true;
5302     const programInfo &program_info = getProgramInfo(uniform_data_layout);
5303     bool result                     = true;
5304 
5305     /* Set up program */
5306     gl.useProgram(program_info.m_program_object_id);
5307     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5308 
5309     /* Prepare uniform buffer */
5310     offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5311 
5312     if (true == are_offsets_verified && false == offset_verification_result)
5313     {
5314         /* Offsets verification failure was already reported, add info about buffer layout */
5315         m_context.getTestContext().getLog()
5316             << tcu::TestLog::Message << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5317             << tcu::TestLog::EndMessage;
5318 
5319         result = false;
5320     }
5321 
5322     /* Set up transform feedback buffer */
5323     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5324     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5325 
5326     /* Begin transform feedback */
5327     gl.beginTransformFeedback(GL_POINTS);
5328     GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5329 
5330     /* Execute draw call for singe vertex */
5331     gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5332     GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5333 
5334     /* Stop transform feedback */
5335     gl.endTransformFeedback();
5336     GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5337 
5338     /* Verify results */
5339     if (false == verifyResults())
5340     {
5341         /* Result verificatioon failure was already reported, add info about layout */
5342         m_context.getTestContext().getLog()
5343             << tcu::TestLog::Message << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5344             << tcu::TestLog::EndMessage;
5345 
5346         result = false;
5347     }
5348 
5349     /* Done */
5350     return result;
5351 }
5352 
testInit()5353 void GPUShaderFP64Test3::testInit()
5354 {
5355     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5356 
5357     /* Uniform block declaration with std140 offsets calculated
5358      *                       | align | loc_req | begins | ends | offset in bytes | imp |
5359      * ivec3   unused1[3]    |     4 |      12 |      0 |   12 |               0 |     |
5360      * double  double_value  |     2 |       2 |     12 |   14 |              48 | XXX |
5361      * bool    unused2       |     1 |       1 |     14 |   15 |              56 |     |
5362      * dvec2   dvec2_value   |     4 |       4 |     16 |   20 |              64 | XXX |
5363      * bvec3   unused3       |     4 |       4 |     20 |   24 |              80 |     |
5364      * dvec3   dvec3_value   |     8 |       8 |     24 |   32 |              96 | XXX |
5365      * int     unused4[3]    |     4 |      12 |     32 |   44 |             128 |     |
5366      * dvec4   dvec4_value   |     8 |       8 |     48 |   56 |             192 | XXX |
5367      * bool    unused5       |     1 |       1 |     56 |   57 |             224 |     |
5368      * bool    unused6[2]    |     4 |       8 |     60 |   68 |             240 |     |
5369      * dmat2   dmat2_value   |     4 |       8 |     68 |   76 |             272 | XXX |
5370      * dmat3   dmat3_value   |     8 |      24 |     80 |  104 |             320 | XXX |
5371      * bool    unused7       |     1 |       1 |    104 |  105 |             416 |     |
5372      * dmat4   dmat4_value   |     8 |      32 |    112 |  144 |             448 | XXX |
5373      * dmat2x3 dmat2x3_value |     8 |      16 |    144 |  160 |             576 | XXX |
5374      * uvec3   unused8       |     4 |       4 |    160 |  164 |             640 |     |
5375      * dmat2x4 dmat2x4_value |     8 |      16 |    168 |  184 |             672 | XXX |
5376      * dmat3x2 dmat3x2_value |     4 |      12 |    184 |  196 |             736 | XXX |
5377      * bool    unused9       |     1 |       1 |    196 |  197 |             784 |     |
5378      * dmat3x4 dmat3x4_value |     8 |      24 |    200 |  224 |             800 | XXX |
5379      * int     unused10      |     1 |       1 |    224 |  225 |             896 |     |
5380      * dmat4x2 dmat4x2_value |     4 |      16 |    228 |  244 |             912 | XXX |
5381      * dmat4x3 dmat4x3_value |     8 |      32 |    248 |  280 |             992 | XXX |
5382      */
5383 
5384     /* Prepare "double precision" unfiorms' details */
5385     m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5386                                                1 /* n_elements */, "double" /* type_name */));
5387     m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5388                                                2 /* n_elements */, "dvec2" /* type_name */));
5389     m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5390                                                3 /* n_elements */, "dvec3" /* type_name */));
5391     m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5392                                                4 /* n_elements */, "dvec4" /* type_name */));
5393     m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5394                                                4 /* n_elements */, "dmat2" /* type_name */));
5395     m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5396                                                9 /* n_elements */, "dmat3" /* type_name */));
5397     m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5398                                                16 /* n_elements */, "dmat4" /* type_name */));
5399     m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5400                                                6 /* n_elements */, "dmat2x3" /* type_name */));
5401     m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5402                                                8 /* n_elements */, "dmat2x4" /* type_name */));
5403     m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5404                                                6 /* n_elements */, "dmat3x2" /* type_name */));
5405     m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5406                                                12 /* n_elements */, "dmat3x4" /* type_name */));
5407     m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5408                                                8 /* n_elements */, "dmat4x2" /* type_name */));
5409     m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5410                                                12 /* n_elements */, "dmat4x3" /* type_name */));
5411 
5412     /* Get random values for getExpectedValue */
5413     m_base_element      = (glw::GLdouble)(rand() % 13);
5414     m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5415 
5416     /* Prepare programInfos for all buffer layouts */
5417     prepareProgram(m_packed_program, PACKED);
5418     prepareProgram(m_shared_program, SHARED);
5419     prepareProgram(m_std140_program, STD140);
5420 
5421     /* Generate buffers */
5422     gl.genBuffers(1, &m_transform_feedback_buffer_id);
5423     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5424 
5425     gl.genBuffers(1, &m_uniform_buffer_id);
5426     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5427 
5428     /* Prepare transform feedback buffer */
5429     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5430     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5431 
5432     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5433     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5434 
5435     /* Prepare texture for color attachment 0 */
5436     gl.genTextures(1, &m_color_texture_id);
5437     GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5438 
5439     gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5440     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5441 
5442     gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5443     GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5444 
5445     /* Prepare FBO with color attachment 0 */
5446     gl.genFramebuffers(1, &m_framebuffer_id);
5447     GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5448 
5449     gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5450     GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5451 
5452     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5453                             0 /* level */);
5454     GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5455 
5456     gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5457     GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5458 
5459     /* Prepare VAO */
5460     gl.genVertexArrays(1, &m_vertex_array_object_id);
5461     GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5462 
5463     gl.bindVertexArray(m_vertex_array_object_id);
5464     GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5465 
5466     /* Tesselation patch set up */
5467     gl.patchParameteri(GL_PATCH_VERTICES, 1);
5468     GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5469 }
5470 
5471 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5472  *
5473  * @return true if all values are as expected, false otherwise
5474  **/
verifyResults() const5475 bool GPUShaderFP64Test3::verifyResults() const
5476 {
5477     glw::GLint *feedback_data    = 0;
5478     bool fragment_shader_result  = false;
5479     bool geometry_shader_result  = false;
5480     const glw::Functions &gl     = m_context.getRenderContext().getFunctions();
5481     bool tess_ctrl_shader_result = false;
5482     bool tess_eval_shader_result = false;
5483     bool vertex_shader_result    = false;
5484 
5485     /* Prepare storage for testure data */
5486     std::vector<glw::GLint> image_data;
5487     image_data.resize(1);
5488 
5489     /* Get texture contents */
5490     gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5491     GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5492 
5493     gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5494     GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5495 
5496     /* Get transform feedback data */
5497     feedback_data = (glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5498     GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5499 
5500     /* Verify results */
5501     fragment_shader_result  = (m_result_success == image_data[0]);
5502     geometry_shader_result  = (m_result_success == feedback_data[0]);
5503     tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5504     tess_eval_shader_result = (m_result_success == feedback_data[2]);
5505     vertex_shader_result    = (m_result_success == feedback_data[3]);
5506 
5507     /* Unmap transform feedback buffer */
5508     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5509     GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5510 
5511     /* Set result */
5512     if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5513                  tess_eval_shader_result && vertex_shader_result))
5514     {
5515         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5516 
5517         m_context.getTestContext().getLog()
5518             << tcu::TestLog::Message << "Vertex shader stage result: " << vertex_shader_result
5519             << tcu::TestLog::EndMessage;
5520 
5521         m_context.getTestContext().getLog()
5522             << tcu::TestLog::Message << "Tesselation control shader stage result: " << tess_ctrl_shader_result
5523             << tcu::TestLog::EndMessage;
5524 
5525         m_context.getTestContext().getLog()
5526             << tcu::TestLog::Message << "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5527             << tcu::TestLog::EndMessage;
5528 
5529         m_context.getTestContext().getLog()
5530             << tcu::TestLog::Message << "Geometry shader stage result: " << geometry_shader_result
5531             << tcu::TestLog::EndMessage;
5532 
5533         m_context.getTestContext().getLog()
5534             << tcu::TestLog::Message << "Fragment shader stage result: " << fragment_shader_result
5535             << tcu::TestLog::EndMessage;
5536 
5537         return false;
5538     }
5539     else
5540     {
5541         return true;
5542     }
5543 }
5544 
5545 /** Write main routine of <shader_stage> shader to stream
5546  *
5547  * @param stream       Output stream with source code of shader
5548  * @param shader_stage Shader stage
5549  **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5550 void GPUShaderFP64Test3::writeMainBody(std::ostream &stream, shaderStage shader_stage) const
5551 {
5552     glw::GLuint type_ordinal        = 1;
5553     const glw::GLchar *varying_name = "";
5554 
5555     /* Select name for varying that will hold result of "that" shader_stage */
5556     switch (shader_stage)
5557     {
5558     case FRAGMENT_SHADER:
5559         varying_name = m_varying_name_fs_out_fs_result;
5560         break;
5561     case GEOMETRY_SHADER:
5562         varying_name = m_varying_name_gs_fs_gs_result;
5563         break;
5564     case TESS_CONTROL_SHADER:
5565         varying_name = m_varying_name_tcs_tes_tcs_result;
5566         break;
5567     case TESS_EVAL_SHADER:
5568         varying_name = m_varying_name_tes_gs_tes_result;
5569         break;
5570     case VERTEX_SHADER:
5571         varying_name = m_varying_name_vs_tcs_vs_result;
5572         break;
5573     }
5574 
5575     /* void main() */
5576     stream << "void main()\n"
5577               "{\n";
5578 
5579     /* Tesselation levels output */
5580     if (TESS_CONTROL_SHADER == shader_stage)
5581     {
5582         stream << "gl_TessLevelOuter[0] = 1.0;\n"
5583                   "gl_TessLevelOuter[1] = 1.0;\n"
5584                   "gl_TessLevelOuter[2] = 1.0;\n"
5585                   "gl_TessLevelOuter[3] = 1.0;\n"
5586                   "gl_TessLevelInner[0] = 1.0;\n"
5587                   "gl_TessLevelInner[1] = 1.0;\n"
5588                   "\n";
5589     }
5590 
5591     /* For each "double precision" uniform
5592      *
5593      * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5594      * {
5595      *     VARYING_NAME = m_result_failure;
5596      * }
5597      */
5598     for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5599          end != it; ++it, ++type_ordinal)
5600     {
5601         stream << "    ";
5602 
5603         /* First comparison is done with if, next with else if */
5604         if (1 != type_ordinal)
5605         {
5606             stream << "else ";
5607         }
5608 
5609         /* if (TYPE_NAME( */
5610         stream << "if (" << it->m_type_name << "(";
5611 
5612         /* PREDIFINED_VALUES */
5613         for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5614         {
5615             stream << getExpectedValue(type_ordinal, element);
5616 
5617             /* Separate with comma */
5618             if (it->m_n_elements != element + 1)
5619             {
5620                 stream << ", ";
5621             }
5622         }
5623 
5624         /*
5625          * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5626          * {
5627          *     VARYING_NAME
5628          */
5629         stream << ") != " << m_uniform_block_instance_name << "." << it->m_name
5630                << ")\n"
5631                   "    {\n"
5632                   "        "
5633                << varying_name;
5634 
5635         /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5636         if (TESS_CONTROL_SHADER == shader_stage)
5637         {
5638             stream << "[gl_InvocationID]";
5639         }
5640 
5641         /*
5642          * = m_result_failure;
5643          * }
5644          */
5645         stream << " = " << m_result_failure << ";\n"
5646                << "    }\n";
5647     }
5648 
5649     /* If all comparisons are ok
5650      *
5651      *     else
5652      *     {
5653      *         VARYING_NAME = m_result_success;
5654      *     }
5655      */
5656 
5657     /*
5658      * else
5659      * {
5660      *     VARYING_NAME
5661      */
5662     stream << "    else\n"
5663               "    {\n"
5664               "        "
5665            << varying_name;
5666 
5667     /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5668     if (TESS_CONTROL_SHADER == shader_stage)
5669     {
5670         stream << "[gl_InvocationID]";
5671     }
5672 
5673     /*
5674      * = m_result_success;
5675      * }
5676      *
5677      */
5678     stream << " = " << m_result_success << ";\n"
5679            << "    }\n"
5680            << "\n";
5681 
5682     /* For each pair of "input/output" varyings
5683      *
5684      * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5685      **/
5686     writeVaryingPassthrough(stream, shader_stage);
5687 
5688     /* Geometry shader have to emit vertex */
5689     if (GEOMETRY_SHADER == shader_stage)
5690     {
5691         stream << "\n"
5692                   "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5693                   "EmitVertex();\n"
5694                   "EndPrimitive();\n";
5695     }
5696 
5697     /* Close scope of main */
5698     stream << "}\n\n";
5699 }
5700 
5701 /** Write shader preamble to stream
5702  *
5703  * @param stream       Output stream with source code of shader
5704  * @param shader_stage Shader stage
5705  **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5706 void GPUShaderFP64Test3::writePreamble(std::ostream &stream, shaderStage shader_stage) const
5707 {
5708     stream << "#version 400 core\n"
5709               "\n"
5710               "precision highp float;\n"
5711               "\n";
5712 
5713     switch (shader_stage)
5714     {
5715     case FRAGMENT_SHADER:
5716         break;
5717     case GEOMETRY_SHADER:
5718         stream << "layout(points)                   in;\n"
5719                   "layout(points, max_vertices = 1) out;\n"
5720                   "\n";
5721         break;
5722     case TESS_CONTROL_SHADER:
5723         stream << "layout(vertices = 1) out;\n"
5724                   "\n";
5725         break;
5726     case TESS_EVAL_SHADER:
5727         stream << "layout(isolines, point_mode) in;\n"
5728                   "\n";
5729         break;
5730     case VERTEX_SHADER:
5731         break;
5732     }
5733 }
5734 
5735 /** Write name uniform blcok definition with specific layout to stream
5736  *
5737  * @param stream              Output stream with source code of shader
5738  * @param uniform_data_layout Buffer layout
5739  **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5740 void GPUShaderFP64Test3::writeUniformBlock(std::ostream &stream, uniformDataLayout uniform_data_layout) const
5741 {
5742     const glw::GLchar *layout = getUniformLayoutName(uniform_data_layout);
5743 
5744     stream << "layout(" << layout << ") uniform " << m_uniform_block_name
5745            << "\n"
5746               "{\n"
5747               "    ivec3   unused1[3];\n"
5748               "    double  double_value;\n"
5749               "    bool    unused2;\n"
5750               "    dvec2   dvec2_value;\n"
5751               "    bvec3   unused3;\n"
5752               "    dvec3   dvec3_value;\n"
5753               "    int     unused4[3];\n"
5754               "    dvec4   dvec4_value;\n"
5755               "    bool    unused5;\n"
5756               "    bool    unused6[2];\n"
5757               "    dmat2   dmat2_value;\n"
5758               "    dmat3   dmat3_value;\n"
5759               "    bool    unused7;\n"
5760               "    dmat4   dmat4_value;\n"
5761               "    dmat2x3 dmat2x3_value;\n"
5762               "    uvec3   unused8;\n"
5763               "    dmat2x4 dmat2x4_value;\n"
5764               "    dmat3x2 dmat3x2_value;\n"
5765               "    bool    unused9;\n"
5766               "    dmat3x4 dmat3x4_value;\n"
5767               "    int     unused10;\n"
5768               "    dmat4x2 dmat4x2_value;\n"
5769               "    dmat4x3 dmat4x3_value;\n"
5770               "} "
5771            << m_uniform_block_instance_name << ";\n";
5772 
5773     stream << "\n";
5774 }
5775 
5776 /** Write definitions of varyings specific for given <shader_stage> to stream
5777  *
5778  * @param stream       Output stream with source code of shader
5779  * @param shader_stage Shader stage
5780  **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5781 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream &stream, shaderStage shader_stage) const
5782 {
5783     static const glw::GLchar *const varying_type = "int";
5784 
5785     switch (shader_stage)
5786     {
5787     case FRAGMENT_SHADER:
5788 
5789         /* In */
5790         stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5791         stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5792         stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5793         stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5794 
5795         stream << "\n";
5796 
5797         /* Out */
5798         stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5799 
5800         break;
5801 
5802     case GEOMETRY_SHADER:
5803 
5804         /* In */
5805         stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5806         stream << "in  " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5807         stream << "in  " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5808 
5809         stream << "\n";
5810 
5811         /* Out */
5812         stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5813         stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5814         stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5815         stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5816 
5817         break;
5818 
5819     case TESS_CONTROL_SHADER:
5820 
5821         /* In */
5822         stream << "in  " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5823 
5824         stream << "\n";
5825 
5826         /* Out */
5827         stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5828         stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5829 
5830         break;
5831 
5832     case TESS_EVAL_SHADER:
5833 
5834         /* In */
5835         stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5836         stream << "in  " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5837 
5838         stream << "\n";
5839 
5840         /* Out */
5841         stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5842         stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5843         stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5844 
5845         break;
5846 
5847     case VERTEX_SHADER:
5848 
5849         /* Out */
5850         stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5851 
5852         break;
5853     }
5854 
5855     stream << "\n";
5856 }
5857 
5858 /** Write passthrough code of "input/output" varying pairs to stream
5859  *
5860  * @param stream       Output stream with source code of shader
5861  * @param shader_stage Shader stage
5862  **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5863 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream &stream, shaderStage shader_stage) const
5864 {
5865     switch (shader_stage)
5866     {
5867     case FRAGMENT_SHADER:
5868         break;
5869 
5870     case GEOMETRY_SHADER:
5871 
5872         stream << "    " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5873         stream << "    " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5874         stream << "    " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5875 
5876         break;
5877 
5878     case TESS_CONTROL_SHADER:
5879 
5880         stream << "    " << m_varying_name_tcs_tes_vs_result
5881                << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5882 
5883         break;
5884 
5885     case TESS_EVAL_SHADER:
5886 
5887         stream << "    " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5888         stream << "    " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5889 
5890         break;
5891 
5892     case VERTEX_SHADER:
5893 
5894         break;
5895     }
5896 }
5897 
5898 /** Constructor. Sets all uniform locations to -1 and sets all
5899  *  values to 0.
5900  */
_data()5901 GPUShaderFP64Test4::_data::_data()
5902 {
5903     memset(&uniform_double, 0, sizeof(uniform_double));
5904     memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5905     memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5906     memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5907     memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5908     memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5909     memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5910 
5911     uniform_location_double        = -1;
5912     uniform_location_double_arr[0] = -1;
5913     uniform_location_double_arr[1] = -1;
5914     uniform_location_dvec2         = -1;
5915     uniform_location_dvec2_arr[0]  = -1;
5916     uniform_location_dvec2_arr[1]  = -1;
5917     uniform_location_dvec3         = -1;
5918     uniform_location_dvec3_arr[0]  = -1;
5919     uniform_location_dvec3_arr[1]  = -1;
5920     uniform_location_dvec4         = -1;
5921     uniform_location_dvec4_arr[0]  = -1;
5922     uniform_location_dvec4_arr[1]  = -1;
5923 }
5924 
5925 /** Constructor
5926  *
5927  *  @param context Rendering context.
5928  */
GPUShaderFP64Test4(deqp::Context & context)5929 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context &context)
5930     : TestCase(context, "state_query",
5931                "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5932                " report correct properties of & values assigned to double-precision uniforms.")
5933     , m_has_test_passed(true)
5934     , m_uniform_name_buffer(0)
5935     , m_cs_id(0)
5936     , m_fs_id(0)
5937     , m_gs_id(0)
5938     , m_po_cs_id(0)
5939     , m_po_noncs_id(0)
5940     , m_tc_id(0)
5941     , m_te_id(0)
5942     , m_vs_id(0)
5943 {
5944     /* Left blank intentionally */
5945 }
5946 
5947 /** Deinitializes all GL objects, as well as releases all bufers, that may
5948  *  have beenallocated or  created during test execution.
5949  **/
deinit()5950 void GPUShaderFP64Test4::deinit()
5951 {
5952     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
5953 
5954     if (m_cs_id != 0)
5955     {
5956         gl.deleteShader(m_cs_id);
5957 
5958         m_cs_id = 0;
5959     }
5960 
5961     if (m_fs_id != 0)
5962     {
5963         gl.deleteShader(m_fs_id);
5964 
5965         m_fs_id = 0;
5966     }
5967 
5968     if (m_gs_id != 0)
5969     {
5970         gl.deleteShader(m_gs_id);
5971 
5972         m_gs_id = 0;
5973     }
5974 
5975     if (m_po_cs_id != 0)
5976     {
5977         gl.deleteProgram(m_po_cs_id);
5978 
5979         m_po_cs_id = 0;
5980     }
5981 
5982     if (m_po_noncs_id != 0)
5983     {
5984         gl.deleteProgram(m_po_noncs_id);
5985 
5986         m_po_noncs_id = 0;
5987     }
5988 
5989     if (m_tc_id != 0)
5990     {
5991         gl.deleteShader(m_tc_id);
5992 
5993         m_tc_id = 0;
5994     }
5995 
5996     if (m_te_id != 0)
5997     {
5998         gl.deleteShader(m_te_id);
5999 
6000         m_te_id = 0;
6001     }
6002 
6003     if (m_uniform_name_buffer != DE_NULL)
6004     {
6005         delete[] m_uniform_name_buffer;
6006 
6007         m_uniform_name_buffer = DE_NULL;
6008     }
6009 
6010     if (m_vs_id != 0)
6011     {
6012         gl.deleteShader(m_vs_id);
6013 
6014         m_vs_id = 0;
6015     }
6016 }
6017 
6018 /** Generates double-precision values for all uniforms defined for all program objects
6019  *  used by the test.
6020  *
6021  *  This function DOES NOT use any GL API. It only calculates & stores the values
6022  *  in internal storage for further usage.
6023  */
generateUniformValues()6024 void GPUShaderFP64Test4::generateUniformValues()
6025 {
6026     _stage_data *stages[]       = {&m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs};
6027     const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
6028 
6029     for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6030     {
6031         _stage_data *stage_ptr = stages[n_stage];
6032 
6033         /* Iterate through all uniform components and assign them double values */
6034         double *double_ptrs[] = {
6035             &stage_ptr->uniform_structure_arrays[0].uniform_double,
6036             stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
6037             stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
6038             stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
6039             stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
6040             stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
6041             stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
6042             stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
6043             stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
6044             stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
6045             stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
6046             stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
6047             &stage_ptr->uniform_structure_arrays[1].uniform_double,
6048             stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
6049             stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
6050             stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
6051             stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
6052             stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
6053             stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
6054             stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6055             stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6056             stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6057             stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6058             stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6059             &stage_ptr->uniforms.uniform_double,
6060             stage_ptr->uniforms.uniform_double_arr + 0,
6061             stage_ptr->uniforms.uniform_double_arr + 1,
6062             stage_ptr->uniforms.uniform_dvec2 + 0,
6063             stage_ptr->uniforms.uniform_dvec2 + 1,
6064             stage_ptr->uniforms.uniform_dvec2_arr + 0,
6065             stage_ptr->uniforms.uniform_dvec2_arr + 1,
6066             stage_ptr->uniforms.uniform_dvec2_arr + 2,
6067             stage_ptr->uniforms.uniform_dvec2_arr + 3,
6068             stage_ptr->uniforms.uniform_dvec3 + 0,
6069             stage_ptr->uniforms.uniform_dvec3 + 1,
6070             stage_ptr->uniforms.uniform_dvec3 + 2,
6071             stage_ptr->uniforms.uniform_dvec3_arr + 0,
6072             stage_ptr->uniforms.uniform_dvec3_arr + 1,
6073             stage_ptr->uniforms.uniform_dvec3_arr + 2,
6074             stage_ptr->uniforms.uniform_dvec3_arr + 3,
6075             stage_ptr->uniforms.uniform_dvec3_arr + 4,
6076             stage_ptr->uniforms.uniform_dvec3_arr + 5,
6077             stage_ptr->uniforms.uniform_dvec4 + 0,
6078             stage_ptr->uniforms.uniform_dvec4 + 1,
6079             stage_ptr->uniforms.uniform_dvec4 + 2,
6080             stage_ptr->uniforms.uniform_dvec4 + 3,
6081             stage_ptr->uniforms.uniform_dvec4_arr + 0,
6082             stage_ptr->uniforms.uniform_dvec4_arr + 1,
6083             stage_ptr->uniforms.uniform_dvec4_arr + 2,
6084             stage_ptr->uniforms.uniform_dvec4_arr + 3,
6085             stage_ptr->uniforms.uniform_dvec4_arr + 4,
6086             stage_ptr->uniforms.uniform_dvec4_arr + 5,
6087             stage_ptr->uniforms.uniform_dvec4_arr + 6,
6088             stage_ptr->uniforms.uniform_dvec4_arr + 7,
6089         };
6090         const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6091 
6092         for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6093         {
6094             double *double_ptr = double_ptrs[n_double_ptr];
6095 
6096             /* Generate the value. Use magic numbers to generate a set of double-precision
6097              * floating-point numbers.
6098              */
6099             static int seed = 16762362;
6100 
6101             *double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6102 
6103             seed += 751;
6104         } /* for (all pointers to double variables) */
6105     }     /* for (all stages) */
6106 }
6107 
6108 /** Initializes all program & shader objects required to run the test. The function also
6109  *  retrieves locations of all uniforms defined by both program objects.
6110  **/
initProgramObjects()6111 void GPUShaderFP64Test4::initProgramObjects()
6112 {
6113     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6114 
6115     /* Create program & shader objects */
6116 
6117     /* Compute shader support and GL 4.2 required */
6118     if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6119         (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6120     {
6121         m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6122     }
6123 
6124     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6125     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6126     m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6127     m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6128     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6129     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6130 
6131     /* m_cs_id is initialized only if compute shaders are supported */
6132     if (0 != m_cs_id)
6133     {
6134         m_po_cs_id = gl.createProgram();
6135     }
6136 
6137     m_po_noncs_id = gl.createProgram();
6138     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6139 
6140     /* Configure compute shader body */
6141     const char *cs_body = "#version 420\n"
6142                           "#extension GL_ARB_compute_shader          : require\n"
6143                           "\n"
6144                           "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6145                           "\n"
6146                           "layout(rgba32f) uniform image2D testImage;\n"
6147                           "\n"
6148                           "uniform double cs_double;\n"
6149                           "uniform dvec2  cs_dvec2;\n"
6150                           "uniform dvec3  cs_dvec3;\n"
6151                           "uniform dvec4  cs_dvec4;\n"
6152                           "uniform double cs_double_arr[2];\n"
6153                           "uniform dvec2  cs_dvec2_arr [2];\n"
6154                           "uniform dvec3  cs_dvec3_arr [2];\n"
6155                           "uniform dvec4  cs_dvec4_arr [2];\n"
6156                           "\n"
6157                           "uniform struct cs_struct\n"
6158                           "{\n"
6159                           "    double struct_double;\n"
6160                           "    dvec2  struct_dvec2;\n"
6161                           "    dvec3  struct_dvec3;\n"
6162                           "    dvec4  struct_dvec4;\n"
6163                           "} cs_array[2];\n"
6164                           "\n"
6165                           "void main()\n"
6166                           "{\n"
6167                           "    double tmp = cs_double                  * cs_dvec2.x                 * cs_dvec3.y       "
6168                           "          * cs_dvec4.z                 *\n"
6169                           "                 cs_double_arr[0]           * cs_dvec2_arr[0].x          * "
6170                           "cs_dvec3_arr[0].z          * cs_dvec4_arr[0].w          *\n"
6171                           "                 cs_double_arr[1]           * cs_dvec2_arr[1].x          * "
6172                           "cs_dvec3_arr[1].z          * cs_dvec4_arr[1].w          *\n"
6173                           "                 cs_array[0].struct_double  * cs_array[0].struct_dvec2.y * "
6174                           "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6175                           "                 cs_array[1].struct_double  * cs_array[1].struct_dvec2.y * "
6176                           "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6177                           "\n"
6178                           "    imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6179                           "}\n";
6180 
6181     /* m_cs_id is initialized only if compute shaders are supported */
6182     if (0 != m_cs_id)
6183     {
6184         gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6185         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6186     }
6187 
6188     /* Configure vertex shader body */
6189     const char *vs_body = "#version 400\n"
6190                           "\n"
6191                           "uniform double vs_double;\n"
6192                           "uniform dvec2  vs_dvec2;\n"
6193                           "uniform dvec3  vs_dvec3;\n"
6194                           "uniform dvec4  vs_dvec4;\n"
6195                           "uniform double vs_double_arr[2];\n"
6196                           "uniform dvec2  vs_dvec2_arr [2];\n"
6197                           "uniform dvec3  vs_dvec3_arr [2];\n"
6198                           "uniform dvec4  vs_dvec4_arr [2];\n"
6199                           "\n"
6200                           "uniform struct vs_struct\n"
6201                           "{\n"
6202                           "    double struct_double;\n"
6203                           "    dvec2  struct_dvec2;\n"
6204                           "    dvec3  struct_dvec3;\n"
6205                           "    dvec4  struct_dvec4;\n"
6206                           "} vs_array[2];\n"
6207                           "\n"
6208                           "void main()\n"
6209                           "{\n"
6210                           "    if (vs_double                 * vs_dvec2.x                 * vs_dvec3.x                 "
6211                           "* vs_dvec4.x                 *\n"
6212                           "        vs_double_arr[0]          * vs_dvec2_arr[0].x          * vs_dvec3_arr[0].x          "
6213                           "* vs_dvec4_arr[0].x          *\n"
6214                           "        vs_double_arr[1]          * vs_dvec2_arr[1].x          * vs_dvec3_arr[1].x          "
6215                           "* vs_dvec4_arr[1].x          *\n"
6216                           "        vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6217                           "* vs_array[0].struct_dvec4.x *\n"
6218                           "        vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6219                           "* vs_array[1].struct_dvec4.x > 1.0)\n"
6220                           "    {\n"
6221                           "        gl_Position = vec4(0);\n"
6222                           "    }\n"
6223                           "    else\n"
6224                           "    {\n"
6225                           "        gl_Position = vec4(1);\n"
6226                           "    }\n"
6227                           "}\n";
6228 
6229     gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6230     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6231 
6232     /* Configure tessellation control shader body */
6233     const char *tc_body =
6234         "#version 400\n"
6235         "\n"
6236         "uniform double tc_double;\n"
6237         "uniform dvec2  tc_dvec2;\n"
6238         "uniform dvec3  tc_dvec3;\n"
6239         "uniform dvec4  tc_dvec4;\n"
6240         "uniform double tc_double_arr[2];\n"
6241         "uniform dvec2  tc_dvec2_arr [2];\n"
6242         "uniform dvec3  tc_dvec3_arr [2];\n"
6243         "uniform dvec4  tc_dvec4_arr [2];\n"
6244         "\n"
6245         "uniform struct tc_struct\n"
6246         "{\n"
6247         "    double struct_double;\n"
6248         "    dvec2  struct_dvec2;\n"
6249         "    dvec3  struct_dvec3;\n"
6250         "    dvec4  struct_dvec4;\n"
6251         "} tc_array[2];\n"
6252         "\n"
6253         "layout(vertices = 4) out;\n"
6254         "\n"
6255         "void main()\n"
6256         "{\n"
6257         "    gl_TessLevelOuter[0] = (tc_double        > 1.0) ? 2.0 : 3.0;\n"
6258         "    gl_TessLevelOuter[1] = (tc_dvec2.x       > 1.0) ? 3.0 : 4.0;\n"
6259         "    gl_TessLevelOuter[2] = (tc_dvec3.x       > 1.0) ? 4.0 : 5.0;\n"
6260         "    gl_TessLevelOuter[3] = (tc_dvec4.x       > 1.0) ? 5.0 : 6.0;\n"
6261         "    gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6262         "    gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6263         "\n"
6264         "    if (tc_dvec2_arr[0].y          * tc_dvec2_arr[1].y          *\n"
6265         "        tc_dvec3_arr[0].z          * tc_dvec3_arr[1].z          *\n"
6266         "        tc_dvec4_arr[0].z          * tc_dvec4_arr[1].z          *\n"
6267         "        tc_array[0].struct_double  * tc_array[0].struct_dvec2.x * \n"
6268         "        tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6269         "        tc_array[1].struct_double  * tc_array[1].struct_dvec2.x * \n"
6270         "        tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6271         "    {\n"
6272         "        gl_TessLevelInner[1] = 3.0;\n"
6273         "        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
6274         "    }\n"
6275         "    else\n"
6276         "    {\n"
6277         "        gl_TessLevelInner[1] = 0.0;\n"
6278         "        gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(1);\n"
6279         "    }\n"
6280         "}\n";
6281 
6282     gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6283     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6284 
6285     /* Configure tessellation evaluation shader body */
6286     const char *te_body = "#version 400\n"
6287                           "\n"
6288                           "uniform double te_double;\n"
6289                           "uniform dvec2  te_dvec2;\n"
6290                           "uniform dvec3  te_dvec3;\n"
6291                           "uniform dvec4  te_dvec4;\n"
6292                           "uniform double te_double_arr[2];\n"
6293                           "uniform dvec2  te_dvec2_arr [2];\n"
6294                           "uniform dvec3  te_dvec3_arr [2];\n"
6295                           "uniform dvec4  te_dvec4_arr [2];\n"
6296                           "\n"
6297                           "uniform struct te_struct\n"
6298                           "{\n"
6299                           "    double struct_double;\n"
6300                           "    dvec2  struct_dvec2;\n"
6301                           "    dvec3  struct_dvec3;\n"
6302                           "    dvec4  struct_dvec4;\n"
6303                           "} te_array[2];\n"
6304                           "\n"
6305                           "layout(triangles) in;\n"
6306                           "\n"
6307                           "void main()\n"
6308                           "{\n"
6309                           "    if (te_double                 * te_dvec2.x                 * te_dvec3.x                 "
6310                           "* te_dvec4.x                 *\n"
6311                           "        te_double_arr[0]          * te_dvec2_arr[0].x          * te_dvec3_arr[0].x          "
6312                           "* te_dvec4_arr[0].x          *\n"
6313                           "        te_double_arr[1]          * te_dvec2_arr[1].x          * te_dvec3_arr[1].x          "
6314                           "* te_dvec4_arr[1].x          *\n"
6315                           "        te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6316                           "* te_array[0].struct_dvec4.x *\n"
6317                           "        te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6318                           "* te_array[1].struct_dvec4.x > 1.0)\n"
6319                           "    {\n"
6320                           "        gl_Position = gl_in[0].gl_Position;\n"
6321                           "    }\n"
6322                           "    else\n"
6323                           "    {\n"
6324                           "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6325                           "    }\n"
6326                           "}\n";
6327 
6328     gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6329     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6330 
6331     /* Configure geometry shader body */
6332     const char *gs_body = "#version 400\n"
6333                           "\n"
6334                           "uniform double gs_double;\n"
6335                           "uniform dvec2  gs_dvec2;\n"
6336                           "uniform dvec3  gs_dvec3;\n"
6337                           "uniform dvec4  gs_dvec4;\n"
6338                           "uniform double gs_double_arr[2];\n"
6339                           "uniform dvec2  gs_dvec2_arr [2];\n"
6340                           "uniform dvec3  gs_dvec3_arr [2];\n"
6341                           "uniform dvec4  gs_dvec4_arr [2];\n"
6342                           "\n"
6343                           "uniform struct gs_struct\n"
6344                           "{\n"
6345                           "    double struct_double;\n"
6346                           "    dvec2  struct_dvec2;\n"
6347                           "    dvec3  struct_dvec3;\n"
6348                           "    dvec4  struct_dvec4;\n"
6349                           "} gs_array[2];\n"
6350                           "\n"
6351                           "layout (points)                   in;\n"
6352                           "layout (points, max_vertices = 1) out;\n"
6353                           "\n"
6354                           "void main()\n"
6355                           "{\n"
6356                           "    if (gs_double                 * gs_dvec2.x                 * gs_dvec3.x                 "
6357                           "* gs_dvec4.x        *\n"
6358                           "        gs_double_arr[0]          * gs_dvec2_arr[0].x          * gs_dvec3_arr[0].x          "
6359                           "* gs_dvec4_arr[0].x *\n"
6360                           "        gs_double_arr[1]          * gs_dvec2_arr[1].x          * gs_dvec3_arr[1].x          "
6361                           "* gs_dvec4_arr[1].x *\n"
6362                           "        gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6363                           "* gs_array[0].struct_dvec4.x *\n"
6364                           "        gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6365                           "* gs_array[1].struct_dvec4.x > 1.0)\n"
6366                           "    {\n"
6367                           "        gl_Position = gl_in[0].gl_Position;\n"
6368                           "    }\n"
6369                           "    else\n"
6370                           "    {\n"
6371                           "        gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6372                           "    }\n"
6373                           "\n"
6374                           "    EmitVertex();\n"
6375                           "}\n";
6376 
6377     gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6378     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6379 
6380     /* Configure fragment shader body */
6381     const char *fs_body = "#version 400\n"
6382                           "\n"
6383                           "uniform double fs_double;\n"
6384                           "uniform dvec2  fs_dvec2;\n"
6385                           "uniform dvec3  fs_dvec3;\n"
6386                           "uniform dvec4  fs_dvec4;\n"
6387                           "uniform double fs_double_arr[2];\n"
6388                           "uniform dvec2  fs_dvec2_arr [2];\n"
6389                           "uniform dvec3  fs_dvec3_arr [2];\n"
6390                           "uniform dvec4  fs_dvec4_arr [2];\n"
6391                           "\n"
6392                           "uniform struct fs_struct\n"
6393                           "{\n"
6394                           "    double struct_double;\n"
6395                           "    dvec2  struct_dvec2;\n"
6396                           "    dvec3  struct_dvec3;\n"
6397                           "    dvec4  struct_dvec4;\n"
6398                           "} fs_array[2];\n"
6399                           "\n"
6400                           "out vec4 result;\n"
6401                           "\n"
6402                           "void main()\n"
6403                           "{\n"
6404                           "    if (fs_double                 * fs_dvec2.x                 * fs_dvec3.x                 "
6405                           "* fs_dvec4.x        *\n"
6406                           "        fs_double_arr[0]          * fs_dvec2_arr[0].x          * fs_dvec3_arr[0].x          "
6407                           "* fs_dvec4_arr[0].x *\n"
6408                           "        fs_double_arr[1]          * fs_dvec2_arr[1].x          * fs_dvec3_arr[1].x          "
6409                           "* fs_dvec4_arr[1].x *\n"
6410                           "        fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6411                           "* fs_array[0].struct_dvec4.x *\n"
6412                           "        fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6413                           "* fs_array[1].struct_dvec4.x > 1.0)\n"
6414                           "    {\n"
6415                           "        result = vec4(0.0);\n"
6416                           "    }\n"
6417                           "    else\n"
6418                           "    {\n"
6419                           "        result = vec4(1.0);\n"
6420                           "    }\n"
6421                           "}\n";
6422 
6423     gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6424     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6425 
6426     /* Compile the shaders */
6427     const glw::GLuint shaders[]  = {m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id};
6428     const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6429 
6430     for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6431     {
6432         glw::GLint compile_status = GL_FALSE;
6433         glw::GLuint so_id         = shaders[n_shader];
6434 
6435         /* Skip compute shader if not supported */
6436         if (0 == so_id)
6437         {
6438             continue;
6439         }
6440 
6441         gl.compileShader(so_id);
6442         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6443 
6444         gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6445         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6446 
6447         if (compile_status != GL_TRUE)
6448         {
6449             TCU_FAIL("Shader compilation failed");
6450         }
6451 
6452         if (so_id == m_cs_id)
6453         {
6454             gl.attachShader(m_po_cs_id, so_id);
6455         }
6456         else
6457         {
6458             gl.attachShader(m_po_noncs_id, so_id);
6459         }
6460 
6461         GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6462     } /* for (all shaders) */
6463 
6464     /* Link the program */
6465     const glw::GLuint programs[]  = {m_po_cs_id, m_po_noncs_id};
6466     const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6467     glw::GLint link_status        = GL_FALSE;
6468 
6469     for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6470     {
6471         glw::GLuint po_id = programs[n_program];
6472 
6473         /* Skip compute shader program if not supported */
6474         if (0 == po_id)
6475         {
6476             continue;
6477         }
6478 
6479         gl.linkProgram(po_id);
6480         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6481 
6482         gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6483         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6484 
6485         if (link_status != GL_TRUE)
6486         {
6487             TCU_FAIL("Program linking failed");
6488         }
6489     } /* for (both program objects) */
6490 
6491     /* Retrieve uniform locations */
6492     _stage_data *cs_stage_data[]                    = {&m_data_cs};
6493     static const char *cs_uniform_prefixes[]        = {"cs_"};
6494     static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6495 
6496     _stage_data *noncs_stage_data[]             = {&m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs};
6497     static const char *noncs_uniform_prefixes[] = {"fs_", "gs_", "tc_", "te_", "vs_"};
6498     static const unsigned int n_noncs_uniform_prefixes =
6499         sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6500 
6501     for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6502     {
6503         unsigned int n_uniform_prefixes = DE_NULL;
6504         glw::GLuint po_id               = programs[n_program];
6505         _stage_data **stages_data       = DE_NULL;
6506         const char **uniform_prefixes   = DE_NULL;
6507 
6508         if (n_program == 0)
6509         {
6510             stages_data        = cs_stage_data;
6511             uniform_prefixes   = cs_uniform_prefixes;
6512             n_uniform_prefixes = n_cs_uniform_prefixes;
6513         }
6514         else
6515         {
6516             stages_data        = noncs_stage_data;
6517             uniform_prefixes   = noncs_uniform_prefixes;
6518             n_uniform_prefixes = n_noncs_uniform_prefixes;
6519         }
6520 
6521         /* Skip compute shader program if not supported */
6522         if (0 == po_id)
6523         {
6524             continue;
6525         }
6526 
6527         /* Uniform names used by the test program consist of a prefix (different for each
6528          * shader stage) and a common part.
6529          */
6530         for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6531         {
6532             _stage_data *stage_data              = stages_data[n_uniform_prefix];
6533             std::string uniform_prefix           = std::string(uniform_prefixes[n_uniform_prefix]);
6534             std::string uniform_double_name      = uniform_prefix + "double";
6535             std::string uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6536             std::string uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6537             std::string uniform_dvec2_name       = uniform_prefix + "dvec2";
6538             std::string uniform_dvec2_arr0_name  = uniform_prefix + "dvec2_arr[0]";
6539             std::string uniform_dvec2_arr1_name  = uniform_prefix + "dvec2_arr[1]";
6540             std::string uniform_dvec3_name       = uniform_prefix + "dvec3";
6541             std::string uniform_dvec3_arr0_name  = uniform_prefix + "dvec3_arr[0]";
6542             std::string uniform_dvec3_arr1_name  = uniform_prefix + "dvec3_arr[1]";
6543             std::string uniform_dvec4_name       = uniform_prefix + "dvec4";
6544             std::string uniform_dvec4_arr0_name  = uniform_prefix + "dvec4_arr[0]";
6545             std::string uniform_dvec4_arr1_name  = uniform_prefix + "dvec4_arr[1]";
6546             std::string uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6547             std::string uniform_arr0_dvec2_name  = uniform_prefix + "array[0].struct_dvec2";
6548             std::string uniform_arr0_dvec3_name  = uniform_prefix + "array[0].struct_dvec3";
6549             std::string uniform_arr0_dvec4_name  = uniform_prefix + "array[0].struct_dvec4";
6550             std::string uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6551             std::string uniform_arr1_dvec2_name  = uniform_prefix + "array[1].struct_dvec2";
6552             std::string uniform_arr1_dvec3_name  = uniform_prefix + "array[1].struct_dvec3";
6553             std::string uniform_arr1_dvec4_name  = uniform_prefix + "array[1].struct_dvec4";
6554 
6555             /* Retrieve uniform locations */
6556             stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6557             stage_data->uniforms.uniform_location_double_arr[0] =
6558                 gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6559             stage_data->uniforms.uniform_location_double_arr[1] =
6560                 gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6561             stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6562             stage_data->uniforms.uniform_location_dvec2_arr[0] =
6563                 gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6564             stage_data->uniforms.uniform_location_dvec2_arr[1] =
6565                 gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6566             stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6567             stage_data->uniforms.uniform_location_dvec3_arr[0] =
6568                 gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6569             stage_data->uniforms.uniform_location_dvec3_arr[1] =
6570                 gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6571             stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6572             stage_data->uniforms.uniform_location_dvec4_arr[0] =
6573                 gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6574             stage_data->uniforms.uniform_location_dvec4_arr[1] =
6575                 gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6576             stage_data->uniform_structure_arrays[0].uniform_location_double =
6577                 gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6578             stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6579                 gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6580             stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6581                 gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6582             stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6583                 gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6584             stage_data->uniform_structure_arrays[1].uniform_location_double =
6585                 gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6586             stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6587                 gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6588             stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6589                 gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6590             stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6591                 gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6592             GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6593 
6594             if (stage_data->uniforms.uniform_location_double == -1 ||
6595                 stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6596                 stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6597                 stage_data->uniforms.uniform_location_dvec2 == -1 ||
6598                 stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6599                 stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6600                 stage_data->uniforms.uniform_location_dvec3 == -1 ||
6601                 stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6602                 stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6603                 stage_data->uniforms.uniform_location_dvec4 == -1 ||
6604                 stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6605                 stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6606                 stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6607                 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6608                 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6609                 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6610                 stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6611                 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6612                 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6613                 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6614             {
6615                 TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6616             }
6617 
6618             /* Make sure locations of subsequent items in array uniforms are correct */
6619             if (stage_data->uniforms.uniform_location_double_arr[1] !=
6620                     (stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6621                 stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6622                     (stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6623                 stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6624                     (stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6625                 stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6626                     (stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6627             {
6628                 m_testCtx.getLog() << tcu::TestLog::Message
6629                                    << "Uniform locations:"
6630                                       " double_arr[0]:"
6631                                    << stage_data->uniforms.uniform_location_double_arr[0]
6632                                    << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6633                                    << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6634                                    << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6635                                    << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6636                                    << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6637                                    << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6638                                    << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6639                                    << tcu::TestLog::EndMessage;
6640 
6641                 TCU_FAIL("Double-precision uniform array item locations are invalid.");
6642             }
6643         } /* for (all uniform prefixes) */
6644     }     /* for (both program objects) */
6645 }
6646 
6647 /** Initializes all objects required to run the test. */
initTest()6648 void GPUShaderFP64Test4::initTest()
6649 {
6650     initProgramObjects();
6651 
6652     generateUniformValues();
6653     initUniformValues();
6654 }
6655 
6656 /** Assigns values generated by generateUniformValues() to uniforms defined by
6657  *  both program objects.
6658  **/
initUniformValues()6659 void GPUShaderFP64Test4::initUniformValues()
6660 {
6661     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6662 
6663     /* Iterate through all programs */
6664     _stage_data *cs_stages[]          = {&m_data_cs};
6665     _stage_data *noncs_stages[]       = {&m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs};
6666     const unsigned int n_cs_stages    = sizeof(cs_stages) / sizeof(cs_stages[0]);
6667     const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6668 
6669     const glw::GLuint programs[]  = {m_po_cs_id, m_po_noncs_id};
6670     const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6671 
6672     for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6673     {
6674         glw::GLuint po_id        = programs[n_program];
6675         unsigned int n_stages    = 0;
6676         _stage_data **stage_data = DE_NULL;
6677 
6678         if (po_id == m_po_cs_id)
6679         {
6680             n_stages   = n_cs_stages;
6681             stage_data = cs_stages;
6682         }
6683         else
6684         {
6685             n_stages   = n_noncs_stages;
6686             stage_data = noncs_stages;
6687         }
6688 
6689         /* Skip compute shader program if not supported */
6690         if (0 == po_id)
6691         {
6692             continue;
6693         }
6694 
6695         gl.useProgram(po_id);
6696         GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6697 
6698         for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6699         {
6700             /* Iterate through all uniforms */
6701             _stage_data *stage_ptr = stage_data[n_stage];
6702 
6703             gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6704             gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6705             gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6706             gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6707                          stage_ptr->uniform_structure_arrays[0].uniform_double);
6708             gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6709                          stage_ptr->uniform_structure_arrays[1].uniform_double);
6710             GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6711 
6712             gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6713             gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6714                           stage_ptr->uniforms.uniform_dvec2_arr + 0);
6715             gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6716                           stage_ptr->uniforms.uniform_dvec2_arr + 2);
6717             gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6718                           stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6719             gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6720                           stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6721             GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6722 
6723             gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6724             gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6725                           stage_ptr->uniforms.uniform_dvec3_arr + 0);
6726             gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6727                           stage_ptr->uniforms.uniform_dvec3_arr + 3);
6728             gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6729                           stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6730             gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6731                           stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6732             GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6733 
6734             gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6735             gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6736                           stage_ptr->uniforms.uniform_dvec4_arr + 0);
6737             gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6738                           stage_ptr->uniforms.uniform_dvec4_arr + 4);
6739             gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6740                           stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6741             gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6742                           stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6743             GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6744         } /* for (all shader stages) */
6745     }     /* for (both program objects) */
6746 }
6747 
6748 /** Executes test iteration.
6749  *
6750  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6751  */
iterate()6752 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6753 {
6754     /* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6755 
6756     /* Initialize all objects required to run the test */
6757     initTest();
6758 
6759     /* Verify the implementation reports correct values for all stages we've configured */
6760     m_has_test_passed &= verifyUniformValues();
6761 
6762     /* Is this also the case when "program interface query" mechanism is used? */
6763     if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6764     {
6765         m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6766     }
6767 
6768     /* We're done */
6769     if (m_has_test_passed)
6770     {
6771         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6772     }
6773     else
6774     {
6775         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6776     }
6777 
6778     return STOP;
6779 }
6780 
6781 /** Verifies that:
6782  *
6783  *  a) glGetProgramResourceIndex()
6784  *  b) glGetProgramResourceiv()
6785  *  c) glGetProgramResourceName()
6786  *
6787  *  functions return correct values for double-precision uniforms.
6788  *
6789  *  @return true if the verification was passed, false otherwise.
6790  */
verifyProgramInterfaceQuerySupport()6791 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6792 {
6793     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6794     bool result              = true;
6795 
6796     /* Iterate through all programs */
6797     const char *cs_prefixes[]         = {"cs_"};
6798     _stage_data *cs_stages[]          = {&m_data_cs};
6799     const char *noncs_prefixes[]      = {"fs_", "gs_", "tc_", "te_", "vs_"};
6800     _stage_data *noncs_stages[]       = {&m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs};
6801     const unsigned int n_cs_stages    = sizeof(cs_stages) / sizeof(cs_stages[0]);
6802     const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6803 
6804     const glw::GLuint programs[]  = {m_po_cs_id, m_po_noncs_id};
6805     const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6806 
6807     for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6808     {
6809         glw::GLuint po_id           = programs[n_program];
6810         unsigned int n_stages       = 0;
6811         const char **stage_prefixes = DE_NULL;
6812         _stage_data **stage_data    = DE_NULL;
6813 
6814         if (po_id == m_po_cs_id)
6815         {
6816             n_stages       = n_cs_stages;
6817             stage_data     = cs_stages;
6818             stage_prefixes = cs_prefixes;
6819         }
6820         else
6821         {
6822             n_stages       = n_noncs_stages;
6823             stage_data     = noncs_stages;
6824             stage_prefixes = noncs_prefixes;
6825         }
6826 
6827         /* Skip compute shader program if not supported */
6828         if (0 == po_id)
6829         {
6830             continue;
6831         }
6832 
6833         /* Determine maximum uniform name length */
6834         glw::GLint max_uniform_name_length = 0;
6835 
6836         gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6837         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6838 
6839         /* Allocate a buffer we will use to hold uniform names */
6840         m_uniform_name_buffer = new char[max_uniform_name_length];
6841 
6842         for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6843         {
6844             /* Iterate through all uniforms */
6845             _stage_data *stage_ptr   = stage_data[n_stage];
6846             const char *stage_prefix = stage_prefixes[n_stage];
6847 
6848             /* Construct an array that will be used to run the test in an automated manner */
6849             _program_interface_query_test_item uniforms[] = {
6850                 /* array size */ /* name */ /* type */ /* location */
6851                 {1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double},
6852                 {2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0]},
6853                 {1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2},
6854                 {2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0]},
6855                 {1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3},
6856                 {2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0]},
6857                 {1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4},
6858                 {2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0]},
6859                 {1, "array[0].struct_double", GL_DOUBLE, stage_ptr->uniform_structure_arrays->uniform_location_double},
6860                 {1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6861                  stage_ptr->uniform_structure_arrays->uniform_location_dvec2},
6862                 {1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6863                  stage_ptr->uniform_structure_arrays->uniform_location_dvec3},
6864                 {1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6865                  stage_ptr->uniform_structure_arrays->uniform_location_dvec4},
6866                 {1, "array[1].struct_double", GL_DOUBLE, stage_ptr->uniform_structure_arrays->uniform_location_double},
6867                 {1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6868                  stage_ptr->uniform_structure_arrays->uniform_location_dvec2},
6869                 {1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6870                  stage_ptr->uniform_structure_arrays->uniform_location_dvec3},
6871                 {1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6872                  stage_ptr->uniform_structure_arrays->uniform_location_dvec4},
6873             };
6874             const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6875 
6876             /* Prefix the names with stage-specific string */
6877             for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6878             {
6879                 _program_interface_query_test_item &current_item = uniforms[n_uniform];
6880 
6881                 current_item.name = std::string(stage_prefix) + current_item.name;
6882             } /* for (all uniform descriptors) */
6883 
6884             const glw::GLenum properties[]  = {GL_ARRAY_SIZE, GL_TYPE};
6885             const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6886 
6887             for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6888             {
6889                 _program_interface_query_test_item &current_item = uniforms[n_uniform];
6890                 glw::GLint n_written_items                       = 0;
6891                 glw::GLint retrieved_array_size                  = 0;
6892                 glw::GLint retrieved_name_length                 = 0;
6893                 glw::GLenum retrieved_type                       = GL_NONE;
6894                 glw::GLint temp_buffer[2]                        = {0, GL_NONE};
6895 
6896                 /* Retrieve index of the iteration-specific uniform */
6897                 glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6898                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6899 
6900                 /* Make sure glGetProgramResourceName() returns correct values */
6901                 memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6902 
6903                 gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6904                                           resource_index, max_uniform_name_length, &retrieved_name_length,
6905                                           m_uniform_name_buffer);
6906                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6907 
6908                 if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6909                     memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6910                 {
6911                     m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6912                                        << resource_index
6913                                        << "]"
6914                                           ": expected:["
6915                                        << current_item.name
6916                                        << "]"
6917                                           ", reported:["
6918                                        << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6919 
6920                     result = false;
6921                     continue;
6922                 }
6923 
6924                 /* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6925                 gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6926                                         resource_index, n_properties, properties,
6927                                         sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6928                 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6929 
6930                 if (n_written_items != n_properties)
6931                 {
6932                     TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6933                 }
6934 
6935                 /* For clarity, copy the retrieved values to separate variables */
6936                 retrieved_array_size = temp_buffer[0];
6937                 retrieved_type       = temp_buffer[1];
6938 
6939                 /* Verify the values */
6940                 if (retrieved_array_size != current_item.expected_array_size)
6941                 {
6942                     m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6943                                        << current_item.name << "]"
6944                                        << ": expected:[" << current_item.expected_array_size
6945                                        << "]"
6946                                           ", reported:["
6947                                        << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6948 
6949                     result = false;
6950                 }
6951 
6952                 if (retrieved_type != current_item.expected_type)
6953                 {
6954                     m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6955                                        << current_item.name << "]"
6956                                        << ": expected:[" << current_item.expected_type
6957                                        << "]"
6958                                           ", reported:["
6959                                        << retrieved_type << "]" << tcu::TestLog::EndMessage;
6960 
6961                     result = false;
6962                 }
6963             } /* for (all uniforms) */
6964         }     /* for (all shader stages) */
6965 
6966         /* We're now OK to release the buffer we used to hold uniform names for
6967          * the program */
6968         if (m_uniform_name_buffer != DE_NULL)
6969         {
6970             delete[] m_uniform_name_buffer;
6971 
6972             m_uniform_name_buffer = DE_NULL;
6973         }
6974     } /* for (both program objects) */
6975 
6976     return result;
6977 }
6978 
6979 /** Verifies glGetUniform*() calls return correct values assigned to
6980  *  double-precision uniforms.
6981  *
6982  *  @return true if all values reported by OpenGL were found to be correct,
6983  *          false otherwise.
6984  **/
verifyUniformValues()6985 bool GPUShaderFP64Test4::verifyUniformValues()
6986 {
6987     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
6988     bool result              = true;
6989 
6990     /* Iterate through all programs */
6991     _stage_data *cs_stages[]          = {&m_data_cs};
6992     _stage_data *noncs_stages[]       = {&m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs};
6993     const unsigned int n_cs_stages    = sizeof(cs_stages) / sizeof(cs_stages[0]);
6994     const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6995 
6996     const glw::GLuint programs[] = {
6997         m_po_noncs_id,
6998         m_po_cs_id,
6999     };
7000     const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
7001 
7002     for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
7003     {
7004         glw::GLuint po_id        = programs[n_program];
7005         unsigned int n_stages    = 0;
7006         _stage_data **stage_data = DE_NULL;
7007 
7008         if (po_id == m_po_cs_id)
7009         {
7010             n_stages   = n_cs_stages;
7011             stage_data = cs_stages;
7012         }
7013         else
7014         {
7015             n_stages   = n_noncs_stages;
7016             stage_data = noncs_stages;
7017         }
7018 
7019         /* Skip compute shader program if not supported */
7020         if (0 == po_id)
7021         {
7022             continue;
7023         }
7024 
7025         for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
7026         {
7027             /* Iterate through all uniforms */
7028             _stage_data *stage_ptr = stage_data[n_stage];
7029 
7030             /* Set up arrays that we will guide the automated testing */
7031             const uniform_value_pair double_uniforms[] = {
7032                 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
7033                 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
7034                                    stage_ptr->uniforms.uniform_double_arr + 0),
7035                 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
7036                                    stage_ptr->uniforms.uniform_double_arr + 1),
7037                 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
7038                                    &stage_ptr->uniform_structure_arrays[0].uniform_double),
7039                 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
7040                                    &stage_ptr->uniform_structure_arrays[1].uniform_double)};
7041             const uniform_value_pair dvec2_uniforms[] = {
7042                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
7043                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
7044                                    stage_ptr->uniforms.uniform_dvec2_arr + 0),
7045                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
7046                                    stage_ptr->uniforms.uniform_dvec2_arr + 2),
7047                 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
7048                                    stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
7049                 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
7050                                    stage_ptr->uniform_structure_arrays[1].uniform_dvec2)};
7051             const uniform_value_pair dvec3_uniforms[] = {
7052                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
7053                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
7054                                    stage_ptr->uniforms.uniform_dvec3_arr + 0),
7055                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
7056                                    stage_ptr->uniforms.uniform_dvec3_arr + 3),
7057                 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
7058                                    stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
7059                 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
7060                                    stage_ptr->uniform_structure_arrays[1].uniform_dvec3)};
7061             const uniform_value_pair dvec4_uniforms[] = {
7062                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7063                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7064                                    stage_ptr->uniforms.uniform_dvec4_arr + 0),
7065                 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7066                                    stage_ptr->uniforms.uniform_dvec4_arr + 4),
7067                 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7068                                    stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7069                 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7070                                    stage_ptr->uniform_structure_arrays[1].uniform_dvec4)};
7071 
7072             /* Iterate over all uniforms and verify the values reported by the API */
7073             double returned_double_data[4];
7074             float returned_float_data[4];
7075             int returned_int_data[4];
7076             unsigned int returned_uint_data[4];
7077 
7078             for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7079             {
7080                 const uniform_value_pair *current_uv_pairs = NULL;
7081                 const unsigned int n_components_used       = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7082                 unsigned int n_pairs                       = 0;
7083 
7084                 switch (n_type)
7085                 {
7086                 case 0: /* double */
7087                 {
7088                     current_uv_pairs = double_uniforms;
7089                     n_pairs          = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7090 
7091                     break;
7092                 }
7093 
7094                 case 1: /* dvec2 */
7095                 {
7096                     current_uv_pairs = dvec2_uniforms;
7097                     n_pairs          = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7098 
7099                     break;
7100                 }
7101 
7102                 case 2: /* dvec3 */
7103                 {
7104                     current_uv_pairs = dvec3_uniforms;
7105                     n_pairs          = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7106 
7107                     break;
7108                 }
7109 
7110                 case 3: /* dvec4 */
7111                 {
7112                     current_uv_pairs = dvec4_uniforms;
7113                     n_pairs          = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7114 
7115                     break;
7116                 }
7117 
7118                 default:
7119                 {
7120                     TCU_FAIL("Invalid type index requested");
7121                 }
7122                 } /* switch (n_type) */
7123 
7124                 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7125                 {
7126                     const uniform_value_pair &current_uv_pair = current_uv_pairs[n_pair];
7127                     glw::GLint uniform_location               = current_uv_pair.first;
7128                     const double *uniform_value               = current_uv_pair.second;
7129 
7130                     /* Retrieve the values from the GL implementation*/
7131                     gl.getUniformdv(po_id, uniform_location, returned_double_data);
7132                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7133 
7134                     gl.getUniformfv(po_id, uniform_location, returned_float_data);
7135                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7136 
7137                     gl.getUniformiv(po_id, uniform_location, returned_int_data);
7138                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7139 
7140                     gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7141                     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7142 
7143                     /* Make sure the values reported match the reference values */
7144                     bool can_continue   = true;
7145                     const float epsilon = 1e-5f;
7146 
7147                     for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7148                     {
7149                         if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7150                         {
7151                             m_testCtx.getLog()
7152                                 << tcu::TestLog::Message
7153                                 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7154                                 << uniform_location
7155                                 << "]"
7156                                    " and component ["
7157                                 << n_component
7158                                 << "]"
7159                                    ": retrieved:["
7160                                 << returned_double_data[n_component]
7161                                 << "]"
7162                                    ", expected:["
7163                                 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7164 
7165                             result = false;
7166                         }
7167 
7168                         if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7169                         {
7170                             m_testCtx.getLog()
7171                                 << tcu::TestLog::Message
7172                                 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7173                                 << uniform_location
7174                                 << "]"
7175                                    " and component ["
7176                                 << n_component
7177                                 << "]"
7178                                    ": retrieved:["
7179                                 << returned_float_data[n_component]
7180                                 << "]"
7181                                    ", expected:["
7182                                 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7183 
7184                             result = false;
7185                         }
7186 
7187                         /* ints */
7188                         int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7189                         unsigned int rounded_uniform_value_uint =
7190                             (unsigned int)(uniform_value[n_component] > 0.0) ?
7191                                 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7192                                 0;
7193 
7194                         if (returned_int_data[n_component] != rounded_uniform_value_sint)
7195                         {
7196                             m_testCtx.getLog()
7197                                 << tcu::TestLog::Message
7198                                 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7199                                 << uniform_location
7200                                 << "]"
7201                                    " and component ["
7202                                 << n_component
7203                                 << "]"
7204                                    ": retrieved:["
7205                                 << returned_int_data[n_component]
7206                                 << "]"
7207                                    ", expected:["
7208                                 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7209 
7210                             result = false;
7211                         }
7212 
7213                         if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7214                         {
7215                             m_testCtx.getLog()
7216                                 << tcu::TestLog::Message
7217                                 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7218                                 << uniform_location
7219                                 << "]"
7220                                    " and component ["
7221                                 << n_component
7222                                 << "]"
7223                                    ": retrieved:["
7224                                 << returned_uint_data[n_component]
7225                                 << "]"
7226                                    ", expected:["
7227                                 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7228 
7229                             result = false;
7230                         }
7231                     } /* for (all components) */
7232                 }     /* for (all uniform+value pairs) */
7233             }         /* for (all 4 uniform types) */
7234         }             /* for (all shader stages) */
7235     }                 /* for (both program objects) */
7236 
7237     /* All done! */
7238     return result;
7239 }
7240 
7241 /** Constructor
7242  *
7243  *  @param context Rendering context.
7244  */
GPUShaderFP64Test5(deqp::Context & context)7245 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context &context)
7246     : TestCase(context, "conversions",
7247                "Verifies explicit and implicit casts involving double-precision"
7248                " floating-point variables work correctly")
7249     , m_base_value_bo_data(DE_NULL)
7250     , m_base_value_bo_id(0)
7251     , m_has_test_passed(true)
7252     , m_po_base_value_attribute_location(-1)
7253     , m_po_id(0)
7254     , m_vao_id(0)
7255     , m_vs_id(0)
7256     , m_xfb_bo_id(0)
7257     , m_xfb_bo_size(0)
7258 {
7259     /* Set up base value array (as per test spec) */
7260     m_base_values[0] = -25.12065f;
7261     m_base_values[1] = 0.0f;
7262     m_base_values[2] = 0.001f;
7263     m_base_values[3] = 1.0f;
7264     m_base_values[4] = 256.78901f;
7265 
7266     /* Set up swizzle matrix */
7267     m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7268     m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7269     m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7270     m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7271     m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7272     m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7273     m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7274     m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7275     m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7276     m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7277     m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7278     m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7279     m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7280     m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7281     m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7282     m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7283 }
7284 
deinit()7285 void GPUShaderFP64Test5::deinit()
7286 {
7287     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7288 
7289     if (m_base_value_bo_data != DE_NULL)
7290     {
7291         delete[] m_base_value_bo_data;
7292 
7293         m_base_value_bo_data = DE_NULL;
7294     }
7295 
7296     if (m_base_value_bo_id != 0)
7297     {
7298         gl.deleteBuffers(1, &m_base_value_bo_id);
7299 
7300         m_base_value_bo_id = 0;
7301     }
7302 
7303     if (m_vao_id != 0)
7304     {
7305         gl.deleteVertexArrays(1, &m_vao_id);
7306 
7307         m_vao_id = 0;
7308     }
7309 
7310     if (m_xfb_bo_id != 0)
7311     {
7312         gl.deleteBuffers(1, &m_xfb_bo_id);
7313 
7314         m_xfb_bo_id = 0;
7315     }
7316 
7317     /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7318      * take care of it here
7319      */
7320     deinitInteration();
7321 }
7322 
7323 /** Deinitializes all buffers and GL objects that may have been generated
7324  *  during test execution.
7325  **/
deinitInteration()7326 void GPUShaderFP64Test5::deinitInteration()
7327 {
7328     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7329 
7330     if (m_po_id != 0)
7331     {
7332         gl.deleteProgram(m_po_id);
7333 
7334         m_po_id = 0;
7335     }
7336 
7337     if (m_vs_id != 0)
7338     {
7339         gl.deleteShader(m_vs_id);
7340 
7341         m_vs_id = 0;
7342     }
7343 }
7344 
7345 /** Executes a single test case iteration using user-provided test case descriptor.
7346  *
7347  *  This function may throw a TestError exception if GL implementation misbehaves.
7348  *
7349  *  @param test_case Test case descriptor to use.
7350  *
7351  *  @return true if the values returned by GL implementation were found to be valid,
7352  *          false otherwise.
7353  **/
executeIteration(const _test_case & test_case)7354 bool GPUShaderFP64Test5::executeIteration(const _test_case &test_case)
7355 {
7356     bool result = true;
7357 
7358     /* Convert the base values array to the type of input attribute we'll be using
7359      * for the iteration.
7360      */
7361     Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7362 
7363     if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7364     {
7365         /* bools are actually represented by ints, since bool varyings are not allowed */
7366         base_value_type = Utils::VARIABLE_TYPE_INT;
7367     }
7368 
7369     const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7370     const unsigned int n_base_values             = sizeof(m_base_values) / sizeof(m_base_values[0]);
7371 
7372     m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7373 
7374     unsigned char *base_value_traveller_ptr = m_base_value_bo_data;
7375 
7376     for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7377     {
7378         switch (base_value_type)
7379         {
7380         case Utils::VARIABLE_TYPE_DOUBLE:
7381             *((double *)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7382             break;
7383         case Utils::VARIABLE_TYPE_FLOAT:
7384             *((float *)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7385             break;
7386         case Utils::VARIABLE_TYPE_INT:
7387             *((int *)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7388             break;
7389         case Utils::VARIABLE_TYPE_UINT:
7390             *((unsigned int *)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7391             break;
7392 
7393         default:
7394         {
7395             TCU_FAIL("Unrecognized base value type");
7396         }
7397         }
7398 
7399         base_value_traveller_ptr += base_value_component_size;
7400     } /* for (all base values) */
7401 
7402     /* Update buffer object storage with the data we've just finished preparing. */
7403     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7404 
7405     gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7406     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7407 
7408     gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7409     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7410 
7411     /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7412      * new data is interpreted correctly.
7413      */
7414     if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7415     {
7416         gl.vertexAttribPointer(m_po_base_value_attribute_location, 1,                             /* size */
7417                                Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7418                                0,                                                                 /* stride */
7419                                DE_NULL);                                                          /* pointer */
7420         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7421     }
7422     else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7423     {
7424         gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1,                      /* size */
7425                                 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7426                                 DE_NULL);                                                   /* pointer */
7427         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7428     }
7429     else
7430     {
7431         DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7432 
7433         gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7434                                 GL_DOUBLE, 0,                          /* stride */
7435                                 DE_NULL);                              /* pointer */
7436         GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7437     }
7438 
7439     gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7440     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7441 
7442     /* Execute the draw call */
7443     gl.useProgram(m_po_id);
7444     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7445 
7446     gl.beginTransformFeedback(GL_POINTS);
7447     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7448     {
7449         gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7450         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7451     }
7452     gl.endTransformFeedback();
7453     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7454 
7455     /* Map the XFB buffer object into process space */
7456     void *xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7457 
7458     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7459     DE_ASSERT(xfb_data_ptr != NULL);
7460 
7461     /* Verify the data */
7462     result &= verifyXFBData((const unsigned char *)xfb_data_ptr, test_case);
7463 
7464     /* Unmap the XFB BO */
7465     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7466     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7467 
7468     /** Good to release the data buffer at this point */
7469     if (m_base_value_bo_data != DE_NULL)
7470     {
7471         delete[] m_base_value_bo_data;
7472 
7473         m_base_value_bo_data = DE_NULL;
7474     }
7475 
7476     /* All done */
7477     return result;
7478 }
7479 
7480 /** Returns properties of a swizzle operator described by @param type swizzle type.
7481  *
7482  *  @param out_swizzle_string  Deref will be used to store a GLSL literal
7483  *                             corresponding to the specific swizzle operator.
7484  *                             Must not be NULL.
7485  *  @param out_n_components    Deref will be used to store the amount of components
7486  *                             used by the operator. Must not be NULL.
7487  *  @param out_component_order Deref will be used to store up to 4 integer values,
7488  *                             corresponding to component indices described by the
7489  *                             operator for a particular position.  Must not be NULL.
7490  **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7491 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string *out_swizzle_string,
7492                                                   unsigned int *out_n_components, unsigned int *out_component_order)
7493 {
7494     unsigned int result_component_order[4] = {0};
7495     unsigned int result_n_components       = 0;
7496     std::string result_swizzle_string;
7497 
7498     switch (type)
7499     {
7500     case SWIZZLE_TYPE_NONE:
7501     {
7502         result_swizzle_string = "";
7503         result_n_components   = 0;
7504 
7505         break;
7506     }
7507 
7508     case SWIZZLE_TYPE_XWZY:
7509     {
7510         result_swizzle_string     = "xwzy";
7511         result_n_components       = 4;
7512         result_component_order[0] = 0;
7513         result_component_order[1] = 3;
7514         result_component_order[2] = 2;
7515         result_component_order[3] = 1;
7516 
7517         break;
7518     }
7519 
7520     case SWIZZLE_TYPE_XZXY:
7521     {
7522         result_swizzle_string     = "xzxy";
7523         result_n_components       = 4;
7524         result_component_order[0] = 0;
7525         result_component_order[1] = 2;
7526         result_component_order[2] = 0;
7527         result_component_order[3] = 1;
7528 
7529         break;
7530     }
7531 
7532     case SWIZZLE_TYPE_XZY:
7533     {
7534         result_swizzle_string     = "xzy";
7535         result_n_components       = 3;
7536         result_component_order[0] = 0;
7537         result_component_order[1] = 2;
7538         result_component_order[2] = 1;
7539 
7540         break;
7541     }
7542 
7543     case SWIZZLE_TYPE_XZYW:
7544     {
7545         result_swizzle_string     = "xzyw";
7546         result_n_components       = 4;
7547         result_component_order[0] = 0;
7548         result_component_order[1] = 2;
7549         result_component_order[2] = 1;
7550         result_component_order[3] = 3;
7551 
7552         break;
7553     }
7554 
7555     case SWIZZLE_TYPE_Y:
7556     {
7557         result_swizzle_string     = "y";
7558         result_n_components       = 1;
7559         result_component_order[0] = 1;
7560 
7561         break;
7562     }
7563 
7564     case SWIZZLE_TYPE_YX:
7565     {
7566         result_swizzle_string     = "yx";
7567         result_n_components       = 2;
7568         result_component_order[0] = 1;
7569         result_component_order[1] = 0;
7570 
7571         break;
7572     }
7573 
7574     case SWIZZLE_TYPE_YXX:
7575     {
7576         result_swizzle_string     = "yxx";
7577         result_n_components       = 3;
7578         result_component_order[0] = 1;
7579         result_component_order[1] = 0;
7580         result_component_order[2] = 0;
7581 
7582         break;
7583     }
7584 
7585     case SWIZZLE_TYPE_YXXY:
7586     {
7587         result_swizzle_string     = "yxxy";
7588         result_n_components       = 4;
7589         result_component_order[0] = 1;
7590         result_component_order[1] = 0;
7591         result_component_order[2] = 0;
7592         result_component_order[3] = 1;
7593 
7594         break;
7595     }
7596 
7597     case SWIZZLE_TYPE_Z:
7598     {
7599         result_swizzle_string     = "z";
7600         result_n_components       = 1;
7601         result_component_order[0] = 2;
7602 
7603         break;
7604     }
7605 
7606     case SWIZZLE_TYPE_ZY:
7607     {
7608         result_swizzle_string     = "zy";
7609         result_n_components       = 2;
7610         result_component_order[0] = 2;
7611         result_component_order[1] = 1;
7612 
7613         break;
7614     }
7615 
7616     case SWIZZLE_TYPE_W:
7617     {
7618         result_swizzle_string     = "w";
7619         result_n_components       = 1;
7620         result_component_order[0] = 3;
7621 
7622         break;
7623     }
7624 
7625     case SWIZZLE_TYPE_WX:
7626     {
7627         result_swizzle_string     = "wx";
7628         result_n_components       = 2;
7629         result_component_order[0] = 3;
7630         result_component_order[1] = 0;
7631 
7632         break;
7633     }
7634 
7635     default:
7636     {
7637         TCU_FAIL("Unrecognized swizzle type");
7638     }
7639     } /* switch (type) */
7640 
7641     if (out_swizzle_string != DE_NULL)
7642     {
7643         *out_swizzle_string = result_swizzle_string;
7644     }
7645 
7646     if (out_n_components != DE_NULL)
7647     {
7648         *out_n_components = result_n_components;
7649     }
7650 
7651     if (out_component_order != DE_NULL)
7652     {
7653         memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7654     }
7655 }
7656 
7657 /** Returns body of a vertex shader that should be used for particular test case,
7658  *  given user-specified test case descriptor.
7659  *
7660  *  @param test_case Descriptor to use for the query.
7661  *
7662  *  @return Requested data.
7663  **/
getVertexShaderBody(const _test_case & test_case)7664 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case &test_case)
7665 {
7666     std::stringstream result;
7667     const std::string base_type_string  = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7668     const std::string dst_type_string   = Utils::getVariableTypeString(test_case.dst_type);
7669     const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7670     const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7671     const std::string src_type_string   = Utils::getVariableTypeString(test_case.src_type);
7672 
7673     /* Add version preamble */
7674     result << "#version 420\n"
7675               "\n";
7676 
7677     /* Declare output variables. Note that boolean output variables are not supported, so we need
7678      * to handle that special case correctly */
7679     if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7680     {
7681         result << "out int result;\n";
7682     }
7683     else
7684     {
7685         result << "out " << dst_type_string << " result;\n";
7686     }
7687 
7688     /* Declare input variables. Handle the bool case exclusively. */
7689     if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7690     {
7691         /* Use ints for bools. We will cast them to bool in the code later. */
7692         result << "in int base_value;\n";
7693     }
7694     else
7695     {
7696         result << "in " << base_type_string << " base_value;\n";
7697     }
7698 
7699     /* Declare main() and construct the value we will be casting from.
7700      *
7701      * Note: Addition operations on bool values cause an implicit conversion to int
7702      *       which is not allowed. Hence, we skip these operations for this special
7703      *       case.
7704      */
7705     result << "void main()\n"
7706               "{\n"
7707            << src_type_string << " lside_value = ";
7708 
7709     if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7710     {
7711         result << src_type_string << "(0 != ";
7712     }
7713     else
7714     {
7715         result << src_type_string << "(";
7716     }
7717 
7718     if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7719     {
7720         for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7721         {
7722             result << "base_value + " << n_component;
7723 
7724             if (n_component != (n_src_components - 1))
7725             {
7726                 result << ", ";
7727             }
7728         } /* for (all components) */
7729     }
7730     else
7731     {
7732         DE_ASSERT(n_src_components == 1);
7733 
7734         result << "base_value";
7735     }
7736 
7737     result << ");\n";
7738 
7739     /* Perform the casting operation. Add swizzle operator if possible. */
7740     if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7741     {
7742         /* Handle the bool case exclusively */
7743         if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7744         {
7745             result << "result = (bool(lside_value) == false) ? 0 : 1";
7746         }
7747         else
7748         {
7749             result << "result = (lside_value == false) ? 0 : 1";
7750         }
7751     }
7752     else
7753     {
7754         if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7755         {
7756             result << "result = " << dst_type_string << "(lside_value)";
7757         }
7758         else
7759         {
7760             result << "result = lside_value";
7761         }
7762     }
7763 
7764     if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7765     {
7766         /* Add a swizzle operator  */
7767         DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7768         DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7769 
7770         unsigned int swizzle_component_order[4] = {0};
7771         unsigned int swizzle_n_components       = 0;
7772         _swizzle_type swizzle_operator          = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7773         std::string swizzle_string;
7774 
7775         getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7776 
7777         if (swizzle_n_components > 0)
7778         {
7779             result << "." << swizzle_string;
7780         }
7781     }
7782 
7783     /* Close the shader implementation. */
7784     result << ";\n"
7785               "}\n";
7786 
7787     return result.str();
7788 }
7789 
7790 /** Initializes program & shader objects needed to run the iteration, given
7791  *  user-specified test case descriptor.
7792  *
7793  *  This function can throw a TestError exception if a GL error is detected
7794  *  during execution.
7795  *
7796  *  @param test_case Descriptor to use for the iteration.
7797  **/
initIteration(_test_case & test_case)7798 void GPUShaderFP64Test5::initIteration(_test_case &test_case)
7799 {
7800     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7801 
7802     /* Create program & shader objects */
7803     m_po_id = gl.createProgram();
7804     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7805 
7806     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7807     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7808 
7809     /* Configure shader body */
7810     std::string body         = getVertexShaderBody(test_case);
7811     const char *body_raw_ptr = body.c_str();
7812 
7813     gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7814     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7815 
7816     /* Store it in the test case descriptor for logging purposes */
7817     test_case.shader_body = body;
7818 
7819     /* Compile the shader */
7820     glw::GLint compile_status = GL_FALSE;
7821 
7822     gl.compileShader(m_vs_id);
7823     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7824 
7825     gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7826     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7827 
7828     if (compile_status != GL_TRUE)
7829     {
7830         TCU_FAIL("Shader compilation failed");
7831     }
7832 
7833     /* Attach the shader to the program obejct */
7834     gl.attachShader(m_po_id, m_vs_id);
7835     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7836 
7837     /* Configure XFB for the program object */
7838     const char *xfb_varying_name = "result";
7839 
7840     gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7841     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7842 
7843     /* Link the program object */
7844     glw::GLint link_status = GL_FALSE;
7845 
7846     gl.linkProgram(m_po_id);
7847     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7848 
7849     gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7850     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7851 
7852     if (link_status != GL_TRUE)
7853     {
7854         TCU_FAIL("Program linking failed");
7855     }
7856 
7857     /* Retrieve attribute locations */
7858     m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7859     GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7860 
7861     if (m_po_base_value_attribute_location == -1)
7862     {
7863         TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7864     }
7865 }
7866 
7867 /** Initializes GL objects used by all test cases.
7868  *
7869  *  This function may throw a TestError exception if GL implementation reports
7870  *  an error at any point.
7871  **/
initTest()7872 void GPUShaderFP64Test5::initTest()
7873 {
7874     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
7875 
7876     /* Generate buffer object IDs */
7877     gl.genBuffers(1, &m_base_value_bo_id);
7878     gl.genBuffers(1, &m_xfb_bo_id);
7879     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7880 
7881     /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7882      * will never eat up more than 1 double (as per test spec) and we will be drawing
7883      * as many points in a single draw call as there are defined in m_base_values array.
7884      */
7885     const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7886 
7887     gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7888     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7889 
7890     gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7891     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7892 
7893     /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7894      * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7895      * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7896      */
7897     const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7898 
7899     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7900     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7901 
7902     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7903     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7904 
7905     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7906     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7907 
7908     /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7909     m_xfb_bo_size = xfb_bo_size;
7910 
7911     /* Generate a vertex array object we will need to use for the draw calls */
7912     gl.genVertexArrays(1, &m_vao_id);
7913     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7914 
7915     gl.bindVertexArray(m_vao_id);
7916     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7917 }
7918 
7919 /** Executes test iteration.
7920  *
7921  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7922  */
iterate()7923 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7924 {
7925     /* Do not execute the test if GL_ARB_texture_view is not supported */
7926     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7927     {
7928         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7929     }
7930 
7931     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7932     {
7933         throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7934     }
7935 
7936     /* Initialize GL objects needed to run the tests */
7937     initTest();
7938 
7939     /* Build iteration array to run the tests in an automated manner */
7940     _test_case test_cases[]         = {/* test case type */ /* source type */ /* destination type */
7941                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7942                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, ""},
7943                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, ""},
7944                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, ""},
7945                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7946                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, ""},
7947                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, ""},
7948                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, ""},
7949                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7950                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, ""},
7951                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, ""},
7952                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, ""},
7953                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, ""},
7954                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, ""},
7955                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, ""},
7956                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, ""},
7957                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, ""},
7958                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, ""},
7959                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, ""},
7960                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, ""},
7961                                {TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, ""},
7962 
7963                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7964                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7965                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, ""},
7966                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, ""},
7967                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, ""},
7968                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, ""},
7969                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, ""},
7970                                {TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, ""}};
7971     const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7972 
7973     /* Execute all iterations */
7974     for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7975     {
7976         _test_case &test_case = test_cases[n_test_case];
7977 
7978         /* Initialize a program object we will use to perform the casting */
7979         initIteration(test_case);
7980 
7981         /* Use the program object to XFB the results */
7982         m_has_test_passed &= executeIteration(test_case);
7983 
7984         /* Release the GL Resource for this sub test */
7985         deinitInteration();
7986 
7987     } /* for (all test cases) */
7988     /* We're done */
7989     if (m_has_test_passed)
7990     {
7991         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7992     }
7993     else
7994     {
7995         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7996     }
7997 
7998     return STOP;
7999 }
8000 
8001 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
8002  *  for which the data have been generated.
8003  *
8004  *  @param data_ptr  Buffer holding the data XFBed out by the shader.
8005  *  @param test_case Descriptor of the test case, for which the vertex shader was
8006  *                   generated.
8007  *
8008  *  @return true if the data were found to be valid, false otherwise.
8009  **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)8010 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char *data_ptr, const _test_case &test_case)
8011 {
8012     const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
8013     const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
8014     const float epsilon                       = 1e-5f;
8015     const unsigned int n_base_values          = sizeof(m_base_values) / sizeof(m_base_values[0]);
8016     const unsigned int n_result_components    = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
8017     const unsigned int n_src_components       = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
8018     bool result                               = true;
8019     _swizzle_type swizzle_operator            = SWIZZLE_TYPE_NONE;
8020     unsigned int swizzle_order[4]             = {0};
8021     const unsigned char *traveller_ptr        = data_ptr;
8022 
8023     if (!Utils::isMatrixVariableType(test_case.src_type))
8024     {
8025         DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
8026         DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
8027 
8028         swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
8029 
8030         getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
8031                                  DE_NULL,                   /* out_n_components */
8032                                  swizzle_order);
8033     }
8034 
8035     for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
8036     {
8037         for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
8038         {
8039             unsigned int n_swizzled_component = n_result_component;
8040 
8041             if (swizzle_operator != SWIZZLE_TYPE_NONE)
8042             {
8043                 n_swizzled_component =
8044                     (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
8045             }
8046 
8047             switch (base_dst_type)
8048             {
8049             case Utils::VARIABLE_TYPE_BOOL:
8050             case Utils::VARIABLE_TYPE_INT:
8051             {
8052                 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8053                 double expected_value     = ref_expected_value;
8054                 int result_value          = *((int *)traveller_ptr);
8055 
8056                 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
8057                 {
8058                     if (expected_value != 0.0)
8059                     {
8060                         expected_value = 1.0;
8061                     }
8062                 }
8063 
8064                 if (result_value != (int)expected_value)
8065                 {
8066                     m_testCtx.getLog() << tcu::TestLog::Message
8067                                        << "Invalid boolean/integer value obtained when doing an "
8068                                        << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8069                                        << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8070                                        << "]"
8071                                           ", component index: ["
8072                                        << n_swizzled_component
8073                                        << "]"
8074                                           ", value: ["
8075                                        << ref_expected_value
8076                                        << "]"
8077                                           " to GLSL type ["
8078                                        << Utils::getVariableTypeString(test_case.dst_type)
8079                                        << "]"
8080                                           ", retrieved value: ["
8081                                        << result_value
8082                                        << "]"
8083                                           ", expected value: ["
8084                                        << (int)expected_value
8085                                        << "]"
8086                                           ", shader used:\n"
8087                                        << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8088 
8089                     result = false;
8090                 }
8091 
8092                 traveller_ptr += sizeof(int);
8093                 break;
8094             } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8095 
8096             case Utils::VARIABLE_TYPE_DOUBLE:
8097             {
8098                 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8099                 double expected_value     = ref_expected_value;
8100                 double result_value       = *((double *)traveller_ptr);
8101 
8102                 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8103                 {
8104                     expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8105                 }
8106                 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8107                 {
8108                     expected_value = (int)expected_value;
8109                 }
8110                 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8111                 {
8112                     // Negative values in base values array when converted to unsigned int will be ZERO
8113                     // Addition operations done inside the shader in such cases will operate on ZERO rather
8114                     // than the negative value being passed.
8115                     // Replicate the sequence of conversion and addition operations done on the
8116                     // shader input, to calculate the expected values in XFB data in the
8117                     // problematic cases.
8118                     if (expected_value < 0)
8119                     {
8120                         expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8121                     }
8122                     expected_value = (unsigned int)expected_value;
8123                 }
8124 
8125                 traveller_ptr += sizeof(double);
8126                 if (de::abs(result_value - expected_value) > epsilon)
8127                 {
8128                     m_testCtx.getLog() << tcu::TestLog::Message
8129                                        << "Invalid double-precision floating-point value obtained when doing an "
8130                                        << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8131                                        << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8132                                        << "]"
8133                                           ", component index: ["
8134                                        << n_swizzled_component
8135                                        << "]"
8136                                           ", value: ["
8137                                        << ref_expected_value
8138                                        << "]"
8139                                           " to GLSL type ["
8140                                        << Utils::getVariableTypeString(test_case.dst_type)
8141                                        << "]"
8142                                           ", retrieved value: ["
8143                                        << std::setprecision(16) << result_value
8144                                        << "]"
8145                                           ", expected value: ["
8146                                        << std::setprecision(16) << expected_value
8147                                        << "]"
8148                                           ", shader used:\n"
8149                                        << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8150 
8151                     result = false;
8152                 }
8153 
8154                 break;
8155             } /* VARIABLE_TYPE_DOUBLE case */
8156 
8157             case Utils::VARIABLE_TYPE_FLOAT:
8158             {
8159                 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8160                 float expected_value     = ref_expected_value;
8161                 float result_value       = *((float *)traveller_ptr);
8162 
8163                 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8164                 {
8165                     expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8166                 }
8167                 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8168                 {
8169                     expected_value = (float)((int)expected_value);
8170                 }
8171                 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8172                 {
8173                     expected_value = (float)((unsigned int)expected_value);
8174                 }
8175 
8176                 traveller_ptr += sizeof(float);
8177                 if (de::abs(result_value - expected_value) > epsilon)
8178                 {
8179                     m_testCtx.getLog() << tcu::TestLog::Message
8180                                        << "Invalid single-precision floating-point value obtained when doing an "
8181                                        << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8182                                        << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8183                                        << "]"
8184                                           ", component index: ["
8185                                        << n_swizzled_component
8186                                        << "]"
8187                                           ", value: ["
8188                                        << ref_expected_value
8189                                        << "]"
8190                                           " to GLSL type ["
8191                                        << Utils::getVariableTypeString(test_case.dst_type)
8192                                        << "]"
8193                                           ", retrieved value: ["
8194                                        << std::setprecision(16) << result_value
8195                                        << "]"
8196                                           ", expected value: ["
8197                                        << std::setprecision(16) << expected_value
8198                                        << "]"
8199                                           ", shader used:\n"
8200                                        << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8201 
8202                     result = false;
8203                 }
8204 
8205                 break;
8206             } /* VARIABLE_TYPE_FLOAT case */
8207 
8208             case Utils::VARIABLE_TYPE_UINT:
8209             {
8210                 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8211                 double expected_value     = ref_expected_value;
8212                 unsigned int result_value = *((unsigned int *)traveller_ptr);
8213 
8214                 traveller_ptr += sizeof(unsigned int);
8215                 if (result_value != (unsigned int)expected_value)
8216                 {
8217                     if (expected_value < 0.0)
8218                     {
8219                         // It is undefined to convert a negative floating-point value to an uint.
8220                         break;
8221                     }
8222 
8223                     m_testCtx.getLog() << tcu::TestLog::Message
8224                                        << "Invalid unsigned integer value obtained when doing an "
8225                                        << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8226                                        << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8227                                        << "]"
8228                                           ", component index: ["
8229                                        << n_swizzled_component
8230                                        << "]"
8231                                           ", value: ["
8232                                        << ref_expected_value
8233                                        << "]"
8234                                           " to GLSL type ["
8235                                        << Utils::getVariableTypeString(test_case.dst_type)
8236                                        << "]"
8237                                           ", retrieved value: ["
8238                                        << result_value
8239                                        << "]"
8240                                           ", expected value: ["
8241                                        << (unsigned int)expected_value
8242                                        << "]"
8243                                           ", shader used:\n"
8244                                        << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8245 
8246                     result = false;
8247                 }
8248 
8249                 break;
8250             } /* VARIABLE_TYPE_UINT case */
8251 
8252             default:
8253             {
8254                 TCU_FAIL("Unrecognized variable type");
8255             }
8256             } /* switch (test_case.dst_type) */
8257         }     /* for (all result components) */
8258     }         /* for (all base values) */
8259 
8260     return result;
8261 }
8262 
8263 /** Constructor
8264  *
8265  *  @param context Rendering context.
8266  */
GPUShaderFP64Test6(deqp::Context & context)8267 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context &context)
8268     : TestCase(context, "illegal_conversions",
8269                "Verifies that invalid casts to double-precision variables are detected "
8270                "during compilation time.")
8271     , m_cs_id(0)
8272     , m_fs_id(0)
8273     , m_gs_id(0)
8274     , m_tc_id(0)
8275     , m_te_id(0)
8276     , m_vs_id(0)
8277     , m_has_test_passed(true)
8278 {
8279 }
8280 
8281 /** Deinitializes all buffers and GL objects that may have been generated
8282  *  during test execution.
8283  **/
deinit()8284 void GPUShaderFP64Test6::deinit()
8285 {
8286     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8287 
8288     if (m_cs_id != 0)
8289     {
8290         gl.deleteShader(m_cs_id);
8291 
8292         m_cs_id = 0;
8293     }
8294 
8295     if (m_fs_id != 0)
8296     {
8297         gl.deleteShader(m_fs_id);
8298 
8299         m_fs_id = 0;
8300     }
8301 
8302     if (m_gs_id != 0)
8303     {
8304         gl.deleteShader(m_gs_id);
8305 
8306         m_gs_id = 0;
8307     }
8308 
8309     if (m_tc_id != 0)
8310     {
8311         gl.deleteShader(m_tc_id);
8312 
8313         m_tc_id = 0;
8314     }
8315 
8316     if (m_te_id != 0)
8317     {
8318         gl.deleteShader(m_te_id);
8319 
8320         m_te_id = 0;
8321     }
8322 
8323     if (m_vs_id != 0)
8324     {
8325         gl.deleteShader(m_vs_id);
8326 
8327         m_vs_id = 0;
8328     }
8329 }
8330 
8331 /** Executes a single test case.
8332  *
8333  *  This function can throw TestError exceptions if GL implementation reports
8334  *  an error.
8335  *
8336  *  @param test_case Test case descriptor.
8337  *
8338  *  @return true if test case passed, false otherwise.
8339  **/
executeIteration(const _test_case & test_case)8340 bool GPUShaderFP64Test6::executeIteration(const _test_case &test_case)
8341 {
8342     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
8343     const glw::GLuint so_ids[]  = {m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id};
8344     const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8345     bool result                 = true;
8346     const char *stage_body      = NULL;
8347     const char *stage_name      = NULL;
8348 
8349     for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8350     {
8351         const glw::GLuint so_id = so_ids[n_so_id];
8352 
8353         /* Skip compute shader if it is not supported */
8354         if (0 == so_id)
8355         {
8356             continue;
8357         }
8358 
8359         /* Compile the shader */
8360         gl.compileShader(so_id);
8361         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8362 
8363         /* Has the compilation failed as expected? */
8364         glw::GLint compile_status = GL_TRUE;
8365 
8366         gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8367         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8368 
8369         if (compile_status == GL_TRUE)
8370         {
8371             /* What is the current stage's name? */
8372             if (so_id == m_cs_id)
8373             {
8374                 stage_body = test_case.cs_shader_body.c_str();
8375                 stage_name = "Compute shader";
8376             }
8377             else if (so_id == m_fs_id)
8378             {
8379                 stage_body = test_case.fs_shader_body.c_str();
8380                 stage_name = "Fragment shader";
8381             }
8382             else if (so_id == m_gs_id)
8383             {
8384                 stage_body = test_case.gs_shader_body.c_str();
8385                 stage_name = "Geometry shader";
8386             }
8387             else if (so_id == m_tc_id)
8388             {
8389                 stage_body = test_case.tc_shader_body.c_str();
8390                 stage_name = "Tessellation control shader";
8391             }
8392             else if (so_id == m_te_id)
8393             {
8394                 stage_body = test_case.te_shader_body.c_str();
8395                 stage_name = "Tessellation evaluation shader";
8396             }
8397             else if (so_id == m_vs_id)
8398             {
8399                 stage_body = test_case.vs_shader_body.c_str();
8400                 stage_name = "Vertex shader";
8401             }
8402             else
8403             {
8404                 /* Doesn't make much sense to throw exceptions here so.. */
8405                 stage_body = "";
8406                 stage_name = "[?]";
8407             }
8408 
8409             /* This shader should have never compiled successfully! */
8410             m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8411                                << " has been compiled successfully, even though the shader was malformed."
8412                                   " Following is shader body:\n"
8413                                << stage_body << tcu::TestLog::EndMessage;
8414 
8415             result = false;
8416         }
8417     } /* for (all shader objects) */
8418 
8419     return result;
8420 }
8421 
8422 /** Retrieves body of a compute shader that should be used for the purpose of
8423  *  user-specified test case.
8424  *
8425  *  @param test_case Test case descriptor to use.
8426  *
8427  *  @return Requested string.
8428  **/
getComputeShaderBody(const _test_case & test_case)8429 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case &test_case)
8430 {
8431     std::stringstream result_sstream;
8432 
8433     /* Add pre-amble */
8434     result_sstream << "#version 420\n"
8435                       "#extension GL_ARB_compute_shader          : require\n"
8436                       "\n"
8437                       "layout(local_size_x = 6) in;\n"
8438                       "\n"
8439                       "void main()\n"
8440                       "{\n";
8441 
8442     /* Add local variable declarations */
8443     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8444 
8445     if (test_case.src_array_size > 1)
8446     {
8447         result_sstream << "[" << test_case.src_array_size << "]";
8448     }
8449 
8450     result_sstream << ";\n";
8451 
8452     if (test_case.wrap_dst_type_in_structure)
8453     {
8454         result_sstream << "struct\n"
8455                           "{\n"
8456                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8457     }
8458     else
8459     {
8460         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8461     }
8462 
8463     result_sstream << ";\n";
8464 
8465     if (test_case.wrap_dst_type_in_structure)
8466     {
8467         result_sstream << "\n} dst;\n";
8468     }
8469 
8470     /* Add actual body */
8471     result_sstream << "dst = src;\n"
8472                       "}\n";
8473 
8474     /* Return the body */
8475     return result_sstream.str();
8476 }
8477 
8478 /** Retrieves body of a fragment shader that should be used for the purpose of
8479  *  user-specified test case.
8480  *
8481  *  @param test_case Test case descriptor to use.
8482  *
8483  *  @return Requested string.
8484  **/
getFragmentShaderBody(const _test_case & test_case)8485 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case &test_case)
8486 {
8487     std::stringstream result_sstream;
8488 
8489     /* Add pre-amble */
8490     result_sstream << "#version 420\n"
8491                       "\n"
8492                       "void main()\n"
8493                       "{\n";
8494 
8495     /* Add local variable declarations */
8496     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8497 
8498     if (test_case.src_array_size > 1)
8499     {
8500         result_sstream << "[" << test_case.src_array_size << "]";
8501     }
8502 
8503     result_sstream << ";\n";
8504 
8505     if (test_case.wrap_dst_type_in_structure)
8506     {
8507         result_sstream << "struct\n"
8508                           "{\n"
8509                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8510     }
8511     else
8512     {
8513         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8514     }
8515 
8516     result_sstream << ";\n";
8517 
8518     if (test_case.wrap_dst_type_in_structure)
8519     {
8520         result_sstream << "\n} dst;\n";
8521     }
8522 
8523     /* Add actual body */
8524     result_sstream << "dst = src;\n"
8525                       "}\n";
8526 
8527     /* Return the body */
8528     return result_sstream.str();
8529 }
8530 
8531 /** Retrieves body of a geometry shader that should be used for the purpose of
8532  *  user-specified test case.
8533  *
8534  *  @param test_case Test case descriptor to use.
8535  *
8536  *  @return Requested string.
8537  **/
getGeometryShaderBody(const _test_case & test_case)8538 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case &test_case)
8539 {
8540     std::stringstream result_sstream;
8541 
8542     /* Add preamble */
8543     result_sstream << "#version 420\n"
8544                       "\n"
8545                       "layout(points)                 in;\n"
8546                       "layout(max_vertices=1, points) out;\n"
8547                       "\n"
8548                       "void main()\n"
8549                       "{\n";
8550 
8551     /* Add local variable declarations */
8552     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8553 
8554     if (test_case.src_array_size > 1)
8555     {
8556         result_sstream << "[" << test_case.src_array_size << "]";
8557     }
8558 
8559     result_sstream << ";\n";
8560 
8561     if (test_case.wrap_dst_type_in_structure)
8562     {
8563         result_sstream << "struct\n"
8564                           "{\n"
8565                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8566     }
8567     else
8568     {
8569         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8570     }
8571 
8572     result_sstream << ";\n"
8573                       "\n";
8574 
8575     if (test_case.wrap_dst_type_in_structure)
8576     {
8577         result_sstream << "} dst;\n";
8578     }
8579 
8580     /* Add actual body */
8581     result_sstream << "dst = src;\n"
8582                       "}\n";
8583 
8584     /* We're done! */
8585     return result_sstream.str();
8586 }
8587 
8588 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8589  *  user-specified test case.
8590  *
8591  *  @param test_case Test case descriptor to use.
8592  *
8593  *  @return Requested string.
8594  **/
getTessellationControlShaderBody(const _test_case & test_case)8595 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case &test_case)
8596 {
8597     std::stringstream result_sstream;
8598 
8599     /* Add preamble */
8600     result_sstream << "#version 420\n"
8601                       "\n"
8602                       "layout(vertices=4) out;\n"
8603                       "\n"
8604                       "void main()\n"
8605                       "{\n";
8606 
8607     /* Add local variable declarations. */
8608     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8609 
8610     if (test_case.src_array_size > 1)
8611     {
8612         result_sstream << "[" << test_case.src_array_size << "]";
8613     }
8614 
8615     result_sstream << ";\n";
8616 
8617     if (test_case.wrap_dst_type_in_structure)
8618     {
8619         result_sstream << "struct\n"
8620                           "{\n"
8621                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8622     }
8623     else
8624     {
8625         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8626     }
8627 
8628     if (test_case.wrap_dst_type_in_structure)
8629     {
8630         result_sstream << ";\n"
8631                           "} dst;\n";
8632     }
8633     else
8634     {
8635         result_sstream << ";\n";
8636     }
8637 
8638     /* Continue with the actual body. */
8639     result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8640                       "gl_TessLevelOuter[1] = 1.0;\n"
8641                       "dst                  = src;\n"
8642                       "}\n";
8643 
8644     /* Return the body */
8645     return result_sstream.str();
8646 }
8647 
8648 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8649  *  user-specified test case.
8650  *
8651  *  @param test_case Test case descriptor to use.
8652  *
8653  *  @return Requested string.
8654  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8655 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case &test_case)
8656 {
8657     std::stringstream result_sstream;
8658 
8659     /* Add preamble */
8660     result_sstream << "#version 420\n"
8661                       "\n"
8662                       "layout(isolines) in;\n"
8663                       "\n"
8664                       "void main()\n"
8665                       "{\n";
8666 
8667     /* Add local variable declarations */
8668     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8669 
8670     if (test_case.src_array_size > 1)
8671     {
8672         result_sstream << "[" << test_case.src_array_size << "]";
8673     }
8674 
8675     result_sstream << ";\n";
8676 
8677     if (test_case.wrap_dst_type_in_structure)
8678     {
8679         result_sstream << "struct\n"
8680                           "{\n"
8681                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8682     }
8683     else
8684     {
8685         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8686     }
8687 
8688     if (test_case.wrap_dst_type_in_structure)
8689     {
8690         result_sstream << ";\n"
8691                           "} dst;\n";
8692     }
8693     else
8694     {
8695         result_sstream << ";\n";
8696     }
8697 
8698     /* Continue with the actual body. */
8699     result_sstream << "dst = src;\n";
8700 
8701     /* Complete the body */
8702     result_sstream << "}\n";
8703 
8704     /* Return the body */
8705     return result_sstream.str();
8706 }
8707 
8708 /** Retrieves body of a vertex shader that should be used for the purpose of
8709  *  user-specified test case.
8710  *
8711  *  @param test_case Test case descriptor to use.
8712  *
8713  *  @return Requested string.
8714  **/
getVertexShaderBody(const _test_case & test_case)8715 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case &test_case)
8716 {
8717     std::stringstream result_sstream;
8718 
8719     /* Add preamble */
8720     result_sstream << "#version 420\n"
8721                       "\n"
8722                       "void main()\n"
8723                       "{\n";
8724 
8725     /* Add local variables */
8726     result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8727 
8728     if (test_case.src_array_size > 1)
8729     {
8730         result_sstream << "[" << test_case.src_array_size << "]";
8731     }
8732 
8733     result_sstream << ";\n";
8734 
8735     if (test_case.wrap_dst_type_in_structure)
8736     {
8737         result_sstream << "struct\n"
8738                           "{\n"
8739                        << Utils::getVariableTypeString(test_case.dst_type) << " member";
8740     }
8741     else
8742     {
8743         result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8744     }
8745 
8746     if (test_case.wrap_dst_type_in_structure)
8747     {
8748         result_sstream << ";\n"
8749                           "} dst;\n";
8750     }
8751     else
8752     {
8753         result_sstream << ";\n";
8754     }
8755 
8756     /* Start actual body */
8757     result_sstream << "dst         = src;\n"
8758                       "gl_Position = vec4(1.0);\n"
8759                       "}";
8760 
8761     return result_sstream.str();
8762 }
8763 
8764 /** Initializes shader objects required to run the test. */
initTest()8765 void GPUShaderFP64Test6::initTest()
8766 {
8767     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8768 
8769     /* Generate shader objects */
8770 
8771     /* Compute shader support and GL 4.2 required */
8772     if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8773         (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8774     {
8775         m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8776     }
8777 
8778     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8779     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8780     m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8781     m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8782     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8783 
8784     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8785 }
8786 
8787 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8788  *
8789  *  @param test_case Test case descriptor to generate the shader bodies for.
8790  **/
initIteration(_test_case & test_case)8791 void GPUShaderFP64Test6::initIteration(_test_case &test_case)
8792 {
8793     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8794 
8795     test_case.cs_shader_body = getComputeShaderBody(test_case);
8796     test_case.fs_shader_body = getFragmentShaderBody(test_case);
8797     test_case.gs_shader_body = getGeometryShaderBody(test_case);
8798     test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8799     test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8800     test_case.vs_shader_body = getVertexShaderBody(test_case);
8801 
8802     /* Assign the bodies to relevant shaders */
8803     const char *cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8804     const char *fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8805     const char *gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8806     const char *tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8807     const char *te_body_raw_ptr = test_case.te_shader_body.c_str();
8808     const char *vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8809 
8810     /* m_cs_id is initialized only if compute_shader is supported */
8811     if (0 != m_cs_id)
8812     {
8813         gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8814     }
8815 
8816     gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8817     gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8818     gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8819     gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8820     gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8821     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8822 }
8823 
8824 /** Executes test iteration.
8825  *
8826  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8827  */
iterate()8828 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8829 {
8830     /* Do not execute the test if GL_ARB_texture_view is not supported */
8831     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8832     {
8833         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8834     }
8835 
8836     /* Initialize GL objects needed to run the tests */
8837     initTest();
8838 
8839     /* Build iteration array to run the tests in an automated manner */
8840     _test_case test_cases[] = {
8841         /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8842         {2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", ""},
8843         {2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", ""},
8844         {2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", ""},
8845         {2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", ""},
8846         {2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", ""},
8847         {2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", ""},
8848         {2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", ""},
8849         {2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", ""},
8850         {2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", ""},
8851         {2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", ""},
8852         {2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", ""},
8853         {2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", ""},
8854         {2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", ""},
8855         {2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", ""},
8856         {2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", ""},
8857         {2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", ""},
8858         {2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", ""},
8859         {2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", ""},
8860         {2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", ""},
8861         {2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", ""},
8862         {2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", ""},
8863         {2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", ""},
8864         {2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", ""},
8865         {2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", ""},
8866         {2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", ""},
8867         {2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", ""},
8868         {2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", ""},
8869         {2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", ""},
8870         {2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", ""},
8871         {2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", ""},
8872         {2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", ""},
8873         {2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", ""},
8874         {2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", ""},
8875         {2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", ""},
8876         {2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", ""},
8877         {2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", ""},
8878         {2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", ""},
8879         {2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", ""},
8880         {2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", ""},
8881         {2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", ""},
8882         {2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", ""},
8883         {2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", ""}};
8884     const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8885 
8886     /* Execute all iterations */
8887     for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8888     {
8889         _test_case &test_case = test_cases[n_test_case];
8890 
8891         /* Initialize a program object we will use to perform the casting */
8892         initIteration(test_case);
8893 
8894         /* Use the program object to XFB the results */
8895         m_has_test_passed &= executeIteration(test_case);
8896 
8897     } /* for (all test cases) */
8898 
8899     /* We're done */
8900     if (m_has_test_passed)
8901     {
8902         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8903     }
8904     else
8905     {
8906         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8907     }
8908 
8909     return STOP;
8910 }
8911 
8912 /** Constructor
8913  *
8914  *  @param context Rendering context.
8915  */
GPUShaderFP64Test7(deqp::Context & context)8916 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context &context)
8917     : TestCase(context, "varyings",
8918                "Verifies double-precision floating-point varyings work correctly "
8919                "in all shader stages.")
8920     , m_are_double_inputs_supported(false)
8921     , m_fbo_id(0)
8922     , m_fs_id(0)
8923     , m_gs_id(0)
8924     , m_has_test_passed(true)
8925     , m_n_max_components_per_stage(0)
8926     , m_n_xfb_varyings(0)
8927     , m_po_id(0)
8928     , m_tc_id(0)
8929     , m_te_id(0)
8930     , m_to_id(0)
8931     , m_to_data(NULL)
8932     , m_to_height(4)
8933     , m_to_width(4)
8934     , m_xfb_bo_id(0)
8935     , m_xfb_varyings(NULL)
8936     , m_vao_id(0)
8937     , m_vs_id(0)
8938 {
8939 }
8940 
8941 /** Compiles all shaders attached to test program object and links it.
8942  *
8943  *  @param variables
8944  *
8945  *  @return true if the process was executed successfully, false otherwise.
8946  */
buildTestProgram(_variables & variables)8947 bool GPUShaderFP64Test7::buildTestProgram(_variables &variables)
8948 {
8949     std::string fs_body      = getFragmentShaderBody(variables);
8950     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
8951     std::string gs_body      = getGeometryShaderBody(variables);
8952     std::string tc_body      = getTessellationControlShaderBody(variables);
8953     std::string te_body      = getTessellationEvaluationShaderBody(variables);
8954     std::string vs_body      = getVertexShaderBody(variables);
8955     bool result              = false;
8956 
8957     /* Try to link the program object */
8958     glw::GLint link_status = GL_FALSE;
8959 
8960     /* Compile the shaders */
8961     if (!compileShader(m_fs_id, fs_body))
8962     {
8963         m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8964 
8965         goto end;
8966     }
8967 
8968     if (!compileShader(m_gs_id, gs_body))
8969     {
8970         m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8971 
8972         goto end;
8973     }
8974 
8975     if (!compileShader(m_tc_id, tc_body))
8976     {
8977         m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8978                            << tcu::TestLog::EndMessage;
8979 
8980         goto end;
8981     }
8982 
8983     if (!compileShader(m_te_id, te_body))
8984     {
8985         m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8986                            << tcu::TestLog::EndMessage;
8987 
8988         goto end;
8989     }
8990 
8991     if (!compileShader(m_vs_id, vs_body))
8992     {
8993         m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8994 
8995         goto end;
8996     }
8997 
8998     /* Configure XFB */
8999     releaseXFBVaryingNames();
9000     generateXFBVaryingNames(variables);
9001 
9002     gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
9003 
9004     gl.linkProgram(m_po_id);
9005 
9006     /* Have we succeeded? */
9007     GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
9008 
9009     gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
9010     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
9011 
9012     if (link_status != GL_TRUE)
9013     {
9014         m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
9015                            << tcu::TestLog::EndMessage;
9016 
9017         goto end;
9018     }
9019 
9020     /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
9021     if (m_are_double_inputs_supported)
9022     {
9023         const size_t n_variables = variables.size();
9024 
9025         for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9026         {
9027             _variable &current_variable = variables[n_variable];
9028             std::stringstream attribute_name_sstream;
9029 
9030             attribute_name_sstream << "in_vs_variable" << n_variable;
9031 
9032             if (current_variable.array_size > 1)
9033             {
9034                 attribute_name_sstream << "[0]";
9035             }
9036 
9037             current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
9038 
9039             if (current_variable.attribute_location == -1)
9040             {
9041                 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
9042                                    << attribute_name_sstream.str().c_str()
9043                                    << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
9044 
9045                 m_has_test_passed = false;
9046                 goto end;
9047             }
9048         } /* for (all test variables) */
9049     }     /* if (m_are_double_inputs_supported) */
9050 
9051     m_current_fs_body = fs_body;
9052     m_current_gs_body = gs_body;
9053     m_current_tc_body = tc_body;
9054     m_current_te_body = te_body;
9055     m_current_vs_body = vs_body;
9056 
9057     result = true;
9058 
9059 end:
9060     return result;
9061 }
9062 
9063 /** Updates shader object's body and then compiles the shader.
9064  *
9065  *  @param body Body to use for the shader.
9066  *
9067  *  @return true if the shader compiled successfully, false otherwise.
9068  **/
compileShader(glw::GLint shader_id,const std::string & body)9069 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string &body)
9070 {
9071     const char *body_raw_ptr  = body.c_str();
9072     glw::GLint compile_status = GL_FALSE;
9073     const glw::Functions &gl  = m_context.getRenderContext().getFunctions();
9074 
9075     gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
9076     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
9077 
9078     gl.compileShader(shader_id);
9079     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9080 
9081     gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
9082     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9083 
9084     return (compile_status == GL_TRUE);
9085 }
9086 
9087 /** Configure storage of a buffer object used for capturing XFB data.
9088  *
9089  *  @param variables Holds descriptor for all variables used for the iteration the
9090  *                   BO is being configured for. Storage size will be directly related
9091  *                   to the number of the variables and their type.
9092  */
configureXFBBuffer(const _variables & variables)9093 void GPUShaderFP64Test7::configureXFBBuffer(const _variables &variables)
9094 {
9095     DE_ASSERT(m_n_xfb_varyings != 0);
9096 
9097     /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9098      * The test only draws a single patch, and triangles are caught by transform feed-back.
9099      * Let's initialize the storage, according to the list of variables that will be used
9100      * for the test run.
9101      */
9102     unsigned int bo_size = 0;
9103 
9104     for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9105          variables_iterator++)
9106     {
9107         const _variable &variable   = *variables_iterator;
9108         unsigned int n_bytes_needed = static_cast<unsigned int>(
9109             Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9110 
9111         bo_size += n_bytes_needed;
9112     } /* for (all variables) */
9113 
9114     bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9115 
9116     /* Set up the BO storage */
9117     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9118 
9119     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9120     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9121 }
9122 
9123 /** Deinitializes all buffers and GL objects that may have been generated
9124  *  during test execution.
9125  **/
deinit()9126 void GPUShaderFP64Test7::deinit()
9127 {
9128     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9129 
9130     if (m_fbo_id != 0)
9131     {
9132         gl.deleteFramebuffers(1, &m_fbo_id);
9133 
9134         m_fbo_id = 0;
9135     }
9136 
9137     if (m_fs_id != 0)
9138     {
9139         gl.deleteShader(m_fs_id);
9140 
9141         m_fs_id = 0;
9142     }
9143 
9144     if (m_gs_id != 0)
9145     {
9146         gl.deleteShader(m_gs_id);
9147 
9148         m_gs_id = 0;
9149     }
9150 
9151     if (m_po_id != 0)
9152     {
9153         gl.deleteProgram(m_po_id);
9154 
9155         m_po_id = 0;
9156     }
9157 
9158     if (m_tc_id != 0)
9159     {
9160         gl.deleteShader(m_tc_id);
9161 
9162         m_tc_id = 0;
9163     }
9164 
9165     if (m_te_id != 0)
9166     {
9167         gl.deleteShader(m_te_id);
9168 
9169         m_te_id = 0;
9170     }
9171 
9172     if (m_to_data != NULL)
9173     {
9174         delete[] m_to_data;
9175 
9176         m_to_data = NULL;
9177     }
9178 
9179     if (m_to_id != 0)
9180     {
9181         gl.deleteTextures(1, &m_to_id);
9182 
9183         m_to_id = 0;
9184     }
9185 
9186     if (m_xfb_bo_id != 0)
9187     {
9188         gl.deleteBuffers(1, &m_xfb_bo_id);
9189 
9190         m_xfb_bo_id = 0;
9191     }
9192 
9193     if (m_xfb_varyings != DE_NULL)
9194     {
9195         releaseXFBVaryingNames();
9196     }
9197 
9198     if (m_vao_id != 0)
9199     {
9200         gl.deleteVertexArrays(1, &m_vao_id);
9201 
9202         m_vao_id = 0;
9203     }
9204 
9205     if (m_vs_id != 0)
9206     {
9207         gl.deleteShader(m_vs_id);
9208 
9209         m_vs_id = 0;
9210     }
9211 }
9212 
9213 /** Executes the functional part of the test (case a) from the test spec)
9214  *
9215  *  @param variables Vector of variable descriptors defining properties of
9216  *                   variables that should be used for the iteration.
9217  *
9218  *  @return true if the test passed, false otherwise.
9219  **/
executeFunctionalTest(_variables & variables)9220 bool GPUShaderFP64Test7::executeFunctionalTest(_variables &variables)
9221 {
9222     bool result = true;
9223 
9224     /* Build the test program */
9225     if (!buildTestProgram(variables))
9226     {
9227         return false;
9228     }
9229 
9230     /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9231     if (m_are_double_inputs_supported)
9232     {
9233         setInputAttributeValues(variables);
9234     }
9235 
9236     /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9237      * only, if a data mismatch is detected.
9238      */
9239     configureXFBBuffer(variables);
9240 
9241     /* Issue a draw call using the test program */
9242     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
9243 
9244     gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9245     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9246 
9247     gl.clear(GL_COLOR_BUFFER_BIT);
9248     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9249 
9250     gl.useProgram(m_po_id);
9251     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9252 
9253     gl.viewport(0, /* x */
9254                 0, /* y */
9255                 m_to_width, m_to_height);
9256     GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9257 
9258     gl.beginTransformFeedback(GL_TRIANGLES);
9259     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9260     {
9261         gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9262         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9263     }
9264     gl.endTransformFeedback();
9265     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9266 
9267     /* Verify color attachment contents */
9268     const float epsilon = 1.0f / 255.0f;
9269 
9270     gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9271     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9272 
9273     for (unsigned int y = 0; y < m_to_height; ++y)
9274     {
9275         const unsigned char *row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9276 
9277         for (unsigned int x = 0; x < m_to_width; ++x)
9278         {
9279             const unsigned char *pixel_ptr = row_ptr + 4 /* rgba */ * x;
9280 
9281             if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9282                 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9283             {
9284                 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9285                                    << ")"
9286                                       "; expected:(0, 255, 0, 0), found: ("
9287                                    << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9288                                    << ", " << (int)pixel_ptr[3]
9289                                    << "), with the following variable types used as varyings:"
9290                                    << tcu::TestLog::EndMessage;
9291 
9292                 /* List the variable types that failed the test */
9293                 const size_t n_variables = variables.size();
9294 
9295                 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9296                 {
9297                     m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9298                                        << Utils::getVariableTypeString(variables[n_variable].type)
9299                                        << " (array size:" << variables[n_variable].array_size << ")"
9300                                        << tcu::TestLog::EndMessage;
9301                 } /* for (all variable types) */
9302 
9303                 /* Log the variable contents */
9304                 logVariableContents(variables);
9305 
9306                 /* Log shaders used for the iteration */
9307                 m_testCtx.getLog() << tcu::TestLog::Message
9308                                    << "Shaders used:\n"
9309                                       "\n"
9310                                       "(VS):\n"
9311                                    << m_current_vs_body.c_str() << "\n"
9312                                    << "(TC):\n"
9313                                       "\n"
9314                                    << m_current_tc_body.c_str()
9315                                    << "\n"
9316                                       "(TE):\n"
9317                                       "\n"
9318                                    << m_current_te_body.c_str()
9319                                    << "\n"
9320                                       "(GS):\n"
9321                                    << m_current_gs_body.c_str()
9322                                    << "\n"
9323                                       "(FS):\n"
9324                                       "\n"
9325                                    << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9326 
9327                 result = false;
9328 
9329                 goto end;
9330             }
9331         } /* for (all columns) */
9332     }     /* for (all rows) */
9333 
9334 /* All done! */
9335 end:
9336     return result;
9337 }
9338 
9339 /** Takes user-input vector of test variables and allocates & fills an array of strings
9340  *  holding names of geometry shader stage varyings that should be captured during
9341  *  transform feedback operation. The array will be stored in m_xfb_varyings.
9342  *
9343  *  @param variables Holds all test variable descriptors to be used for the iteration.
9344  */
generateXFBVaryingNames(const _variables & variables)9345 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables &variables)
9346 {
9347     unsigned int n_variable = 0;
9348     unsigned int n_varying  = 0;
9349     unsigned int n_varyings = 0;
9350 
9351     if (m_xfb_varyings != NULL)
9352     {
9353         releaseXFBVaryingNames();
9354     }
9355 
9356     for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9357          ++variables_iterator)
9358     {
9359         const _variable &variable = *variables_iterator;
9360 
9361         n_varyings += variable.array_size;
9362     }
9363 
9364     m_xfb_varyings = new glw::GLchar *[n_varyings];
9365 
9366     for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9367          ++variables_iterator, ++n_variable)
9368     {
9369         const _variable &variable = *variables_iterator;
9370 
9371         for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9372         {
9373             std::stringstream varying_sstream;
9374             size_t varying_length;
9375 
9376             varying_sstream << "gs_variable" << n_variable;
9377 
9378             if (variable.array_size > 1)
9379             {
9380                 varying_sstream << "[" << array_index << "]";
9381             }
9382 
9383             /* Store the varying name */
9384             varying_length            = varying_sstream.str().length();
9385             m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9386 
9387             memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9388             m_xfb_varyings[n_varying][varying_length] = 0;
9389         } /* for (all array indices) */
9390     }     /* for (all varyings) */
9391 
9392     m_n_xfb_varyings = n_varyings;
9393 }
9394 
9395 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9396  *  without using the "flat" keyword. (case c) )
9397  *
9398  *  @param input_variable_type Variable type to use for input variable declaration.
9399  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9400  *                             of the arrayed variable.
9401  *
9402  *  @return Requested string.
9403  **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9404 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9405     Utils::_variable_type input_variable_type, unsigned int array_size)
9406 {
9407     std::stringstream result_sstream;
9408     std::stringstream array_index_stringstream;
9409     std::stringstream array_size_stringstream;
9410 
9411     if (array_size > 1)
9412     {
9413         array_index_stringstream << "[0]";
9414         array_size_stringstream << "[" << array_size << "]";
9415     }
9416 
9417     if (Utils::isMatrixVariableType(input_variable_type))
9418     {
9419         array_index_stringstream << "[0].x";
9420     }
9421     else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9422     {
9423         array_index_stringstream << "[0]";
9424     }
9425 
9426     result_sstream << "#version 400\n"
9427                       "\n"
9428                       "in "
9429                    << Utils::getVariableTypeString(input_variable_type) << " test_input"
9430                    << array_size_stringstream.str()
9431                    << ";\n"
9432                       "\n"
9433                       "out float test_output;\n"
9434                       "\n"
9435                       "void main()\n"
9436                       "{\n"
9437                       "    if (test_input"
9438                    << array_index_stringstream.str()
9439                    << " > 2.0)\n"
9440                       "    {\n"
9441                       "        test_output = 1.0;\n"
9442                       "    }\n"
9443                       "    else\n"
9444                       "    {\n"
9445                       "        test_output = 3.0;\n"
9446                       "    }\n"
9447                       "}\n";
9448 
9449     return result_sstream.str();
9450 }
9451 
9452 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9453  *
9454  *  @param input_variable_type Variable type to use for input variable declaration.
9455  *  @param array_size          1 if the variable should not be arrayed; otherwise defines size
9456  *                             of the arrayed variable.
9457  *
9458  *  @return Requested string.
9459  **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9460 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9461     Utils::_variable_type output_variable_type, unsigned int array_size)
9462 {
9463     std::stringstream array_index_sstream;
9464     std::stringstream array_size_sstream;
9465     std::stringstream result_sstream;
9466     std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9467 
9468     if (array_size > 1)
9469     {
9470         array_index_sstream << "[0]";
9471         array_size_sstream << "[" << array_size << "]";
9472     }
9473 
9474     result_sstream << "#version 400\n"
9475                       "\n"
9476                       "out "
9477                    << output_variable_type_string << " test_output" << array_size_sstream.str()
9478                    << ";\n"
9479                       "\n"
9480                       "void main()\n"
9481                       "{\n"
9482                       "    test_output"
9483                    << array_index_sstream.str() << " = " << output_variable_type_string
9484                    << "(2.0);\n"
9485                       "}\n";
9486 
9487     return result_sstream.str();
9488 }
9489 
9490 /** Retrieves body of a fragment shader that uses user-specified set of variables
9491  *  to declare contents of input & output block.
9492  *
9493  *  @param variables As per description.
9494  *
9495  *  @return Requested string.
9496  **/
getFragmentShaderBody(const _variables & variables)9497 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables &variables)
9498 {
9499     std::stringstream result_sstream;
9500 
9501     /* Form the pre-amble */
9502     result_sstream << "#version 400\n"
9503                       "\n"
9504 
9505                    /* Add input block */
9506                    << "in GS_DATA\n"
9507                       "{\n"
9508                    << getVariableDeclarations("gs", variables, "flat")
9509                    << "};\n"
9510                       "\n"
9511 
9512                    /* Add output variable */
9513                    << "out vec4 result;\n"
9514                       "\n"
9515 
9516                       /* Add main() definition */
9517                       "void main()\n"
9518                       "{\n"
9519                       "const double epsilon = 1e-5;\n"
9520                       "\n"
9521                       "result = vec4(1, 0, 0, 0);\n"
9522                       "\n";
9523 
9524     /* Determine expected values first */
9525     unsigned int base_counter = 1;
9526     const size_t n_variables  = variables.size();
9527 
9528     for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9529     {
9530         unsigned int variable_array_size        = variables[n_variable].array_size;
9531         Utils::_variable_type variable_type     = variables[n_variable].type;
9532         unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9533         std::string variable_type_string        = Utils::getVariableTypeString(variable_type);
9534 
9535         std::stringstream array_size_sstream;
9536 
9537         if (variable_array_size > 1)
9538         {
9539             array_size_sstream << "[" << variable_array_size << "]";
9540         }
9541 
9542         /* Local variable declaration */
9543         result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9544                        << ";\n"
9545                           "\n";
9546 
9547         /* Set expected values */
9548         for (unsigned int index = 0; index < variable_array_size; ++index)
9549         {
9550             std::stringstream array_index_sstream;
9551 
9552             if (variable_array_size > 1)
9553             {
9554                 array_index_sstream << "[" << index << "]";
9555             }
9556 
9557             result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9558                            << variable_type_string << "(";
9559 
9560             for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9561             {
9562                 unsigned int expected_value =
9563                     (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9564 
9565                 if (m_are_double_inputs_supported)
9566                 {
9567                     /* VS input attributes */
9568                     //expected_value += (base_counter + 6);
9569                     expected_value -= 1;
9570                 }
9571 
9572                 result_sstream << expected_value;
9573 
9574                 if (n_component != (n_variable_type_components - 1))
9575                 {
9576                     result_sstream << ", ";
9577                 }
9578 
9579                 ++base_counter;
9580             } /* for (all components) */
9581 
9582             result_sstream << ");\n";
9583         } /* for (all array indices) */
9584 
9585         result_sstream << "\n";
9586     } /* for (all variable types) */
9587 
9588     /* Now that we know the expected values, do a huge conditional check to verify if all
9589      * input variables carry correct information.
9590      */
9591     result_sstream << "if (";
9592 
9593     for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9594     {
9595         unsigned int variable_array_size        = variables[n_variable].array_size;
9596         Utils::_variable_type variable_type     = variables[n_variable].type;
9597         bool is_variable_type_matrix            = Utils::isMatrixVariableType(variable_type);
9598         unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9599         std::string variable_type_string        = Utils::getVariableTypeString(variable_type);
9600 
9601         for (unsigned int index = 0; index < variable_array_size; ++index)
9602         {
9603             std::stringstream array_index_sstream;
9604 
9605             if (variable_array_size > 1)
9606             {
9607                 array_index_sstream << "[" << index << "]";
9608             }
9609 
9610             for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9611             {
9612                 std::stringstream component_index_sstream;
9613 
9614                 if (n_variable_type_components > 1)
9615                 {
9616                     component_index_sstream << "[" << n_component << "]";
9617                 }
9618 
9619                 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9620 
9621                 if (is_variable_type_matrix)
9622                 {
9623                     const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9624                     const unsigned int column    = n_component % n_columns;
9625                     const unsigned int row       = n_component / n_columns;
9626 
9627                     result_sstream << "[" << column
9628                                    << "]"
9629                                       "."
9630                                    << Utils::getComponentAtIndex(row);
9631                 }
9632                 else
9633                 {
9634                     result_sstream << component_index_sstream.str();
9635                 }
9636 
9637                 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9638 
9639                 if (is_variable_type_matrix)
9640                 {
9641                     const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9642                     const unsigned int column    = n_component % n_columns;
9643                     const unsigned int row       = n_component / n_columns;
9644 
9645                     result_sstream << "[" << column
9646                                    << "]"
9647                                       "."
9648                                    << Utils::getComponentAtIndex(row);
9649                 }
9650                 else
9651                 {
9652                     result_sstream << component_index_sstream.str();
9653                 }
9654 
9655                 result_sstream << ") <= epsilon &&";
9656             } /* for (all components) */
9657         }     /* for (all array indices) */
9658     }         /* for (all variable types) */
9659 
9660     result_sstream << "true)\n"
9661                       "{\n"
9662                       "    result = vec4(0, 1, 0, 0);\n"
9663                       "}\n"
9664                       "}\n";
9665 
9666     /* All done */
9667     return result_sstream.str();
9668 }
9669 
9670 /** Retrieves body of a geometry shader that uses user-specified set of variables
9671  *  to declare contents of input & output block.
9672  *
9673  *  @param variables As per description.
9674  *
9675  *  @return Requested string.
9676  **/
getGeometryShaderBody(const _variables & variables)9677 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables &variables)
9678 {
9679     std::stringstream result_sstream;
9680 
9681     /* Form the pre-amble */
9682     result_sstream << "#version 400\n"
9683                       "\n"
9684                       "layout(triangles)                      in;\n"
9685                       "layout(triangle_strip, max_vertices=4) out;\n"
9686                       "\n"
9687 
9688                       /* Add the input block */
9689                       "in TE_DATA\n"
9690                       "{\n"
9691                    << getVariableDeclarations("te", variables)
9692                    << "} in_data[];\n"
9693                       "\n"
9694 
9695                       /* Add the output block */
9696                       "out GS_DATA\n"
9697                       "{\n"
9698                    << getVariableDeclarations("gs", variables, "flat")
9699                    << "};\n"
9700                       "\n"
9701 
9702                       /* Declare main() function */
9703                       "void main()\n"
9704                       "{\n";
9705 
9706     /* Take input variables, add a predefined value and forward them to output variables */
9707     const float quad_vertices[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9708                                    1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f};
9709     const unsigned int n_quad_vertices =
9710         sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9711     const size_t n_variables = variables.size();
9712 
9713     for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9714     {
9715         unsigned int counter             = 4;
9716         const float *current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9717 
9718         for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9719         {
9720             unsigned int variable_array_size        = variables[n_variable].array_size;
9721             Utils::_variable_type variable_type     = variables[n_variable].type;
9722             unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9723             std::string variable_type_string        = Utils::getVariableTypeString(variable_type);
9724 
9725             for (unsigned int index = 0; index < variable_array_size; ++index)
9726             {
9727                 std::stringstream array_index_sstream;
9728 
9729                 if (variable_array_size > 1)
9730                 {
9731                     array_index_sstream << "[" << index << "]";
9732                 }
9733 
9734                 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9735                                << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9736                                << variable_type_string << "(";
9737 
9738                 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9739                 {
9740                     result_sstream << (counter++);
9741 
9742                     if (n_component != (n_variable_type_components - 1))
9743                     {
9744                         result_sstream << ", ";
9745                     }
9746                 } /* for (all components) */
9747 
9748                 result_sstream << ");\n";
9749             } /* for (all array indices) */
9750         }     /* for (all variable types) */
9751 
9752         result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9753                        << current_quad_vertex[2] << ", " << current_quad_vertex[3]
9754                        << ");\n"
9755                           "EmitVertex();\n";
9756     } /* for (all emitted quad vertices) */
9757 
9758     result_sstream << "EndPrimitive();\n"
9759                       "}\n";
9760 
9761     /* All done */
9762     return result_sstream.str();
9763 }
9764 
9765 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9766  *  to declare contents of input & output block.
9767  *
9768  *  @param variables As per description.
9769  *
9770  *  @return Requested string.
9771  **/
getTessellationControlShaderBody(const _variables & variables)9772 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables &variables)
9773 {
9774     std::stringstream result_sstream;
9775 
9776     /* Form the pre-amble */
9777     result_sstream << "#version 400\n"
9778                       "\n"
9779                       "layout (vertices=4) out;\n"
9780 
9781                       /* Declare input block */
9782                       "in VS_DATA\n"
9783                       "{\n"
9784                    << getVariableDeclarations("vs", variables)
9785                    << "} in_data[];\n"
9786 
9787                       /* Declare output block */
9788                       "out TC_DATA\n"
9789                       "{\n"
9790                    << getVariableDeclarations("tc", variables)
9791                    << "} out_data[];\n"
9792                       "\n"
9793 
9794                       /* Define main() */
9795                       "void main()\n"
9796                       "{\n"
9797                       "    gl_TessLevelInner[0] = 1;\n"
9798                       "    gl_TessLevelInner[1] = 1;\n"
9799                       "    gl_TessLevelOuter[0] = 1;\n"
9800                       "    gl_TessLevelOuter[1] = 1;\n"
9801                       "    gl_TessLevelOuter[2] = 1;\n"
9802                       "    gl_TessLevelOuter[3] = 1;\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     = 2;
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 << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9826                            << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9827                            << variable_type_string << "(";
9828 
9829             for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9830             {
9831                 result_sstream << (counter++);
9832 
9833                 if (n_component != (n_variable_type_components - 1))
9834                 {
9835                     result_sstream << ", ";
9836                 }
9837             }
9838 
9839             result_sstream << ");\n";
9840         } /* for (all array indices) */
9841     }     /* for (all variable types) */
9842 
9843     result_sstream << "}\n";
9844 
9845     /* We're done */
9846     return result_sstream.str();
9847 }
9848 
9849 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9850  *  to declare contents of input & output block.
9851  *
9852  *  @param variables As per description.
9853  *
9854  *  @return Requested string.
9855  **/
getTessellationEvaluationShaderBody(const _variables & variables)9856 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables &variables)
9857 {
9858     std::stringstream result_sstream;
9859 
9860     /* Form the pre-amble */
9861     result_sstream << "#version 400\n"
9862                       "\n"
9863                       "layout(quads) in;\n"
9864                       "\n"
9865 
9866                       /* Define input block */
9867                       "in TC_DATA\n"
9868                       "{\n"
9869                    << getVariableDeclarations("tc", variables)
9870                    << "} in_data[];\n"
9871                       "\n"
9872 
9873                       /* Define output block */
9874                       "out TE_DATA\n"
9875                       "{\n"
9876                    << getVariableDeclarations("te", variables)
9877                    << "};\n"
9878                       "\n"
9879 
9880                       /* Define main() */
9881                       "void main()\n"
9882                       "{\n";
9883 
9884     /* Take input variables, add a predefined value and forward them to output variables */
9885     const size_t n_variables = variables.size();
9886     unsigned int counter     = 3;
9887 
9888     for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9889     {
9890         unsigned int variable_array_size        = variables[n_variable].array_size;
9891         Utils::_variable_type variable_type     = variables[n_variable].type;
9892         unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9893         std::string variable_type_string        = Utils::getVariableTypeString(variable_type);
9894 
9895         for (unsigned int index = 0; index < variable_array_size; ++index)
9896         {
9897             std::stringstream array_index_sstream;
9898 
9899             if (variable_array_size > 1)
9900             {
9901                 array_index_sstream << "[" << index << "]";
9902             }
9903 
9904             result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9905                            << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9906 
9907             for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9908             {
9909                 result_sstream << (counter++);
9910 
9911                 if (n_component != (n_variable_type_components - 1))
9912                 {
9913                     result_sstream << ", ";
9914                 }
9915             } /* for (all components) */
9916 
9917             result_sstream << ");\n";
9918         } /* for (all array indices) */
9919     }     /* for (all variable types) */
9920 
9921     result_sstream << "}\n";
9922 
9923     /* All done */
9924     return result_sstream.str();
9925 }
9926 
9927 /** Returns a string containing declarations of user-specified set of variables.
9928  *  Each declaration can optionally use a layot qualifier requested by the caller.
9929  *
9930  *  @param prefix             Prefix to use for variable names.
9931  *  @param variables          List of variables to declare in the result string.
9932  *  @param explicit_locations true if each declaration should explicitly define location
9933  *                            of the variable ( eg. (layout location=X) )
9934  *  @param layout_qualifier   Optional qualifier to use for the declaration. Must not
9935  *                            be NULL.
9936  *
9937  *  @return Requested string.
9938  **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9939 std::string GPUShaderFP64Test7::getVariableDeclarations(const char *prefix, const _variables &variables,
9940                                                         const char *layout_qualifier)
9941 {
9942     std::stringstream result_sstream;
9943 
9944     /* Define output variables */
9945     const size_t n_variables = variables.size();
9946 
9947     for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9948     {
9949         unsigned int variable_array_size    = variables[n_variable].array_size;
9950         Utils::_variable_type variable_type = variables[n_variable].type;
9951         std::string variable_type_string    = Utils::getVariableTypeString(variable_type);
9952 
9953         result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9954 
9955         if (variable_array_size > 1)
9956         {
9957             result_sstream << "[" << variable_array_size << "]";
9958         }
9959 
9960         result_sstream << ";\n";
9961     } /* for (all user-specified variable types) */
9962 
9963     return result_sstream.str();
9964 }
9965 
9966 /** Retrieves body of a vertex shader that uses user-specified set of variables
9967  *  to declare contents of input & output block.
9968  *
9969  *  @param variables As per description.
9970  *
9971  *  @return Requested string.
9972  **/
getVertexShaderBody(const _variables & variables)9973 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables &variables)
9974 {
9975     std::stringstream result_sstream;
9976 
9977     /* Form pre-amble */
9978     result_sstream << "#version 400\n"
9979                       "\n";
9980 
9981     /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9982     if (m_are_double_inputs_supported)
9983     {
9984         result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9985                        << getVariableDeclarations("in_vs", variables, "in");
9986     }
9987 
9988     /* Define output variables */
9989     result_sstream << "out VS_DATA\n"
9990                       "{\n"
9991                    << getVariableDeclarations("vs", variables);
9992 
9993     /* Define main() */
9994     result_sstream << "};\n"
9995                       "\n"
9996                       "void main()\n"
9997                       "{\n";
9998 
9999     /* Set output variable values */
10000     unsigned int counter     = 1;
10001     const size_t n_variables = variables.size();
10002 
10003     for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
10004     {
10005         unsigned int variable_array_size              = variables[n_variable].array_size;
10006         Utils::_variable_type variable_type           = variables[n_variable].type;
10007         const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
10008         std::string variable_type_string              = Utils::getVariableTypeString(variable_type);
10009 
10010         for (unsigned int index = 0; index < variable_array_size; ++index)
10011         {
10012             if (variable_array_size == 1)
10013             {
10014                 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
10015             }
10016             else
10017             {
10018                 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
10019                                << " = " << variable_type_string << "(";
10020             }
10021 
10022             for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
10023             {
10024                 result_sstream << (double)(counter++);
10025 
10026                 /* Use input attributes, if available */
10027                 if (m_are_double_inputs_supported)
10028                 {
10029                     result_sstream << " + in_vs_variable" << n_variable;
10030 
10031                     if (variable_array_size > 1)
10032                     {
10033                         result_sstream << "[" << index << "]";
10034                     }
10035 
10036                     if (Utils::isMatrixVariableType(variables[n_variable].type))
10037                     {
10038                         const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
10039                         const unsigned int column    = n_component % n_columns;
10040                         const unsigned int row       = n_component / n_columns;
10041 
10042                         result_sstream << "[" << (column)
10043                                        << "]"
10044                                           "."
10045                                        << Utils::getComponentAtIndex(row);
10046                     }
10047                     else if (n_variable_type_components > 1)
10048                     {
10049                         result_sstream << "[" << n_component << "]";
10050                     }
10051                 }
10052 
10053                 if (n_component != (n_variable_type_components - 1))
10054                 {
10055                     result_sstream << ", ";
10056                 }
10057             } /* for (all components) */
10058 
10059             result_sstream << ");\n";
10060         }
10061     } /* for (all variable types) */
10062 
10063     /* We will be using geometry shader to lay out the actual vertices so
10064      * the only thing we need to make sure is that the vertex never gets
10065      * culled.
10066      */
10067     result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
10068                       "}\n";
10069 
10070     /* That's it */
10071     return result_sstream.str();
10072 }
10073 
10074 /** Initializes shader objects required to run the test. */
initTest()10075 void GPUShaderFP64Test7::initTest()
10076 {
10077     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10078 
10079     /* Are double-precision input variables supported? */
10080     m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
10081 
10082     /* Create a vertex array object */
10083     gl.genVertexArrays(1, &m_vao_id);
10084     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
10085 
10086     gl.bindVertexArray(m_vao_id);
10087     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
10088 
10089     /* Create a texture object we will use as FBO's color attachment */
10090     gl.genTextures(1, &m_to_id);
10091     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
10092 
10093     gl.bindTexture(GL_TEXTURE_2D, m_to_id);
10094     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
10095 
10096     gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
10097     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
10098 
10099     /* Allocate temporary buffer to hold the texture data we will be reading
10100      * from color attachment. */
10101     m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
10102 
10103     /* Create and set up a framebuffer object */
10104     gl.genFramebuffers(1, &m_fbo_id);
10105     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
10106 
10107     gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
10108     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
10109 
10110     gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10111     GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10112 
10113     /* Create all shader objects */
10114     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10115     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10116     m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10117     m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10118     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10119     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10120 
10121     /* Create test program object */
10122     m_po_id = gl.createProgram();
10123     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10124 
10125     /* Attach the shaders to the program object */
10126     gl.attachShader(m_po_id, m_fs_id);
10127     gl.attachShader(m_po_id, m_gs_id);
10128     gl.attachShader(m_po_id, m_tc_id);
10129     gl.attachShader(m_po_id, m_te_id);
10130     gl.attachShader(m_po_id, m_vs_id);
10131     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10132 
10133     /* The test passes double-precision values through the whole rendering pipeline.
10134      * This translates to a notable amount of components that we would need to transfer
10135      * all values in one fell swoop. The number is large enough to exceed minimum
10136      * capabilities as described for OpenGL 4.0 implementations.
10137      * For that reason, the test executes in turns. Each turn is allocated as many
10138      * double-precision scalar/matrix values as supported by the tested GL implementation.
10139      */
10140     glw::GLint gl_max_fragment_input_components_value                 = 0;
10141     glw::GLint gl_max_geometry_input_components_value                 = 0;
10142     glw::GLint gl_max_geometry_output_components_value                = 0;
10143     glw::GLint gl_max_tess_control_input_components_value             = 0;
10144     glw::GLint gl_max_tess_control_output_components_value            = 0;
10145     glw::GLint gl_max_tess_evaluation_input_components_value          = 0;
10146     glw::GLint gl_max_tess_evaluation_output_components_value         = 0;
10147     glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10148     glw::GLint gl_max_vertex_output_components_value                  = 0;
10149 
10150     gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10151     gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10152     gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10153     gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10154     gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10155     gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10156     gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10157     gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10158                    &gl_max_transform_feedback_interleaved_components_value);
10159     gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10160     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10161 
10162     m_n_max_components_per_stage =
10163         de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10164     m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10165     m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10166     m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10167     m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10168     m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10169     m_n_max_components_per_stage =
10170         de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10171     m_n_max_components_per_stage =
10172         de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10173 
10174     /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10175      * the input patch */
10176     gl.patchParameteri(GL_PATCH_VERTICES, 1);
10177 
10178     GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10179 
10180     /* Initialize a BO we will use to hold XFB data */
10181     gl.genBuffers(1, &m_xfb_bo_id);
10182     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10183 
10184     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10185     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10186 
10187     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10188     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10189 }
10190 
10191 /** Executes test iteration.
10192  *
10193  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10194  */
iterate()10195 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10196 {
10197     /* Do not execute the test if GL_ARB_texture_view is not supported */
10198     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10199     {
10200         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10201     }
10202 
10203     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10204     {
10205         throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10206     }
10207 
10208     /* Initialize GL objects required to run the test */
10209     initTest();
10210 
10211     /* Check the negative cases first */
10212     const Utils::_variable_type double_variable_types[] = {
10213         Utils::VARIABLE_TYPE_DOUBLE,  Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10214         Utils::VARIABLE_TYPE_DVEC4,   Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10215         Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10216         Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10217         Utils::VARIABLE_TYPE_DMAT4X3,
10218     };
10219     const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10220 
10221     for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10222          ++n_double_variable_type)
10223     {
10224         for (unsigned int array_size = 1; array_size < 3; ++array_size)
10225         {
10226             Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10227 
10228             if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10229             {
10230                 m_testCtx.getLog() << tcu::TestLog::Message
10231                                    << "A fragment shader with double-precision output variable compiled successfully."
10232                                    << tcu::TestLog::EndMessage;
10233 
10234                 m_has_test_passed = false;
10235             }
10236 
10237             if (compileShader(m_fs_id,
10238                               getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10239             {
10240                 m_testCtx.getLog()
10241                     << tcu::TestLog::Message
10242                     << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10243                        " compiled successfully."
10244                     << tcu::TestLog::EndMessage;
10245 
10246                 m_has_test_passed = false;
10247             }
10248         }
10249     } /* for (all variable types) */
10250 
10251     /* Execute functional test. Split the run into as many iterations as necessary
10252      * so that we do not exceed GL implementation's capabilities. */
10253     unsigned int n_tested_variables = 0;
10254     _variables variables_to_test;
10255 
10256     while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10257     {
10258         glw::GLint total_n_used_components = 0;
10259 
10260         /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10261          * of varying components that can be used for all shadr stages.
10262          */
10263         while (total_n_used_components < m_n_max_components_per_stage &&
10264                n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10265         {
10266             _variable new_variable;
10267             unsigned int n_type_components = 0;
10268             glw::GLint n_used_components   = 0;
10269 
10270             new_variable.array_size =
10271                 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10272             new_variable.type = double_variable_types[n_tested_variables / 2];
10273 
10274             /* Double-precision varyings can use twice as many components as single-precision FPs */
10275             n_type_components = 4 /* components per location */ *
10276                                 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10277             n_used_components = n_type_components * new_variable.array_size * 2;
10278 
10279             /* Do we have enough space? */
10280             if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10281             {
10282                 if (n_used_components > m_n_max_components_per_stage)
10283                 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10284                     n_tested_variables++;
10285                 }
10286                 break;
10287             }
10288 
10289             /* We can safely test the type in current iteration */
10290             total_n_used_components += n_used_components;
10291             n_tested_variables++;
10292 
10293             variables_to_test.push_back(new_variable);
10294         }
10295 
10296         if (variables_to_test.size() > 0)
10297         {
10298             m_has_test_passed &= executeFunctionalTest(variables_to_test);
10299 
10300             variables_to_test.clear();
10301         }
10302     }
10303 
10304     /* We're done */
10305     if (m_has_test_passed)
10306     {
10307         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10308     }
10309     else
10310     {
10311         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10312     }
10313 
10314     return STOP;
10315 }
10316 
10317 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10318 void GPUShaderFP64Test7::logVariableContents(const _variables &variables)
10319 {
10320     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10321     std::stringstream log_sstream;
10322 
10323     log_sstream << "Test variable values as retrieved from geometry shader:\n";
10324 
10325     /* Map the XFB BO contents into process space */
10326     const void *xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10327 
10328     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10329 
10330     /* Read the variable contents. We only care about the set of varyings emitted
10331      * for first vertex in the geometry shader */
10332     unsigned int n_varying             = 0;
10333     const unsigned char *traveller_ptr = (const unsigned char *)xfb_bo_data;
10334 
10335     for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10336          ++variables_iterator, ++n_varying)
10337     {
10338         const _variable &variable                       = *variables_iterator;
10339         const Utils::_variable_type &base_variable_type = Utils::getBaseVariableType(variable.type);
10340         const unsigned int n_components                 = Utils::getNumberOfComponentsForVariableType(variable.type);
10341 
10342         for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10343         {
10344             log_sstream << "gs_variable" << n_varying;
10345 
10346             if (variable.array_size > 1)
10347             {
10348                 log_sstream << "[" << array_index << "]";
10349             }
10350 
10351             log_sstream << ": (";
10352 
10353             for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10354             {
10355                 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10356 
10357                 if (n_component != (n_components - 1))
10358                 {
10359                     log_sstream << ", ";
10360                 }
10361 
10362                 traveller_ptr += sizeof(double);
10363             }
10364 
10365             log_sstream << ")\n";
10366         } /* for (all array indices) */
10367     }     /* for (all variables) */
10368 
10369     /* Unmap the BO */
10370     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10371     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10372 
10373     /* Pass the logged stream into the framework */
10374     m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10375 }
10376 
10377 /** De-allocates an arary holding strings representing names of varyings that
10378  *  should be used for transform feed-back.
10379  **/
releaseXFBVaryingNames()10380 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10381 {
10382     for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10383     {
10384         delete[] m_xfb_varyings[n_varying];
10385     }
10386 
10387     delete[] m_xfb_varyings;
10388     m_xfb_varyings = DE_NULL;
10389 
10390     m_n_xfb_varyings = 0;
10391 }
10392 
10393 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10394  *  Takes a list of test variables used for current iteration and assigns increasing values
10395  *  to subsequent input attributes of the test program.
10396  *
10397  *  @param variables Test variables of the current iteration.
10398  */
setInputAttributeValues(const _variables & variables)10399 void GPUShaderFP64Test7::setInputAttributeValues(const _variables &variables)
10400 {
10401     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10402 
10403     for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10404          variable_iterator++)
10405     {
10406         const _variable &variable             = *variable_iterator;
10407         const bool is_matrix_type             = Utils::isMatrixVariableType(variable.type);
10408         const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10409         unsigned int n_components             = 0;
10410         unsigned int n_columns                = 1;
10411 
10412         if (is_matrix_type)
10413         {
10414             n_columns    = Utils::getNumberOfColumnsForVariableType(variable.type);
10415             n_components = n_total_components / n_columns;
10416 
10417             DE_ASSERT(n_total_components % n_columns == 0);
10418         }
10419         else
10420         {
10421             n_components = n_total_components;
10422         }
10423 
10424         DE_ASSERT(n_components >= 1 && n_components <= 4);
10425 
10426         for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10427         {
10428             const double data[] = {-1, -1, -1, -1};
10429 
10430             switch (n_components)
10431             {
10432             case 1:
10433             {
10434                 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10435                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10436 
10437                 break;
10438             }
10439 
10440             case 2:
10441             {
10442                 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10443                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10444 
10445                 break;
10446             }
10447 
10448             case 3:
10449             {
10450                 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10451                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10452 
10453                 break;
10454             }
10455 
10456             case 4:
10457             {
10458                 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10459                 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10460 
10461                 break;
10462             }
10463 
10464             default:
10465             {
10466                 TCU_FAIL("Unrecognized number of components");
10467             }
10468             } /* switch (n_components) */
10469 
10470             /* Make sure VAAs are disabled */
10471             gl.disableVertexAttribArray(variable.attribute_location + index);
10472             GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10473         } /* for (all array indices) */
10474     }     /* for (all variables) */
10475 }
10476 
10477 /** Constructor
10478  *
10479  *  @param context Rendering context.
10480  */
GPUShaderFP64Test8(deqp::Context & context)10481 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context &context)
10482     : TestCase(context, "valid_constructors",
10483                "Verifies that valid double-precision floating-point constructors "
10484                "are accepted during compilation stage")
10485     , m_cs_id(0)
10486     , m_fs_id(0)
10487     , m_gs_id(0)
10488     , m_tc_id(0)
10489     , m_te_id(0)
10490     , m_vs_id(0)
10491     , m_has_test_passed(true)
10492 {
10493 }
10494 
10495 /** Deinitializes all buffers and GL objects that may have been generated
10496  *  during test execution.
10497  **/
deinit()10498 void GPUShaderFP64Test8::deinit()
10499 {
10500     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
10501 
10502     if (m_cs_id != 0)
10503     {
10504         gl.deleteShader(m_cs_id);
10505 
10506         m_cs_id = 0;
10507     }
10508 
10509     if (m_fs_id != 0)
10510     {
10511         gl.deleteShader(m_fs_id);
10512 
10513         m_fs_id = 0;
10514     }
10515 
10516     if (m_gs_id != 0)
10517     {
10518         gl.deleteShader(m_gs_id);
10519 
10520         m_gs_id = 0;
10521     }
10522 
10523     if (m_tc_id != 0)
10524     {
10525         gl.deleteShader(m_tc_id);
10526 
10527         m_tc_id = 0;
10528     }
10529 
10530     if (m_te_id != 0)
10531     {
10532         gl.deleteShader(m_te_id);
10533 
10534         m_te_id = 0;
10535     }
10536 
10537     if (m_vs_id != 0)
10538     {
10539         gl.deleteShader(m_vs_id);
10540 
10541         m_vs_id = 0;
10542     }
10543 }
10544 
10545 /** Executes a single test case.
10546  *
10547  *  This function can throw TestError exceptions if GL implementation reports
10548  *  an error.
10549  *
10550  *  @param test_case Test case descriptor.
10551  *
10552  *  @return true if test case passed, false otherwise.
10553  **/
executeIteration(const _test_case & test_case)10554 bool GPUShaderFP64Test8::executeIteration(const _test_case &test_case)
10555 {
10556     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
10557     const glw::GLuint so_ids[]  = {m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id};
10558     const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
10559     bool result                 = true;
10560     const char *stage_body      = NULL;
10561     const char *stage_name      = NULL;
10562 
10563     for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10564     {
10565         const glw::GLuint so_id = so_ids[n_so_id];
10566 
10567         /* Skip compute shader if it is not supported */
10568         if (0 == so_id)
10569         {
10570             continue;
10571         }
10572 
10573         /* Compile the shader */
10574         gl.compileShader(so_id);
10575         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10576 
10577         /* Has the compilation succeeded as expected? */
10578         glw::GLint compile_status = GL_FALSE;
10579 
10580         gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10581         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10582 
10583         if (compile_status == GL_FALSE)
10584         {
10585             /* What is the current stage's name? */
10586             if (so_id == m_cs_id)
10587             {
10588                 stage_body = test_case.cs_shader_body.c_str();
10589                 stage_name = "Compute shader";
10590             }
10591             else if (so_id == m_fs_id)
10592             {
10593                 stage_body = test_case.fs_shader_body.c_str();
10594                 stage_name = "Fragment shader";
10595             }
10596             else if (so_id == m_gs_id)
10597             {
10598                 stage_body = test_case.gs_shader_body.c_str();
10599                 stage_name = "Geometry shader";
10600             }
10601             else if (so_id == m_tc_id)
10602             {
10603                 stage_body = test_case.tc_shader_body.c_str();
10604                 stage_name = "Tessellation control shader";
10605             }
10606             else if (so_id == m_te_id)
10607             {
10608                 stage_body = test_case.te_shader_body.c_str();
10609                 stage_name = "Tessellation evaluation shader";
10610             }
10611             else if (so_id == m_vs_id)
10612             {
10613                 stage_body = test_case.vs_shader_body.c_str();
10614                 stage_name = "Vertex shader";
10615             }
10616             else
10617             {
10618                 /* Doesn't make much sense to throw exceptions here so.. */
10619                 stage_body = "";
10620                 stage_name = "[?]";
10621             }
10622 
10623             /* This shader should have never failed to compile! */
10624             m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10625                                << " has not compiled successfully, even though the shader is valid."
10626                                   " Following is shader's body:\n"
10627                                << stage_body << tcu::TestLog::EndMessage;
10628 
10629             result = false;
10630         }
10631     } /* for (all shader objects) */
10632 
10633     return result;
10634 }
10635 
10636 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10637  *  type.
10638  *
10639  *  @param variable_type Variable type to return valid argument lists for.
10640  **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10641 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10642     const Utils::_variable_type &variable_type)
10643 {
10644     const Utils::_variable_type matrix_types[] = {
10645         Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10646         Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10647         Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10648     };
10649     const Utils::_variable_type scalar_types[] = {Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10650                                                   Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4};
10651     const unsigned int n_matrix_types          = sizeof(matrix_types) / sizeof(matrix_types[0]);
10652     const unsigned int n_scalar_types          = sizeof(scalar_types) / sizeof(scalar_types[0]);
10653     const int n_total_components               = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10654 
10655     /* Construct the argument list tree root. Each node carries a counter that tells how many components
10656      * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10657      * any children. Otherwise, each node is assigned as many children, as there are types that could be
10658      * used to define a subsequent argument, and its counter is increased by the amount of components
10659      * described by the type.
10660      */
10661     _argument_list_tree_node root;
10662 
10663     root.n_components_used = 0;
10664     root.parent            = NULL;
10665     root.type              = variable_type;
10666 
10667     /* Fill till all leaves use up all available components */
10668     _argument_list_tree_node_queue nodes_queue;
10669 
10670     nodes_queue.push(&root);
10671 
10672     do
10673     {
10674         /* Pop the first item in the queue */
10675         _argument_list_tree_node *current_node_ptr = nodes_queue.front();
10676         nodes_queue.pop();
10677 
10678         /* Matrix variable types can be defined by a combination of non-matrix variable types OR
10679          * a single matrix variable type.
10680          *
10681          * Let's handle the latter case first.
10682          */
10683         const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10684 
10685         if (Utils::isMatrixVariableType(current_node_ptr->type))
10686         {
10687             /* Iterate through all known matrix types. All the types can be used
10688              * as a constructor, assuming only one value is used to define new matrix's
10689              * contents. */
10690             for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10691             {
10692                 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10693 
10694                 /* Construct a new child node. Since GLSL spec clearly states we must not use more
10695                  * than one constructor argument if the only argument is a matrix type, mark the node
10696                  * as if it defined all available components.
10697                  */
10698                 _argument_list_tree_node *new_subnode = new _argument_list_tree_node;
10699 
10700                 new_subnode->n_components_used = n_total_components;
10701                 new_subnode->parent            = current_node_ptr;
10702                 new_subnode->type              = new_argument_type;
10703 
10704                 /* Add the descriptor to node list but do not add it to the queue. This would be
10705                  * a redundant operation, since no new children nodes would have been assigned to
10706                  * this node anyway.
10707                  */
10708                 current_node_ptr->children.push_back(new_subnode);
10709             } /* for (all matrix types) */
10710         }     /* if (current node's type is a matrix) */
10711 
10712         /* Now for a combination of non-matrix variable types.. */
10713         if (!Utils::isMatrixVariableType(current_node_ptr->type))
10714         {
10715             /* Iterate through all known scalar types */
10716             for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10717             {
10718                 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10719                 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10720 
10721                 /* Only use the scalar type if we don't exceed the amount of components we can define
10722                  * for requested type.
10723                  */
10724                 if (n_new_argument_components <= n_components_remaining)
10725                 {
10726                     /* Form new node descriptor */
10727                     _argument_list_tree_node *new_subnode = new _argument_list_tree_node;
10728 
10729                     new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10730                     new_subnode->parent            = current_node_ptr;
10731                     new_subnode->type              = new_argument_type;
10732 
10733                     current_node_ptr->children.push_back(new_subnode);
10734                     nodes_queue.push(new_subnode);
10735                 }
10736             } /* for (all scalar types) */
10737         }     /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10738     } while (nodes_queue.size() > 0);
10739 
10740     /* To construct the argument lists, traverse the tree. Each path from root to child
10741      * gives us a single argument list.
10742      *
10743      * First, identify leaf nodes.
10744      */
10745     _argument_list_tree_nodes leaf_nodes;
10746 
10747     nodes_queue.push(&root);
10748 
10749     do
10750     {
10751         _argument_list_tree_node *current_node_ptr = nodes_queue.front();
10752         nodes_queue.pop();
10753 
10754         if (current_node_ptr->children.size() == 0)
10755         {
10756             /* This is a leaf node !*/
10757             leaf_nodes.push_back(current_node_ptr);
10758         }
10759         else
10760         {
10761             /* Throw all children nodes to the queue */
10762             const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10763 
10764             for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10765             {
10766                 nodes_queue.push(current_node_ptr->children[n_children_node]);
10767             } /* for (all children nodes) */
10768         }
10769     } while (nodes_queue.size() > 0);
10770 
10771     /* For all leaf nodes, move up the tree and construct the argument lists. */
10772     const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10773     _argument_lists result;
10774 
10775     for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10776     {
10777         _argument_list argument_list;
10778         _argument_list_tree_node *current_node_ptr = leaf_nodes[n_leaf_node];
10779 
10780         do
10781         {
10782             if (current_node_ptr != &root)
10783             {
10784                 if (argument_list.size() == 0)
10785                 {
10786                     argument_list.push_back(current_node_ptr->type);
10787                 }
10788                 else
10789                 {
10790                     argument_list.insert(argument_list.begin(), current_node_ptr->type);
10791                 }
10792             }
10793 
10794             current_node_ptr = current_node_ptr->parent;
10795         } while (current_node_ptr != NULL);
10796 
10797         result.push_back(argument_list);
10798     } /* for (all leaf nodes) */
10799 
10800     return result;
10801 }
10802 
10803 /** Retrieves body of a compute shader that should be used for the purpose of
10804  *  user-specified test case.
10805  *
10806  *  @param test_case Test case descriptor to use.
10807  *
10808  *  @return Requested string.
10809  **/
getComputeShaderBody(const _test_case & test_case)10810 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case &test_case)
10811 {
10812     std::stringstream result_sstream;
10813 
10814     /* Form the body */
10815     result_sstream << "#version 420\n"
10816                       "#extension GL_ARB_compute_shader          : require\n"
10817                       "\n"
10818                       "layout(local_size_x = 1) in;\n"
10819                       "\n"
10820                       "void main()\n"
10821                       "{\n"
10822                    << getGeneralBody(test_case) << "}\n";
10823 
10824     /* Return the body */
10825     return result_sstream.str();
10826 }
10827 
10828 /** Retrieves body of a fragment shader that should be used for the purpose of
10829  *  user-specified test case.
10830  *
10831  *  @param test_case Test case descriptor to use.
10832  *
10833  *  @return Requested string.
10834  **/
getFragmentShaderBody(const _test_case & test_case)10835 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case &test_case)
10836 {
10837     std::stringstream result_sstream;
10838 
10839     /* Form the body */
10840     result_sstream << "#version 420\n"
10841                       "\n"
10842                       "void main()\n"
10843                       "{\n"
10844                    << getGeneralBody(test_case)
10845                    << "}\n"
10846                       "\n";
10847 
10848     /* Return the body */
10849     return result_sstream.str();
10850 }
10851 
10852 /** Returns a GLSL line that defines and initializes a variable as described by
10853  *  user-specified test case descriptor.
10854  *
10855  *  @param test_case Test case descriptor to use for the query.
10856  *
10857  *  @return As per description
10858  **/
getGeneralBody(const _test_case & test_case)10859 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case &test_case)
10860 {
10861     std::stringstream result_sstream;
10862 
10863     /* Form the body */
10864     std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10865 
10866     result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10867 
10868     for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10869          argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10870     {
10871         const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10872         std::string argument_variable_type_string          = Utils::getVariableTypeString(argument_variable_type);
10873         const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10874 
10875         if (argument_list_iterator != test_case.argument_list.begin())
10876         {
10877             result_sstream << ", ";
10878         }
10879 
10880         result_sstream << argument_variable_type_string << "(";
10881 
10882         for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10883         {
10884             result_sstream << (double)(n_component + 1);
10885 
10886             if (n_component != (argument_n_components - 1))
10887             {
10888                 result_sstream << ", ";
10889             }
10890         } /* for (all argument components) */
10891 
10892         result_sstream << ")";
10893     } /* for (all arguments) */
10894 
10895     result_sstream << ");\n";
10896 
10897     return result_sstream.str();
10898 }
10899 
10900 /** Retrieves body of a geometry shader that should be used for the purpose of
10901  *  user-specified test case.
10902  *
10903  *  @param test_case Test case descriptor to use.
10904  *
10905  *  @return Requested string.
10906  **/
getGeometryShaderBody(const _test_case & test_case)10907 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case &test_case)
10908 {
10909     std::stringstream result_sstream;
10910 
10911     /* Form the body */
10912     result_sstream << "#version 420\n"
10913                       "\n"
10914                       "layout(points)                 in;\n"
10915                       "layout(max_vertices=1, points) out;\n"
10916                       "\n"
10917                       "void main()\n"
10918                       "{\n"
10919                    << getGeneralBody(test_case)
10920                    << "}\n"
10921                       "\n";
10922 
10923     /* We're done! */
10924     return result_sstream.str();
10925 }
10926 
10927 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10928  *  user-specified test case.
10929  *
10930  *  @param test_case Test case descriptor to use.
10931  *
10932  *  @return Requested string.
10933  **/
getTessellationControlShaderBody(const _test_case & test_case)10934 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case &test_case)
10935 {
10936     std::stringstream result_sstream;
10937 
10938     /* Form the body */
10939     result_sstream << "#version 420\n"
10940                       "\n"
10941                       "layout(vertices=4) out;\n"
10942                       "\n"
10943                       "void main()\n"
10944                       "{\n"
10945                    << getGeneralBody(test_case)
10946                    << "}\n"
10947                       "\n";
10948 
10949     /* Return the body */
10950     return result_sstream.str();
10951 }
10952 
10953 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10954  *  user-specified test case.
10955  *
10956  *  @param test_case Test case descriptor to use.
10957  *
10958  *  @return Requested string.
10959  **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10960 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case &test_case)
10961 {
10962     std::stringstream result_sstream;
10963 
10964     /* Form the body */
10965     result_sstream << "#version 420\n"
10966                       "\n"
10967                       "layout(isolines) in;\n"
10968                       "\n"
10969                       "void main()\n"
10970                       "{\n"
10971                    << getGeneralBody(test_case)
10972                    << "}\n"
10973                       "\n";
10974 
10975     /* Return the body */
10976     return result_sstream.str();
10977 }
10978 
10979 /** Retrieves body of a vertex shader that should be used for the purpose of
10980  *  user-specified test case.
10981  *
10982  *  @param test_case Test case descriptor to use.
10983  *
10984  *  @return Requested string.
10985  **/
getVertexShaderBody(const _test_case & test_case)10986 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case &test_case)
10987 {
10988     std::stringstream result_sstream;
10989 
10990     /* Form the body */
10991     result_sstream << "#version 420\n"
10992                       "\n"
10993                       "void main()\n"
10994                       "{\n"
10995                    << getGeneralBody(test_case)
10996                    << "}\n"
10997                       "\n";
10998 
10999     return result_sstream.str();
11000 }
11001 
11002 /** Initializes shader objects required to run the test. */
initTest()11003 void GPUShaderFP64Test8::initTest()
11004 {
11005     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
11006 
11007     /* Generate shader objects */
11008 
11009     /* Compute shader support and GL 4.2 required */
11010     if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
11011         (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
11012     {
11013         m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
11014     }
11015 
11016     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
11017     m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
11018     m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
11019     m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
11020     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11021 
11022     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
11023 }
11024 
11025 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
11026  *
11027  *  @param test_case Test case descriptor to generate the shader bodies for.
11028  **/
initIteration(_test_case & test_case)11029 void GPUShaderFP64Test8::initIteration(_test_case &test_case)
11030 {
11031     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
11032 
11033     test_case.cs_shader_body = getComputeShaderBody(test_case);
11034     test_case.fs_shader_body = getFragmentShaderBody(test_case);
11035     test_case.gs_shader_body = getGeometryShaderBody(test_case);
11036     test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
11037     test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
11038     test_case.vs_shader_body = getVertexShaderBody(test_case);
11039 
11040     /* Assign the bodies to relevant shaders */
11041     const char *cs_body_raw_ptr = test_case.cs_shader_body.c_str();
11042     const char *fs_body_raw_ptr = test_case.fs_shader_body.c_str();
11043     const char *gs_body_raw_ptr = test_case.gs_shader_body.c_str();
11044     const char *tc_body_raw_ptr = test_case.tc_shader_body.c_str();
11045     const char *te_body_raw_ptr = test_case.te_shader_body.c_str();
11046     const char *vs_body_raw_ptr = test_case.vs_shader_body.c_str();
11047 
11048     /* m_cs_id is initialized only if compute_shader is supported */
11049     if (0 != m_cs_id)
11050     {
11051         gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
11052     }
11053 
11054     gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
11055     gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
11056     gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
11057     gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
11058     gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11059     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
11060 }
11061 
11062 /** Executes test iteration.
11063  *
11064  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11065  */
iterate()11066 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
11067 {
11068     /* Do not execute the test if GL_ARB_texture_view is not supported */
11069     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11070     {
11071         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11072     }
11073 
11074     /* Initialize GL objects needed to run the tests */
11075     initTest();
11076 
11077     /* Build iteration array to run the tests in an automated manner */
11078     const Utils::_variable_type variable_types[] = {
11079         Utils::VARIABLE_TYPE_DMAT2,  Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
11080         Utils::VARIABLE_TYPE_DMAT3,  Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11081         Utils::VARIABLE_TYPE_DMAT4,  Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
11082         Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11083         Utils::VARIABLE_TYPE_DVEC4};
11084     const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11085 
11086     for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11087     {
11088         const Utils::_variable_type variable_type = variable_types[n_variable_type];
11089 
11090         /* Construct a set of argument lists valid for the variable type considered */
11091         _argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
11092 
11093         for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
11094              argument_list_iterator != argument_lists.end(); argument_list_iterator++)
11095         {
11096             /* Constructor thwe test case descriptor */
11097             _test_case test_case;
11098 
11099             test_case.argument_list = *argument_list_iterator;
11100             test_case.type          = variable_type;
11101 
11102             /* Initialize a program object we will use to perform the casting */
11103             initIteration(test_case);
11104 
11105             /* See if the shader compiles. */
11106             m_has_test_passed &= executeIteration(test_case);
11107         } /* for (all argument lists) */
11108     }     /* for (all variable types) */
11109 
11110     /* We're done */
11111     if (m_has_test_passed)
11112     {
11113         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11114     }
11115     else
11116     {
11117         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11118     }
11119 
11120     return STOP;
11121 }
11122 
11123 /** Constructor.
11124  *
11125  *  @param context Rendering context.
11126  *
11127  **/
GPUShaderFP64Test9(deqp::Context & context)11128 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context &context)
11129     : TestCase(context, "operators",
11130                "Verifies that general and relational operators work "
11131                "correctly when used against double-precision floating-"
11132                "point types.")
11133     , m_has_test_passed(true)
11134     , m_po_id(0)
11135     , m_xfb_bo_id(0)
11136     , m_vao_id(0)
11137     , m_vs_id(0)
11138 {
11139     /* Left blank intentionally */
11140 }
11141 
11142 /** Deinitializes all ES objects that may have been created during
11143  *  test execution.
11144  **/
deinit()11145 void GPUShaderFP64Test9::deinit()
11146 {
11147     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
11148 
11149     if (m_po_id != 0)
11150     {
11151         gl.deleteProgram(m_po_id);
11152 
11153         m_po_id = 0;
11154     }
11155 
11156     if (m_xfb_bo_id != 0)
11157     {
11158         gl.deleteBuffers(1, &m_xfb_bo_id);
11159 
11160         m_xfb_bo_id = 0;
11161     }
11162 
11163     if (m_vao_id != 0)
11164     {
11165         gl.deleteVertexArrays(1, &m_vao_id);
11166 
11167         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11168     }
11169 
11170     if (m_vs_id != 0)
11171     {
11172         gl.deleteShader(m_vs_id);
11173 
11174         m_vs_id = 0;
11175     }
11176 }
11177 
11178 /** Executes a single test iteration using user-specified test case properties.
11179  *
11180  *  @param test_case Test case descriptor.
11181  *
11182  *  @return true if the pass was successful, false if the test should fail.
11183  **/
executeTestIteration(const _test_case & test_case)11184 bool GPUShaderFP64Test9::executeTestIteration(const _test_case &test_case)
11185 {
11186     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
11187     bool result              = true;
11188 
11189     /* Activate the test program object */
11190     gl.useProgram(m_po_id);
11191     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11192 
11193     /* Draw a single point with XFB enabled */
11194     gl.beginTransformFeedback(GL_POINTS);
11195     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11196     {
11197         gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11198         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11199     }
11200     gl.endTransformFeedback();
11201     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11202 
11203     /* Map the XFB BO into process space */
11204     const void *xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11205 
11206     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11207 
11208     result = verifyXFBData(test_case, (const unsigned char *)xfb_data_ptr);
11209 
11210     /* Unmap the BO */
11211     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11212     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11213 
11214     return result;
11215 }
11216 
11217 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11218  *  under user-specified location.
11219  *
11220  *  @param matrix_a_type  Type of the l-side matrix.
11221  *  @param matrix_a_data  Row-ordered data of l-side matrix.
11222  *  @param matrix_b_type  Type of the r-side matrix.
11223  *  @param matrix_b_data  Row-ordered data of r-side matrix.
11224  *  @param out_result_ptr Deref to be used to store the multiplication result.
11225  **/
getMatrixMultiplicationResult(const Utils::_variable_type & matrix_a_type,const std::vector<double> & matrix_a_data,const Utils::_variable_type & matrix_b_type,const std::vector<double> & matrix_b_data,double * out_result_ptr)11226 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type &matrix_a_type,
11227                                                        const std::vector<double> &matrix_a_data,
11228                                                        const Utils::_variable_type &matrix_b_type,
11229                                                        const std::vector<double> &matrix_b_data, double *out_result_ptr)
11230 {
11231     (void)matrix_b_type;
11232     using namespace tcu;
11233     /* To keep the code maintainable, we only consider cases relevant for this test */
11234     switch (matrix_a_type)
11235     {
11236     case Utils::VARIABLE_TYPE_DMAT2:
11237     {
11238         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11239 
11240         tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11241         tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11242         tcu::Matrix2d result;
11243 
11244         matrix_a = transpose(matrix_a);
11245         matrix_b = transpose(matrix_b);
11246         result   = matrix_a * matrix_b;
11247 
11248         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11249         break;
11250     }
11251 
11252     case Utils::VARIABLE_TYPE_DMAT2X3:
11253     {
11254         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11255 
11256         tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11257         tcu::Matrix<double, 3, 2> matrix_a_transposed;
11258         tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11259         tcu::Matrix<double, 2, 3> matrix_b_transposed;
11260         tcu::Matrix<double, 3, 3> result;
11261 
11262         matrix_a_transposed = transpose(matrix_a);
11263         matrix_b_transposed = transpose(matrix_b);
11264         result              = matrix_a_transposed * matrix_b_transposed;
11265 
11266         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11267         break;
11268     }
11269 
11270     case Utils::VARIABLE_TYPE_DMAT2X4:
11271     {
11272         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11273 
11274         tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11275         tcu::Matrix<double, 4, 2> matrix_a_transposed;
11276         tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11277         tcu::Matrix<double, 2, 4> matrix_b_transposed;
11278         tcu::Matrix<double, 4, 4> result;
11279 
11280         matrix_a_transposed = transpose(matrix_a);
11281         matrix_b_transposed = transpose(matrix_b);
11282         result              = matrix_a_transposed * matrix_b_transposed;
11283 
11284         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11285         break;
11286     }
11287 
11288     case Utils::VARIABLE_TYPE_DMAT3:
11289     {
11290         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11291 
11292         tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11293         tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11294         tcu::Matrix<double, 3, 3> result;
11295 
11296         matrix_a = transpose(matrix_a);
11297         matrix_b = transpose(matrix_b);
11298         result   = matrix_a * matrix_b;
11299 
11300         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11301         break;
11302     }
11303 
11304     case Utils::VARIABLE_TYPE_DMAT3X2:
11305     {
11306         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11307 
11308         tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11309         tcu::Matrix<double, 2, 3> matrix_a_transposed;
11310         tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11311         tcu::Matrix<double, 3, 2> matrix_b_transposed;
11312         tcu::Matrix<double, 2, 2> result;
11313 
11314         matrix_a_transposed = transpose(matrix_a);
11315         matrix_b_transposed = transpose(matrix_b);
11316         result              = matrix_a_transposed * matrix_b_transposed;
11317 
11318         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11319         break;
11320     }
11321 
11322     case Utils::VARIABLE_TYPE_DMAT3X4:
11323     {
11324         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11325 
11326         tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11327         tcu::Matrix<double, 4, 3> matrix_a_transposed;
11328         tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11329         tcu::Matrix<double, 3, 4> matrix_b_transposed;
11330         tcu::Matrix<double, 4, 4> result;
11331 
11332         matrix_a_transposed = transpose(matrix_a);
11333         matrix_b_transposed = transpose(matrix_b);
11334         result              = matrix_a_transposed * matrix_b_transposed;
11335 
11336         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11337         break;
11338     }
11339 
11340     case Utils::VARIABLE_TYPE_DMAT4:
11341     {
11342         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11343 
11344         tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11345         tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11346         tcu::Matrix<double, 4, 4> result;
11347 
11348         matrix_a = transpose(matrix_a);
11349         matrix_b = transpose(matrix_b);
11350         result   = matrix_a * matrix_b;
11351 
11352         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11353         break;
11354     }
11355 
11356     case Utils::VARIABLE_TYPE_DMAT4X2:
11357     {
11358         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11359 
11360         tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11361         tcu::Matrix<double, 2, 4> matrix_a_transposed;
11362         tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11363         tcu::Matrix<double, 4, 2> matrix_b_transposed;
11364         tcu::Matrix<double, 2, 2> result;
11365 
11366         matrix_a_transposed = transpose(matrix_a);
11367         matrix_b_transposed = transpose(matrix_b);
11368         result              = matrix_a_transposed * matrix_b_transposed;
11369 
11370         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11371         break;
11372     }
11373 
11374     case Utils::VARIABLE_TYPE_DMAT4X3:
11375     {
11376         DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11377 
11378         tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11379         tcu::Matrix<double, 3, 4> matrix_a_transposed;
11380         tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11381         tcu::Matrix<double, 4, 3> matrix_b_transposed;
11382         tcu::Matrix<double, 3, 3> result;
11383 
11384         matrix_a_transposed = transpose(matrix_a);
11385         matrix_b_transposed = transpose(matrix_b);
11386         result              = matrix_a_transposed * matrix_b_transposed;
11387 
11388         memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11389         break;
11390     }
11391 
11392     default:
11393     {
11394         TCU_FAIL("Unrecognized matrix A type");
11395     }
11396     } /* switch (matrix_a_type) */
11397 }
11398 
11399 /** Returns GLSL operator representation of the user-specified operation.
11400  *
11401  *  @param operation_type Internal operation type to retrieve the operator for.
11402  *
11403  *  @return As per description.
11404  **/
getOperatorForOperationType(const _operation_type & operation_type)11405 const char *GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type &operation_type)
11406 {
11407     const char *result = NULL;
11408 
11409     switch (operation_type)
11410     {
11411     case OPERATION_TYPE_ADDITION:
11412         result = "+";
11413         break;
11414     case OPERATION_TYPE_DIVISION:
11415         result = "/";
11416         break;
11417     case OPERATION_TYPE_MULTIPLICATION:
11418         result = "*";
11419         break;
11420     case OPERATION_TYPE_SUBTRACTION:
11421         result = "-";
11422         break;
11423 
11424     case OPERATION_TYPE_PRE_DECREMENTATION:
11425     case OPERATION_TYPE_POST_DECREMENTATION:
11426     {
11427         result = "--";
11428 
11429         break;
11430     }
11431 
11432     case OPERATION_TYPE_PRE_INCREMENTATION:
11433     case OPERATION_TYPE_POST_INCREMENTATION:
11434     {
11435         result = "++";
11436 
11437         break;
11438     }
11439 
11440     default:
11441     {
11442         TCU_FAIL("Unrecognized operation type");
11443     }
11444     } /* switch(operation_type) */
11445 
11446     return result;
11447 }
11448 
11449 /** Returns a string representing user-specified operation type.
11450  *
11451  *  @param operation_type Operation type to return the literal for.
11452  *
11453  *  @return Requested string.
11454  **/
getOperationTypeString(const _operation_type & operation_type)11455 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type &operation_type)
11456 {
11457     std::string result = "[?]";
11458 
11459     switch (operation_type)
11460     {
11461     case OPERATION_TYPE_ADDITION:
11462         result = "addition";
11463         break;
11464     case OPERATION_TYPE_DIVISION:
11465         result = "division";
11466         break;
11467     case OPERATION_TYPE_MULTIPLICATION:
11468         result = "multiplication";
11469         break;
11470     case OPERATION_TYPE_SUBTRACTION:
11471         result = "subtraction";
11472         break;
11473     case OPERATION_TYPE_PRE_DECREMENTATION:
11474         result = "pre-decrementation";
11475         break;
11476     case OPERATION_TYPE_PRE_INCREMENTATION:
11477         result = "pre-incrementation";
11478         break;
11479     case OPERATION_TYPE_POST_DECREMENTATION:
11480         result = "post-decrementation";
11481         break;
11482     case OPERATION_TYPE_POST_INCREMENTATION:
11483         result = "post-incrementation";
11484         break;
11485 
11486     default:
11487     {
11488         TCU_FAIL("Unrecognized operation type");
11489     }
11490     }
11491 
11492     return result;
11493 }
11494 
11495 /** Returns body of a vertex shader that should be used for user-specified test case
11496  *  descriptor.
11497  *
11498  *  @param test_case Test case descriptor.
11499  *
11500  *  @return Requested GLSL shader body.
11501  **/
getVertexShaderBody(_test_case & test_case)11502 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case &test_case)
11503 {
11504     std::stringstream result_sstream;
11505     std::string result_variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11506     std::string variable_type_fp_string      = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11507     std::string variable_type_string         = Utils::getVariableTypeString(test_case.variable_type);
11508     const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11509 
11510     /* If we are to multiply matrices, we will need to use a different type
11511      * for the result variable if either of the matrices is not square.
11512      */
11513     if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11514         Utils::isMatrixVariableType(test_case.variable_type))
11515     {
11516         Utils::_variable_type result_variable_type;
11517         Utils::_variable_type transposed_matrix_variable_type =
11518             Utils::getTransposedMatrixVariableType(test_case.variable_type);
11519 
11520         result_variable_type =
11521             Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11522         result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11523 
11524         test_case.result_variable_type = result_variable_type;
11525     }
11526 
11527     /* Form the pre-amble */
11528     result_sstream << "#version 400\n"
11529                       "\n"
11530 
11531                       /* Add output variables */
11532                       "out "
11533                    << result_variable_type_string
11534                    << " result;\n"
11535                       "out ivec2 result_lt;\n"
11536                       "out ivec2 result_lte;\n"
11537                       "out ivec2 result_gt;\n"
11538                       "out ivec2 result_gte;\n"
11539                       "void main()\n"
11540                       "{\n";
11541 
11542     /* Form reference values */
11543     result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11544 
11545     for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11546     {
11547         result_sstream << (n_variable_component + 1);
11548 
11549         if (n_variable_component != (n_variable_components - 1))
11550         {
11551             result_sstream << ", ";
11552         }
11553     } /* for (all variable components) */
11554 
11555     result_sstream << ");\n";
11556 
11557     for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11558          ++n_ref2_case)
11559     {
11560         Utils::_variable_type compatible_variable_type = test_case.variable_type;
11561 
11562         if (Utils::isMatrixVariableType(compatible_variable_type) &&
11563             test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11564         {
11565             compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11566         }
11567 
11568         std::string ref2_variable_type_fp_string =
11569             Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11570         std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11571         std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11572         std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11573 
11574         result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11575 
11576         for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11577              ++n_variable_component)
11578         {
11579             result_sstream << (n_variable_components - (n_variable_component + 1));
11580 
11581             if (n_variable_component != (n_variable_components - 1))
11582             {
11583                 result_sstream << ", ";
11584             }
11585         } /* for (all variable components) */
11586 
11587         result_sstream << ");\n";
11588     } /* for (both reference2 declarations) */
11589 
11590     /* Add actual body */
11591     result_sstream << "\n"
11592                       "result = ";
11593 
11594     if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11595         test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11596     {
11597         result_sstream << getOperatorForOperationType(test_case.operation_type);
11598     }
11599 
11600     result_sstream << "reference1 ";
11601 
11602     if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11603         test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11604         test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11605         test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11606     {
11607         if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11608             test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11609         {
11610             result_sstream << getOperatorForOperationType(test_case.operation_type);
11611         }
11612     }
11613     else
11614     {
11615         result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11616     }
11617 
11618     result_sstream << ";\n";
11619 
11620     if (Utils::isScalarVariableType(test_case.variable_type))
11621     {
11622         result_sstream << "result_lt [0] = (reference1 <  reference2)  ? 1 : 0;\n"
11623                           "result_lt [1] = (reference1 <  reference2f) ? 1 : 0;\n"
11624                           "result_lte[0] = (reference1 <= reference2)  ? 1 : 0;\n"
11625                           "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11626                           "result_gt [0] = (reference1 >  reference2)  ? 1 : 0;\n"
11627                           "result_gt [1] = (reference1 >  reference2f) ? 1 : 0;\n"
11628                           "result_gte[0] = (reference1 >= reference2)  ? 1 : 0;\n"
11629                           "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11630     }
11631     else
11632     {
11633         result_sstream << "result_lt [0] = 1;\n"
11634                           "result_lt [1] = 1;\n"
11635                           "result_lte[0] = 1;\n"
11636                           "result_lte[1] = 1;\n"
11637                           "result_gt [0] = 1;\n"
11638                           "result_gt [1] = 1;\n"
11639                           "result_gte[0] = 1;\n"
11640                           "result_gte[1] = 1;\n";
11641     }
11642 
11643     result_sstream << "}\n";
11644 
11645     /* All done */
11646     return result_sstream.str();
11647 }
11648 
11649 /** Initializes all GL objects required to run the test.
11650  *
11651  *  This function can throw a TestError exception if the implementation misbehaves.
11652  */
initTest()11653 void GPUShaderFP64Test9::initTest()
11654 {
11655     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
11656 
11657     /* Create program & vertex shader objects */
11658     m_po_id = gl.createProgram();
11659     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11660 
11661     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11662 
11663     /* Attach the shader to the program */
11664     gl.attachShader(m_po_id, m_vs_id);
11665     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11666 
11667     /* Set up a buffer object */
11668     gl.genBuffers(1, &m_xfb_bo_id);
11669     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11670 
11671     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11672     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11673 
11674     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11675     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11676 
11677     /* Set up a vertex array object */
11678     gl.genVertexArrays(1, &m_vao_id);
11679     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11680 
11681     gl.bindVertexArray(m_vao_id);
11682     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11683 }
11684 
11685 /** Initializes all GL objects required to run an iteration described by
11686  *  user-specified test case descriptor.
11687  *
11688  *  @param test_case Test case descriptor to use for the initialization.
11689  **/
initTestIteration(_test_case & test_case)11690 void GPUShaderFP64Test9::initTestIteration(_test_case &test_case)
11691 {
11692     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
11693     std::string vs_body         = getVertexShaderBody(test_case);
11694     const char *vs_body_raw_ptr = vs_body.c_str();
11695 
11696     /* Store the shader's body */
11697     test_case.vs_body = vs_body;
11698 
11699     /* Try to compile the shader */
11700     glw::GLint compile_status = GL_FALSE;
11701 
11702     gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11703     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11704 
11705     gl.compileShader(m_vs_id);
11706     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11707 
11708     gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11709     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11710 
11711     if (compile_status != GL_TRUE)
11712     {
11713         TCU_FAIL("Test shader compilation failed.");
11714     }
11715 
11716     /* Configure XFB */
11717     const char *xfb_names[]        = {"result", "result_lt", "result_lte", "result_gt", "result_gte"};
11718     const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11719 
11720     gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11721     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11722 
11723     /* Try to link the program */
11724     glw::GLint link_status = GL_FALSE;
11725 
11726     gl.linkProgram(m_po_id);
11727     GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11728 
11729     gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11730     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11731 
11732     if (link_status != GL_TRUE)
11733     {
11734         TCU_FAIL("Test program linking failure");
11735     }
11736 
11737     /* Set up XFB BO data storage */
11738     const unsigned int result_variable_size = static_cast<unsigned int>(
11739         Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11740     const unsigned int xfb_bo_size = static_cast<unsigned int>(
11741         result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11742 
11743     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11744     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11745 }
11746 
11747 /** Executes test iteration.
11748  *
11749  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11750  */
iterate()11751 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11752 {
11753     /* Do not execute the test if GL_ARB_texture_view is not supported */
11754     if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11755     {
11756         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11757     }
11758 
11759     /* Initialize all ES objects required to run all the checks */
11760     initTest();
11761 
11762     /* Iterate through all variable types we want to test */
11763     const Utils::_variable_type variable_types[] = {
11764         Utils::VARIABLE_TYPE_DMAT2,  Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
11765         Utils::VARIABLE_TYPE_DMAT3,  Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11766         Utils::VARIABLE_TYPE_DMAT4,  Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
11767         Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,   Utils::VARIABLE_TYPE_DVEC3,
11768         Utils::VARIABLE_TYPE_DVEC4};
11769     const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11770 
11771     for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11772     {
11773         /* Iterate through all operation types we want to check */
11774         for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11775         {
11776             _operation_type operation_type             = (_operation_type)n_operation_type;
11777             const Utils::_variable_type &variable_type = variable_types[n_variable_type];
11778 
11779             /* Construct test case descriptor */
11780             _test_case test_case;
11781 
11782             test_case.operation_type       = operation_type;
11783             test_case.result_variable_type = variable_type;
11784             test_case.variable_type        = variable_type;
11785 
11786             /* Run the iteration */
11787             initTestIteration(test_case);
11788 
11789             m_has_test_passed &= executeTestIteration(test_case);
11790         } /* for (all operation types) */
11791     }     /* for (all variable types) */
11792 
11793     /* All done. */
11794     if (m_has_test_passed)
11795     {
11796         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11797     }
11798     else
11799     {
11800         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11801     }
11802 
11803     return STOP;
11804 }
11805 
11806 /** Verifies data XFBed out by the draw call for user-specified test case
11807  *  descriptor.
11808  *
11809  *  @param test_case Test case descriptor
11810  *  @param xfb_data  Buffer holding the data XFBed out during the draw call.
11811  *                   Must not be NULL.
11812  *
11813  *  @return true if the data was found to be correct, false otherwise.
11814  **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11815 bool GPUShaderFP64Test9::verifyXFBData(const _test_case &test_case, const unsigned char *xfb_data)
11816 {
11817     const double epsilon = 1e-5;
11818     const unsigned int n_result_components =
11819         Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11820     bool result                    = true;
11821     const double *xfb_data_result  = (const double *)xfb_data;
11822     const int *xfb_data_result_lt  = (const int *)(xfb_data_result + n_result_components);
11823     const int *xfb_data_result_lte = (const int *)xfb_data_result_lt + 2;  /* cast/non-cast cases */
11824     const int *xfb_data_result_gt  = (const int *)xfb_data_result_lte + 2; /* cast/non-cast cases */
11825     const int *xfb_data_result_gte = (const int *)xfb_data_result_gt + 2;  /* cast/non-cast cases */
11826 
11827     /* Prepare reference values */
11828     int modifier;
11829     std::vector<double> reference1;
11830     std::vector<double> reference2;
11831 
11832     if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11833         test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11834     {
11835         modifier = 1;
11836     }
11837     else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11838              test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11839     {
11840         modifier = -1;
11841     }
11842     else
11843     {
11844         modifier = 0;
11845     }
11846 
11847     if (Utils::isMatrixVariableType(test_case.variable_type))
11848     {
11849         /* Matrices may be of different sizes so we need to compute the
11850          * reference values separately for each matrix
11851          */
11852         const Utils::_variable_type matrix_a_type = test_case.variable_type;
11853         const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11854         const unsigned int n_matrix_a_components  = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11855         const unsigned int n_matrix_b_components  = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11856 
11857         for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11858         {
11859             reference1.push_back(modifier + n_component + 1);
11860         }
11861 
11862         for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11863         {
11864             reference2.push_back(n_matrix_b_components - (n_component + 1));
11865         }
11866     } /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11867     else
11868     {
11869         /* Generate as many components as will be expected for the result variable */
11870         for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11871         {
11872             reference1.push_back(modifier + n_result_component + 1);
11873             reference2.push_back(n_result_components - (n_result_component + 1));
11874         }
11875     }
11876 
11877     /* Verify the result value(s) */
11878     if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11879         Utils::isMatrixVariableType(test_case.variable_type))
11880     {
11881         /* Matrix multiplication */
11882         double expected_result_data[4 * 4];
11883         Utils::_variable_type matrix_a_type = test_case.variable_type;
11884         Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11885 
11886         getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11887 
11888         for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11889         {
11890             if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11891             {
11892                 std::stringstream log_sstream;
11893 
11894                 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11895                             << Utils::getVariableTypeString(matrix_b_type)
11896                             << " matrix multiplication was incorrect; expected:(";
11897 
11898                 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11899                      ++n_logged_component)
11900                 {
11901                     log_sstream << expected_result_data[n_logged_component];
11902 
11903                     if (n_logged_component != (n_result_components - 1))
11904                     {
11905                         log_sstream << ", ";
11906                     }
11907                 } /* for (all components to be logged) */
11908 
11909                 log_sstream << "), retrieved:(";
11910 
11911                 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11912                      ++n_logged_component)
11913                 {
11914                     log_sstream << xfb_data_result[n_logged_component];
11915 
11916                     if (n_logged_component != (n_result_components - 1))
11917                     {
11918                         log_sstream << ", ";
11919                     }
11920                 } /* for (all components to be logged) */
11921 
11922                 log_sstream << ")";
11923 
11924                 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11925 
11926                 result = false;
11927                 break;
11928             }
11929         } /* for (all result components) */
11930     }     /* if (dealing with matrix multiplication) */
11931     else
11932     {
11933         for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11934         {
11935             double expected_value = reference1[n_component];
11936 
11937             switch (test_case.operation_type)
11938             {
11939             case OPERATION_TYPE_ADDITION:
11940                 expected_value += reference2[n_component];
11941                 break;
11942             case OPERATION_TYPE_DIVISION:
11943                 expected_value /= reference2[n_component];
11944                 break;
11945             case OPERATION_TYPE_MULTIPLICATION:
11946                 expected_value *= reference2[n_component];
11947                 break;
11948             case OPERATION_TYPE_SUBTRACTION:
11949                 expected_value -= reference2[n_component];
11950                 break;
11951 
11952             case OPERATION_TYPE_PRE_DECREMENTATION:
11953             case OPERATION_TYPE_PRE_INCREMENTATION:
11954             {
11955                 /* Modifier already applied */
11956                 break;
11957             }
11958 
11959             case OPERATION_TYPE_POST_DECREMENTATION:
11960             case OPERATION_TYPE_POST_INCREMENTATION:
11961             {
11962                 /* Need to reverse the modification for the purpose of the following check */
11963                 expected_value -= modifier;
11964 
11965                 break;
11966             }
11967 
11968             default:
11969             {
11970                 TCU_FAIL("Unrecognized operation type");
11971             }
11972             } /* switch (test_case.operation_type) */
11973 
11974             if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11975             {
11976                 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11977                 std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
11978 
11979                 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11980                                    << variable_type_string
11981                                    << "]"
11982                                       " and operation type ["
11983                                    << operation_type_string
11984                                    << "]"
11985                                       " were found invalid."
11986                                    << tcu::TestLog::EndMessage;
11987 
11988                 result = false;
11989                 break;
11990             } /* if (test case failed) */
11991         }     /* for (all components) */
11992     }
11993 
11994     /* Verify the comparison operation results */
11995     if (Utils::isScalarVariableType(test_case.variable_type))
11996     {
11997         DE_ASSERT(n_result_components == 1);
11998 
11999         const bool expected_result_lt[2]  = {reference1[0] < reference2[0], reference1[0] < (float)reference2[0]};
12000         const bool expected_result_lte[2] = {reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0]};
12001         const bool expected_result_gt[2]  = {reference1[0] > reference2[0], reference1[0] > (float)reference2[0]};
12002         const bool expected_result_gte[2] = {reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0]};
12003 
12004         if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
12005             (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
12006         {
12007             std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12008             std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12009 
12010             m_testCtx.getLog() << tcu::TestLog::Message
12011                                << "Values reported for lower-than operator used for "
12012                                   "variable type ["
12013                                << variable_type_string
12014                                << "]"
12015                                   "and operation type ["
12016                                << operation_type_string
12017                                << "]"
12018                                   "was found invalid; expected:("
12019                                << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
12020                                << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
12021                                << tcu::TestLog::EndMessage;
12022 
12023             result = false;
12024         }
12025 
12026         if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
12027             (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
12028         {
12029             std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12030             std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12031 
12032             m_testCtx.getLog() << tcu::TestLog::Message
12033                                << "Values reported for lower-than-or-equal operator used for "
12034                                   "variable type ["
12035                                << variable_type_string
12036                                << "]"
12037                                   "and operation type ["
12038                                << operation_type_string
12039                                << "]"
12040                                   "was found invalid; expected:("
12041                                << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
12042                                << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
12043                                << tcu::TestLog::EndMessage;
12044 
12045             result = false;
12046         }
12047 
12048         if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
12049             (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
12050         {
12051             std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12052             std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12053 
12054             m_testCtx.getLog() << tcu::TestLog::Message
12055                                << "Values reported for greater-than operator used for "
12056                                   "variable type ["
12057                                << variable_type_string
12058                                << "]"
12059                                   "and operation type ["
12060                                << operation_type_string
12061                                << "]"
12062                                   "was found invalid; expected:("
12063                                << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
12064                                << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
12065                                << tcu::TestLog::EndMessage;
12066 
12067             result = false;
12068         }
12069 
12070         if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
12071             (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
12072         {
12073             std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12074             std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12075 
12076             m_testCtx.getLog() << tcu::TestLog::Message
12077                                << "Values reported for greater-than-or-equal operator used for "
12078                                   "variable type ["
12079                                << variable_type_string
12080                                << "]"
12081                                   "and operation type ["
12082                                << operation_type_string
12083                                << "]"
12084                                   "was found invalid; expected:("
12085                                << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
12086                                << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
12087                                << tcu::TestLog::EndMessage;
12088 
12089             result = false;
12090         }
12091     } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
12092     else
12093     {
12094         if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
12095             xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
12096             xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
12097         {
12098             std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12099             std::string variable_type_string  = Utils::getVariableTypeString(test_case.variable_type);
12100 
12101             m_testCtx.getLog() << tcu::TestLog::Message
12102                                << "Invalid value was reported for matrix variable type, for which "
12103                                   " operator checks are not executed; variable type ["
12104                                << variable_type_string
12105                                << "]"
12106                                   "and operation type ["
12107                                << operation_type_string << "]" << tcu::TestLog::EndMessage;
12108 
12109             result = false;
12110         }
12111     }
12112 
12113     return result;
12114 }
12115 
12116 namespace TypeHelpers
12117 {
12118 /** Get base type for reference types
12119  *
12120  * @tparam T type
12121  **/
12122 template <typename T>
12123 class referenceToType
12124 {
12125 public:
12126     typedef T result;
12127 };
12128 
12129 template <typename T>
12130 class referenceToType<const T &>
12131 {
12132 public:
12133     typedef T result;
12134 };
12135 
12136 /** Maps variable type with enumeration Utils::_variable_type
12137  *
12138  * @tparam T type
12139  **/
12140 template <typename T>
12141 class typeInfo;
12142 
12143 template <>
12144 class typeInfo<glw::GLboolean>
12145 {
12146 public:
12147     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12148 };
12149 
12150 template <>
12151 class typeInfo<glw::GLdouble>
12152 {
12153 public:
12154     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12155 };
12156 
12157 template <>
12158 class typeInfo<tcu::UVec2>
12159 {
12160 public:
12161     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12162 };
12163 
12164 template <>
12165 class typeInfo<tcu::UVec3>
12166 {
12167 public:
12168     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12169 };
12170 
12171 template <>
12172 class typeInfo<tcu::UVec4>
12173 {
12174 public:
12175     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12176 };
12177 
12178 template <>
12179 class typeInfo<tcu::DVec2>
12180 {
12181 public:
12182     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12183 };
12184 
12185 template <>
12186 class typeInfo<tcu::DVec3>
12187 {
12188 public:
12189     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12190 };
12191 
12192 template <>
12193 class typeInfo<tcu::DVec4>
12194 {
12195 public:
12196     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12197 };
12198 
12199 template <>
12200 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2>>
12201 {
12202 public:
12203     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12204 };
12205 
12206 template <>
12207 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2>>
12208 {
12209 public:
12210     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12211 };
12212 
12213 template <>
12214 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2>>
12215 {
12216 public:
12217     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12218 };
12219 
12220 template <>
12221 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3>>
12222 {
12223 public:
12224     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12225 };
12226 
12227 template <>
12228 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3>>
12229 {
12230 public:
12231     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12232 };
12233 
12234 template <>
12235 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3>>
12236 {
12237 public:
12238     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12239 };
12240 
12241 template <>
12242 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4>>
12243 {
12244 public:
12245     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12246 };
12247 
12248 template <>
12249 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4>>
12250 {
12251 public:
12252     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12253 };
12254 
12255 template <>
12256 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4>>
12257 {
12258 public:
12259     static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12260 };
12261 } // namespace TypeHelpers
12262 
12263 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12264  *
12265  **/
12266 namespace Math
12267 {
12268 template <typename T>
12269 static T clamp(T x, T minVal, T maxVal);
12270 
12271 template <int Size>
12272 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix);
12273 
12274 template <int Size>
12275 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size> &src);
12276 
12277 template <typename T>
12278 static T determinant(T val);
12279 
12280 template <typename T>
12281 static T determinant(const tcu::Matrix<T, 2, 2> &mat);
12282 
12283 template <typename T>
12284 static T determinant(const tcu::Matrix<T, 3, 3> &mat);
12285 
12286 template <typename T>
12287 static T determinant(const tcu::Matrix<T, 4, 4> &mat);
12288 
12289 template <int Size>
12290 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix,
12291                                                                 glw::GLuint column, glw::GLuint row);
12292 
12293 template <int Size>
12294 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size> &left,
12295                                             const tcu::Vector<glw::GLdouble, Size> &right);
12296 
12297 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12298 
12299 static glw::GLdouble fract(glw::GLdouble val);
12300 
12301 template <typename T>
12302 static T frexp(T val, glw::GLint &exp);
12303 
12304 template <int Size>
12305 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size> &left,
12306                                                   const tcu::Vector<glw::GLdouble, Size> &right);
12307 
12308 template <int Size>
12309 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12310                                                        const tcu::Vector<glw::GLdouble, Size> &right);
12311 
12312 template <int Size>
12313 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix);
12314 
12315 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12316 
12317 static glw::GLuint isinf_impl(glw::GLdouble val);
12318 
12319 static glw::GLuint isnan_impl(glw::GLdouble val);
12320 
12321 template <typename T>
12322 static T ldexp(T val, glw::GLint exp);
12323 
12324 template <int Size>
12325 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size> &left,
12326                                                const tcu::Vector<glw::GLdouble, Size> &right);
12327 
12328 template <int Size>
12329 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12330                                                     const tcu::Vector<glw::GLdouble, Size> &right);
12331 
12332 template <typename T>
12333 static T max(T left, T right);
12334 
12335 template <typename T>
12336 static T min(T left, T right);
12337 
12338 template <int Size>
12339 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix, glw::GLuint column,
12340                                 glw::GLuint row);
12341 
12342 template <typename T>
12343 static T mix(T left, T right, T weight);
12344 
12345 template <typename T>
12346 static T mod(T left, T right);
12347 
12348 template <typename T>
12349 static T modf(T val, T &integer);
12350 
12351 template <typename T>
12352 static T multiply(T left, T right);
12353 
12354 template <int Size>
12355 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12356                                                const tcu::Vector<glw::GLdouble, Size> &right);
12357 
12358 template <int Cols, int Rows>
12359 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows> &left,
12360                                                            const tcu::Vector<glw::GLdouble, Cols> &right);
12361 
12362 static glw::GLdouble packDouble2x32(const tcu::UVec2 &in);
12363 
12364 template <typename T>
12365 static T round(T t);
12366 
12367 template <typename T>
12368 static T roundEven(T t);
12369 
12370 template <typename T>
12371 static T sign(T t);
12372 
12373 template <typename T>
12374 static T smoothStep(T e0, T e1, T val);
12375 
12376 template <typename T>
12377 static T step(T edge, T val);
12378 
12379 template <typename T, int Rows, int Cols>
12380 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols> &matrix);
12381 
12382 template <typename T>
12383 static T trunc(T t);
12384 
12385 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble &val);
12386 
12387 template <typename T>
clamp(T x,T minVal,T maxVal)12388 static T clamp(T x, T minVal, T maxVal)
12389 {
12390     return min(max(x, minVal), maxVal);
12391 }
12392 
12393 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12394 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix)
12395 {
12396     tcu::Matrix<glw::GLdouble, Size, Size> result;
12397 
12398     for (glw::GLuint c = 0; c < Size; ++c)
12399     {
12400         for (glw::GLuint r = 0; r < Size; ++r)
12401         {
12402             const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12403 
12404             result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12405         }
12406     }
12407 
12408     return result;
12409 }
12410 
12411 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12412 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size> &src)
12413 {
12414     tcu::Vector<glw::GLuint, Size> result;
12415 
12416     for (glw::GLint i = 0; i < Size; ++i)
12417     {
12418         if (GL_FALSE != src[i])
12419         {
12420             result[i] = 1;
12421         }
12422         else
12423         {
12424             result[i] = 0;
12425         }
12426     }
12427 
12428     return result;
12429 }
12430 
12431 template <typename T>
det2(T _00,T _10,T _01,T _11)12432 static T det2(T _00, T _10, T _01, T _11)
12433 {
12434     return _00 * _11 - _01 * _10;
12435 }
12436 
12437 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12438 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12439 {
12440     return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12441 }
12442 
12443 template <typename T>
det4(T _00,T _10,T _20,T _30,T _01,T _11,T _21,T _31,T _02,T _12,T _22,T _32,T _03,T _13,T _23,T _33)12444 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,
12445               T _33)
12446 {
12447     return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12448            _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12449            _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12450            _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12451 }
12452 
12453 template <typename T>
determinant(T val)12454 static T determinant(T val)
12455 {
12456     return val;
12457 }
12458 
12459 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12460 static T determinant(const tcu::Matrix<T, 2, 2> &mat)
12461 {
12462     return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12463 }
12464 
12465 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12466 static T determinant(const tcu::Matrix<T, 3, 3> &mat)
12467 {
12468     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));
12469 }
12470 
12471 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12472 static T determinant(const tcu::Matrix<T, 4, 4> &mat)
12473 {
12474     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),
12475                 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12476 }
12477 
12478 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12479 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix,
12480                                                                 glw::GLuint column, glw::GLuint row)
12481 {
12482     // GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12483 #if (DE_COMPILER == DE_COMPILER_GCC)
12484 #pragma GCC diagnostic push
12485 #pragma GCC diagnostic ignored "-Warray-bounds"
12486 #endif
12487 
12488     const glw::GLint eCol = static_cast<glw::GLint>(column);
12489     const glw::GLint eRow = static_cast<glw::GLint>(row);
12490 
12491     tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12492 
12493     for (glw::GLint c = 0; c < Size; ++c)
12494     {
12495         /* Skip eliminated column */
12496         if (eCol == c)
12497         {
12498             continue;
12499         }
12500 
12501         for (glw::GLint r = 0; r < Size; ++r)
12502         {
12503             /* Skip eliminated row */
12504             if (eRow == r)
12505             {
12506                 continue;
12507             }
12508 
12509             const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12510             const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12511 
12512             result(r + r_offset, c + c_offset) = matrix(r, c);
12513         }
12514     }
12515 
12516     return result;
12517 
12518 #if (DE_COMPILER == DE_COMPILER_GCC)
12519 #pragma GCC diagnostic pop
12520 #endif
12521 }
12522 
12523 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12524 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size> &left,
12525                                             const tcu::Vector<glw::GLdouble, Size> &right)
12526 {
12527     return convertBvecToUvec(tcu::equal(left, right));
12528 }
12529 
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12530 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12531 {
12532     return a * b + c;
12533 }
12534 
fract(glw::GLdouble val)12535 static glw::GLdouble fract(glw::GLdouble val)
12536 {
12537     return val - floor(val);
12538 }
12539 
12540 template <typename T>
frexp(T val,glw::GLint & exp)12541 static T frexp(T val, glw::GLint &exp)
12542 {
12543     return ::frexp(val, &exp);
12544 }
12545 
12546 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12547 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size> &left,
12548                                                   const tcu::Vector<glw::GLdouble, Size> &right)
12549 {
12550     return convertBvecToUvec(tcu::greaterThan(left, right));
12551 }
12552 
12553 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12554 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12555                                                        const tcu::Vector<glw::GLdouble, Size> &right)
12556 {
12557     return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12558 }
12559 
12560 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12561 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix)
12562 {
12563     const tcu::Matrix<glw::GLdouble, Size, Size> cof      = cofactors(matrix);
12564     const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12565     const glw::GLdouble det                               = determinant(matrix);
12566     const glw::GLdouble inv_det                           = 1.0 / det;
12567 
12568     tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12569 
12570     return result;
12571 }
12572 
inverseSqrt(glw::GLdouble val)12573 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12574 {
12575     const glw::GLdouble root = sqrt(val);
12576 
12577     return (1.0 / root);
12578 }
12579 
isinf_impl(glw::GLdouble val)12580 static glw::GLuint isinf_impl(glw::GLdouble val)
12581 {
12582     const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12583 
12584     return ((infinity == val) || (-infinity == val));
12585 }
12586 
isnan_impl(glw::GLdouble val)12587 static glw::GLuint isnan_impl(glw::GLdouble val)
12588 {
12589     return val != val;
12590 }
12591 
12592 template <typename T>
ldexp(T val,glw::GLint exp)12593 static T ldexp(T val, glw::GLint exp)
12594 {
12595     return ::ldexp(val, exp);
12596 }
12597 
12598 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12599 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size> &left,
12600                                                const tcu::Vector<glw::GLdouble, Size> &right)
12601 {
12602     return convertBvecToUvec(tcu::lessThan(left, right));
12603 }
12604 
12605 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12606 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12607                                                     const tcu::Vector<glw::GLdouble, Size> &right)
12608 {
12609     return convertBvecToUvec(tcu::lessThanEqual(left, right));
12610 }
12611 
12612 template <typename T>
max(T left,T right)12613 static T max(T left, T right)
12614 {
12615     return (left >= right) ? left : right;
12616 }
12617 
12618 template <typename T>
min(T left,T right)12619 static T min(T left, T right)
12620 {
12621     return (left <= right) ? left : right;
12622 }
12623 
12624 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12625 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size> &matrix, glw::GLuint column,
12626                                 glw::GLuint row)
12627 {
12628     tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12629 
12630     return determinant(eliminated);
12631 }
12632 
12633 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12634 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2> &matrix, glw::GLuint column, glw::GLuint row)
12635 {
12636     const glw::GLuint r = (0 == row) ? 1 : 0;
12637     const glw::GLuint c = (0 == column) ? 1 : 0;
12638 
12639     return matrix(r, c);
12640 }
12641 
12642 template <typename T>
mix(T left,T right,T weight)12643 static T mix(T left, T right, T weight)
12644 {
12645     return left * (1 - weight) + right * (weight);
12646 }
12647 
12648 template <typename T>
mod(T left,T right)12649 static T mod(T left, T right)
12650 {
12651     const T div_res = left / right;
12652     const T floored = floor(div_res);
12653 
12654     return left - right * floored;
12655 }
12656 
12657 template <typename T>
modf(T val,T & integer)12658 static T modf(T val, T &integer)
12659 {
12660     return ::modf(val, &integer);
12661 }
12662 
12663 template <typename T>
multiply(T left,T right)12664 static T multiply(T left, T right)
12665 {
12666     T result = left * right;
12667 
12668     return result;
12669 }
12670 
12671 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12672 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size> &left,
12673                                                const tcu::Vector<glw::GLdouble, Size> &right)
12674 {
12675     return convertBvecToUvec(tcu::notEqual(left, right));
12676 }
12677 
12678 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12679 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows> &left,
12680                                                            const tcu::Vector<glw::GLdouble, Cols> &right)
12681 {
12682     tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12683     tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12684     tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12685 
12686     for (glw::GLuint i = 0; i < Rows; ++i)
12687     {
12688         left_mat(i, 0) = left[i];
12689     }
12690 
12691     for (glw::GLuint i = 0; i < Cols; ++i)
12692     {
12693         right_mat(0, i) = right[i];
12694     }
12695 
12696     result = left_mat * right_mat;
12697 
12698     return result;
12699 }
12700 
packDouble2x32(const tcu::UVec2 & in)12701 static glw::GLdouble packDouble2x32(const tcu::UVec2 &in)
12702 {
12703     const glw::GLuint buffer[2] = {in[0], in[1]};
12704     glw::GLdouble result;
12705     memcpy(&result, buffer, sizeof(result));
12706     return result;
12707 }
12708 
12709 template <typename T>
round(T t)12710 static T round(T t)
12711 {
12712     T frac = fract(t);
12713     T res  = t - frac;
12714 
12715     if (((T)0.5) < frac)
12716     {
12717         res += ((T)1.0);
12718     }
12719 
12720     return res;
12721 }
12722 
12723 template <typename T>
roundEven(T t)12724 static T roundEven(T t)
12725 {
12726     T frac = fract(t);
12727     T res  = t - frac;
12728 
12729     if (((T)0.5) < frac)
12730     {
12731         res += ((T)1.0);
12732     }
12733     else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12734     {
12735         res += ((T)1.0);
12736     }
12737 
12738     return res;
12739 }
12740 
12741 template <typename T>
sign(T t)12742 static T sign(T t)
12743 {
12744     if (0 > t)
12745     {
12746         return -1;
12747     }
12748     else if (0 == t)
12749     {
12750         return 0;
12751     }
12752     else
12753     {
12754         return 1;
12755     }
12756 }
12757 
12758 template <typename T>
smoothStep(T e0,T e1,T val)12759 static T smoothStep(T e0, T e1, T val)
12760 {
12761     if (e0 >= val)
12762     {
12763         return 0;
12764     }
12765 
12766     if (e1 <= val)
12767     {
12768         return 1;
12769     }
12770 
12771     T temp = (val - e0) / (e1 - e0);
12772 
12773     T result = temp * temp * (3 - 2 * temp);
12774 
12775     return result;
12776 }
12777 
12778 template <typename T>
step(T edge,T val)12779 static T step(T edge, T val)
12780 {
12781     if (edge > val)
12782     {
12783         return 0;
12784     }
12785     else
12786     {
12787         return 1;
12788     }
12789 }
12790 
12791 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12792 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols> &matrix)
12793 {
12794     tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12795 
12796     return result;
12797 }
12798 
12799 template <typename T>
trunc(T t)12800 static T trunc(T t)
12801 {
12802     const T abs_value    = de::abs(t);
12803     const T result_value = floor(abs_value);
12804 
12805     const T result = sign(t) * result_value;
12806 
12807     return result;
12808 }
12809 
unpackDouble2x32(const glw::GLdouble & val)12810 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble &val)
12811 {
12812     glw::GLuint *ptr = (glw::GLuint *)&val;
12813     tcu::UVec2 result(ptr[0], ptr[1]);
12814 
12815     return result;
12816 }
12817 } // namespace Math
12818 
12819 /** Enumeration of tested functions
12820  * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12821  * For example "max" can be called for (dvec3, double).
12822  **/
12823 enum FunctionEnum
12824 {
12825     FUNCTION_ABS = 0,
12826     FUNCTION_CEIL,
12827     FUNCTION_CLAMP,
12828     FUNCTION_CLAMP_AGAINST_SCALAR,
12829     FUNCTION_CROSS,
12830     FUNCTION_DETERMINANT,
12831     FUNCTION_DISTANCE,
12832     FUNCTION_DOT,
12833     FUNCTION_EQUAL,
12834     FUNCTION_FACEFORWARD,
12835     FUNCTION_FLOOR,
12836     FUNCTION_FMA,
12837     FUNCTION_FRACT,
12838     FUNCTION_FREXP,
12839     FUNCTION_GREATERTHAN,
12840     FUNCTION_GREATERTHANEQUAL,
12841     FUNCTION_INVERSE,
12842     FUNCTION_INVERSESQRT,
12843     FUNCTION_LDEXP,
12844     FUNCTION_LESSTHAN,
12845     FUNCTION_LESSTHANEQUAL,
12846     FUNCTION_LENGTH,
12847     FUNCTION_MATRIXCOMPMULT,
12848     FUNCTION_MAX,
12849     FUNCTION_MAX_AGAINST_SCALAR,
12850     FUNCTION_MIN,
12851     FUNCTION_MIN_AGAINST_SCALAR,
12852     FUNCTION_MIX,
12853     FUNCTION_MOD,
12854     FUNCTION_MOD_AGAINST_SCALAR,
12855     FUNCTION_MODF,
12856     FUNCTION_NORMALIZE,
12857     FUNCTION_NOTEQUAL,
12858     FUNCTION_OUTERPRODUCT,
12859     FUNCTION_PACKDOUBLE2X32,
12860     FUNCTION_REFLECT,
12861     FUNCTION_REFRACT,
12862     FUNCTION_ROUND,
12863     FUNCTION_ROUNDEVEN,
12864     FUNCTION_SIGN,
12865     FUNCTION_SMOOTHSTEP,
12866     FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12867     FUNCTION_SQRT,
12868     FUNCTION_STEP,
12869     FUNCTION_STEP_AGAINST_SCALAR,
12870     FUNCTION_TRANSPOSE,
12871     FUNCTION_TRUNC,
12872     FUNCTION_UNPACKDOUBLE2X32,
12873     FUNCTION_ISNAN,
12874     FUNCTION_ISINF,
12875 };
12876 
12877 struct TypeDefinition
12878 {
12879     std::string name;
12880     glw::GLuint n_columns;
12881     glw::GLuint n_rows;
12882 };
12883 
12884 /** Implementation of BuiltinFunctionTest test, description follows:
12885  *
12886  *  Verify double-precision support in common functions works correctly.
12887  *  All double-precision types that apply for particular cases should
12888  *  be tested for the following functions:
12889  *
12890  *  - abs();
12891  *  - ceil();
12892  *  - clamp();
12893  *  - cross();
12894  *  - determinant();
12895  *  - distance();
12896  *  - dot();
12897  *  - equal();
12898  *  - faceforward();
12899  *  - floor();
12900  *  - fma();
12901  *  - fract();
12902  *  - frexp();
12903  *  - greaterThan();
12904  *  - greaterThanEqual();
12905  *  - inverse();
12906  *  - inversesqrt();
12907  *  - ldexp();
12908  *  - lessThan();
12909  *  - lessThanEqual();
12910  *  - length();
12911  *  - matrixCompMult();
12912  *  - max();
12913  *  - min();
12914  *  - mix();
12915  *  - mod();
12916  *  - modf();
12917  *  - normalize();
12918  *  - notEqual();
12919  *  - outerProduct();
12920  *  - packDouble2x32();
12921  *  - reflect();
12922  *  - refract();
12923  *  - round();
12924  *  - roundEven();
12925  *  - sign();
12926  *  - smoothstep();
12927  *  - sqrt();
12928  *  - step();
12929  *  - transpose();
12930  *  - trunc();
12931  *  - unpackDouble2x32();
12932  *  - isnan();
12933  *  - isinf();
12934  *
12935  *  The test should work by creating a program object (for each case
12936  *  considered), to which a vertex shader should be attached. The
12937  *  shader should define input variables that should be used as
12938  *  arguments for the function in question. The result of the
12939  *  operation should then be XFBed back to the test, where the
12940  *  value should be verified.
12941  *
12942  *  Reference function implementation from pre-DEQP CTS framework
12943  *  should be ported to C for verification purposes where available.
12944  *
12945  *  The test should use 1024 different scalar/vector/matrix argument
12946  *  combinations. It should pass if all functions are determined
12947  *  to work correctly for all argument combinations used.
12948  **/
12949 class BuiltinFunctionTest : public deqp::TestCase
12950 {
12951 public:
12952     /* Public methods */
12953     BuiltinFunctionTest(deqp::Context &context, std::string caseName, FunctionEnum function,
12954                         TypeDefinition typeDefinition);
12955 
12956     virtual void deinit();
12957     virtual tcu::TestNode::IterateResult iterate();
12958 
12959     /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12960      *
12961      **/
12962     class functionObject
12963     {
12964     public:
12965         functionObject(FunctionEnum function_enum, const glw::GLchar *function_name, glw::GLvoid *function_pointer,
12966                        Utils::_variable_type result_type);
12967 
~functionObject()12968         virtual ~functionObject()
12969         {
12970         }
12971 
12972         virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const = 0;
12973 
12974         virtual glw::GLuint getArgumentCount() const                              = 0;
12975         virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12976         glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12977         glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12978         glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12979         glw::GLuint getArgumentStride() const;
12980         glw::GLuint getArgumentStride(glw::GLuint argument) const;
12981         FunctionEnum getFunctionEnum() const;
12982         const glw::GLchar *getName() const;
12983         glw::GLuint getResultComponents(glw::GLuint result) const;
12984         virtual glw::GLuint getResultCount() const;
12985         glw::GLuint getResultOffset(glw::GLuint result) const;
12986         virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12987         glw::GLuint getResultStride(glw::GLuint result) const;
12988         glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12989         glw::GLuint getResultStride() const;
12990 
12991     protected:
12992         const FunctionEnum m_function_enum;
12993         const glw::GLchar *m_function_name;
12994         const glw::GLvoid *m_p_function;
12995         const Utils::_variable_type m_res_type;
12996     };
12997 
12998 private:
12999     /* Private types */
13000     /** General type enumeration
13001      *
13002      **/
13003     enum generalType
13004     {
13005         SCALAR = 0,
13006         VECTOR,
13007         MATRIX,
13008     };
13009 
13010     /** Details of variable type
13011      *
13012      **/
13013     struct typeDetails
13014     {
13015         typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
13016 
13017         generalType m_general_type;
13018         glw::GLuint m_n_columns;
13019         glw::GLuint m_n_rows;
13020         glw::GLenum m_type;
13021         std::string m_type_name;
13022     };
13023 
13024     /* Typedefs for gl.uniform* function pointers */
13025     typedef GLW_APICALL void(GLW_APIENTRY *uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
13026                                                                        const glw::GLdouble *);
13027     typedef GLW_APICALL void(GLW_APIENTRY *uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble *);
13028     typedef GLW_APICALL void(GLW_APIENTRY *uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint *);
13029     typedef GLW_APICALL void(GLW_APIENTRY *uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint *);
13030 
13031     /* Private methods */
13032     bool compare(Utils::_variable_type type, const glw::GLvoid *left, const glw::GLvoid *right);
13033 
13034     functionObject *getFunctionObject(FunctionEnum function, const typeDetails &type);
13035 
13036     uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
13037                                                          const functionObject &function_object) const;
13038 
13039     uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
13040                                                          const functionObject &function_object) const;
13041 
13042     uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
13043                                                          const functionObject &function_object) const;
13044 
13045     uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
13046                                                          const functionObject &function_object) const;
13047 
13048     const glw::GLchar *getUniformName(glw::GLuint argument) const;
13049     const glw::GLchar *getVaryingName(glw::GLuint argument) const;
13050 
13051     bool isFunctionImplemented(FunctionEnum function, const typeDetails &type) const;
13052 
13053     void logVariableType(const glw::GLvoid *buffer, const glw::GLchar *name, Utils::_variable_type type) const;
13054 
13055     void prepareArgument(const functionObject &function_object, glw::GLuint vertex, glw::GLubyte *buffer);
13056 
13057     void prepareComponents(const functionObject &function_object, glw::GLuint vertex, glw::GLuint argument,
13058                            glw::GLubyte *buffer);
13059 
13060     void prepareProgram(const functionObject &function_object, Utils::programInfo &program_info);
13061 
13062     void prepareTestData(const functionObject &function_object);
13063     void prepareVertexShaderCode(const functionObject &function_object);
13064 
13065     bool test(FunctionEnum function, const typeDetails &type);
13066 
13067     void testBegin(const functionObject &function_object, glw::GLuint program_id, glw::GLuint vertex);
13068 
13069     void testInit();
13070 
13071     bool isResultEdgeCase(const functionObject &function_object, glw::GLuint vertex,
13072                           const Utils::_variable_type result_type, const glw::GLvoid *expected_result_src,
13073                           const glw::GLvoid *result_src);
13074 
13075     bool verifyResults(const functionObject &function_object, glw::GLuint vertex);
13076 
13077     /* Private constants */
13078     static const glw::GLdouble m_epsilon;
13079     static const glw::GLuint m_n_veritces;
13080 
13081     /* Private fields */
13082     glw::GLuint m_transform_feedback_buffer_id;
13083     glw::GLuint m_vertex_array_object_id;
13084 
13085     std::vector<glw::GLubyte> m_expected_results_data;
13086     FunctionEnum m_function;
13087     TypeDefinition m_typeDefinition;
13088     std::vector<glw::GLubyte> m_argument_data;
13089     std::string m_vertex_shader_code;
13090 };
13091 
13092 /* Constants used by BuiltinFunctionTest */
13093 /** Khronos Bug #14010
13094  *  Using an epsilon value for comparing floating points is error prone.
13095  *  Rather than writing a new floating point comparison function, I am
13096  *  increasing the epsilon value to allow greater orders of magnitude
13097  *  of floating point values.
13098  **/
13099 const glw::GLdouble BuiltinFunctionTest::m_epsilon  = 0.00002;
13100 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
13101 
13102 /** Implementations of function objects required by "BuiltinFunctionTest"
13103  *
13104  **/
13105 namespace FunctionObject
13106 {
13107 /** Maps variable type with enumeration Utils::_variable_type
13108  *
13109  * @tparam T type
13110  **/
13111 template <typename T>
13112 class typeInfo
13113 {
13114 public:
13115     static const Utils::_variable_type variable_type =
13116         TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
13117 };
13118 
13119 /** Place data from <in> into <buffer>
13120  *
13121  * @param buffer Buffer
13122  * @param in     Input data
13123  **/
13124 template <typename T>
13125 class pack
13126 {
13127 public:
set(glw::GLvoid * buffer,const T & in)13128     static void set(glw::GLvoid *buffer, const T &in)
13129     {
13130         *(T *)buffer = in;
13131     }
13132 };
13133 
13134 /** Place tcu::Matrix data from <in> into <buffer>
13135  *
13136  * @param buffer Buffer
13137  * @param in     Input data
13138  **/
13139 template <int Cols, int Rows>
13140 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols>>
13141 {
13142 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13143     static void set(glw::GLvoid *buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols> &in)
13144     {
13145         glw::GLdouble *data = (glw::GLdouble *)buffer;
13146 
13147         for (glw::GLint column = 0; column < Cols; ++column)
13148         {
13149             for (glw::GLint row = 0; row < Rows; ++row)
13150             {
13151                 glw::GLint index = column * Rows + row;
13152 
13153                 data[index] = in(row, column);
13154             }
13155         }
13156     }
13157 };
13158 
13159 /** Get data of <out> from <buffer>
13160  *
13161  * @param buffer Buffer
13162  * @param out    Output data
13163  **/
13164 template <typename T>
13165 class unpack
13166 {
13167 public:
get(const glw::GLvoid * buffer,T & out)13168     static void get(const glw::GLvoid *buffer, T &out)
13169     {
13170         out = *(T *)buffer;
13171     }
13172 };
13173 
13174 /** Get tcu::Matrix data from <buffer>
13175  *
13176  * @param buffer Buffer
13177  * @param out    Output data
13178  **/
13179 template <int Cols, int Rows>
13180 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols>>
13181 {
13182 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13183     static void get(const glw::GLvoid *buffer, tcu::Matrix<glw::GLdouble, Rows, Cols> &out)
13184     {
13185         const glw::GLdouble *data = (glw::GLdouble *)buffer;
13186 
13187         for (glw::GLint column = 0; column < Cols; ++column)
13188         {
13189             for (glw::GLint row = 0; row < Rows; ++row)
13190             {
13191                 glw::GLint index = column * Rows + row;
13192 
13193                 out(row, column) = data[index];
13194             }
13195         }
13196     }
13197 };
13198 
13199 /** Base of unary function classes
13200  *
13201  **/
13202 class unaryBase : public BuiltinFunctionTest::functionObject
13203 {
13204 public:
unaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13205     unaryBase(FunctionEnum function_enum, const glw::GLchar *function_name, glw::GLvoid *function_pointer,
13206               const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13207         : functionObject(function_enum, function_name, function_pointer, res_type)
13208         , m_arg_type(arg_type)
13209     {
13210     }
13211 
getArgumentCount() const13212     virtual glw::GLuint getArgumentCount() const
13213     {
13214         return 1;
13215     }
13216 
getArgumentType(glw::GLuint) const13217     virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13218     {
13219         return m_arg_type;
13220     }
13221 
13222 protected:
13223     const Utils::_variable_type m_arg_type;
13224 };
13225 
13226 /** Unary function class. It treats input argument as one variable.
13227  *
13228  * @tparam ResT Type of result
13229  * @tparam ArgT Type of argument
13230  **/
13231 template <typename ResT, typename ArgT>
13232 class unary : public unaryBase
13233 {
13234 public:
13235     typedef ResT (*functionPointer)(const ArgT &);
13236 
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13237     unary(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer)
13238         : unaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, typeInfo<ResT>::variable_type,
13239                     typeInfo<ArgT>::variable_type)
13240     {
13241     }
13242 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13243     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13244     {
13245         ResT result;
13246         ArgT arg;
13247 
13248         unpack<ArgT>::get(argument_src, arg);
13249 
13250         functionPointer p_function = (functionPointer)m_p_function;
13251 
13252         result = p_function(arg);
13253 
13254         pack<ResT>::set(result_dst, result);
13255     }
13256 };
13257 
13258 /** Unary function class. It treats input argument as separate components.
13259  *
13260  * @tparam ResT Type of result
13261  **/
13262 template <typename ResT>
13263 class unaryByComponent : public unaryBase
13264 {
13265 public:
13266     typedef ResT (*functionPointer)(glw::GLdouble);
13267 
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13268     unaryByComponent(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer,
13269                      const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13270         : unaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, res_type, arg_type)
13271     {
13272     }
13273 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13274     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13275     {
13276         glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13277         ResT *p_result           = (ResT *)result_dst;
13278         glw::GLdouble *p_arg     = (glw::GLdouble *)argument_src;
13279 
13280         functionPointer p_function = (functionPointer)m_p_function;
13281 
13282         for (glw::GLuint component = 0; component < n_components; ++component)
13283         {
13284             p_result[component] = p_function(p_arg[component]);
13285         }
13286     }
13287 };
13288 
13289 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13290  *
13291  * @tparam ResT Type of result
13292  * @tparam ArgT Type of argument
13293  * @tparam OutT Type of output parameter
13294  **/
13295 template <typename ResT, typename ArgT, typename OutT>
13296 class unaryWithOutputByComponent : public unaryBase
13297 {
13298 public:
13299     typedef ResT (*functionPointer)(ArgT, OutT &);
13300 
unaryWithOutputByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type,const Utils::_variable_type out_type)13301     unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar *function_name,
13302                                functionPointer function_pointer, const Utils::_variable_type res_type,
13303                                const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13304         : unaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, res_type, arg_type)
13305         , m_out_type(out_type)
13306     {
13307     }
13308 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13309     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13310     {
13311         ResT *p_result = (ResT *)result_dst;
13312         OutT *p_out    = (OutT *)((glw::GLubyte *)result_dst + getResultOffset(1));
13313         ArgT *p_arg    = (ArgT *)argument_src;
13314 
13315         const glw::GLuint n_components_0 = getArgumentComponents(0);
13316         const glw::GLuint n_components_1 = getResultComponents(1);
13317         const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13318 
13319         const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13320         const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13321 
13322         functionPointer p_function = (functionPointer)m_p_function;
13323 
13324         for (glw::GLuint component = 0; component < n_components; ++component)
13325         {
13326             const ArgT first_arg = p_arg[component * component_step_0];
13327             OutT &second_arg     = p_out[component * component_step_1];
13328 
13329             p_result[component] = p_function(first_arg, second_arg);
13330         }
13331     }
13332 
getResultCount() const13333     glw::GLuint getResultCount() const
13334     {
13335         return 2;
13336     }
13337 
getResultType(glw::GLuint result) const13338     Utils::_variable_type getResultType(glw::GLuint result) const
13339     {
13340         Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13341 
13342         switch (result)
13343         {
13344         case 0:
13345             type = m_res_type;
13346             break;
13347         case 1:
13348             type = m_out_type;
13349             break;
13350         default:
13351             TCU_FAIL("Not implemented");
13352             break;
13353         }
13354 
13355         return type;
13356     }
13357 
13358 protected:
13359     const Utils::_variable_type m_out_type;
13360 };
13361 
13362 /** Base of binary function classes.
13363  *
13364  **/
13365 class binaryBase : public BuiltinFunctionTest::functionObject
13366 {
13367 public:
binaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type)13368     binaryBase(FunctionEnum function_enum, const glw::GLchar *function_name, glw::GLvoid *function_pointer,
13369                const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13370                const Utils::_variable_type arg_2_type)
13371         : functionObject(function_enum, function_name, function_pointer, res_type)
13372         , m_arg_1_type(arg_1_type)
13373         , m_arg_2_type(arg_2_type)
13374     {
13375     }
13376 
getArgumentCount() const13377     virtual glw::GLuint getArgumentCount() const
13378     {
13379         return 2;
13380     }
13381 
getArgumentType(glw::GLuint argument) const13382     virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13383     {
13384         switch (argument)
13385         {
13386         case 0:
13387             return m_arg_1_type;
13388         case 1:
13389             return m_arg_2_type;
13390         default:
13391             return Utils::VARIABLE_TYPE_UNKNOWN;
13392         }
13393     }
13394 
13395 protected:
13396     const Utils::_variable_type m_arg_1_type;
13397     const Utils::_variable_type m_arg_2_type;
13398 };
13399 
13400 /** Binary function class. It treats input arguments as two variables.
13401  *
13402  * @param ResT  Type of result
13403  * @param Arg1T Type of first argument
13404  * @param Arg2T Type of second argument
13405  **/
13406 template <typename ResT, typename Arg1T, typename Arg2T>
13407 class binary : public binaryBase
13408 {
13409 public:
13410     typedef ResT (*functionPointer)(const Arg1T &, const Arg2T &);
13411 
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13412     binary(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer)
13413         : binaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, typeInfo<ResT>::variable_type,
13414                      typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13415     {
13416     }
13417 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13418     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13419     {
13420         const glw::GLuint argument_1_stride = getArgumentStride(0);
13421 
13422         functionPointer p_function = (functionPointer)m_p_function;
13423 
13424         Arg1T arg_1;
13425         Arg2T arg_2;
13426         ResT result;
13427 
13428         unpack<Arg1T>::get(argument_src, arg_1);
13429         unpack<Arg2T>::get((glw::GLubyte *)argument_src + argument_1_stride, arg_2);
13430 
13431         result = p_function(arg_1, arg_2);
13432 
13433         pack<ResT>::set(result_dst, result);
13434     }
13435 };
13436 
13437 /** Binary function class. It treats input arguments as separate components.
13438  *
13439  * @param ResT  Type of result
13440  * @param Arg1T Type of first argument
13441  * @param Arg2T Type of second argument
13442  **/
13443 template <typename ResT, typename Arg1T, typename Arg2T>
13444 class binaryByComponent : public binaryBase
13445 {
13446 public:
13447     typedef ResT (*functionPointer)(Arg1T, Arg2T);
13448 
binaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type)13449     binaryByComponent(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer,
13450                       const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13451                       const Utils::_variable_type arg_2_type)
13452         : binaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, res_type, arg_1_type, arg_2_type)
13453     {
13454     }
13455 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13456     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13457     {
13458         ResT *p_result = (ResT *)result_dst;
13459         Arg1T *p_arg_1 = (Arg1T *)argument_src;
13460         Arg2T *p_arg_2 = (Arg2T *)((glw::GLubyte *)argument_src + getArgumentOffset(1));
13461 
13462         const glw::GLuint n_components_0 = getArgumentComponents(0);
13463         const glw::GLuint n_components_1 = getArgumentComponents(1);
13464         const glw::GLuint n_components   = de::max(n_components_0, n_components_1);
13465 
13466         const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13467         const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13468 
13469         functionPointer p_function = (functionPointer)m_p_function;
13470 
13471         for (glw::GLuint component = 0; component < n_components; ++component)
13472         {
13473             const Arg1T first_arg  = p_arg_1[component * component_step_0];
13474             const Arg2T second_arg = p_arg_2[component * component_step_1];
13475 
13476             p_result[component] = p_function(first_arg, second_arg);
13477         }
13478     }
13479 };
13480 
13481 /** Base of tenary function classes.
13482  *
13483  **/
13484 class tenaryBase : public BuiltinFunctionTest::functionObject
13485 {
13486 public:
tenaryBase(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type,const Utils::_variable_type arg_3_type)13487     tenaryBase(FunctionEnum function_enum, const glw::GLchar *function_name, glw::GLvoid *function_pointer,
13488                const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13489                const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13490         : functionObject(function_enum, function_name, function_pointer, res_type)
13491         , m_arg_1_type(arg_1_type)
13492         , m_arg_2_type(arg_2_type)
13493         , m_arg_3_type(arg_3_type)
13494     {
13495     }
13496 
getArgumentCount() const13497     virtual glw::GLuint getArgumentCount() const
13498     {
13499         return 3;
13500     }
13501 
getArgumentType(glw::GLuint argument) const13502     virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13503     {
13504         switch (argument)
13505         {
13506         case 0:
13507             return m_arg_1_type;
13508         case 1:
13509             return m_arg_2_type;
13510         case 2:
13511             return m_arg_3_type;
13512         default:
13513             return Utils::VARIABLE_TYPE_UNKNOWN;
13514         }
13515     }
13516 
13517 protected:
13518     const Utils::_variable_type m_arg_1_type;
13519     const Utils::_variable_type m_arg_2_type;
13520     const Utils::_variable_type m_arg_3_type;
13521 };
13522 
13523 /** Tenary function class. It treats input arguments as three variables.
13524  *
13525  * @param ResT  Type of result
13526  * @param Arg1T Type of first argument
13527  * @param Arg2T Type of second argument
13528  * @param Arg3T Type of third argument
13529  **/
13530 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13531 class tenary : public tenaryBase
13532 {
13533 public:
13534     typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13535     typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13536     typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13537     typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13538 
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13539     tenary(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer)
13540         : tenaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, typeInfo<ResT>::variable_type,
13541                      typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13542     {
13543     }
13544 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13545     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13546     {
13547         const glw::GLuint argument_2_offset = getArgumentOffset(1);
13548         const glw::GLuint argument_3_offset = getArgumentOffset(2);
13549 
13550         functionPointer p_function = (functionPointer)m_p_function;
13551 
13552         arg1T arg_1;
13553         arg2T arg_2;
13554         arg3T arg_3;
13555         ResT result;
13556 
13557         unpack<arg1T>::get(argument_src, arg_1);
13558         unpack<arg2T>::get((glw::GLubyte *)argument_src + argument_2_offset, arg_2);
13559         unpack<arg3T>::get((glw::GLubyte *)argument_src + argument_3_offset, arg_3);
13560 
13561         result = p_function(arg_1, arg_2, arg_3);
13562 
13563         pack<ResT>::set(result_dst, result);
13564     }
13565 };
13566 
13567 /** Tenary function class. It treats input arguments as separate components.
13568  *
13569 
13570  **/
13571 class tenaryByComponent : public tenaryBase
13572 {
13573 public:
13574     typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13575 
tenaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_1_type,const Utils::_variable_type arg_2_type,const Utils::_variable_type arg_3_type)13576     tenaryByComponent(FunctionEnum function_enum, const glw::GLchar *function_name, functionPointer function_pointer,
13577                       const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13578                       const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13579         : tenaryBase(function_enum, function_name, (glw::GLvoid *)function_pointer, res_type, arg_1_type, arg_2_type,
13580                      arg_3_type)
13581     {
13582     }
13583 
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13584     virtual void call(glw::GLvoid *result_dst, const glw::GLvoid *argument_src) const
13585     {
13586         glw::GLdouble *p_result    = (glw::GLdouble *)result_dst;
13587         const glw::GLdouble *p_arg = (const glw::GLdouble *)argument_src;
13588 
13589         const glw::GLuint n_components_0 = getArgumentComponents(0);
13590         const glw::GLuint n_components_1 = getArgumentComponents(1);
13591         const glw::GLuint n_components_2 = getArgumentComponents(2);
13592         const glw::GLuint n_components   = de::max(de::max(n_components_0, n_components_1), n_components_2);
13593 
13594         const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13595         const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13596         const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13597 
13598         functionPointer p_function = (functionPointer)m_p_function;
13599 
13600         for (glw::GLuint component = 0; component < n_components; ++component)
13601         {
13602             const glw::GLdouble first_arg  = p_arg[component * component_step_0];
13603             const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13604             const glw::GLdouble third_arg  = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13605 
13606             p_result[component] = p_function(first_arg, second_arg, third_arg);
13607         }
13608     }
13609 };
13610 } // namespace FunctionObject
13611 
13612 /** Constructor.
13613  *
13614  *  @param context Rendering context.
13615  **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13616 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context &context, std::string caseName, FunctionEnum function,
13617                                          TypeDefinition typeDefinition)
13618     : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13619     , m_transform_feedback_buffer_id(0)
13620     , m_vertex_array_object_id(0)
13621     , m_function(function)
13622     , m_typeDefinition(typeDefinition)
13623 {
13624     /* Nothing to be done here */
13625 }
13626 
13627 /** Deinitializes all GL objects that may have been created during test execution.
13628  *
13629  **/
deinit()13630 void BuiltinFunctionTest::deinit()
13631 {
13632     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
13633 
13634     /* Clean buffers */
13635     if (0 != m_transform_feedback_buffer_id)
13636     {
13637         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13638         gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13639         m_transform_feedback_buffer_id = 0;
13640     }
13641 
13642     /* Clean VAO */
13643     if (0 != m_vertex_array_object_id)
13644     {
13645         gl.bindVertexArray(0);
13646         gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13647         m_vertex_array_object_id = 0;
13648     }
13649 }
13650 
13651 /** Execute test
13652  *
13653  * @return tcu::TestNode::STOP
13654  **/
iterate()13655 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13656 {
13657     /* Check if extension is supported */
13658     if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13659     {
13660         throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13661     }
13662 
13663     testInit();
13664 
13665     /* Verify result */
13666     typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13667     if (test(m_function, type))
13668     {
13669         m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13670     }
13671     else
13672     {
13673         m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13674     }
13675 
13676     /* Done */
13677     return tcu::TestNode::STOP;
13678 }
13679 
13680 /** Constructor
13681  *
13682  * @param function_enum    Function enumeration
13683  * @param function_name    Function name
13684  * @param function_pointer Pointer to routine that wiil be executed
13685  * @param result_type      Type of result
13686  **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13687 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar *function_name,
13688                                                     glw::GLvoid *function_pointer, Utils::_variable_type result_type)
13689     : m_function_enum(function_enum)
13690     , m_function_name(function_name)
13691     , m_p_function(function_pointer)
13692     , m_res_type(result_type)
13693 {
13694     /* Nothing to be done here */
13695 }
13696 
13697 /** Get number of components for <argument>
13698  *
13699  * @param argument Argument ordinal, starts with 0
13700  *
13701  * @return Number of components
13702  **/
getArgumentComponents(glw::GLuint argument) const13703 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13704 {
13705     const Utils::_variable_type type = getArgumentType(argument);
13706     const glw::GLuint n_components   = Utils::getNumberOfComponentsForVariableType(type);
13707 
13708     return n_components;
13709 }
13710 
13711 /** Get size in bytes of single component of <argument>
13712  *
13713  * @param argument Argument ordinal, starts with 0
13714  *
13715  * @return Size of component
13716  **/
getArgumentComponentSize(glw::GLuint argument) const13717 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13718 {
13719     const Utils::_variable_type type      = getArgumentType(argument);
13720     const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13721     const glw::GLuint base_type_size      = Utils::getBaseVariableTypeComponentSize(base_type);
13722 
13723     return base_type_size;
13724 }
13725 
13726 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13727  *
13728  * @param argument Argument ordinal, starts with 0
13729  *
13730  * @return Offset of arguemnt's data
13731  **/
getArgumentOffset(glw::GLuint argument) const13732 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13733 {
13734     glw::GLuint result = 0;
13735 
13736     for (glw::GLuint i = 0; i < argument; ++i)
13737     {
13738         result += getArgumentStride(i);
13739     }
13740 
13741     return result;
13742 }
13743 
13744 /** Get stride in bytes of all arguments
13745  *
13746  * @return Stride of all arguments
13747  **/
getArgumentStride() const13748 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13749 {
13750     const glw::GLuint n_args = getArgumentCount();
13751     glw::GLuint result       = 0;
13752 
13753     for (glw::GLuint i = 0; i < n_args; ++i)
13754     {
13755         result += getArgumentStride(i);
13756     }
13757 
13758     return result;
13759 }
13760 
13761 /** Get stride in bytes of <argument>
13762  *
13763  * @param argument Argument ordinal, starts with 0
13764  *
13765  * @return Stride of argument
13766  **/
getArgumentStride(glw::GLuint argument) const13767 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13768 {
13769     const glw::GLuint component_size = getArgumentComponentSize(argument);
13770     const glw::GLuint n_components   = getArgumentComponents(argument);
13771 
13772     return n_components * component_size;
13773 }
13774 
13775 /** Get function enumeration
13776  *
13777  * @return Function enumeration
13778  **/
getFunctionEnum() const13779 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13780 {
13781     return m_function_enum;
13782 }
13783 
13784 /** Get function name
13785  *
13786  * @return Function name
13787  **/
getName() const13788 const glw::GLchar *BuiltinFunctionTest::functionObject::getName() const
13789 {
13790     return m_function_name;
13791 }
13792 
13793 /** Get number of components for <result>
13794  *
13795  * @param result Result ordinal, starts with 0
13796  *
13797  * @return Number of components
13798  **/
getResultComponents(glw::GLuint result) const13799 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13800 {
13801     const Utils::_variable_type type = getResultType(result);
13802     const glw::GLuint n_components   = Utils::getNumberOfComponentsForVariableType(type);
13803 
13804     return n_components;
13805 }
13806 
13807 /** Get number of results
13808  *
13809  * @return Number of results
13810  **/
getResultCount() const13811 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13812 {
13813     return 1;
13814 }
13815 
13816 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13817  *
13818  * @param result Result ordinal, starts with 0
13819  *
13820  * @return Offset
13821  **/
getResultOffset(glw::GLuint result) const13822 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13823 {
13824     glw::GLuint offset = 0;
13825 
13826     for (glw::GLuint i = 0; i < result; ++i)
13827     {
13828         offset += getResultStride(i);
13829         offset = deAlign32(offset, getBaseTypeSize(i));
13830     }
13831 
13832     return offset;
13833 }
13834 
13835 /** Get stride in bytes of <result>.
13836  *
13837  * @param result Result ordinal, starts with 0
13838  *
13839  * @return Stride
13840  **/
getResultStride(glw::GLuint result) const13841 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13842 {
13843     const Utils::_variable_type type = getResultType(result);
13844     const glw::GLuint n_components   = Utils::getNumberOfComponentsForVariableType(type);
13845 
13846     return n_components * getBaseTypeSize(result);
13847 }
13848 
13849 /** Get size in bytes of <result> base component.
13850  *
13851  * @param result Result ordinal, starts with 0
13852  *
13853  * @return Alignment
13854  **/
getBaseTypeSize(glw::GLuint result) const13855 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13856 {
13857     const Utils::_variable_type type      = getResultType(result);
13858     const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13859     const glw::GLuint base_type_size      = Utils::getBaseVariableTypeComponentSize(base_type);
13860 
13861     return base_type_size;
13862 }
13863 
13864 /** Get stride in bytes of all results.
13865  *
13866  * @return Stride
13867  **/
getResultStride() const13868 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13869 {
13870     const glw::GLuint n_results = getResultCount();
13871     glw::GLuint stride          = 0;
13872     glw::GLuint maxAlignment    = 0;
13873 
13874     for (glw::GLuint i = 0; i < n_results; ++i)
13875     {
13876         const glw::GLuint alignment = getBaseTypeSize(i);
13877         stride += getResultStride(i);
13878         stride       = deAlign32(stride, alignment);
13879         maxAlignment = deMaxu32(maxAlignment, alignment);
13880     }
13881 
13882     // The stride of all results must also be aligned,
13883     // so results for next vertex are aligned.
13884     return deAlign32(stride, maxAlignment);
13885 }
13886 
13887 /** Get type of <result>.
13888  *
13889  * @param result Result ordinal, starts with 0
13890  *
13891  * @return Type
13892  **/
getResultType(glw::GLuint) const13893 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13894 {
13895     return m_res_type;
13896 }
13897 
13898 /** Constructor
13899  *
13900  * @param n_columns Number of columns
13901  * @param n_rows    Number of rows
13902  **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13903 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13904     : m_n_columns(n_columns)
13905     , m_n_rows(n_rows)
13906 {
13907     Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13908     m_type                     = Utils::getGLDataTypeOfVariableType(type);
13909     m_type_name                = Utils::getVariableTypeString(type);
13910 
13911     if (1 == m_n_columns)
13912     {
13913         if (1 == m_n_rows)
13914         {
13915             m_general_type = SCALAR;
13916         }
13917         else
13918         {
13919             m_general_type = VECTOR;
13920         }
13921     }
13922     else
13923     {
13924         m_general_type = MATRIX;
13925     }
13926 }
13927 
13928 /** Compare two values
13929  *
13930  * @param type  Type of values
13931  * @param left  Pointer to left value
13932  * @param right Pointer to right value
13933  *
13934  * @return true if values are equal, false otherwise
13935  **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13936 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid *left, const glw::GLvoid *right)
13937 {
13938     bool result = true;
13939 
13940     const glw::GLuint n_components        = Utils::getNumberOfComponentsForVariableType(type);
13941     const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13942 
13943     switch (base_type)
13944     {
13945     case Utils::VARIABLE_TYPE_DOUBLE:
13946 
13947     {
13948         const glw::GLdouble *left_values  = (glw::GLdouble *)left;
13949         const glw::GLdouble *right_values = (glw::GLdouble *)right;
13950 
13951         for (glw::GLuint component = 0; component < n_components; ++component)
13952         {
13953             const glw::GLdouble left_value  = left_values[component];
13954             const glw::GLdouble right_value = right_values[component];
13955 
13956             if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13957                 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13958             {
13959                 result = false;
13960                 break;
13961             }
13962         }
13963     }
13964 
13965     break;
13966 
13967     case Utils::VARIABLE_TYPE_INT:
13968 
13969     {
13970         const glw::GLint *left_values  = (glw::GLint *)left;
13971         const glw::GLint *right_values = (glw::GLint *)right;
13972 
13973         for (glw::GLuint component = 0; component < n_components; ++component)
13974         {
13975             const glw::GLint left_value  = left_values[component];
13976             const glw::GLint right_value = right_values[component];
13977 
13978             if (left_value != right_value)
13979             {
13980                 result = false;
13981                 break;
13982             }
13983         }
13984     }
13985 
13986     break;
13987 
13988     case Utils::VARIABLE_TYPE_UINT:
13989 
13990     {
13991         const glw::GLuint *left_values  = (glw::GLuint *)left;
13992         const glw::GLuint *right_values = (glw::GLuint *)right;
13993 
13994         for (glw::GLuint component = 0; component < n_components; ++component)
13995         {
13996             const glw::GLuint left_value  = left_values[component];
13997             const glw::GLuint right_value = right_values[component];
13998 
13999             if (left_value != right_value)
14000             {
14001                 result = false;
14002                 break;
14003             }
14004         }
14005     }
14006 
14007     break;
14008 
14009     default:
14010 
14011         TCU_FAIL("Not implemented");
14012     }
14013 
14014     return result;
14015 }
14016 
14017 /** Create instance of function object for given function enumeration and type
14018  *
14019  * @param function Function enumeration
14020  * @param type     Type details
14021  *
14022  * @return Create object
14023  **/
getFunctionObject(FunctionEnum function,const typeDetails & type)14024 BuiltinFunctionTest::functionObject *BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
14025                                                                             const typeDetails &type)
14026 {
14027     typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
14028     typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
14029     typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
14030     typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
14031     typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
14032     typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
14033     typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
14034     typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
14035     typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
14036 
14037     const glw::GLuint n_columns               = type.m_n_columns;
14038     const glw::GLuint n_rows                  = type.m_n_rows;
14039     const Utils::_variable_type scalar_type   = Utils::getDoubleVariableType(1, 1);
14040     const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
14041     const Utils::_variable_type uint_type     = Utils::getUintVariableType(1, n_rows);
14042     const Utils::_variable_type int_type      = Utils::getIntVariableType(1, n_rows);
14043 
14044     switch (function)
14045     {
14046     case FUNCTION_ABS:
14047 
14048         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14049             function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
14050 
14051     case FUNCTION_CEIL:
14052 
14053         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14054             function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
14055 
14056     case FUNCTION_CLAMP:
14057 
14058         return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
14059                                                      variable_type /* arg1_type */, variable_type /* arg2_type */,
14060                                                      variable_type /* arg3_type */);
14061 
14062     case FUNCTION_CLAMP_AGAINST_SCALAR:
14063 
14064         return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type  */,
14065                                                      variable_type /* arg1_type */, scalar_type /* arg2_type */,
14066                                                      scalar_type /* arg3_type */);
14067 
14068     case FUNCTION_CROSS:
14069 
14070         return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14071             function, "cross", tcu::cross);
14072 
14073     case FUNCTION_DETERMINANT:
14074 
14075         switch (variable_type)
14076         {
14077         case Utils::VARIABLE_TYPE_DMAT2:
14078             return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
14079                                                                                          Math::determinant);
14080         case Utils::VARIABLE_TYPE_DMAT3:
14081             return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
14082                                                                                          Math::determinant);
14083         case Utils::VARIABLE_TYPE_DMAT4:
14084             return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
14085                                                                                          Math::determinant);
14086         default:
14087             TCU_FAIL("Not implemented");
14088         }
14089 
14090     case FUNCTION_DISTANCE:
14091 
14092         switch (variable_type)
14093         {
14094         case Utils::VARIABLE_TYPE_DVEC2:
14095             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14096                 function, "distance", tcu::distance);
14097         case Utils::VARIABLE_TYPE_DVEC3:
14098             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14099                 function, "distance", tcu::distance);
14100         case Utils::VARIABLE_TYPE_DVEC4:
14101             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14102                 function, "distance", tcu::distance);
14103         default:
14104             break;
14105         }
14106 
14107         break;
14108 
14109     case FUNCTION_DOT:
14110 
14111         switch (variable_type)
14112         {
14113         case Utils::VARIABLE_TYPE_DVEC2:
14114             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14115                 function, "dot", tcu::dot);
14116         case Utils::VARIABLE_TYPE_DVEC3:
14117             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14118                 function, "dot", tcu::dot);
14119         case Utils::VARIABLE_TYPE_DVEC4:
14120             return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14121                 function, "dot", tcu::dot);
14122         default:
14123             break;
14124         }
14125 
14126         break;
14127 
14128     case FUNCTION_EQUAL:
14129 
14130         switch (variable_type)
14131         {
14132         case Utils::VARIABLE_TYPE_DVEC2:
14133             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14134                 function, "equal", Math::equal);
14135         case Utils::VARIABLE_TYPE_DVEC3:
14136             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14137                 function, "equal", Math::equal);
14138         case Utils::VARIABLE_TYPE_DVEC4:
14139             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14140                 function, "equal", Math::equal);
14141         default:
14142             break;
14143         }
14144 
14145         break;
14146 
14147     case FUNCTION_FACEFORWARD:
14148 
14149         switch (variable_type)
14150         {
14151         case Utils::VARIABLE_TYPE_DVEC2:
14152             return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2 & /* Arg1T */,
14153                                               const tcu::DVec2 & /* Arg2T */, const tcu::DVec2 & /* Arg3T */>(
14154                 function, "faceforward", tcu::faceForward);
14155         case Utils::VARIABLE_TYPE_DVEC3:
14156             return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3 & /* Arg1T */,
14157                                               const tcu::DVec3 & /* Arg2T */, const tcu::DVec3 & /* Arg3T */>(
14158                 function, "faceforward", tcu::faceForward);
14159         case Utils::VARIABLE_TYPE_DVEC4:
14160             return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4 & /* Arg1T */,
14161                                               const tcu::DVec4 & /* Arg2T */, const tcu::DVec4 & /* Arg3T */>(
14162                 function, "faceforward", tcu::faceForward);
14163         default:
14164             break;
14165         }
14166 
14167         break;
14168 
14169     case FUNCTION_FLOOR:
14170 
14171         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14172             function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14173 
14174     case FUNCTION_FMA:
14175 
14176         return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type  */,
14177                                                      variable_type /* arg1_type */, variable_type /* arg2_type */,
14178                                                      variable_type /* arg3_type */);
14179 
14180     case FUNCTION_FRACT:
14181 
14182         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14183             function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14184 
14185     case FUNCTION_FREXP:
14186 
14187         return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14188                                                               glw::GLint /* OutT */>(
14189             function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14190             int_type /* out_type */);
14191 
14192     case FUNCTION_GREATERTHAN:
14193 
14194         switch (variable_type)
14195         {
14196         case Utils::VARIABLE_TYPE_DVEC2:
14197             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14198                 function, "greaterThan", Math::greaterThan);
14199         case Utils::VARIABLE_TYPE_DVEC3:
14200             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14201                 function, "greaterThan", Math::greaterThan);
14202         case Utils::VARIABLE_TYPE_DVEC4:
14203             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14204                 function, "greaterThan", Math::greaterThan);
14205         default:
14206             break;
14207         }
14208 
14209         break;
14210 
14211     case FUNCTION_GREATERTHANEQUAL:
14212 
14213         switch (variable_type)
14214         {
14215         case Utils::VARIABLE_TYPE_DVEC2:
14216             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14217                 function, "greaterThanEqual", Math::greaterThanEqual);
14218         case Utils::VARIABLE_TYPE_DVEC3:
14219             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14220                 function, "greaterThanEqual", Math::greaterThanEqual);
14221         case Utils::VARIABLE_TYPE_DVEC4:
14222             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14223                 function, "greaterThanEqual", Math::greaterThanEqual);
14224         default:
14225             break;
14226         }
14227 
14228         break;
14229 
14230     case FUNCTION_INVERSE:
14231 
14232         switch (variable_type)
14233         {
14234         case Utils::VARIABLE_TYPE_DMAT2:
14235             return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14236         case Utils::VARIABLE_TYPE_DMAT3:
14237             return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14238         case Utils::VARIABLE_TYPE_DMAT4:
14239             return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14240         default:
14241             break;
14242         }
14243 
14244         break;
14245 
14246     case FUNCTION_INVERSESQRT:
14247 
14248         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14249             function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14250 
14251     case FUNCTION_LDEXP:
14252 
14253         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14254                                                      glw::GLint /* Arg2T */>(
14255             function, "ldexp", ::ldexp, variable_type /* res_type  */, variable_type /* arg1_type */,
14256             int_type /* arg2_type */);
14257 
14258     case FUNCTION_LESSTHAN:
14259 
14260         switch (variable_type)
14261         {
14262         case Utils::VARIABLE_TYPE_DVEC2:
14263             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14264                 function, "lessThan", Math::lessThan);
14265         case Utils::VARIABLE_TYPE_DVEC3:
14266             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14267                 function, "lessThan", Math::lessThan);
14268         case Utils::VARIABLE_TYPE_DVEC4:
14269             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14270                 function, "lessThan", Math::lessThan);
14271         default:
14272             break;
14273         }
14274 
14275         break;
14276 
14277     case FUNCTION_LESSTHANEQUAL:
14278 
14279         switch (variable_type)
14280         {
14281         case Utils::VARIABLE_TYPE_DVEC2:
14282             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14283                 function, "lessThanEqual", Math::lessThanEqual);
14284         case Utils::VARIABLE_TYPE_DVEC3:
14285             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14286                 function, "lessThanEqual", Math::lessThanEqual);
14287         case Utils::VARIABLE_TYPE_DVEC4:
14288             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14289                 function, "lessThanEqual", Math::lessThanEqual);
14290         default:
14291             break;
14292         }
14293 
14294         break;
14295 
14296     case FUNCTION_LENGTH:
14297 
14298         switch (variable_type)
14299         {
14300         case Utils::VARIABLE_TYPE_DVEC2:
14301             return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14302                                                                                               tcu::length);
14303         case Utils::VARIABLE_TYPE_DVEC3:
14304             return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14305                                                                                               tcu::length);
14306         case Utils::VARIABLE_TYPE_DVEC4:
14307             return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14308                                                                                               tcu::length);
14309         default:
14310             break;
14311         }
14312 
14313         break;
14314 
14315     case FUNCTION_MATRIXCOMPMULT:
14316 
14317         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14318                                                      glw::GLdouble /* Arg2T */>(
14319             function, "matrixCompMult", Math::multiply, variable_type /* res_type  */, variable_type /* arg1_type */,
14320             variable_type /* arg2_type */);
14321 
14322     case FUNCTION_MAX:
14323 
14324         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14325                                                      glw::GLdouble /* Arg2T */>(
14326             function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14327             variable_type /* arg2_type */);
14328 
14329     case FUNCTION_MAX_AGAINST_SCALAR:
14330 
14331         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14332                                                      glw::GLdouble /* Arg2T */>(
14333             function, "max", Math::max, variable_type /* res_type  */, variable_type /* arg1_type */,
14334             scalar_type /* arg2_type */);
14335 
14336     case FUNCTION_MIN:
14337 
14338         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14339                                                      glw::GLdouble /* Arg2T */>(
14340             function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14341             variable_type /* arg2_type */);
14342 
14343     case FUNCTION_MIN_AGAINST_SCALAR:
14344 
14345         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14346                                                      glw::GLdouble /* Arg2T */>(
14347             function, "min", Math::min, variable_type /* res_type  */, variable_type /* arg1_type */,
14348             scalar_type /* arg2_type */);
14349 
14350     case FUNCTION_MIX:
14351 
14352         return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type  */,
14353                                                      variable_type /* arg1_type */, variable_type /* arg2_type */,
14354                                                      variable_type /* arg3_type */);
14355 
14356     case FUNCTION_MOD:
14357 
14358         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14359                                                      glw::GLdouble /* Arg2T */>(
14360             function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14361             variable_type /* arg2_type */);
14362 
14363     case FUNCTION_MOD_AGAINST_SCALAR:
14364 
14365         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14366                                                      glw::GLdouble /* Arg2T */>(
14367             function, "mod", Math::mod, variable_type /* res_type  */, variable_type /* arg1_type */,
14368             scalar_type /* arg2_type */);
14369 
14370     case FUNCTION_MODF:
14371 
14372         return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14373                                                               glw::GLdouble /* OutT */>(
14374             function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14375             variable_type /* out_type */);
14376 
14377     case FUNCTION_NORMALIZE:
14378 
14379         switch (variable_type)
14380         {
14381         case Utils::VARIABLE_TYPE_DVEC2:
14382             return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14383                                                                                            tcu::normalize);
14384         case Utils::VARIABLE_TYPE_DVEC3:
14385             return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14386                                                                                            tcu::normalize);
14387         case Utils::VARIABLE_TYPE_DVEC4:
14388             return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14389                                                                                            tcu::normalize);
14390         default:
14391             break;
14392         }
14393 
14394         break;
14395 
14396     case FUNCTION_NOTEQUAL:
14397 
14398         switch (variable_type)
14399         {
14400         case Utils::VARIABLE_TYPE_DVEC2:
14401             return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14402                 function, "notEqual", Math::notEqual);
14403         case Utils::VARIABLE_TYPE_DVEC3:
14404             return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14405                 function, "notEqual", Math::notEqual);
14406         case Utils::VARIABLE_TYPE_DVEC4:
14407             return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14408                 function, "notEqual", Math::notEqual);
14409         default:
14410             break;
14411         }
14412 
14413         break;
14414 
14415     case FUNCTION_OUTERPRODUCT:
14416 
14417         switch (variable_type)
14418         {
14419         case Utils::VARIABLE_TYPE_DMAT2:
14420             return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14421                 function, "outerProduct", Math::outerProduct);
14422         case Utils::VARIABLE_TYPE_DMAT2X3:
14423             return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14424                 function, "outerProduct", Math::outerProduct);
14425         case Utils::VARIABLE_TYPE_DMAT2X4:
14426             return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14427                 function, "outerProduct", Math::outerProduct);
14428         case Utils::VARIABLE_TYPE_DMAT3:
14429             return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14430                 function, "outerProduct", Math::outerProduct);
14431         case Utils::VARIABLE_TYPE_DMAT3X2:
14432             return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14433                 function, "outerProduct", Math::outerProduct);
14434         case Utils::VARIABLE_TYPE_DMAT3X4:
14435             return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14436                 function, "outerProduct", Math::outerProduct);
14437         case Utils::VARIABLE_TYPE_DMAT4:
14438             return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14439                 function, "outerProduct", Math::outerProduct);
14440         case Utils::VARIABLE_TYPE_DMAT4X2:
14441             return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14442                 function, "outerProduct", Math::outerProduct);
14443         case Utils::VARIABLE_TYPE_DMAT4X3:
14444             return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14445                 function, "outerProduct", Math::outerProduct);
14446         default:
14447             break;
14448         }
14449 
14450         break;
14451 
14452     case FUNCTION_PACKDOUBLE2X32:
14453 
14454         return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14455                                                                                           Math::packDouble2x32);
14456 
14457     case FUNCTION_REFLECT:
14458 
14459         switch (variable_type)
14460         {
14461         case Utils::VARIABLE_TYPE_DVEC2:
14462             return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14463                 function, "reflect", tcu::reflect);
14464         case Utils::VARIABLE_TYPE_DVEC3:
14465             return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14466                 function, "reflect", tcu::reflect);
14467         case Utils::VARIABLE_TYPE_DVEC4:
14468             return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14469                 function, "reflect", tcu::reflect);
14470         default:
14471             break;
14472         }
14473 
14474         break;
14475 
14476     case FUNCTION_REFRACT:
14477 
14478         switch (variable_type)
14479         {
14480         case Utils::VARIABLE_TYPE_DVEC2:
14481             return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2 & /* Arg1T */,
14482                                               const tcu::DVec2 & /* Arg2T */, glw::GLdouble /* Arg3T */>(
14483                 function, "refract", tcu::refract);
14484         case Utils::VARIABLE_TYPE_DVEC3:
14485             return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3 & /* Arg1T */,
14486                                               const tcu::DVec3 & /* Arg2T */, glw::GLdouble /* Arg3T */>(
14487                 function, "refract", tcu::refract);
14488         case Utils::VARIABLE_TYPE_DVEC4:
14489             return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4 & /* Arg1T */,
14490                                               const tcu::DVec4 & /* Arg2T */, glw::GLdouble /* Arg3T */>(
14491                 function, "refract", tcu::refract);
14492         default:
14493             break;
14494         }
14495 
14496         break;
14497 
14498     case FUNCTION_ROUND:
14499 
14500         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14501             function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14502 
14503     case FUNCTION_ROUNDEVEN:
14504 
14505         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14506             function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14507 
14508     case FUNCTION_SIGN:
14509 
14510         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14511             function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14512 
14513     case FUNCTION_SMOOTHSTEP:
14514 
14515         return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14516                                                      variable_type /* res_type  */, variable_type /* arg1_type */,
14517                                                      variable_type /* arg2_type */, variable_type /* arg3_type */);
14518 
14519     case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14520 
14521         return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14522                                                      variable_type /* res_type  */, scalar_type /* arg1_type */,
14523                                                      scalar_type /* arg2_type */, variable_type /* arg3_type */);
14524 
14525     case FUNCTION_SQRT:
14526 
14527         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14528             function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14529 
14530     case FUNCTION_STEP:
14531 
14532         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14533                                                      glw::GLdouble /* Arg2T */>(
14534             function, "step", Math::step, variable_type /* res_type  */, variable_type /* arg1_type */,
14535             variable_type /* arg2_type */);
14536 
14537     case FUNCTION_STEP_AGAINST_SCALAR:
14538 
14539         return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14540                                                      glw::GLdouble /* Arg2T */>(
14541             function, "step", Math::step, variable_type /* res_type  */, scalar_type /* arg1_type */,
14542             variable_type /* arg2_type */);
14543 
14544     case FUNCTION_TRANSPOSE:
14545 
14546         switch (variable_type)
14547         {
14548         case Utils::VARIABLE_TYPE_DMAT2:
14549             return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14550                                                                                  Math::transpose);
14551         case Utils::VARIABLE_TYPE_DMAT2X3:
14552             return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14553                                                                                      Math::transpose);
14554         case Utils::VARIABLE_TYPE_DMAT2X4:
14555             return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14556                                                                                      Math::transpose);
14557         case Utils::VARIABLE_TYPE_DMAT3:
14558             return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14559                                                                                  Math::transpose);
14560         case Utils::VARIABLE_TYPE_DMAT3X2:
14561             return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14562                                                                                      Math::transpose);
14563         case Utils::VARIABLE_TYPE_DMAT3X4:
14564             return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14565                                                                                      Math::transpose);
14566         case Utils::VARIABLE_TYPE_DMAT4:
14567             return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14568                                                                                  Math::transpose);
14569         case Utils::VARIABLE_TYPE_DMAT4X2:
14570             return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14571                                                                                      Math::transpose);
14572         case Utils::VARIABLE_TYPE_DMAT4X3:
14573             return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14574                                                                                      Math::transpose);
14575         default:
14576             break;
14577         }
14578 
14579         break;
14580 
14581     case FUNCTION_TRUNC:
14582 
14583         return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14584             function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14585 
14586     case FUNCTION_UNPACKDOUBLE2X32:
14587 
14588         return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14589                                                                                           Math::unpackDouble2x32);
14590 
14591     case FUNCTION_ISNAN:
14592 
14593         return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14594             function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14595 
14596     case FUNCTION_ISINF:
14597 
14598         return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14599             function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14600 
14601     default:
14602         TCU_FAIL("Not implemented");
14603         return 0;
14604     }
14605 
14606     TCU_FAIL("Not implemented");
14607     return 0;
14608 }
14609 
14610 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14611  *
14612  * @param argument        Argument index
14613  * @param function_object Function object
14614  *
14615  * @return Function pointer
14616  **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14617 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14618     glw::GLuint argument, const functionObject &function_object) const
14619 {
14620     const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14621     const glw::Functions &gl                  = m_context.getRenderContext().getFunctions();
14622 
14623     switch (argument_type)
14624     {
14625     case Utils::VARIABLE_TYPE_DMAT2:
14626         return gl.uniformMatrix2dv;
14627     case Utils::VARIABLE_TYPE_DMAT2X3:
14628         return gl.uniformMatrix2x3dv;
14629     case Utils::VARIABLE_TYPE_DMAT2X4:
14630         return gl.uniformMatrix2x4dv;
14631     case Utils::VARIABLE_TYPE_DMAT3:
14632         return gl.uniformMatrix3dv;
14633     case Utils::VARIABLE_TYPE_DMAT3X2:
14634         return gl.uniformMatrix3x2dv;
14635     case Utils::VARIABLE_TYPE_DMAT3X4:
14636         return gl.uniformMatrix3x4dv;
14637     case Utils::VARIABLE_TYPE_DMAT4:
14638         return gl.uniformMatrix4dv;
14639     case Utils::VARIABLE_TYPE_DMAT4X2:
14640         return gl.uniformMatrix4x2dv;
14641     case Utils::VARIABLE_TYPE_DMAT4X3:
14642         return gl.uniformMatrix4x3dv;
14643     default:
14644         break;
14645     }
14646 
14647     TCU_FAIL("Not implemented");
14648     return 0;
14649 }
14650 
14651 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14652  *
14653  * @param argument        Argument index
14654  * @param function_object Function object
14655  *
14656  * @return Function pointer
14657  **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14658 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14659     glw::GLuint argument, const functionObject &function_object) const
14660 {
14661     const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14662     const glw::Functions &gl                  = m_context.getRenderContext().getFunctions();
14663 
14664     switch (argument_type)
14665     {
14666     case Utils::VARIABLE_TYPE_DOUBLE:
14667         return gl.uniform1dv;
14668     case Utils::VARIABLE_TYPE_DVEC2:
14669         return gl.uniform2dv;
14670     case Utils::VARIABLE_TYPE_DVEC3:
14671         return gl.uniform3dv;
14672     case Utils::VARIABLE_TYPE_DVEC4:
14673         return gl.uniform4dv;
14674     default:
14675         TCU_FAIL("Not implemented");
14676     }
14677 
14678     return 0;
14679 }
14680 
14681 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14682  *
14683  * @param argument        Argument index
14684  * @param function_object Function object
14685  *
14686  * @return Function pointer
14687  **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14688 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14689     glw::GLuint argument, const functionObject &function_object) const
14690 {
14691     const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14692     const glw::Functions &gl                  = m_context.getRenderContext().getFunctions();
14693 
14694     switch (argument_type)
14695     {
14696     case Utils::VARIABLE_TYPE_INT:
14697         return gl.uniform1iv;
14698     case Utils::VARIABLE_TYPE_IVEC2:
14699         return gl.uniform2iv;
14700     case Utils::VARIABLE_TYPE_IVEC3:
14701         return gl.uniform3iv;
14702     case Utils::VARIABLE_TYPE_IVEC4:
14703         return gl.uniform4iv;
14704     default:
14705         TCU_FAIL("Not implemented");
14706     }
14707 
14708     return 0;
14709 }
14710 
14711 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14712  *
14713  * @param argument        Argument index
14714  * @param function_object Function object
14715  *
14716  * @return Function pointer
14717  **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14718 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14719     glw::GLuint argument, const functionObject &function_object) const
14720 {
14721     const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14722     const glw::Functions &gl                  = m_context.getRenderContext().getFunctions();
14723 
14724     switch (argument_type)
14725     {
14726     case Utils::VARIABLE_TYPE_UVEC2:
14727         return gl.uniform2uiv;
14728     default:
14729         TCU_FAIL("Not implemented");
14730     }
14731 
14732     return 0;
14733 }
14734 
14735 /** Get name of uniform that will be used as <argument>.
14736  *
14737  * @param argument Argument index
14738  *
14739  * @return Name of uniform
14740  **/
getUniformName(glw::GLuint argument) const14741 const glw::GLchar *BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14742 {
14743     switch (argument)
14744     {
14745     case 0:
14746         return "uniform_0";
14747     case 1:
14748         return "uniform_1";
14749     case 2:
14750         return "uniform_2";
14751     default:
14752         TCU_FAIL("Not implemented");
14753         return 0;
14754     }
14755 }
14756 
14757 /** Get name of varying that will be used as <result>.
14758  *
14759  * @param result Result index
14760  *
14761  * @return Name of varying
14762  **/
getVaryingName(glw::GLuint result) const14763 const glw::GLchar *BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14764 {
14765     switch (result)
14766     {
14767     case 0:
14768         return "result_0";
14769     case 1:
14770         return "result_1";
14771     case 2:
14772         return "result_2";
14773     default:
14774         TCU_FAIL("Not implemented");
14775         return 0;
14776     }
14777 }
14778 
14779 /** Check if given combination of function and type is implemented
14780  *
14781  * @param function Function enumeration
14782  * @param type     Type details
14783  *
14784  * @return true if function is available for given type, false otherwise
14785  **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14786 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails &type) const
14787 {
14788     static const bool look_up_table[][3] = {
14789         /* SCALAR, VECTOR, MATRIX */
14790         /* FUNCTION_ABS:                       */ {true, true, false},
14791         /* FUNCTION_CEIL:                      */ {true, true, false},
14792         /* FUNCTION_CLAMP:                     */ {true, true, false},
14793         /* FUNCTION_CLAMP_AGAINST_SCALAR:      */ {false, true, false},
14794         /* FUNCTION_CROSS:                     */ {false, true, false},
14795         /* FUNCTION_DETERMINANT:               */ {false, false, true},
14796         /* FUNCTION_DISTANCE:                  */ {false, true, false},
14797         /* FUNCTION_DOT:                       */ {false, true, false},
14798         /* FUNCTION_EQUAL:                     */ {false, true, false},
14799         /* FUNCTION_FACEFORWARD:               */ {false, true, false},
14800         /* FUNCTION_FLOOR:                     */ {true, true, false},
14801         /* FUNCTION_FMA:                       */ {true, true, false},
14802         /* FUNCTION_FRACT:                     */ {true, true, false},
14803         /* FUNCTION_FREXP:                     */ {true, true, false},
14804         /* FUNCTION_GREATERTHAN:               */ {false, true, false},
14805         /* FUNCTION_GREATERTHANEQUAL:          */ {false, true, false},
14806         /* FUNCTION_INVERSE:                   */ {false, false, true},
14807         /* FUNCTION_INVERSESQRT:               */ {true, true, false},
14808         /* FUNCTION_LDEXP:                     */ {true, true, false},
14809         /* FUNCTION_LESSTHAN:                  */ {false, true, false},
14810         /* FUNCTION_LESSTHANEQUAL:             */ {false, true, false},
14811         /* FUNCTION_LENGTH:                    */ {false, true, false},
14812         /* FUNCTION_MATRIXCOMPMULT:            */ {false, false, true},
14813         /* FUNCTION_MAX:                       */ {true, true, false},
14814         /* FUNCTION_MAX_AGAINST_SCALAR:        */ {false, true, false},
14815         /* FUNCTION_MIN:                       */ {true, true, false},
14816         /* FUNCTION_MIN_AGAINST_SCALAR:        */ {false, true, false},
14817         /* FUNCTION_MIX:                       */ {true, true, false},
14818         /* FUNCTION_MOD:                       */ {true, true, false},
14819         /* FUNCTION_MOD_AGAINST_SCALAR:        */ {false, true, false},
14820         /* FUNCTION_MODF:                      */ {true, true, false},
14821         /* FUNCTION_NORMALIZE:                 */ {false, true, false},
14822         /* FUNCTION_NOTEQUAL:                  */ {false, true, false},
14823         /* FUNCTION_OUTERPRODUCT:              */ {false, false, true},
14824         /* FUNCTION_PACKDOUBLE2X32:            */ {true, false, false},
14825         /* FUNCTION_REFLECT:                   */ {false, true, false},
14826         /* FUNCTION_REFRACT:                   */ {false, true, false},
14827         /* FUNCTION_ROUND:                     */ {true, true, false},
14828         /* FUNCTION_ROUNDEVEN:                 */ {true, true, false},
14829         /* FUNCTION_SIGN:                      */ {true, false, false},
14830         /* FUNCTION_SMOOTHSTEP:                */ {true, true, false},
14831         /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ {false, true, false},
14832         /* FUNCTION_SQRT:                      */ {true, true, false},
14833         /* FUNCTION_STEP:                      */ {true, true, false},
14834         /* FUNCTION_STEP_AGAINST_SCALAR:       */ {false, true, false},
14835         /* FUNCTION_TRANSPOSE:                 */ {false, false, false},
14836         /* FUNCTION_TRUNC:                     */ {true, true, false},
14837         /* FUNCTION_UNPACKDOUBLE2X32:          */ {true, false, false},
14838         /* FUNCTION_ISNAN:                     */ {true, true, false},
14839         /* FUNCTION_ISINF:                     */ {true, true, false},
14840     };
14841 
14842     bool result = look_up_table[function][type.m_general_type];
14843 
14844     if (true == result)
14845     {
14846         switch (function)
14847         {
14848         case FUNCTION_CROSS: /* Only 3 element vectors */
14849             result = (3 == type.m_n_rows);
14850             break;
14851         case FUNCTION_DETERMINANT: /* Only square matrices */
14852         case FUNCTION_INVERSE:
14853             result = (type.m_n_columns == type.m_n_rows);
14854             break;
14855         default:
14856             break;
14857         }
14858     }
14859 
14860     return result;
14861 }
14862 
14863 /** Logs variable of given type: name (type) [values]
14864  *
14865  * @param buffer Source of data
14866  * @param name   Name of variable
14867  * @param type   Type of variable
14868  **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14869 void BuiltinFunctionTest::logVariableType(const glw::GLvoid *buffer, const glw::GLchar *name,
14870                                           Utils::_variable_type type) const
14871 {
14872     const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14873     const glw::GLuint n_components        = Utils::getNumberOfComponentsForVariableType(type);
14874     tcu::MessageBuilder message           = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14875 
14876     message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14877 
14878     for (glw::GLuint component = 0; component < n_components; ++component)
14879     {
14880         if (0 != component)
14881         {
14882             message << ", ";
14883         }
14884 
14885         switch (base_type)
14886         {
14887         case Utils::VARIABLE_TYPE_DOUBLE:
14888             message << ((glw::GLdouble *)buffer)[component];
14889             break;
14890         case Utils::VARIABLE_TYPE_INT:
14891             message << ((glw::GLint *)buffer)[component];
14892             break;
14893         case Utils::VARIABLE_TYPE_UINT:
14894             message << ((glw::GLuint *)buffer)[component];
14895             break;
14896         default:
14897             TCU_FAIL("Not implemented");
14898         }
14899     }
14900 
14901     message << "]" << tcu::TestLog::EndMessage;
14902 }
14903 
14904 /** Prepare input arguments, data are stored in <buffer>
14905  *
14906  * @param function_object Function object
14907  * @param vertex          Vertex index
14908  * @param buffer          Buffer pointer
14909  **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14910 void BuiltinFunctionTest::prepareArgument(const functionObject &function_object, glw::GLuint vertex,
14911                                           glw::GLubyte *buffer)
14912 {
14913     const glw::GLuint n_arguments = function_object.getArgumentCount();
14914 
14915     for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14916     {
14917         const glw::GLuint offset = function_object.getArgumentOffset(argument);
14918 
14919         prepareComponents(function_object, vertex, argument, buffer + offset);
14920     }
14921 }
14922 
14923 /** Prepare components for given <function_object>, <vertex> and <argument>
14924  *
14925  * @param function_object Function object
14926  * @param vertex          Vertex index
14927  * @param argument        Argument index
14928  * @param buffer          Buffer pointer
14929  **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14930 void BuiltinFunctionTest::prepareComponents(const functionObject &function_object, glw::GLuint vertex,
14931                                             glw::GLuint argument, glw::GLubyte *buffer)
14932 {
14933     glw::GLuint argument_index[3]             = {0};
14934     glw::GLuint argument_reset[3]             = {0};
14935     glw::GLuint argument_step[3]              = {0};
14936     glw::GLdouble double_argument_start[3]    = {0.0};
14937     const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14938     glw::GLuint int_argument_start            = -4;
14939     const glw::GLuint n_arguments             = function_object.getArgumentCount();
14940     const glw::GLuint n_components            = function_object.getArgumentComponents(argument);
14941     glw::GLuint uint_argument_start           = 0;
14942 
14943     switch (n_arguments)
14944     {
14945     case 1:
14946         argument_step[0]         = 1;
14947         argument_reset[0]        = 1024;
14948         double_argument_start[0] = -511.5;
14949         break;
14950     case 2:
14951         argument_step[0]         = 32;
14952         argument_step[1]         = 1;
14953         argument_reset[0]        = 32;
14954         argument_reset[1]        = 32;
14955         double_argument_start[0] = -15.5;
14956         double_argument_start[1] = -15.5;
14957         break;
14958     case 3:
14959         argument_step[0]         = 64;
14960         argument_step[1]         = 8;
14961         argument_step[2]         = 1;
14962         argument_reset[0]        = 16;
14963         argument_reset[1]        = 8;
14964         argument_reset[2]        = 8;
14965         double_argument_start[0] = -7.5;
14966         double_argument_start[1] = -3.5;
14967         double_argument_start[2] = -3.5;
14968         break;
14969     default:
14970         TCU_FAIL("Not implemented");
14971         return;
14972     }
14973 
14974     switch (function_object.getFunctionEnum())
14975     {
14976     case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14977     case FUNCTION_CLAMP_AGAINST_SCALAR:
14978         double_argument_start[2] = 4.5;
14979         break;
14980     case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14981         double_argument_start[0] = 16.5;
14982         break;
14983     case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14984     case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14985         argument_step[0]         = 1;
14986         argument_step[1]         = 8;
14987         argument_step[2]         = 64;
14988         argument_reset[0]        = 8;
14989         argument_reset[1]        = 8;
14990         argument_reset[2]        = 16;
14991         double_argument_start[0] = -3.5;
14992         double_argument_start[1] = 4.5;
14993         double_argument_start[2] = -7.5;
14994         break;
14995     default:
14996         break;
14997     }
14998 
14999     for (glw::GLuint i = 0; i < n_arguments; ++i)
15000     {
15001         argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
15002     }
15003 
15004     switch (base_arg_type)
15005     {
15006     case Utils::VARIABLE_TYPE_DOUBLE:
15007     {
15008         glw::GLdouble *argument_dst = (glw::GLdouble *)buffer;
15009 
15010         double_argument_start[argument] += argument_index[argument];
15011 
15012         for (glw::GLuint component = 0; component < n_components; ++component)
15013         {
15014             glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
15015 
15016             switch (function_object.getFunctionEnum())
15017             {
15018             case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
15019                 if (0.5 == Math::fract(value))
15020                 {
15021                     value += 0.01;
15022                 }
15023                 break;
15024             default:
15025                 break;
15026             }
15027 
15028             argument_dst[component] = value;
15029         }
15030     }
15031     break;
15032     case Utils::VARIABLE_TYPE_INT:
15033     {
15034         glw::GLint *argument_dst = (glw::GLint *)buffer;
15035 
15036         uint_argument_start += argument_index[argument];
15037 
15038         for (glw::GLuint component = 0; component < n_components; ++component)
15039         {
15040             const glw::GLint value = int_argument_start + component;
15041 
15042             argument_dst[component] = value;
15043         }
15044     }
15045     break;
15046     case Utils::VARIABLE_TYPE_UINT:
15047     {
15048         glw::GLuint *argument_dst = (glw::GLuint *)buffer;
15049 
15050         uint_argument_start += argument_index[argument];
15051 
15052         for (glw::GLuint component = 0; component < n_components; ++component)
15053         {
15054             const glw::GLuint value = uint_argument_start + component;
15055 
15056             argument_dst[component] = value;
15057         }
15058     }
15059     break;
15060     default:
15061         TCU_FAIL("Not implemented");
15062         return;
15063     }
15064 }
15065 
15066 /** Prepare programInfo for given functionObject
15067  *
15068  * @param function_object  Function object
15069  * @param out_program_info Program info
15070  **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)15071 void BuiltinFunctionTest::prepareProgram(const functionObject &function_object, Utils::programInfo &out_program_info)
15072 {
15073     const glw::GLuint n_varying_names          = function_object.getResultCount();
15074     static const glw::GLchar *varying_names[3] = {getVaryingName(0), getVaryingName(1), getVaryingName(2)};
15075 
15076     prepareVertexShaderCode(function_object);
15077 
15078     out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
15079                            varying_names, n_varying_names);
15080 }
15081 
15082 /** Prepare input data and expected results for given function object
15083  *
15084  * @param function_object Function object
15085  **/
prepareTestData(const functionObject & function_object)15086 void BuiltinFunctionTest::prepareTestData(const functionObject &function_object)
15087 {
15088     const glw::GLuint result_stride        = function_object.getResultStride();
15089     const glw::GLuint result_buffer_size   = result_stride * m_n_veritces;
15090     const glw::GLuint argument_stride      = function_object.getArgumentStride();
15091     const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
15092 
15093     m_argument_data.clear();
15094     m_expected_results_data.clear();
15095 
15096     m_argument_data.resize(argument_buffer_size);
15097     m_expected_results_data.resize(result_buffer_size);
15098 
15099     for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15100     {
15101         const glw::GLuint result_offset   = vertex * result_stride;
15102         glw::GLdouble *result_dst         = (glw::GLdouble *)&m_expected_results_data[result_offset];
15103         const glw::GLuint argument_offset = vertex * argument_stride;
15104         glw::GLubyte *argument_dst        = &m_argument_data[argument_offset];
15105 
15106         prepareArgument(function_object, vertex, argument_dst);
15107         function_object.call(result_dst, argument_dst);
15108     }
15109 }
15110 
15111 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
15112  *
15113  * @param function_object Function object
15114  **/
prepareVertexShaderCode(const functionObject & function_object)15115 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject &function_object)
15116 {
15117     static const glw::GLchar *shader_template_code = "#version 400 core\n"
15118                                                      "\n"
15119                                                      "precision highp float;\n"
15120                                                      "\n"
15121                                                      "ARGUMENT_DEFINITION"
15122                                                      "\n"
15123                                                      "RESULT_DEFINITION"
15124                                                      "\n"
15125                                                      "void main()\n"
15126                                                      "{\n"
15127                                                      "    RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
15128                                                      "}\n"
15129                                                      "\n";
15130 
15131     static const glw::GLchar *argument_definition_token = "ARGUMENT_DEFINITION";
15132     static const glw::GLchar *argument_token            = "ARGUMENT";
15133     static const glw::GLchar *function_name_token       = "FUNCTION_NAME";
15134     static const glw::GLchar *result_definition_token   = "RESULT_DEFINITION";
15135     static const glw::GLchar *result_name_token         = "RESULT_NAME";
15136     static const glw::GLchar *result_type_token         = "RESULT_TYPE";
15137     static const glw::GLchar *uniform_name_token        = "UNIFORM_NAME";
15138     static const glw::GLchar *uniform_type_token        = "UNIFORM_TYPE";
15139 
15140     static const glw::GLchar *argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15141     static const glw::GLchar *argument_str        = ", UNIFORM_NAMEARGUMENT";
15142     static const glw::GLchar *first_argument      = "UNIFORM_NAMEARGUMENT";
15143     static const glw::GLchar *result_definition   = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15144 
15145     const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15146     const glw::GLuint first_argument_length      = (glw::GLuint)strlen(first_argument);
15147     const glw::GLuint n_arguments                = function_object.getArgumentCount();
15148     const glw::GLuint n_results                  = function_object.getResultCount();
15149     const glw::GLuint result_definition_length   = (glw::GLuint)strlen(result_definition);
15150     std::string result_type                      = Utils::getVariableTypeString(function_object.getResultType(0));
15151 
15152     size_t search_position = 0;
15153     std::string string     = shader_template_code;
15154 
15155     /* Replace ARGUMENT_DEFINITION with definitions */
15156     for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15157     {
15158         Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15159         const glw::GLchar *uniform_name     = getUniformName(argument);
15160         std::string uniform_type            = Utils::getVariableTypeString(argument_type);
15161 
15162         Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15163 
15164         search_position -= argument_definition_length;
15165 
15166         Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15167         Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15168     }
15169 
15170     /* Remove ARGUMENT_DEFINITION */
15171     Utils::replaceToken(argument_definition_token, search_position, "", string);
15172 
15173     /* Replace RESULT_DEFINITION with definitions */
15174     for (glw::GLuint result = 0; result < n_results; ++result)
15175     {
15176         Utils::_variable_type variable_type = function_object.getResultType(result);
15177         const glw::GLchar *varying_name     = getVaryingName(result);
15178         std::string varying_type            = Utils::getVariableTypeString(variable_type);
15179 
15180         Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15181 
15182         search_position -= result_definition_length;
15183 
15184         Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15185         Utils::replaceToken(result_name_token, search_position, varying_name, string);
15186     }
15187 
15188     /* Remove RESULT_DEFINITION */
15189     Utils::replaceToken(result_definition_token, search_position, "", string);
15190 
15191     /* Replace RESULT_NAME */
15192     Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15193 
15194     /* Replace RESULT_TYPE */
15195     Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15196 
15197     /* Replace FUNCTION_NAME */
15198     Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15199 
15200     /* Replace ARGUMENT with list of arguments */
15201     for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15202     {
15203         const glw::GLchar *uniform_name = getUniformName(argument);
15204 
15205         if (0 == argument)
15206         {
15207             Utils::replaceToken(argument_token, search_position, first_argument, string);
15208         }
15209         else
15210         {
15211             Utils::replaceToken(argument_token, search_position, argument_str, string);
15212         }
15213 
15214         search_position -= first_argument_length;
15215 
15216         Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15217     }
15218 
15219     for (glw::GLuint result = 1; result < n_results; ++result)
15220     {
15221         const glw::GLchar *varying_name = getVaryingName(result);
15222 
15223         Utils::replaceToken(argument_token, search_position, argument_str, string);
15224 
15225         search_position -= first_argument_length;
15226 
15227         Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15228     }
15229 
15230     /* Remove ARGUMENT */
15231     Utils::replaceToken(argument_token, search_position, "", string);
15232 
15233     m_vertex_shader_code = string;
15234 }
15235 
15236 /** Test single function with one type
15237  *
15238  * param function Function enumeration
15239  * param type     Type details
15240  *
15241  * @return true if test pass (or function is not available for <type>), false otherwise
15242  **/
test(FunctionEnum function,const typeDetails & type)15243 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails &type)
15244 {
15245     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
15246 
15247     /* Skip if function is not implemented for type */
15248     if (false == isFunctionImplemented(function, type))
15249     {
15250         return true;
15251     }
15252 
15253     Utils::programInfo program(m_context);
15254     de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15255 
15256     prepareProgram(*function_object, program);
15257     prepareTestData(*function_object);
15258 
15259     /* Set up program */
15260     gl.useProgram(program.m_program_object_id);
15261     GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15262 
15263     for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15264     {
15265         testBegin(*function_object, program.m_program_object_id, vertex);
15266 
15267         gl.beginTransformFeedback(GL_POINTS);
15268         GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15269 
15270         gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15271         GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15272 
15273         gl.endTransformFeedback();
15274         GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15275 
15276         if (false == verifyResults(*function_object, vertex))
15277         {
15278             return false;
15279         }
15280     }
15281 
15282     return true;
15283 }
15284 
15285 /** Update transform feedback buffer and uniforms
15286  *
15287  * @param function_object Function object
15288  * @param program_id      Program object id
15289  * @param vertex          Vertex index
15290  **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15291 void BuiltinFunctionTest::testBegin(const functionObject &function_object, glw::GLuint program_id, glw::GLuint vertex)
15292 {
15293     const glw::GLuint arguments_stride   = function_object.getArgumentStride();
15294     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
15295     const glw::GLuint n_arguments        = function_object.getArgumentCount();
15296     const glw::GLuint result_buffer_size = function_object.getResultStride();
15297     const glw::GLuint vertex_offset      = arguments_stride * vertex;
15298 
15299     /* Update transform feedback buffer */
15300     std::vector<glw::GLubyte> transform_feedback_buffer_data;
15301     transform_feedback_buffer_data.resize(result_buffer_size);
15302 
15303     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15304     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15305 
15306     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15307                   GL_DYNAMIC_COPY);
15308     GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15309 
15310     gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15311                        result_buffer_size);
15312     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15313 
15314     /* Update VAO */
15315     gl.bindVertexArray(m_vertex_array_object_id);
15316     GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15317 
15318     for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15319     {
15320         const glw::GLuint argument_offset         = function_object.getArgumentOffset(argument);
15321         const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15322         const glw::GLuint n_columns               = Utils::getNumberOfColumnsForVariableType(argument_type);
15323         const glw::GLchar *uniform_name           = getUniformName(argument);
15324         const glw::GLint uniform_location         = gl.getUniformLocation(program_id, uniform_name);
15325         const glw::GLdouble *uniform_src          = (glw::GLdouble *)&m_argument_data[vertex_offset + argument_offset];
15326 
15327         GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15328 
15329         if (-1 == uniform_location)
15330         {
15331             TCU_FAIL("Inactive uniform");
15332         }
15333 
15334         if (1 == n_columns)
15335         {
15336             switch (Utils::getBaseVariableType(argument_type))
15337             {
15338             case Utils::VARIABLE_TYPE_DOUBLE:
15339             {
15340                 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15341 
15342                 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15343             }
15344             break;
15345             case Utils::VARIABLE_TYPE_UINT:
15346             {
15347                 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15348 
15349                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint *)uniform_src);
15350             }
15351             break;
15352             case Utils::VARIABLE_TYPE_INT:
15353             {
15354                 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15355 
15356                 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint *)uniform_src);
15357             }
15358             break;
15359             default:
15360                 TCU_FAIL("Not implemented");
15361             }
15362         }
15363         else
15364         {
15365             uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15366 
15367             p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15368         }
15369     }
15370 }
15371 
15372 /** Init GL obejcts
15373  *
15374  **/
testInit()15375 void BuiltinFunctionTest::testInit()
15376 {
15377     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
15378 
15379     gl.genBuffers(1, &m_transform_feedback_buffer_id);
15380     GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15381 
15382     gl.genVertexArrays(1, &m_vertex_array_object_id);
15383     GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15384 
15385     gl.enable(GL_RASTERIZER_DISCARD);
15386 }
15387 
15388 /** Checks if function result is an acceptable edge case
15389  *
15390  * @param function_object Function object
15391  * @param vertex          Vertex index
15392  *
15393  * @return true if all results are as expected, false otherwise
15394  **/
isResultEdgeCase(const functionObject & function_object,glw::GLuint vertex,const Utils::_variable_type result_type,const glw::GLvoid * expected_result_src,const glw::GLvoid * result_src)15395 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject &function_object, glw::GLuint vertex,
15396                                            const Utils::_variable_type result_type,
15397                                            const glw::GLvoid *expected_result_src, const glw::GLvoid *result_src)
15398 {
15399     FunctionEnum function_type = function_object.getFunctionEnum();
15400     switch (function_type)
15401     {
15402     // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15403     // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15404     // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15405     case FUNCTION_MOD:
15406     case FUNCTION_MOD_AGAINST_SCALAR:
15407     {
15408         const glw::GLuint arguments_stride   = function_object.getArgumentStride();
15409         const glw::GLuint vertex_offset      = arguments_stride * vertex;
15410         const glw::GLuint argument_1_offset  = function_object.getArgumentOffset(0);
15411         const glw::GLuint argument_2_offset  = function_object.getArgumentOffset(1);
15412         const glw::GLuint argument_1_index   = argument_1_offset + vertex_offset;
15413         const glw::GLuint argument_2_index   = argument_2_offset + vertex_offset;
15414         const glw::GLubyte *argument_1_bytes = &m_argument_data[argument_1_index];
15415         const glw::GLubyte *argument_2_bytes = &m_argument_data[argument_2_index];
15416         const glw::GLdouble *argument_1      = reinterpret_cast<const glw::GLdouble *>(argument_1_bytes);
15417         const glw::GLdouble *argument_2      = reinterpret_cast<const glw::GLdouble *>(argument_2_bytes);
15418         const glw::GLdouble *expected_result = reinterpret_cast<const glw::GLdouble *>(expected_result_src);
15419         const glw::GLdouble *actual_result   = reinterpret_cast<const glw::GLdouble *>(result_src);
15420         bool edge_case_present               = false;
15421         bool recheck                         = false;
15422 
15423         // verify if there is a mod(a, a) case and prepare new expected result
15424         const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15425         std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15426         for (glw::GLuint component = 0; component < n_components; ++component)
15427         {
15428             glw::GLdouble expected_result_component = expected_result[component];
15429             glw::GLdouble actual_result_component   = actual_result[component];
15430             glw::GLdouble argument_1_component      = argument_1[component];
15431             glw::GLdouble argument_2_component      = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15432 
15433             // if coresponding components of arguments are equal and if component of first argument
15434             // and component of result are equal then expected result must be corrected
15435             bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15436                                                           round(argument_1_component / argument_2_component));
15437             edge_case_present =
15438                 possible_edge_case && (m_epsilon > de::abs(argument_2_component - actual_result_component));
15439             recheck |= edge_case_present;
15440             corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15441         }
15442 
15443         // recheck test result with corrected expected result
15444         return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15445     }
15446     default:
15447         return false;
15448     }
15449 }
15450 
15451 /** Compare contents of transform feedback buffer with expected results
15452  *
15453  * @param function_object Function object
15454  * @param vertex          Vertex index
15455  *
15456  * @return true if all results are as expected, false otherwise
15457  **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15458 bool BuiltinFunctionTest::verifyResults(const functionObject &function_object, glw::GLuint vertex)
15459 {
15460     const glw::Functions &gl             = m_context.getRenderContext().getFunctions();
15461     bool test_result                     = true;
15462     const glw::GLuint n_results          = function_object.getResultCount();
15463     const glw::GLuint results_stride     = function_object.getResultStride();
15464     const glw::GLuint results_offset     = vertex * results_stride;
15465     const glw::GLubyte *expected_results = &m_expected_results_data[results_offset];
15466 
15467     /* Get transform feedback data */
15468     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15469     GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15470 
15471     glw::GLubyte *feedback_data = (glw::GLubyte *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15472     GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15473 
15474     for (glw::GLuint result = 0; result < n_results; ++result)
15475     {
15476         const Utils::_variable_type result_type = function_object.getResultType(result);
15477         const glw::GLuint result_offset         = function_object.getResultOffset(result);
15478 
15479         const glw::GLvoid *expected_result_src = expected_results + result_offset;
15480         const glw::GLvoid *result_src          = feedback_data + result_offset;
15481 
15482         if (compare(result_type, expected_result_src, result_src))
15483             continue;
15484 
15485         if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15486         {
15487             test_result = false;
15488             break;
15489         }
15490     }
15491 
15492     /* Unmap transform feedback buffer */
15493     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15494     GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15495 
15496     if (false == test_result)
15497     {
15498         const glw::GLuint argument_stride  = function_object.getArgumentStride();
15499         const glw::GLuint arguments_offset = vertex * argument_stride;
15500 
15501         m_context.getTestContext().getLog()
15502             << tcu::TestLog::Message << "Error. Invalid result." << tcu::TestLog::EndMessage;
15503 
15504         m_context.getTestContext().getLog()
15505             << tcu::TestLog::Message << "Function: " << function_object.getName() << tcu::TestLog::EndMessage;
15506 
15507         for (glw::GLuint result = 0; result < n_results; ++result)
15508         {
15509             const Utils::_variable_type result_type = function_object.getResultType(result);
15510             const glw::GLuint result_offset         = function_object.getResultOffset(result);
15511 
15512             const glw::GLvoid *expected_result_src = expected_results + result_offset;
15513             const glw::GLvoid *result_src          = feedback_data + result_offset;
15514 
15515             logVariableType(result_src, "Result", result_type);
15516             logVariableType(expected_result_src, "Expected result", result_type);
15517         }
15518 
15519         for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15520         {
15521             const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15522             const glw::GLubyte *argument_src  = &m_argument_data[arguments_offset + argument_offset];
15523 
15524             logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15525         }
15526 
15527         m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15528                                             << m_vertex_shader_code << tcu::TestLog::EndMessage;
15529     }
15530 
15531     return test_result;
15532 }
15533 
15534 /** Constructor.
15535  *
15536  *  @param context Rendering context.
15537  **/
GPUShaderFP64Tests(deqp::Context & context)15538 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context &context)
15539     : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15540 {
15541     /* Left blank on purpose */
15542 }
15543 
15544 /** Initializes a texture_storage_multisample test group.
15545  *
15546  **/
init(void)15547 void GPUShaderFP64Tests::init(void)
15548 {
15549     TestCaseGroup *fp64 = new TestCaseGroup(m_context, "fp64", "");
15550     fp64->addChild(new GPUShaderFP64Test1(m_context));
15551     fp64->addChild(new GPUShaderFP64Test2(m_context));
15552     fp64->addChild(new GPUShaderFP64Test3(m_context));
15553     fp64->addChild(new GPUShaderFP64Test4(m_context));
15554     fp64->addChild(new GPUShaderFP64Test5(m_context));
15555     fp64->addChild(new GPUShaderFP64Test6(m_context));
15556     fp64->addChild(new GPUShaderFP64Test7(m_context));
15557     fp64->addChild(new GPUShaderFP64Test8(m_context));
15558     fp64->addChild(new GPUShaderFP64Test9(m_context));
15559     addChild(fp64);
15560 
15561     TypeDefinition typeDefinition[] = {{"double", 1, 1}, {"dvec2", 1, 2},   {"dvec3", 1, 3},   {"dvec4", 1, 4},
15562                                        {"dmat2", 2, 2},  {"dmat2x3", 2, 3}, {"dmat2x4", 2, 4}, {"dmat3x2", 3, 2},
15563                                        {"dmat3", 3, 3},  {"dmat3x4", 3, 4}, {"dmat4x2", 4, 2}, {"dmat4x3", 4, 3},
15564                                        {"dmat4", 4, 4}};
15565 
15566     struct BuiltinFunctions
15567     {
15568         std::string name;
15569         FunctionEnum function;
15570     } builtinFunctions[] = {{"abs", FUNCTION_ABS},
15571                             {"ceil", FUNCTION_CEIL},
15572                             {"clamp", FUNCTION_CLAMP},
15573                             {"clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR},
15574                             {"cross", FUNCTION_CROSS},
15575                             {"determinant", FUNCTION_DETERMINANT},
15576                             {"distance", FUNCTION_DISTANCE},
15577                             {"dot", FUNCTION_DOT},
15578                             {"equal", FUNCTION_EQUAL},
15579                             {"faceforward", FUNCTION_FACEFORWARD},
15580                             {"floor", FUNCTION_FLOOR},
15581                             {"fma", FUNCTION_FMA},
15582                             {"fract", FUNCTION_FRACT},
15583                             {"frexp", FUNCTION_FREXP},
15584                             {"greaterthan", FUNCTION_GREATERTHAN},
15585                             {"greaterthanequal", FUNCTION_GREATERTHANEQUAL},
15586                             {"inverse", FUNCTION_INVERSE},
15587                             {"inversesqrt", FUNCTION_INVERSESQRT},
15588                             {"ldexp", FUNCTION_LDEXP},
15589                             {"lessthan", FUNCTION_LESSTHAN},
15590                             {"lessthanequal", FUNCTION_LESSTHANEQUAL},
15591                             {"length", FUNCTION_LENGTH},
15592                             {"matrixcompmult", FUNCTION_MATRIXCOMPMULT},
15593                             {"max", FUNCTION_MAX},
15594                             {"max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR},
15595                             {"min", FUNCTION_MIN},
15596                             {"min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR},
15597                             {"mix", FUNCTION_MIX},
15598                             {"mod", FUNCTION_MOD},
15599                             {"mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR},
15600                             {"modf", FUNCTION_MODF},
15601                             {"normalize", FUNCTION_NORMALIZE},
15602                             {"notequal", FUNCTION_NOTEQUAL},
15603                             {"outerproduct", FUNCTION_OUTERPRODUCT},
15604                             {"packdouble2x32", FUNCTION_PACKDOUBLE2X32},
15605                             {"reflect", FUNCTION_REFLECT},
15606                             {"refract", FUNCTION_REFRACT},
15607                             {"round", FUNCTION_ROUND},
15608                             {"roundeven", FUNCTION_ROUNDEVEN},
15609                             {"sign", FUNCTION_SIGN},
15610                             {"smoothstep", FUNCTION_SMOOTHSTEP},
15611                             {"smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR},
15612                             {"sqrt", FUNCTION_SQRT},
15613                             {"step", FUNCTION_STEP},
15614                             {"step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR},
15615                             {"transpose", FUNCTION_TRANSPOSE},
15616                             {"trunc", FUNCTION_TRUNC},
15617                             {"unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32},
15618                             {"isnan", FUNCTION_ISNAN},
15619                             {"isinf", FUNCTION_ISINF}};
15620 
15621     TestCaseGroup *builin = new TestCaseGroup(m_context, "builtin", "");
15622     for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15623     {
15624         const BuiltinFunctions &bf = builtinFunctions[i];
15625         for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15626         {
15627             std::string caseName = bf.name + "_" + typeDefinition[j].name;
15628             builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15629         }
15630     }
15631     addChild(builin);
15632 }
15633 
15634 } // namespace gl4cts
15635