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 ¤t_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 ¤t_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 ¤t_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 ¤t_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