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
519 type = types[n_columns - 1][n_rows - 1];
520
521 return type;
522 }
523
524 /** Returns a single-precision equivalent of a double-precision floating-point variable
525 * type.
526 *
527 * @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
528 * are accepted.
529 *
530 * @return Requested GLSL type.
531 **/
getFPVariableTypeStringForVariableType(_variable_type type)532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
533 {
534 std::string result = "[?]";
535
536 switch (type)
537 {
538 case VARIABLE_TYPE_DOUBLE:
539 result = "float";
540 break;
541 case VARIABLE_TYPE_DMAT2:
542 result = "mat2";
543 break;
544 case VARIABLE_TYPE_DMAT2X3:
545 result = "mat2x3";
546 break;
547 case VARIABLE_TYPE_DMAT2X4:
548 result = "mat2x4";
549 break;
550 case VARIABLE_TYPE_DMAT3:
551 result = "mat3";
552 break;
553 case VARIABLE_TYPE_DMAT3X2:
554 result = "mat3x2";
555 break;
556 case VARIABLE_TYPE_DMAT3X4:
557 result = "mat3x4";
558 break;
559 case VARIABLE_TYPE_DMAT4:
560 result = "mat4";
561 break;
562 case VARIABLE_TYPE_DMAT4X2:
563 result = "mat4x2";
564 break;
565 case VARIABLE_TYPE_DMAT4X3:
566 result = "mat4x3";
567 break;
568 case VARIABLE_TYPE_DVEC2:
569 result = "vec2";
570 break;
571 case VARIABLE_TYPE_DVEC3:
572 result = "vec3";
573 break;
574 case VARIABLE_TYPE_DVEC4:
575 result = "vec4";
576 break;
577
578 default:
579 {
580 TCU_FAIL("Unrecognized variable type");
581 }
582 }; /* switch (type) */
583
584 return result;
585 }
586
587 /** Returns GL data type enum corresponding to user-provided base variable type.
588 *
589 * @param type Base variable type to return corresponding GLenum value for.
590 *
591 * @return Corresponding GLenum value or GL_NONE if the input value was not
592 * recognized.
593 **/
getGLDataTypeOfBaseVariableType(_variable_type type)594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
595 {
596 glw::GLenum result = GL_NONE;
597
598 switch (type)
599 {
600 case VARIABLE_TYPE_BOOL:
601 result = GL_BOOL;
602 break;
603 case VARIABLE_TYPE_DOUBLE:
604 result = GL_DOUBLE;
605 break;
606 case VARIABLE_TYPE_FLOAT:
607 result = GL_FLOAT;
608 break;
609 case VARIABLE_TYPE_INT:
610 result = GL_INT;
611 break;
612 case VARIABLE_TYPE_UINT:
613 result = GL_UNSIGNED_INT;
614 break;
615
616 default:
617 {
618 TCU_FAIL("Unrecognized variable type");
619 }
620 }
621
622 return result;
623 }
624
625 /** Return GLenum representing given <type>
626 *
627 * @param type Type of variable
628 *
629 * @return GL enumeration
630 **/
getGLDataTypeOfVariableType(_variable_type type)631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
632 {
633 glw::GLenum result = GL_NONE;
634
635 switch (type)
636 {
637 case VARIABLE_TYPE_BOOL:
638 result = GL_BOOL;
639 break;
640 case VARIABLE_TYPE_DOUBLE:
641 result = GL_DOUBLE;
642 break;
643 case VARIABLE_TYPE_DMAT2:
644 result = GL_DOUBLE_MAT2;
645 break;
646 case VARIABLE_TYPE_DMAT2X3:
647 result = GL_DOUBLE_MAT2x3;
648 break;
649 case VARIABLE_TYPE_DMAT2X4:
650 result = GL_DOUBLE_MAT2x4;
651 break;
652 case VARIABLE_TYPE_DMAT3:
653 result = GL_DOUBLE_MAT3;
654 break;
655 case VARIABLE_TYPE_DMAT3X2:
656 result = GL_DOUBLE_MAT3x2;
657 break;
658 case VARIABLE_TYPE_DMAT3X4:
659 result = GL_DOUBLE_MAT3x4;
660 break;
661 case VARIABLE_TYPE_DMAT4:
662 result = GL_DOUBLE_MAT4;
663 break;
664 case VARIABLE_TYPE_DMAT4X2:
665 result = GL_DOUBLE_MAT4x2;
666 break;
667 case VARIABLE_TYPE_DMAT4X3:
668 result = GL_DOUBLE_MAT4x3;
669 break;
670 case VARIABLE_TYPE_DVEC2:
671 result = GL_DOUBLE_VEC2;
672 break;
673 case VARIABLE_TYPE_DVEC3:
674 result = GL_DOUBLE_VEC3;
675 break;
676 case VARIABLE_TYPE_DVEC4:
677 result = GL_DOUBLE_VEC4;
678 break;
679 case VARIABLE_TYPE_FLOAT:
680 result = GL_FLOAT;
681 break;
682 case VARIABLE_TYPE_INT:
683 result = GL_INT;
684 break;
685 case VARIABLE_TYPE_IVEC2:
686 result = GL_INT_VEC2;
687 break;
688 case VARIABLE_TYPE_IVEC3:
689 result = GL_INT_VEC3;
690 break;
691 case VARIABLE_TYPE_IVEC4:
692 result = GL_INT_VEC4;
693 break;
694 case VARIABLE_TYPE_MAT2:
695 result = GL_FLOAT_MAT2;
696 break;
697 case VARIABLE_TYPE_MAT2X3:
698 result = GL_FLOAT_MAT2x3;
699 break;
700 case VARIABLE_TYPE_MAT2X4:
701 result = GL_FLOAT_MAT2x4;
702 break;
703 case VARIABLE_TYPE_MAT3:
704 result = GL_FLOAT_MAT3;
705 break;
706 case VARIABLE_TYPE_MAT3X2:
707 result = GL_FLOAT_MAT3x2;
708 break;
709 case VARIABLE_TYPE_MAT3X4:
710 result = GL_FLOAT_MAT3x4;
711 break;
712 case VARIABLE_TYPE_MAT4:
713 result = GL_FLOAT_MAT4;
714 break;
715 case VARIABLE_TYPE_MAT4X2:
716 result = GL_FLOAT_MAT4x2;
717 break;
718 case VARIABLE_TYPE_MAT4X3:
719 result = GL_FLOAT_MAT4x3;
720 break;
721 case VARIABLE_TYPE_UINT:
722 result = GL_UNSIGNED_INT;
723 break;
724 case VARIABLE_TYPE_UVEC2:
725 result = GL_UNSIGNED_INT_VEC2;
726 break;
727 case VARIABLE_TYPE_UVEC3:
728 result = GL_UNSIGNED_INT_VEC3;
729 break;
730 case VARIABLE_TYPE_UVEC4:
731 result = GL_UNSIGNED_INT_VEC4;
732 break;
733 case VARIABLE_TYPE_VEC2:
734 result = GL_FLOAT_VEC2;
735 break;
736 case VARIABLE_TYPE_VEC3:
737 result = GL_FLOAT_VEC3;
738 break;
739 case VARIABLE_TYPE_VEC4:
740 result = GL_FLOAT_VEC4;
741 break;
742
743 default:
744 {
745 TCU_FAIL("Unrecognized variable type");
746 }
747 }
748
749 return result;
750 }
751
752 /** Get _variable_type representing integer type with given dimmensions
753 *
754 * @param n_columns Number of columns
755 * @param n_row Number of rows
756 *
757 * @return Corresponding _variable_type
758 **/
getIntVariableType(glw::GLuint n_columns,glw::GLuint n_rows)759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
760 {
761 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
762
763 static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
764 VARIABLE_TYPE_IVEC4 };
765
766 if (1 != n_columns)
767 {
768 TCU_FAIL("Not implemented");
769 }
770 else
771 {
772 type = types[n_rows - 1];
773 }
774
775 return type;
776 }
777
778 /** Returns te number of components that variables defined with user-specified type
779 * support. For matrix types, total amount of values accessible for the type will be
780 * returned.
781 *
782 * @param type Variable type to return the described vale for.
783 *
784 * @return As per description or 0 if @param type was not recognized.
785 */
getNumberOfComponentsForVariableType(_variable_type type)786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
787 {
788 unsigned int result = 0;
789
790 switch (type)
791 {
792 case VARIABLE_TYPE_BOOL:
793 case VARIABLE_TYPE_DOUBLE:
794 case VARIABLE_TYPE_FLOAT:
795 case VARIABLE_TYPE_INT:
796 case VARIABLE_TYPE_UINT:
797 {
798 result = 1;
799
800 break;
801 }
802
803 case VARIABLE_TYPE_DVEC2:
804 case VARIABLE_TYPE_IVEC2:
805 case VARIABLE_TYPE_UVEC2:
806 case VARIABLE_TYPE_VEC2:
807 {
808 result = 2;
809
810 break;
811 }
812
813 case VARIABLE_TYPE_DVEC3:
814 case VARIABLE_TYPE_IVEC3:
815 case VARIABLE_TYPE_UVEC3:
816 case VARIABLE_TYPE_VEC3:
817 {
818 result = 3;
819
820 break;
821 }
822
823 case VARIABLE_TYPE_DVEC4:
824 case VARIABLE_TYPE_IVEC4:
825 case VARIABLE_TYPE_UVEC4:
826 case VARIABLE_TYPE_VEC4:
827 {
828 result = 4;
829
830 break;
831 }
832
833 case VARIABLE_TYPE_DMAT2:
834 case VARIABLE_TYPE_MAT2:
835 {
836 result = 2 * 2;
837
838 break;
839 }
840
841 case VARIABLE_TYPE_DMAT2X3:
842 case VARIABLE_TYPE_DMAT3X2:
843 case VARIABLE_TYPE_MAT2X3:
844 case VARIABLE_TYPE_MAT3X2:
845 {
846 result = 2 * 3;
847
848 break;
849 }
850
851 case VARIABLE_TYPE_DMAT2X4:
852 case VARIABLE_TYPE_DMAT4X2:
853 case VARIABLE_TYPE_MAT2X4:
854 case VARIABLE_TYPE_MAT4X2:
855 {
856 result = 2 * 4;
857
858 break;
859 }
860
861 case VARIABLE_TYPE_DMAT3:
862 case VARIABLE_TYPE_MAT3:
863 {
864 result = 3 * 3;
865
866 break;
867 }
868
869 case VARIABLE_TYPE_DMAT3X4:
870 case VARIABLE_TYPE_DMAT4X3:
871 case VARIABLE_TYPE_MAT3X4:
872 case VARIABLE_TYPE_MAT4X3:
873 {
874 result = 3 * 4;
875
876 break;
877 }
878
879 case VARIABLE_TYPE_DMAT4:
880 case VARIABLE_TYPE_MAT4:
881 {
882 result = 4 * 4;
883
884 break;
885 }
886
887 default:
888 {
889 TCU_FAIL("Unrecognized type");
890 }
891 } /* switch (type) */
892
893 return result;
894 }
895
896 /** Returns number of columns user-specified matrix variable type describes.
897 *
898 * @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
899 * values are valid.
900 *
901 * @return As per description.
902 **/
getNumberOfColumnsForVariableType(_variable_type type)903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
904 {
905 unsigned int result = 0;
906
907 switch (type)
908 {
909 case VARIABLE_TYPE_BOOL:
910 case VARIABLE_TYPE_DOUBLE:
911 case VARIABLE_TYPE_FLOAT:
912 case VARIABLE_TYPE_INT:
913 case VARIABLE_TYPE_UINT:
914 case VARIABLE_TYPE_DVEC2:
915 case VARIABLE_TYPE_IVEC2:
916 case VARIABLE_TYPE_UVEC2:
917 case VARIABLE_TYPE_VEC2:
918 case VARIABLE_TYPE_DVEC3:
919 case VARIABLE_TYPE_IVEC3:
920 case VARIABLE_TYPE_UVEC3:
921 case VARIABLE_TYPE_VEC3:
922 case VARIABLE_TYPE_DVEC4:
923 case VARIABLE_TYPE_IVEC4:
924 case VARIABLE_TYPE_UVEC4:
925 case VARIABLE_TYPE_VEC4:
926 {
927 result = 1;
928
929 break;
930 }
931
932 case VARIABLE_TYPE_DMAT2:
933 case VARIABLE_TYPE_DMAT2X3:
934 case VARIABLE_TYPE_DMAT2X4:
935 case VARIABLE_TYPE_MAT2:
936 case VARIABLE_TYPE_MAT2X3:
937 case VARIABLE_TYPE_MAT2X4:
938 {
939 result = 2;
940
941 break;
942 }
943
944 case VARIABLE_TYPE_DMAT3:
945 case VARIABLE_TYPE_DMAT3X2:
946 case VARIABLE_TYPE_DMAT3X4:
947 case VARIABLE_TYPE_MAT3:
948 case VARIABLE_TYPE_MAT3X2:
949 case VARIABLE_TYPE_MAT3X4:
950 {
951 result = 3;
952
953 break;
954 }
955
956 case VARIABLE_TYPE_DMAT4:
957 case VARIABLE_TYPE_DMAT4X2:
958 case VARIABLE_TYPE_DMAT4X3:
959 case VARIABLE_TYPE_MAT4:
960 case VARIABLE_TYPE_MAT4X2:
961 case VARIABLE_TYPE_MAT4X3:
962 {
963 result = 4;
964
965 break;
966 }
967
968 default:
969 {
970 TCU_FAIL("Unrecognized type");
971 }
972 } /* switch (type) */
973
974 return result;
975 }
976
977 /** Returns maximum number of uniform locations taken by user-specified double-precision
978 * variable type.
979 *
980 * @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
981 *
982 * @return As per description.
983 **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
985 {
986 unsigned int result = 0;
987
988 switch (type)
989 {
990 case VARIABLE_TYPE_DOUBLE:
991 result = 1;
992 break;
993 case VARIABLE_TYPE_DVEC2:
994 result = 1;
995 break;
996 case VARIABLE_TYPE_DVEC3:
997 result = 2;
998 break;
999 case VARIABLE_TYPE_DVEC4:
1000 result = 2;
1001 break;
1002 case VARIABLE_TYPE_DMAT2:
1003 result = 2;
1004 break;
1005 case VARIABLE_TYPE_DMAT2X3:
1006 result = 6;
1007 break;
1008 case VARIABLE_TYPE_DMAT2X4:
1009 result = 8;
1010 break;
1011 case VARIABLE_TYPE_DMAT3:
1012 result = 6;
1013 break;
1014 case VARIABLE_TYPE_DMAT3X2:
1015 result = 4;
1016 break;
1017 case VARIABLE_TYPE_DMAT3X4:
1018 result = 8;
1019 break;
1020 case VARIABLE_TYPE_DMAT4:
1021 result = 8;
1022 break;
1023 case VARIABLE_TYPE_DMAT4X2:
1024 result = 4;
1025 break;
1026 case VARIABLE_TYPE_DMAT4X3:
1027 result = 6;
1028 break;
1029
1030 default:
1031 {
1032 TCU_FAIL("Unrecognized type");
1033 }
1034 } /* switch (type) */
1035
1036 return result;
1037 }
1038
1039 /** Get number of rows for given variable type
1040 *
1041 * @param type Type of variable
1042 *
1043 * @return Number of rows
1044 **/
getNumberOfRowsForVariableType(_variable_type type)1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1046 {
1047 unsigned int result = 0;
1048
1049 switch (type)
1050 {
1051 case VARIABLE_TYPE_BOOL:
1052 case VARIABLE_TYPE_DOUBLE:
1053 case VARIABLE_TYPE_FLOAT:
1054 case VARIABLE_TYPE_INT:
1055 case VARIABLE_TYPE_UINT:
1056 {
1057 result = 1;
1058
1059 break;
1060 }
1061
1062 case VARIABLE_TYPE_DVEC2:
1063 case VARIABLE_TYPE_IVEC2:
1064 case VARIABLE_TYPE_UVEC2:
1065 case VARIABLE_TYPE_VEC2:
1066 case VARIABLE_TYPE_DMAT2:
1067 case VARIABLE_TYPE_DMAT3X2:
1068 case VARIABLE_TYPE_DMAT4X2:
1069 case VARIABLE_TYPE_MAT2:
1070 case VARIABLE_TYPE_MAT3X2:
1071 case VARIABLE_TYPE_MAT4X2:
1072 {
1073 result = 2;
1074
1075 break;
1076 }
1077
1078 case VARIABLE_TYPE_DVEC3:
1079 case VARIABLE_TYPE_IVEC3:
1080 case VARIABLE_TYPE_UVEC3:
1081 case VARIABLE_TYPE_VEC3:
1082 case VARIABLE_TYPE_DMAT2X3:
1083 case VARIABLE_TYPE_DMAT3:
1084 case VARIABLE_TYPE_DMAT4X3:
1085 case VARIABLE_TYPE_MAT2X3:
1086 case VARIABLE_TYPE_MAT3:
1087 case VARIABLE_TYPE_MAT4X3:
1088 {
1089 result = 3;
1090
1091 break;
1092 }
1093
1094 case VARIABLE_TYPE_DVEC4:
1095 case VARIABLE_TYPE_IVEC4:
1096 case VARIABLE_TYPE_UVEC4:
1097 case VARIABLE_TYPE_VEC4:
1098 case VARIABLE_TYPE_DMAT2X4:
1099 case VARIABLE_TYPE_DMAT3X4:
1100 case VARIABLE_TYPE_DMAT4:
1101 case VARIABLE_TYPE_MAT2X4:
1102 case VARIABLE_TYPE_MAT3X4:
1103 case VARIABLE_TYPE_MAT4:
1104 {
1105 result = 4;
1106
1107 break;
1108 }
1109
1110 default:
1111 {
1112 TCU_FAIL("Unrecognized type");
1113 }
1114 } /* switch (type) */
1115
1116 return result;
1117 }
1118
1119 /** Returns variable type of a matrix constructed by multiplying two matrices.
1120 *
1121 * @param type_matrix_a L-side matrix type.
1122 * @param type_matrix_b R-side matrix type.
1123 *
1124 * @return As per description.
1125 **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,_variable_type type_matrix_b)1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1127 _variable_type type_matrix_b)
1128 {
1129 const unsigned int n_a_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1130 const unsigned int n_a_components = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1131 const unsigned int n_a_rows = n_a_components / n_a_columns;
1132 const unsigned int n_b_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1133 const unsigned int n_result_columns = n_b_columns;
1134 const unsigned int n_result_rows = n_a_rows;
1135 Utils::_variable_type result;
1136
1137 switch (n_result_columns)
1138 {
1139 case 2:
1140 {
1141 switch (n_result_rows)
1142 {
1143 case 2:
1144 result = VARIABLE_TYPE_DMAT2;
1145 break;
1146 case 3:
1147 result = VARIABLE_TYPE_DMAT2X3;
1148 break;
1149 case 4:
1150 result = VARIABLE_TYPE_DMAT2X4;
1151 break;
1152
1153 default:
1154 {
1155 TCU_FAIL("Unrecognized amount of rows in result variable");
1156 }
1157 } /* switch (n_result_rows) */
1158
1159 break;
1160 } /* case 2: */
1161
1162 case 3:
1163 {
1164 switch (n_result_rows)
1165 {
1166 case 2:
1167 result = VARIABLE_TYPE_DMAT3X2;
1168 break;
1169 case 3:
1170 result = VARIABLE_TYPE_DMAT3;
1171 break;
1172 case 4:
1173 result = VARIABLE_TYPE_DMAT3X4;
1174 break;
1175
1176 default:
1177 {
1178 TCU_FAIL("Unrecognized amount of rows in result variable");
1179 }
1180 } /* switch (n_result_rows) */
1181
1182 break;
1183 } /* case 3: */
1184
1185 case 4:
1186 {
1187 switch (n_result_rows)
1188 {
1189 case 2:
1190 result = VARIABLE_TYPE_DMAT4X2;
1191 break;
1192 case 3:
1193 result = VARIABLE_TYPE_DMAT4X3;
1194 break;
1195 case 4:
1196 result = VARIABLE_TYPE_DMAT4;
1197 break;
1198
1199 default:
1200 {
1201 TCU_FAIL("Unrecognized amount of rows in result variable");
1202 }
1203 } /* switch (n_result_rows) */
1204
1205 break;
1206 } /* case 4: */
1207
1208 default:
1209 {
1210 TCU_FAIL("Unrecognized amount of columns in result variable");
1211 }
1212 } /* switch (n_result_columns) */
1213
1214 /* Done */
1215 return result;
1216 }
1217
1218 /** Returns a string holding the value represented by user-provided variable, for which
1219 * the data are represented in @param type variable type.
1220 *
1221 * @return As per description.
1222 **/
getStringForVariableTypeValue(_variable_type type,const unsigned char * data_ptr)1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)
1224 {
1225 std::stringstream result_sstream;
1226
1227 switch (type)
1228 {
1229 case VARIABLE_TYPE_BOOL:
1230 result_sstream << *((bool*)data_ptr);
1231 break;
1232 case VARIABLE_TYPE_DOUBLE:
1233 result_sstream << *((double*)data_ptr);
1234 break;
1235 case VARIABLE_TYPE_FLOAT:
1236 result_sstream << *((float*)data_ptr);
1237 break;
1238 case VARIABLE_TYPE_INT:
1239 result_sstream << *((int*)data_ptr);
1240 break;
1241 case VARIABLE_TYPE_UINT:
1242 result_sstream << *((unsigned int*)data_ptr);
1243 break;
1244
1245 default:
1246 {
1247 TCU_FAIL("Unrecognized variable type requested");
1248 }
1249 } /* switch (type) */
1250
1251 return result_sstream.str();
1252 }
1253
1254 /** Returns variable type of a transposed matrix of user-specified variable type.
1255 *
1256 * @param type Variable type of the matrix to be transposed.
1257 *
1258 * @return Transposed matrix variable type.
1259 **/
getTransposedMatrixVariableType(Utils::_variable_type type)1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1261 {
1262 Utils::_variable_type result;
1263
1264 switch (type)
1265 {
1266 case VARIABLE_TYPE_DMAT2:
1267 result = VARIABLE_TYPE_DMAT2;
1268 break;
1269 case VARIABLE_TYPE_DMAT2X3:
1270 result = VARIABLE_TYPE_DMAT3X2;
1271 break;
1272 case VARIABLE_TYPE_DMAT2X4:
1273 result = VARIABLE_TYPE_DMAT4X2;
1274 break;
1275 case VARIABLE_TYPE_DMAT3:
1276 result = VARIABLE_TYPE_DMAT3;
1277 break;
1278 case VARIABLE_TYPE_DMAT3X2:
1279 result = VARIABLE_TYPE_DMAT2X3;
1280 break;
1281 case VARIABLE_TYPE_DMAT3X4:
1282 result = VARIABLE_TYPE_DMAT4X3;
1283 break;
1284 case VARIABLE_TYPE_DMAT4:
1285 result = VARIABLE_TYPE_DMAT4;
1286 break;
1287 case VARIABLE_TYPE_DMAT4X2:
1288 result = VARIABLE_TYPE_DMAT2X4;
1289 break;
1290 case VARIABLE_TYPE_DMAT4X3:
1291 result = VARIABLE_TYPE_DMAT3X4;
1292 break;
1293
1294 default:
1295 {
1296 TCU_FAIL("Unrecognized double-precision matrix variable type.");
1297 }
1298 } /* switch (type) */
1299
1300 return result;
1301 }
1302
1303 /** Get _variable_type representing unsigned integer type with given dimmensions
1304 *
1305 * @param n_columns Number of columns
1306 * @param n_row Number of rows
1307 *
1308 * @return Corresponding _variable_type
1309 **/
getUintVariableType(glw::GLuint n_columns,glw::GLuint n_rows)1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1311 {
1312 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1313
1314 static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1315 VARIABLE_TYPE_UVEC4 };
1316
1317 if (1 != n_columns)
1318 {
1319 TCU_FAIL("Not implemented");
1320 }
1321 else
1322 {
1323 type = types[n_rows - 1];
1324 }
1325
1326 return type;
1327 }
1328
1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1330 * variable type.
1331 *
1332 * @param type Variable type to use for the query.
1333 *
1334 * @return Requested GLSL keyword or [?] if @param type was not recognized.
1335 **/
getVariableTypeString(_variable_type type)1336 std::string Utils::getVariableTypeString(_variable_type type)
1337 {
1338 std::string result = "[?]";
1339
1340 switch (type)
1341 {
1342 case VARIABLE_TYPE_BOOL:
1343 result = "bool";
1344 break;
1345 case VARIABLE_TYPE_BVEC2:
1346 result = "bvec2";
1347 break;
1348 case VARIABLE_TYPE_BVEC3:
1349 result = "bvec3";
1350 break;
1351 case VARIABLE_TYPE_BVEC4:
1352 result = "bvec4";
1353 break;
1354 case VARIABLE_TYPE_DOUBLE:
1355 result = "double";
1356 break;
1357 case VARIABLE_TYPE_DMAT2:
1358 result = "dmat2";
1359 break;
1360 case VARIABLE_TYPE_DMAT2X3:
1361 result = "dmat2x3";
1362 break;
1363 case VARIABLE_TYPE_DMAT2X4:
1364 result = "dmat2x4";
1365 break;
1366 case VARIABLE_TYPE_DMAT3:
1367 result = "dmat3";
1368 break;
1369 case VARIABLE_TYPE_DMAT3X2:
1370 result = "dmat3x2";
1371 break;
1372 case VARIABLE_TYPE_DMAT3X4:
1373 result = "dmat3x4";
1374 break;
1375 case VARIABLE_TYPE_DMAT4:
1376 result = "dmat4";
1377 break;
1378 case VARIABLE_TYPE_DMAT4X2:
1379 result = "dmat4x2";
1380 break;
1381 case VARIABLE_TYPE_DMAT4X3:
1382 result = "dmat4x3";
1383 break;
1384 case VARIABLE_TYPE_DVEC2:
1385 result = "dvec2";
1386 break;
1387 case VARIABLE_TYPE_DVEC3:
1388 result = "dvec3";
1389 break;
1390 case VARIABLE_TYPE_DVEC4:
1391 result = "dvec4";
1392 break;
1393 case VARIABLE_TYPE_FLOAT:
1394 result = "float";
1395 break;
1396 case VARIABLE_TYPE_INT:
1397 result = "int";
1398 break;
1399 case VARIABLE_TYPE_IVEC2:
1400 result = "ivec2";
1401 break;
1402 case VARIABLE_TYPE_IVEC3:
1403 result = "ivec3";
1404 break;
1405 case VARIABLE_TYPE_IVEC4:
1406 result = "ivec4";
1407 break;
1408 case VARIABLE_TYPE_MAT2:
1409 result = "mat2";
1410 break;
1411 case VARIABLE_TYPE_MAT2X3:
1412 result = "mat2x3";
1413 break;
1414 case VARIABLE_TYPE_MAT2X4:
1415 result = "mat2x4";
1416 break;
1417 case VARIABLE_TYPE_MAT3:
1418 result = "mat3";
1419 break;
1420 case VARIABLE_TYPE_MAT3X2:
1421 result = "mat3x2";
1422 break;
1423 case VARIABLE_TYPE_MAT3X4:
1424 result = "mat3x4";
1425 break;
1426 case VARIABLE_TYPE_MAT4:
1427 result = "mat4";
1428 break;
1429 case VARIABLE_TYPE_MAT4X2:
1430 result = "mat4x2";
1431 break;
1432 case VARIABLE_TYPE_MAT4X3:
1433 result = "mat4x3";
1434 break;
1435 case VARIABLE_TYPE_UINT:
1436 result = "uint";
1437 break;
1438 case VARIABLE_TYPE_UVEC2:
1439 result = "uvec2";
1440 break;
1441 case VARIABLE_TYPE_UVEC3:
1442 result = "uvec3";
1443 break;
1444 case VARIABLE_TYPE_UVEC4:
1445 result = "uvec4";
1446 break;
1447 case VARIABLE_TYPE_VEC2:
1448 result = "vec2";
1449 break;
1450 case VARIABLE_TYPE_VEC3:
1451 result = "vec3";
1452 break;
1453 case VARIABLE_TYPE_VEC4:
1454 result = "vec4";
1455 break;
1456
1457 default:
1458 {
1459 TCU_FAIL("Unrecognized variable type");
1460 }
1461 }; /* switch (type) */
1462
1463 return result;
1464 }
1465
1466 /** Check if GL context meets version requirements
1467 *
1468 * @param gl Functions
1469 * @param required_major Minimum required MAJOR_VERSION
1470 * @param required_minor Minimum required MINOR_VERSION
1471 *
1472 * @return true if GL context version is at least as requested, false otherwise
1473 **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
1475 {
1476 glw::GLint major = 0;
1477 glw::GLint minor = 0;
1478
1479 gl.getIntegerv(GL_MAJOR_VERSION, &major);
1480 gl.getIntegerv(GL_MINOR_VERSION, &minor);
1481
1482 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483
1484 if (major > required_major)
1485 {
1486 /* Major is higher than required one */
1487 return true;
1488 }
1489 else if (major == required_major)
1490 {
1491 if (minor >= required_minor)
1492 {
1493 /* Major is equal to required one */
1494 /* Minor is higher than or equal to required one */
1495 return true;
1496 }
1497 else
1498 {
1499 /* Major is equal to required one */
1500 /* Minor is lower than required one */
1501 return false;
1502 }
1503 }
1504 else
1505 {
1506 /* Major is lower than required one */
1507 return false;
1508 }
1509 }
1510
1511 /** Tells whether user-specified variable type corresponds to a matrix type.
1512 *
1513 * @param type Variable type to use for the query.
1514 *
1515 * @return true if the variable type describes a matrix, false otherwise.
1516 **/
isMatrixVariableType(_variable_type type)1517 bool Utils::isMatrixVariableType(_variable_type type)
1518 {
1519 return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1520 type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1521 type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1522 type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1523 type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1524 type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1525 }
1526
1527 /** Tells whether user-specified variable type is scalar.
1528 *
1529 * @return true if @param type is a scalar variable type, false otherwise.
1530 **/
isScalarVariableType(_variable_type type)1531 bool Utils::isScalarVariableType(_variable_type type)
1532 {
1533 bool result = false;
1534
1535 switch (type)
1536 {
1537 case VARIABLE_TYPE_BOOL:
1538 result = true;
1539 break;
1540 case VARIABLE_TYPE_DOUBLE:
1541 result = true;
1542 break;
1543 case VARIABLE_TYPE_FLOAT:
1544 result = true;
1545 break;
1546 case VARIABLE_TYPE_INT:
1547 result = true;
1548 break;
1549 case VARIABLE_TYPE_UINT:
1550 result = true;
1551 break;
1552 default:
1553 break;
1554 }; /* switch (type) */
1555
1556 return result;
1557 }
1558
1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1560 *
1561 * @param token Token string
1562 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1563 * @param text String that will be used as replacement for <token>
1564 * @param string String to work on
1565 **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
1567 std::string& string)
1568 {
1569 const size_t text_length = strlen(text);
1570 const size_t token_length = strlen(token);
1571 const size_t token_position = string.find(token, search_position);
1572
1573 string.replace(token_position, token_length, text, text_length);
1574
1575 search_position = token_position + text_length;
1576 }
1577
1578 /** Constructor.
1579 *
1580 * @param context Rendering context.
1581 *
1582 **/
GPUShaderFP64Test1(deqp::Context & context)1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context)
1584 : TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision "
1585 "float uniform support & glUniform*() / glUniformMatrix*() API "
1586 " are reported correctly.")
1587 , m_has_test_passed(true)
1588 , m_po_bool_arr_uniform_location(0)
1589 , m_po_bool_uniform_location(0)
1590 , m_po_bvec2_arr_uniform_location(0)
1591 , m_po_bvec2_uniform_location(0)
1592 , m_po_bvec3_arr_uniform_location(0)
1593 , m_po_bvec3_uniform_location(0)
1594 , m_po_bvec4_arr_uniform_location(0)
1595 , m_po_bvec4_uniform_location(0)
1596 , m_po_dmat2_arr_uniform_location(0)
1597 , m_po_dmat2_uniform_location(0)
1598 , m_po_dmat2x3_arr_uniform_location(0)
1599 , m_po_dmat2x3_uniform_location(0)
1600 , m_po_dmat2x4_arr_uniform_location(0)
1601 , m_po_dmat2x4_uniform_location(0)
1602 , m_po_dmat3_arr_uniform_location(0)
1603 , m_po_dmat3_uniform_location(0)
1604 , m_po_dmat3x2_arr_uniform_location(0)
1605 , m_po_dmat3x2_uniform_location(0)
1606 , m_po_dmat3x4_arr_uniform_location(0)
1607 , m_po_dmat3x4_uniform_location(0)
1608 , m_po_dmat4_arr_uniform_location(0)
1609 , m_po_dmat4_uniform_location(0)
1610 , m_po_dmat4x2_arr_uniform_location(0)
1611 , m_po_dmat4x2_uniform_location(0)
1612 , m_po_dmat4x3_arr_uniform_location(0)
1613 , m_po_dmat4x3_uniform_location(0)
1614 , m_po_double_arr_uniform_location(0)
1615 , m_po_double_uniform_location(0)
1616 , m_po_dvec2_arr_uniform_location(0)
1617 , m_po_dvec2_uniform_location(0)
1618 , m_po_dvec3_arr_uniform_location(0)
1619 , m_po_dvec3_uniform_location(0)
1620 , m_po_dvec4_arr_uniform_location(0)
1621 , m_po_dvec4_uniform_location(0)
1622 , m_po_float_arr_uniform_location(0)
1623 , m_po_float_uniform_location(0)
1624 , m_po_int_arr_uniform_location(0)
1625 , m_po_int_uniform_location(0)
1626 , m_po_ivec2_arr_uniform_location(0)
1627 , m_po_ivec2_uniform_location(0)
1628 , m_po_ivec3_arr_uniform_location(0)
1629 , m_po_ivec3_uniform_location(0)
1630 , m_po_ivec4_arr_uniform_location(0)
1631 , m_po_ivec4_uniform_location(0)
1632 , m_po_sampler_uniform_location(0)
1633 , m_po_uint_arr_uniform_location(0)
1634 , m_po_uint_uniform_location(0)
1635 , m_po_uvec2_arr_uniform_location(0)
1636 , m_po_uvec2_uniform_location(0)
1637 , m_po_uvec3_arr_uniform_location(0)
1638 , m_po_uvec3_uniform_location(0)
1639 , m_po_uvec4_arr_uniform_location(0)
1640 , m_po_uvec4_uniform_location(0)
1641 , m_po_vec2_arr_uniform_location(0)
1642 , m_po_vec2_uniform_location(0)
1643 , m_po_vec3_arr_uniform_location(0)
1644 , m_po_vec3_uniform_location(0)
1645 , m_po_vec4_arr_uniform_location(0)
1646 , m_po_vec4_uniform_location(0)
1647 , m_po_id(0)
1648 , m_vs_id(0)
1649 {
1650 /* Left blank intentionally */
1651 }
1652
1653 /** Deinitializes all GL objects that may have been created during
1654 * test execution.
1655 **/
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[] = {
2250 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2251 };
2252 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2253 bool result = true;
2254 glw::GLint uniform_locations[] = { m_po_bool_arr_uniform_location, m_po_bool_uniform_location,
2255 m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2256 m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2257 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location };
2258 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2259
2260 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2261 ++n_uniform_function)
2262 {
2263 const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2264
2265 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2266 {
2267 const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2268
2269 switch (uniform_function)
2270 {
2271 case UNIFORM_FUNCTION_1D:
2272 gl.uniform1d(uniform_location, 0.0);
2273 break;
2274 case UNIFORM_FUNCTION_2D:
2275 gl.uniform2d(uniform_location, 0.0, 1.0);
2276 break;
2277 case UNIFORM_FUNCTION_3D:
2278 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2279 break;
2280 case UNIFORM_FUNCTION_4D:
2281 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2282 break;
2283
2284 case UNIFORM_FUNCTION_1DV:
2285 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2286 break;
2287 case UNIFORM_FUNCTION_2DV:
2288 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2289 break;
2290 case UNIFORM_FUNCTION_3DV:
2291 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2292 break;
2293 case UNIFORM_FUNCTION_4DV:
2294 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2295 break;
2296
2297 case UNIFORM_FUNCTION_MATRIX2DV:
2298 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2299 break;
2300 case UNIFORM_FUNCTION_MATRIX2X3DV:
2301 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2302 break;
2303 case UNIFORM_FUNCTION_MATRIX2X4DV:
2304 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2305 break;
2306 case UNIFORM_FUNCTION_MATRIX3DV:
2307 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2308 break;
2309 case UNIFORM_FUNCTION_MATRIX3X2DV:
2310 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2311 break;
2312 case UNIFORM_FUNCTION_MATRIX3X4DV:
2313 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2314 break;
2315 case UNIFORM_FUNCTION_MATRIX4DV:
2316 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2317 break;
2318 case UNIFORM_FUNCTION_MATRIX4X2DV:
2319 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2320 break;
2321 case UNIFORM_FUNCTION_MATRIX4X3DV:
2322 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2323 break;
2324
2325 default:
2326 {
2327 TCU_FAIL("Unrecognized uniform function");
2328 }
2329 }
2330
2331 /* Make sure GL_INVALID_OPERATION was generated by the call */
2332 const glw::GLenum error_code = gl.getError();
2333
2334 if (error_code != GL_INVALID_OPERATION)
2335 {
2336 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2337 << "() did not generate an error"
2338 " when applied against a boolean uniform."
2339 << tcu::TestLog::EndMessage;
2340
2341 result = false;
2342 }
2343 } /* for (all bool uniforms) */
2344 } /* for (all uniform functions) */
2345
2346 return result;
2347 }
2348
2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2350 * glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2351 *
2352 * @return true if the implementation was found to behave as expected, false otherwise.
2353 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2355 {
2356 const double double_data[] = {
2357 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2358 };
2359 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2360 bool result = true;
2361
2362 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2363 ++n_uniform_function)
2364 {
2365 _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2366
2367 switch (uniform_function)
2368 {
2369 case UNIFORM_FUNCTION_1D:
2370 gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2371 break;
2372 case UNIFORM_FUNCTION_2D:
2373 gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2374 break;
2375 case UNIFORM_FUNCTION_3D:
2376 gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2377 break;
2378 case UNIFORM_FUNCTION_4D:
2379 gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2380 break;
2381
2382 case UNIFORM_FUNCTION_1DV:
2383 gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2384 break;
2385 case UNIFORM_FUNCTION_2DV:
2386 gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2387 break;
2388 case UNIFORM_FUNCTION_3DV:
2389 gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2390 break;
2391 case UNIFORM_FUNCTION_4DV:
2392 gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2393 break;
2394
2395 case UNIFORM_FUNCTION_MATRIX2DV:
2396 gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2397 break;
2398 case UNIFORM_FUNCTION_MATRIX2X3DV:
2399 gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2400 break;
2401 case UNIFORM_FUNCTION_MATRIX2X4DV:
2402 gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2403 break;
2404 case UNIFORM_FUNCTION_MATRIX3DV:
2405 gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2406 break;
2407 case UNIFORM_FUNCTION_MATRIX3X2DV:
2408 gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2409 break;
2410 case UNIFORM_FUNCTION_MATRIX3X4DV:
2411 gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2412 break;
2413 case UNIFORM_FUNCTION_MATRIX4DV:
2414 gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2415 break;
2416 case UNIFORM_FUNCTION_MATRIX4X2DV:
2417 gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2418 break;
2419 case UNIFORM_FUNCTION_MATRIX4X3DV:
2420 gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2421 break;
2422
2423 default:
2424 {
2425 TCU_FAIL("Unrecognized uniform function");
2426 }
2427 }
2428
2429 /* Make sure GL_INVALID_OPERATION was generated by the call */
2430 const glw::GLenum error_code = gl.getError();
2431
2432 if (error_code != GL_INVALID_OPERATION)
2433 {
2434 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2435 << "() did not generate an error"
2436 " when applied against a sampler uniform."
2437 << tcu::TestLog::EndMessage;
2438
2439 result = false;
2440 }
2441 } /* for (all uniform functions) */
2442
2443 return result;
2444 }
2445
2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2447 * glUniformMatrix*dv() functions is used to load a compatible uniform using an
2448 * invalid <count> argument.
2449 *
2450 * @return true if the implementation was found to behave as expected, false otherwise.
2451 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2453 {
2454 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
2455 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2456 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2457 bool result = true;
2458 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV,
2459 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV,
2460 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2461 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2462 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2463 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2464 UNIFORM_FUNCTION_MATRIX4X3DV };
2465 const glw::GLint uniforms[] = {
2466 m_po_bool_uniform_location, m_po_bvec2_uniform_location, m_po_bvec3_uniform_location,
2467 m_po_bvec4_uniform_location, m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location,
2468 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, m_po_dmat3x2_uniform_location,
2469 m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location,
2470 m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2471 m_po_dvec3_uniform_location, m_po_dvec4_uniform_location, m_po_float_uniform_location,
2472 m_po_int_uniform_location, m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
2473 m_po_ivec4_uniform_location, m_po_uint_uniform_location, m_po_uvec2_uniform_location,
2474 m_po_uvec3_uniform_location, m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
2475 m_po_vec3_uniform_location, m_po_vec4_uniform_location
2476 };
2477
2478 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2479 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
2480
2481 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2482 {
2483 _uniform_function uniform_function = uniform_functions[n_uniform_function];
2484
2485 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2486 {
2487 glw::GLint uniform_location = uniforms[n_uniform];
2488
2489 /* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2490 * and glUniform*() functions with vector uniforms.
2491 */
2492 bool is_matrix_uniform = isMatrixUniform(uniform_location);
2493
2494 if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2495 ((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2496 {
2497 continue;
2498 }
2499
2500 /* Issue the call with an invalid <count> argument */
2501 switch (uniform_function)
2502 {
2503 case UNIFORM_FUNCTION_1DV:
2504 gl.uniform1dv(uniform_location, 2, double_values);
2505 break;
2506 case UNIFORM_FUNCTION_2DV:
2507 gl.uniform2dv(uniform_location, 2, double_values);
2508 break;
2509 case UNIFORM_FUNCTION_3DV:
2510 gl.uniform3dv(uniform_location, 2, double_values);
2511 break;
2512 case UNIFORM_FUNCTION_4DV:
2513 gl.uniform4dv(uniform_location, 2, double_values);
2514 break;
2515 case UNIFORM_FUNCTION_MATRIX2DV:
2516 gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2517 break;
2518 case UNIFORM_FUNCTION_MATRIX2X3DV:
2519 gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2520 break;
2521 case UNIFORM_FUNCTION_MATRIX2X4DV:
2522 gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2523 break;
2524 case UNIFORM_FUNCTION_MATRIX3DV:
2525 gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2526 break;
2527 case UNIFORM_FUNCTION_MATRIX3X2DV:
2528 gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2529 break;
2530 case UNIFORM_FUNCTION_MATRIX3X4DV:
2531 gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2532 break;
2533 case UNIFORM_FUNCTION_MATRIX4DV:
2534 gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2535 break;
2536 case UNIFORM_FUNCTION_MATRIX4X2DV:
2537 gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2538 break;
2539 case UNIFORM_FUNCTION_MATRIX4X3DV:
2540 gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2541 break;
2542
2543 default:
2544 {
2545 TCU_FAIL("Unrecognized uniform function");
2546 }
2547 } /* switch (uniform_function) */
2548
2549 /* Make sure GL_INVALID_VALUE was generated */
2550 glw::GLenum error_code = gl.getError();
2551
2552 if (error_code != GL_INVALID_OPERATION)
2553 {
2554 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2555 << "() "
2556 "was called with an invalid count argument but did not generate a "
2557 "GL_INVALID_OPERATION error"
2558 << tcu::TestLog::EndMessage;
2559
2560 result = false;
2561 }
2562 } /* for (all non-arrayed uniforms) */
2563 } /* for (all uniform functions) */
2564
2565 return result;
2566 }
2567
2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2569 * glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2570 *
2571 * @return true if the implementation was found to behave as expected, false otherwise.
2572 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2574 {
2575 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2576 bool result = true;
2577
2578 /* Find the largest valid uniform location */
2579 const glw::GLint uniform_locations[] = {
2580 m_po_bool_arr_uniform_location, m_po_bool_uniform_location, m_po_bvec2_arr_uniform_location,
2581 m_po_bvec2_uniform_location, m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2582 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location, m_po_dmat2_arr_uniform_location,
2583 m_po_dmat2_uniform_location, m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2584 m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location, m_po_dmat3_arr_uniform_location,
2585 m_po_dmat3_uniform_location, m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2586 m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location, m_po_dmat4_arr_uniform_location,
2587 m_po_dmat4_uniform_location, m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2588 m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location, m_po_double_arr_uniform_location,
2589 m_po_double_uniform_location, m_po_dvec2_arr_uniform_location, m_po_dvec2_uniform_location,
2590 m_po_dvec3_arr_uniform_location, m_po_dvec3_uniform_location, m_po_dvec4_arr_uniform_location,
2591 m_po_dvec4_uniform_location, m_po_float_arr_uniform_location, m_po_float_uniform_location,
2592 m_po_int_arr_uniform_location, m_po_int_uniform_location, m_po_ivec2_arr_uniform_location,
2593 m_po_ivec2_uniform_location, m_po_ivec3_arr_uniform_location, m_po_ivec3_uniform_location,
2594 m_po_ivec4_arr_uniform_location, m_po_ivec4_uniform_location, m_po_uint_arr_uniform_location,
2595 m_po_uint_uniform_location, m_po_uvec2_arr_uniform_location, m_po_uvec2_uniform_location,
2596 m_po_uvec3_arr_uniform_location, m_po_uvec3_uniform_location, m_po_uvec4_arr_uniform_location,
2597 m_po_uvec4_uniform_location, m_po_vec2_arr_uniform_location, m_po_vec2_uniform_location,
2598 m_po_vec3_arr_uniform_location, m_po_vec3_uniform_location, m_po_vec4_arr_uniform_location,
2599 m_po_vec4_uniform_location
2600 };
2601 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2602 glw::GLint valid_uniform_location = -1;
2603
2604 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2605 {
2606 glw::GLint uniform_location = uniform_locations[n_uniform_location];
2607
2608 if (uniform_location > valid_uniform_location)
2609 {
2610 valid_uniform_location = uniform_location;
2611 }
2612 } /* for (all uniform locations) */
2613
2614 /* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2615 * for invalid uniform location that is != -1
2616 */
2617 const double double_data[] = {
2618 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2619 };
2620 const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2621
2622 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2623 ++n_uniform_function)
2624 {
2625 _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2626
2627 switch (uniform_function)
2628 {
2629 case UNIFORM_FUNCTION_1D:
2630 gl.uniform1d(invalid_uniform_location, 0.0);
2631 break;
2632 case UNIFORM_FUNCTION_2D:
2633 gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2634 break;
2635 case UNIFORM_FUNCTION_3D:
2636 gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2637 break;
2638 case UNIFORM_FUNCTION_4D:
2639 gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2640 break;
2641
2642 case UNIFORM_FUNCTION_1DV:
2643 gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2644 break;
2645 case UNIFORM_FUNCTION_2DV:
2646 gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2647 break;
2648 case UNIFORM_FUNCTION_3DV:
2649 gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2650 break;
2651 case UNIFORM_FUNCTION_4DV:
2652 gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2653 break;
2654
2655 case UNIFORM_FUNCTION_MATRIX2DV:
2656 gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657 break;
2658 case UNIFORM_FUNCTION_MATRIX2X3DV:
2659 gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660 break;
2661 case UNIFORM_FUNCTION_MATRIX2X4DV:
2662 gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663 break;
2664 case UNIFORM_FUNCTION_MATRIX3DV:
2665 gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666 break;
2667 case UNIFORM_FUNCTION_MATRIX3X2DV:
2668 gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669 break;
2670 case UNIFORM_FUNCTION_MATRIX3X4DV:
2671 gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672 break;
2673 case UNIFORM_FUNCTION_MATRIX4DV:
2674 gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675 break;
2676 case UNIFORM_FUNCTION_MATRIX4X2DV:
2677 gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2678 break;
2679 case UNIFORM_FUNCTION_MATRIX4X3DV:
2680 gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2681 break;
2682
2683 default:
2684 {
2685 TCU_FAIL("Unrecognized uniform function");
2686 }
2687 }
2688
2689 const glw::GLenum error_code = gl.getError();
2690
2691 if (error_code != GL_INVALID_OPERATION)
2692 {
2693 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2694 << "() did not generate an error"
2695 " when passed an invalid uniform location different from -1."
2696 << tcu::TestLog::EndMessage;
2697
2698 result = false;
2699 }
2700 } /* for (all uniform functions) */
2701
2702 return result;
2703 }
2704
2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2706 * glUniformMatrix*dv() functions is used to load a compatible uniform using an
2707 * invalid <count> argument of -1.
2708 *
2709 * @return true if the implementation was found to behave as expected, false otherwise.
2710 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2712 {
2713 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
2714 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2715 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2716 bool result = true;
2717 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV,
2718 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV,
2719 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2720 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2721 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2722 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2723 UNIFORM_FUNCTION_MATRIX4X3DV };
2724 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2725
2726 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2727 {
2728 _uniform_function uniform_function = uniform_functions[n_uniform_function];
2729
2730 switch (uniform_function)
2731 {
2732 case UNIFORM_FUNCTION_1DV:
2733 gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2734 break;
2735 case UNIFORM_FUNCTION_2DV:
2736 gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2737 break;
2738 case UNIFORM_FUNCTION_3DV:
2739 gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2740 break;
2741 case UNIFORM_FUNCTION_4DV:
2742 gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2743 break;
2744 case UNIFORM_FUNCTION_MATRIX2DV:
2745 gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2746 break;
2747 case UNIFORM_FUNCTION_MATRIX2X3DV:
2748 gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2749 break;
2750 case UNIFORM_FUNCTION_MATRIX2X4DV:
2751 gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2752 break;
2753 case UNIFORM_FUNCTION_MATRIX3DV:
2754 gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2755 break;
2756 case UNIFORM_FUNCTION_MATRIX3X2DV:
2757 gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2758 break;
2759 case UNIFORM_FUNCTION_MATRIX3X4DV:
2760 gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2761 break;
2762 case UNIFORM_FUNCTION_MATRIX4DV:
2763 gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2764 break;
2765 case UNIFORM_FUNCTION_MATRIX4X2DV:
2766 gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2767 break;
2768 case UNIFORM_FUNCTION_MATRIX4X3DV:
2769 gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2770 break;
2771
2772 default:
2773 {
2774 TCU_FAIL("Unrecognized uniform function");
2775 }
2776 } /* switch (uniform_function) */
2777
2778 /* Make sure GL_INVALID_VALUE was generated */
2779 glw::GLenum error_code = gl.getError();
2780
2781 if (error_code != GL_INVALID_VALUE)
2782 {
2783 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2784 << "() "
2785 "was called with a negative count argument but did not generate a "
2786 "GL_INVALID_VALUE error"
2787 << tcu::TestLog::EndMessage;
2788
2789 result = false;
2790 }
2791 } /* for (all uniform functions) */
2792
2793 return result;
2794 }
2795
2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2797 * glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2798 * function (as per spec).
2799 *
2800 * @return true if the implementation was found to behave as expected, false otherwise.
2801 **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2803 {
2804 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2805 glw::GLenum error_code = GL_NO_ERROR;
2806 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2807 bool result = true;
2808
2809 const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location,
2810 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,
2811 m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2812 m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location,
2813 m_po_dmat4x3_uniform_location, m_po_double_uniform_location,
2814 m_po_dvec2_uniform_location, m_po_dvec3_uniform_location,
2815 m_po_dvec4_uniform_location };
2816 const unsigned int n_double_uniform_locations =
2817 sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2818
2819 gl.useProgram(m_po_id);
2820 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2821
2822 for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2823 {
2824 glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2825
2826 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2827 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2828 {
2829 _uniform_function e_function = static_cast<_uniform_function>(function);
2830 /* Exclude valid combinations */
2831 if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2832 ((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2833 ((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2834 ((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2835 ((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2836 ((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2837 ((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2838 ((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2839 ((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2840 ((uniform_location == m_po_double_uniform_location) &&
2841 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2842 ((uniform_location == m_po_dvec2_uniform_location) &&
2843 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2844 ((uniform_location == m_po_dvec3_uniform_location) &&
2845 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2846 ((uniform_location == m_po_dvec4_uniform_location) &&
2847 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2848 {
2849 continue;
2850 }
2851
2852 switch (e_function)
2853 {
2854 case UNIFORM_FUNCTION_1D:
2855 {
2856 gl.uniform1d(uniform_location, double_data[0]);
2857
2858 break;
2859 }
2860
2861 case UNIFORM_FUNCTION_2D:
2862 {
2863 gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2864
2865 break;
2866 }
2867
2868 case UNIFORM_FUNCTION_3D:
2869 {
2870 gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2871
2872 break;
2873 }
2874
2875 case UNIFORM_FUNCTION_4D:
2876 {
2877 gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2878
2879 break;
2880 }
2881
2882 case UNIFORM_FUNCTION_1DV:
2883 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2884 break;
2885 case UNIFORM_FUNCTION_2DV:
2886 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2887 break;
2888 case UNIFORM_FUNCTION_3DV:
2889 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2890 break;
2891 case UNIFORM_FUNCTION_4DV:
2892 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2893 break;
2894 case UNIFORM_FUNCTION_MATRIX2DV:
2895 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2896 break;
2897 case UNIFORM_FUNCTION_MATRIX2X3DV:
2898 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2899 break;
2900 case UNIFORM_FUNCTION_MATRIX2X4DV:
2901 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2902 break;
2903 case UNIFORM_FUNCTION_MATRIX3DV:
2904 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2905 break;
2906 case UNIFORM_FUNCTION_MATRIX3X2DV:
2907 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2908 break;
2909 case UNIFORM_FUNCTION_MATRIX3X4DV:
2910 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2911 break;
2912 case UNIFORM_FUNCTION_MATRIX4DV:
2913 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2914 break;
2915 case UNIFORM_FUNCTION_MATRIX4X2DV:
2916 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2917 break;
2918 case UNIFORM_FUNCTION_MATRIX4X3DV:
2919 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2920 break;
2921
2922 default:
2923 {
2924 TCU_FAIL("Unrecognized function");
2925 }
2926 } /* switch (function) */
2927
2928 /* Make sure GL_INVALID_OPERATION error was generated */
2929 error_code = gl.getError();
2930
2931 if (error_code != GL_INVALID_OPERATION)
2932 {
2933 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2934 << "] was generated when a mismatched "
2935 "double-precision uniform function "
2936 << getUniformFunctionString(e_function) << "() was used to configure uniform "
2937 << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2938
2939 result = false;
2940 }
2941 } /* for (all uniform functions) */
2942 } /* for (all uniform locations) */
2943
2944 return result;
2945 }
2946
2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2948 * glUniform*dv() functions is used to load an uniform, size of which is incompatible
2949 * with the function.
2950 *
2951 * @return true if the implementation was found to behave as expected, false otherwise.
2952 **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2954 {
2955 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2956 glw::GLenum error_code = GL_NO_ERROR;
2957 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2958 bool result = true;
2959
2960 const int data[] = {
2961 /* API function */ /* Uniform location */ /* Count (dv functions only) */
2962 (int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV,
2963 m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0,
2964 (int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2965 m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2,
2966 (int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2967 m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0,
2968 (int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2969 m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2,
2970 (int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2971 m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0,
2972 (int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2973 m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2,
2974 (int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2975 m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0,
2976 (int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D,
2977 m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2,
2978 };
2979 const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
2980
2981 gl.useProgram(m_po_id);
2982 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2983
2984 for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
2985 {
2986 _uniform_function function = (_uniform_function)data[n_check * 3 + 0];
2987 int uniform_location = data[n_check * 3 + 1];
2988 int uniform_count = data[n_check * 3 + 2];
2989
2990 switch (function)
2991 {
2992 case UNIFORM_FUNCTION_1D:
2993 gl.uniform1d(uniform_location, 0.0);
2994 break;
2995 case UNIFORM_FUNCTION_1DV:
2996 gl.uniform1dv(uniform_location, uniform_count, double_data);
2997 break;
2998 case UNIFORM_FUNCTION_2D:
2999 gl.uniform2d(uniform_location, 0.0, 1.0);
3000 break;
3001 case UNIFORM_FUNCTION_2DV:
3002 gl.uniform2dv(uniform_location, uniform_count, double_data);
3003 break;
3004 case UNIFORM_FUNCTION_3D:
3005 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3006 break;
3007 case UNIFORM_FUNCTION_3DV:
3008 gl.uniform3dv(uniform_location, uniform_count, double_data);
3009 break;
3010 case UNIFORM_FUNCTION_4D:
3011 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3012 break;
3013 case UNIFORM_FUNCTION_4DV:
3014 gl.uniform4dv(uniform_location, uniform_count, double_data);
3015 break;
3016
3017 default:
3018 {
3019 DE_ASSERT(false);
3020 }
3021 } /* switch (function) */
3022
3023 error_code = gl.getError();
3024 if (error_code != GL_INVALID_OPERATION)
3025 {
3026 m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3027 << "() function did not generate GL_INVALID_OPERATION error when called for"
3028 " a uniform of incompatible size. (check index: "
3029 << n_check << ")" << tcu::TestLog::EndMessage;
3030
3031 result = false;
3032 }
3033 } /* for (all checks) */
3034
3035 return result;
3036 }
3037
3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3039 * glUniform*dv() functions is used to load an uniform, type of which is incompatible
3040 * with the function.
3041 *
3042 * @return true if the implementation was found to behave as expected, false otherwise.
3043 **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3045 {
3046 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
3047 glw::GLenum error_code = GL_NO_ERROR;
3048 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3049 bool result = true;
3050
3051 const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location, m_po_bvec2_uniform_location,
3052 m_po_bvec3_uniform_location, m_po_bvec4_uniform_location,
3053 m_po_float_uniform_location, m_po_int_uniform_location,
3054 m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
3055 m_po_ivec4_uniform_location, m_po_uint_uniform_location,
3056 m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3057 m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
3058 m_po_vec3_uniform_location, m_po_vec4_uniform_location };
3059 const unsigned int n_nondouble_uniform_locations =
3060 sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3061
3062 gl.useProgram(m_po_id);
3063 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3064
3065 for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3066 {
3067 glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3068
3069 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3070 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3071 {
3072 switch (static_cast<_uniform_function>(function))
3073 {
3074 case UNIFORM_FUNCTION_1D:
3075 gl.uniform1d(uniform_location, 0.0);
3076 break;
3077 case UNIFORM_FUNCTION_1DV:
3078 gl.uniform1dv(uniform_location, 1, double_data);
3079 break;
3080 case UNIFORM_FUNCTION_2D:
3081 gl.uniform2d(uniform_location, 0.0, 1.0);
3082 break;
3083 case UNIFORM_FUNCTION_2DV:
3084 gl.uniform2dv(uniform_location, 1, double_data);
3085 break;
3086 case UNIFORM_FUNCTION_3D:
3087 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3088 break;
3089 case UNIFORM_FUNCTION_3DV:
3090 gl.uniform3dv(uniform_location, 1, double_data);
3091 break;
3092 case UNIFORM_FUNCTION_4D:
3093 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3094 break;
3095 case UNIFORM_FUNCTION_4DV:
3096 gl.uniform4dv(uniform_location, 1, double_data);
3097 break;
3098
3099 case UNIFORM_FUNCTION_MATRIX2DV:
3100 gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3101 break;
3102 case UNIFORM_FUNCTION_MATRIX2X3DV:
3103 gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3104 break;
3105 case UNIFORM_FUNCTION_MATRIX2X4DV:
3106 gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3107 break;
3108 case UNIFORM_FUNCTION_MATRIX3DV:
3109 gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3110 break;
3111 case UNIFORM_FUNCTION_MATRIX3X2DV:
3112 gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3113 break;
3114 case UNIFORM_FUNCTION_MATRIX3X4DV:
3115 gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3116 break;
3117 case UNIFORM_FUNCTION_MATRIX4DV:
3118 gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3119 break;
3120 case UNIFORM_FUNCTION_MATRIX4X2DV:
3121 gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3122 break;
3123 case UNIFORM_FUNCTION_MATRIX4X3DV:
3124 gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3125 break;
3126
3127 default:
3128 {
3129 DE_ASSERT(false);
3130 }
3131 } /* switch (function) */
3132
3133 error_code = gl.getError();
3134 if (error_code != GL_INVALID_OPERATION)
3135 {
3136 m_testCtx.getLog() << tcu::TestLog::Message
3137 << getUniformFunctionString(static_cast<_uniform_function>(function))
3138 << "() function did not generate GL_INVALID_OPERATION error when called for"
3139 " a uniform of incompatible type."
3140 << tcu::TestLog::EndMessage;
3141
3142 result = false;
3143 }
3144 }
3145 } /* for (all checks) */
3146
3147 return result;
3148 }
3149
3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3151 * glUniform*dv() functions are called without a bound program object.
3152 *
3153 * @return true if the implementation was found to behave as expected, false otherwise.
3154 **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3156 {
3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3158 bool result = true;
3159
3160 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3161 function++)
3162 {
3163 const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
3164
3165 switch (static_cast<_uniform_function>(function))
3166 {
3167 case UNIFORM_FUNCTION_1D:
3168 gl.uniform1d(m_po_double_uniform_location, 0.0);
3169 break;
3170 case UNIFORM_FUNCTION_1DV:
3171 gl.uniform1dv(m_po_double_uniform_location, 1, data);
3172 break;
3173 case UNIFORM_FUNCTION_2D:
3174 gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3175 break;
3176 case UNIFORM_FUNCTION_2DV:
3177 gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3178 break;
3179 case UNIFORM_FUNCTION_3D:
3180 gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3181 break;
3182 case UNIFORM_FUNCTION_3DV:
3183 gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3184 break;
3185 case UNIFORM_FUNCTION_4D:
3186 gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3187 break;
3188 case UNIFORM_FUNCTION_4DV:
3189 gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3190 break;
3191
3192 case UNIFORM_FUNCTION_MATRIX2DV:
3193 gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3194 break;
3195 case UNIFORM_FUNCTION_MATRIX2X3DV:
3196 gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3197 break;
3198 case UNIFORM_FUNCTION_MATRIX2X4DV:
3199 gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3200 break;
3201 case UNIFORM_FUNCTION_MATRIX3DV:
3202 gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3203 break;
3204 case UNIFORM_FUNCTION_MATRIX3X2DV:
3205 gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3206 break;
3207 case UNIFORM_FUNCTION_MATRIX3X4DV:
3208 gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3209 break;
3210 case UNIFORM_FUNCTION_MATRIX4DV:
3211 gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3212 break;
3213 case UNIFORM_FUNCTION_MATRIX4X2DV:
3214 gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3215 break;
3216 case UNIFORM_FUNCTION_MATRIX4X3DV:
3217 gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3218 break;
3219
3220 default:
3221 {
3222 TCU_FAIL("Unrecognized uniform function");
3223 }
3224 } /* switch (func) */
3225
3226 /* Query the error code */
3227 glw::GLenum error_code = gl.getError();
3228
3229 if (error_code != GL_INVALID_OPERATION)
3230 {
3231 m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3232 << getUniformFunctionString(static_cast<_uniform_function>(function))
3233 << "() was called without an active program object" << tcu::TestLog::EndMessage;
3234
3235 result = false;
3236 }
3237 } /* for (all uniform functions) */
3238
3239 return result;
3240 }
3241
3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3244 const glw::GLint GPUShaderFP64Test2::m_result_failure = 2;
3245 const glw::GLint GPUShaderFP64Test2::m_result_success = 1;
3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width = 32;
3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height = m_n_captured_results / m_texture_width;
3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3249 m_n_captured_results * sizeof(captured_varying_type);
3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name = "UniformBlock";
3251 const glw::GLenum GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3252
3253 /** Constructor
3254 *
3255 * @param context Test context
3256 **/
GPUShaderFP64Test2(deqp::Context & context)3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context)
3258 : TestCase(context, "max_uniform_components",
3259 "Verifies that maximum allowed uniform components can be used as double-precision float types")
3260 , m_pDispatchCompute(0)
3261 , m_framebuffer_id(0)
3262 , m_texture_id(0)
3263 , m_transform_feedback_buffer_id(0)
3264 , m_uniform_buffer_id(0)
3265 , m_vertex_array_object_id(0)
3266 {
3267 /* Nothing to be done */
3268 }
3269
3270 /** Deinitialize test
3271 *
3272 **/
deinit()3273 void GPUShaderFP64Test2::deinit()
3274 {
3275 /* GL entry points */
3276 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3277
3278 /* Clean frambuffer */
3279 if (0 != m_framebuffer_id)
3280 {
3281 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3282 gl.deleteFramebuffers(1, &m_framebuffer_id);
3283 m_framebuffer_id = 0;
3284 }
3285
3286 /* Clean texture */
3287 if (0 != m_texture_id)
3288 {
3289 gl.bindTexture(GL_TEXTURE_2D, 0);
3290 gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3291 GL_READ_ONLY, GL_RGBA8);
3292 gl.deleteTextures(1, &m_texture_id);
3293 m_texture_id = 0;
3294 }
3295
3296 /* Clean buffers */
3297 if (0 != m_transform_feedback_buffer_id)
3298 {
3299 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3300 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3301 m_transform_feedback_buffer_id = 0;
3302 }
3303
3304 if (0 != m_uniform_buffer_id)
3305 {
3306 gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3307 gl.deleteBuffers(1, &m_uniform_buffer_id);
3308 m_uniform_buffer_id = 0;
3309 }
3310
3311 /* Clean VAO */
3312 if (0 != m_vertex_array_object_id)
3313 {
3314 gl.bindVertexArray(0);
3315 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3316 m_vertex_array_object_id = 0;
3317 }
3318 }
3319
3320 /** Execute test
3321 *
3322 * @return tcu::TestNode::STOP
3323 **/
iterate()3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3325 {
3326 bool result = true;
3327
3328 /* Check if extension is supported */
3329 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3330 {
3331 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3332 }
3333
3334 /* Initialize test */
3335 testInit();
3336
3337 prepareShaderStages();
3338 prepareUniformTypes();
3339
3340 /* For all shaders and uniform type combinations */
3341 for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3342 m_shader_stages.end() != shader_stage; ++shader_stage)
3343 {
3344 for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3345 m_uniform_types.end() != uniform_type; ++uniform_type)
3346 {
3347 /* Execute test */
3348 if (false == test(*shader_stage, *uniform_type))
3349 {
3350 result = false;
3351 }
3352 }
3353 }
3354
3355 /* Set result */
3356 if (true == result)
3357 {
3358 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3359 }
3360 else
3361 {
3362 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3363 }
3364
3365 /* Done */
3366 return tcu::TestNode::STOP;
3367 }
3368
3369 /** Constructor
3370 *
3371 * @param n_columns Number of columns
3372 * @param n_rows Number of rows
3373 **/
uniformTypeDetails(glw::GLuint n_columns,glw::GLuint n_rows)3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3375 : m_n_columns(n_columns), m_n_rows(n_rows)
3376 {
3377 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3378
3379 m_type_name = Utils::getVariableTypeString(type);
3380 m_type = Utils::getGLDataTypeOfVariableType(type);
3381 }
3382
3383 /** Get primitive type captured with transform feedback
3384 *
3385 * @param shader_stage Tested shader stage id
3386 *
3387 * @return Primitive type
3388 **/
getCapturedPrimitiveType(shaderStage shader_stage) const3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3390 {
3391 switch (shader_stage)
3392 {
3393 case GEOMETRY_SHADER:
3394 case TESS_CTRL_SHADER:
3395 case TESS_EVAL_SHADER:
3396 case VERTEX_SHADER:
3397 return GL_POINTS;
3398 break;
3399
3400 default:
3401 return GL_NONE;
3402 break;
3403 }
3404 }
3405
3406 /** Get primitive type drawn with DrawArrays
3407 *
3408 * @param shader_stage Tested shader stage id
3409 *
3410 * @return Primitive type
3411 **/
getDrawPrimitiveType(shaderStage shader_stage) const3412 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3413 {
3414 switch (shader_stage)
3415 {
3416 case FRAGMENT_SHADER:
3417 return GL_TRIANGLE_FAN;
3418 break;
3419
3420 case GEOMETRY_SHADER:
3421 case VERTEX_SHADER:
3422 return GL_POINTS;
3423 break;
3424
3425 case TESS_CTRL_SHADER:
3426 case TESS_EVAL_SHADER:
3427 return GL_PATCHES;
3428 break;
3429
3430 default:
3431 return GL_NONE;
3432 break;
3433 }
3434 }
3435
3436 /** Get maximum allowed number of uniform components
3437 *
3438 * @param shader_stage Tested shader stage id
3439 *
3440 * @return Maxmimum uniform components
3441 **/
getMaxUniformComponents(shaderStage shader_stage) const3442 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3443 {
3444 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3445 glw::GLint max_uniform_components = 0;
3446 glw::GLenum pname = 0;
3447
3448 switch (shader_stage)
3449 {
3450 case COMPUTE_SHADER:
3451 pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3452 break;
3453 case FRAGMENT_SHADER:
3454 pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3455 break;
3456 case GEOMETRY_SHADER:
3457 pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3458 break;
3459 case TESS_CTRL_SHADER:
3460 pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3461 break;
3462 case TESS_EVAL_SHADER:
3463 pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3464 break;
3465 case VERTEX_SHADER:
3466 pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3467 break;
3468 }
3469
3470 gl.getIntegerv(pname, &max_uniform_components);
3471 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3472
3473 return max_uniform_components;
3474 }
3475
3476 /** Get maximum size allowed for an uniform block
3477 *
3478 * @return Maxmimum uniform block size
3479 **/
getMaxUniformBlockSize() const3480 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3481 {
3482 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3483 glw::GLint max_uniform_block_size = 0;
3484
3485 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3486 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3487
3488 return max_uniform_block_size;
3489 }
3490
3491 /** Get number of components required to store single uniform of given type
3492 *
3493 * @param uniform_type Tested uniform type
3494 *
3495 * @return Number of components
3496 **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3497 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3498 {
3499 static const glw::GLuint type_size = 2; /* double takes 2 N */
3500 const glw::GLuint column_length = uniform_type.m_n_rows;
3501
3502 if (1 == uniform_type.m_n_columns)
3503 {
3504 return type_size * column_length;
3505 }
3506 else
3507 {
3508 const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3509
3510 return alignment * uniform_type.m_n_columns;
3511 }
3512 }
3513
3514 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3515 *
3516 * @param uniform_type Tested uniform type
3517 *
3518 * @return Size of a single member
3519 **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3520 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3521 {
3522 static const glw::GLuint vec4_size = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3523 const glw::GLuint column_length = uniform_type.m_n_rows;
3524
3525 /** Size for a layout(std140, column_major) uniform_type uniform[] **/
3526 return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3527 }
3528
3529 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3530 *
3531 * @param shader_stage Tested shader stage id
3532 * @param uniform_type Tested uniform type
3533 *
3534 * @return Number of components
3535 **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3536 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage shader_stage,
3537 const uniformTypeDetails& uniform_type) const
3538 {
3539 const glw::GLuint max_uniform_components = getMaxUniformComponents(shader_stage);
3540 const glw::GLuint required_components = getRequiredComponentsNumber(uniform_type);
3541 const glw::GLuint n_uniforms = max_uniform_components / required_components;
3542 const glw::GLuint max_uniform_block_size = getMaxUniformBlockSize();
3543 const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3544 const glw::GLuint max_uniforms = max_uniform_block_size / uniform_type_member_size;
3545
3546 return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3547 }
3548
3549 /** Get name of shader stage
3550 *
3551 * @param shader_stage Tested shader stage id
3552 *
3553 * @return Name
3554 **/
getShaderStageName(shaderStage shader_stage) const3555 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3556 {
3557 switch (shader_stage)
3558 {
3559 case COMPUTE_SHADER:
3560 return "compute shader";
3561 break;
3562 case FRAGMENT_SHADER:
3563 return "fragment shader";
3564 break;
3565 case GEOMETRY_SHADER:
3566 return "geometry shader";
3567 break;
3568 case TESS_CTRL_SHADER:
3569 return "tesselation control shader";
3570 break;
3571 case TESS_EVAL_SHADER:
3572 return "tesselation evaluation shader";
3573 break;
3574 case VERTEX_SHADER:
3575 return "vertex shader";
3576 break;
3577 }
3578
3579 return 0;
3580 }
3581
3582 /** Inspect program to get: buffer_size, offset, strides and block index
3583 *
3584 * @param program_id Program id
3585 * @param out_buffer_size Size of uniform buffer
3586 * @param out_uniform_details Uniform offset and strides
3587 * @param uniform_block_index Uniform block index
3588 **/
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) const3589 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3590 const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3591 uniformDetails& out_uniform_details, glw::GLuint uniform_block_index) const
3592 {
3593 glw::GLint array_stride = 0;
3594 std::vector<glw::GLchar> extracted_uniform_name;
3595 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3596 glw::GLuint index = 0;
3597 glw::GLint matrix_stride = 0;
3598 glw::GLint offset = 0;
3599 glw::GLsizei size = 0;
3600 glw::GLenum type = 0;
3601 const glw::GLchar* uniform_name = 0;
3602 std::string uniform_name_str;
3603 std::stringstream uniform_name_stream;
3604
3605 /* Get index of uniform block */
3606 uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3607 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3608
3609 if (GL_INVALID_INDEX == uniform_block_index)
3610 {
3611 TCU_FAIL("Unifom block is inactive");
3612 }
3613
3614 /* Get size of uniform block */
3615 gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3616 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3617
3618 if (0 == out_buffer_size)
3619 {
3620 TCU_FAIL("Unifom block size is 0");
3621 }
3622
3623 /* Prepare uniform name */
3624 uniform_name_stream << "uniform_array";
3625
3626 uniform_name_str = uniform_name_stream.str();
3627 uniform_name = uniform_name_str.c_str();
3628
3629 /* Get index of uniform */
3630 gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3632
3633 if (GL_INVALID_INDEX == index)
3634 {
3635 TCU_FAIL("Unifom is inactive");
3636 }
3637
3638 /* Verify getActiveUniform results */
3639 extracted_uniform_name.resize(uniform_name_str.length() * 2);
3640
3641 gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3642 &extracted_uniform_name[0]);
3643 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3644
3645 if ((n_uniforms != size) || (uniform_type.m_type != type))
3646 {
3647 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3648 << " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3649 << " expected: " << uniform_type.m_type
3650 << ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3651
3652 TCU_FAIL("Invalid GetActiveUniform results");
3653 }
3654
3655 /* Get offset of uniform */
3656 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3657 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3658
3659 if (-1 == offset)
3660 {
3661 TCU_FAIL("Unifom has invalid offset");
3662 }
3663
3664 out_uniform_details.m_offset = offset;
3665
3666 /* Get matrix stride of uniform */
3667 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3668 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3669
3670 if (-1 == matrix_stride)
3671 {
3672 TCU_FAIL("Unifom has invalid matrix stride");
3673 }
3674
3675 out_uniform_details.m_matrix_stride = matrix_stride;
3676
3677 /* Get array stride of uniform */
3678 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3679 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3680
3681 if (-1 == matrix_stride)
3682 {
3683 TCU_FAIL("Unifom has invalid matrix stride");
3684 }
3685
3686 out_uniform_details.m_array_stride = array_stride;
3687 }
3688
3689 /** Prepare source code for "boilerplate" shaders
3690 *
3691 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3692 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3693 * @param out_source_code Source code
3694 **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3695 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3696 const glw::GLchar* stage_specific_main_body,
3697 std::string& out_source_code) const
3698 {
3699 /* Shader template */
3700 static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3701 "\n"
3702 "precision highp float;\n"
3703 "\n"
3704 "STAGE_SPECIFIC_LAYOUT"
3705 "void main()\n"
3706 "{\n"
3707 "STAGE_SPECIFIC_MAIN_BODY"
3708 "}\n"
3709 "\n";
3710
3711 std::string string = boilerplate_shader_template_code;
3712
3713 /* Tokens */
3714 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
3715 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3716
3717 size_t search_position = 0;
3718
3719 /* Replace tokens */
3720 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3721 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3722
3723 /* Store resuls */
3724 out_source_code = string;
3725 }
3726
3727 /** Prepare program for given combination of shader stage and uniform type
3728 *
3729 * @param shader_stage Shader stage
3730 * @param uniform_type Uniform type
3731 * @param out_program_info Instance of programInfo
3732 **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3733 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3734 Utils::programInfo& out_program_info) const
3735 {
3736 /* Stage specific layouts */
3737 static const glw::GLchar* geometry_shader_layout_code = "layout(points) in;\n"
3738 "layout(points, max_vertices = 1) out;\n"
3739 "\n";
3740
3741 static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3742 "\n";
3743
3744 static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3745 "\n";
3746
3747 /* Stage specific main body */
3748 static const glw::GLchar* boilerplate_fragment_shader_body_code = " discard;\n";
3749
3750 static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = " gl_TessLevelOuter[0] = 1.0;\n"
3751 " gl_TessLevelOuter[1] = 1.0;\n"
3752 " gl_TessLevelOuter[2] = 1.0;\n"
3753 " gl_TessLevelOuter[3] = 1.0;\n"
3754 " gl_TessLevelInner[0] = 1.0;\n"
3755 " gl_TessLevelInner[1] = 1.0;\n";
3756
3757 static const glw::GLchar* boilerplate_vertex_shader_body_code = " gl_Position = vec4(1, 0, 0, 1);\n";
3758
3759 static const glw::GLchar* corner_vertex_shader_body_code = " if (0 == gl_VertexID)\n"
3760 " {\n"
3761 " gl_Position = vec4(-1, -1, 0, 1);\n"
3762 " }\n"
3763 " else if (1 == gl_VertexID)\n"
3764 " {\n"
3765 " gl_Position = vec4(-1, 1, 0, 1);\n"
3766 " }\n"
3767 " else if (2 == gl_VertexID)\n"
3768 " {\n"
3769 " gl_Position = vec4(1, 1, 0, 1);\n"
3770 " }\n"
3771 " else if (3 == gl_VertexID)\n"
3772 " {\n"
3773 " gl_Position = vec4(1, -1, 0, 1);\n"
3774 " }\n";
3775
3776 static const glw::GLchar* passthrough_tess_eval_shader_body_code = " result = tcs_tes_result[0];\n";
3777
3778 static const glw::GLchar* test_shader_body_code = "\n result = verification_result;\n";
3779
3780 static const glw::GLchar* test_geometry_shader_body_code = "\n result = verification_result;\n"
3781 "\n"
3782 " EmitVertex();\n"
3783 " EndPrimitive();\n";
3784
3785 static const glw::GLchar* test_tess_ctrl_shader_body_code =
3786 "\n tcs_tes_result[gl_InvocationID] = verification_result;\n"
3787 "\n"
3788 " gl_TessLevelOuter[0] = 1.0;\n"
3789 " gl_TessLevelOuter[1] = 1.0;\n"
3790 " gl_TessLevelOuter[2] = 1.0;\n"
3791 " gl_TessLevelOuter[3] = 1.0;\n"
3792 " gl_TessLevelInner[0] = 1.0;\n"
3793 " gl_TessLevelInner[1] = 1.0;\n";
3794
3795 /* In variables */
3796 static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in int tcs_tes_result[];\n";
3797
3798 /* Out variables */
3799 static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3800
3801 static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3802
3803 static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3804
3805 /* Varying name */
3806 static const glw::GLchar* varying_name = "result";
3807 glw::GLuint n_varyings = 1;
3808
3809 /* Storage for ready shaders */
3810 std::string compute_shader_code;
3811 std::string fragment_shader_code;
3812 std::string geometry_shader_code;
3813 std::string tess_ctrl_shader_code;
3814 std::string tess_eval_shader_code;
3815 std::string vertex_shader_code;
3816
3817 /* Storage for uniform definition and verification code */
3818 std::string uniform_definitions;
3819 std::string uniform_verification;
3820
3821 /* Get uniform definition and verification code */
3822 prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3823 prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3824
3825 /* Prepare vertex shader */
3826 switch (shader_stage)
3827 {
3828 case FRAGMENT_SHADER:
3829
3830 prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3831
3832 break;
3833
3834 case GEOMETRY_SHADER:
3835 case TESS_CTRL_SHADER:
3836 case TESS_EVAL_SHADER:
3837
3838 prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3839
3840 break;
3841
3842 case VERTEX_SHADER:
3843
3844 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3845 test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3846 test_shader_body_code /* body */, vertex_shader_code);
3847
3848 break;
3849
3850 default:
3851 break;
3852 }
3853
3854 /* Prepare fragment shader */
3855 switch (shader_stage)
3856 {
3857 case FRAGMENT_SHADER:
3858
3859 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3860 test_fragment_shader_out_variable /* out var */,
3861 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3862 fragment_shader_code);
3863
3864 break;
3865
3866 case GEOMETRY_SHADER:
3867 case TESS_CTRL_SHADER:
3868 case TESS_EVAL_SHADER:
3869 case VERTEX_SHADER:
3870
3871 prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3872 fragment_shader_code);
3873
3874 break;
3875
3876 default:
3877 break;
3878 }
3879
3880 /* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3881 switch (shader_stage)
3882 {
3883 case COMPUTE_SHADER:
3884
3885 prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3886
3887 break;
3888
3889 case GEOMETRY_SHADER:
3890
3891 prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3892 "" /* in var */, test_shader_out_variable /* out var */,
3893 uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3894 geometry_shader_code);
3895
3896 break;
3897
3898 case TESS_CTRL_SHADER:
3899
3900 prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3901 "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3902 uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3903 tess_ctrl_shader_code);
3904
3905 prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3906 test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3907 "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3908 tess_eval_shader_code);
3909
3910 break;
3911
3912 case TESS_EVAL_SHADER:
3913
3914 prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3915 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3916
3917 prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3918 "" /* in var */, test_shader_out_variable /* out var */,
3919 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3920 tess_eval_shader_code);
3921
3922 break;
3923
3924 default:
3925 break;
3926 };
3927
3928 /* Select shaders that will be used by program */
3929 const glw::GLchar* cs_c_str = 0;
3930 const glw::GLchar* fs_c_str = 0;
3931 const glw::GLchar* gs_c_str = 0;
3932 const glw::GLchar* tcs_c_str = 0;
3933 const glw::GLchar* tes_c_str = 0;
3934 const glw::GLchar* vs_c_str = 0;
3935
3936 if (false == compute_shader_code.empty())
3937 {
3938 cs_c_str = compute_shader_code.c_str();
3939 }
3940
3941 if (false == fragment_shader_code.empty())
3942 {
3943 fs_c_str = fragment_shader_code.c_str();
3944 }
3945
3946 if (false == geometry_shader_code.empty())
3947 {
3948 gs_c_str = geometry_shader_code.c_str();
3949 }
3950
3951 if (false == tess_ctrl_shader_code.empty())
3952 {
3953 tcs_c_str = tess_ctrl_shader_code.c_str();
3954 }
3955
3956 if (false == tess_eval_shader_code.empty())
3957 {
3958 tes_c_str = tess_eval_shader_code.c_str();
3959 }
3960
3961 if (false == vertex_shader_code.empty())
3962 {
3963 vs_c_str = vertex_shader_code.c_str();
3964 }
3965
3966 /* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3967 if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3968 {
3969 n_varyings = 0;
3970 }
3971
3972 /* Build */
3973 out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
3974 }
3975
3976 /** Prepare collection of tested shader stages
3977 *
3978 */
prepareShaderStages()3979 void GPUShaderFP64Test2::prepareShaderStages()
3980 {
3981 /* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3982 if (0 != m_pDispatchCompute)
3983 {
3984 m_shader_stages.push_back(COMPUTE_SHADER);
3985 }
3986
3987 m_shader_stages.push_back(FRAGMENT_SHADER);
3988 m_shader_stages.push_back(GEOMETRY_SHADER);
3989 m_shader_stages.push_back(TESS_CTRL_SHADER);
3990 m_shader_stages.push_back(TESS_EVAL_SHADER);
3991 m_shader_stages.push_back(VERTEX_SHADER);
3992 }
3993
3994 /** Prepare source code for "tested" shader stage
3995 *
3996 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3997 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
3998 * @param in_variable_definitions String that will replace IN_VARIABLE_DEFINITION token
3999 * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
4000 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4001 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
4002 * @param out_source_code Shader source code
4003 **/
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) const4004 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
4005 const glw::GLchar* uniform_definitions,
4006 const glw::GLchar* in_variable_definitions,
4007 const glw::GLchar* out_variable_definitions,
4008 const glw::GLchar* uniform_verification,
4009 const glw::GLchar* stage_specific_main_body,
4010 std::string& out_source_code) const
4011 {
4012 /* Shader template */
4013 static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4014 "\n"
4015 "precision highp float;\n"
4016 "\n"
4017 "STAGE_SPECIFIC_LAYOUT"
4018 "UNIFORM_DEFINITIONS"
4019 "IN_VARIABLE_DEFINITION"
4020 "OUT_VARIABLE_DEFINITION"
4021 "\n"
4022 "void main()\n"
4023 "{\n"
4024 "UNIFORM_VERIFICATION"
4025 "STAGE_SPECIFIC_MAIN_BODY"
4026 "}\n"
4027 "\n";
4028
4029 std::string string = test_shader_template_code;
4030
4031 /* Tokens */
4032 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
4033 static const glw::GLchar* in_var_token = "IN_VARIABLE_DEFINITION";
4034 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
4035 static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4036 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4037 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4038
4039 size_t search_position = 0;
4040
4041 /* Replace tokens */
4042 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4043 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4044 Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4045 Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4046 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4047 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4048
4049 /* Store resuls */
4050 out_source_code = string;
4051 }
4052
4053 /** Prepare source code for "tested" compute shaders
4054 *
4055 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
4056 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4057 * @param out_source_code Source code
4058 **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4059 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4060 const glw::GLchar* uniform_verification,
4061 std::string& out_source_code) const
4062 {
4063 /* Shader template */
4064 static const glw::GLchar* test_shader_template_code =
4065 "#version 420 core\n"
4066 "#extension GL_ARB_compute_shader : require\n"
4067 "#extension GL_ARB_shader_image_load_store : require\n"
4068 "\n"
4069 "precision highp float;\n"
4070 "\n"
4071 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4072 "\n"
4073 "UNIFORM_DEFINITIONS"
4074 "layout(r32i) writeonly uniform iimage2D result;\n"
4075 "\n"
4076 "void main()\n"
4077 "{\n"
4078 "UNIFORM_VERIFICATION"
4079 "\n"
4080 " imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4081 "}\n"
4082 "\n";
4083
4084 std::string string = test_shader_template_code;
4085
4086 /* Tokens */
4087 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4088 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4089
4090 size_t search_position = 0;
4091
4092 /* Replace tokens */
4093 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4094 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4095
4096 /* Store resuls */
4097 out_source_code = string;
4098 }
4099
4100 /** Prepare source code which defines uniforms for tested shader stage
4101 *
4102 * @param shader_stage Shader stage id
4103 * @param uniform_type Details of uniform type
4104 * @param out_source_code Source code
4105 **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4106 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4107 std::string& out_source_code) const
4108 {
4109 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4110 std::stringstream stream;
4111
4112 /*
4113 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4114 * {
4115 * TYPE_NAME uniform_array[N_UNIFORMS];
4116 * };
4117 */
4118 stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4119 "{\n";
4120
4121 stream << " " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4122
4123 stream << "};\n\n";
4124
4125 out_source_code = stream.str();
4126 }
4127
4128 /** Prepare uniform buffer for test
4129 *
4130 * @param shader_stage Shader stage id
4131 * @param uniform_type Details of uniform type
4132 * @param program_info Program object info
4133 **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4134 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4135 const Utils::programInfo& program_info) const
4136 {
4137 glw::GLint buffer_size = 0;
4138 glw::GLuint element_ordinal = 1;
4139 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4140 const glw::GLuint n_columns = uniform_type.m_n_columns;
4141 const glw::GLuint n_rows = uniform_type.m_n_rows;
4142 const glw::GLuint n_elements = n_columns * n_rows;
4143 uniformDetails uniform_details;
4144 const glw::GLuint program_id = program_info.m_program_object_id;
4145 const glw::GLint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4146 std::vector<glw::GLubyte> uniform_buffer_data;
4147 glw::GLuint uniform_block_index = 0;
4148
4149 /* Get uniform details */
4150 inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4151
4152 /* Uniform offset and strides */
4153 const glw::GLuint array_stride = uniform_details.m_array_stride;
4154 const glw::GLuint matrix_stride = uniform_details.m_matrix_stride;
4155 const glw::GLuint uniform_offset = uniform_details.m_offset;
4156
4157 /* Prepare storage for buffer data */
4158 uniform_buffer_data.resize(buffer_size);
4159
4160 /* Prepare uniform data */
4161 for (glw::GLint i = 0; i < n_uniforms; ++i)
4162 {
4163 const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4164
4165 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4166 {
4167 const glw::GLuint column = element / n_rows;
4168 const glw::GLuint column_elem = element % n_rows;
4169 const glw::GLdouble value = element_ordinal;
4170 const glw::GLuint value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4171 column_elem * sizeof(glw::GLdouble));
4172 glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4173
4174 *value_dst = value;
4175 }
4176 }
4177
4178 /* Update uniform buffer with new set of data */
4179 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4180 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4181
4182 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4183 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4184
4185 /* Bind uniform block to uniform buffer */
4186 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4187 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4188
4189 gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4190 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4191 }
4192
4193 /** Prepare collection of tested uniform types
4194 *
4195 **/
prepareUniformTypes()4196 void GPUShaderFP64Test2::prepareUniformTypes()
4197 {
4198 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4199 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4200 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4201 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4202 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4203 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4204 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4205 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4206 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4207 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4208 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4209 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4210 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4211 }
4212
4213 /** Prepare source code that verifes uniform values
4214 *
4215 * @param shader_stage Shader stage id
4216 * @param uniform_type Details of uniform type
4217 * @param out_source_code Source code
4218 **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4219 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4220 std::string& out_source_code) const
4221 {
4222 glw::GLuint element_ordinal = 1;
4223 const glw::GLuint n_columns = uniform_type.m_n_columns;
4224 const glw::GLuint n_rows = uniform_type.m_n_rows;
4225 const glw::GLuint n_elements = n_columns * n_rows;
4226 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4227 std::stringstream stream;
4228
4229 /*
4230 * int verification_result = M_RESULT_SUCCESS;
4231 *
4232 * for (int i = 0; i < N_UNIFORMS; ++i)
4233 * {
4234 * if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4235 * {
4236 * verification_result = M_RESULT_FAILURE
4237 * }
4238 * }
4239 */
4240 stream << " int verification_result = " << m_result_success << ";\n"
4241 "\n"
4242 " for (int i = 0; i < "
4243 << n_uniforms << "; ++i)\n"
4244 " {\n"
4245 " if ("
4246 << uniform_type.m_type_name << "(";
4247
4248 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4249 {
4250 stream << "i * (" << n_elements << ") + " << element + 1;
4251
4252 if (n_elements != element + 1)
4253 {
4254 stream << ", ";
4255 }
4256 }
4257
4258 stream << ") != uniform_array[i])\n"
4259 " {\n"
4260 " verification_result = "
4261 << m_result_failure << ";\n"
4262 " }\n"
4263 " }\n";
4264
4265 out_source_code = stream.str();
4266 }
4267
4268 /** Execute test for given combination of "tested" shader stage and uniform type
4269 *
4270 * @param shader_stage Tested shader stage id
4271 * @param uniform_type Tested uniform type
4272 *
4273 * @return true if test passed, false otherwise
4274 **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4275 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4276 {
4277 const glw::GLenum draw_primitive = getDrawPrimitiveType(shader_stage);
4278 static const glw::GLint first_vertex = 0;
4279 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4280 const glw::GLsizei n_vertices = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4281 Utils::programInfo program_info(m_context);
4282 bool result = true;
4283
4284 /* Prepare program */
4285 prepareProgram(shader_stage, uniform_type, program_info);
4286
4287 gl.useProgram(program_info.m_program_object_id);
4288 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4289
4290 /* Prepare uniform buffer and bind it with uniform block */
4291 prepareUniforms(shader_stage, uniform_type, program_info);
4292
4293 /* Prepare storage for test results */
4294 testBegin(program_info.m_program_object_id, shader_stage);
4295
4296 /* Execute */
4297 if (COMPUTE_SHADER == shader_stage)
4298 {
4299 m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4300 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4301 }
4302 else
4303 {
4304 gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4305 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4306 }
4307
4308 /* Clean after test */
4309 testEnd(shader_stage);
4310
4311 /* Check results */
4312 if (false == verifyResults(shader_stage))
4313 {
4314 m_context.getTestContext().getLog()
4315 << tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4316 << ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4317
4318 result = false;
4319 }
4320
4321 return result;
4322 }
4323
4324 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4325 *
4326 * @param program_id Program object id
4327 * @param shader_stage Tested shader stage id
4328 **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4329 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4330 {
4331 std::vector<glw::GLint> buffer_data;
4332 const glw::GLenum captured_primitive = getCapturedPrimitiveType(shader_stage);
4333 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4334
4335 /* Prepare buffer filled with m_result_failure */
4336 buffer_data.resize(m_n_captured_results);
4337 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4338 {
4339 buffer_data[i] = m_result_failure;
4340 }
4341
4342 /* Prepare buffer for test results */
4343 switch (shader_stage)
4344 {
4345 case GEOMETRY_SHADER:
4346 case TESS_CTRL_SHADER:
4347 case TESS_EVAL_SHADER:
4348 case VERTEX_SHADER:
4349
4350 /* Verify getTransformFeedbackVarying results */
4351 {
4352 glw::GLsizei size = 0;
4353 glw::GLenum type = 0;
4354 glw::GLchar name[16];
4355
4356 gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4357 name);
4358 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4359
4360 if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4361 {
4362 m_context.getTestContext().getLog()
4363 << tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4364 << " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4365 << ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4366
4367 TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4368 }
4369 }
4370
4371 /* Create/clean transform feedback buffer */
4372 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4373 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4374
4375 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4376 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4377
4378 /* Set up transform feedback buffer */
4379 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4380 m_transform_feedback_buffer_size);
4381 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4382
4383 gl.beginTransformFeedback(captured_primitive);
4384 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4385
4386 break;
4387
4388 case FRAGMENT_SHADER:
4389
4390 /* Clean texture */
4391 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4392 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4393
4394 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4395 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4396 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4397
4398 /* Set up texture as color attachment 0 */
4399 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4400 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4401
4402 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4403 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4404
4405 gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4406 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4407
4408 break;
4409
4410 case COMPUTE_SHADER:
4411
4412 /* Clean texture */
4413 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4414 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4415
4416 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4417 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4418 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4419
4420 glw::GLint location = gl.getUniformLocation(program_id, "result");
4421 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4422
4423 if (-1 == location)
4424 {
4425 TCU_FAIL("Inactive uniform \"result\"");
4426 }
4427
4428 gl.uniform1i(location, 0 /* first image unit */);
4429 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4430
4431 /* Bind texture to first image unit */
4432 gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4433 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4434 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4435
4436 break;
4437 }
4438 }
4439
4440 /** Unbind transform feedback buffer, framebuffer or image unit
4441 *
4442 * @param shader_stage Tested shader stage id
4443 **/
testEnd(shaderStage shader_stage) const4444 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4445 {
4446 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4447
4448 switch (shader_stage)
4449 {
4450 case GEOMETRY_SHADER:
4451 case TESS_CTRL_SHADER:
4452 case TESS_EVAL_SHADER:
4453 case VERTEX_SHADER:
4454
4455 gl.endTransformFeedback();
4456
4457 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4458
4459 break;
4460
4461 case FRAGMENT_SHADER:
4462
4463 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4464 0 /* level */);
4465
4466 gl.bindTexture(GL_TEXTURE_2D, 0);
4467
4468 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4469
4470 break;
4471
4472 case COMPUTE_SHADER:
4473
4474 gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4475 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4476
4477 break;
4478 }
4479 }
4480
4481 /** Initialize OpenGL objects for test
4482 *
4483 **/
testInit()4484 void GPUShaderFP64Test2::testInit()
4485 {
4486 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4487
4488 /* The test is in 4.0 group. However:
4489 * - compute_shader is core since 4.3
4490 * - compute_shader require at least version 4.2 of GL */
4491 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4492 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4493 {
4494 m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4495 }
4496
4497 /* Tesselation patch set up */
4498 gl.patchParameteri(GL_PATCH_VERTICES, 1);
4499 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4500
4501 /* Generate FBO */
4502 gl.genFramebuffers(1, &m_framebuffer_id);
4503 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4504
4505 /* Prepare texture */
4506 gl.genTextures(1, &m_texture_id);
4507 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4508
4509 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4510 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4511
4512 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4513 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4514
4515 /* Prepare transform feedback buffer */
4516 gl.genBuffers(1, &m_transform_feedback_buffer_id);
4517 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4518
4519 /* Generate uniform buffer */
4520 gl.genBuffers(1, &m_uniform_buffer_id);
4521 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4522
4523 /* Prepare VAO */
4524 gl.genVertexArrays(1, &m_vertex_array_object_id);
4525 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4526
4527 gl.bindVertexArray(m_vertex_array_object_id);
4528 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4529 }
4530
4531 /** Result verification, expected result is that whole buffer is filled with m_result_success
4532 *
4533 * @param shader_stage Tested shader stage id
4534 **/
verifyResults(shaderStage shader_stage) const4535 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4536 {
4537 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4538
4539 if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4540 {
4541 /* Verify contents of texture */
4542
4543 /* Prepare storage for testure data */
4544 std::vector<glw::GLint> image_data;
4545 image_data.resize(m_texture_width * m_texture_height);
4546
4547 /* Get texture contents */
4548 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4549 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4550
4551 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4552 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4553
4554 for (glw::GLuint y = 0; y < m_texture_width; ++y)
4555 {
4556 for (glw::GLuint x = 0; x < m_texture_height; ++x)
4557 {
4558 const glw::GLuint offset = y * m_texture_width + x;
4559 const glw::GLint value = image_data[offset];
4560
4561 if (m_result_success != value)
4562 {
4563 m_context.getTestContext().getLog()
4564 << tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4565 << tcu::TestLog::EndMessage;
4566
4567 return false;
4568 }
4569 }
4570 }
4571
4572 return true;
4573 }
4574 else
4575 {
4576 /* Verify contents of transform feedback buffer */
4577
4578 bool result = true;
4579
4580 /* Get transform feedback data */
4581 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4582 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4583
4584 glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4585 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4586
4587 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4588 {
4589 const glw::GLint value = feedback_data[i];
4590
4591 if (m_result_success != value)
4592 {
4593 m_context.getTestContext().getLog() << tcu::TestLog::Message
4594 << "Error. Transform feedback buffer contents are wrong at " << i
4595 << tcu::TestLog::EndMessage;
4596
4597 result = false;
4598 break;
4599 }
4600 }
4601
4602 /* Unmap transform feedback buffer */
4603 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4604 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4605
4606 return result;
4607 }
4608 }
4609
4610 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4611 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4612 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4613
4614 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name = "UniformBlock";
4615 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4616
4617 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result = "fs_out_fs_result";
4618 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result = "gs_fs_gs_result";
4619 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result = "gs_fs_tcs_result";
4620 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result = "gs_fs_tes_result";
4621 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result = "gs_fs_vs_result";
4622 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4623 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result = "tcs_tes_vs_result";
4624 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result = "tes_gs_tcs_result";
4625 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result = "tes_gs_tes_result";
4626 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result = "tes_gs_vs_result";
4627 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result = "vs_tcs_vs_result";
4628
4629 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4630 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset = -1;
4631 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride = -1;
4632 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4633
4634 /** Constructor
4635 *
4636 * @param context Test context
4637 **/
GPUShaderFP64Test3(deqp::Context & context)4638 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4639 : TestCase(context, "named_uniform_blocks",
4640 "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4641 {
4642 /* Nothing to be done */
4643 }
4644
4645 /** Deinitialize test
4646 *
4647 **/
deinit()4648 void GPUShaderFP64Test3::deinit()
4649 {
4650 /* GL entry points */
4651 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4652
4653 /* Clean programs */
4654 m_packed_program.deinit(m_context);
4655 m_shared_program.deinit(m_context);
4656 m_std140_program.deinit(m_context);
4657
4658 /* Clean frambuffer */
4659 if (0 != m_framebuffer_id)
4660 {
4661 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4662 gl.deleteFramebuffers(1, &m_framebuffer_id);
4663
4664 m_framebuffer_id = 0;
4665 }
4666
4667 /* Clean texture */
4668 if (0 != m_color_texture_id)
4669 {
4670 gl.bindTexture(GL_TEXTURE_2D, 0);
4671 gl.deleteTextures(1, &m_color_texture_id);
4672
4673 m_color_texture_id = 0;
4674 }
4675
4676 /* Clean buffers */
4677 if (0 != m_transform_feedback_buffer_id)
4678 {
4679 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4680 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4681
4682 m_transform_feedback_buffer_id = 0;
4683 }
4684
4685 if (0 != m_uniform_buffer_id)
4686 {
4687 gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4688 gl.deleteBuffers(1, &m_uniform_buffer_id);
4689
4690 m_uniform_buffer_id = 0;
4691 }
4692
4693 /* Clean VAO */
4694 if (0 != m_vertex_array_object_id)
4695 {
4696 gl.bindVertexArray(0);
4697 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4698
4699 m_vertex_array_object_id = 0;
4700 }
4701 }
4702
4703 /** Execute test
4704 *
4705 * @return tcu::TestNode::STOP
4706 **/
iterate()4707 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4708 {
4709 bool result = true;
4710
4711 /* Check if extension is supported */
4712 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4713 {
4714 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4715 }
4716
4717 /* Initialize test */
4718 testInit();
4719
4720 /* Test "packed" uniform buffer layout */
4721 if (false == test(PACKED))
4722 {
4723 result = false;
4724 }
4725
4726 /* Test "shared" uniform buffer layout */
4727 if (false == test(SHARED))
4728 {
4729 result = false;
4730 }
4731
4732 /* Test "std140" uniform buffer layout */
4733 if (false == test(STD140))
4734 {
4735 result = false;
4736 }
4737
4738 /* Set result */
4739 if (true == result)
4740 {
4741 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4742 }
4743 else
4744 {
4745 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4746 }
4747
4748 /* Done */
4749 return tcu::TestNode::STOP;
4750 }
4751
4752 /** Constructor
4753 *
4754 **/
programInfo()4755 GPUShaderFP64Test3::programInfo::programInfo()
4756 : m_fragment_shader_id(0)
4757 , m_geometry_shader_id(0)
4758 , m_program_object_id(0)
4759 , m_tesselation_control_shader_id(0)
4760 , m_tesselation_evaluation_shader_id(0)
4761 , m_vertex_shader_id(0)
4762 , m_buffer_size(0)
4763 , m_uniform_block_index(0)
4764 {
4765 /* Nothing to be done here */
4766 }
4767
4768 /** Compile shader
4769 *
4770 * @param context Test context
4771 * @param shader_id Shader object id
4772 * @param shader_code Shader source code
4773 **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4774 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4775 const glw::GLchar* shader_code) const
4776 {
4777 /* GL entry points */
4778 const glw::Functions& gl = context.getRenderContext().getFunctions();
4779
4780 /* Compilation status */
4781 glw::GLint status = GL_FALSE;
4782
4783 /* Set source code */
4784 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4785 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4786
4787 /* Compile */
4788 gl.compileShader(shader_id);
4789 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4790
4791 /* Get compilation status */
4792 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4793 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4794
4795 /* Log compilation error */
4796 if (GL_TRUE != status)
4797 {
4798 glw::GLint length = 0;
4799 std::vector<glw::GLchar> message;
4800
4801 /* Error log length */
4802 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4803 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4804
4805 /* Prepare storage */
4806 message.resize(length);
4807
4808 /* Get error log */
4809 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4810 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4811
4812 /* Log */
4813 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4814 << &message[0] << "\nShader source\n"
4815 << shader_code << tcu::TestLog::EndMessage;
4816
4817 TCU_FAIL("Failed to compile shader");
4818 }
4819 }
4820
4821 /** Cleans program and attached shaders
4822 *
4823 * @param context Test context
4824 **/
deinit(deqp::Context & context)4825 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4826 {
4827 /* GL entry points */
4828 const glw::Functions& gl = context.getRenderContext().getFunctions();
4829
4830 /* Restore default program */
4831 gl.useProgram(0);
4832
4833 /* Clean program object */
4834 if (0 != m_program_object_id)
4835 {
4836 gl.deleteProgram(m_program_object_id);
4837 m_program_object_id = 0;
4838 }
4839
4840 /* Clean shaders */
4841 if (0 != m_fragment_shader_id)
4842 {
4843 gl.deleteShader(m_fragment_shader_id);
4844 m_fragment_shader_id = 0;
4845 }
4846
4847 if (0 != m_geometry_shader_id)
4848 {
4849 gl.deleteShader(m_geometry_shader_id);
4850 m_geometry_shader_id = 0;
4851 }
4852
4853 if (0 != m_tesselation_control_shader_id)
4854 {
4855 gl.deleteShader(m_tesselation_control_shader_id);
4856 m_tesselation_control_shader_id = 0;
4857 }
4858
4859 if (0 != m_tesselation_evaluation_shader_id)
4860 {
4861 gl.deleteShader(m_tesselation_evaluation_shader_id);
4862 m_tesselation_evaluation_shader_id = 0;
4863 }
4864
4865 if (0 != m_vertex_shader_id)
4866 {
4867 gl.deleteShader(m_vertex_shader_id);
4868 m_vertex_shader_id = 0;
4869 }
4870 }
4871
4872 /** Build program and query for uniform layout
4873 *
4874 * @param context Test context
4875 * @param uniform_details Collection of uniform details
4876 * @param fragment_shader_code Fragment shader source code
4877 * @param geometry_shader_code Geometry shader source code
4878 * @param tesselation_control_shader_code Tesselation control shader source code
4879 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4880 * @param vertex_shader_code Vertex shader source code
4881 **/
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)4882 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4883 const glw::GLchar* fragment_shader_code,
4884 const glw::GLchar* geometry_shader_code,
4885 const glw::GLchar* tesselation_control_shader_code,
4886 const glw::GLchar* tesselation_evaluation_shader_code,
4887 const glw::GLchar* vertex_shader_code)
4888 {
4889 /* GL entry points */
4890 const glw::Functions& gl = context.getRenderContext().getFunctions();
4891
4892 /* Names of varyings to be captured with transform feedback */
4893 static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4894 m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4895 static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4896
4897 /* Create shader objects */
4898 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
4899 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
4900 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
4901 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4902 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
4903 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4904
4905 /* Create program object */
4906 m_program_object_id = gl.createProgram();
4907 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4908
4909 /* Set up names of varyings to be captured with transform feedback */
4910 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4911 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4912
4913 /* Compile shaders */
4914 compile(context, m_fragment_shader_id, fragment_shader_code);
4915 compile(context, m_geometry_shader_id, geometry_shader_code);
4916 compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4917 compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4918 compile(context, m_vertex_shader_id, vertex_shader_code);
4919
4920 /* Link program */
4921 link(context);
4922
4923 /* Inspect program object */
4924 /* Get index of named uniform block */
4925 m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4926 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4927
4928 if (GL_INVALID_INDEX == m_uniform_block_index)
4929 {
4930 TCU_FAIL("Unifom block is inactive");
4931 }
4932
4933 /* Get size of named uniform block */
4934 gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4935 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4936
4937 if (0 == m_buffer_size)
4938 {
4939 TCU_FAIL("Unifom block size is 0");
4940 }
4941
4942 /* Get information about "double precision" uniforms */
4943 for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4944 end != it; ++it)
4945 {
4946 const glw::GLchar* uniform_name = 0;
4947 std::string uniform_name_str;
4948 std::stringstream uniform_name_stream;
4949 glw::GLuint index = 0;
4950 glw::GLint offset = 0;
4951 glw::GLint matrix_stride = 0;
4952
4953 /* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4954 uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4955
4956 uniform_name_str = uniform_name_stream.str();
4957 uniform_name = uniform_name_str.c_str();
4958
4959 /* Get index of uniform */
4960 gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4961 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4962
4963 if (GL_INVALID_INDEX == index)
4964 {
4965 TCU_FAIL("Unifom is inactive");
4966 }
4967
4968 /* Get offset of uniform */
4969 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4970 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4971
4972 if (m_invalid_uniform_offset == offset)
4973 {
4974 TCU_FAIL("Unifom has invalid offset");
4975 }
4976
4977 m_uniform_offsets.push_back(offset);
4978
4979 /* Get matrix stride of uniform */
4980 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4981 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4982
4983 if (m_invalid_uniform_matrix_stride == offset)
4984 {
4985 TCU_FAIL("Unifom has invalid matrix stride");
4986 }
4987
4988 m_uniform_matrix_strides.push_back(matrix_stride);
4989 }
4990 }
4991
4992 /** Attach shaders and link program
4993 *
4994 * @param context Test context
4995 **/
link(deqp::Context & context) const4996 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4997 {
4998 /* GL entry points */
4999 const glw::Functions& gl = context.getRenderContext().getFunctions();
5000
5001 /* Link status */
5002 glw::GLint status = GL_FALSE;
5003
5004 /* Attach shaders */
5005 gl.attachShader(m_program_object_id, m_fragment_shader_id);
5006 gl.attachShader(m_program_object_id, m_geometry_shader_id);
5007 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
5008 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
5009 gl.attachShader(m_program_object_id, m_vertex_shader_id);
5010 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
5011
5012 /* Link */
5013 gl.linkProgram(m_program_object_id);
5014 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5015
5016 /* Get link status */
5017 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5018 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5019
5020 /* Log link error */
5021 if (GL_TRUE != status)
5022 {
5023 glw::GLint length = 0;
5024 std::vector<glw::GLchar> message;
5025
5026 /* Get error log length */
5027 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5028 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5029
5030 message.resize(length);
5031
5032 /* Get error log */
5033 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5034 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5035
5036 /* Log */
5037 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5038 << &message[0] << tcu::TestLog::EndMessage;
5039
5040 TCU_FAIL("Failed to link program");
5041 }
5042 }
5043
5044 /** Returns "predefined" values that will be used to fill uniform data
5045 *
5046 * @param type_ordinal Ordinal number of "double precision" uniform type
5047 * @param element Index of element in uniform
5048 *
5049 * @return "Predefined" value
5050 **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5051 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5052 {
5053 return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5054 ((m_base_element - (glw::GLdouble)element) / 4.0);
5055 }
5056
5057 /** Returns a reference of programInfo instance specific for given buffer layout
5058 *
5059 * @param uniform_data_layout Buffer layout
5060 *
5061 * @return Reference to an instance of programInfo
5062 **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5063 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5064 {
5065 const programInfo* program_info = 0;
5066
5067 switch (uniform_data_layout)
5068 {
5069 case PACKED:
5070
5071 program_info = &m_packed_program;
5072
5073 break;
5074
5075 case SHARED:
5076
5077 program_info = &m_shared_program;
5078
5079 break;
5080
5081 case STD140:
5082
5083 program_info = &m_std140_program;
5084
5085 break;
5086 }
5087
5088 return *program_info;
5089 }
5090
5091 /** Get "name" of buffer layout
5092 *
5093 * @param uniform_data_layout Buffer layout
5094 *
5095 * @return "Name" of layout
5096 **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5097 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5098 {
5099 const glw::GLchar* layout = "";
5100
5101 switch (uniform_data_layout)
5102 {
5103 case PACKED:
5104 layout = "packed";
5105 break;
5106 case SHARED:
5107 layout = "shared";
5108 break;
5109 case STD140:
5110 layout = "std140";
5111 break;
5112 }
5113
5114 return layout;
5115 }
5116
5117 /** Prepare programInfo instance for specific buffer layout
5118 *
5119 * @param program_info Instance of programInfo
5120 * @param uniform_data_layout Buffer layout
5121 **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5122 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5123 {
5124 /* Storage for shader source code */
5125 std::stringstream fragment_shader_code;
5126 std::stringstream geometry_shader_code;
5127 std::stringstream tess_control_shader_code;
5128 std::stringstream tess_eval_shader_code;
5129 std::stringstream vertex_shader_code;
5130
5131 /* Write preambles */
5132 writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5133 writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5134 writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5135 writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5136 writePreamble(vertex_shader_code, VERTEX_SHADER);
5137
5138 /* Write definition of named uniform block */
5139 writeUniformBlock(fragment_shader_code, uniform_data_layout);
5140 writeUniformBlock(geometry_shader_code, uniform_data_layout);
5141 writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5142 writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5143 writeUniformBlock(vertex_shader_code, uniform_data_layout);
5144
5145 /* Write definitions of varyings */
5146 writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5147 writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5148 writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5149 writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5150 writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5151
5152 /* Write main routine */
5153 writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5154 writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5155 writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5156 writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5157 writeMainBody(vertex_shader_code, VERTEX_SHADER);
5158
5159 /* Init programInfo instance */
5160 program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5161 geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5162 tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5163 }
5164
5165 /** Prepare uniform buffer
5166 *
5167 * @param program_info Instance of programInfo
5168 * @param verify_offsets If uniform offsets should be verified against expected values
5169 *
5170 * @return false if uniform offsets verification result is failure, true otherwise
5171 **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5172 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5173 {
5174 const glw::GLuint buffer_size = program_info.m_buffer_size;
5175 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5176 bool offset_verification_result = true;
5177 glw::GLuint type_ordinal = 1;
5178 std::vector<uniformDetails>::const_iterator it_uniform_details = m_uniform_details.begin();
5179 std::vector<glw::GLint>::const_iterator it_uniform_offsets = program_info.m_uniform_offsets.begin();
5180 std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5181
5182 /* Prepare storage for uniform buffer data */
5183 std::vector<glw::GLubyte> buffer_data;
5184 buffer_data.resize(buffer_size);
5185
5186 /* For each "double precision" uniform */
5187 for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5188 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5189 {
5190 const glw::GLint matrix_stride = *it_uniform_matrix_strides;
5191 const glw::GLuint n_columns = it_uniform_details->m_n_columns;
5192 const glw::GLuint n_elements = it_uniform_details->m_n_elements;
5193 const glw::GLuint column_length = n_elements / n_columns;
5194 const glw::GLint uniform_offset = *it_uniform_offsets;
5195
5196 /* For each element of uniform */
5197 for (glw::GLuint element = 0; element < n_elements; ++element)
5198 {
5199 const glw::GLuint column = element / column_length;
5200 const glw::GLuint column_elem = element % column_length;
5201 const glw::GLdouble value = getExpectedValue(type_ordinal, element);
5202 const glw::GLuint value_offset =
5203 static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5204
5205 glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5206
5207 /* Store value */
5208 *value_dst = value;
5209 }
5210
5211 /* Uniform offset verification */
5212 if (true == verify_offsets)
5213 {
5214 const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5215
5216 if (expected_offset != uniform_offset)
5217 {
5218 if (true == offset_verification_result)
5219 {
5220 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5221 }
5222
5223 m_context.getTestContext().getLog()
5224 << tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5225 << " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5226 << tcu::TestLog::EndMessage;
5227
5228 offset_verification_result = false;
5229 }
5230 }
5231 }
5232
5233 /* Update uniform buffer with prepared data */
5234 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5235 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5236
5237 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5238 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5239
5240 /* Bind uniform buffer as data source for named uniform block */
5241 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5242 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5243
5244 gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5245 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5246
5247 /* Done */
5248 return offset_verification_result;
5249 }
5250
5251 /** Prepare data, execute draw call and verify results
5252 *
5253 * @param uniform_data_layout
5254 *
5255 * @return true if test pass, false otherwise
5256 **/
test(uniformDataLayout uniform_data_layout) const5257 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5258 {
5259 bool are_offsets_verified = (STD140 == uniform_data_layout);
5260 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5261 bool offset_verification_result = true;
5262 const programInfo& program_info = getProgramInfo(uniform_data_layout);
5263 bool result = true;
5264
5265 /* Set up program */
5266 gl.useProgram(program_info.m_program_object_id);
5267 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5268
5269 /* Prepare uniform buffer */
5270 offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5271
5272 if (true == are_offsets_verified && false == offset_verification_result)
5273 {
5274 /* Offsets verification failure was already reported, add info about buffer layout */
5275 m_context.getTestContext().getLog() << tcu::TestLog::Message
5276 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5277 << tcu::TestLog::EndMessage;
5278
5279 result = false;
5280 }
5281
5282 /* Set up transform feedback buffer */
5283 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5284 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5285
5286 /* Begin transform feedback */
5287 gl.beginTransformFeedback(GL_POINTS);
5288 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5289
5290 /* Execute draw call for singe vertex */
5291 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5292 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5293
5294 /* Stop transform feedback */
5295 gl.endTransformFeedback();
5296 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5297
5298 /* Verify results */
5299 if (false == verifyResults())
5300 {
5301 /* Result verificatioon failure was already reported, add info about layout */
5302 m_context.getTestContext().getLog() << tcu::TestLog::Message
5303 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5304 << tcu::TestLog::EndMessage;
5305
5306 result = false;
5307 }
5308
5309 /* Done */
5310 return result;
5311 }
5312
testInit()5313 void GPUShaderFP64Test3::testInit()
5314 {
5315 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5316
5317 /* Uniform block declaration with std140 offsets calculated
5318 * | align | loc_req | begins | ends | offset in bytes | imp |
5319 * ivec3 dummy1[3] | 4 | 12 | 0 | 12 | 0 | |
5320 * double double_value | 2 | 2 | 12 | 14 | 48 | XXX |
5321 * bool dummy2 | 1 | 1 | 14 | 15 | 56 | |
5322 * dvec2 dvec2_value | 4 | 4 | 16 | 20 | 64 | XXX |
5323 * bvec3 dummy3 | 4 | 4 | 20 | 24 | 80 | |
5324 * dvec3 dvec3_value | 8 | 8 | 24 | 32 | 96 | XXX |
5325 * int dummy4[3] | 4 | 12 | 32 | 44 | 128 | |
5326 * dvec4 dvec4_value | 8 | 8 | 48 | 56 | 192 | XXX |
5327 * bool dummy5 | 1 | 1 | 56 | 57 | 224 | |
5328 * bool dummy6[2] | 4 | 8 | 60 | 68 | 240 | |
5329 * dmat2 dmat2_value | 4 | 8 | 68 | 76 | 272 | XXX |
5330 * dmat3 dmat3_value | 8 | 24 | 80 | 104 | 320 | XXX |
5331 * bool dummy7 | 1 | 1 | 104 | 105 | 416 | |
5332 * dmat4 dmat4_value | 8 | 32 | 112 | 144 | 448 | XXX |
5333 * dmat2x3 dmat2x3_value | 8 | 16 | 144 | 160 | 576 | XXX |
5334 * uvec3 dummy8 | 4 | 4 | 160 | 164 | 640 | |
5335 * dmat2x4 dmat2x4_value | 8 | 16 | 168 | 184 | 672 | XXX |
5336 * dmat3x2 dmat3x2_value | 4 | 12 | 184 | 196 | 736 | XXX |
5337 * bool dummy9 | 1 | 1 | 196 | 197 | 784 | |
5338 * dmat3x4 dmat3x4_value | 8 | 24 | 200 | 224 | 800 | XXX |
5339 * int dummy10 | 1 | 1 | 224 | 225 | 896 | |
5340 * dmat4x2 dmat4x2_value | 4 | 16 | 228 | 244 | 912 | XXX |
5341 * dmat4x3 dmat4x3_value | 8 | 32 | 248 | 280 | 992 | XXX |
5342 */
5343
5344 /* Prepare "double precision" unfiorms' details */
5345 m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5346 1 /* n_elements */, "double" /* type_name */));
5347 m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5348 2 /* n_elements */, "dvec2" /* type_name */));
5349 m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5350 3 /* n_elements */, "dvec3" /* type_name */));
5351 m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5352 4 /* n_elements */, "dvec4" /* type_name */));
5353 m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5354 4 /* n_elements */, "dmat2" /* type_name */));
5355 m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5356 9 /* n_elements */, "dmat3" /* type_name */));
5357 m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5358 16 /* n_elements */, "dmat4" /* type_name */));
5359 m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5360 6 /* n_elements */, "dmat2x3" /* type_name */));
5361 m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5362 8 /* n_elements */, "dmat2x4" /* type_name */));
5363 m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5364 6 /* n_elements */, "dmat3x2" /* type_name */));
5365 m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5366 12 /* n_elements */, "dmat3x4" /* type_name */));
5367 m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5368 8 /* n_elements */, "dmat4x2" /* type_name */));
5369 m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5370 12 /* n_elements */, "dmat4x3" /* type_name */));
5371
5372 /* Get random values for getExpectedValue */
5373 m_base_element = (glw::GLdouble)(rand() % 13);
5374 m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5375
5376 /* Prepare programInfos for all buffer layouts */
5377 prepareProgram(m_packed_program, PACKED);
5378 prepareProgram(m_shared_program, SHARED);
5379 prepareProgram(m_std140_program, STD140);
5380
5381 /* Generate buffers */
5382 gl.genBuffers(1, &m_transform_feedback_buffer_id);
5383 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5384
5385 gl.genBuffers(1, &m_uniform_buffer_id);
5386 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5387
5388 /* Prepare transform feedback buffer */
5389 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5390 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5391
5392 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5393 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5394
5395 /* Prepare texture for color attachment 0 */
5396 gl.genTextures(1, &m_color_texture_id);
5397 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5398
5399 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5400 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5401
5402 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5403 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5404
5405 /* Prepare FBO with color attachment 0 */
5406 gl.genFramebuffers(1, &m_framebuffer_id);
5407 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5408
5409 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5410 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5411
5412 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5413 0 /* level */);
5414 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5415
5416 gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5417 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5418
5419 /* Prepare VAO */
5420 gl.genVertexArrays(1, &m_vertex_array_object_id);
5421 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5422
5423 gl.bindVertexArray(m_vertex_array_object_id);
5424 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5425
5426 /* Tesselation patch set up */
5427 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5428 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5429 }
5430
5431 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5432 *
5433 * @return true if all values are as expected, false otherwise
5434 **/
verifyResults() const5435 bool GPUShaderFP64Test3::verifyResults() const
5436 {
5437 glw::GLint* feedback_data = 0;
5438 bool fragment_shader_result = false;
5439 bool geometry_shader_result = false;
5440 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5441 bool tess_ctrl_shader_result = false;
5442 bool tess_eval_shader_result = false;
5443 bool vertex_shader_result = false;
5444
5445 /* Prepare storage for testure data */
5446 std::vector<glw::GLint> image_data;
5447 image_data.resize(1);
5448
5449 /* Get texture contents */
5450 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5451 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5452
5453 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5454 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5455
5456 /* Get transform feedback data */
5457 feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5458 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5459
5460 /* Verify results */
5461 fragment_shader_result = (m_result_success == image_data[0]);
5462 geometry_shader_result = (m_result_success == feedback_data[0]);
5463 tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5464 tess_eval_shader_result = (m_result_success == feedback_data[2]);
5465 vertex_shader_result = (m_result_success == feedback_data[3]);
5466
5467 /* Unmap transform feedback buffer */
5468 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5469 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5470
5471 /* Set result */
5472 if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5473 tess_eval_shader_result && vertex_shader_result))
5474 {
5475 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5476
5477 m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 << "Vertex shader stage result: " << vertex_shader_result
5479 << tcu::TestLog::EndMessage;
5480
5481 m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 << "Tesselation control shader stage result: " << tess_ctrl_shader_result
5483 << tcu::TestLog::EndMessage;
5484
5485 m_context.getTestContext().getLog() << tcu::TestLog::Message
5486 << "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5487 << tcu::TestLog::EndMessage;
5488
5489 m_context.getTestContext().getLog() << tcu::TestLog::Message
5490 << "Geometry shader stage result: " << geometry_shader_result
5491 << tcu::TestLog::EndMessage;
5492
5493 m_context.getTestContext().getLog() << tcu::TestLog::Message
5494 << "Fragment shader stage result: " << fragment_shader_result
5495 << tcu::TestLog::EndMessage;
5496
5497 return false;
5498 }
5499 else
5500 {
5501 return true;
5502 }
5503 }
5504
5505 /** Write main routine of <shader_stage> shader to stream
5506 *
5507 * @param stream Output stream with source code of shader
5508 * @param shader_stage Shader stage
5509 **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5510 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5511 {
5512 glw::GLuint type_ordinal = 1;
5513 const glw::GLchar* varying_name = "";
5514
5515 /* Select name for varying that will hold result of "that" shader_stage */
5516 switch (shader_stage)
5517 {
5518 case FRAGMENT_SHADER:
5519 varying_name = m_varying_name_fs_out_fs_result;
5520 break;
5521 case GEOMETRY_SHADER:
5522 varying_name = m_varying_name_gs_fs_gs_result;
5523 break;
5524 case TESS_CONTROL_SHADER:
5525 varying_name = m_varying_name_tcs_tes_tcs_result;
5526 break;
5527 case TESS_EVAL_SHADER:
5528 varying_name = m_varying_name_tes_gs_tes_result;
5529 break;
5530 case VERTEX_SHADER:
5531 varying_name = m_varying_name_vs_tcs_vs_result;
5532 break;
5533 }
5534
5535 /* void main() */
5536 stream << "void main()\n"
5537 "{\n";
5538
5539 /* Tesselation levels output */
5540 if (TESS_CONTROL_SHADER == shader_stage)
5541 {
5542 stream << "gl_TessLevelOuter[0] = 1.0;\n"
5543 "gl_TessLevelOuter[1] = 1.0;\n"
5544 "gl_TessLevelOuter[2] = 1.0;\n"
5545 "gl_TessLevelOuter[3] = 1.0;\n"
5546 "gl_TessLevelInner[0] = 1.0;\n"
5547 "gl_TessLevelInner[1] = 1.0;\n"
5548 "\n";
5549 }
5550
5551 /* For each "double precision" uniform
5552 *
5553 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5554 * {
5555 * VARYING_NAME = m_result_failure;
5556 * }
5557 */
5558 for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5559 end != it; ++it, ++type_ordinal)
5560 {
5561 stream << " ";
5562
5563 /* First comparison is done with if, next with else if */
5564 if (1 != type_ordinal)
5565 {
5566 stream << "else ";
5567 }
5568
5569 /* if (TYPE_NAME( */
5570 stream << "if (" << it->m_type_name << "(";
5571
5572 /* PREDIFINED_VALUES */
5573 for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5574 {
5575 stream << getExpectedValue(type_ordinal, element);
5576
5577 /* Separate with comma */
5578 if (it->m_n_elements != element + 1)
5579 {
5580 stream << ", ";
5581 }
5582 }
5583
5584 /*
5585 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5586 * {
5587 * VARYING_NAME
5588 */
5589 stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5590 " {\n"
5591 " "
5592 << varying_name;
5593
5594 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5595 if (TESS_CONTROL_SHADER == shader_stage)
5596 {
5597 stream << "[gl_InvocationID]";
5598 }
5599
5600 /*
5601 * = m_result_failure;
5602 * }
5603 */
5604 stream << " = " << m_result_failure << ";\n"
5605 << " }\n";
5606 }
5607
5608 /* If all comparisons are ok
5609 *
5610 * else
5611 * {
5612 * VARYING_NAME = m_result_success;
5613 * }
5614 */
5615
5616 /*
5617 * else
5618 * {
5619 * VARYING_NAME
5620 */
5621 stream << " else\n"
5622 " {\n"
5623 " "
5624 << varying_name;
5625
5626 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5627 if (TESS_CONTROL_SHADER == shader_stage)
5628 {
5629 stream << "[gl_InvocationID]";
5630 }
5631
5632 /*
5633 * = m_result_success;
5634 * }
5635 *
5636 */
5637 stream << " = " << m_result_success << ";\n"
5638 << " }\n"
5639 << "\n";
5640
5641 /* For each pair of "input/output" varyings
5642 *
5643 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5644 **/
5645 writeVaryingPassthrough(stream, shader_stage);
5646
5647 /* Geometry shader have to emit vertex */
5648 if (GEOMETRY_SHADER == shader_stage)
5649 {
5650 stream << "\n"
5651 "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5652 "EmitVertex();\n"
5653 "EndPrimitive();\n";
5654 }
5655
5656 /* Close scope of main */
5657 stream << "}\n\n";
5658 }
5659
5660 /** Write shader preamble to stream
5661 *
5662 * @param stream Output stream with source code of shader
5663 * @param shader_stage Shader stage
5664 **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5665 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5666 {
5667 stream << "#version 400 core\n"
5668 "\n"
5669 "precision highp float;\n"
5670 "\n";
5671
5672 switch (shader_stage)
5673 {
5674 case FRAGMENT_SHADER:
5675 break;
5676 case GEOMETRY_SHADER:
5677 stream << "layout(points) in;\n"
5678 "layout(points, max_vertices = 1) out;\n"
5679 "\n";
5680 break;
5681 case TESS_CONTROL_SHADER:
5682 stream << "layout(vertices = 1) out;\n"
5683 "\n";
5684 break;
5685 case TESS_EVAL_SHADER:
5686 stream << "layout(isolines, point_mode) in;\n"
5687 "\n";
5688 break;
5689 case VERTEX_SHADER:
5690 break;
5691 }
5692 }
5693
5694 /** Write name uniform blcok definition with specific layout to stream
5695 *
5696 * @param stream Output stream with source code of shader
5697 * @param uniform_data_layout Buffer layout
5698 **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5699 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5700 {
5701 const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5702
5703 stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5704 "{\n"
5705 " ivec3 dummy1[3];\n"
5706 " double double_value;\n"
5707 " bool dummy2;\n"
5708 " dvec2 dvec2_value;\n"
5709 " bvec3 dummy3;\n"
5710 " dvec3 dvec3_value;\n"
5711 " int dummy4[3];\n"
5712 " dvec4 dvec4_value;\n"
5713 " bool dummy5;\n"
5714 " bool dummy6[2];\n"
5715 " dmat2 dmat2_value;\n"
5716 " dmat3 dmat3_value;\n"
5717 " bool dummy7;\n"
5718 " dmat4 dmat4_value;\n"
5719 " dmat2x3 dmat2x3_value;\n"
5720 " uvec3 dummy8;\n"
5721 " dmat2x4 dmat2x4_value;\n"
5722 " dmat3x2 dmat3x2_value;\n"
5723 " bool dummy9;\n"
5724 " dmat3x4 dmat3x4_value;\n"
5725 " int dummy10;\n"
5726 " dmat4x2 dmat4x2_value;\n"
5727 " dmat4x3 dmat4x3_value;\n"
5728 "} "
5729 << m_uniform_block_instance_name << ";\n";
5730
5731 stream << "\n";
5732 }
5733
5734 /** Write definitions of varyings specific for given <shader_stage> to stream
5735 *
5736 * @param stream Output stream with source code of shader
5737 * @param shader_stage Shader stage
5738 **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5739 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5740 {
5741 static const glw::GLchar* const varying_type = "int";
5742
5743 switch (shader_stage)
5744 {
5745 case FRAGMENT_SHADER:
5746
5747 /* In */
5748 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5749 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5750 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5751 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5752
5753 stream << "\n";
5754
5755 /* Out */
5756 stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5757
5758 break;
5759
5760 case GEOMETRY_SHADER:
5761
5762 /* In */
5763 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5764 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5765 stream << "in " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5766
5767 stream << "\n";
5768
5769 /* Out */
5770 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5771 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5772 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5773 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5774
5775 break;
5776
5777 case TESS_CONTROL_SHADER:
5778
5779 /* In */
5780 stream << "in " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5781
5782 stream << "\n";
5783
5784 /* Out */
5785 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5786 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5787
5788 break;
5789
5790 case TESS_EVAL_SHADER:
5791
5792 /* In */
5793 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5794 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5795
5796 stream << "\n";
5797
5798 /* Out */
5799 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5800 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5801 stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5802
5803 break;
5804
5805 case VERTEX_SHADER:
5806
5807 /* Out */
5808 stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5809
5810 break;
5811 }
5812
5813 stream << "\n";
5814 }
5815
5816 /** Write passthrough code of "input/output" varying pairs to stream
5817 *
5818 * @param stream Output stream with source code of shader
5819 * @param shader_stage Shader stage
5820 **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5821 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5822 {
5823 switch (shader_stage)
5824 {
5825 case FRAGMENT_SHADER:
5826 break;
5827
5828 case GEOMETRY_SHADER:
5829
5830 stream << " " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5831 stream << " " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5832 stream << " " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5833
5834 break;
5835
5836 case TESS_CONTROL_SHADER:
5837
5838 stream << " " << m_varying_name_tcs_tes_vs_result
5839 << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5840
5841 break;
5842
5843 case TESS_EVAL_SHADER:
5844
5845 stream << " " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5846 stream << " " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5847
5848 break;
5849
5850 case VERTEX_SHADER:
5851
5852 break;
5853 }
5854 }
5855
5856 /** Constructor. Sets all uniform locations to -1 and sets all
5857 * values to 0.
5858 */
_data()5859 GPUShaderFP64Test4::_data::_data()
5860 {
5861 memset(&uniform_double, 0, sizeof(uniform_double));
5862 memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5863 memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5864 memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5865 memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5866 memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5867 memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5868
5869 uniform_location_double = -1;
5870 uniform_location_double_arr[0] = -1;
5871 uniform_location_double_arr[1] = -1;
5872 uniform_location_dvec2 = -1;
5873 uniform_location_dvec2_arr[0] = -1;
5874 uniform_location_dvec2_arr[1] = -1;
5875 uniform_location_dvec3 = -1;
5876 uniform_location_dvec3_arr[0] = -1;
5877 uniform_location_dvec3_arr[1] = -1;
5878 uniform_location_dvec4 = -1;
5879 uniform_location_dvec4_arr[0] = -1;
5880 uniform_location_dvec4_arr[1] = -1;
5881 }
5882
5883 /** Constructor
5884 *
5885 * @param context Rendering context.
5886 */
GPUShaderFP64Test4(deqp::Context & context)5887 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5888 : TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5889 " report correct properties of & values assigned to double-precision uniforms.")
5890 , m_has_test_passed(true)
5891 , m_uniform_name_buffer(0)
5892 , m_cs_id(0)
5893 , m_fs_id(0)
5894 , m_gs_id(0)
5895 , m_po_cs_id(0)
5896 , m_po_noncs_id(0)
5897 , m_tc_id(0)
5898 , m_te_id(0)
5899 , m_vs_id(0)
5900 {
5901 /* Left blank intentionally */
5902 }
5903
5904 /** Deinitializes all GL objects, as well as releases all bufers, that may
5905 * have beenallocated or created during test execution.
5906 **/
deinit()5907 void GPUShaderFP64Test4::deinit()
5908 {
5909 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5910
5911 if (m_cs_id != 0)
5912 {
5913 gl.deleteShader(m_cs_id);
5914
5915 m_cs_id = 0;
5916 }
5917
5918 if (m_fs_id != 0)
5919 {
5920 gl.deleteShader(m_fs_id);
5921
5922 m_fs_id = 0;
5923 }
5924
5925 if (m_gs_id != 0)
5926 {
5927 gl.deleteShader(m_gs_id);
5928
5929 m_gs_id = 0;
5930 }
5931
5932 if (m_po_cs_id != 0)
5933 {
5934 gl.deleteProgram(m_po_cs_id);
5935
5936 m_po_cs_id = 0;
5937 }
5938
5939 if (m_po_noncs_id != 0)
5940 {
5941 gl.deleteProgram(m_po_noncs_id);
5942
5943 m_po_noncs_id = 0;
5944 }
5945
5946 if (m_tc_id != 0)
5947 {
5948 gl.deleteShader(m_tc_id);
5949
5950 m_tc_id = 0;
5951 }
5952
5953 if (m_te_id != 0)
5954 {
5955 gl.deleteShader(m_te_id);
5956
5957 m_te_id = 0;
5958 }
5959
5960 if (m_uniform_name_buffer != DE_NULL)
5961 {
5962 delete[] m_uniform_name_buffer;
5963
5964 m_uniform_name_buffer = DE_NULL;
5965 }
5966
5967 if (m_vs_id != 0)
5968 {
5969 gl.deleteShader(m_vs_id);
5970
5971 m_vs_id = 0;
5972 }
5973 }
5974
5975 /** Generates double-precision values for all uniforms defined for all program objects
5976 * used by the test.
5977 *
5978 * This function DOES NOT use any GL API. It only calculates & stores the values
5979 * in internal storage for further usage.
5980 */
generateUniformValues()5981 void GPUShaderFP64Test4::generateUniformValues()
5982 {
5983 _stage_data* stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5984 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5985
5986 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5987 {
5988 _stage_data* stage_ptr = stages[n_stage];
5989
5990 /* Iterate through all uniform components and assign them double values */
5991 double* double_ptrs[] = {
5992 &stage_ptr->uniform_structure_arrays[0].uniform_double,
5993 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5994 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5995 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5996 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5997 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 2,
5998 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 3,
5999 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
6000 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
6001 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
6002 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 3,
6003 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 4,
6004 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 5,
6005 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
6006 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
6007 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
6008 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
6009 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 4,
6010 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 5,
6011 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 6,
6012 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 7,
6013 &stage_ptr->uniform_structure_arrays[1].uniform_double,
6014 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
6015 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
6016 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
6017 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
6018 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 2,
6019 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 3,
6020 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
6021 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
6022 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6023 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 3,
6024 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 4,
6025 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 5,
6026 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6027 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6028 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6029 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6030 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 4,
6031 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 5,
6032 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 6,
6033 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 7,
6034 &stage_ptr->uniforms.uniform_double,
6035 stage_ptr->uniforms.uniform_double_arr + 0,
6036 stage_ptr->uniforms.uniform_double_arr + 1,
6037 stage_ptr->uniforms.uniform_dvec2 + 0,
6038 stage_ptr->uniforms.uniform_dvec2 + 1,
6039 stage_ptr->uniforms.uniform_dvec2_arr + 0,
6040 stage_ptr->uniforms.uniform_dvec2_arr + 1,
6041 stage_ptr->uniforms.uniform_dvec2_arr + 2,
6042 stage_ptr->uniforms.uniform_dvec2_arr + 3,
6043 stage_ptr->uniforms.uniform_dvec3 + 0,
6044 stage_ptr->uniforms.uniform_dvec3 + 1,
6045 stage_ptr->uniforms.uniform_dvec3 + 2,
6046 stage_ptr->uniforms.uniform_dvec3_arr + 0,
6047 stage_ptr->uniforms.uniform_dvec3_arr + 1,
6048 stage_ptr->uniforms.uniform_dvec3_arr + 2,
6049 stage_ptr->uniforms.uniform_dvec3_arr + 3,
6050 stage_ptr->uniforms.uniform_dvec3_arr + 4,
6051 stage_ptr->uniforms.uniform_dvec3_arr + 5,
6052 stage_ptr->uniforms.uniform_dvec4 + 0,
6053 stage_ptr->uniforms.uniform_dvec4 + 1,
6054 stage_ptr->uniforms.uniform_dvec4 + 2,
6055 stage_ptr->uniforms.uniform_dvec4 + 3,
6056 stage_ptr->uniforms.uniform_dvec4_arr + 0,
6057 stage_ptr->uniforms.uniform_dvec4_arr + 1,
6058 stage_ptr->uniforms.uniform_dvec4_arr + 2,
6059 stage_ptr->uniforms.uniform_dvec4_arr + 3,
6060 stage_ptr->uniforms.uniform_dvec4_arr + 4,
6061 stage_ptr->uniforms.uniform_dvec4_arr + 5,
6062 stage_ptr->uniforms.uniform_dvec4_arr + 6,
6063 stage_ptr->uniforms.uniform_dvec4_arr + 7,
6064 };
6065 const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6066
6067 for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6068 {
6069 double* double_ptr = double_ptrs[n_double_ptr];
6070
6071 /* Generate the value. Use magic numbers to generate a set of double-precision
6072 * floating-point numbers.
6073 */
6074 static int seed = 16762362;
6075
6076 *double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6077
6078 seed += 751;
6079 } /* for (all pointers to double variables) */
6080 } /* for (all stages) */
6081 }
6082
6083 /** Initializes all program & shader objects required to run the test. The function also
6084 * retrieves locations of all uniforms defined by both program objects.
6085 **/
initProgramObjects()6086 void GPUShaderFP64Test4::initProgramObjects()
6087 {
6088 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6089
6090 /* Create program & shader objects */
6091
6092 /* Compute shader support and GL 4.2 required */
6093 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6094 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6095 {
6096 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6097 }
6098
6099 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6100 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6101 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6102 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6103 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6104 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6105
6106 /* m_cs_id is initialized only if compute shaders are supported */
6107 if (0 != m_cs_id)
6108 {
6109 m_po_cs_id = gl.createProgram();
6110 }
6111
6112 m_po_noncs_id = gl.createProgram();
6113 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6114
6115 /* Configure compute shader body */
6116 const char* cs_body = "#version 420\n"
6117 "#extension GL_ARB_compute_shader : require\n"
6118 "\n"
6119 "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6120 "\n"
6121 "layout(rgba32f) uniform image2D testImage;\n"
6122 "\n"
6123 "uniform double cs_double;\n"
6124 "uniform dvec2 cs_dvec2;\n"
6125 "uniform dvec3 cs_dvec3;\n"
6126 "uniform dvec4 cs_dvec4;\n"
6127 "uniform double cs_double_arr[2];\n"
6128 "uniform dvec2 cs_dvec2_arr [2];\n"
6129 "uniform dvec3 cs_dvec3_arr [2];\n"
6130 "uniform dvec4 cs_dvec4_arr [2];\n"
6131 "\n"
6132 "uniform struct cs_struct\n"
6133 "{\n"
6134 " double struct_double;\n"
6135 " dvec2 struct_dvec2;\n"
6136 " dvec3 struct_dvec3;\n"
6137 " dvec4 struct_dvec4;\n"
6138 "} cs_array[2];\n"
6139 "\n"
6140 "void main()\n"
6141 "{\n"
6142 " double tmp = cs_double * cs_dvec2.x * cs_dvec3.y "
6143 " * cs_dvec4.z *\n"
6144 " cs_double_arr[0] * cs_dvec2_arr[0].x * "
6145 "cs_dvec3_arr[0].z * cs_dvec4_arr[0].w *\n"
6146 " cs_double_arr[1] * cs_dvec2_arr[1].x * "
6147 "cs_dvec3_arr[1].z * cs_dvec4_arr[1].w *\n"
6148 " cs_array[0].struct_double * cs_array[0].struct_dvec2.y * "
6149 "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6150 " cs_array[1].struct_double * cs_array[1].struct_dvec2.y * "
6151 "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6152 "\n"
6153 " imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6154 "}\n";
6155
6156 /* m_cs_id is initialized only if compute shaders are supported */
6157 if (0 != m_cs_id)
6158 {
6159 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6160 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6161 }
6162
6163 /* Configure vertex shader body */
6164 const char* vs_body = "#version 400\n"
6165 "\n"
6166 "uniform double vs_double;\n"
6167 "uniform dvec2 vs_dvec2;\n"
6168 "uniform dvec3 vs_dvec3;\n"
6169 "uniform dvec4 vs_dvec4;\n"
6170 "uniform double vs_double_arr[2];\n"
6171 "uniform dvec2 vs_dvec2_arr [2];\n"
6172 "uniform dvec3 vs_dvec3_arr [2];\n"
6173 "uniform dvec4 vs_dvec4_arr [2];\n"
6174 "\n"
6175 "uniform struct vs_struct\n"
6176 "{\n"
6177 " double struct_double;\n"
6178 " dvec2 struct_dvec2;\n"
6179 " dvec3 struct_dvec3;\n"
6180 " dvec4 struct_dvec4;\n"
6181 "} vs_array[2];\n"
6182 "\n"
6183 "void main()\n"
6184 "{\n"
6185 " if (vs_double * vs_dvec2.x * vs_dvec3.x "
6186 "* vs_dvec4.x *\n"
6187 " vs_double_arr[0] * vs_dvec2_arr[0].x * vs_dvec3_arr[0].x "
6188 "* vs_dvec4_arr[0].x *\n"
6189 " vs_double_arr[1] * vs_dvec2_arr[1].x * vs_dvec3_arr[1].x "
6190 "* vs_dvec4_arr[1].x *\n"
6191 " vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6192 "* vs_array[0].struct_dvec4.x *\n"
6193 " vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6194 "* vs_array[1].struct_dvec4.x > 1.0)\n"
6195 " {\n"
6196 " gl_Position = vec4(0);\n"
6197 " }\n"
6198 " else\n"
6199 " {\n"
6200 " gl_Position = vec4(1);\n"
6201 " }\n"
6202 "}\n";
6203
6204 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6205 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6206
6207 /* Configure tessellation control shader body */
6208 const char* tc_body = "#version 400\n"
6209 "\n"
6210 "uniform double tc_double;\n"
6211 "uniform dvec2 tc_dvec2;\n"
6212 "uniform dvec3 tc_dvec3;\n"
6213 "uniform dvec4 tc_dvec4;\n"
6214 "uniform double tc_double_arr[2];\n"
6215 "uniform dvec2 tc_dvec2_arr [2];\n"
6216 "uniform dvec3 tc_dvec3_arr [2];\n"
6217 "uniform dvec4 tc_dvec4_arr [2];\n"
6218 "\n"
6219 "uniform struct tc_struct\n"
6220 "{\n"
6221 " double struct_double;\n"
6222 " dvec2 struct_dvec2;\n"
6223 " dvec3 struct_dvec3;\n"
6224 " dvec4 struct_dvec4;\n"
6225 "} tc_array[2];\n"
6226 "\n"
6227 "layout(vertices = 4) out;\n"
6228 "\n"
6229 "void main()\n"
6230 "{\n"
6231 " gl_TessLevelOuter[0] = (tc_double > 1.0) ? 2.0 : 3.0;\n"
6232 " gl_TessLevelOuter[1] = (tc_dvec2.x > 1.0) ? 3.0 : 4.0;\n"
6233 " gl_TessLevelOuter[2] = (tc_dvec3.x > 1.0) ? 4.0 : 5.0;\n"
6234 " gl_TessLevelOuter[3] = (tc_dvec4.x > 1.0) ? 5.0 : 6.0;\n"
6235 " gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6236 " gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6237 "\n"
6238 " if (tc_dvec2_arr[0].y * tc_dvec2_arr[1].y *\n"
6239 " tc_dvec3_arr[0].z * tc_dvec3_arr[1].z *\n"
6240 " tc_dvec4_arr[0].z * tc_dvec4_arr[1].z *\n"
6241 " tc_array[0].struct_double * tc_array[0].struct_dvec2.x * \n"
6242 " tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6243 " tc_array[1].struct_double * tc_array[1].struct_dvec2.x * \n"
6244 " tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6245 " {\n"
6246 " gl_TessLevelInner[1] = 3.0;\n"
6247 " }\n"
6248 "}\n";
6249
6250 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6251 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6252
6253 /* Configure tessellation evaluation shader body */
6254 const char* te_body = "#version 400\n"
6255 "\n"
6256 "uniform double te_double;\n"
6257 "uniform dvec2 te_dvec2;\n"
6258 "uniform dvec3 te_dvec3;\n"
6259 "uniform dvec4 te_dvec4;\n"
6260 "uniform double te_double_arr[2];\n"
6261 "uniform dvec2 te_dvec2_arr [2];\n"
6262 "uniform dvec3 te_dvec3_arr [2];\n"
6263 "uniform dvec4 te_dvec4_arr [2];\n"
6264 "\n"
6265 "uniform struct te_struct\n"
6266 "{\n"
6267 " double struct_double;\n"
6268 " dvec2 struct_dvec2;\n"
6269 " dvec3 struct_dvec3;\n"
6270 " dvec4 struct_dvec4;\n"
6271 "} te_array[2];\n"
6272 "\n"
6273 "layout(triangles) in;\n"
6274 "\n"
6275 "void main()\n"
6276 "{\n"
6277 " if (te_double * te_dvec2.x * te_dvec3.x "
6278 "* te_dvec4.x *\n"
6279 " te_double_arr[0] * te_dvec2_arr[0].x * te_dvec3_arr[0].x "
6280 "* te_dvec4_arr[0].x *\n"
6281 " te_double_arr[1] * te_dvec2_arr[1].x * te_dvec3_arr[1].x "
6282 "* te_dvec4_arr[1].x *\n"
6283 " te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6284 "* te_array[0].struct_dvec4.x *\n"
6285 " te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6286 "* te_array[1].struct_dvec4.x > 1.0)\n"
6287 " {\n"
6288 " gl_Position = gl_in[0].gl_Position;\n"
6289 " }\n"
6290 " else\n"
6291 " {\n"
6292 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6293 " }\n"
6294 "}\n";
6295
6296 gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6297 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6298
6299 /* Configure geometry shader body */
6300 const char* gs_body = "#version 400\n"
6301 "\n"
6302 "uniform double gs_double;\n"
6303 "uniform dvec2 gs_dvec2;\n"
6304 "uniform dvec3 gs_dvec3;\n"
6305 "uniform dvec4 gs_dvec4;\n"
6306 "uniform double gs_double_arr[2];\n"
6307 "uniform dvec2 gs_dvec2_arr [2];\n"
6308 "uniform dvec3 gs_dvec3_arr [2];\n"
6309 "uniform dvec4 gs_dvec4_arr [2];\n"
6310 "\n"
6311 "uniform struct gs_struct\n"
6312 "{\n"
6313 " double struct_double;\n"
6314 " dvec2 struct_dvec2;\n"
6315 " dvec3 struct_dvec3;\n"
6316 " dvec4 struct_dvec4;\n"
6317 "} gs_array[2];\n"
6318 "\n"
6319 "layout (points) in;\n"
6320 "layout (points, max_vertices = 1) out;\n"
6321 "\n"
6322 "void main()\n"
6323 "{\n"
6324 " if (gs_double * gs_dvec2.x * gs_dvec3.x "
6325 "* gs_dvec4.x *\n"
6326 " gs_double_arr[0] * gs_dvec2_arr[0].x * gs_dvec3_arr[0].x "
6327 "* gs_dvec4_arr[0].x *\n"
6328 " gs_double_arr[1] * gs_dvec2_arr[1].x * gs_dvec3_arr[1].x "
6329 "* gs_dvec4_arr[1].x *\n"
6330 " gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6331 "* gs_array[0].struct_dvec4.x *\n"
6332 " gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6333 "* gs_array[1].struct_dvec4.x > 1.0)\n"
6334 " {\n"
6335 " gl_Position = gl_in[0].gl_Position;\n"
6336 " }\n"
6337 " else\n"
6338 " {\n"
6339 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6340 " }\n"
6341 "\n"
6342 " EmitVertex();\n"
6343 "}\n";
6344
6345 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6346 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6347
6348 /* Configure fragment shader body */
6349 const char* fs_body = "#version 400\n"
6350 "\n"
6351 "uniform double fs_double;\n"
6352 "uniform dvec2 fs_dvec2;\n"
6353 "uniform dvec3 fs_dvec3;\n"
6354 "uniform dvec4 fs_dvec4;\n"
6355 "uniform double fs_double_arr[2];\n"
6356 "uniform dvec2 fs_dvec2_arr [2];\n"
6357 "uniform dvec3 fs_dvec3_arr [2];\n"
6358 "uniform dvec4 fs_dvec4_arr [2];\n"
6359 "\n"
6360 "uniform struct fs_struct\n"
6361 "{\n"
6362 " double struct_double;\n"
6363 " dvec2 struct_dvec2;\n"
6364 " dvec3 struct_dvec3;\n"
6365 " dvec4 struct_dvec4;\n"
6366 "} fs_array[2];\n"
6367 "\n"
6368 "out vec4 result;\n"
6369 "\n"
6370 "void main()\n"
6371 "{\n"
6372 " if (fs_double * fs_dvec2.x * fs_dvec3.x "
6373 "* fs_dvec4.x *\n"
6374 " fs_double_arr[0] * fs_dvec2_arr[0].x * fs_dvec3_arr[0].x "
6375 "* fs_dvec4_arr[0].x *\n"
6376 " fs_double_arr[1] * fs_dvec2_arr[1].x * fs_dvec3_arr[1].x "
6377 "* fs_dvec4_arr[1].x *\n"
6378 " fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6379 "* fs_array[0].struct_dvec4.x *\n"
6380 " fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6381 "* fs_array[1].struct_dvec4.x > 1.0)\n"
6382 " {\n"
6383 " result = vec4(0.0);\n"
6384 " }\n"
6385 " else\n"
6386 " {\n"
6387 " result = vec4(1.0);\n"
6388 " }\n"
6389 "}\n";
6390
6391 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6392 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6393
6394 /* Compile the shaders */
6395 const glw::GLuint shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6396 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6397
6398 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6399 {
6400 glw::GLint compile_status = GL_FALSE;
6401 glw::GLuint so_id = shaders[n_shader];
6402
6403 /* Skip compute shader if not supported */
6404 if (0 == so_id)
6405 {
6406 continue;
6407 }
6408
6409 gl.compileShader(so_id);
6410 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6411
6412 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6413 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6414
6415 if (compile_status != GL_TRUE)
6416 {
6417 TCU_FAIL("Shader compilation failed");
6418 }
6419
6420 if (so_id == m_cs_id)
6421 {
6422 gl.attachShader(m_po_cs_id, so_id);
6423 }
6424 else
6425 {
6426 gl.attachShader(m_po_noncs_id, so_id);
6427 }
6428
6429 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6430 } /* for (all shaders) */
6431
6432 /* Link the program */
6433 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6434 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6435 glw::GLint link_status = GL_FALSE;
6436
6437 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6438 {
6439 glw::GLuint po_id = programs[n_program];
6440
6441 /* Skip compute shader program if not supported */
6442 if (0 == po_id)
6443 {
6444 continue;
6445 }
6446
6447 gl.linkProgram(po_id);
6448 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6449
6450 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6451 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6452
6453 if (link_status != GL_TRUE)
6454 {
6455 TCU_FAIL("Program linking failed");
6456 }
6457 } /* for (both program objects) */
6458
6459 /* Retrieve uniform locations */
6460 _stage_data* cs_stage_data[] = { &m_data_cs };
6461 static const char* cs_uniform_prefixes[] = { "cs_" };
6462 static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6463
6464 _stage_data* noncs_stage_data[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6465 static const char* noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6466 static const unsigned int n_noncs_uniform_prefixes =
6467 sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6468
6469 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6470 {
6471 unsigned int n_uniform_prefixes = DE_NULL;
6472 glw::GLuint po_id = programs[n_program];
6473 _stage_data** stages_data = DE_NULL;
6474 const char** uniform_prefixes = DE_NULL;
6475
6476 if (n_program == 0)
6477 {
6478 stages_data = cs_stage_data;
6479 uniform_prefixes = cs_uniform_prefixes;
6480 n_uniform_prefixes = n_cs_uniform_prefixes;
6481 }
6482 else
6483 {
6484 stages_data = noncs_stage_data;
6485 uniform_prefixes = noncs_uniform_prefixes;
6486 n_uniform_prefixes = n_noncs_uniform_prefixes;
6487 }
6488
6489 /* Skip compute shader program if not supported */
6490 if (0 == po_id)
6491 {
6492 continue;
6493 }
6494
6495 /* Uniform names used by the test program consist of a prefix (different for each
6496 * shader stage) and a common part.
6497 */
6498 for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6499 {
6500 _stage_data* stage_data = stages_data[n_uniform_prefix];
6501 std::string uniform_prefix = std::string(uniform_prefixes[n_uniform_prefix]);
6502 std::string uniform_double_name = uniform_prefix + "double";
6503 std::string uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6504 std::string uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6505 std::string uniform_dvec2_name = uniform_prefix + "dvec2";
6506 std::string uniform_dvec2_arr0_name = uniform_prefix + "dvec2_arr[0]";
6507 std::string uniform_dvec2_arr1_name = uniform_prefix + "dvec2_arr[1]";
6508 std::string uniform_dvec3_name = uniform_prefix + "dvec3";
6509 std::string uniform_dvec3_arr0_name = uniform_prefix + "dvec3_arr[0]";
6510 std::string uniform_dvec3_arr1_name = uniform_prefix + "dvec3_arr[1]";
6511 std::string uniform_dvec4_name = uniform_prefix + "dvec4";
6512 std::string uniform_dvec4_arr0_name = uniform_prefix + "dvec4_arr[0]";
6513 std::string uniform_dvec4_arr1_name = uniform_prefix + "dvec4_arr[1]";
6514 std::string uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6515 std::string uniform_arr0_dvec2_name = uniform_prefix + "array[0].struct_dvec2";
6516 std::string uniform_arr0_dvec3_name = uniform_prefix + "array[0].struct_dvec3";
6517 std::string uniform_arr0_dvec4_name = uniform_prefix + "array[0].struct_dvec4";
6518 std::string uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6519 std::string uniform_arr1_dvec2_name = uniform_prefix + "array[1].struct_dvec2";
6520 std::string uniform_arr1_dvec3_name = uniform_prefix + "array[1].struct_dvec3";
6521 std::string uniform_arr1_dvec4_name = uniform_prefix + "array[1].struct_dvec4";
6522
6523 /* Retrieve uniform locations */
6524 stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6525 stage_data->uniforms.uniform_location_double_arr[0] =
6526 gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6527 stage_data->uniforms.uniform_location_double_arr[1] =
6528 gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6529 stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6530 stage_data->uniforms.uniform_location_dvec2_arr[0] =
6531 gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6532 stage_data->uniforms.uniform_location_dvec2_arr[1] =
6533 gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6534 stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6535 stage_data->uniforms.uniform_location_dvec3_arr[0] =
6536 gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6537 stage_data->uniforms.uniform_location_dvec3_arr[1] =
6538 gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6539 stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6540 stage_data->uniforms.uniform_location_dvec4_arr[0] =
6541 gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6542 stage_data->uniforms.uniform_location_dvec4_arr[1] =
6543 gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6544 stage_data->uniform_structure_arrays[0].uniform_location_double =
6545 gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6546 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6547 gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6548 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6549 gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6550 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6551 gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6552 stage_data->uniform_structure_arrays[1].uniform_location_double =
6553 gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6554 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6555 gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6556 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6557 gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6558 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6559 gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6560 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6561
6562 if (stage_data->uniforms.uniform_location_double == -1 ||
6563 stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6564 stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6565 stage_data->uniforms.uniform_location_dvec2 == -1 ||
6566 stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6567 stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6568 stage_data->uniforms.uniform_location_dvec3 == -1 ||
6569 stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6570 stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6571 stage_data->uniforms.uniform_location_dvec4 == -1 ||
6572 stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6573 stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6574 stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6575 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6576 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6577 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6578 stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6579 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6580 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6581 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6582 {
6583 TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6584 }
6585
6586 /* Make sure locations of subsequent items in array uniforms are correct */
6587 if (stage_data->uniforms.uniform_location_double_arr[1] !=
6588 (stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6589 stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6590 (stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6591 stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6592 (stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6593 stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6594 (stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6595 {
6596 m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6597 " double_arr[0]:"
6598 << stage_data->uniforms.uniform_location_double_arr[0]
6599 << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6600 << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6601 << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6602 << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6603 << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6604 << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6605 << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6606 << tcu::TestLog::EndMessage;
6607
6608 TCU_FAIL("Double-precision uniform array item locations are invalid.");
6609 }
6610 } /* for (all uniform prefixes) */
6611 } /* for (both program objects) */
6612 }
6613
6614 /** Initializes all objects required to run the test. */
initTest()6615 void GPUShaderFP64Test4::initTest()
6616 {
6617 initProgramObjects();
6618
6619 generateUniformValues();
6620 initUniformValues();
6621 }
6622
6623 /** Assigns values generated by generateUniformValues() to uniforms defined by
6624 * both program objects.
6625 **/
initUniformValues()6626 void GPUShaderFP64Test4::initUniformValues()
6627 {
6628 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6629
6630 /* Iterate through all programs */
6631 _stage_data* cs_stages[] = { &m_data_cs };
6632 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6633 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6634 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6635
6636 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6637 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6638
6639 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6640 {
6641 glw::GLuint po_id = programs[n_program];
6642 unsigned int n_stages = 0;
6643 _stage_data** stage_data = DE_NULL;
6644
6645 if (po_id == m_po_cs_id)
6646 {
6647 n_stages = n_cs_stages;
6648 stage_data = cs_stages;
6649 }
6650 else
6651 {
6652 n_stages = n_noncs_stages;
6653 stage_data = noncs_stages;
6654 }
6655
6656 /* Skip compute shader program if not supported */
6657 if (0 == po_id)
6658 {
6659 continue;
6660 }
6661
6662 gl.useProgram(po_id);
6663 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6664
6665 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6666 {
6667 /* Iterate through all uniforms */
6668 _stage_data* stage_ptr = stage_data[n_stage];
6669
6670 gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6671 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6672 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6673 gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6674 stage_ptr->uniform_structure_arrays[0].uniform_double);
6675 gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6676 stage_ptr->uniform_structure_arrays[1].uniform_double);
6677 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6678
6679 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6680 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6681 stage_ptr->uniforms.uniform_dvec2_arr + 0);
6682 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6683 stage_ptr->uniforms.uniform_dvec2_arr + 2);
6684 gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6685 stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6686 gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6687 stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6688 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6689
6690 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6691 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6692 stage_ptr->uniforms.uniform_dvec3_arr + 0);
6693 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6694 stage_ptr->uniforms.uniform_dvec3_arr + 3);
6695 gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6696 stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6697 gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6698 stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6699 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6700
6701 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6702 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6703 stage_ptr->uniforms.uniform_dvec4_arr + 0);
6704 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6705 stage_ptr->uniforms.uniform_dvec4_arr + 4);
6706 gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6707 stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6708 gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6709 stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6710 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6711 } /* for (all shader stages) */
6712 } /* for (both program objects) */
6713 }
6714
6715 /** Executes test iteration.
6716 *
6717 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6718 */
iterate()6719 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6720 {
6721 /* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6722
6723 /* Initialize all objects required to run the test */
6724 initTest();
6725
6726 /* Verify the implementation reports correct values for all stages we've configured */
6727 m_has_test_passed &= verifyUniformValues();
6728
6729 /* Is this also the case when "program interface query" mechanism is used? */
6730 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6731 {
6732 m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6733 }
6734
6735 /* We're done */
6736 if (m_has_test_passed)
6737 {
6738 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6739 }
6740 else
6741 {
6742 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6743 }
6744
6745 return STOP;
6746 }
6747
6748 /** Verifies that:
6749 *
6750 * a) glGetProgramResourceIndex()
6751 * b) glGetProgramResourceiv()
6752 * c) glGetProgramResourceName()
6753 *
6754 * functions return correct values for double-precision uniforms.
6755 *
6756 * @return true if the verification was passed, false otherwise.
6757 */
verifyProgramInterfaceQuerySupport()6758 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6759 {
6760 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6761 bool result = true;
6762
6763 /* Iterate through all programs */
6764 const char* cs_prefixes[] = { "cs_" };
6765 _stage_data* cs_stages[] = { &m_data_cs };
6766 const char* noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6767 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6768 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6769 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6770
6771 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6772 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6773
6774 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6775 {
6776 glw::GLuint po_id = programs[n_program];
6777 unsigned int n_stages = 0;
6778 const char** stage_prefixes = DE_NULL;
6779 _stage_data** stage_data = DE_NULL;
6780
6781 if (po_id == m_po_cs_id)
6782 {
6783 n_stages = n_cs_stages;
6784 stage_data = cs_stages;
6785 stage_prefixes = cs_prefixes;
6786 }
6787 else
6788 {
6789 n_stages = n_noncs_stages;
6790 stage_data = noncs_stages;
6791 stage_prefixes = noncs_prefixes;
6792 }
6793
6794 /* Skip compute shader program if not supported */
6795 if (0 == po_id)
6796 {
6797 continue;
6798 }
6799
6800 /* Determine maximum uniform name length */
6801 glw::GLint max_uniform_name_length = 0;
6802
6803 gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6804 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6805
6806 /* Allocate a buffer we will use to hold uniform names */
6807 m_uniform_name_buffer = new char[max_uniform_name_length];
6808
6809 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6810 {
6811 /* Iterate through all uniforms */
6812 _stage_data* stage_ptr = stage_data[n_stage];
6813 const char* stage_prefix = stage_prefixes[n_stage];
6814
6815 /* Construct an array that will be used to run the test in an automated manner */
6816 _program_interface_query_test_item uniforms[] = {
6817 /* array size */ /* name */ /* type */ /* location */
6818 { 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6819 { 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6820 { 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6821 { 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6822 { 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6823 { 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6824 { 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6825 { 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6826 { 1, "array[0].struct_double", GL_DOUBLE,
6827 stage_ptr->uniform_structure_arrays->uniform_location_double },
6828 { 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6829 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6830 { 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6831 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6832 { 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6833 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6834 { 1, "array[1].struct_double", GL_DOUBLE,
6835 stage_ptr->uniform_structure_arrays->uniform_location_double },
6836 { 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6837 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6838 { 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6839 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6840 { 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6841 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6842 };
6843 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6844
6845 /* Prefix the names with stage-specific string */
6846 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6847 {
6848 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6849
6850 current_item.name = std::string(stage_prefix) + current_item.name;
6851 } /* for (all uniform descriptors) */
6852
6853 const glw::GLenum properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6854 const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6855
6856 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6857 {
6858 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6859 glw::GLint n_written_items = 0;
6860 glw::GLint retrieved_array_size = 0;
6861 glw::GLint retrieved_name_length = 0;
6862 glw::GLenum retrieved_type = GL_NONE;
6863 glw::GLint temp_buffer[2] = { 0, GL_NONE };
6864
6865 /* Retrieve index of the iteration-specific uniform */
6866 glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6867 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6868
6869 /* Make sure glGetProgramResourceName() returns correct values */
6870 memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6871
6872 gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6873 resource_index, max_uniform_name_length, &retrieved_name_length,
6874 m_uniform_name_buffer);
6875 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6876
6877 if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6878 memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6879 {
6880 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6881 << resource_index << "]"
6882 ": expected:["
6883 << current_item.name << "]"
6884 ", reported:["
6885 << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6886
6887 result = false;
6888 continue;
6889 }
6890
6891 /* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6892 gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6893 resource_index, n_properties, properties,
6894 sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6895 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6896
6897 if (n_written_items != n_properties)
6898 {
6899 TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6900 }
6901
6902 /* For clarity, copy the retrieved values to separate variables */
6903 retrieved_array_size = temp_buffer[0];
6904 retrieved_type = temp_buffer[1];
6905
6906 /* Verify the values */
6907 if (retrieved_array_size != current_item.expected_array_size)
6908 {
6909 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6910 << current_item.name << "]"
6911 << ": expected:[" << current_item.expected_array_size << "]"
6912 ", reported:["
6913 << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6914
6915 result = false;
6916 }
6917
6918 if (retrieved_type != current_item.expected_type)
6919 {
6920 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6921 << current_item.name << "]"
6922 << ": expected:[" << current_item.expected_type << "]"
6923 ", reported:["
6924 << retrieved_type << "]" << tcu::TestLog::EndMessage;
6925
6926 result = false;
6927 }
6928 } /* for (all uniforms) */
6929 } /* for (all shader stages) */
6930
6931 /* We're now OK to release the buffer we used to hold uniform names for
6932 * the program */
6933 if (m_uniform_name_buffer != DE_NULL)
6934 {
6935 delete[] m_uniform_name_buffer;
6936
6937 m_uniform_name_buffer = DE_NULL;
6938 }
6939 } /* for (both program objects) */
6940
6941 return result;
6942 }
6943
6944 /** Verifies glGetUniform*() calls return correct values assigned to
6945 * double-precision uniforms.
6946 *
6947 * @return true if all values reported by OpenGL were found to be correct,
6948 * false otherwise.
6949 **/
verifyUniformValues()6950 bool GPUShaderFP64Test4::verifyUniformValues()
6951 {
6952 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6953 bool result = true;
6954
6955 /* Iterate through all programs */
6956 _stage_data* cs_stages[] = { &m_data_cs };
6957 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6958 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6959 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6960
6961 const glw::GLuint programs[] = {
6962 m_po_noncs_id, m_po_cs_id,
6963 };
6964 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6965
6966 /* Set up rounding for the tests */
6967 deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
6968
6969 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6970 {
6971 glw::GLuint po_id = programs[n_program];
6972 unsigned int n_stages = 0;
6973 _stage_data** stage_data = DE_NULL;
6974
6975 if (po_id == m_po_cs_id)
6976 {
6977 n_stages = n_cs_stages;
6978 stage_data = cs_stages;
6979 }
6980 else
6981 {
6982 n_stages = n_noncs_stages;
6983 stage_data = noncs_stages;
6984 }
6985
6986 /* Skip compute shader program if not supported */
6987 if (0 == po_id)
6988 {
6989 continue;
6990 }
6991
6992 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6993 {
6994 /* Iterate through all uniforms */
6995 _stage_data* stage_ptr = stage_data[n_stage];
6996
6997 /* Set up arrays that we will guide the automated testing */
6998 const uniform_value_pair double_uniforms[] = {
6999 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
7000 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
7001 stage_ptr->uniforms.uniform_double_arr + 0),
7002 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
7003 stage_ptr->uniforms.uniform_double_arr + 1),
7004 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
7005 &stage_ptr->uniform_structure_arrays[0].uniform_double),
7006 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
7007 &stage_ptr->uniform_structure_arrays[1].uniform_double)
7008 };
7009 const uniform_value_pair dvec2_uniforms[] = {
7010 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
7011 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
7012 stage_ptr->uniforms.uniform_dvec2_arr + 0),
7013 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
7014 stage_ptr->uniforms.uniform_dvec2_arr + 2),
7015 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
7016 stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
7017 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
7018 stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
7019 };
7020 const uniform_value_pair dvec3_uniforms[] = {
7021 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
7022 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
7023 stage_ptr->uniforms.uniform_dvec3_arr + 0),
7024 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
7025 stage_ptr->uniforms.uniform_dvec3_arr + 3),
7026 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
7027 stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
7028 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
7029 stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7030 };
7031 const uniform_value_pair dvec4_uniforms[] = {
7032 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7033 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7034 stage_ptr->uniforms.uniform_dvec4_arr + 0),
7035 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7036 stage_ptr->uniforms.uniform_dvec4_arr + 4),
7037 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7038 stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7039 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7040 stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7041 };
7042
7043 /* Iterate over all uniforms and verify the values reported by the API */
7044 double returned_double_data[4];
7045 float returned_float_data[4];
7046 int returned_int_data[4];
7047 unsigned int returned_uint_data[4];
7048
7049 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7050 {
7051 const uniform_value_pair* current_uv_pairs = NULL;
7052 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7053 unsigned int n_pairs = 0;
7054
7055 switch (n_type)
7056 {
7057 case 0: /* double */
7058 {
7059 current_uv_pairs = double_uniforms;
7060 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7061
7062 break;
7063 }
7064
7065 case 1: /* dvec2 */
7066 {
7067 current_uv_pairs = dvec2_uniforms;
7068 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7069
7070 break;
7071 }
7072
7073 case 2: /* dvec3 */
7074 {
7075 current_uv_pairs = dvec3_uniforms;
7076 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7077
7078 break;
7079 }
7080
7081 case 3: /* dvec4 */
7082 {
7083 current_uv_pairs = dvec4_uniforms;
7084 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7085
7086 break;
7087 }
7088
7089 default:
7090 {
7091 TCU_FAIL("Invalid type index requested");
7092 }
7093 } /* switch (n_type) */
7094
7095 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7096 {
7097 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair];
7098 glw::GLint uniform_location = current_uv_pair.first;
7099 const double* uniform_value = current_uv_pair.second;
7100
7101 /* Retrieve the values from the GL implementation*/
7102 gl.getUniformdv(po_id, uniform_location, returned_double_data);
7103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7104
7105 gl.getUniformfv(po_id, uniform_location, returned_float_data);
7106 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7107
7108 gl.getUniformiv(po_id, uniform_location, returned_int_data);
7109 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7110
7111 gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7113
7114 /* Make sure the values reported match the reference values */
7115 bool can_continue = true;
7116 const float epsilon = 1e-5f;
7117
7118 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7119 {
7120 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7121 {
7122 m_testCtx.getLog()
7123 << tcu::TestLog::Message
7124 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7125 << uniform_location << "]"
7126 " and component ["
7127 << n_component << "]"
7128 ": retrieved:["
7129 << returned_double_data[n_component] << "]"
7130 ", expected:["
7131 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7132
7133 result = false;
7134 }
7135
7136 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7137 {
7138 m_testCtx.getLog()
7139 << tcu::TestLog::Message
7140 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7141 << uniform_location << "]"
7142 " and component ["
7143 << n_component << "]"
7144 ": retrieved:["
7145 << returned_float_data[n_component] << "]"
7146 ", expected:["
7147 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7148
7149 result = false;
7150 }
7151
7152 /* ints */
7153 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7154 unsigned int rounded_uniform_value_uint =
7155 (unsigned int)(uniform_value[n_component] > 0.0) ?
7156 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7157 0;
7158
7159 if (returned_int_data[n_component] != rounded_uniform_value_sint)
7160 {
7161 m_testCtx.getLog()
7162 << tcu::TestLog::Message
7163 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7164 << uniform_location << "]"
7165 " and component ["
7166 << n_component << "]"
7167 ": retrieved:["
7168 << returned_int_data[n_component] << "]"
7169 ", expected:["
7170 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7171
7172 result = false;
7173 }
7174
7175 if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7176 {
7177 m_testCtx.getLog()
7178 << tcu::TestLog::Message
7179 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7180 << uniform_location << "]"
7181 " and component ["
7182 << n_component << "]"
7183 ": retrieved:["
7184 << returned_uint_data[n_component] << "]"
7185 ", expected:["
7186 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7187
7188 result = false;
7189 }
7190 } /* for (all components) */
7191 } /* for (all uniform+value pairs) */
7192 } /* for (all 4 uniform types) */
7193 } /* for (all shader stages) */
7194 } /* for (both program objects) */
7195
7196 /* All done! */
7197 return result;
7198 }
7199
7200 /** Constructor
7201 *
7202 * @param context Rendering context.
7203 */
GPUShaderFP64Test5(deqp::Context & context)7204 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7205 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7206 " floating-point variables work correctly")
7207 , m_base_value_bo_data(DE_NULL)
7208 , m_base_value_bo_id(0)
7209 , m_has_test_passed(true)
7210 , m_po_base_value_attribute_location(-1)
7211 , m_po_id(0)
7212 , m_vao_id(0)
7213 , m_vs_id(0)
7214 , m_xfb_bo_id(0)
7215 , m_xfb_bo_size(0)
7216 {
7217 /* Set up base value array (as per test spec) */
7218 m_base_values[0] = -25.12065f;
7219 m_base_values[1] = 0.0f;
7220 m_base_values[2] = 0.001f;
7221 m_base_values[3] = 1.0f;
7222 m_base_values[4] = 256.78901f;
7223
7224 /* Set up swizzle matrix */
7225 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7226 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7227 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7228 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7229 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7230 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7231 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7232 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7233 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7234 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7235 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7236 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7237 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7238 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7239 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7240 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7241 }
7242
deinit()7243 void GPUShaderFP64Test5::deinit()
7244 {
7245 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7246
7247 if (m_base_value_bo_data != DE_NULL)
7248 {
7249 delete[] m_base_value_bo_data;
7250
7251 m_base_value_bo_data = DE_NULL;
7252 }
7253
7254 if (m_base_value_bo_id != 0)
7255 {
7256 gl.deleteBuffers(1, &m_base_value_bo_id);
7257
7258 m_base_value_bo_id = 0;
7259 }
7260
7261 if (m_vao_id != 0)
7262 {
7263 gl.deleteVertexArrays(1, &m_vao_id);
7264
7265 m_vao_id = 0;
7266 }
7267
7268 if (m_xfb_bo_id != 0)
7269 {
7270 gl.deleteBuffers(1, &m_xfb_bo_id);
7271
7272 m_xfb_bo_id = 0;
7273 }
7274
7275 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7276 * take care of it here
7277 */
7278 deinitInteration();
7279 }
7280
7281 /** Deinitializes all buffers and GL objects that may have been generated
7282 * during test execution.
7283 **/
deinitInteration()7284 void GPUShaderFP64Test5::deinitInteration()
7285 {
7286 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7287
7288 if (m_po_id != 0)
7289 {
7290 gl.deleteProgram(m_po_id);
7291
7292 m_po_id = 0;
7293 }
7294
7295 if (m_vs_id != 0)
7296 {
7297 gl.deleteShader(m_vs_id);
7298
7299 m_vs_id = 0;
7300 }
7301 }
7302
7303 /** Executes a single test case iteration using user-provided test case descriptor.
7304 *
7305 * This function may throw a TestError exception if GL implementation misbehaves.
7306 *
7307 * @param test_case Test case descriptor to use.
7308 *
7309 * @return true if the values returned by GL implementation were found to be valid,
7310 * false otherwise.
7311 **/
executeIteration(const _test_case & test_case)7312 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7313 {
7314 bool result = true;
7315
7316 /* Convert the base values array to the type of input attribute we'll be using
7317 * for the iteration.
7318 */
7319 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7320
7321 if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7322 {
7323 /* bools are actually represented by ints, since bool varyings are not allowed */
7324 base_value_type = Utils::VARIABLE_TYPE_INT;
7325 }
7326
7327 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7328 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7329
7330 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7331
7332 unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7333
7334 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7335 {
7336 switch (base_value_type)
7337 {
7338 case Utils::VARIABLE_TYPE_DOUBLE:
7339 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7340 break;
7341 case Utils::VARIABLE_TYPE_FLOAT:
7342 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7343 break;
7344 case Utils::VARIABLE_TYPE_INT:
7345 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7346 break;
7347 case Utils::VARIABLE_TYPE_UINT:
7348 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7349 break;
7350
7351 default:
7352 {
7353 TCU_FAIL("Unrecognized base value type");
7354 }
7355 }
7356
7357 base_value_traveller_ptr += base_value_component_size;
7358 } /* for (all base values) */
7359
7360 /* Update buffer object storage with the data we've just finished preparing. */
7361 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7362
7363 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7364 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7365
7366 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7367 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7368
7369 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7370 * new data is interpreted correctly.
7371 */
7372 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7373 {
7374 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */
7375 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7376 0, /* stride */
7377 DE_NULL); /* pointer */
7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7379 }
7380 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7381 {
7382 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */
7383 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7384 DE_NULL); /* pointer */
7385 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7386 }
7387 else
7388 {
7389 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7390
7391 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7392 GL_DOUBLE, 0, /* stride */
7393 DE_NULL); /* pointer */
7394 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7395 }
7396
7397 gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7398 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7399
7400 /* Execute the draw call */
7401 gl.useProgram(m_po_id);
7402 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7403
7404 gl.beginTransformFeedback(GL_POINTS);
7405 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7406 {
7407 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7408 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7409 }
7410 gl.endTransformFeedback();
7411 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7412
7413 /* Map the XFB buffer object into process space */
7414 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7415
7416 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7417 DE_ASSERT(xfb_data_ptr != NULL);
7418
7419 /* Verify the data */
7420 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7421
7422 /* Unmap the XFB BO */
7423 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7424 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7425
7426 /** Good to release the data buffer at this point */
7427 if (m_base_value_bo_data != DE_NULL)
7428 {
7429 delete[] m_base_value_bo_data;
7430
7431 m_base_value_bo_data = DE_NULL;
7432 }
7433
7434 /* All done */
7435 return result;
7436 }
7437
7438 /** Returns properties of a swizzle operator described by @param type swizzle type.
7439 *
7440 * @param out_swizzle_string Deref will be used to store a GLSL literal
7441 * corresponding to the specific swizzle operator.
7442 * Must not be NULL.
7443 * @param out_n_components Deref will be used to store the amount of components
7444 * used by the operator. Must not be NULL.
7445 * @param out_component_order Deref will be used to store up to 4 integer values,
7446 * corresponding to component indices described by the
7447 * operator for a particular position. Must not be NULL.
7448 **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7449 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7450 unsigned int* out_n_components, unsigned int* out_component_order)
7451 {
7452 unsigned int result_component_order[4] = { 0 };
7453 unsigned int result_n_components = 0;
7454 std::string result_swizzle_string;
7455
7456 switch (type)
7457 {
7458 case SWIZZLE_TYPE_NONE:
7459 {
7460 result_swizzle_string = "";
7461 result_n_components = 0;
7462
7463 break;
7464 }
7465
7466 case SWIZZLE_TYPE_XWZY:
7467 {
7468 result_swizzle_string = "xwzy";
7469 result_n_components = 4;
7470 result_component_order[0] = 0;
7471 result_component_order[1] = 3;
7472 result_component_order[2] = 2;
7473 result_component_order[3] = 1;
7474
7475 break;
7476 }
7477
7478 case SWIZZLE_TYPE_XZXY:
7479 {
7480 result_swizzle_string = "xzxy";
7481 result_n_components = 4;
7482 result_component_order[0] = 0;
7483 result_component_order[1] = 2;
7484 result_component_order[2] = 0;
7485 result_component_order[3] = 1;
7486
7487 break;
7488 }
7489
7490 case SWIZZLE_TYPE_XZY:
7491 {
7492 result_swizzle_string = "xzy";
7493 result_n_components = 3;
7494 result_component_order[0] = 0;
7495 result_component_order[1] = 2;
7496 result_component_order[2] = 1;
7497
7498 break;
7499 }
7500
7501 case SWIZZLE_TYPE_XZYW:
7502 {
7503 result_swizzle_string = "xzyw";
7504 result_n_components = 4;
7505 result_component_order[0] = 0;
7506 result_component_order[1] = 2;
7507 result_component_order[2] = 1;
7508 result_component_order[3] = 3;
7509
7510 break;
7511 }
7512
7513 case SWIZZLE_TYPE_Y:
7514 {
7515 result_swizzle_string = "y";
7516 result_n_components = 1;
7517 result_component_order[0] = 1;
7518
7519 break;
7520 }
7521
7522 case SWIZZLE_TYPE_YX:
7523 {
7524 result_swizzle_string = "yx";
7525 result_n_components = 2;
7526 result_component_order[0] = 1;
7527 result_component_order[1] = 0;
7528
7529 break;
7530 }
7531
7532 case SWIZZLE_TYPE_YXX:
7533 {
7534 result_swizzle_string = "yxx";
7535 result_n_components = 3;
7536 result_component_order[0] = 1;
7537 result_component_order[1] = 0;
7538 result_component_order[2] = 0;
7539
7540 break;
7541 }
7542
7543 case SWIZZLE_TYPE_YXXY:
7544 {
7545 result_swizzle_string = "yxxy";
7546 result_n_components = 4;
7547 result_component_order[0] = 1;
7548 result_component_order[1] = 0;
7549 result_component_order[2] = 0;
7550 result_component_order[3] = 1;
7551
7552 break;
7553 }
7554
7555 case SWIZZLE_TYPE_Z:
7556 {
7557 result_swizzle_string = "z";
7558 result_n_components = 1;
7559 result_component_order[0] = 2;
7560
7561 break;
7562 }
7563
7564 case SWIZZLE_TYPE_ZY:
7565 {
7566 result_swizzle_string = "zy";
7567 result_n_components = 2;
7568 result_component_order[0] = 2;
7569 result_component_order[1] = 1;
7570
7571 break;
7572 }
7573
7574 case SWIZZLE_TYPE_W:
7575 {
7576 result_swizzle_string = "w";
7577 result_n_components = 1;
7578 result_component_order[0] = 3;
7579
7580 break;
7581 }
7582
7583 case SWIZZLE_TYPE_WX:
7584 {
7585 result_swizzle_string = "wx";
7586 result_n_components = 2;
7587 result_component_order[0] = 3;
7588 result_component_order[1] = 0;
7589
7590 break;
7591 }
7592
7593 default:
7594 {
7595 TCU_FAIL("Unrecognized swizzle type");
7596 }
7597 } /* switch (type) */
7598
7599 if (out_swizzle_string != DE_NULL)
7600 {
7601 *out_swizzle_string = result_swizzle_string;
7602 }
7603
7604 if (out_n_components != DE_NULL)
7605 {
7606 *out_n_components = result_n_components;
7607 }
7608
7609 if (out_component_order != DE_NULL)
7610 {
7611 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7612 }
7613 }
7614
7615 /** Returns body of a vertex shader that should be used for particular test case,
7616 * given user-specified test case descriptor.
7617 *
7618 * @param test_case Descriptor to use for the query.
7619 *
7620 * @return Requested data.
7621 **/
getVertexShaderBody(const _test_case & test_case)7622 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7623 {
7624 std::stringstream result;
7625 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7626 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type);
7627 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7628 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7629 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type);
7630
7631 /* Add version preamble */
7632 result << "#version 420\n"
7633 "\n";
7634
7635 /* Declare output variables. Note that boolean output variables are not supported, so we need
7636 * to handle that special case correctly */
7637 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7638 {
7639 result << "out int result;\n";
7640 }
7641 else
7642 {
7643 result << "out " << dst_type_string << " result;\n";
7644 }
7645
7646 /* Declare input variables. Handle the bool case exclusively. */
7647 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7648 {
7649 /* Use ints for bools. We will cast them to bool in the code later. */
7650 result << "in int base_value;\n";
7651 }
7652 else
7653 {
7654 result << "in " << base_type_string << " base_value;\n";
7655 }
7656
7657 /* Declare main() and construct the value we will be casting from.
7658 *
7659 * Note: Addition operations on bool values cause an implicit conversion to int
7660 * which is not allowed. Hence, we skip these operations for this special
7661 * case.
7662 */
7663 result << "void main()\n"
7664 "{\n"
7665 << src_type_string << " lside_value = ";
7666
7667 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7668 {
7669 result << src_type_string << "(0 != ";
7670 }
7671 else
7672 {
7673 result << src_type_string << "(";
7674 }
7675
7676 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7677 {
7678 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7679 {
7680 result << "base_value + " << n_component;
7681
7682 if (n_component != (n_src_components - 1))
7683 {
7684 result << ", ";
7685 }
7686 } /* for (all components) */
7687 }
7688 else
7689 {
7690 DE_ASSERT(n_src_components == 1);
7691
7692 result << "base_value";
7693 }
7694
7695 result << ");\n";
7696
7697 /* Perform the casting operation. Add swizzle operator if possible. */
7698 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7699 {
7700 /* Handle the bool case exclusively */
7701 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7702 {
7703 result << "result = (bool(lside_value) == false) ? 0 : 1";
7704 }
7705 else
7706 {
7707 result << "result = (lside_value == false) ? 0 : 1";
7708 }
7709 }
7710 else
7711 {
7712 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7713 {
7714 result << "result = " << dst_type_string << "(lside_value)";
7715 }
7716 else
7717 {
7718 result << "result = lside_value";
7719 }
7720 }
7721
7722 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7723 {
7724 /* Add a swizzle operator */
7725 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7726 DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7727
7728 unsigned int swizzle_component_order[4] = { 0 };
7729 unsigned int swizzle_n_components = 0;
7730 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7731 std::string swizzle_string;
7732
7733 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7734
7735 if (swizzle_n_components > 0)
7736 {
7737 result << "." << swizzle_string;
7738 }
7739 }
7740
7741 /* Close the shader implementation. */
7742 result << ";\n"
7743 "}\n";
7744
7745 return result.str();
7746 }
7747
7748 /** Initializes program & shader objects needed to run the iteration, given
7749 * user-specified test case descriptor.
7750 *
7751 * This function can throw a TestError exception if a GL error is detected
7752 * during execution.
7753 *
7754 * @param test_case Descriptor to use for the iteration.
7755 **/
initIteration(_test_case & test_case)7756 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7757 {
7758 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7759
7760 /* Create program & shader objects */
7761 m_po_id = gl.createProgram();
7762 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7763
7764 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7765 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7766
7767 /* Configure shader body */
7768 std::string body = getVertexShaderBody(test_case);
7769 const char* body_raw_ptr = body.c_str();
7770
7771 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7772 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7773
7774 /* Store it in the test case descriptor for logging purposes */
7775 test_case.shader_body = body;
7776
7777 /* Compile the shader */
7778 glw::GLint compile_status = GL_FALSE;
7779
7780 gl.compileShader(m_vs_id);
7781 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7782
7783 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7784 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7785
7786 if (compile_status != GL_TRUE)
7787 {
7788 TCU_FAIL("Shader compilation failed");
7789 }
7790
7791 /* Attach the shader to the program obejct */
7792 gl.attachShader(m_po_id, m_vs_id);
7793 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7794
7795 /* Configure XFB for the program object */
7796 const char* xfb_varying_name = "result";
7797
7798 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7799 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7800
7801 /* Link the program object */
7802 glw::GLint link_status = GL_FALSE;
7803
7804 gl.linkProgram(m_po_id);
7805 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7806
7807 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7808 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7809
7810 if (link_status != GL_TRUE)
7811 {
7812 TCU_FAIL("Program linking failed");
7813 }
7814
7815 /* Retrieve attribute locations */
7816 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7817 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7818
7819 if (m_po_base_value_attribute_location == -1)
7820 {
7821 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7822 }
7823 }
7824
7825 /** Initializes GL objects used by all test cases.
7826 *
7827 * This function may throw a TestError exception if GL implementation reports
7828 * an error at any point.
7829 **/
initTest()7830 void GPUShaderFP64Test5::initTest()
7831 {
7832 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7833
7834 /* Generate buffer object IDs */
7835 gl.genBuffers(1, &m_base_value_bo_id);
7836 gl.genBuffers(1, &m_xfb_bo_id);
7837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7838
7839 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7840 * will never eat up more than 1 double (as per test spec) and we will be drawing
7841 * as many points in a single draw call as there are defined in m_base_values array.
7842 */
7843 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7844
7845 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7846 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7847
7848 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7849 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7850
7851 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7852 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7853 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7854 */
7855 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7856
7857 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7858 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7859
7860 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7861 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7862
7863 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7864 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7865
7866 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7867 m_xfb_bo_size = xfb_bo_size;
7868
7869 /* Generate a vertex array object we will need to use for the draw calls */
7870 gl.genVertexArrays(1, &m_vao_id);
7871 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7872
7873 gl.bindVertexArray(m_vao_id);
7874 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7875 }
7876
7877 /** Executes test iteration.
7878 *
7879 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7880 */
iterate()7881 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7882 {
7883 /* Do not execute the test if GL_ARB_texture_view is not supported */
7884 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7885 {
7886 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7887 }
7888
7889 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7890 {
7891 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7892 }
7893
7894 /* Initialize GL objects needed to run the tests */
7895 initTest();
7896
7897 /* Build iteration array to run the tests in an automated manner */
7898 _test_case test_cases[] = {
7899 /* test case type */ /* source type */ /* destination type */
7900 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7901 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7902 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7903 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7904 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7905 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7906 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7907 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7908 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7909 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7910 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7911 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7912 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7913 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7914 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7915 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7916 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7917 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7918 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7919 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7920 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7921
7922 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7923 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7924 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7925 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7926 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7927 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7928 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7929 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7930 };
7931 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7932
7933 /* Execute all iterations */
7934 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7935 {
7936 _test_case& test_case = test_cases[n_test_case];
7937
7938 /* Initialize a program object we will use to perform the casting */
7939 initIteration(test_case);
7940
7941 /* Use the program object to XFB the results */
7942 m_has_test_passed &= executeIteration(test_case);
7943
7944 /* Release the GL Resource for this sub test */
7945 deinitInteration();
7946
7947 } /* for (all test cases) */
7948 /* We're done */
7949 if (m_has_test_passed)
7950 {
7951 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7952 }
7953 else
7954 {
7955 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7956 }
7957
7958 return STOP;
7959 }
7960
7961 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7962 * for which the data have been generated.
7963 *
7964 * @param data_ptr Buffer holding the data XFBed out by the shader.
7965 * @param test_case Descriptor of the test case, for which the vertex shader was
7966 * generated.
7967 *
7968 * @return true if the data were found to be valid, false otherwise.
7969 **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7970 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7971 {
7972 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
7973 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
7974 const float epsilon = 1e-5f;
7975 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7976 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7977 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7978 bool result = true;
7979 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE;
7980 unsigned int swizzle_order[4] = { 0 };
7981 const unsigned char* traveller_ptr = data_ptr;
7982
7983 if (!Utils::isMatrixVariableType(test_case.src_type))
7984 {
7985 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7986 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7987
7988 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7989
7990 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7991 DE_NULL, /* out_n_components */
7992 swizzle_order);
7993 }
7994
7995 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7996 {
7997 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7998 {
7999 unsigned int n_swizzled_component = n_result_component;
8000
8001 if (swizzle_operator != SWIZZLE_TYPE_NONE)
8002 {
8003 n_swizzled_component =
8004 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
8005 }
8006
8007 switch (base_dst_type)
8008 {
8009 case Utils::VARIABLE_TYPE_BOOL:
8010 case Utils::VARIABLE_TYPE_INT:
8011 {
8012 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8013 double expected_value = ref_expected_value;
8014 int result_value = *((int*)traveller_ptr);
8015
8016 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
8017 {
8018 if (expected_value != 0.0)
8019 {
8020 expected_value = 1.0;
8021 }
8022 }
8023
8024 if (result_value != (int)expected_value)
8025 {
8026 m_testCtx.getLog() << tcu::TestLog::Message
8027 << "Invalid boolean/integer value obtained when doing an "
8028 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8029 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8030 << "]"
8031 ", component index: ["
8032 << n_swizzled_component << "]"
8033 ", value: ["
8034 << ref_expected_value << "]"
8035 " to GLSL type ["
8036 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8037 ", retrieved value: ["
8038 << result_value << "]"
8039 ", expected value: ["
8040 << (int)expected_value << "]"
8041 ", shader used:\n"
8042 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8043
8044 result = false;
8045 }
8046
8047 traveller_ptr += sizeof(int);
8048 break;
8049 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8050
8051 case Utils::VARIABLE_TYPE_DOUBLE:
8052 {
8053 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8054 double expected_value = ref_expected_value;
8055 double result_value = *((double*)traveller_ptr);
8056
8057 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8058 {
8059 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8060 }
8061 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8062 {
8063 expected_value = (int)expected_value;
8064 }
8065 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8066 {
8067 // Negative values in base values array when converted to unsigned int will be ZERO
8068 // Addition operations done inside the shader in such cases will operate on ZERO rather
8069 // than the negative value being passed.
8070 // Replicate the sequence of conversion and addition operations done on the
8071 // shader input, to calculate the expected values in XFB data in the
8072 // problematic cases.
8073 if (expected_value < 0)
8074 {
8075 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8076 }
8077 expected_value = (unsigned int)expected_value;
8078 }
8079
8080 traveller_ptr += sizeof(double);
8081 if (de::abs(result_value - expected_value) > epsilon)
8082 {
8083 m_testCtx.getLog() << tcu::TestLog::Message
8084 << "Invalid double-precision floating-point value obtained when doing an "
8085 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8086 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8087 << "]"
8088 ", component index: ["
8089 << n_swizzled_component << "]"
8090 ", value: ["
8091 << ref_expected_value << "]"
8092 " to GLSL type ["
8093 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8094 ", retrieved value: ["
8095 << std::setprecision(16) << result_value << "]"
8096 ", expected value: ["
8097 << std::setprecision(16) << expected_value << "]"
8098 ", shader used:\n"
8099 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8100
8101 result = false;
8102 }
8103
8104 break;
8105 } /* VARIABLE_TYPE_DOUBLE case */
8106
8107 case Utils::VARIABLE_TYPE_FLOAT:
8108 {
8109 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8110 float expected_value = ref_expected_value;
8111 float result_value = *((float*)traveller_ptr);
8112
8113 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8114 {
8115 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8116 }
8117 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8118 {
8119 expected_value = (float)((int)expected_value);
8120 }
8121 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8122 {
8123 expected_value = (float)((unsigned int)expected_value);
8124 }
8125
8126 traveller_ptr += sizeof(float);
8127 if (de::abs(result_value - expected_value) > epsilon)
8128 {
8129 m_testCtx.getLog() << tcu::TestLog::Message
8130 << "Invalid single-precision floating-point value obtained when doing an "
8131 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8132 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8133 << "]"
8134 ", component index: ["
8135 << n_swizzled_component << "]"
8136 ", value: ["
8137 << ref_expected_value << "]"
8138 " to GLSL type ["
8139 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8140 ", retrieved value: ["
8141 << std::setprecision(16) << result_value << "]"
8142 ", expected value: ["
8143 << std::setprecision(16) << expected_value << "]"
8144 ", shader used:\n"
8145 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8146
8147 result = false;
8148 }
8149
8150 break;
8151 } /* VARIABLE_TYPE_FLOAT case */
8152
8153 case Utils::VARIABLE_TYPE_UINT:
8154 {
8155 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8156 double expected_value = ref_expected_value;
8157 unsigned int result_value = *((unsigned int*)traveller_ptr);
8158
8159 traveller_ptr += sizeof(unsigned int);
8160 if (result_value != (unsigned int)expected_value)
8161 {
8162 if (expected_value < 0.0)
8163 {
8164 // It is undefined to convert a negative floating-point value to an uint.
8165 break;
8166 }
8167
8168 m_testCtx.getLog() << tcu::TestLog::Message
8169 << "Invalid unsigned integer value obtained when doing an "
8170 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8171 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8172 << "]"
8173 ", component index: ["
8174 << n_swizzled_component << "]"
8175 ", value: ["
8176 << ref_expected_value << "]"
8177 " to GLSL type ["
8178 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8179 ", retrieved value: ["
8180 << result_value << "]"
8181 ", expected value: ["
8182 << (unsigned int)expected_value << "]"
8183 ", shader used:\n"
8184 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8185
8186 result = false;
8187 }
8188
8189 break;
8190 } /* VARIABLE_TYPE_UINT case */
8191
8192 default:
8193 {
8194 TCU_FAIL("Unrecognized variable type");
8195 }
8196 } /* switch (test_case.dst_type) */
8197 } /* for (all result components) */
8198 } /* for (all base values) */
8199
8200 return result;
8201 }
8202
8203 /** Constructor
8204 *
8205 * @param context Rendering context.
8206 */
GPUShaderFP64Test6(deqp::Context & context)8207 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8208 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8209 "during compilation time.")
8210 , m_cs_id(0)
8211 , m_fs_id(0)
8212 , m_gs_id(0)
8213 , m_tc_id(0)
8214 , m_te_id(0)
8215 , m_vs_id(0)
8216 , m_has_test_passed(true)
8217 {
8218 }
8219
8220 /** Deinitializes all buffers and GL objects that may have been generated
8221 * during test execution.
8222 **/
deinit()8223 void GPUShaderFP64Test6::deinit()
8224 {
8225 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8226
8227 if (m_cs_id != 0)
8228 {
8229 gl.deleteShader(m_cs_id);
8230
8231 m_cs_id = 0;
8232 }
8233
8234 if (m_fs_id != 0)
8235 {
8236 gl.deleteShader(m_fs_id);
8237
8238 m_fs_id = 0;
8239 }
8240
8241 if (m_gs_id != 0)
8242 {
8243 gl.deleteShader(m_gs_id);
8244
8245 m_gs_id = 0;
8246 }
8247
8248 if (m_tc_id != 0)
8249 {
8250 gl.deleteShader(m_tc_id);
8251
8252 m_tc_id = 0;
8253 }
8254
8255 if (m_te_id != 0)
8256 {
8257 gl.deleteShader(m_te_id);
8258
8259 m_te_id = 0;
8260 }
8261
8262 if (m_vs_id != 0)
8263 {
8264 gl.deleteShader(m_vs_id);
8265
8266 m_vs_id = 0;
8267 }
8268 }
8269
8270 /** Executes a single test case.
8271 *
8272 * This function can throw TestError exceptions if GL implementation reports
8273 * an error.
8274 *
8275 * @param test_case Test case descriptor.
8276 *
8277 * @return true if test case passed, false otherwise.
8278 **/
executeIteration(const _test_case & test_case)8279 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8280 {
8281 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8282 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8283 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8284 bool result = true;
8285 const char* stage_body = NULL;
8286 const char* stage_name = NULL;
8287
8288 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8289 {
8290 const glw::GLuint so_id = so_ids[n_so_id];
8291
8292 /* Skip compute shader if it is not supported */
8293 if (0 == so_id)
8294 {
8295 continue;
8296 }
8297
8298 /* Compile the shader */
8299 gl.compileShader(so_id);
8300 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8301
8302 /* Has the compilation failed as expected? */
8303 glw::GLint compile_status = GL_TRUE;
8304
8305 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8306 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8307
8308 if (compile_status == GL_TRUE)
8309 {
8310 /* What is the current stage's name? */
8311 if (so_id == m_cs_id)
8312 {
8313 stage_body = test_case.cs_shader_body.c_str();
8314 stage_name = "Compute shader";
8315 }
8316 else if (so_id == m_fs_id)
8317 {
8318 stage_body = test_case.fs_shader_body.c_str();
8319 stage_name = "Fragment shader";
8320 }
8321 else if (so_id == m_gs_id)
8322 {
8323 stage_body = test_case.gs_shader_body.c_str();
8324 stage_name = "Geometry shader";
8325 }
8326 else if (so_id == m_tc_id)
8327 {
8328 stage_body = test_case.tc_shader_body.c_str();
8329 stage_name = "Tessellation control shader";
8330 }
8331 else if (so_id == m_te_id)
8332 {
8333 stage_body = test_case.te_shader_body.c_str();
8334 stage_name = "Tessellation evaluation shader";
8335 }
8336 else if (so_id == m_vs_id)
8337 {
8338 stage_body = test_case.vs_shader_body.c_str();
8339 stage_name = "Vertex shader";
8340 }
8341 else
8342 {
8343 /* Doesn't make much sense to throw exceptions here so.. */
8344 stage_body = "";
8345 stage_name = "[?]";
8346 }
8347
8348 /* This shader should have never compiled successfully! */
8349 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8350 << " has been compiled successfully, even though the shader was malformed."
8351 " Following is shader body:\n"
8352 << stage_body << tcu::TestLog::EndMessage;
8353
8354 result = false;
8355 }
8356 } /* for (all shader objects) */
8357
8358 return result;
8359 }
8360
8361 /** Retrieves body of a compute shader that should be used for the purpose of
8362 * user-specified test case.
8363 *
8364 * @param test_case Test case descriptor to use.
8365 *
8366 * @return Requested string.
8367 **/
getComputeShaderBody(const _test_case & test_case)8368 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8369 {
8370 std::stringstream result_sstream;
8371
8372 /* Add pre-amble */
8373 result_sstream << "#version 420\n"
8374 "#extension GL_ARB_compute_shader : require\n"
8375 "\n"
8376 "layout(local_size_x = 6) in;\n"
8377 "\n"
8378 "void main()\n"
8379 "{\n";
8380
8381 /* Add local variable declarations */
8382 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8383
8384 if (test_case.src_array_size > 1)
8385 {
8386 result_sstream << "[" << test_case.src_array_size << "]";
8387 }
8388
8389 result_sstream << ";\n";
8390
8391 if (test_case.wrap_dst_type_in_structure)
8392 {
8393 result_sstream << "struct\n"
8394 "{\n"
8395 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8396 }
8397 else
8398 {
8399 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8400 }
8401
8402 result_sstream << ";\n";
8403
8404 if (test_case.wrap_dst_type_in_structure)
8405 {
8406 result_sstream << "\n} dst;\n";
8407 }
8408
8409 /* Add actual body */
8410 result_sstream << "dst = src;\n"
8411 "}\n";
8412
8413 /* Return the body */
8414 return result_sstream.str();
8415 }
8416
8417 /** Retrieves body of a fragment shader that should be used for the purpose of
8418 * user-specified test case.
8419 *
8420 * @param test_case Test case descriptor to use.
8421 *
8422 * @return Requested string.
8423 **/
getFragmentShaderBody(const _test_case & test_case)8424 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8425 {
8426 std::stringstream result_sstream;
8427
8428 /* Add pre-amble */
8429 result_sstream << "#version 420\n"
8430 "\n"
8431 "void main()\n"
8432 "{\n";
8433
8434 /* Add local variable declarations */
8435 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8436
8437 if (test_case.src_array_size > 1)
8438 {
8439 result_sstream << "[" << test_case.src_array_size << "]";
8440 }
8441
8442 result_sstream << ";\n";
8443
8444 if (test_case.wrap_dst_type_in_structure)
8445 {
8446 result_sstream << "struct\n"
8447 "{\n"
8448 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8449 }
8450 else
8451 {
8452 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8453 }
8454
8455 result_sstream << ";\n";
8456
8457 if (test_case.wrap_dst_type_in_structure)
8458 {
8459 result_sstream << "\n} dst;\n";
8460 }
8461
8462 /* Add actual body */
8463 result_sstream << "dst = src;\n"
8464 "}\n";
8465
8466 /* Return the body */
8467 return result_sstream.str();
8468 }
8469
8470 /** Retrieves body of a geometry shader that should be used for the purpose of
8471 * user-specified test case.
8472 *
8473 * @param test_case Test case descriptor to use.
8474 *
8475 * @return Requested string.
8476 **/
getGeometryShaderBody(const _test_case & test_case)8477 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8478 {
8479 std::stringstream result_sstream;
8480
8481 /* Add preamble */
8482 result_sstream << "#version 420\n"
8483 "\n"
8484 "layout(points) in;\n"
8485 "layout(max_vertices=1, points) out;\n"
8486 "\n"
8487 "void main()\n"
8488 "{\n";
8489
8490 /* Add local variable declarations */
8491 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8492
8493 if (test_case.src_array_size > 1)
8494 {
8495 result_sstream << "[" << test_case.src_array_size << "]";
8496 }
8497
8498 result_sstream << ";\n";
8499
8500 if (test_case.wrap_dst_type_in_structure)
8501 {
8502 result_sstream << "struct\n"
8503 "{\n"
8504 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8505 }
8506 else
8507 {
8508 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8509 }
8510
8511 result_sstream << ";\n"
8512 "\n";
8513
8514 if (test_case.wrap_dst_type_in_structure)
8515 {
8516 result_sstream << "} dst;\n";
8517 }
8518
8519 /* Add actual body */
8520 result_sstream << "dst = src;\n"
8521 "}\n";
8522
8523 /* We're done! */
8524 return result_sstream.str();
8525 }
8526
8527 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8528 * user-specified test case.
8529 *
8530 * @param test_case Test case descriptor to use.
8531 *
8532 * @return Requested string.
8533 **/
getTessellationControlShaderBody(const _test_case & test_case)8534 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8535 {
8536 std::stringstream result_sstream;
8537
8538 /* Add preamble */
8539 result_sstream << "#version 420\n"
8540 "\n"
8541 "layout(vertices=4) out;\n"
8542 "\n"
8543 "void main()\n"
8544 "{\n";
8545
8546 /* Add local variable declarations. */
8547 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8548
8549 if (test_case.src_array_size > 1)
8550 {
8551 result_sstream << "[" << test_case.src_array_size << "]";
8552 }
8553
8554 result_sstream << ";\n";
8555
8556 if (test_case.wrap_dst_type_in_structure)
8557 {
8558 result_sstream << "struct\n"
8559 "{\n"
8560 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8561 }
8562 else
8563 {
8564 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8565 }
8566
8567 if (test_case.wrap_dst_type_in_structure)
8568 {
8569 result_sstream << ";\n"
8570 "} dst;\n";
8571 }
8572 else
8573 {
8574 result_sstream << ";\n";
8575 }
8576
8577 /* Continue with the actual body. */
8578 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8579 "gl_TessLevelOuter[1] = 1.0;\n"
8580 "dst = src;\n"
8581 "}\n";
8582
8583 /* Return the body */
8584 return result_sstream.str();
8585 }
8586
8587 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8588 * user-specified test case.
8589 *
8590 * @param test_case Test case descriptor to use.
8591 *
8592 * @return Requested string.
8593 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8594 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8595 {
8596 std::stringstream result_sstream;
8597
8598 /* Add preamble */
8599 result_sstream << "#version 420\n"
8600 "\n"
8601 "layout(isolines) in;\n"
8602 "\n"
8603 "void main()\n"
8604 "{\n";
8605
8606 /* Add local variable declarations */
8607 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8608
8609 if (test_case.src_array_size > 1)
8610 {
8611 result_sstream << "[" << test_case.src_array_size << "]";
8612 }
8613
8614 result_sstream << ";\n";
8615
8616 if (test_case.wrap_dst_type_in_structure)
8617 {
8618 result_sstream << "struct\n"
8619 "{\n"
8620 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8621 }
8622 else
8623 {
8624 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8625 }
8626
8627 if (test_case.wrap_dst_type_in_structure)
8628 {
8629 result_sstream << ";\n"
8630 "} dst;\n";
8631 }
8632 else
8633 {
8634 result_sstream << ";\n";
8635 }
8636
8637 /* Continue with the actual body. */
8638 result_sstream << "dst = src;\n";
8639
8640 /* Complete the body */
8641 result_sstream << "}\n";
8642
8643 /* Return the body */
8644 return result_sstream.str();
8645 }
8646
8647 /** Retrieves body of a vertex shader that should be used for the purpose of
8648 * user-specified test case.
8649 *
8650 * @param test_case Test case descriptor to use.
8651 *
8652 * @return Requested string.
8653 **/
getVertexShaderBody(const _test_case & test_case)8654 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8655 {
8656 std::stringstream result_sstream;
8657
8658 /* Add preamble */
8659 result_sstream << "#version 420\n"
8660 "\n"
8661 "void main()\n"
8662 "{\n";
8663
8664 /* Add local variables */
8665 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8666
8667 if (test_case.src_array_size > 1)
8668 {
8669 result_sstream << "[" << test_case.src_array_size << "]";
8670 }
8671
8672 result_sstream << ";\n";
8673
8674 if (test_case.wrap_dst_type_in_structure)
8675 {
8676 result_sstream << "struct\n"
8677 "{\n"
8678 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8679 }
8680 else
8681 {
8682 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8683 }
8684
8685 if (test_case.wrap_dst_type_in_structure)
8686 {
8687 result_sstream << ";\n"
8688 "} dst;\n";
8689 }
8690 else
8691 {
8692 result_sstream << ";\n";
8693 }
8694
8695 /* Start actual body */
8696 result_sstream << "dst = src;\n"
8697 "gl_Position = vec4(1.0);\n"
8698 "}";
8699
8700 return result_sstream.str();
8701 }
8702
8703 /** Initializes shader objects required to run the test. */
initTest()8704 void GPUShaderFP64Test6::initTest()
8705 {
8706 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8707
8708 /* Generate shader objects */
8709
8710 /* Compute shader support and GL 4.2 required */
8711 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8712 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8713 {
8714 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8715 }
8716
8717 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8718 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8719 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8720 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8721 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8722
8723 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8724 }
8725
8726 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8727 *
8728 * @param test_case Test case descriptor to generate the shader bodies for.
8729 **/
initIteration(_test_case & test_case)8730 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8731 {
8732 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8733
8734 test_case.cs_shader_body = getComputeShaderBody(test_case);
8735 test_case.fs_shader_body = getFragmentShaderBody(test_case);
8736 test_case.gs_shader_body = getGeometryShaderBody(test_case);
8737 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8738 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8739 test_case.vs_shader_body = getVertexShaderBody(test_case);
8740
8741 /* Assign the bodies to relevant shaders */
8742 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8743 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8744 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8745 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8746 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8747 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8748
8749 /* m_cs_id is initialized only if compute_shader is supported */
8750 if (0 != m_cs_id)
8751 {
8752 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8753 }
8754
8755 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8756 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8757 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8758 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8759 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8760 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8761 }
8762
8763 /** Executes test iteration.
8764 *
8765 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8766 */
iterate()8767 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8768 {
8769 /* Do not execute the test if GL_ARB_texture_view is not supported */
8770 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8771 {
8772 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8773 }
8774
8775 /* Initialize GL objects needed to run the tests */
8776 initTest();
8777
8778 /* Build iteration array to run the tests in an automated manner */
8779 _test_case test_cases[] = {
8780 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8781 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8782 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8783 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8784 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8785 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8786 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8787 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8788 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8789 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8790 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8791 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8792 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8793 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8794 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8795 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8796 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8797 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8798 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8799 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8800 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8801 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8802 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8803 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8804 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8805 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8806 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8807 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8808 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8809 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8810 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8811 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8812 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8813 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8814 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8815 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8816 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8817 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8818 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8819 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8820 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8821 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8822 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8823 };
8824 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8825
8826 /* Execute all iterations */
8827 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8828 {
8829 _test_case& test_case = test_cases[n_test_case];
8830
8831 /* Initialize a program object we will use to perform the casting */
8832 initIteration(test_case);
8833
8834 /* Use the program object to XFB the results */
8835 m_has_test_passed &= executeIteration(test_case);
8836
8837 } /* for (all test cases) */
8838
8839 /* We're done */
8840 if (m_has_test_passed)
8841 {
8842 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8843 }
8844 else
8845 {
8846 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8847 }
8848
8849 return STOP;
8850 }
8851
8852 /** Constructor
8853 *
8854 * @param context Rendering context.
8855 */
GPUShaderFP64Test7(deqp::Context & context)8856 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8857 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8858 "in all shader stages.")
8859 , m_are_double_inputs_supported(false)
8860 , m_fbo_id(0)
8861 , m_fs_id(0)
8862 , m_gs_id(0)
8863 , m_has_test_passed(true)
8864 , m_n_max_components_per_stage(0)
8865 , m_n_xfb_varyings(0)
8866 , m_po_id(0)
8867 , m_tc_id(0)
8868 , m_te_id(0)
8869 , m_to_id(0)
8870 , m_to_data(NULL)
8871 , m_to_height(4)
8872 , m_to_width(4)
8873 , m_xfb_bo_id(0)
8874 , m_xfb_varyings(NULL)
8875 , m_vao_id(0)
8876 , m_vs_id(0)
8877 {
8878 }
8879
8880 /** Compiles all shaders attached to test program object and links it.
8881 *
8882 * @param variables
8883 *
8884 * @return true if the process was executed successfully, false otherwise.
8885 */
buildTestProgram(_variables & variables)8886 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8887 {
8888 std::string fs_body = getFragmentShaderBody(variables);
8889 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8890 std::string gs_body = getGeometryShaderBody(variables);
8891 std::string tc_body = getTessellationControlShaderBody(variables);
8892 std::string te_body = getTessellationEvaluationShaderBody(variables);
8893 std::string vs_body = getVertexShaderBody(variables);
8894 bool result = false;
8895
8896 /* Try to link the program object */
8897 glw::GLint link_status = GL_FALSE;
8898
8899 /* Compile the shaders */
8900 if (!compileShader(m_fs_id, fs_body))
8901 {
8902 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8903
8904 goto end;
8905 }
8906
8907 if (!compileShader(m_gs_id, gs_body))
8908 {
8909 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8910
8911 goto end;
8912 }
8913
8914 if (!compileShader(m_tc_id, tc_body))
8915 {
8916 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8917 << tcu::TestLog::EndMessage;
8918
8919 goto end;
8920 }
8921
8922 if (!compileShader(m_te_id, te_body))
8923 {
8924 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8925 << tcu::TestLog::EndMessage;
8926
8927 goto end;
8928 }
8929
8930 if (!compileShader(m_vs_id, vs_body))
8931 {
8932 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8933
8934 goto end;
8935 }
8936
8937 /* Configure XFB */
8938 releaseXFBVaryingNames();
8939 generateXFBVaryingNames(variables);
8940
8941 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8942
8943 gl.linkProgram(m_po_id);
8944
8945 /* Have we succeeded? */
8946 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8947
8948 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8949 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8950
8951 if (link_status != GL_TRUE)
8952 {
8953 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8954 << tcu::TestLog::EndMessage;
8955
8956 goto end;
8957 }
8958
8959 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8960 if (m_are_double_inputs_supported)
8961 {
8962 const size_t n_variables = variables.size();
8963
8964 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8965 {
8966 _variable& current_variable = variables[n_variable];
8967 std::stringstream attribute_name_sstream;
8968
8969 attribute_name_sstream << "in_vs_variable" << n_variable;
8970
8971 if (current_variable.array_size > 1)
8972 {
8973 attribute_name_sstream << "[0]";
8974 }
8975
8976 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8977
8978 if (current_variable.attribute_location == -1)
8979 {
8980 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8981 << attribute_name_sstream.str().c_str()
8982 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8983
8984 m_has_test_passed = false;
8985 goto end;
8986 }
8987 } /* for (all test variables) */
8988 } /* if (m_are_double_inputs_supported) */
8989
8990 m_current_fs_body = fs_body;
8991 m_current_gs_body = gs_body;
8992 m_current_tc_body = tc_body;
8993 m_current_te_body = te_body;
8994 m_current_vs_body = vs_body;
8995
8996 result = true;
8997
8998 end:
8999 return result;
9000 }
9001
9002 /** Updates shader object's body and then compiles the shader.
9003 *
9004 * @param body Body to use for the shader.
9005 *
9006 * @return true if the shader compiled successfully, false otherwise.
9007 **/
compileShader(glw::GLint shader_id,const std::string & body)9008 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
9009 {
9010 const char* body_raw_ptr = body.c_str();
9011 glw::GLint compile_status = GL_FALSE;
9012 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9013
9014 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
9015 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
9016
9017 gl.compileShader(shader_id);
9018 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
9019
9020 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
9021 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
9022
9023 return (compile_status == GL_TRUE);
9024 }
9025
9026 /** Configure storage of a buffer object used for capturing XFB data.
9027 *
9028 * @param variables Holds descriptor for all variables used for the iteration the
9029 * BO is being configured for. Storage size will be directly related
9030 * to the number of the variables and their type.
9031 */
configureXFBBuffer(const _variables & variables)9032 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9033 {
9034 DE_ASSERT(m_n_xfb_varyings != 0);
9035
9036 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9037 * The test only draws a single patch, and triangles are caught by transform feed-back.
9038 * Let's initialize the storage, according to the list of variables that will be used
9039 * for the test run.
9040 */
9041 unsigned int bo_size = 0;
9042
9043 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9044 variables_iterator++)
9045 {
9046 const _variable& variable = *variables_iterator;
9047 unsigned int n_bytes_needed = static_cast<unsigned int>(
9048 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9049
9050 bo_size += n_bytes_needed;
9051 } /* for (all variables) */
9052
9053 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9054
9055 /* Set up the BO storage */
9056 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9057
9058 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9059 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9060 }
9061
9062 /** Deinitializes all buffers and GL objects that may have been generated
9063 * during test execution.
9064 **/
deinit()9065 void GPUShaderFP64Test7::deinit()
9066 {
9067 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9068
9069 if (m_fbo_id != 0)
9070 {
9071 gl.deleteFramebuffers(1, &m_fbo_id);
9072
9073 m_fbo_id = 0;
9074 }
9075
9076 if (m_fs_id != 0)
9077 {
9078 gl.deleteShader(m_fs_id);
9079
9080 m_fs_id = 0;
9081 }
9082
9083 if (m_gs_id != 0)
9084 {
9085 gl.deleteShader(m_gs_id);
9086
9087 m_gs_id = 0;
9088 }
9089
9090 if (m_po_id != 0)
9091 {
9092 gl.deleteProgram(m_po_id);
9093
9094 m_po_id = 0;
9095 }
9096
9097 if (m_tc_id != 0)
9098 {
9099 gl.deleteShader(m_tc_id);
9100
9101 m_tc_id = 0;
9102 }
9103
9104 if (m_te_id != 0)
9105 {
9106 gl.deleteShader(m_te_id);
9107
9108 m_te_id = 0;
9109 }
9110
9111 if (m_to_data != NULL)
9112 {
9113 delete[] m_to_data;
9114
9115 m_to_data = NULL;
9116 }
9117
9118 if (m_to_id != 0)
9119 {
9120 gl.deleteTextures(1, &m_to_id);
9121
9122 m_to_id = 0;
9123 }
9124
9125 if (m_xfb_bo_id != 0)
9126 {
9127 gl.deleteBuffers(1, &m_xfb_bo_id);
9128
9129 m_xfb_bo_id = 0;
9130 }
9131
9132 if (m_xfb_varyings != DE_NULL)
9133 {
9134 releaseXFBVaryingNames();
9135 }
9136
9137 if (m_vao_id != 0)
9138 {
9139 gl.deleteVertexArrays(1, &m_vao_id);
9140
9141 m_vao_id = 0;
9142 }
9143
9144 if (m_vs_id != 0)
9145 {
9146 gl.deleteShader(m_vs_id);
9147
9148 m_vs_id = 0;
9149 }
9150 }
9151
9152 /** Executes the functional part of the test (case a) from the test spec)
9153 *
9154 * @param variables Vector of variable descriptors defining properties of
9155 * variables that should be used for the iteration.
9156 *
9157 * @return true if the test passed, false otherwise.
9158 **/
executeFunctionalTest(_variables & variables)9159 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9160 {
9161 bool result = true;
9162
9163 /* Build the test program */
9164 if (!buildTestProgram(variables))
9165 {
9166 return false;
9167 }
9168
9169 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9170 if (m_are_double_inputs_supported)
9171 {
9172 setInputAttributeValues(variables);
9173 }
9174
9175 /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9176 * only, if a data mismatch is detected.
9177 */
9178 configureXFBBuffer(variables);
9179
9180 /* Issue a draw call using the test program */
9181 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9182
9183 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9184 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9185
9186 gl.clear(GL_COLOR_BUFFER_BIT);
9187 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9188
9189 gl.useProgram(m_po_id);
9190 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9191
9192 gl.viewport(0, /* x */
9193 0, /* y */
9194 m_to_width, m_to_height);
9195 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9196
9197 gl.beginTransformFeedback(GL_TRIANGLES);
9198 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9199 {
9200 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9201 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9202 }
9203 gl.endTransformFeedback();
9204 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9205
9206 /* Verify color attachment contents */
9207 const float epsilon = 1.0f / 255.0f;
9208
9209 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9210 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9211
9212 for (unsigned int y = 0; y < m_to_height; ++y)
9213 {
9214 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9215
9216 for (unsigned int x = 0; x < m_to_width; ++x)
9217 {
9218 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9219
9220 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9221 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9222 {
9223 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9224 << ")"
9225 "; expected:(0, 255, 0, 0), found: ("
9226 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9227 << ", " << (int)pixel_ptr[3]
9228 << "), with the following variable types used as varyings:"
9229 << tcu::TestLog::EndMessage;
9230
9231 /* List the variable types that failed the test */
9232 const size_t n_variables = variables.size();
9233
9234 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9235 {
9236 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9237 << Utils::getVariableTypeString(variables[n_variable].type)
9238 << " (array size:" << variables[n_variable].array_size << ")"
9239 << tcu::TestLog::EndMessage;
9240 } /* for (all variable types) */
9241
9242 /* Log the variable contents */
9243 logVariableContents(variables);
9244
9245 /* Log shaders used for the iteration */
9246 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9247 "\n"
9248 "(VS):\n"
9249 << m_current_vs_body.c_str() << "\n"
9250 << "(TC):\n"
9251 "\n"
9252 << m_current_tc_body.c_str() << "\n"
9253 "(TE):\n"
9254 "\n"
9255 << m_current_te_body.c_str() << "\n"
9256 "(GS):\n"
9257 << m_current_gs_body.c_str() << "\n"
9258 "(FS):\n"
9259 "\n"
9260 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9261
9262 result = false;
9263
9264 goto end;
9265 }
9266 } /* for (all columns) */
9267 } /* for (all rows) */
9268
9269 /* All done! */
9270 end:
9271 return result;
9272 }
9273
9274 /** Takes user-input vector of test variables and allocates & fills an array of strings
9275 * holding names of geometry shader stage varyings that should be captured during
9276 * transform feedback operation. The array will be stored in m_xfb_varyings.
9277 *
9278 * @param variables Holds all test variable descriptors to be used for the iteration.
9279 */
generateXFBVaryingNames(const _variables & variables)9280 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9281 {
9282 unsigned int n_variable = 0;
9283 unsigned int n_varying = 0;
9284 unsigned int n_varyings = 0;
9285
9286 if (m_xfb_varyings != NULL)
9287 {
9288 releaseXFBVaryingNames();
9289 }
9290
9291 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9292 ++variables_iterator)
9293 {
9294 const _variable& variable = *variables_iterator;
9295
9296 n_varyings += variable.array_size;
9297 }
9298
9299 m_xfb_varyings = new glw::GLchar*[n_varyings];
9300
9301 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9302 ++variables_iterator, ++n_variable)
9303 {
9304 const _variable& variable = *variables_iterator;
9305
9306 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9307 {
9308 std::stringstream varying_sstream;
9309 size_t varying_length;
9310
9311 varying_sstream << "gs_variable" << n_variable;
9312
9313 if (variable.array_size > 1)
9314 {
9315 varying_sstream << "[" << array_index << "]";
9316 }
9317
9318 /* Store the varying name */
9319 varying_length = varying_sstream.str().length();
9320 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9321
9322 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9323 m_xfb_varyings[n_varying][varying_length] = 0;
9324 } /* for (all array indices) */
9325 } /* for (all varyings) */
9326
9327 m_n_xfb_varyings = n_varyings;
9328 }
9329
9330 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9331 * without using the "flat" keyword. (case c) )
9332 *
9333 * @param input_variable_type Variable type to use for input variable declaration.
9334 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9335 * of the arrayed variable.
9336 *
9337 * @return Requested string.
9338 **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9339 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9340 Utils::_variable_type input_variable_type, unsigned int array_size)
9341 {
9342 std::stringstream result_sstream;
9343 std::stringstream array_index_stringstream;
9344 std::stringstream array_size_stringstream;
9345
9346 if (array_size > 1)
9347 {
9348 array_index_stringstream << "[0]";
9349 array_size_stringstream << "[" << array_size << "]";
9350 }
9351
9352 if (Utils::isMatrixVariableType(input_variable_type))
9353 {
9354 array_index_stringstream << "[0].x";
9355 }
9356 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9357 {
9358 array_index_stringstream << "[0]";
9359 }
9360
9361 result_sstream << "#version 400\n"
9362 "\n"
9363 "in "
9364 << Utils::getVariableTypeString(input_variable_type) << " test_input"
9365 << array_size_stringstream.str() << ";\n"
9366 "\n"
9367 "out float test_output;\n"
9368 "\n"
9369 "void main()\n"
9370 "{\n"
9371 " if (test_input"
9372 << array_index_stringstream.str() << " > 2.0)\n"
9373 " {\n"
9374 " test_output = 1.0;\n"
9375 " }\n"
9376 " else\n"
9377 " {\n"
9378 " test_output = 3.0;\n"
9379 " }\n"
9380 "}\n";
9381
9382 return result_sstream.str();
9383 }
9384
9385 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9386 *
9387 * @param input_variable_type Variable type to use for input variable declaration.
9388 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9389 * of the arrayed variable.
9390 *
9391 * @return Requested string.
9392 **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9393 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9394 Utils::_variable_type output_variable_type, unsigned int array_size)
9395 {
9396 std::stringstream array_index_sstream;
9397 std::stringstream array_size_sstream;
9398 std::stringstream result_sstream;
9399 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9400
9401 if (array_size > 1)
9402 {
9403 array_index_sstream << "[0]";
9404 array_size_sstream << "[" << array_size << "]";
9405 }
9406
9407 result_sstream << "#version 400\n"
9408 "\n"
9409 "out "
9410 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9411 "\n"
9412 "void main()\n"
9413 "{\n"
9414 " test_output"
9415 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9416 "}\n";
9417
9418 return result_sstream.str();
9419 }
9420
9421 /** Retrieves body of a fragment shader that uses user-specified set of variables
9422 * to declare contents of input & output block.
9423 *
9424 * @param variables As per description.
9425 *
9426 * @return Requested string.
9427 **/
getFragmentShaderBody(const _variables & variables)9428 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9429 {
9430 std::stringstream result_sstream;
9431
9432 /* Form the pre-amble */
9433 result_sstream << "#version 400\n"
9434 "\n"
9435
9436 /* Add input block */
9437 << "in GS_DATA\n"
9438 "{\n"
9439 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9440 "\n"
9441
9442 /* Add output variable */
9443 << "out vec4 result;\n"
9444 "\n"
9445
9446 /* Add main() definition */
9447 "void main()\n"
9448 "{\n"
9449 "const double epsilon = 1e-5;\n"
9450 "\n"
9451 "result = vec4(1, 0, 0, 0);\n"
9452 "\n";
9453
9454 /* Determine expected values first */
9455 unsigned int base_counter = 1;
9456 const size_t n_variables = variables.size();
9457
9458 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9459 {
9460 unsigned int variable_array_size = variables[n_variable].array_size;
9461 Utils::_variable_type variable_type = variables[n_variable].type;
9462 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9463 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9464
9465 std::stringstream array_size_sstream;
9466
9467 if (variable_array_size > 1)
9468 {
9469 array_size_sstream << "[" << variable_array_size << "]";
9470 }
9471
9472 /* Local variable declaration */
9473 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9474 << ";\n"
9475 "\n";
9476
9477 /* Set expected values */
9478 for (unsigned int index = 0; index < variable_array_size; ++index)
9479 {
9480 std::stringstream array_index_sstream;
9481
9482 if (variable_array_size > 1)
9483 {
9484 array_index_sstream << "[" << index << "]";
9485 }
9486
9487 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9488 << variable_type_string << "(";
9489
9490 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9491 {
9492 unsigned int expected_value =
9493 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9494
9495 if (m_are_double_inputs_supported)
9496 {
9497 /* VS input attributes */
9498 //expected_value += (base_counter + 6);
9499 expected_value -= 1;
9500 }
9501
9502 result_sstream << expected_value;
9503
9504 if (n_component != (n_variable_type_components - 1))
9505 {
9506 result_sstream << ", ";
9507 }
9508
9509 ++base_counter;
9510 } /* for (all components) */
9511
9512 result_sstream << ");\n";
9513 } /* for (all array indices) */
9514
9515 result_sstream << "\n";
9516 } /* for (all variable types) */
9517
9518 /* Now that we know the expected values, do a huge conditional check to verify if all
9519 * input variables carry correct information.
9520 */
9521 result_sstream << "if (";
9522
9523 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9524 {
9525 unsigned int variable_array_size = variables[n_variable].array_size;
9526 Utils::_variable_type variable_type = variables[n_variable].type;
9527 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type);
9528 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9529 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9530
9531 for (unsigned int index = 0; index < variable_array_size; ++index)
9532 {
9533 std::stringstream array_index_sstream;
9534
9535 if (variable_array_size > 1)
9536 {
9537 array_index_sstream << "[" << index << "]";
9538 }
9539
9540 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9541 {
9542 std::stringstream component_index_sstream;
9543
9544 if (n_variable_type_components > 1)
9545 {
9546 component_index_sstream << "[" << n_component << "]";
9547 }
9548
9549 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9550
9551 if (is_variable_type_matrix)
9552 {
9553 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9554 const unsigned int column = n_component % n_columns;
9555 const unsigned int row = n_component / n_columns;
9556
9557 result_sstream << "[" << column << "]"
9558 "."
9559 << Utils::getComponentAtIndex(row);
9560 }
9561 else
9562 {
9563 result_sstream << component_index_sstream.str();
9564 }
9565
9566 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9567
9568 if (is_variable_type_matrix)
9569 {
9570 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9571 const unsigned int column = n_component % n_columns;
9572 const unsigned int row = n_component / n_columns;
9573
9574 result_sstream << "[" << column << "]"
9575 "."
9576 << Utils::getComponentAtIndex(row);
9577 }
9578 else
9579 {
9580 result_sstream << component_index_sstream.str();
9581 }
9582
9583 result_sstream << ") <= epsilon &&";
9584 } /* for (all components) */
9585 } /* for (all array indices) */
9586 } /* for (all variable types) */
9587
9588 result_sstream << "true)\n"
9589 "{\n"
9590 " result = vec4(0, 1, 0, 0);\n"
9591 "}\n"
9592 "}\n";
9593
9594 /* All done */
9595 return result_sstream.str();
9596 }
9597
9598 /** Retrieves body of a geometry shader that uses user-specified set of variables
9599 * to declare contents of input & output block.
9600 *
9601 * @param variables As per description.
9602 *
9603 * @return Requested string.
9604 **/
getGeometryShaderBody(const _variables & variables)9605 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9606 {
9607 std::stringstream result_sstream;
9608
9609 /* Form the pre-amble */
9610 result_sstream << "#version 400\n"
9611 "\n"
9612 "layout(triangles) in;\n"
9613 "layout(triangle_strip, max_vertices=4) out;\n"
9614 "\n"
9615
9616 /* Add the input block */
9617 "in TE_DATA\n"
9618 "{\n"
9619 << getVariableDeclarations("te", variables) << "} in_data[];\n"
9620 "\n"
9621
9622 /* Add the output block */
9623 "out GS_DATA\n"
9624 "{\n"
9625 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9626 "\n"
9627
9628 /* Declare main() function */
9629 "void main()\n"
9630 "{\n";
9631
9632 /* Take input variables, add a predefined value and forward them to output variables */
9633 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9634 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
9635 const unsigned int n_quad_vertices =
9636 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9637 const size_t n_variables = variables.size();
9638
9639 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9640 {
9641 unsigned int counter = 4;
9642 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9643
9644 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9645 {
9646 unsigned int variable_array_size = variables[n_variable].array_size;
9647 Utils::_variable_type variable_type = variables[n_variable].type;
9648 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9649 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9650
9651 for (unsigned int index = 0; index < variable_array_size; ++index)
9652 {
9653 std::stringstream array_index_sstream;
9654
9655 if (variable_array_size > 1)
9656 {
9657 array_index_sstream << "[" << index << "]";
9658 }
9659
9660 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9661 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9662 << variable_type_string << "(";
9663
9664 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9665 {
9666 result_sstream << (counter++);
9667
9668 if (n_component != (n_variable_type_components - 1))
9669 {
9670 result_sstream << ", ";
9671 }
9672 } /* for (all components) */
9673
9674 result_sstream << ");\n";
9675 } /* for (all array indices) */
9676 } /* for (all variable types) */
9677
9678 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9679 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9680 "EmitVertex();\n";
9681 } /* for (all emitted quad vertices) */
9682
9683 result_sstream << "EndPrimitive();\n"
9684 "}\n";
9685
9686 /* All done */
9687 return result_sstream.str();
9688 }
9689
9690 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9691 * to declare contents of input & output block.
9692 *
9693 * @param variables As per description.
9694 *
9695 * @return Requested string.
9696 **/
getTessellationControlShaderBody(const _variables & variables)9697 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9698 {
9699 std::stringstream result_sstream;
9700
9701 /* Form the pre-amble */
9702 result_sstream << "#version 400\n"
9703 "\n"
9704 "layout (vertices=4) out;\n"
9705
9706 /* Declare input block */
9707 "in VS_DATA\n"
9708 "{\n"
9709 << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9710
9711 /* Declare output block */
9712 "out TC_DATA\n"
9713 "{\n"
9714 << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9715 "\n"
9716
9717 /* Define main() */
9718 "void main()\n"
9719 "{\n"
9720 " gl_TessLevelInner[0] = 1;\n"
9721 " gl_TessLevelInner[1] = 1;\n"
9722 " gl_TessLevelOuter[0] = 1;\n"
9723 " gl_TessLevelOuter[1] = 1;\n"
9724 " gl_TessLevelOuter[2] = 1;\n"
9725 " gl_TessLevelOuter[3] = 1;\n"
9726 "\n";
9727
9728 /* Take input variables, add a predefined value and forward them to output variables */
9729 const size_t n_variables = variables.size();
9730 unsigned int counter = 2;
9731
9732 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9733 {
9734 unsigned int variable_array_size = variables[n_variable].array_size;
9735 Utils::_variable_type variable_type = variables[n_variable].type;
9736 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9737 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9738
9739 for (unsigned int index = 0; index < variable_array_size; ++index)
9740 {
9741 std::stringstream array_index_sstream;
9742
9743 if (variable_array_size > 1)
9744 {
9745 array_index_sstream << "[" << index << "]";
9746 }
9747
9748 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9749 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9750 << variable_type_string << "(";
9751
9752 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9753 {
9754 result_sstream << (counter++);
9755
9756 if (n_component != (n_variable_type_components - 1))
9757 {
9758 result_sstream << ", ";
9759 }
9760 }
9761
9762 result_sstream << ");\n";
9763 } /* for (all array indices) */
9764 } /* for (all variable types) */
9765
9766 result_sstream << "}\n";
9767
9768 /* We're done */
9769 return result_sstream.str();
9770 }
9771
9772 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9773 * to declare contents of input & output block.
9774 *
9775 * @param variables As per description.
9776 *
9777 * @return Requested string.
9778 **/
getTessellationEvaluationShaderBody(const _variables & variables)9779 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9780 {
9781 std::stringstream result_sstream;
9782
9783 /* Form the pre-amble */
9784 result_sstream << "#version 400\n"
9785 "\n"
9786 "layout(quads) in;\n"
9787 "\n"
9788
9789 /* Define input block */
9790 "in TC_DATA\n"
9791 "{\n"
9792 << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9793 "\n"
9794
9795 /* Define output block */
9796 "out TE_DATA\n"
9797 "{\n"
9798 << getVariableDeclarations("te", variables) << "};\n"
9799 "\n"
9800
9801 /* Define main() */
9802 "void main()\n"
9803 "{\n";
9804
9805 /* Take input variables, add a predefined value and forward them to output variables */
9806 const size_t n_variables = variables.size();
9807 unsigned int counter = 3;
9808
9809 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9810 {
9811 unsigned int variable_array_size = variables[n_variable].array_size;
9812 Utils::_variable_type variable_type = variables[n_variable].type;
9813 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9814 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9815
9816 for (unsigned int index = 0; index < variable_array_size; ++index)
9817 {
9818 std::stringstream array_index_sstream;
9819
9820 if (variable_array_size > 1)
9821 {
9822 array_index_sstream << "[" << index << "]";
9823 }
9824
9825 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9826 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9827
9828 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9829 {
9830 result_sstream << (counter++);
9831
9832 if (n_component != (n_variable_type_components - 1))
9833 {
9834 result_sstream << ", ";
9835 }
9836 } /* for (all components) */
9837
9838 result_sstream << ");\n";
9839 } /* for (all array indices) */
9840 } /* for (all variable types) */
9841
9842 result_sstream << "}\n";
9843
9844 /* All done */
9845 return result_sstream.str();
9846 }
9847
9848 /** Returns a string containing declarations of user-specified set of variables.
9849 * Each declaration can optionally use a layot qualifier requested by the caller.
9850 *
9851 * @param prefix Prefix to use for variable names.
9852 * @param variables List of variables to declare in the result string.
9853 * @param explicit_locations true if each declaration should explicitly define location
9854 * of the variable ( eg. (layout location=X) )
9855 * @param layout_qualifier Optional qualifier to use for the declaration. Must not
9856 * be NULL.
9857 *
9858 * @return Requested string.
9859 **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9860 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9861 const char* layout_qualifier)
9862 {
9863 std::stringstream result_sstream;
9864
9865 /* Define output variables */
9866 const size_t n_variables = variables.size();
9867
9868 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9869 {
9870 unsigned int variable_array_size = variables[n_variable].array_size;
9871 Utils::_variable_type variable_type = variables[n_variable].type;
9872 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9873
9874 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9875
9876 if (variable_array_size > 1)
9877 {
9878 result_sstream << "[" << variable_array_size << "]";
9879 }
9880
9881 result_sstream << ";\n";
9882 } /* for (all user-specified variable types) */
9883
9884 return result_sstream.str();
9885 }
9886
9887 /** Retrieves body of a vertex shader that uses user-specified set of variables
9888 * to declare contents of input & output block.
9889 *
9890 * @param variables As per description.
9891 *
9892 * @return Requested string.
9893 **/
getVertexShaderBody(const _variables & variables)9894 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9895 {
9896 std::stringstream result_sstream;
9897
9898 /* Form pre-amble */
9899 result_sstream << "#version 400\n"
9900 "\n";
9901
9902 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9903 if (m_are_double_inputs_supported)
9904 {
9905 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9906 << getVariableDeclarations("in_vs", variables, "in");
9907 }
9908
9909 /* Define output variables */
9910 result_sstream << "out VS_DATA\n"
9911 "{\n"
9912 << getVariableDeclarations("vs", variables);
9913
9914 /* Define main() */
9915 result_sstream << "};\n"
9916 "\n"
9917 "void main()\n"
9918 "{\n";
9919
9920 /* Set output variable values */
9921 unsigned int counter = 1;
9922 const size_t n_variables = variables.size();
9923
9924 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9925 {
9926 unsigned int variable_array_size = variables[n_variable].array_size;
9927 Utils::_variable_type variable_type = variables[n_variable].type;
9928 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9929 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9930
9931 for (unsigned int index = 0; index < variable_array_size; ++index)
9932 {
9933 if (variable_array_size == 1)
9934 {
9935 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9936 }
9937 else
9938 {
9939 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9940 << " = " << variable_type_string << "(";
9941 }
9942
9943 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9944 {
9945 result_sstream << (double)(counter++);
9946
9947 /* Use input attributes, if available */
9948 if (m_are_double_inputs_supported)
9949 {
9950 result_sstream << " + in_vs_variable" << n_variable;
9951
9952 if (variable_array_size > 1)
9953 {
9954 result_sstream << "[" << index << "]";
9955 }
9956
9957 if (Utils::isMatrixVariableType(variables[n_variable].type))
9958 {
9959 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9960 const unsigned int column = n_component % n_columns;
9961 const unsigned int row = n_component / n_columns;
9962
9963 result_sstream << "[" << (column) << "]"
9964 "."
9965 << Utils::getComponentAtIndex(row);
9966 }
9967 else if (n_variable_type_components > 1)
9968 {
9969 result_sstream << "[" << n_component << "]";
9970 }
9971 }
9972
9973 if (n_component != (n_variable_type_components - 1))
9974 {
9975 result_sstream << ", ";
9976 }
9977 } /* for (all components) */
9978
9979 result_sstream << ");\n";
9980 }
9981 } /* for (all variable types) */
9982
9983 /* We will be using geometry shader to lay out the actual vertices so
9984 * the only thing we need to make sure is that the vertex never gets
9985 * culled.
9986 */
9987 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9988 "}\n";
9989
9990 /* That's it */
9991 return result_sstream.str();
9992 }
9993
9994 /** Initializes shader objects required to run the test. */
initTest()9995 void GPUShaderFP64Test7::initTest()
9996 {
9997 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9998
9999 /* Are double-precision input variables supported? */
10000 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
10001
10002 /* Create a vertex array object */
10003 gl.genVertexArrays(1, &m_vao_id);
10004 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
10005
10006 gl.bindVertexArray(m_vao_id);
10007 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
10008
10009 /* Create a texture object we will use as FBO's color attachment */
10010 gl.genTextures(1, &m_to_id);
10011 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
10012
10013 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
10014 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
10015
10016 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
10017 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
10018
10019 /* Allocate temporary buffer to hold the texture data we will be reading
10020 * from color attachment. */
10021 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
10022
10023 /* Create and set up a framebuffer object */
10024 gl.genFramebuffers(1, &m_fbo_id);
10025 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
10026
10027 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
10028 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
10029
10030 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10031 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10032
10033 /* Create all shader objects */
10034 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10035 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10036 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10037 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10038 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10039 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10040
10041 /* Create test program object */
10042 m_po_id = gl.createProgram();
10043 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10044
10045 /* Attach the shaders to the program object */
10046 gl.attachShader(m_po_id, m_fs_id);
10047 gl.attachShader(m_po_id, m_gs_id);
10048 gl.attachShader(m_po_id, m_tc_id);
10049 gl.attachShader(m_po_id, m_te_id);
10050 gl.attachShader(m_po_id, m_vs_id);
10051 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10052
10053 /* The test passes double-precision values through the whole rendering pipeline.
10054 * This translates to a notable amount of components that we would need to transfer
10055 * all values in one fell swoop. The number is large enough to exceed minimum
10056 * capabilities as described for OpenGL 4.0 implementations.
10057 * For that reason, the test executes in turns. Each turn is allocated as many
10058 * double-precision scalar/matrix values as supported by the tested GL implementation.
10059 */
10060 glw::GLint gl_max_fragment_input_components_value = 0;
10061 glw::GLint gl_max_geometry_input_components_value = 0;
10062 glw::GLint gl_max_geometry_output_components_value = 0;
10063 glw::GLint gl_max_tess_control_input_components_value = 0;
10064 glw::GLint gl_max_tess_control_output_components_value = 0;
10065 glw::GLint gl_max_tess_evaluation_input_components_value = 0;
10066 glw::GLint gl_max_tess_evaluation_output_components_value = 0;
10067 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10068 glw::GLint gl_max_vertex_output_components_value = 0;
10069
10070 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10071 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10072 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10073 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10074 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10075 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10076 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10077 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10078 &gl_max_transform_feedback_interleaved_components_value);
10079 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10080 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10081
10082 m_n_max_components_per_stage =
10083 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10084 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10085 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10086 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10087 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10088 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10089 m_n_max_components_per_stage =
10090 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10091 m_n_max_components_per_stage =
10092 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10093
10094 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10095 * the input patch */
10096 gl.patchParameteri(GL_PATCH_VERTICES, 1);
10097
10098 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10099
10100 /* Initialize a BO we will use to hold XFB data */
10101 gl.genBuffers(1, &m_xfb_bo_id);
10102 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10103
10104 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10105 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10106
10107 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10108 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10109 }
10110
10111 /** Executes test iteration.
10112 *
10113 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10114 */
iterate()10115 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10116 {
10117 /* Do not execute the test if GL_ARB_texture_view is not supported */
10118 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10119 {
10120 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10121 }
10122
10123 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10124 {
10125 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10126 }
10127
10128 /* Initialize GL objects required to run the test */
10129 initTest();
10130
10131 /* Check the negative cases first */
10132 const Utils::_variable_type double_variable_types[] = {
10133 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10134 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10135 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10136 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10137 Utils::VARIABLE_TYPE_DMAT4X3,
10138 };
10139 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10140
10141 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10142 ++n_double_variable_type)
10143 {
10144 for (unsigned int array_size = 1; array_size < 3; ++array_size)
10145 {
10146 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10147
10148 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10149 {
10150 m_testCtx.getLog() << tcu::TestLog::Message
10151 << "A fragment shader with double-precision output variable compiled successfully."
10152 << tcu::TestLog::EndMessage;
10153
10154 m_has_test_passed = false;
10155 }
10156
10157 if (compileShader(m_fs_id,
10158 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10159 {
10160 m_testCtx.getLog()
10161 << tcu::TestLog::Message
10162 << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10163 " compiled successfully."
10164 << tcu::TestLog::EndMessage;
10165
10166 m_has_test_passed = false;
10167 }
10168 }
10169 } /* for (all variable types) */
10170
10171 /* Execute functional test. Split the run into as many iterations as necessary
10172 * so that we do not exceed GL implementation's capabilities. */
10173 unsigned int n_tested_variables = 0;
10174 _variables variables_to_test;
10175
10176 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10177 {
10178 glw::GLint total_n_used_components = 0;
10179
10180 /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10181 * of varying components that can be used for all shadr stages.
10182 */
10183 while (total_n_used_components < m_n_max_components_per_stage &&
10184 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10185 {
10186 _variable new_variable;
10187 unsigned int n_type_components = 0;
10188 glw::GLint n_used_components = 0;
10189
10190 new_variable.array_size =
10191 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10192 new_variable.type = double_variable_types[n_tested_variables / 2];
10193
10194 /* Double-precision varyings can use twice as many components as single-precision FPs */
10195 n_type_components = 4 /* components per location */ *
10196 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10197 n_used_components = n_type_components * new_variable.array_size * 2;
10198
10199 /* Do we have enough space? */
10200 if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10201 {
10202 if (n_used_components > m_n_max_components_per_stage)
10203 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10204 n_tested_variables++;
10205 }
10206 break;
10207 }
10208
10209 /* We can safely test the type in current iteration */
10210 total_n_used_components += n_used_components;
10211 n_tested_variables++;
10212
10213 variables_to_test.push_back(new_variable);
10214 }
10215
10216 if (variables_to_test.size() > 0)
10217 {
10218 m_has_test_passed &= executeFunctionalTest(variables_to_test);
10219
10220 variables_to_test.clear();
10221 }
10222 }
10223
10224 /* We're done */
10225 if (m_has_test_passed)
10226 {
10227 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10228 }
10229 else
10230 {
10231 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10232 }
10233
10234 return STOP;
10235 }
10236
10237 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10238 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10239 {
10240 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10241 std::stringstream log_sstream;
10242
10243 log_sstream << "Test variable values as retrieved from geometry shader:\n";
10244
10245 /* Map the XFB BO contents into process space */
10246 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10247
10248 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10249
10250 /* Read the variable contents. We only care about the set of varyings emitted
10251 * for first vertex in the geometry shader */
10252 unsigned int n_varying = 0;
10253 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10254
10255 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10256 ++variables_iterator, ++n_varying)
10257 {
10258 const _variable& variable = *variables_iterator;
10259 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10260 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10261
10262 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10263 {
10264 log_sstream << "gs_variable" << n_varying;
10265
10266 if (variable.array_size > 1)
10267 {
10268 log_sstream << "[" << array_index << "]";
10269 }
10270
10271 log_sstream << ": (";
10272
10273 for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10274 {
10275 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10276
10277 if (n_component != (n_components - 1))
10278 {
10279 log_sstream << ", ";
10280 }
10281
10282 traveller_ptr += sizeof(double);
10283 }
10284
10285 log_sstream << ")\n";
10286 } /* for (all array indices) */
10287 } /* for (all variables) */
10288
10289 /* Unmap the BO */
10290 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10291 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10292
10293 /* Pass the logged stream into the framework */
10294 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10295 }
10296
10297 /** De-allocates an arary holding strings representing names of varyings that
10298 * should be used for transform feed-back.
10299 **/
releaseXFBVaryingNames()10300 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10301 {
10302 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10303 {
10304 delete[] m_xfb_varyings[n_varying];
10305 }
10306
10307 delete m_xfb_varyings;
10308 m_xfb_varyings = DE_NULL;
10309
10310 m_n_xfb_varyings = 0;
10311 }
10312
10313 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10314 * Takes a list of test variables used for current iteration and assigns increasing values
10315 * to subsequent input attributes of the test program.
10316 *
10317 * @param variables Test variables of the current iteration.
10318 */
setInputAttributeValues(const _variables & variables)10319 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10320 {
10321 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10322 unsigned int counter = 6;
10323
10324 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10325 variable_iterator++)
10326 {
10327 const _variable& variable = *variable_iterator;
10328 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type);
10329 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10330 unsigned int n_components = 0;
10331 unsigned int n_columns = 1;
10332
10333 if (is_matrix_type)
10334 {
10335 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type);
10336 n_components = n_total_components / n_columns;
10337
10338 DE_ASSERT(n_total_components % n_columns == 0);
10339 }
10340 else
10341 {
10342 n_components = n_total_components;
10343 }
10344
10345 DE_ASSERT(n_components >= 1 && n_components <= 4);
10346
10347 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10348 {
10349 const double data[] = { -1, -1, -1, -1 };
10350
10351 switch (n_components)
10352 {
10353 case 1:
10354 {
10355 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10356 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10357
10358 break;
10359 }
10360
10361 case 2:
10362 {
10363 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10364 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10365
10366 break;
10367 }
10368
10369 case 3:
10370 {
10371 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10372 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10373
10374 break;
10375 }
10376
10377 case 4:
10378 {
10379 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10380 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10381
10382 break;
10383 }
10384
10385 default:
10386 {
10387 TCU_FAIL("Unrecognized number of components");
10388 }
10389 } /* switch (n_components) */
10390
10391 /* Make sure VAAs are disabled */
10392 gl.disableVertexAttribArray(variable.attribute_location + index);
10393 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10394
10395 counter += n_components;
10396 } /* for (all array indices) */
10397 } /* for (all variables) */
10398 }
10399
10400 /** Constructor
10401 *
10402 * @param context Rendering context.
10403 */
GPUShaderFP64Test8(deqp::Context & context)10404 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10405 : TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10406 "are accepted during compilation stage")
10407 , m_cs_id(0)
10408 , m_fs_id(0)
10409 , m_gs_id(0)
10410 , m_tc_id(0)
10411 , m_te_id(0)
10412 , m_vs_id(0)
10413 , m_has_test_passed(true)
10414 {
10415 }
10416
10417 /** Deinitializes all buffers and GL objects that may have been generated
10418 * during test execution.
10419 **/
deinit()10420 void GPUShaderFP64Test8::deinit()
10421 {
10422 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10423
10424 if (m_cs_id != 0)
10425 {
10426 gl.deleteShader(m_cs_id);
10427
10428 m_cs_id = 0;
10429 }
10430
10431 if (m_fs_id != 0)
10432 {
10433 gl.deleteShader(m_fs_id);
10434
10435 m_fs_id = 0;
10436 }
10437
10438 if (m_gs_id != 0)
10439 {
10440 gl.deleteShader(m_gs_id);
10441
10442 m_gs_id = 0;
10443 }
10444
10445 if (m_tc_id != 0)
10446 {
10447 gl.deleteShader(m_tc_id);
10448
10449 m_tc_id = 0;
10450 }
10451
10452 if (m_te_id != 0)
10453 {
10454 gl.deleteShader(m_te_id);
10455
10456 m_te_id = 0;
10457 }
10458
10459 if (m_vs_id != 0)
10460 {
10461 gl.deleteShader(m_vs_id);
10462
10463 m_vs_id = 0;
10464 }
10465 }
10466
10467 /** Executes a single test case.
10468 *
10469 * This function can throw TestError exceptions if GL implementation reports
10470 * an error.
10471 *
10472 * @param test_case Test case descriptor.
10473 *
10474 * @return true if test case passed, false otherwise.
10475 **/
executeIteration(const _test_case & test_case)10476 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10477 {
10478 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10479 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10480 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
10481 bool result = true;
10482 const char* stage_body = NULL;
10483 const char* stage_name = NULL;
10484
10485 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10486 {
10487 const glw::GLuint so_id = so_ids[n_so_id];
10488
10489 /* Skip compute shader if it is not supported */
10490 if (0 == so_id)
10491 {
10492 continue;
10493 }
10494
10495 /* Compile the shader */
10496 gl.compileShader(so_id);
10497 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10498
10499 /* Has the compilation succeeded as expected? */
10500 glw::GLint compile_status = GL_FALSE;
10501
10502 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10503 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10504
10505 if (compile_status == GL_FALSE)
10506 {
10507 /* What is the current stage's name? */
10508 if (so_id == m_cs_id)
10509 {
10510 stage_body = test_case.cs_shader_body.c_str();
10511 stage_name = "Compute shader";
10512 }
10513 else if (so_id == m_fs_id)
10514 {
10515 stage_body = test_case.fs_shader_body.c_str();
10516 stage_name = "Fragment shader";
10517 }
10518 else if (so_id == m_gs_id)
10519 {
10520 stage_body = test_case.gs_shader_body.c_str();
10521 stage_name = "Geometry shader";
10522 }
10523 else if (so_id == m_tc_id)
10524 {
10525 stage_body = test_case.tc_shader_body.c_str();
10526 stage_name = "Tessellation control shader";
10527 }
10528 else if (so_id == m_te_id)
10529 {
10530 stage_body = test_case.te_shader_body.c_str();
10531 stage_name = "Tessellation evaluation shader";
10532 }
10533 else if (so_id == m_vs_id)
10534 {
10535 stage_body = test_case.vs_shader_body.c_str();
10536 stage_name = "Vertex shader";
10537 }
10538 else
10539 {
10540 /* Doesn't make much sense to throw exceptions here so.. */
10541 stage_body = "";
10542 stage_name = "[?]";
10543 }
10544
10545 /* This shader should have never failed to compile! */
10546 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10547 << " has not compiled successfully, even though the shader is valid."
10548 " Following is shader's body:\n"
10549 << stage_body << tcu::TestLog::EndMessage;
10550
10551 result = false;
10552 }
10553 } /* for (all shader objects) */
10554
10555 return result;
10556 }
10557
10558 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10559 * type.
10560 *
10561 * @param variable_type Variable type to return valid argument lists for.
10562 **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10563 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10564 const Utils::_variable_type& variable_type)
10565 {
10566 const Utils::_variable_type matrix_types[] = {
10567 Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10568 Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10569 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10570 };
10571 const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10572 Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10573 const unsigned int n_matrix_types = sizeof(matrix_types) / sizeof(matrix_types[0]);
10574 const unsigned int n_scalar_types = sizeof(scalar_types) / sizeof(scalar_types[0]);
10575 const int n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10576
10577 /* Construct the argument list tree root. Each node carries a counter that tells how many components
10578 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10579 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10580 * used to define a subsequent argument, and its counter is increased by the amount of components
10581 * described by the type.
10582 */
10583 _argument_list_tree_node root;
10584
10585 root.n_components_used = 0;
10586 root.parent = NULL;
10587 root.type = variable_type;
10588
10589 /* Fill till all leaves use up all available components */
10590 _argument_list_tree_node_queue nodes_queue;
10591
10592 nodes_queue.push(&root);
10593
10594 do
10595 {
10596 /* Pop the first item in the queue */
10597 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10598 nodes_queue.pop();
10599
10600 /* Matrix variable types can be defined by a combination of non-matrix variable types OR
10601 * a single matrix variable type.
10602 *
10603 * Let's handle the latter case first.
10604 */
10605 const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10606
10607 if (Utils::isMatrixVariableType(current_node_ptr->type))
10608 {
10609 /* Iterate through all known matrix types. All the types can be used
10610 * as a constructor, assuming only one value is used to define new matrix's
10611 * contents. */
10612 for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10613 {
10614 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10615
10616 /* Construct a new child node. Since GLSL spec clearly states we must not use more
10617 * than one constructor argument if the only argument is a matrix type, mark the node
10618 * as if it defined all available components.
10619 */
10620 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10621
10622 new_subnode->n_components_used = n_total_components;
10623 new_subnode->parent = current_node_ptr;
10624 new_subnode->type = new_argument_type;
10625
10626 /* Add the descriptor to node list but do not add it to the queue. This would be
10627 * a redundant operation, since no new children nodes would have been assigned to
10628 * this node anyway.
10629 */
10630 current_node_ptr->children.push_back(new_subnode);
10631 } /* for (all matrix types) */
10632 } /* if (current node's type is a matrix) */
10633
10634 /* Now for a combination of non-matrix variable types.. */
10635 if (!Utils::isMatrixVariableType(current_node_ptr->type))
10636 {
10637 /* Iterate through all known scalar types */
10638 for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10639 {
10640 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10641 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10642
10643 /* Only use the scalar type if we don't exceed the amount of components we can define
10644 * for requested type.
10645 */
10646 if (n_new_argument_components <= n_components_remaining)
10647 {
10648 /* Form new node descriptor */
10649 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10650
10651 new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10652 new_subnode->parent = current_node_ptr;
10653 new_subnode->type = new_argument_type;
10654
10655 current_node_ptr->children.push_back(new_subnode);
10656 nodes_queue.push(new_subnode);
10657 }
10658 } /* for (all scalar types) */
10659 } /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10660 } while (nodes_queue.size() > 0);
10661
10662 /* To construct the argument lists, traverse the tree. Each path from root to child
10663 * gives us a single argument list.
10664 *
10665 * First, identify leaf nodes.
10666 */
10667 _argument_list_tree_nodes leaf_nodes;
10668
10669 nodes_queue.push(&root);
10670
10671 do
10672 {
10673 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10674 nodes_queue.pop();
10675
10676 if (current_node_ptr->children.size() == 0)
10677 {
10678 /* This is a leaf node !*/
10679 leaf_nodes.push_back(current_node_ptr);
10680 }
10681 else
10682 {
10683 /* Throw all children nodes to the queue */
10684 const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10685
10686 for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10687 {
10688 nodes_queue.push(current_node_ptr->children[n_children_node]);
10689 } /* for (all children nodes) */
10690 }
10691 } while (nodes_queue.size() > 0);
10692
10693 /* For all leaf nodes, move up the tree and construct the argument lists. */
10694 const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10695 _argument_lists result;
10696
10697 for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10698 {
10699 _argument_list argument_list;
10700 _argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10701
10702 do
10703 {
10704 if (current_node_ptr != &root)
10705 {
10706 if (argument_list.size() == 0)
10707 {
10708 argument_list.push_back(current_node_ptr->type);
10709 }
10710 else
10711 {
10712 argument_list.insert(argument_list.begin(), current_node_ptr->type);
10713 }
10714 }
10715
10716 current_node_ptr = current_node_ptr->parent;
10717 } while (current_node_ptr != NULL);
10718
10719 result.push_back(argument_list);
10720 } /* for (all leaf nodes) */
10721
10722 return result;
10723 }
10724
10725 /** Retrieves body of a compute shader that should be used for the purpose of
10726 * user-specified test case.
10727 *
10728 * @param test_case Test case descriptor to use.
10729 *
10730 * @return Requested string.
10731 **/
getComputeShaderBody(const _test_case & test_case)10732 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10733 {
10734 std::stringstream result_sstream;
10735
10736 /* Form the body */
10737 result_sstream << "#version 420\n"
10738 "#extension GL_ARB_compute_shader : require\n"
10739 "\n"
10740 "layout(local_size_x = 1) in;\n"
10741 "\n"
10742 "void main()\n"
10743 "{\n"
10744 << getGeneralBody(test_case) << "}\n";
10745
10746 /* Return the body */
10747 return result_sstream.str();
10748 }
10749
10750 /** Retrieves body of a fragment shader that should be used for the purpose of
10751 * user-specified test case.
10752 *
10753 * @param test_case Test case descriptor to use.
10754 *
10755 * @return Requested string.
10756 **/
getFragmentShaderBody(const _test_case & test_case)10757 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10758 {
10759 std::stringstream result_sstream;
10760
10761 /* Form the body */
10762 result_sstream << "#version 420\n"
10763 "\n"
10764 "void main()\n"
10765 "{\n"
10766 << getGeneralBody(test_case) << "}\n"
10767 "\n";
10768
10769 /* Return the body */
10770 return result_sstream.str();
10771 }
10772
10773 /** Returns a GLSL line that defines and initializes a variable as described by
10774 * user-specified test case descriptor.
10775 *
10776 * @param test_case Test case descriptor to use for the query.
10777 *
10778 * @return As per description
10779 **/
getGeneralBody(const _test_case & test_case)10780 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10781 {
10782 std::stringstream result_sstream;
10783
10784 /* Form the body */
10785 std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10786
10787 result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10788
10789 for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10790 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10791 {
10792 const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10793 std::string argument_variable_type_string = Utils::getVariableTypeString(argument_variable_type);
10794 const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10795
10796 if (argument_list_iterator != test_case.argument_list.begin())
10797 {
10798 result_sstream << ", ";
10799 }
10800
10801 result_sstream << argument_variable_type_string << "(";
10802
10803 for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10804 {
10805 result_sstream << (double)(n_component + 1);
10806
10807 if (n_component != (argument_n_components - 1))
10808 {
10809 result_sstream << ", ";
10810 }
10811 } /* for (all argument components) */
10812
10813 result_sstream << ")";
10814 } /* for (all arguments) */
10815
10816 result_sstream << ");\n";
10817
10818 return result_sstream.str();
10819 }
10820
10821 /** Retrieves body of a geometry shader that should be used for the purpose of
10822 * user-specified test case.
10823 *
10824 * @param test_case Test case descriptor to use.
10825 *
10826 * @return Requested string.
10827 **/
getGeometryShaderBody(const _test_case & test_case)10828 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10829 {
10830 std::stringstream result_sstream;
10831
10832 /* Form the body */
10833 result_sstream << "#version 420\n"
10834 "\n"
10835 "layout(points) in;\n"
10836 "layout(max_vertices=1, points) out;\n"
10837 "\n"
10838 "void main()\n"
10839 "{\n"
10840 << getGeneralBody(test_case) << "}\n"
10841 "\n";
10842
10843 /* We're done! */
10844 return result_sstream.str();
10845 }
10846
10847 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10848 * user-specified test case.
10849 *
10850 * @param test_case Test case descriptor to use.
10851 *
10852 * @return Requested string.
10853 **/
getTessellationControlShaderBody(const _test_case & test_case)10854 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10855 {
10856 std::stringstream result_sstream;
10857
10858 /* Form the body */
10859 result_sstream << "#version 420\n"
10860 "\n"
10861 "layout(vertices=4) out;\n"
10862 "\n"
10863 "void main()\n"
10864 "{\n"
10865 << getGeneralBody(test_case) << "}\n"
10866 "\n";
10867
10868 /* Return the body */
10869 return result_sstream.str();
10870 }
10871
10872 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10873 * user-specified test case.
10874 *
10875 * @param test_case Test case descriptor to use.
10876 *
10877 * @return Requested string.
10878 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10879 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10880 {
10881 std::stringstream result_sstream;
10882
10883 /* Form the body */
10884 result_sstream << "#version 420\n"
10885 "\n"
10886 "layout(isolines) in;\n"
10887 "\n"
10888 "void main()\n"
10889 "{\n"
10890 << getGeneralBody(test_case) << "}\n"
10891 "\n";
10892
10893 /* Return the body */
10894 return result_sstream.str();
10895 }
10896
10897 /** Retrieves body of a vertex shader that should be used for the purpose of
10898 * user-specified test case.
10899 *
10900 * @param test_case Test case descriptor to use.
10901 *
10902 * @return Requested string.
10903 **/
getVertexShaderBody(const _test_case & test_case)10904 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10905 {
10906 std::stringstream result_sstream;
10907
10908 /* Form the body */
10909 result_sstream << "#version 420\n"
10910 "\n"
10911 "void main()\n"
10912 "{\n"
10913 << getGeneralBody(test_case) << "}\n"
10914 "\n";
10915
10916 return result_sstream.str();
10917 }
10918
10919 /** Initializes shader objects required to run the test. */
initTest()10920 void GPUShaderFP64Test8::initTest()
10921 {
10922 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10923
10924 /* Generate shader objects */
10925
10926 /* Compute shader support and GL 4.2 required */
10927 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10928 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10929 {
10930 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10931 }
10932
10933 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10934 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10935 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10936 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10937 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10938
10939 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10940 }
10941
10942 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10943 *
10944 * @param test_case Test case descriptor to generate the shader bodies for.
10945 **/
initIteration(_test_case & test_case)10946 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10947 {
10948 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10949
10950 test_case.cs_shader_body = getComputeShaderBody(test_case);
10951 test_case.fs_shader_body = getFragmentShaderBody(test_case);
10952 test_case.gs_shader_body = getGeometryShaderBody(test_case);
10953 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10954 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10955 test_case.vs_shader_body = getVertexShaderBody(test_case);
10956
10957 /* Assign the bodies to relevant shaders */
10958 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10959 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10960 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10961 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10962 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10963 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10964
10965 /* m_cs_id is initialized only if compute_shader is supported */
10966 if (0 != m_cs_id)
10967 {
10968 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10969 }
10970
10971 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10972 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10973 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10974 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10975 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10976 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10977 }
10978
10979 /** Executes test iteration.
10980 *
10981 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10982 */
iterate()10983 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10984 {
10985 /* Do not execute the test if GL_ARB_texture_view is not supported */
10986 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10987 {
10988 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10989 }
10990
10991 /* Initialize GL objects needed to run the tests */
10992 initTest();
10993
10994 /* Build iteration array to run the tests in an automated manner */
10995 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10996 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10997 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10998 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10999 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11000 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
11001 Utils::VARIABLE_TYPE_DVEC4 };
11002 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11003
11004 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11005 {
11006 const Utils::_variable_type variable_type = variable_types[n_variable_type];
11007
11008 /* Construct a set of argument lists valid for the variable type considered */
11009 _argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
11010
11011 for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
11012 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
11013 {
11014 /* Constructor thwe test case descriptor */
11015 _test_case test_case;
11016
11017 test_case.argument_list = *argument_list_iterator;
11018 test_case.type = variable_type;
11019
11020 /* Initialize a program object we will use to perform the casting */
11021 initIteration(test_case);
11022
11023 /* See if the shader compiles. */
11024 m_has_test_passed &= executeIteration(test_case);
11025 } /* for (all argument lists) */
11026 } /* for (all variable types) */
11027
11028 /* We're done */
11029 if (m_has_test_passed)
11030 {
11031 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11032 }
11033 else
11034 {
11035 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11036 }
11037
11038 return STOP;
11039 }
11040
11041 /** Constructor.
11042 *
11043 * @param context Rendering context.
11044 *
11045 **/
GPUShaderFP64Test9(deqp::Context & context)11046 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11047 : TestCase(context, "operators", "Verifies that general and relational operators work "
11048 "correctly when used against double-precision floating-"
11049 "point types.")
11050 , m_has_test_passed(true)
11051 , m_po_id(0)
11052 , m_xfb_bo_id(0)
11053 , m_vao_id(0)
11054 , m_vs_id(0)
11055 {
11056 /* Left blank intentionally */
11057 }
11058
11059 /** Deinitializes all ES objects that may have been created during
11060 * test execution.
11061 **/
deinit()11062 void GPUShaderFP64Test9::deinit()
11063 {
11064 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11065
11066 if (m_po_id != 0)
11067 {
11068 gl.deleteProgram(m_po_id);
11069
11070 m_po_id = 0;
11071 }
11072
11073 if (m_xfb_bo_id != 0)
11074 {
11075 gl.deleteBuffers(1, &m_xfb_bo_id);
11076
11077 m_xfb_bo_id = 0;
11078 }
11079
11080 if (m_vao_id != 0)
11081 {
11082 gl.deleteVertexArrays(1, &m_vao_id);
11083
11084 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11085 }
11086
11087 if (m_vs_id != 0)
11088 {
11089 gl.deleteShader(m_vs_id);
11090
11091 m_vs_id = 0;
11092 }
11093 }
11094
11095 /** Executes a single test iteration using user-specified test case properties.
11096 *
11097 * @param test_case Test case descriptor.
11098 *
11099 * @return true if the pass was successful, false if the test should fail.
11100 **/
executeTestIteration(const _test_case & test_case)11101 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11102 {
11103 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11104 bool result = true;
11105
11106 /* Activate the test program object */
11107 gl.useProgram(m_po_id);
11108 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11109
11110 /* Draw a single point with XFB enabled */
11111 gl.beginTransformFeedback(GL_POINTS);
11112 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11113 {
11114 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11115 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11116 }
11117 gl.endTransformFeedback();
11118 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11119
11120 /* Map the XFB BO into process space */
11121 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11122
11123 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11124
11125 result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11126
11127 /* Unmap the BO */
11128 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11129 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11130
11131 return result;
11132 }
11133
11134 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11135 * under user-specified location.
11136 *
11137 * @param matrix_a_type Type of the l-side matrix.
11138 * @param matrix_a_data Row-ordered data of l-side matrix.
11139 * @param matrix_b_type Type of the r-side matrix.
11140 * @param matrix_b_data Row-ordered data of r-side matrix.
11141 * @param out_result_ptr Deref to be used to store the multiplication result.
11142 **/
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)11143 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11144 const std::vector<double>& matrix_a_data,
11145 const Utils::_variable_type& matrix_b_type,
11146 const std::vector<double>& matrix_b_data, double* out_result_ptr)
11147 {
11148 (void)matrix_b_type;
11149 using namespace tcu;
11150 /* To keep the code maintainable, we only consider cases relevant for this test */
11151 switch (matrix_a_type)
11152 {
11153 case Utils::VARIABLE_TYPE_DMAT2:
11154 {
11155 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11156
11157 tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11158 tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11159 tcu::Matrix2d result;
11160
11161 matrix_a = transpose(matrix_a);
11162 matrix_b = transpose(matrix_b);
11163 result = matrix_a * matrix_b;
11164
11165 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11166 break;
11167 }
11168
11169 case Utils::VARIABLE_TYPE_DMAT2X3:
11170 {
11171 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11172
11173 tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11174 tcu::Matrix<double, 3, 2> matrix_a_transposed;
11175 tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11176 tcu::Matrix<double, 2, 3> matrix_b_transposed;
11177 tcu::Matrix<double, 3, 3> result;
11178
11179 matrix_a_transposed = transpose(matrix_a);
11180 matrix_b_transposed = transpose(matrix_b);
11181 result = matrix_a_transposed * matrix_b_transposed;
11182
11183 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11184 break;
11185 }
11186
11187 case Utils::VARIABLE_TYPE_DMAT2X4:
11188 {
11189 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11190
11191 tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11192 tcu::Matrix<double, 4, 2> matrix_a_transposed;
11193 tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11194 tcu::Matrix<double, 2, 4> matrix_b_transposed;
11195 tcu::Matrix<double, 4, 4> result;
11196
11197 matrix_a_transposed = transpose(matrix_a);
11198 matrix_b_transposed = transpose(matrix_b);
11199 result = matrix_a_transposed * matrix_b_transposed;
11200
11201 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11202 break;
11203 }
11204
11205 case Utils::VARIABLE_TYPE_DMAT3:
11206 {
11207 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11208
11209 tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11210 tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11211 tcu::Matrix<double, 3, 3> result;
11212
11213 matrix_a = transpose(matrix_a);
11214 matrix_b = transpose(matrix_b);
11215 result = matrix_a * matrix_b;
11216
11217 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11218 break;
11219 }
11220
11221 case Utils::VARIABLE_TYPE_DMAT3X2:
11222 {
11223 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11224
11225 tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11226 tcu::Matrix<double, 2, 3> matrix_a_transposed;
11227 tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11228 tcu::Matrix<double, 3, 2> matrix_b_transposed;
11229 tcu::Matrix<double, 2, 2> result;
11230
11231 matrix_a_transposed = transpose(matrix_a);
11232 matrix_b_transposed = transpose(matrix_b);
11233 result = matrix_a_transposed * matrix_b_transposed;
11234
11235 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11236 break;
11237 }
11238
11239 case Utils::VARIABLE_TYPE_DMAT3X4:
11240 {
11241 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11242
11243 tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11244 tcu::Matrix<double, 4, 3> matrix_a_transposed;
11245 tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11246 tcu::Matrix<double, 3, 4> matrix_b_transposed;
11247 tcu::Matrix<double, 4, 4> result;
11248
11249 matrix_a_transposed = transpose(matrix_a);
11250 matrix_b_transposed = transpose(matrix_b);
11251 result = matrix_a_transposed * matrix_b_transposed;
11252
11253 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11254 break;
11255 }
11256
11257 case Utils::VARIABLE_TYPE_DMAT4:
11258 {
11259 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11260
11261 tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11262 tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11263 tcu::Matrix<double, 4, 4> result;
11264
11265 matrix_a = transpose(matrix_a);
11266 matrix_b = transpose(matrix_b);
11267 result = matrix_a * matrix_b;
11268
11269 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11270 break;
11271 }
11272
11273 case Utils::VARIABLE_TYPE_DMAT4X2:
11274 {
11275 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11276
11277 tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11278 tcu::Matrix<double, 2, 4> matrix_a_transposed;
11279 tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11280 tcu::Matrix<double, 4, 2> matrix_b_transposed;
11281 tcu::Matrix<double, 2, 2> result;
11282
11283 matrix_a_transposed = transpose(matrix_a);
11284 matrix_b_transposed = transpose(matrix_b);
11285 result = matrix_a_transposed * matrix_b_transposed;
11286
11287 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11288 break;
11289 }
11290
11291 case Utils::VARIABLE_TYPE_DMAT4X3:
11292 {
11293 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11294
11295 tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11296 tcu::Matrix<double, 3, 4> matrix_a_transposed;
11297 tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11298 tcu::Matrix<double, 4, 3> matrix_b_transposed;
11299 tcu::Matrix<double, 3, 3> result;
11300
11301 matrix_a_transposed = transpose(matrix_a);
11302 matrix_b_transposed = transpose(matrix_b);
11303 result = matrix_a_transposed * matrix_b_transposed;
11304
11305 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11306 break;
11307 }
11308
11309 default:
11310 {
11311 TCU_FAIL("Unrecognized matrix A type");
11312 }
11313 } /* switch (matrix_a_type) */
11314 }
11315
11316 /** Returns GLSL operator representation of the user-specified operation.
11317 *
11318 * @param operation_type Internal operation type to retrieve the operator for.
11319 *
11320 * @return As per description.
11321 **/
getOperatorForOperationType(const _operation_type & operation_type)11322 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11323 {
11324 const char* result = NULL;
11325
11326 switch (operation_type)
11327 {
11328 case OPERATION_TYPE_ADDITION:
11329 result = "+";
11330 break;
11331 case OPERATION_TYPE_DIVISION:
11332 result = "/";
11333 break;
11334 case OPERATION_TYPE_MULTIPLICATION:
11335 result = "*";
11336 break;
11337 case OPERATION_TYPE_SUBTRACTION:
11338 result = "-";
11339 break;
11340
11341 case OPERATION_TYPE_PRE_DECREMENTATION:
11342 case OPERATION_TYPE_POST_DECREMENTATION:
11343 {
11344 result = "--";
11345
11346 break;
11347 }
11348
11349 case OPERATION_TYPE_PRE_INCREMENTATION:
11350 case OPERATION_TYPE_POST_INCREMENTATION:
11351 {
11352 result = "++";
11353
11354 break;
11355 }
11356
11357 default:
11358 {
11359 TCU_FAIL("Unrecognized operation type");
11360 }
11361 } /* switch(operation_type) */
11362
11363 return result;
11364 }
11365
11366 /** Returns a string representing user-specified operation type.
11367 *
11368 * @param operation_type Operation type to return the literal for.
11369 *
11370 * @return Requested string.
11371 **/
getOperationTypeString(const _operation_type & operation_type)11372 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11373 {
11374 std::string result = "[?]";
11375
11376 switch (operation_type)
11377 {
11378 case OPERATION_TYPE_ADDITION:
11379 result = "addition";
11380 break;
11381 case OPERATION_TYPE_DIVISION:
11382 result = "division";
11383 break;
11384 case OPERATION_TYPE_MULTIPLICATION:
11385 result = "multiplication";
11386 break;
11387 case OPERATION_TYPE_SUBTRACTION:
11388 result = "subtraction";
11389 break;
11390 case OPERATION_TYPE_PRE_DECREMENTATION:
11391 result = "pre-decrementation";
11392 break;
11393 case OPERATION_TYPE_PRE_INCREMENTATION:
11394 result = "pre-incrementation";
11395 break;
11396 case OPERATION_TYPE_POST_DECREMENTATION:
11397 result = "post-decrementation";
11398 break;
11399 case OPERATION_TYPE_POST_INCREMENTATION:
11400 result = "post-incrementation";
11401 break;
11402
11403 default:
11404 {
11405 TCU_FAIL("Unrecognized operation type");
11406 }
11407 }
11408
11409 return result;
11410 }
11411
11412 /** Returns body of a vertex shader that should be used for user-specified test case
11413 * descriptor.
11414 *
11415 * @param test_case Test case descriptor.
11416 *
11417 * @return Requested GLSL shader body.
11418 **/
getVertexShaderBody(_test_case & test_case)11419 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11420 {
11421 std::stringstream result_sstream;
11422 std::string result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11423 std::string variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11424 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11425 const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11426
11427 /* If we are to multiply matrices, we will need to use a different type
11428 * for the result variable if either of the matrices is not square.
11429 */
11430 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11431 Utils::isMatrixVariableType(test_case.variable_type))
11432 {
11433 Utils::_variable_type result_variable_type;
11434 Utils::_variable_type transposed_matrix_variable_type =
11435 Utils::getTransposedMatrixVariableType(test_case.variable_type);
11436
11437 result_variable_type =
11438 Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11439 result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11440
11441 test_case.result_variable_type = result_variable_type;
11442 }
11443
11444 /* Form the pre-amble */
11445 result_sstream << "#version 400\n"
11446 "\n"
11447
11448 /* Add output variables */
11449 "out "
11450 << result_variable_type_string << " result;\n"
11451 "out ivec2 result_lt;\n"
11452 "out ivec2 result_lte;\n"
11453 "out ivec2 result_gt;\n"
11454 "out ivec2 result_gte;\n"
11455 "void main()\n"
11456 "{\n";
11457
11458 /* Form reference values */
11459 result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11460
11461 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11462 {
11463 result_sstream << (n_variable_component + 1);
11464
11465 if (n_variable_component != (n_variable_components - 1))
11466 {
11467 result_sstream << ", ";
11468 }
11469 } /* for (all variable components) */
11470
11471 result_sstream << ");\n";
11472
11473 for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11474 ++n_ref2_case)
11475 {
11476 Utils::_variable_type compatible_variable_type = test_case.variable_type;
11477
11478 if (Utils::isMatrixVariableType(compatible_variable_type) &&
11479 test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11480 {
11481 compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11482 }
11483
11484 std::string ref2_variable_type_fp_string =
11485 Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11486 std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11487 std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11488 std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11489
11490 result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11491
11492 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11493 ++n_variable_component)
11494 {
11495 result_sstream << (n_variable_components - (n_variable_component + 1));
11496
11497 if (n_variable_component != (n_variable_components - 1))
11498 {
11499 result_sstream << ", ";
11500 }
11501 } /* for (all variable components) */
11502
11503 result_sstream << ");\n";
11504 } /* for (both reference2 declarations) */
11505
11506 /* Add actual body */
11507 result_sstream << "\n"
11508 "result = ";
11509
11510 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11511 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11512 {
11513 result_sstream << getOperatorForOperationType(test_case.operation_type);
11514 }
11515
11516 result_sstream << "reference1 ";
11517
11518 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11519 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11520 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11521 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11522 {
11523 if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11524 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11525 {
11526 result_sstream << getOperatorForOperationType(test_case.operation_type);
11527 }
11528 }
11529 else
11530 {
11531 result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11532 }
11533
11534 result_sstream << ";\n";
11535
11536 if (Utils::isScalarVariableType(test_case.variable_type))
11537 {
11538 result_sstream << "result_lt [0] = (reference1 < reference2) ? 1 : 0;\n"
11539 "result_lt [1] = (reference1 < reference2f) ? 1 : 0;\n"
11540 "result_lte[0] = (reference1 <= reference2) ? 1 : 0;\n"
11541 "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11542 "result_gt [0] = (reference1 > reference2) ? 1 : 0;\n"
11543 "result_gt [1] = (reference1 > reference2f) ? 1 : 0;\n"
11544 "result_gte[0] = (reference1 >= reference2) ? 1 : 0;\n"
11545 "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11546 }
11547 else
11548 {
11549 result_sstream << "result_lt [0] = 1;\n"
11550 "result_lt [1] = 1;\n"
11551 "result_lte[0] = 1;\n"
11552 "result_lte[1] = 1;\n"
11553 "result_gt [0] = 1;\n"
11554 "result_gt [1] = 1;\n"
11555 "result_gte[0] = 1;\n"
11556 "result_gte[1] = 1;\n";
11557 }
11558
11559 result_sstream << "}\n";
11560
11561 /* All done */
11562 return result_sstream.str();
11563 }
11564
11565 /** Initializes all GL objects required to run the test.
11566 *
11567 * This function can throw a TestError exception if the implementation misbehaves.
11568 */
initTest()11569 void GPUShaderFP64Test9::initTest()
11570 {
11571 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11572
11573 /* Create program & vertex shader objects */
11574 m_po_id = gl.createProgram();
11575 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11576
11577 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11578
11579 /* Attach the shader to the program */
11580 gl.attachShader(m_po_id, m_vs_id);
11581 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11582
11583 /* Set up a buffer object */
11584 gl.genBuffers(1, &m_xfb_bo_id);
11585 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11586
11587 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11588 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11589
11590 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11591 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11592
11593 /* Set up a vertex array object */
11594 gl.genVertexArrays(1, &m_vao_id);
11595 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11596
11597 gl.bindVertexArray(m_vao_id);
11598 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11599 }
11600
11601 /** Initializes all GL objects required to run an iteration described by
11602 * user-specified test case descriptor.
11603 *
11604 * @param test_case Test case descriptor to use for the initialization.
11605 **/
initTestIteration(_test_case & test_case)11606 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11607 {
11608 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11609 std::string vs_body = getVertexShaderBody(test_case);
11610 const char* vs_body_raw_ptr = vs_body.c_str();
11611
11612 /* Store the shader's body */
11613 test_case.vs_body = vs_body;
11614
11615 /* Try to compile the shader */
11616 glw::GLint compile_status = GL_FALSE;
11617
11618 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11619 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11620
11621 gl.compileShader(m_vs_id);
11622 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11623
11624 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11625 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11626
11627 if (compile_status != GL_TRUE)
11628 {
11629 TCU_FAIL("Test shader compilation failed.");
11630 }
11631
11632 /* Configure XFB */
11633 const char* xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11634 const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11635
11636 gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11637 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11638
11639 /* Try to link the program */
11640 glw::GLint link_status = GL_FALSE;
11641
11642 gl.linkProgram(m_po_id);
11643 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11644
11645 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11646 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11647
11648 if (link_status != GL_TRUE)
11649 {
11650 TCU_FAIL("Test program linking failure");
11651 }
11652
11653 /* Set up XFB BO data storage */
11654 const unsigned int result_variable_size = static_cast<unsigned int>(
11655 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11656 const unsigned int xfb_bo_size = static_cast<unsigned int>(
11657 result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11658
11659 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11660 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11661 }
11662
11663 /** Executes test iteration.
11664 *
11665 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11666 */
iterate()11667 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11668 {
11669 /* Do not execute the test if GL_ARB_texture_view is not supported */
11670 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11671 {
11672 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11673 }
11674
11675 /* Initialize all ES objects required to run all the checks */
11676 initTest();
11677
11678 /* Iterate through all variable types we want to test */
11679 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
11680 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11681 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11682 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
11683 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11684 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
11685 Utils::VARIABLE_TYPE_DVEC4 };
11686 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11687
11688 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11689 {
11690 /* Iterate through all operation types we want to check */
11691 for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11692 {
11693 _operation_type operation_type = (_operation_type)n_operation_type;
11694 const Utils::_variable_type& variable_type = variable_types[n_variable_type];
11695
11696 /* Construct test case descriptor */
11697 _test_case test_case;
11698
11699 test_case.operation_type = operation_type;
11700 test_case.result_variable_type = variable_type;
11701 test_case.variable_type = variable_type;
11702
11703 /* Run the iteration */
11704 initTestIteration(test_case);
11705
11706 m_has_test_passed &= executeTestIteration(test_case);
11707 } /* for (all operation types) */
11708 } /* for (all variable types) */
11709
11710 /* All done. */
11711 if (m_has_test_passed)
11712 {
11713 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11714 }
11715 else
11716 {
11717 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11718 }
11719
11720 return STOP;
11721 }
11722
11723 /** Verifies data XFBed out by the draw call for user-specified test case
11724 * descriptor.
11725 *
11726 * @param test_case Test case descriptor
11727 * @param xfb_data Buffer holding the data XFBed out during the draw call.
11728 * Must not be NULL.
11729 *
11730 * @return true if the data was found to be correct, false otherwise.
11731 **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11732 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11733 {
11734 const double epsilon = 1e-5;
11735 const unsigned int n_result_components =
11736 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11737 bool result = true;
11738 const double* xfb_data_result = (const double*)xfb_data;
11739 const int* xfb_data_result_lt = (const int*)(xfb_data_result + n_result_components);
11740 const int* xfb_data_result_lte = (const int*)xfb_data_result_lt + 2; /* cast/non-cast cases */
11741 const int* xfb_data_result_gt = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11742 const int* xfb_data_result_gte = (const int*)xfb_data_result_gt + 2; /* cast/non-cast cases */
11743
11744 /* Prepare reference values */
11745 int modifier;
11746 std::vector<double> reference1;
11747 std::vector<double> reference2;
11748
11749 if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11750 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11751 {
11752 modifier = 1;
11753 }
11754 else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11755 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11756 {
11757 modifier = -1;
11758 }
11759 else
11760 {
11761 modifier = 0;
11762 }
11763
11764 if (Utils::isMatrixVariableType(test_case.variable_type))
11765 {
11766 /* Matrices may be of different sizes so we need to compute the
11767 * reference values separately for each matrix
11768 */
11769 const Utils::_variable_type matrix_a_type = test_case.variable_type;
11770 const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11771 const unsigned int n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11772 const unsigned int n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11773
11774 for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11775 {
11776 reference1.push_back(modifier + n_component + 1);
11777 }
11778
11779 for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11780 {
11781 reference2.push_back(n_matrix_b_components - (n_component + 1));
11782 }
11783 } /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11784 else
11785 {
11786 /* Generate as many components as will be expected for the result variable */
11787 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11788 {
11789 reference1.push_back(modifier + n_result_component + 1);
11790 reference2.push_back(n_result_components - (n_result_component + 1));
11791 }
11792 }
11793
11794 /* Verify the result value(s) */
11795 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11796 Utils::isMatrixVariableType(test_case.variable_type))
11797 {
11798 /* Matrix multiplication */
11799 double expected_result_data[4 * 4];
11800 Utils::_variable_type matrix_a_type = test_case.variable_type;
11801 Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11802
11803 getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11804
11805 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11806 {
11807 if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11808 {
11809 std::stringstream log_sstream;
11810
11811 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11812 << Utils::getVariableTypeString(matrix_b_type)
11813 << " matrix multiplication was incorrect; expected:(";
11814
11815 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11816 ++n_logged_component)
11817 {
11818 log_sstream << expected_result_data[n_logged_component];
11819
11820 if (n_logged_component != (n_result_components - 1))
11821 {
11822 log_sstream << ", ";
11823 }
11824 } /* for (all components to be logged) */
11825
11826 log_sstream << "), retrieved:(";
11827
11828 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11829 ++n_logged_component)
11830 {
11831 log_sstream << xfb_data_result[n_logged_component];
11832
11833 if (n_logged_component != (n_result_components - 1))
11834 {
11835 log_sstream << ", ";
11836 }
11837 } /* for (all components to be logged) */
11838
11839 log_sstream << ")";
11840
11841 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11842
11843 result = false;
11844 break;
11845 }
11846 } /* for (all result components) */
11847 } /* if (dealing with matrix multiplication) */
11848 else
11849 {
11850 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11851 {
11852 double expected_value = reference1[n_component];
11853
11854 switch (test_case.operation_type)
11855 {
11856 case OPERATION_TYPE_ADDITION:
11857 expected_value += reference2[n_component];
11858 break;
11859 case OPERATION_TYPE_DIVISION:
11860 expected_value /= reference2[n_component];
11861 break;
11862 case OPERATION_TYPE_MULTIPLICATION:
11863 expected_value *= reference2[n_component];
11864 break;
11865 case OPERATION_TYPE_SUBTRACTION:
11866 expected_value -= reference2[n_component];
11867 break;
11868
11869 case OPERATION_TYPE_PRE_DECREMENTATION:
11870 case OPERATION_TYPE_PRE_INCREMENTATION:
11871 {
11872 /* Modifier already applied */
11873 break;
11874 }
11875
11876 case OPERATION_TYPE_POST_DECREMENTATION:
11877 case OPERATION_TYPE_POST_INCREMENTATION:
11878 {
11879 /* Need to reverse the modification for the purpose of the following check */
11880 expected_value -= modifier;
11881
11882 break;
11883 }
11884
11885 default:
11886 {
11887 TCU_FAIL("Unrecognized operation type");
11888 }
11889 } /* switch (test_case.operation_type) */
11890
11891 if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11892 {
11893 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11894 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11895
11896 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11897 << variable_type_string << "]"
11898 " and operation type ["
11899 << operation_type_string << "]"
11900 " were found invalid."
11901 << tcu::TestLog::EndMessage;
11902
11903 result = false;
11904 break;
11905 } /* if (test case failed) */
11906 } /* for (all components) */
11907 }
11908
11909 /* Verify the comparison operation results */
11910 if (Utils::isScalarVariableType(test_case.variable_type))
11911 {
11912 DE_ASSERT(n_result_components == 1);
11913
11914 const bool expected_result_lt[2] = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11915 const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11916 const bool expected_result_gt[2] = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11917 const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11918
11919 if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11920 (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11921 {
11922 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11923 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11924
11925 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11926 "variable type ["
11927 << variable_type_string << "]"
11928 "and operation type ["
11929 << operation_type_string << "]"
11930 "was found invalid; expected:("
11931 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11932 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11933 << tcu::TestLog::EndMessage;
11934
11935 result = false;
11936 }
11937
11938 if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11939 (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11940 {
11941 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11942 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11943
11944 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11945 "variable type ["
11946 << variable_type_string << "]"
11947 "and operation type ["
11948 << operation_type_string << "]"
11949 "was found invalid; expected:("
11950 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11951 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11952 << tcu::TestLog::EndMessage;
11953
11954 result = false;
11955 }
11956
11957 if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11958 (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11959 {
11960 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11961 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11962
11963 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11964 "variable type ["
11965 << variable_type_string << "]"
11966 "and operation type ["
11967 << operation_type_string << "]"
11968 "was found invalid; expected:("
11969 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11970 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11971 << tcu::TestLog::EndMessage;
11972
11973 result = false;
11974 }
11975
11976 if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11977 (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11978 {
11979 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11980 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11981
11982 m_testCtx.getLog() << tcu::TestLog::Message
11983 << "Values reported for greater-than-or-equal operator used for "
11984 "variable type ["
11985 << variable_type_string << "]"
11986 "and operation type ["
11987 << operation_type_string << "]"
11988 "was found invalid; expected:("
11989 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11990 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11991 << tcu::TestLog::EndMessage;
11992
11993 result = false;
11994 }
11995 } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11996 else
11997 {
11998 if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11999 xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
12000 xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
12001 {
12002 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
12003 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
12004
12005 m_testCtx.getLog() << tcu::TestLog::Message
12006 << "Invalid value was reported for matrix variable type, for which "
12007 " operator checks are not executed; variable type ["
12008 << variable_type_string << "]"
12009 "and operation type ["
12010 << operation_type_string << "]" << tcu::TestLog::EndMessage;
12011
12012 result = false;
12013 }
12014 }
12015
12016 return result;
12017 }
12018
12019 namespace TypeHelpers
12020 {
12021 /** Get base type for reference types
12022 *
12023 * @tparam T type
12024 **/
12025 template <typename T>
12026 class referenceToType
12027 {
12028 public:
12029 typedef T result;
12030 };
12031
12032 template <typename T>
12033 class referenceToType<const T&>
12034 {
12035 public:
12036 typedef T result;
12037 };
12038
12039 /** Maps variable type with enumeration Utils::_variable_type
12040 *
12041 * @tparam T type
12042 **/
12043 template <typename T>
12044 class typeInfo;
12045
12046 template <>
12047 class typeInfo<glw::GLboolean>
12048 {
12049 public:
12050 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12051 };
12052
12053 template <>
12054 class typeInfo<glw::GLdouble>
12055 {
12056 public:
12057 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12058 };
12059
12060 template <>
12061 class typeInfo<tcu::UVec2>
12062 {
12063 public:
12064 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12065 };
12066
12067 template <>
12068 class typeInfo<tcu::UVec3>
12069 {
12070 public:
12071 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12072 };
12073
12074 template <>
12075 class typeInfo<tcu::UVec4>
12076 {
12077 public:
12078 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12079 };
12080
12081 template <>
12082 class typeInfo<tcu::DVec2>
12083 {
12084 public:
12085 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12086 };
12087
12088 template <>
12089 class typeInfo<tcu::DVec3>
12090 {
12091 public:
12092 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12093 };
12094
12095 template <>
12096 class typeInfo<tcu::DVec4>
12097 {
12098 public:
12099 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12100 };
12101
12102 template <>
12103 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12104 {
12105 public:
12106 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12107 };
12108
12109 template <>
12110 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12111 {
12112 public:
12113 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12114 };
12115
12116 template <>
12117 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12118 {
12119 public:
12120 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12121 };
12122
12123 template <>
12124 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12125 {
12126 public:
12127 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12128 };
12129
12130 template <>
12131 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12132 {
12133 public:
12134 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12135 };
12136
12137 template <>
12138 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12139 {
12140 public:
12141 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12142 };
12143
12144 template <>
12145 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12146 {
12147 public:
12148 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12149 };
12150
12151 template <>
12152 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12153 {
12154 public:
12155 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12156 };
12157
12158 template <>
12159 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12160 {
12161 public:
12162 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12163 };
12164 } /* TypeHelpers */
12165
12166 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12167 *
12168 **/
12169 namespace Math
12170 {
12171 template <typename T>
12172 static T clamp(T x, T minVal, T maxVal);
12173
12174 template <int Size>
12175 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12176
12177 template <int Size>
12178 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12179
12180 template <typename T>
12181 static T determinant(T val);
12182
12183 template <typename T>
12184 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12185
12186 template <typename T>
12187 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12188
12189 template <typename T>
12190 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12191
12192 template <int Size>
12193 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12194 glw::GLuint column, glw::GLuint row);
12195
12196 template <int Size>
12197 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12198 const tcu::Vector<glw::GLdouble, Size>& right);
12199
12200 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12201
12202 static glw::GLdouble fract(glw::GLdouble val);
12203
12204 template <typename T>
12205 static T frexp(T val, glw::GLint& exp);
12206
12207 template <int Size>
12208 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12209 const tcu::Vector<glw::GLdouble, Size>& right);
12210
12211 template <int Size>
12212 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12213 const tcu::Vector<glw::GLdouble, Size>& right);
12214
12215 template <int Size>
12216 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12217
12218 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12219
12220 static glw::GLuint isinf_impl(glw::GLdouble val);
12221
12222 static glw::GLuint isnan_impl(glw::GLdouble val);
12223
12224 template <typename T>
12225 static T ldexp(T val, glw::GLint exp);
12226
12227 template <int Size>
12228 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12229 const tcu::Vector<glw::GLdouble, Size>& right);
12230
12231 template <int Size>
12232 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12233 const tcu::Vector<glw::GLdouble, Size>& right);
12234
12235 template <typename T>
12236 static T max(T left, T right);
12237
12238 template <typename T>
12239 static T min(T left, T right);
12240
12241 template <int Size>
12242 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12243 glw::GLuint row);
12244
12245 template <typename T>
12246 static T mix(T left, T right, T weight);
12247
12248 template <typename T>
12249 static T mod(T left, T right);
12250
12251 template <typename T>
12252 static T modf(T val, T& integer);
12253
12254 template <typename T>
12255 static T multiply(T left, T right);
12256
12257 template <int Size>
12258 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12259 const tcu::Vector<glw::GLdouble, Size>& right);
12260
12261 template <int Cols, int Rows>
12262 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12263 const tcu::Vector<glw::GLdouble, Cols>& right);
12264
12265 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12266
12267 template <typename T>
12268 static T round(T t);
12269
12270 template <typename T>
12271 static T roundEven(T t);
12272
12273 template <typename T>
12274 static T sign(T t);
12275
12276 template <typename T>
12277 static T smoothStep(T e0, T e1, T val);
12278
12279 template <typename T>
12280 static T step(T edge, T val);
12281
12282 template <typename T, int Rows, int Cols>
12283 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12284
12285 template <typename T>
12286 static T trunc(T t);
12287
12288 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12289
12290 template <typename T>
clamp(T x,T minVal,T maxVal)12291 static T clamp(T x, T minVal, T maxVal)
12292 {
12293 return min(max(x, minVal), maxVal);
12294 }
12295
12296 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12297 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12298 {
12299 tcu::Matrix<glw::GLdouble, Size, Size> result;
12300
12301 for (glw::GLuint c = 0; c < Size; ++c)
12302 {
12303 for (glw::GLuint r = 0; r < Size; ++r)
12304 {
12305 const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12306
12307 result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12308 }
12309 }
12310
12311 return result;
12312 }
12313
12314 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12315 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12316 {
12317 tcu::Vector<glw::GLuint, Size> result;
12318
12319 for (glw::GLint i = 0; i < Size; ++i)
12320 {
12321 if (GL_FALSE != src[i])
12322 {
12323 result[i] = 1;
12324 }
12325 else
12326 {
12327 result[i] = 0;
12328 }
12329 }
12330
12331 return result;
12332 }
12333
12334 template <typename T>
det2(T _00,T _10,T _01,T _11)12335 static T det2(T _00, T _10, T _01, T _11)
12336 {
12337 return _00 * _11 - _01 * _10;
12338 }
12339
12340 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12341 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12342 {
12343 return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12344 }
12345
12346 template <typename T>
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)12347 static T det4(T _00, T _10, T _20, T _30, T _01, T _11, T _21, T _31, T _02, T _12, T _22, T _32, T _03, T _13, T _23,
12348 T _33)
12349 {
12350 return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12351 _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12352 _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12353 _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12354 }
12355
12356 template <typename T>
determinant(T val)12357 static T determinant(T val)
12358 {
12359 return val;
12360 }
12361
12362 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12363 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12364 {
12365 return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12366 }
12367
12368 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12369 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12370 {
12371 return det3(mat(0, 0), mat(0, 1), mat(0, 2), mat(1, 0), mat(1, 1), mat(1, 2), mat(2, 0), mat(2, 1), mat(2, 2));
12372 }
12373
12374 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12375 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12376 {
12377 return det4(mat(0, 0), mat(0, 1), mat(0, 2), mat(0, 3), mat(1, 0), mat(1, 1), mat(1, 2), mat(1, 3), mat(2, 0),
12378 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12379 }
12380
12381 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12382 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12383 glw::GLuint column, glw::GLuint row)
12384 {
12385 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12386
12387 for (glw::GLuint c = 0; c < Size; ++c)
12388 {
12389 /* Skip eliminated column */
12390 if (column == c)
12391 {
12392 continue;
12393 }
12394
12395 for (glw::GLuint r = 0; r < Size; ++r)
12396 {
12397 /* Skip eliminated row */
12398 if (row == r)
12399 {
12400 continue;
12401 }
12402
12403 const glw::GLint r_offset = (r > row) ? -1 : 0;
12404 const glw::GLint c_offset = (c > column) ? -1 : 0;
12405
12406 result(r + r_offset, c + c_offset) = matrix(r, c);
12407 }
12408 }
12409
12410 return result;
12411 }
12412
12413 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12415 const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 return convertBvecToUvec(tcu::equal(left, right));
12418 }
12419
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12420 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12421 {
12422 return a * b + c;
12423 }
12424
fract(glw::GLdouble val)12425 static glw::GLdouble fract(glw::GLdouble val)
12426 {
12427 return val - floor(val);
12428 }
12429
12430 template <typename T>
frexp(T val,glw::GLint & exp)12431 static T frexp(T val, glw::GLint& exp)
12432 {
12433 return ::frexp(val, &exp);
12434 }
12435
12436 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12437 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12438 const tcu::Vector<glw::GLdouble, Size>& right)
12439 {
12440 return convertBvecToUvec(tcu::greaterThan(left, right));
12441 }
12442
12443 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12444 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12445 const tcu::Vector<glw::GLdouble, Size>& right)
12446 {
12447 return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12448 }
12449
12450 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12451 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12452 {
12453 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix);
12454 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12455 const glw::GLdouble det = determinant(matrix);
12456 const glw::GLdouble inv_det = 1.0 / det;
12457
12458 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12459
12460 return result;
12461 }
12462
inverseSqrt(glw::GLdouble val)12463 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12464 {
12465 const glw::GLdouble root = sqrt(val);
12466
12467 return (1.0 / root);
12468 }
12469
isinf_impl(glw::GLdouble val)12470 static glw::GLuint isinf_impl(glw::GLdouble val)
12471 {
12472 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12473
12474 return ((infinity == val) || (-infinity == val));
12475 }
12476
isnan_impl(glw::GLdouble val)12477 static glw::GLuint isnan_impl(glw::GLdouble val)
12478 {
12479 return val != val;
12480 }
12481
12482 template <typename T>
ldexp(T val,glw::GLint exp)12483 static T ldexp(T val, glw::GLint exp)
12484 {
12485 return ::ldexp(val, exp);
12486 }
12487
12488 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12489 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12490 const tcu::Vector<glw::GLdouble, Size>& right)
12491 {
12492 return convertBvecToUvec(tcu::lessThan(left, right));
12493 }
12494
12495 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12496 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12497 const tcu::Vector<glw::GLdouble, Size>& right)
12498 {
12499 return convertBvecToUvec(tcu::lessThanEqual(left, right));
12500 }
12501
12502 template <typename T>
max(T left,T right)12503 static T max(T left, T right)
12504 {
12505 return (left >= right) ? left : right;
12506 }
12507
12508 template <typename T>
min(T left,T right)12509 static T min(T left, T right)
12510 {
12511 return (left <= right) ? left : right;
12512 }
12513
12514 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12515 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12516 glw::GLuint row)
12517 {
12518 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12519
12520 return determinant(eliminated);
12521 }
12522
12523 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12524 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12525 {
12526 const glw::GLuint r = (0 == row) ? 1 : 0;
12527 const glw::GLuint c = (0 == column) ? 1 : 0;
12528
12529 return matrix(r, c);
12530 }
12531
12532 template <typename T>
mix(T left,T right,T weight)12533 static T mix(T left, T right, T weight)
12534 {
12535 return left * (1 - weight) + right * (weight);
12536 }
12537
12538 template <typename T>
mod(T left,T right)12539 static T mod(T left, T right)
12540 {
12541 const T div_res = left / right;
12542 const T floored = floor(div_res);
12543
12544 return left - right * floored;
12545 }
12546
12547 template <typename T>
modf(T val,T & integer)12548 static T modf(T val, T& integer)
12549 {
12550 return ::modf(val, &integer);
12551 }
12552
12553 template <typename T>
multiply(T left,T right)12554 static T multiply(T left, T right)
12555 {
12556 T result = left * right;
12557
12558 return result;
12559 }
12560
12561 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12562 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12563 const tcu::Vector<glw::GLdouble, Size>& right)
12564 {
12565 return convertBvecToUvec(tcu::notEqual(left, right));
12566 }
12567
12568 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12569 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12570 const tcu::Vector<glw::GLdouble, Cols>& right)
12571 {
12572 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12573 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12574 tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12575
12576 for (glw::GLuint i = 0; i < Rows; ++i)
12577 {
12578 left_mat(i, 0) = left[i];
12579 }
12580
12581 for (glw::GLuint i = 0; i < Cols; ++i)
12582 {
12583 right_mat(0, i) = right[i];
12584 }
12585
12586 result = left_mat * right_mat;
12587
12588 return result;
12589 }
12590
packDouble2x32(const tcu::UVec2 & in)12591 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12592 {
12593 const glw::GLuint buffer[2] = { in[0], in[1] };
12594 glw::GLdouble result;
12595 memcpy(&result, buffer, sizeof(result));
12596 return result;
12597 }
12598
12599 template <typename T>
round(T t)12600 static T round(T t)
12601 {
12602 T frac = fract(t);
12603 T res = t - frac;
12604
12605 if (((T)0.5) < frac)
12606 {
12607 res += ((T)1.0);
12608 }
12609
12610 return res;
12611 }
12612
12613 template <typename T>
roundEven(T t)12614 static T roundEven(T t)
12615 {
12616 T frac = fract(t);
12617 T res = t - frac;
12618
12619 if (((T)0.5) < frac)
12620 {
12621 res += ((T)1.0);
12622 }
12623 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12624 {
12625 res += ((T)1.0);
12626 }
12627
12628 return res;
12629 }
12630
12631 template <typename T>
sign(T t)12632 static T sign(T t)
12633 {
12634 if (0 > t)
12635 {
12636 return -1;
12637 }
12638 else if (0 == t)
12639 {
12640 return 0;
12641 }
12642 else
12643 {
12644 return 1;
12645 }
12646 }
12647
12648 template <typename T>
smoothStep(T e0,T e1,T val)12649 static T smoothStep(T e0, T e1, T val)
12650 {
12651 if (e0 >= val)
12652 {
12653 return 0;
12654 }
12655
12656 if (e1 <= val)
12657 {
12658 return 1;
12659 }
12660
12661 T temp = (val - e0) / (e1 - e0);
12662
12663 T result = temp * temp * (3 - 2 * temp);
12664
12665 return result;
12666 }
12667
12668 template <typename T>
step(T edge,T val)12669 static T step(T edge, T val)
12670 {
12671 if (edge > val)
12672 {
12673 return 0;
12674 }
12675 else
12676 {
12677 return 1;
12678 }
12679 }
12680
12681 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12682 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12683 {
12684 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12685
12686 return result;
12687 }
12688
12689 template <typename T>
trunc(T t)12690 static T trunc(T t)
12691 {
12692 const T abs_value = de::abs(t);
12693 const T result_value = floor(abs_value);
12694
12695 const T result = sign(t) * result_value;
12696
12697 return result;
12698 }
12699
unpackDouble2x32(const glw::GLdouble & val)12700 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12701 {
12702 glw::GLuint* ptr = (glw::GLuint*)&val;
12703 tcu::UVec2 result(ptr[0], ptr[1]);
12704
12705 return result;
12706 }
12707 } /* Math */
12708
12709 /** Enumeration of tested functions
12710 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12711 * For example "max" can be called for (dvec3, double).
12712 **/
12713 enum FunctionEnum
12714 {
12715 FUNCTION_ABS = 0,
12716 FUNCTION_CEIL,
12717 FUNCTION_CLAMP,
12718 FUNCTION_CLAMP_AGAINST_SCALAR,
12719 FUNCTION_CROSS,
12720 FUNCTION_DETERMINANT,
12721 FUNCTION_DISTANCE,
12722 FUNCTION_DOT,
12723 FUNCTION_EQUAL,
12724 FUNCTION_FACEFORWARD,
12725 FUNCTION_FLOOR,
12726 FUNCTION_FMA,
12727 FUNCTION_FRACT,
12728 FUNCTION_FREXP,
12729 FUNCTION_GREATERTHAN,
12730 FUNCTION_GREATERTHANEQUAL,
12731 FUNCTION_INVERSE,
12732 FUNCTION_INVERSESQRT,
12733 FUNCTION_LDEXP,
12734 FUNCTION_LESSTHAN,
12735 FUNCTION_LESSTHANEQUAL,
12736 FUNCTION_LENGTH,
12737 FUNCTION_MATRIXCOMPMULT,
12738 FUNCTION_MAX,
12739 FUNCTION_MAX_AGAINST_SCALAR,
12740 FUNCTION_MIN,
12741 FUNCTION_MIN_AGAINST_SCALAR,
12742 FUNCTION_MIX,
12743 FUNCTION_MOD,
12744 FUNCTION_MOD_AGAINST_SCALAR,
12745 FUNCTION_MODF,
12746 FUNCTION_NORMALIZE,
12747 FUNCTION_NOTEQUAL,
12748 FUNCTION_OUTERPRODUCT,
12749 FUNCTION_PACKDOUBLE2X32,
12750 FUNCTION_REFLECT,
12751 FUNCTION_REFRACT,
12752 FUNCTION_ROUND,
12753 FUNCTION_ROUNDEVEN,
12754 FUNCTION_SIGN,
12755 FUNCTION_SMOOTHSTEP,
12756 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12757 FUNCTION_SQRT,
12758 FUNCTION_STEP,
12759 FUNCTION_STEP_AGAINST_SCALAR,
12760 FUNCTION_TRANSPOSE,
12761 FUNCTION_TRUNC,
12762 FUNCTION_UNPACKDOUBLE2X32,
12763 FUNCTION_ISNAN,
12764 FUNCTION_ISINF,
12765 };
12766
12767 struct TypeDefinition
12768 {
12769 std::string name;
12770 glw::GLuint n_columns;
12771 glw::GLuint n_rows;
12772 };
12773
12774 /** Implementation of BuiltinFunctionTest test, description follows:
12775 *
12776 * Verify double-precision support in common functions works correctly.
12777 * All double-precision types that apply for particular cases should
12778 * be tested for the following functions:
12779 *
12780 * - abs();
12781 * - ceil();
12782 * - clamp();
12783 * - cross();
12784 * - determinant();
12785 * - distance();
12786 * - dot();
12787 * - equal();
12788 * - faceforward();
12789 * - floor();
12790 * - fma();
12791 * - fract();
12792 * - frexp();
12793 * - greaterThan();
12794 * - greaterThanEqual();
12795 * - inverse();
12796 * - inversesqrt();
12797 * - ldexp();
12798 * - lessThan();
12799 * - lessThanEqual();
12800 * - length();
12801 * - matrixCompMult();
12802 * - max();
12803 * - min();
12804 * - mix();
12805 * - mod();
12806 * - modf();
12807 * - normalize();
12808 * - notEqual();
12809 * - outerProduct();
12810 * - packDouble2x32();
12811 * - reflect();
12812 * - refract();
12813 * - round();
12814 * - roundEven();
12815 * - sign();
12816 * - smoothstep();
12817 * - sqrt();
12818 * - step();
12819 * - transpose();
12820 * - trunc();
12821 * - unpackDouble2x32();
12822 * - isnan();
12823 * - isinf();
12824 *
12825 * The test should work by creating a program object (for each case
12826 * considered), to which a vertex shader should be attached. The
12827 * shader should define input variables that should be used as
12828 * arguments for the function in question. The result of the
12829 * operation should then be XFBed back to the test, where the
12830 * value should be verified.
12831 *
12832 * Reference function implementation from pre-DEQP CTS framework
12833 * should be ported to C for verification purposes where available.
12834 *
12835 * The test should use 1024 different scalar/vector/matrix argument
12836 * combinations. It should pass if all functions are determined
12837 * to work correctly for all argument combinations used.
12838 **/
12839 class BuiltinFunctionTest : public deqp::TestCase
12840 {
12841 public:
12842 /* Public methods */
12843 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12844 TypeDefinition typeDefinition);
12845
12846 virtual void deinit();
12847 virtual tcu::TestNode::IterateResult iterate();
12848
12849 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12850 *
12851 **/
12852 class functionObject
12853 {
12854 public:
12855 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12856 Utils::_variable_type result_type);
12857
~functionObject()12858 virtual ~functionObject()
12859 {
12860 }
12861
12862 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12863
12864 virtual glw::GLuint getArgumentCount() const = 0;
12865 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12866 glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12867 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12868 glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12869 glw::GLuint getArgumentStride() const;
12870 glw::GLuint getArgumentStride(glw::GLuint argument) const;
12871 FunctionEnum getFunctionEnum() const;
12872 const glw::GLchar* getName() const;
12873 glw::GLuint getResultComponents(glw::GLuint result) const;
12874 virtual glw::GLuint getResultCount() const;
12875 glw::GLuint getResultOffset(glw::GLuint result) const;
12876 virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12877 glw::GLuint getResultStride(glw::GLuint result) const;
12878 glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12879 glw::GLuint getResultStride() const;
12880
12881 protected:
12882 const FunctionEnum m_function_enum;
12883 const glw::GLchar* m_function_name;
12884 const glw::GLvoid* m_p_function;
12885 const Utils::_variable_type m_res_type;
12886 };
12887
12888 private:
12889 /* Private types */
12890 /** General type enumeration
12891 *
12892 **/
12893 enum generalType
12894 {
12895 SCALAR = 0,
12896 VECTOR,
12897 MATRIX,
12898 };
12899
12900 /** Details of variable type
12901 *
12902 **/
12903 struct typeDetails
12904 {
12905 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12906
12907 generalType m_general_type;
12908 glw::GLuint m_n_columns;
12909 glw::GLuint m_n_rows;
12910 glw::GLenum m_type;
12911 std::string m_type_name;
12912 };
12913
12914 /* Typedefs for gl.uniform* function pointers */
12915 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12916 const glw::GLdouble*);
12917 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12918 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12919 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12920
12921 /* Private methods */
12922 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12923
12924 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12925
12926 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
12927 const functionObject& function_object) const;
12928
12929 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
12930 const functionObject& function_object) const;
12931
12932 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
12933 const functionObject& function_object) const;
12934
12935 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
12936 const functionObject& function_object) const;
12937
12938 const glw::GLchar* getUniformName(glw::GLuint argument) const;
12939 const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12940
12941 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12942
12943 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12944
12945 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12946
12947 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12948 glw::GLubyte* buffer);
12949
12950 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12951
12952 void prepareTestData(const functionObject& function_object);
12953 void prepareVertexShaderCode(const functionObject& function_object);
12954
12955 bool test(FunctionEnum function, const typeDetails& type);
12956
12957 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12958
12959 void testInit();
12960
12961 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12962 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12963 const glw::GLvoid* result_src);
12964
12965 bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12966
12967 /* Private constants */
12968 static const glw::GLdouble m_epsilon;
12969 static const glw::GLuint m_n_veritces;
12970
12971 /* Private fields */
12972 glw::GLuint m_transform_feedback_buffer_id;
12973 glw::GLuint m_vertex_array_object_id;
12974
12975 std::vector<glw::GLubyte> m_expected_results_data;
12976 FunctionEnum m_function;
12977 TypeDefinition m_typeDefinition;
12978 std::vector<glw::GLubyte> m_argument_data;
12979 std::string m_vertex_shader_code;
12980 };
12981
12982 /* Constants used by BuiltinFunctionTest */
12983 /** Khronos Bug #14010
12984 * Using an epsilon value for comparing floating points is error prone.
12985 * Rather than writing a new floating point comparison function, I am
12986 * increasing the epsilon value to allow greater orders of magnitude
12987 * of floating point values.
12988 **/
12989 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002;
12990 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
12991
12992 /** Implementations of function objects required by "BuiltinFunctionTest"
12993 *
12994 **/
12995 namespace FunctionObject
12996 {
12997 /** Maps variable type with enumeration Utils::_variable_type
12998 *
12999 * @tparam T type
13000 **/
13001 template <typename T>
13002 class typeInfo
13003 {
13004 public:
13005 static const Utils::_variable_type variable_type =
13006 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
13007 };
13008
13009 /** Place data from <in> into <buffer>
13010 *
13011 * @param buffer Buffer
13012 * @param in Input data
13013 **/
13014 template <typename T>
13015 class pack
13016 {
13017 public:
set(glw::GLvoid * buffer,const T & in)13018 static void set(glw::GLvoid* buffer, const T& in)
13019 {
13020 *(T*)buffer = in;
13021 }
13022 };
13023
13024 /** Place tcu::Matrix data from <in> into <buffer>
13025 *
13026 * @param buffer Buffer
13027 * @param in Input data
13028 **/
13029 template <int Cols, int Rows>
13030 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13031 {
13032 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13033 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13034 {
13035 glw::GLdouble* data = (glw::GLdouble*)buffer;
13036
13037 for (glw::GLint column = 0; column < Cols; ++column)
13038 {
13039 for (glw::GLint row = 0; row < Rows; ++row)
13040 {
13041 glw::GLint index = column * Rows + row;
13042
13043 data[index] = in(row, column);
13044 }
13045 }
13046 }
13047 };
13048
13049 /** Get data of <out> from <buffer>
13050 *
13051 * @param buffer Buffer
13052 * @param out Output data
13053 **/
13054 template <typename T>
13055 class unpack
13056 {
13057 public:
get(const glw::GLvoid * buffer,T & out)13058 static void get(const glw::GLvoid* buffer, T& out)
13059 {
13060 out = *(T*)buffer;
13061 }
13062 };
13063
13064 /** Get tcu::Matrix data from <buffer>
13065 *
13066 * @param buffer Buffer
13067 * @param out Output data
13068 **/
13069 template <int Cols, int Rows>
13070 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13071 {
13072 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13073 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13074 {
13075 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13076
13077 for (glw::GLint column = 0; column < Cols; ++column)
13078 {
13079 for (glw::GLint row = 0; row < Rows; ++row)
13080 {
13081 glw::GLint index = column * Rows + row;
13082
13083 out(row, column) = data[index];
13084 }
13085 }
13086 }
13087 };
13088
13089 /** Base of unary function classes
13090 *
13091 **/
13092 class unaryBase : public BuiltinFunctionTest::functionObject
13093 {
13094 public:
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)13095 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13096 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13097 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13098 {
13099 }
13100
getArgumentCount() const13101 virtual glw::GLuint getArgumentCount() const
13102 {
13103 return 1;
13104 }
13105
getArgumentType(glw::GLuint) const13106 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13107 {
13108 return m_arg_type;
13109 }
13110
13111 protected:
13112 const Utils::_variable_type m_arg_type;
13113 };
13114
13115 /** Unary function class. It treats input argument as one variable.
13116 *
13117 * @tparam ResT Type of result
13118 * @tparam ArgT Type of argument
13119 **/
13120 template <typename ResT, typename ArgT>
13121 class unary : public unaryBase
13122 {
13123 public:
13124 typedef ResT (*functionPointer)(const ArgT&);
13125
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13126 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13127 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13128 typeInfo<ArgT>::variable_type)
13129 {
13130 }
13131
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13132 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13133 {
13134 ResT result;
13135 ArgT arg;
13136
13137 unpack<ArgT>::get(argument_src, arg);
13138
13139 functionPointer p_function = (functionPointer)m_p_function;
13140
13141 result = p_function(arg);
13142
13143 pack<ResT>::set(result_dst, result);
13144 }
13145 };
13146
13147 /** Unary function class. It treats input argument as separate components.
13148 *
13149 * @tparam ResT Type of result
13150 **/
13151 template <typename ResT>
13152 class unaryByComponent : public unaryBase
13153 {
13154 public:
13155 typedef ResT (*functionPointer)(glw::GLdouble);
13156
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13157 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13158 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13159 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13160 {
13161 }
13162
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13163 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13164 {
13165 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13166 ResT* p_result = (ResT*)result_dst;
13167 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src;
13168
13169 functionPointer p_function = (functionPointer)m_p_function;
13170
13171 for (glw::GLuint component = 0; component < n_components; ++component)
13172 {
13173 p_result[component] = p_function(p_arg[component]);
13174 }
13175 }
13176 };
13177
13178 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13179 *
13180 * @tparam ResT Type of result
13181 * @tparam ArgT Type of argument
13182 * @tparam OutT Type of output parameter
13183 **/
13184 template <typename ResT, typename ArgT, typename OutT>
13185 class unaryWithOutputByComponent : public unaryBase
13186 {
13187 public:
13188 typedef ResT (*functionPointer)(ArgT, OutT&);
13189
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)13190 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13191 functionPointer function_pointer, const Utils::_variable_type res_type,
13192 const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13193 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13194 , m_out_type(out_type)
13195 {
13196 }
13197
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13198 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13199 {
13200 ResT* p_result = (ResT*)result_dst;
13201 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13202 ArgT* p_arg = (ArgT*)argument_src;
13203
13204 const glw::GLuint n_components_0 = getArgumentComponents(0);
13205 const glw::GLuint n_components_1 = getResultComponents(1);
13206 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13207
13208 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13209 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13210
13211 functionPointer p_function = (functionPointer)m_p_function;
13212
13213 for (glw::GLuint component = 0; component < n_components; ++component)
13214 {
13215 const ArgT first_arg = p_arg[component * component_step_0];
13216 OutT& second_arg = p_out[component * component_step_1];
13217
13218 p_result[component] = p_function(first_arg, second_arg);
13219 }
13220 }
13221
getResultCount() const13222 glw::GLuint getResultCount() const
13223 {
13224 return 2;
13225 }
13226
getResultType(glw::GLuint result) const13227 Utils::_variable_type getResultType(glw::GLuint result) const
13228 {
13229 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13230
13231 switch (result)
13232 {
13233 case 0:
13234 type = m_res_type;
13235 break;
13236 case 1:
13237 type = m_out_type;
13238 break;
13239 default:
13240 TCU_FAIL("Not implemented");
13241 break;
13242 }
13243
13244 return type;
13245 }
13246
13247 protected:
13248 const Utils::_variable_type m_out_type;
13249 };
13250
13251 /** Base of binary function classes.
13252 *
13253 **/
13254 class binaryBase : public BuiltinFunctionTest::functionObject
13255 {
13256 public:
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)13257 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13258 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13259 const Utils::_variable_type arg_2_type)
13260 : functionObject(function_enum, function_name, function_pointer, res_type)
13261 , m_arg_1_type(arg_1_type)
13262 , m_arg_2_type(arg_2_type)
13263 {
13264 }
13265
getArgumentCount() const13266 virtual glw::GLuint getArgumentCount() const
13267 {
13268 return 2;
13269 }
13270
getArgumentType(glw::GLuint argument) const13271 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13272 {
13273 switch (argument)
13274 {
13275 case 0:
13276 return m_arg_1_type;
13277 break;
13278 case 1:
13279 return m_arg_2_type;
13280 break;
13281 default:
13282 return Utils::VARIABLE_TYPE_UNKNOWN;
13283 break;
13284 }
13285 }
13286
13287 protected:
13288 const Utils::_variable_type m_arg_1_type;
13289 const Utils::_variable_type m_arg_2_type;
13290 };
13291
13292 /** Binary function class. It treats input arguments as two variables.
13293 *
13294 * @param ResT Type of result
13295 * @param Arg1T Type of first argument
13296 * @param Arg2T Type of second argument
13297 **/
13298 template <typename ResT, typename Arg1T, typename Arg2T>
13299 class binary : public binaryBase
13300 {
13301 public:
13302 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13303
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13304 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13305 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13306 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13307 {
13308 }
13309
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13310 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13311 {
13312 const glw::GLuint argument_1_stride = getArgumentStride(0);
13313
13314 functionPointer p_function = (functionPointer)m_p_function;
13315
13316 Arg1T arg_1;
13317 Arg2T arg_2;
13318 ResT result;
13319
13320 unpack<Arg1T>::get(argument_src, arg_1);
13321 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13322
13323 result = p_function(arg_1, arg_2);
13324
13325 pack<ResT>::set(result_dst, result);
13326 }
13327 };
13328
13329 /** Binary function class. It treats input arguments as separate components.
13330 *
13331 * @param ResT Type of result
13332 * @param Arg1T Type of first argument
13333 * @param Arg2T Type of second argument
13334 **/
13335 template <typename ResT, typename Arg1T, typename Arg2T>
13336 class binaryByComponent : public binaryBase
13337 {
13338 public:
13339 typedef ResT (*functionPointer)(Arg1T, Arg2T);
13340
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)13341 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13342 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13343 const Utils::_variable_type arg_2_type)
13344 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13345 {
13346 }
13347
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13348 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13349 {
13350 ResT* p_result = (ResT*)result_dst;
13351 Arg1T* p_arg_1 = (Arg1T*)argument_src;
13352 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13353
13354 const glw::GLuint n_components_0 = getArgumentComponents(0);
13355 const glw::GLuint n_components_1 = getArgumentComponents(1);
13356 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13357
13358 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13359 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13360
13361 functionPointer p_function = (functionPointer)m_p_function;
13362
13363 for (glw::GLuint component = 0; component < n_components; ++component)
13364 {
13365 const Arg1T first_arg = p_arg_1[component * component_step_0];
13366 const Arg2T second_arg = p_arg_2[component * component_step_1];
13367
13368 p_result[component] = p_function(first_arg, second_arg);
13369 }
13370 }
13371 };
13372
13373 /** Base of tenary function classes.
13374 *
13375 **/
13376 class tenaryBase : public BuiltinFunctionTest::functionObject
13377 {
13378 public:
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)13379 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13380 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13381 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13382 : functionObject(function_enum, function_name, function_pointer, res_type)
13383 , m_arg_1_type(arg_1_type)
13384 , m_arg_2_type(arg_2_type)
13385 , m_arg_3_type(arg_3_type)
13386 {
13387 }
13388
getArgumentCount() const13389 virtual glw::GLuint getArgumentCount() const
13390 {
13391 return 3;
13392 }
13393
getArgumentType(glw::GLuint argument) const13394 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13395 {
13396 switch (argument)
13397 {
13398 case 0:
13399 return m_arg_1_type;
13400 break;
13401 case 1:
13402 return m_arg_2_type;
13403 break;
13404 case 2:
13405 return m_arg_3_type;
13406 break;
13407 default:
13408 return Utils::VARIABLE_TYPE_UNKNOWN;
13409 break;
13410 }
13411 }
13412
13413 protected:
13414 const Utils::_variable_type m_arg_1_type;
13415 const Utils::_variable_type m_arg_2_type;
13416 const Utils::_variable_type m_arg_3_type;
13417 };
13418
13419 /** Tenary function class. It treats input arguments as three variables.
13420 *
13421 * @param ResT Type of result
13422 * @param Arg1T Type of first argument
13423 * @param Arg2T Type of second argument
13424 * @param Arg3T Type of third argument
13425 **/
13426 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13427 class tenary : public tenaryBase
13428 {
13429 public:
13430 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13431 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13432 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13433 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13434
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13435 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13436 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13437 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13438 {
13439 }
13440
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13441 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13442 {
13443 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13444 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13445
13446 functionPointer p_function = (functionPointer)m_p_function;
13447
13448 arg1T arg_1;
13449 arg2T arg_2;
13450 arg3T arg_3;
13451 ResT result;
13452
13453 unpack<arg1T>::get(argument_src, arg_1);
13454 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13455 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13456
13457 result = p_function(arg_1, arg_2, arg_3);
13458
13459 pack<ResT>::set(result_dst, result);
13460 }
13461 };
13462
13463 /** Tenary function class. It treats input arguments as separate components.
13464 *
13465
13466 **/
13467 class tenaryByComponent : public tenaryBase
13468 {
13469 public:
13470 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13471
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)13472 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13473 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13474 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13475 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13476 arg_3_type)
13477 {
13478 }
13479
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13480 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13481 {
13482 glw::GLdouble* p_result = (glw::GLdouble*)result_dst;
13483 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src;
13484
13485 const glw::GLuint n_components_0 = getArgumentComponents(0);
13486 const glw::GLuint n_components_1 = getArgumentComponents(1);
13487 const glw::GLuint n_components_2 = getArgumentComponents(2);
13488 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2);
13489
13490 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13491 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13492 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13493
13494 functionPointer p_function = (functionPointer)m_p_function;
13495
13496 for (glw::GLuint component = 0; component < n_components; ++component)
13497 {
13498 const glw::GLdouble first_arg = p_arg[component * component_step_0];
13499 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13500 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13501
13502 p_result[component] = p_function(first_arg, second_arg, third_arg);
13503 }
13504 }
13505 };
13506 } /* FunctionObject */
13507
13508 /** Constructor.
13509 *
13510 * @param context Rendering context.
13511 **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13512 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13513 TypeDefinition typeDefinition)
13514 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13515 , m_transform_feedback_buffer_id(0)
13516 , m_vertex_array_object_id(0)
13517 , m_function(function)
13518 , m_typeDefinition(typeDefinition)
13519 {
13520 /* Nothing to be done here */
13521 }
13522
13523 /** Deinitializes all GL objects that may have been created during test execution.
13524 *
13525 **/
deinit()13526 void BuiltinFunctionTest::deinit()
13527 {
13528 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13529
13530 /* Clean buffers */
13531 if (0 != m_transform_feedback_buffer_id)
13532 {
13533 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13534 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13535 m_transform_feedback_buffer_id = 0;
13536 }
13537
13538 /* Clean VAO */
13539 if (0 != m_vertex_array_object_id)
13540 {
13541 gl.bindVertexArray(0);
13542 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13543 m_vertex_array_object_id = 0;
13544 }
13545 }
13546
13547 /** Execute test
13548 *
13549 * @return tcu::TestNode::STOP
13550 **/
iterate()13551 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13552 {
13553 /* Check if extension is supported */
13554 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13555 {
13556 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13557 }
13558
13559 testInit();
13560
13561 /* Verify result */
13562 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13563 if (test(m_function, type))
13564 {
13565 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13566 }
13567 else
13568 {
13569 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13570 }
13571
13572 /* Done */
13573 return tcu::TestNode::STOP;
13574 }
13575
13576 /** Constructor
13577 *
13578 * @param function_enum Function enumeration
13579 * @param function_name Function name
13580 * @param function_pointer Pointer to routine that wiil be executed
13581 * @param result_type Type of result
13582 **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13583 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13584 glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13585 : m_function_enum(function_enum)
13586 , m_function_name(function_name)
13587 , m_p_function(function_pointer)
13588 , m_res_type(result_type)
13589 {
13590 /* Nothing to be done here */
13591 }
13592
13593 /** Get number of components for <argument>
13594 *
13595 * @param argument Argument ordinal, starts with 0
13596 *
13597 * @return Number of components
13598 **/
getArgumentComponents(glw::GLuint argument) const13599 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13600 {
13601 const Utils::_variable_type type = getArgumentType(argument);
13602 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13603
13604 return n_components;
13605 }
13606
13607 /** Get size in bytes of single component of <argument>
13608 *
13609 * @param argument Argument ordinal, starts with 0
13610 *
13611 * @return Size of component
13612 **/
getArgumentComponentSize(glw::GLuint argument) const13613 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13614 {
13615 const Utils::_variable_type type = getArgumentType(argument);
13616 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13617 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13618
13619 return base_type_size;
13620 }
13621
13622 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13623 *
13624 * @param argument Argument ordinal, starts with 0
13625 *
13626 * @return Offset of arguemnt's data
13627 **/
getArgumentOffset(glw::GLuint argument) const13628 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13629 {
13630 glw::GLuint result = 0;
13631
13632 for (glw::GLuint i = 0; i < argument; ++i)
13633 {
13634 result += getArgumentStride(i);
13635 }
13636
13637 return result;
13638 }
13639
13640 /** Get stride in bytes of all arguments
13641 *
13642 * @return Stride of all arguments
13643 **/
getArgumentStride() const13644 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13645 {
13646 const glw::GLuint n_args = getArgumentCount();
13647 glw::GLuint result = 0;
13648
13649 for (glw::GLuint i = 0; i < n_args; ++i)
13650 {
13651 result += getArgumentStride(i);
13652 }
13653
13654 return result;
13655 }
13656
13657 /** Get stride in bytes of <argument>
13658 *
13659 * @param argument Argument ordinal, starts with 0
13660 *
13661 * @return Stride of argument
13662 **/
getArgumentStride(glw::GLuint argument) const13663 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13664 {
13665 const glw::GLuint component_size = getArgumentComponentSize(argument);
13666 const glw::GLuint n_components = getArgumentComponents(argument);
13667
13668 return n_components * component_size;
13669 }
13670
13671 /** Get function enumeration
13672 *
13673 * @return Function enumeration
13674 **/
getFunctionEnum() const13675 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13676 {
13677 return m_function_enum;
13678 }
13679
13680 /** Get function name
13681 *
13682 * @return Function name
13683 **/
getName() const13684 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13685 {
13686 return m_function_name;
13687 }
13688
13689 /** Get number of components for <result>
13690 *
13691 * @param result Result ordinal, starts with 0
13692 *
13693 * @return Number of components
13694 **/
getResultComponents(glw::GLuint result) const13695 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13696 {
13697 const Utils::_variable_type type = getResultType(result);
13698 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13699
13700 return n_components;
13701 }
13702
13703 /** Get number of results
13704 *
13705 * @return Number of results
13706 **/
getResultCount() const13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13708 {
13709 return 1;
13710 }
13711
13712 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13713 *
13714 * @param result Result ordinal, starts with 0
13715 *
13716 * @return Offset
13717 **/
getResultOffset(glw::GLuint result) const13718 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13719 {
13720 glw::GLuint offset = 0;
13721
13722 for (glw::GLuint i = 0; i < result; ++i)
13723 {
13724 offset += getResultStride(i);
13725 offset = deAlign32(offset, getBaseTypeSize(i));
13726 }
13727
13728 return offset;
13729 }
13730
13731 /** Get stride in bytes of <result>.
13732 *
13733 * @param result Result ordinal, starts with 0
13734 *
13735 * @return Stride
13736 **/
getResultStride(glw::GLuint result) const13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13738 {
13739 const Utils::_variable_type type = getResultType(result);
13740 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13741
13742 return n_components * getBaseTypeSize(result);
13743 }
13744
13745 /** Get size in bytes of <result> base component.
13746 *
13747 * @param result Result ordinal, starts with 0
13748 *
13749 * @return Alignment
13750 **/
getBaseTypeSize(glw::GLuint result) const13751 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13752 {
13753 const Utils::_variable_type type = getResultType(result);
13754 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13755 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13756
13757 return base_type_size;
13758 }
13759
13760 /** Get stride in bytes of all results.
13761 *
13762 * @return Stride
13763 **/
getResultStride() const13764 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13765 {
13766 const glw::GLuint n_results = getResultCount();
13767 glw::GLuint stride = 0;
13768 glw::GLuint maxAlignment = 0;
13769
13770 for (glw::GLuint i = 0; i < n_results; ++i)
13771 {
13772 const glw::GLuint alignment = getBaseTypeSize(i);
13773 stride += getResultStride(i);
13774 stride = deAlign32(stride, alignment);
13775 maxAlignment = deMaxu32(maxAlignment, alignment);
13776 }
13777
13778 // The stride of all results must also be aligned,
13779 // so results for next vertex are aligned.
13780 return deAlign32(stride, maxAlignment);
13781 }
13782
13783 /** Get type of <result>.
13784 *
13785 * @param result Result ordinal, starts with 0
13786 *
13787 * @return Type
13788 **/
getResultType(glw::GLuint) const13789 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13790 {
13791 return m_res_type;
13792 }
13793
13794 /** Constructor
13795 *
13796 * @param n_columns Number of columns
13797 * @param n_rows Number of rows
13798 **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13799 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13800 : m_n_columns(n_columns), m_n_rows(n_rows)
13801 {
13802 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13803 m_type = Utils::getGLDataTypeOfVariableType(type);
13804 m_type_name = Utils::getVariableTypeString(type);
13805
13806 if (1 == m_n_columns)
13807 {
13808 if (1 == m_n_rows)
13809 {
13810 m_general_type = SCALAR;
13811 }
13812 else
13813 {
13814 m_general_type = VECTOR;
13815 }
13816 }
13817 else
13818 {
13819 m_general_type = MATRIX;
13820 }
13821 }
13822
13823 /** Compare two values
13824 *
13825 * @param type Type of values
13826 * @param left Pointer to left value
13827 * @param right Pointer to right value
13828 *
13829 * @return true if values are equal, false otherwise
13830 **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13831 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13832 {
13833 bool result = true;
13834
13835 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13836 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13837
13838 switch (base_type)
13839 {
13840 case Utils::VARIABLE_TYPE_DOUBLE:
13841
13842 {
13843 const glw::GLdouble* left_values = (glw::GLdouble*)left;
13844 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13845
13846 for (glw::GLuint component = 0; component < n_components; ++component)
13847 {
13848 const glw::GLdouble left_value = left_values[component];
13849 const glw::GLdouble right_value = right_values[component];
13850
13851 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13852 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13853 {
13854 result = false;
13855 break;
13856 }
13857 }
13858 }
13859
13860 break;
13861
13862 case Utils::VARIABLE_TYPE_INT:
13863
13864 {
13865 const glw::GLint* left_values = (glw::GLint*)left;
13866 const glw::GLint* right_values = (glw::GLint*)right;
13867
13868 for (glw::GLuint component = 0; component < n_components; ++component)
13869 {
13870 const glw::GLint left_value = left_values[component];
13871 const glw::GLint right_value = right_values[component];
13872
13873 if (left_value != right_value)
13874 {
13875 result = false;
13876 break;
13877 }
13878 }
13879 }
13880
13881 break;
13882
13883 case Utils::VARIABLE_TYPE_UINT:
13884
13885 {
13886 const glw::GLuint* left_values = (glw::GLuint*)left;
13887 const glw::GLuint* right_values = (glw::GLuint*)right;
13888
13889 for (glw::GLuint component = 0; component < n_components; ++component)
13890 {
13891 const glw::GLuint left_value = left_values[component];
13892 const glw::GLuint right_value = right_values[component];
13893
13894 if (left_value != right_value)
13895 {
13896 result = false;
13897 break;
13898 }
13899 }
13900 }
13901
13902 break;
13903
13904 default:
13905
13906 TCU_FAIL("Not implemented");
13907
13908 break;
13909 }
13910
13911 return result;
13912 }
13913
13914 /** Create instance of function object for given function enumeration and type
13915 *
13916 * @param function Function enumeration
13917 * @param type Type details
13918 *
13919 * @return Create object
13920 **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13921 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
13922 const typeDetails& type)
13923 {
13924 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13925 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13926 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13927 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13928 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13929 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13930 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13931 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13932 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13933
13934 const glw::GLuint n_columns = type.m_n_columns;
13935 const glw::GLuint n_rows = type.m_n_rows;
13936 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1);
13937 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13938 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows);
13939 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows);
13940
13941 switch (function)
13942 {
13943 case FUNCTION_ABS:
13944
13945 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13946 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13947
13948 break;
13949
13950 case FUNCTION_CEIL:
13951
13952 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13953 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13954
13955 break;
13956
13957 case FUNCTION_CLAMP:
13958
13959 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13960 variable_type /* arg1_type */, variable_type /* arg2_type */,
13961 variable_type /* arg3_type */);
13962 break;
13963
13964 case FUNCTION_CLAMP_AGAINST_SCALAR:
13965
13966 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13967 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13968 scalar_type /* arg3_type */);
13969 break;
13970
13971 case FUNCTION_CROSS:
13972
13973 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13974 function, "cross", tcu::cross);
13975
13976 break;
13977
13978 case FUNCTION_DETERMINANT:
13979
13980 switch (variable_type)
13981 {
13982 case Utils::VARIABLE_TYPE_DMAT2:
13983 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13984 Math::determinant);
13985 case Utils::VARIABLE_TYPE_DMAT3:
13986 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13987 Math::determinant);
13988 case Utils::VARIABLE_TYPE_DMAT4:
13989 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13990 Math::determinant);
13991 default:
13992 TCU_FAIL("Not implemented");
13993 break;
13994 }
13995
13996 break;
13997
13998 case FUNCTION_DISTANCE:
13999
14000 switch (variable_type)
14001 {
14002 case Utils::VARIABLE_TYPE_DVEC2:
14003 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14004 function, "distance", tcu::distance);
14005 break;
14006 case Utils::VARIABLE_TYPE_DVEC3:
14007 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14008 function, "distance", tcu::distance);
14009 break;
14010 case Utils::VARIABLE_TYPE_DVEC4:
14011 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14012 function, "distance", tcu::distance);
14013 break;
14014 default:
14015 break;
14016 }
14017
14018 break;
14019
14020 case FUNCTION_DOT:
14021
14022 switch (variable_type)
14023 {
14024 case Utils::VARIABLE_TYPE_DVEC2:
14025 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14026 function, "dot", tcu::dot);
14027 break;
14028 case Utils::VARIABLE_TYPE_DVEC3:
14029 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14030 function, "dot", tcu::dot);
14031 break;
14032 case Utils::VARIABLE_TYPE_DVEC4:
14033 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14034 function, "dot", tcu::dot);
14035 break;
14036 default:
14037 break;
14038 }
14039
14040 break;
14041
14042 case FUNCTION_EQUAL:
14043
14044 switch (variable_type)
14045 {
14046 case Utils::VARIABLE_TYPE_DVEC2:
14047 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14048 function, "equal", Math::equal);
14049 break;
14050 case Utils::VARIABLE_TYPE_DVEC3:
14051 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14052 function, "equal", Math::equal);
14053 break;
14054 case Utils::VARIABLE_TYPE_DVEC4:
14055 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14056 function, "equal", Math::equal);
14057 break;
14058 default:
14059 break;
14060 }
14061
14062 break;
14063
14064 case FUNCTION_FACEFORWARD:
14065
14066 switch (variable_type)
14067 {
14068 case Utils::VARIABLE_TYPE_DVEC2:
14069 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14070 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14071 function, "faceforward", tcu::faceForward);
14072 break;
14073 case Utils::VARIABLE_TYPE_DVEC3:
14074 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14075 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14076 function, "faceforward", tcu::faceForward);
14077 break;
14078 case Utils::VARIABLE_TYPE_DVEC4:
14079 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14080 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14081 function, "faceforward", tcu::faceForward);
14082 break;
14083 default:
14084 break;
14085 }
14086
14087 break;
14088
14089 case FUNCTION_FLOOR:
14090
14091 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14092 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14093
14094 break;
14095
14096 case FUNCTION_FMA:
14097
14098 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */,
14099 variable_type /* arg1_type */, variable_type /* arg2_type */,
14100 variable_type /* arg3_type */);
14101
14102 break;
14103
14104 case FUNCTION_FRACT:
14105
14106 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14107 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14108
14109 break;
14110
14111 case FUNCTION_FREXP:
14112
14113 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14114 glw::GLint /* OutT */>(
14115 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14116 int_type /* out_type */);
14117
14118 break;
14119
14120 case FUNCTION_GREATERTHAN:
14121
14122 switch (variable_type)
14123 {
14124 case Utils::VARIABLE_TYPE_DVEC2:
14125 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14126 function, "greaterThan", Math::greaterThan);
14127 break;
14128 case Utils::VARIABLE_TYPE_DVEC3:
14129 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14130 function, "greaterThan", Math::greaterThan);
14131 break;
14132 case Utils::VARIABLE_TYPE_DVEC4:
14133 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14134 function, "greaterThan", Math::greaterThan);
14135 break;
14136 default:
14137 break;
14138 }
14139
14140 break;
14141
14142 case FUNCTION_GREATERTHANEQUAL:
14143
14144 switch (variable_type)
14145 {
14146 case Utils::VARIABLE_TYPE_DVEC2:
14147 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14148 function, "greaterThanEqual", Math::greaterThanEqual);
14149 break;
14150 case Utils::VARIABLE_TYPE_DVEC3:
14151 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14152 function, "greaterThanEqual", Math::greaterThanEqual);
14153 break;
14154 case Utils::VARIABLE_TYPE_DVEC4:
14155 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14156 function, "greaterThanEqual", Math::greaterThanEqual);
14157 break;
14158 default:
14159 break;
14160 }
14161
14162 break;
14163
14164 case FUNCTION_INVERSE:
14165
14166 switch (variable_type)
14167 {
14168 case Utils::VARIABLE_TYPE_DMAT2:
14169 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14170 break;
14171 case Utils::VARIABLE_TYPE_DMAT3:
14172 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14173 break;
14174 case Utils::VARIABLE_TYPE_DMAT4:
14175 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14176 break;
14177 default:
14178 break;
14179 }
14180
14181 break;
14182
14183 case FUNCTION_INVERSESQRT:
14184
14185 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14186 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14187
14188 break;
14189
14190 case FUNCTION_LDEXP:
14191
14192 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14193 glw::GLint /* Arg2T */>(
14194 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */,
14195 int_type /* arg2_type */);
14196
14197 break;
14198
14199 case FUNCTION_LESSTHAN:
14200
14201 switch (variable_type)
14202 {
14203 case Utils::VARIABLE_TYPE_DVEC2:
14204 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14205 function, "lessThan", Math::lessThan);
14206 break;
14207 case Utils::VARIABLE_TYPE_DVEC3:
14208 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14209 function, "lessThan", Math::lessThan);
14210 break;
14211 case Utils::VARIABLE_TYPE_DVEC4:
14212 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14213 function, "lessThan", Math::lessThan);
14214 break;
14215 default:
14216 break;
14217 }
14218
14219 break;
14220
14221 case FUNCTION_LESSTHANEQUAL:
14222
14223 switch (variable_type)
14224 {
14225 case Utils::VARIABLE_TYPE_DVEC2:
14226 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14227 function, "lessThanEqual", Math::lessThanEqual);
14228 break;
14229 case Utils::VARIABLE_TYPE_DVEC3:
14230 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14231 function, "lessThanEqual", Math::lessThanEqual);
14232 break;
14233 case Utils::VARIABLE_TYPE_DVEC4:
14234 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14235 function, "lessThanEqual", Math::lessThanEqual);
14236 break;
14237 default:
14238 break;
14239 }
14240
14241 break;
14242
14243 case FUNCTION_LENGTH:
14244
14245 switch (variable_type)
14246 {
14247 case Utils::VARIABLE_TYPE_DVEC2:
14248 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14249 tcu::length);
14250 break;
14251 case Utils::VARIABLE_TYPE_DVEC3:
14252 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14253 tcu::length);
14254 break;
14255 case Utils::VARIABLE_TYPE_DVEC4:
14256 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14257 tcu::length);
14258 break;
14259 default:
14260 break;
14261 }
14262
14263 break;
14264
14265 case FUNCTION_MATRIXCOMPMULT:
14266
14267 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14268 glw::GLdouble /* Arg2T */>(
14269 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */,
14270 variable_type /* arg2_type */);
14271
14272 break;
14273
14274 case FUNCTION_MAX:
14275
14276 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14277 glw::GLdouble /* Arg2T */>(
14278 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14279 variable_type /* arg2_type */);
14280
14281 break;
14282
14283 case FUNCTION_MAX_AGAINST_SCALAR:
14284
14285 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14286 glw::GLdouble /* Arg2T */>(
14287 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14288 scalar_type /* arg2_type */);
14289
14290 break;
14291
14292 case FUNCTION_MIN:
14293
14294 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14295 glw::GLdouble /* Arg2T */>(
14296 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14297 variable_type /* arg2_type */);
14298
14299 break;
14300
14301 case FUNCTION_MIN_AGAINST_SCALAR:
14302
14303 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14304 glw::GLdouble /* Arg2T */>(
14305 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14306 scalar_type /* arg2_type */);
14307
14308 break;
14309
14310 case FUNCTION_MIX:
14311
14312 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */,
14313 variable_type /* arg1_type */, variable_type /* arg2_type */,
14314 variable_type /* arg3_type */);
14315
14316 break;
14317
14318 case FUNCTION_MOD:
14319
14320 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14321 glw::GLdouble /* Arg2T */>(
14322 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14323 variable_type /* arg2_type */);
14324
14325 break;
14326
14327 case FUNCTION_MOD_AGAINST_SCALAR:
14328
14329 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14330 glw::GLdouble /* Arg2T */>(
14331 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14332 scalar_type /* arg2_type */);
14333
14334 break;
14335
14336 case FUNCTION_MODF:
14337
14338 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14339 glw::GLdouble /* OutT */>(
14340 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14341 variable_type /* out_type */);
14342
14343 break;
14344
14345 case FUNCTION_NORMALIZE:
14346
14347 switch (variable_type)
14348 {
14349 case Utils::VARIABLE_TYPE_DVEC2:
14350 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14351 tcu::normalize);
14352 break;
14353 case Utils::VARIABLE_TYPE_DVEC3:
14354 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14355 tcu::normalize);
14356 break;
14357 case Utils::VARIABLE_TYPE_DVEC4:
14358 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14359 tcu::normalize);
14360 break;
14361 default:
14362 break;
14363 }
14364
14365 break;
14366
14367 case FUNCTION_NOTEQUAL:
14368
14369 switch (variable_type)
14370 {
14371 case Utils::VARIABLE_TYPE_DVEC2:
14372 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14373 function, "notEqual", Math::notEqual);
14374 break;
14375 case Utils::VARIABLE_TYPE_DVEC3:
14376 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14377 function, "notEqual", Math::notEqual);
14378 break;
14379 case Utils::VARIABLE_TYPE_DVEC4:
14380 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14381 function, "notEqual", Math::notEqual);
14382 break;
14383 default:
14384 break;
14385 }
14386
14387 break;
14388
14389 case FUNCTION_OUTERPRODUCT:
14390
14391 switch (variable_type)
14392 {
14393 case Utils::VARIABLE_TYPE_DMAT2:
14394 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14395 function, "outerProduct", Math::outerProduct);
14396 break;
14397 case Utils::VARIABLE_TYPE_DMAT2X3:
14398 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14399 function, "outerProduct", Math::outerProduct);
14400 break;
14401 case Utils::VARIABLE_TYPE_DMAT2X4:
14402 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14403 function, "outerProduct", Math::outerProduct);
14404 break;
14405 case Utils::VARIABLE_TYPE_DMAT3:
14406 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14407 function, "outerProduct", Math::outerProduct);
14408 break;
14409 case Utils::VARIABLE_TYPE_DMAT3X2:
14410 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14411 function, "outerProduct", Math::outerProduct);
14412 break;
14413 case Utils::VARIABLE_TYPE_DMAT3X4:
14414 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14415 function, "outerProduct", Math::outerProduct);
14416 break;
14417 case Utils::VARIABLE_TYPE_DMAT4:
14418 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14419 function, "outerProduct", Math::outerProduct);
14420 break;
14421 case Utils::VARIABLE_TYPE_DMAT4X2:
14422 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14423 function, "outerProduct", Math::outerProduct);
14424 break;
14425 case Utils::VARIABLE_TYPE_DMAT4X3:
14426 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14427 function, "outerProduct", Math::outerProduct);
14428 break;
14429 default:
14430 break;
14431 }
14432
14433 break;
14434
14435 case FUNCTION_PACKDOUBLE2X32:
14436
14437 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14438 Math::packDouble2x32);
14439
14440 break;
14441
14442 case FUNCTION_REFLECT:
14443
14444 switch (variable_type)
14445 {
14446 case Utils::VARIABLE_TYPE_DVEC2:
14447 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14448 function, "reflect", tcu::reflect);
14449 break;
14450 case Utils::VARIABLE_TYPE_DVEC3:
14451 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14452 function, "reflect", tcu::reflect);
14453 break;
14454 case Utils::VARIABLE_TYPE_DVEC4:
14455 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14456 function, "reflect", tcu::reflect);
14457 break;
14458 default:
14459 break;
14460 }
14461
14462 break;
14463
14464 case FUNCTION_REFRACT:
14465
14466 switch (variable_type)
14467 {
14468 case Utils::VARIABLE_TYPE_DVEC2:
14469 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14470 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14471 function, "refract", tcu::refract);
14472 break;
14473 case Utils::VARIABLE_TYPE_DVEC3:
14474 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14475 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14476 function, "refract", tcu::refract);
14477 break;
14478 case Utils::VARIABLE_TYPE_DVEC4:
14479 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14480 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14481 function, "refract", tcu::refract);
14482 break;
14483 default:
14484 break;
14485 }
14486
14487 break;
14488
14489 case FUNCTION_ROUND:
14490
14491 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14492 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14493
14494 break;
14495
14496 case FUNCTION_ROUNDEVEN:
14497
14498 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14499 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14500
14501 break;
14502
14503 case FUNCTION_SIGN:
14504
14505 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14506 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14507
14508 break;
14509
14510 case FUNCTION_SMOOTHSTEP:
14511
14512 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14513 variable_type /* res_type */, variable_type /* arg1_type */,
14514 variable_type /* arg2_type */, variable_type /* arg3_type */);
14515
14516 break;
14517
14518 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14519
14520 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14521 variable_type /* res_type */, scalar_type /* arg1_type */,
14522 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14523
14524 break;
14525
14526 case FUNCTION_SQRT:
14527
14528 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14529 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14530
14531 break;
14532
14533 case FUNCTION_STEP:
14534
14535 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14536 glw::GLdouble /* Arg2T */>(
14537 function, "step", Math::step, variable_type /* res_type */, variable_type /* arg1_type */,
14538 variable_type /* arg2_type */);
14539
14540 break;
14541
14542 case FUNCTION_STEP_AGAINST_SCALAR:
14543
14544 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14545 glw::GLdouble /* Arg2T */>(
14546 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */,
14547 variable_type /* arg2_type */);
14548
14549 break;
14550
14551 case FUNCTION_TRANSPOSE:
14552
14553 switch (variable_type)
14554 {
14555 case Utils::VARIABLE_TYPE_DMAT2:
14556 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14557 Math::transpose);
14558 break;
14559 case Utils::VARIABLE_TYPE_DMAT2X3:
14560 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14561 Math::transpose);
14562 break;
14563 case Utils::VARIABLE_TYPE_DMAT2X4:
14564 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14565 Math::transpose);
14566 break;
14567 case Utils::VARIABLE_TYPE_DMAT3:
14568 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14569 Math::transpose);
14570 break;
14571 case Utils::VARIABLE_TYPE_DMAT3X2:
14572 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14573 Math::transpose);
14574 break;
14575 case Utils::VARIABLE_TYPE_DMAT3X4:
14576 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14577 Math::transpose);
14578 break;
14579 case Utils::VARIABLE_TYPE_DMAT4:
14580 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14581 Math::transpose);
14582 break;
14583 case Utils::VARIABLE_TYPE_DMAT4X2:
14584 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14585 Math::transpose);
14586 break;
14587 case Utils::VARIABLE_TYPE_DMAT4X3:
14588 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14589 Math::transpose);
14590 break;
14591 default:
14592 break;
14593 }
14594
14595 break;
14596
14597 case FUNCTION_TRUNC:
14598
14599 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14600 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14601
14602 break;
14603
14604 case FUNCTION_UNPACKDOUBLE2X32:
14605
14606 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14607 Math::unpackDouble2x32);
14608
14609 break;
14610
14611 case FUNCTION_ISNAN:
14612
14613 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14614 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14615
14616 break;
14617
14618 case FUNCTION_ISINF:
14619
14620 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14621 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14622
14623 break;
14624
14625 default:
14626 TCU_FAIL("Not implemented");
14627 return 0;
14628 break;
14629 }
14630
14631 TCU_FAIL("Not implemented");
14632 return 0;
14633 }
14634
14635 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14636 *
14637 * @param argument Argument index
14638 * @param function_object Function object
14639 *
14640 * @return Function pointer
14641 **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14642 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14643 glw::GLuint argument, const functionObject& function_object) const
14644 {
14645 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14646 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14647
14648 switch (argument_type)
14649 {
14650 case Utils::VARIABLE_TYPE_DMAT2:
14651 return gl.uniformMatrix2dv;
14652 break;
14653 case Utils::VARIABLE_TYPE_DMAT2X3:
14654 return gl.uniformMatrix2x3dv;
14655 break;
14656 case Utils::VARIABLE_TYPE_DMAT2X4:
14657 return gl.uniformMatrix2x4dv;
14658 break;
14659 case Utils::VARIABLE_TYPE_DMAT3:
14660 return gl.uniformMatrix3dv;
14661 break;
14662 case Utils::VARIABLE_TYPE_DMAT3X2:
14663 return gl.uniformMatrix3x2dv;
14664 break;
14665 case Utils::VARIABLE_TYPE_DMAT3X4:
14666 return gl.uniformMatrix3x4dv;
14667 break;
14668 case Utils::VARIABLE_TYPE_DMAT4:
14669 return gl.uniformMatrix4dv;
14670 break;
14671 case Utils::VARIABLE_TYPE_DMAT4X2:
14672 return gl.uniformMatrix4x2dv;
14673 break;
14674 case Utils::VARIABLE_TYPE_DMAT4X3:
14675 return gl.uniformMatrix4x3dv;
14676 break;
14677 default:
14678 break;
14679 }
14680
14681 TCU_FAIL("Not implemented");
14682 return 0;
14683 }
14684
14685 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14686 *
14687 * @param argument Argument index
14688 * @param function_object Function object
14689 *
14690 * @return Function pointer
14691 **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14692 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14693 glw::GLuint argument, const functionObject& function_object) const
14694 {
14695 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14696 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14697
14698 switch (argument_type)
14699 {
14700 case Utils::VARIABLE_TYPE_DOUBLE:
14701 return gl.uniform1dv;
14702 break;
14703 case Utils::VARIABLE_TYPE_DVEC2:
14704 return gl.uniform2dv;
14705 break;
14706 case Utils::VARIABLE_TYPE_DVEC3:
14707 return gl.uniform3dv;
14708 break;
14709 case Utils::VARIABLE_TYPE_DVEC4:
14710 return gl.uniform4dv;
14711 break;
14712 default:
14713 TCU_FAIL("Not implemented");
14714 break;
14715 }
14716
14717 return 0;
14718 }
14719
14720 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14721 *
14722 * @param argument Argument index
14723 * @param function_object Function object
14724 *
14725 * @return Function pointer
14726 **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14727 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14728 glw::GLuint argument, const functionObject& function_object) const
14729 {
14730 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14731 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14732
14733 switch (argument_type)
14734 {
14735 case Utils::VARIABLE_TYPE_INT:
14736 return gl.uniform1iv;
14737 break;
14738 case Utils::VARIABLE_TYPE_IVEC2:
14739 return gl.uniform2iv;
14740 break;
14741 case Utils::VARIABLE_TYPE_IVEC3:
14742 return gl.uniform3iv;
14743 break;
14744 case Utils::VARIABLE_TYPE_IVEC4:
14745 return gl.uniform4iv;
14746 break;
14747 default:
14748 TCU_FAIL("Not implemented");
14749 break;
14750 }
14751
14752 return 0;
14753 }
14754
14755 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14756 *
14757 * @param argument Argument index
14758 * @param function_object Function object
14759 *
14760 * @return Function pointer
14761 **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14762 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14763 glw::GLuint argument, const functionObject& function_object) const
14764 {
14765 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14766 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14767
14768 switch (argument_type)
14769 {
14770 case Utils::VARIABLE_TYPE_UVEC2:
14771 return gl.uniform2uiv;
14772 break;
14773 default:
14774 TCU_FAIL("Not implemented");
14775 break;
14776 }
14777
14778 return 0;
14779 }
14780
14781 /** Get name of uniform that will be used as <argument>.
14782 *
14783 * @param argument Argument index
14784 *
14785 * @return Name of uniform
14786 **/
getUniformName(glw::GLuint argument) const14787 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14788 {
14789 switch (argument)
14790 {
14791 case 0:
14792 return "uniform_0";
14793 break;
14794 case 1:
14795 return "uniform_1";
14796 break;
14797 case 2:
14798 return "uniform_2";
14799 break;
14800 default:
14801 TCU_FAIL("Not implemented");
14802 return 0;
14803 break;
14804 }
14805 }
14806
14807 /** Get name of varying that will be used as <result>.
14808 *
14809 * @param result Result index
14810 *
14811 * @return Name of varying
14812 **/
getVaryingName(glw::GLuint result) const14813 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14814 {
14815 switch (result)
14816 {
14817 case 0:
14818 return "result_0";
14819 break;
14820 case 1:
14821 return "result_1";
14822 break;
14823 case 2:
14824 return "result_2";
14825 break;
14826 default:
14827 TCU_FAIL("Not implemented");
14828 return 0;
14829 break;
14830 }
14831 }
14832
14833 /** Check if given combination of function and type is implemented
14834 *
14835 * @param function Function enumeration
14836 * @param type Type details
14837 *
14838 * @return true if function is available for given type, false otherwise
14839 **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14840 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14841 {
14842 static const bool look_up_table[][3] = {
14843 /* SCALAR, VECTOR, MATRIX */
14844 /* FUNCTION_ABS: */ { true, true, false },
14845 /* FUNCTION_CEIL: */ { true, true, false },
14846 /* FUNCTION_CLAMP: */ { true, true, false },
14847 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false },
14848 /* FUNCTION_CROSS: */ { false, true, false },
14849 /* FUNCTION_DETERMINANT: */ { false, false, true },
14850 /* FUNCTION_DISTANCE: */ { false, true, false },
14851 /* FUNCTION_DOT: */ { false, true, false },
14852 /* FUNCTION_EQUAL: */ { false, true, false },
14853 /* FUNCTION_FACEFORWARD: */ { false, true, false },
14854 /* FUNCTION_FLOOR: */ { true, true, false },
14855 /* FUNCTION_FMA: */ { true, true, false },
14856 /* FUNCTION_FRACT: */ { true, true, false },
14857 /* FUNCTION_FREXP: */ { true, true, false },
14858 /* FUNCTION_GREATERTHAN: */ { false, true, false },
14859 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false },
14860 /* FUNCTION_INVERSE: */ { false, false, true },
14861 /* FUNCTION_INVERSESQRT: */ { true, true, false },
14862 /* FUNCTION_LDEXP: */ { true, true, false },
14863 /* FUNCTION_LESSTHAN: */ { false, true, false },
14864 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false },
14865 /* FUNCTION_LENGTH: */ { false, true, false },
14866 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true },
14867 /* FUNCTION_MAX: */ { true, true, false },
14868 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false },
14869 /* FUNCTION_MIN: */ { true, true, false },
14870 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false },
14871 /* FUNCTION_MIX: */ { true, true, false },
14872 /* FUNCTION_MOD: */ { true, true, false },
14873 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false },
14874 /* FUNCTION_MODF: */ { true, true, false },
14875 /* FUNCTION_NORMALIZE: */ { false, true, false },
14876 /* FUNCTION_NOTEQUAL: */ { false, true, false },
14877 /* FUNCTION_OUTERPRODUCT: */ { false, false, true },
14878 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false },
14879 /* FUNCTION_REFLECT: */ { false, true, false },
14880 /* FUNCTION_REFRACT: */ { false, true, false },
14881 /* FUNCTION_ROUND: */ { true, true, false },
14882 /* FUNCTION_ROUNDEVEN: */ { true, true, false },
14883 /* FUNCTION_SIGN: */ { true, false, false },
14884 /* FUNCTION_SMOOTHSTEP: */ { true, true, false },
14885 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14886 /* FUNCTION_SQRT: */ { true, true, false },
14887 /* FUNCTION_STEP: */ { true, true, false },
14888 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false },
14889 /* FUNCTION_TRANSPOSE: */ { false, false, false },
14890 /* FUNCTION_TRUNC: */ { true, true, false },
14891 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false },
14892 /* FUNCTION_ISNAN: */ { true, true, false },
14893 /* FUNCTION_ISINF: */ { true, true, false },
14894 };
14895
14896 bool result = look_up_table[function][type.m_general_type];
14897
14898 if (true == result)
14899 {
14900 switch (function)
14901 {
14902 case FUNCTION_CROSS: /* Only 3 element vectors */
14903 result = (3 == type.m_n_rows);
14904 break;
14905 case FUNCTION_DETERMINANT: /* Only square matrices */
14906 case FUNCTION_INVERSE:
14907 result = (type.m_n_columns == type.m_n_rows);
14908 break;
14909 default:
14910 break;
14911 }
14912 }
14913
14914 return result;
14915 }
14916
14917 /** Logs variable of given type: name (type) [values]
14918 *
14919 * @param buffer Source of data
14920 * @param name Name of variable
14921 * @param type Type of variable
14922 **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14923 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14924 Utils::_variable_type type) const
14925 {
14926 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14927 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
14928 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14929
14930 message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14931
14932 for (glw::GLuint component = 0; component < n_components; ++component)
14933 {
14934 if (0 != component)
14935 {
14936 message << ", ";
14937 }
14938
14939 switch (base_type)
14940 {
14941 case Utils::VARIABLE_TYPE_DOUBLE:
14942 message << ((glw::GLdouble*)buffer)[component];
14943 break;
14944 case Utils::VARIABLE_TYPE_INT:
14945 message << ((glw::GLint*)buffer)[component];
14946 break;
14947 case Utils::VARIABLE_TYPE_UINT:
14948 message << ((glw::GLuint*)buffer)[component];
14949 break;
14950 default:
14951 TCU_FAIL("Not implemented");
14952 }
14953 }
14954
14955 message << "]" << tcu::TestLog::EndMessage;
14956 }
14957
14958 /** Prepare input arguments, data are stored in <buffer>
14959 *
14960 * @param function_object Function object
14961 * @param vertex Vertex index
14962 * @param buffer Buffer pointer
14963 **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14964 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14965 glw::GLubyte* buffer)
14966 {
14967 const glw::GLuint n_arguments = function_object.getArgumentCount();
14968
14969 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14970 {
14971 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14972
14973 prepareComponents(function_object, vertex, argument, buffer + offset);
14974 }
14975 }
14976
14977 /** Prepare components for given <function_object>, <vertex> and <argument>
14978 *
14979 * @param function_object Function object
14980 * @param vertex Vertex index
14981 * @param argument Argument index
14982 * @param buffer Buffer pointer
14983 **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14984 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14985 glw::GLuint argument, glw::GLubyte* buffer)
14986 {
14987 glw::GLuint argument_index[3] = { 0 };
14988 glw::GLuint argument_reset[3] = { 0 };
14989 glw::GLuint argument_step[3] = { 0 };
14990 glw::GLdouble double_argument_start[3] = { 0.0 };
14991 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14992 glw::GLuint int_argument_start = -4;
14993 const glw::GLuint n_arguments = function_object.getArgumentCount();
14994 const glw::GLuint n_components = function_object.getArgumentComponents(argument);
14995 glw::GLuint uint_argument_start = 0;
14996
14997 switch (n_arguments)
14998 {
14999 case 1:
15000 argument_step[0] = 1;
15001 argument_reset[0] = 1024;
15002 double_argument_start[0] = -511.5;
15003 break;
15004 case 2:
15005 argument_step[0] = 32;
15006 argument_step[1] = 1;
15007 argument_reset[0] = 32;
15008 argument_reset[1] = 32;
15009 double_argument_start[0] = -15.5;
15010 double_argument_start[1] = -15.5;
15011 break;
15012 case 3:
15013 argument_step[0] = 64;
15014 argument_step[1] = 8;
15015 argument_step[2] = 1;
15016 argument_reset[0] = 16;
15017 argument_reset[1] = 8;
15018 argument_reset[2] = 8;
15019 double_argument_start[0] = -7.5;
15020 double_argument_start[1] = -3.5;
15021 double_argument_start[2] = -3.5;
15022 break;
15023 default:
15024 TCU_FAIL("Not implemented");
15025 return;
15026 break;
15027 };
15028
15029 switch (function_object.getFunctionEnum())
15030 {
15031 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
15032 case FUNCTION_CLAMP_AGAINST_SCALAR:
15033 double_argument_start[2] = 4.5;
15034 break;
15035 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
15036 double_argument_start[0] = 16.5;
15037 break;
15038 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
15039 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
15040 argument_step[0] = 1;
15041 argument_step[1] = 8;
15042 argument_step[2] = 64;
15043 argument_reset[0] = 8;
15044 argument_reset[1] = 8;
15045 argument_reset[2] = 16;
15046 double_argument_start[0] = -3.5;
15047 double_argument_start[1] = 4.5;
15048 double_argument_start[2] = -7.5;
15049 break;
15050 default:
15051 break;
15052 }
15053
15054 for (glw::GLuint i = 0; i < n_arguments; ++i)
15055 {
15056 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
15057 }
15058
15059 switch (base_arg_type)
15060 {
15061 case Utils::VARIABLE_TYPE_DOUBLE:
15062 {
15063 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
15064
15065 double_argument_start[argument] += argument_index[argument];
15066
15067 for (glw::GLuint component = 0; component < n_components; ++component)
15068 {
15069 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
15070
15071 switch (function_object.getFunctionEnum())
15072 {
15073 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
15074 if (0.5 == Math::fract(value))
15075 {
15076 value += 0.01;
15077 }
15078 break;
15079 default:
15080 break;
15081 }
15082
15083 argument_dst[component] = value;
15084 }
15085 }
15086 break;
15087 case Utils::VARIABLE_TYPE_INT:
15088 {
15089 glw::GLint* argument_dst = (glw::GLint*)buffer;
15090
15091 uint_argument_start += argument_index[argument];
15092
15093 for (glw::GLuint component = 0; component < n_components; ++component)
15094 {
15095 const glw::GLint value = int_argument_start + component;
15096
15097 argument_dst[component] = value;
15098 }
15099 }
15100 break;
15101 case Utils::VARIABLE_TYPE_UINT:
15102 {
15103 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
15104
15105 uint_argument_start += argument_index[argument];
15106
15107 for (glw::GLuint component = 0; component < n_components; ++component)
15108 {
15109 const glw::GLuint value = uint_argument_start + component;
15110
15111 argument_dst[component] = value;
15112 }
15113 }
15114 break;
15115 default:
15116 TCU_FAIL("Not implemented");
15117 return;
15118 break;
15119 }
15120 }
15121
15122 /** Prepare programInfo for given functionObject
15123 *
15124 * @param function_object Function object
15125 * @param out_program_info Program info
15126 **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)15127 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
15128 {
15129 const glw::GLuint n_varying_names = function_object.getResultCount();
15130 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
15131
15132 prepareVertexShaderCode(function_object);
15133
15134 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
15135 varying_names, n_varying_names);
15136 }
15137
15138 /** Prepare input data and expected results for given function object
15139 *
15140 * @param function_object Function object
15141 **/
prepareTestData(const functionObject & function_object)15142 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
15143 {
15144 const glw::GLuint result_stride = function_object.getResultStride();
15145 const glw::GLuint result_buffer_size = result_stride * m_n_veritces;
15146 const glw::GLuint argument_stride = function_object.getArgumentStride();
15147 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
15148
15149 m_argument_data.clear();
15150 m_expected_results_data.clear();
15151
15152 m_argument_data.resize(argument_buffer_size);
15153 m_expected_results_data.resize(result_buffer_size);
15154
15155 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15156 {
15157 const glw::GLuint result_offset = vertex * result_stride;
15158 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset];
15159 const glw::GLuint argument_offset = vertex * argument_stride;
15160 glw::GLubyte* argument_dst = &m_argument_data[argument_offset];
15161
15162 prepareArgument(function_object, vertex, argument_dst);
15163 function_object.call(result_dst, argument_dst);
15164 }
15165 }
15166
15167 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
15168 *
15169 * @param function_object Function object
15170 **/
prepareVertexShaderCode(const functionObject & function_object)15171 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
15172 {
15173 static const glw::GLchar* shader_template_code = "#version 400 core\n"
15174 "\n"
15175 "precision highp float;\n"
15176 "\n"
15177 "ARGUMENT_DEFINITION"
15178 "\n"
15179 "RESULT_DEFINITION"
15180 "\n"
15181 "void main()\n"
15182 "{\n"
15183 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
15184 "}\n"
15185 "\n";
15186
15187 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15188 static const glw::GLchar* argument_token = "ARGUMENT";
15189 static const glw::GLchar* function_name_token = "FUNCTION_NAME";
15190 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION";
15191 static const glw::GLchar* result_name_token = "RESULT_NAME";
15192 static const glw::GLchar* result_type_token = "RESULT_TYPE";
15193 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME";
15194 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE";
15195
15196 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15197 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT";
15198 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT";
15199 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15200
15201 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15202 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument);
15203 const glw::GLuint n_arguments = function_object.getArgumentCount();
15204 const glw::GLuint n_results = function_object.getResultCount();
15205 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition);
15206 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0));
15207
15208 size_t search_position = 0;
15209 std::string string = shader_template_code;
15210
15211 /* Replace ARGUMENT_DEFINITION with definitions */
15212 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15213 {
15214 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15215 const glw::GLchar* uniform_name = getUniformName(argument);
15216 std::string uniform_type = Utils::getVariableTypeString(argument_type);
15217
15218 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15219
15220 search_position -= argument_definition_length;
15221
15222 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15223 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15224 }
15225
15226 /* Remove ARGUMENT_DEFINITION */
15227 Utils::replaceToken(argument_definition_token, search_position, "", string);
15228
15229 /* Replace RESULT_DEFINITION with definitions */
15230 for (glw::GLuint result = 0; result < n_results; ++result)
15231 {
15232 Utils::_variable_type variable_type = function_object.getResultType(result);
15233 const glw::GLchar* varying_name = getVaryingName(result);
15234 std::string varying_type = Utils::getVariableTypeString(variable_type);
15235
15236 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15237
15238 search_position -= result_definition_length;
15239
15240 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15241 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15242 }
15243
15244 /* Remove RESULT_DEFINITION */
15245 Utils::replaceToken(result_definition_token, search_position, "", string);
15246
15247 /* Replace RESULT_NAME */
15248 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15249
15250 /* Replace RESULT_TYPE */
15251 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15252
15253 /* Replace FUNCTION_NAME */
15254 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15255
15256 /* Replace ARGUMENT with list of arguments */
15257 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15258 {
15259 const glw::GLchar* uniform_name = getUniformName(argument);
15260
15261 if (0 == argument)
15262 {
15263 Utils::replaceToken(argument_token, search_position, first_argument, string);
15264 }
15265 else
15266 {
15267 Utils::replaceToken(argument_token, search_position, argument_str, string);
15268 }
15269
15270 search_position -= first_argument_length;
15271
15272 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15273 }
15274
15275 for (glw::GLuint result = 1; result < n_results; ++result)
15276 {
15277 const glw::GLchar* varying_name = getVaryingName(result);
15278
15279 Utils::replaceToken(argument_token, search_position, argument_str, string);
15280
15281 search_position -= first_argument_length;
15282
15283 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15284 }
15285
15286 /* Remove ARGUMENT */
15287 Utils::replaceToken(argument_token, search_position, "", string);
15288
15289 m_vertex_shader_code = string;
15290 }
15291
15292 /** Test single function with one type
15293 *
15294 * param function Function enumeration
15295 * param type Type details
15296 *
15297 * @return true if test pass (or function is not available for <type>), false otherwise
15298 **/
test(FunctionEnum function,const typeDetails & type)15299 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15300 {
15301 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15302
15303 /* Skip if function is not implemented for type */
15304 if (false == isFunctionImplemented(function, type))
15305 {
15306 return true;
15307 }
15308
15309 Utils::programInfo program(m_context);
15310 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15311
15312 prepareProgram(*function_object, program);
15313 prepareTestData(*function_object);
15314
15315 /* Set up program */
15316 gl.useProgram(program.m_program_object_id);
15317 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15318
15319 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15320 {
15321 testBegin(*function_object, program.m_program_object_id, vertex);
15322
15323 gl.beginTransformFeedback(GL_POINTS);
15324 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15325
15326 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15327 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15328
15329 gl.endTransformFeedback();
15330 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15331
15332 if (false == verifyResults(*function_object, vertex))
15333 {
15334 return false;
15335 }
15336 }
15337
15338 return true;
15339 }
15340
15341 /** Update transform feedback buffer and uniforms
15342 *
15343 * @param function_object Function object
15344 * @param program_id Program object id
15345 * @param vertex Vertex index
15346 **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15347 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15348 {
15349 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15350 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15351 const glw::GLuint n_arguments = function_object.getArgumentCount();
15352 const glw::GLuint result_buffer_size = function_object.getResultStride();
15353 const glw::GLuint vertex_offset = arguments_stride * vertex;
15354
15355 /* Update transform feedback buffer */
15356 std::vector<glw::GLubyte> transform_feedback_buffer_data;
15357 transform_feedback_buffer_data.resize(result_buffer_size);
15358
15359 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15360 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15361
15362 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15363 GL_DYNAMIC_COPY);
15364 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15365
15366 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15367 result_buffer_size);
15368 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15369
15370 /* Update VAO */
15371 gl.bindVertexArray(m_vertex_array_object_id);
15372 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15373
15374 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15375 {
15376 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15377 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15378 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type);
15379 const glw::GLchar* uniform_name = getUniformName(argument);
15380 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name);
15381 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15382
15383 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15384
15385 if (-1 == uniform_location)
15386 {
15387 TCU_FAIL("Inactive uniform");
15388 }
15389
15390 if (1 == n_columns)
15391 {
15392 switch (Utils::getBaseVariableType(argument_type))
15393 {
15394 case Utils::VARIABLE_TYPE_DOUBLE:
15395 {
15396 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15397
15398 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15399 }
15400 break;
15401 case Utils::VARIABLE_TYPE_UINT:
15402 {
15403 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15404
15405 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15406 }
15407 break;
15408 case Utils::VARIABLE_TYPE_INT:
15409 {
15410 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15411
15412 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15413 }
15414 break;
15415 default:
15416 TCU_FAIL("Not implemented");
15417 break;
15418 }
15419 }
15420 else
15421 {
15422 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15423
15424 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15425 }
15426 }
15427 }
15428
15429 /** Init GL obejcts
15430 *
15431 **/
testInit()15432 void BuiltinFunctionTest::testInit()
15433 {
15434 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15435
15436 gl.genBuffers(1, &m_transform_feedback_buffer_id);
15437 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15438
15439 gl.genVertexArrays(1, &m_vertex_array_object_id);
15440 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15441
15442 gl.enable(GL_RASTERIZER_DISCARD);
15443 }
15444
15445 /** Checks if function result is an acceptable edge case
15446 *
15447 * @param function_object Function object
15448 * @param vertex Vertex index
15449 *
15450 * @return true if all results are as expected, false otherwise
15451 **/
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)15452 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15453 const Utils::_variable_type result_type,
15454 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15455 {
15456 FunctionEnum function_type = function_object.getFunctionEnum();
15457 switch (function_type)
15458 {
15459 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15460 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15461 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15462 case FUNCTION_MOD:
15463 case FUNCTION_MOD_AGAINST_SCALAR:
15464 {
15465 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15466 const glw::GLuint vertex_offset = arguments_stride * vertex;
15467 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0);
15468 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1);
15469 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset;
15470 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset;
15471 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index];
15472 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index];
15473 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15474 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15475 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15476 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src);
15477 bool edge_case_present = false;
15478 bool recheck = false;
15479
15480 // verify if there is a mod(a, a) case and prepare new expected result
15481 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15482 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15483 for (glw::GLuint component = 0; component < n_components; ++component)
15484 {
15485 glw::GLdouble expected_result_component = expected_result[component];
15486 glw::GLdouble actual_result_component = actual_result[component];
15487 glw::GLdouble argument_1_component = argument_1[component];
15488 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15489
15490 // if coresponding components of arguments are equal and if component of first argument
15491 // and component of result are equal then expected result must be corrected
15492 edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) &&
15493 (m_epsilon > de::abs(argument_1_component - actual_result_component));
15494 recheck |= edge_case_present;
15495 corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component;
15496 }
15497
15498 // recheck test result with corrected expected result
15499 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15500 }
15501 default:
15502 return false;
15503 }
15504 }
15505
15506 /** Compare contents of transform feedback buffer with expected results
15507 *
15508 * @param function_object Function object
15509 * @param vertex Vertex index
15510 *
15511 * @return true if all results are as expected, false otherwise
15512 **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15513 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15514 {
15515 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15516 bool test_result = true;
15517 const glw::GLuint n_results = function_object.getResultCount();
15518 const glw::GLuint results_stride = function_object.getResultStride();
15519 const glw::GLuint results_offset = vertex * results_stride;
15520 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset];
15521
15522 /* Get transform feedback data */
15523 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15524 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15525
15526 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15527 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15528
15529 for (glw::GLuint result = 0; result < n_results; ++result)
15530 {
15531 const Utils::_variable_type result_type = function_object.getResultType(result);
15532 const glw::GLuint result_offset = function_object.getResultOffset(result);
15533
15534 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15535 const glw::GLvoid* result_src = feedback_data + result_offset;
15536
15537 if (compare(result_type, expected_result_src, result_src))
15538 continue;
15539
15540 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15541 {
15542 test_result = false;
15543 break;
15544 }
15545 }
15546
15547 /* Unmap transform feedback buffer */
15548 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15549 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15550
15551 if (false == test_result)
15552 {
15553 const glw::GLuint argument_stride = function_object.getArgumentStride();
15554 const glw::GLuint arguments_offset = vertex * argument_stride;
15555
15556 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15557 << tcu::TestLog::EndMessage;
15558
15559 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15560 << tcu::TestLog::EndMessage;
15561
15562 for (glw::GLuint result = 0; result < n_results; ++result)
15563 {
15564 const Utils::_variable_type result_type = function_object.getResultType(result);
15565 const glw::GLuint result_offset = function_object.getResultOffset(result);
15566
15567 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15568 const glw::GLvoid* result_src = feedback_data + result_offset;
15569
15570 logVariableType(result_src, "Result", result_type);
15571 logVariableType(expected_result_src, "Expected result", result_type);
15572 }
15573
15574 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15575 {
15576 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15577 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset];
15578
15579 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15580 }
15581
15582 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15583 << m_vertex_shader_code << tcu::TestLog::EndMessage;
15584 }
15585
15586 return test_result;
15587 }
15588
15589 /** Constructor.
15590 *
15591 * @param context Rendering context.
15592 **/
GPUShaderFP64Tests(deqp::Context & context)15593 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15594 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15595 {
15596 /* Left blank on purpose */
15597 }
15598
15599 /** Initializes a texture_storage_multisample test group.
15600 *
15601 **/
init(void)15602 void GPUShaderFP64Tests::init(void)
15603 {
15604 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15605 fp64->addChild(new GPUShaderFP64Test1(m_context));
15606 fp64->addChild(new GPUShaderFP64Test2(m_context));
15607 fp64->addChild(new GPUShaderFP64Test3(m_context));
15608 fp64->addChild(new GPUShaderFP64Test4(m_context));
15609 fp64->addChild(new GPUShaderFP64Test5(m_context));
15610 fp64->addChild(new GPUShaderFP64Test6(m_context));
15611 fp64->addChild(new GPUShaderFP64Test7(m_context));
15612 fp64->addChild(new GPUShaderFP64Test8(m_context));
15613 fp64->addChild(new GPUShaderFP64Test9(m_context));
15614 addChild(fp64);
15615
15616 TypeDefinition typeDefinition[] =
15617 {
15618 { "double", 1, 1 },
15619 { "dvec2", 1, 2 },
15620 { "dvec3", 1, 3 },
15621 { "dvec4", 1, 4 },
15622 { "dmat2", 2, 2 },
15623 { "dmat2x3", 2, 3 },
15624 { "dmat2x4", 2, 4 },
15625 { "dmat3x2", 3, 2 },
15626 { "dmat3", 3, 3 },
15627 { "dmat3x4", 3, 4 },
15628 { "dmat4x2", 4, 2 },
15629 { "dmat4x3", 4, 3 },
15630 { "dmat4", 4, 4 }
15631 };
15632
15633 struct BuiltinFunctions
15634 {
15635 std::string name;
15636 FunctionEnum function;
15637 } builtinFunctions[] = {
15638 { "abs", FUNCTION_ABS },
15639 { "ceil", FUNCTION_CEIL },
15640 { "clamp", FUNCTION_CLAMP },
15641 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR },
15642 { "cross", FUNCTION_CROSS },
15643 { "determinant", FUNCTION_DETERMINANT },
15644 { "distance", FUNCTION_DISTANCE },
15645 { "dot", FUNCTION_DOT },
15646 { "equal", FUNCTION_EQUAL },
15647 { "faceforward", FUNCTION_FACEFORWARD },
15648 { "floor", FUNCTION_FLOOR },
15649 { "fma", FUNCTION_FMA },
15650 { "fract", FUNCTION_FRACT },
15651 { "frexp", FUNCTION_FREXP },
15652 { "greaterthan", FUNCTION_GREATERTHAN },
15653 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL },
15654 { "inverse", FUNCTION_INVERSE },
15655 { "inversesqrt", FUNCTION_INVERSESQRT },
15656 { "ldexp", FUNCTION_LDEXP },
15657 { "lessthan", FUNCTION_LESSTHAN },
15658 { "lessthanequal", FUNCTION_LESSTHANEQUAL },
15659 { "length", FUNCTION_LENGTH },
15660 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT },
15661 { "max", FUNCTION_MAX },
15662 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR },
15663 { "min", FUNCTION_MIN },
15664 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR },
15665 { "mix", FUNCTION_MIX },
15666 { "mod", FUNCTION_MOD },
15667 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR },
15668 { "modf", FUNCTION_MODF },
15669 { "normalize", FUNCTION_NORMALIZE },
15670 { "notequal", FUNCTION_NOTEQUAL },
15671 { "outerproduct", FUNCTION_OUTERPRODUCT },
15672 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 },
15673 { "reflect", FUNCTION_REFLECT },
15674 { "refract", FUNCTION_REFRACT },
15675 { "round", FUNCTION_ROUND },
15676 { "roundeven", FUNCTION_ROUNDEVEN },
15677 { "sign", FUNCTION_SIGN },
15678 { "smoothstep", FUNCTION_SMOOTHSTEP },
15679 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15680 { "sqrt", FUNCTION_SQRT },
15681 { "step", FUNCTION_STEP },
15682 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR },
15683 { "transpose", FUNCTION_TRANSPOSE },
15684 { "trunc", FUNCTION_TRUNC },
15685 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 },
15686 { "isnan", FUNCTION_ISNAN },
15687 { "isinf", FUNCTION_ISINF }
15688 };
15689
15690 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15691 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15692 {
15693 const BuiltinFunctions& bf = builtinFunctions[i];
15694 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15695 {
15696 std::string caseName = bf.name + "_" + typeDefinition[j].name;
15697 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15698 }
15699 }
15700 addChild(builin);
15701 }
15702
15703 } /* glcts namespace */
15704