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
3399 default:
3400 return GL_NONE;
3401 }
3402 }
3403
3404 /** Get primitive type drawn with DrawArrays
3405 *
3406 * @param shader_stage Tested shader stage id
3407 *
3408 * @return Primitive type
3409 **/
getDrawPrimitiveType(shaderStage shader_stage) const3410 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3411 {
3412 switch (shader_stage)
3413 {
3414 case FRAGMENT_SHADER:
3415 return GL_TRIANGLE_FAN;
3416
3417 case GEOMETRY_SHADER:
3418 case VERTEX_SHADER:
3419 return GL_POINTS;
3420
3421 case TESS_CTRL_SHADER:
3422 case TESS_EVAL_SHADER:
3423 return GL_PATCHES;
3424
3425 default:
3426 return GL_NONE;
3427 }
3428 }
3429
3430 /** Get maximum allowed number of uniform components
3431 *
3432 * @param shader_stage Tested shader stage id
3433 *
3434 * @return Maxmimum uniform components
3435 **/
getMaxUniformComponents(shaderStage shader_stage) const3436 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3437 {
3438 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3439 glw::GLint max_uniform_components = 0;
3440 glw::GLenum pname = 0;
3441
3442 switch (shader_stage)
3443 {
3444 case COMPUTE_SHADER:
3445 pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3446 break;
3447 case FRAGMENT_SHADER:
3448 pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3449 break;
3450 case GEOMETRY_SHADER:
3451 pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3452 break;
3453 case TESS_CTRL_SHADER:
3454 pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3455 break;
3456 case TESS_EVAL_SHADER:
3457 pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3458 break;
3459 case VERTEX_SHADER:
3460 pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3461 break;
3462 }
3463
3464 gl.getIntegerv(pname, &max_uniform_components);
3465 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3466
3467 return max_uniform_components;
3468 }
3469
3470 /** Get maximum size allowed for an uniform block
3471 *
3472 * @return Maxmimum uniform block size
3473 **/
getMaxUniformBlockSize() const3474 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3475 {
3476 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3477 glw::GLint max_uniform_block_size = 0;
3478
3479 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3480 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3481
3482 return max_uniform_block_size;
3483 }
3484
3485 /** Get number of components required to store single uniform of given type
3486 *
3487 * @param uniform_type Tested uniform type
3488 *
3489 * @return Number of components
3490 **/
getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const3491 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3492 {
3493 static const glw::GLuint type_size = 2; /* double takes 2 N */
3494 const glw::GLuint column_length = uniform_type.m_n_rows;
3495
3496 if (1 == uniform_type.m_n_columns)
3497 {
3498 return type_size * column_length;
3499 }
3500 else
3501 {
3502 const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3503
3504 return alignment * uniform_type.m_n_columns;
3505 }
3506 }
3507
3508 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3509 *
3510 * @param uniform_type Tested uniform type
3511 *
3512 * @return Size of a single member
3513 **/
getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const3514 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3515 {
3516 static const glw::GLuint vec4_size = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3517 const glw::GLuint column_length = uniform_type.m_n_rows;
3518
3519 /** Size for a layout(std140, column_major) uniform_type uniform[] **/
3520 return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3521 }
3522
3523 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3524 *
3525 * @param shader_stage Tested shader stage id
3526 * @param uniform_type Tested uniform type
3527 *
3528 * @return Number of components
3529 **/
getAmountUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const3530 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage shader_stage,
3531 const uniformTypeDetails& uniform_type) const
3532 {
3533 const glw::GLuint max_uniform_components = getMaxUniformComponents(shader_stage);
3534 const glw::GLuint required_components = getRequiredComponentsNumber(uniform_type);
3535 const glw::GLuint n_uniforms = max_uniform_components / required_components;
3536 const glw::GLuint max_uniform_block_size = getMaxUniformBlockSize();
3537 const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3538 const glw::GLuint max_uniforms = max_uniform_block_size / uniform_type_member_size;
3539
3540 return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3541 }
3542
3543 /** Get name of shader stage
3544 *
3545 * @param shader_stage Tested shader stage id
3546 *
3547 * @return Name
3548 **/
getShaderStageName(shaderStage shader_stage) const3549 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3550 {
3551 switch (shader_stage)
3552 {
3553 case COMPUTE_SHADER:
3554 return "compute shader";
3555 case FRAGMENT_SHADER:
3556 return "fragment shader";
3557 case GEOMETRY_SHADER:
3558 return "geometry shader";
3559 case TESS_CTRL_SHADER:
3560 return "tesselation control shader";
3561 case TESS_EVAL_SHADER:
3562 return "tesselation evaluation shader";
3563 case VERTEX_SHADER:
3564 return "vertex shader";
3565 }
3566
3567 return 0;
3568 }
3569
3570 /** Inspect program to get: buffer_size, offset, strides and block index
3571 *
3572 * @param program_id Program id
3573 * @param out_buffer_size Size of uniform buffer
3574 * @param out_uniform_details Uniform offset and strides
3575 * @param uniform_block_index Uniform block index
3576 **/
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) const3577 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3578 const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3579 uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const
3580 {
3581 glw::GLint array_stride = 0;
3582 std::vector<glw::GLchar> extracted_uniform_name;
3583 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3584 glw::GLuint index = 0;
3585 glw::GLint matrix_stride = 0;
3586 glw::GLint offset = 0;
3587 glw::GLsizei size = 0;
3588 glw::GLenum type = 0;
3589 const glw::GLchar* uniform_name = 0;
3590 std::string uniform_name_str;
3591 std::stringstream uniform_name_stream;
3592
3593 /* Get index of uniform block */
3594 uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3595 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3596
3597 if (GL_INVALID_INDEX == uniform_block_index)
3598 {
3599 TCU_FAIL("Unifom block is inactive");
3600 }
3601
3602 /* Get size of uniform block */
3603 gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3604 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3605
3606 if (0 == out_buffer_size)
3607 {
3608 TCU_FAIL("Unifom block size is 0");
3609 }
3610
3611 /* Prepare uniform name */
3612 uniform_name_stream << "uniform_array";
3613
3614 uniform_name_str = uniform_name_stream.str();
3615 uniform_name = uniform_name_str.c_str();
3616
3617 /* Get index of uniform */
3618 gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3619 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3620
3621 if (GL_INVALID_INDEX == index)
3622 {
3623 TCU_FAIL("Unifom is inactive");
3624 }
3625
3626 /* Verify getActiveUniform results */
3627 extracted_uniform_name.resize(uniform_name_str.length() * 2);
3628
3629 gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3630 &extracted_uniform_name[0]);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3632
3633 if ((n_uniforms != size) || (uniform_type.m_type != type))
3634 {
3635 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3636 << " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3637 << " expected: " << uniform_type.m_type
3638 << ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3639
3640 TCU_FAIL("Invalid GetActiveUniform results");
3641 }
3642
3643 /* Get offset of uniform */
3644 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3645 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3646
3647 if (-1 == offset)
3648 {
3649 TCU_FAIL("Unifom has invalid offset");
3650 }
3651
3652 out_uniform_details.m_offset = offset;
3653
3654 /* Get matrix stride of uniform */
3655 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3656 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3657
3658 if (-1 == matrix_stride)
3659 {
3660 TCU_FAIL("Unifom has invalid matrix stride");
3661 }
3662
3663 out_uniform_details.m_matrix_stride = matrix_stride;
3664
3665 /* Get array stride of uniform */
3666 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3667 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3668
3669 if (-1 == matrix_stride)
3670 {
3671 TCU_FAIL("Unifom has invalid matrix stride");
3672 }
3673
3674 out_uniform_details.m_array_stride = array_stride;
3675 }
3676
3677 /** Prepare source code for "boilerplate" shaders
3678 *
3679 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3680 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3681 * @param out_source_code Source code
3682 **/
prepareBoilerplateShader(const glw::GLchar* stage_specific_layout, const glw::GLchar* stage_specific_main_body, std::string& out_source_code) const3683 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3684 const glw::GLchar* stage_specific_main_body,
3685 std::string& out_source_code) const
3686 {
3687 /* Shader template */
3688 static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3689 "\n"
3690 "precision highp float;\n"
3691 "\n"
3692 "STAGE_SPECIFIC_LAYOUT"
3693 "void main()\n"
3694 "{\n"
3695 "STAGE_SPECIFIC_MAIN_BODY"
3696 "}\n"
3697 "\n";
3698
3699 std::string string = boilerplate_shader_template_code;
3700
3701 /* Tokens */
3702 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
3703 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3704
3705 size_t search_position = 0;
3706
3707 /* Replace tokens */
3708 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3709 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3710
3711 /* Store resuls */
3712 out_source_code = string;
3713 }
3714
3715 /** Prepare program for given combination of shader stage and uniform type
3716 *
3717 * @param shader_stage Shader stage
3718 * @param uniform_type Uniform type
3719 * @param out_program_info Instance of programInfo
3720 **/
prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type, Utils::programInfo& out_program_info) const3721 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3722 Utils::programInfo& out_program_info) const
3723 {
3724 /* Stage specific layouts */
3725 static const glw::GLchar* geometry_shader_layout_code = "layout(points) in;\n"
3726 "layout(points, max_vertices = 1) out;\n"
3727 "\n";
3728
3729 static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3730 "\n";
3731
3732 static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3733 "\n";
3734
3735 /* Stage specific main body */
3736 static const glw::GLchar* boilerplate_fragment_shader_body_code = " discard;\n";
3737
3738 static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = " gl_TessLevelOuter[0] = 1.0;\n"
3739 " gl_TessLevelOuter[1] = 1.0;\n"
3740 " gl_TessLevelOuter[2] = 1.0;\n"
3741 " gl_TessLevelOuter[3] = 1.0;\n"
3742 " gl_TessLevelInner[0] = 1.0;\n"
3743 " gl_TessLevelInner[1] = 1.0;\n";
3744
3745 static const glw::GLchar* boilerplate_vertex_shader_body_code = " gl_Position = vec4(1, 0, 0, 1);\n";
3746
3747 static const glw::GLchar* corner_vertex_shader_body_code = " if (0 == gl_VertexID)\n"
3748 " {\n"
3749 " gl_Position = vec4(-1, -1, 0, 1);\n"
3750 " }\n"
3751 " else if (1 == gl_VertexID)\n"
3752 " {\n"
3753 " gl_Position = vec4(-1, 1, 0, 1);\n"
3754 " }\n"
3755 " else if (2 == gl_VertexID)\n"
3756 " {\n"
3757 " gl_Position = vec4(1, 1, 0, 1);\n"
3758 " }\n"
3759 " else if (3 == gl_VertexID)\n"
3760 " {\n"
3761 " gl_Position = vec4(1, -1, 0, 1);\n"
3762 " }\n";
3763
3764 static const glw::GLchar* passthrough_tess_eval_shader_body_code = " result = tcs_tes_result[0];\n";
3765
3766 static const glw::GLchar* test_shader_body_code = "\n result = verification_result;\n";
3767
3768 static const glw::GLchar* test_geometry_shader_body_code = "\n result = verification_result;\n"
3769 "\n"
3770 " EmitVertex();\n"
3771 " EndPrimitive();\n";
3772
3773 static const glw::GLchar* test_tess_ctrl_shader_body_code =
3774 "\n tcs_tes_result[gl_InvocationID] = verification_result;\n"
3775 "\n"
3776 " gl_TessLevelOuter[0] = 1.0;\n"
3777 " gl_TessLevelOuter[1] = 1.0;\n"
3778 " gl_TessLevelOuter[2] = 1.0;\n"
3779 " gl_TessLevelOuter[3] = 1.0;\n"
3780 " gl_TessLevelInner[0] = 1.0;\n"
3781 " gl_TessLevelInner[1] = 1.0;\n";
3782
3783 /* In variables */
3784 static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in int tcs_tes_result[];\n";
3785
3786 /* Out variables */
3787 static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3788
3789 static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3790
3791 static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3792
3793 /* Varying name */
3794 static const glw::GLchar* varying_name = "result";
3795 glw::GLuint n_varyings = 1;
3796
3797 /* Storage for ready shaders */
3798 std::string compute_shader_code;
3799 std::string fragment_shader_code;
3800 std::string geometry_shader_code;
3801 std::string tess_ctrl_shader_code;
3802 std::string tess_eval_shader_code;
3803 std::string vertex_shader_code;
3804
3805 /* Storage for uniform definition and verification code */
3806 std::string uniform_definitions;
3807 std::string uniform_verification;
3808
3809 /* Get uniform definition and verification code */
3810 prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3811 prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3812
3813 /* Prepare vertex shader */
3814 switch (shader_stage)
3815 {
3816 case FRAGMENT_SHADER:
3817
3818 prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3819
3820 break;
3821
3822 case GEOMETRY_SHADER:
3823 case TESS_CTRL_SHADER:
3824 case TESS_EVAL_SHADER:
3825
3826 prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3827
3828 break;
3829
3830 case VERTEX_SHADER:
3831
3832 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3833 test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3834 test_shader_body_code /* body */, vertex_shader_code);
3835
3836 break;
3837
3838 default:
3839 break;
3840 }
3841
3842 /* Prepare fragment shader */
3843 switch (shader_stage)
3844 {
3845 case FRAGMENT_SHADER:
3846
3847 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3848 test_fragment_shader_out_variable /* out var */,
3849 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3850 fragment_shader_code);
3851
3852 break;
3853
3854 case GEOMETRY_SHADER:
3855 case TESS_CTRL_SHADER:
3856 case TESS_EVAL_SHADER:
3857 case VERTEX_SHADER:
3858
3859 prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3860 fragment_shader_code);
3861
3862 break;
3863
3864 default:
3865 break;
3866 }
3867
3868 /* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3869 switch (shader_stage)
3870 {
3871 case COMPUTE_SHADER:
3872
3873 prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3874
3875 break;
3876
3877 case GEOMETRY_SHADER:
3878
3879 prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3880 "" /* in var */, test_shader_out_variable /* out var */,
3881 uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3882 geometry_shader_code);
3883
3884 break;
3885
3886 case TESS_CTRL_SHADER:
3887
3888 prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3889 "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3890 uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3891 tess_ctrl_shader_code);
3892
3893 prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3894 test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3895 "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3896 tess_eval_shader_code);
3897
3898 break;
3899
3900 case TESS_EVAL_SHADER:
3901
3902 prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3903 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3904
3905 prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3906 "" /* in var */, test_shader_out_variable /* out var */,
3907 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3908 tess_eval_shader_code);
3909
3910 break;
3911
3912 default:
3913 break;
3914 }
3915
3916 /* Select shaders that will be used by program */
3917 const glw::GLchar* cs_c_str = 0;
3918 const glw::GLchar* fs_c_str = 0;
3919 const glw::GLchar* gs_c_str = 0;
3920 const glw::GLchar* tcs_c_str = 0;
3921 const glw::GLchar* tes_c_str = 0;
3922 const glw::GLchar* vs_c_str = 0;
3923
3924 if (false == compute_shader_code.empty())
3925 {
3926 cs_c_str = compute_shader_code.c_str();
3927 }
3928
3929 if (false == fragment_shader_code.empty())
3930 {
3931 fs_c_str = fragment_shader_code.c_str();
3932 }
3933
3934 if (false == geometry_shader_code.empty())
3935 {
3936 gs_c_str = geometry_shader_code.c_str();
3937 }
3938
3939 if (false == tess_ctrl_shader_code.empty())
3940 {
3941 tcs_c_str = tess_ctrl_shader_code.c_str();
3942 }
3943
3944 if (false == tess_eval_shader_code.empty())
3945 {
3946 tes_c_str = tess_eval_shader_code.c_str();
3947 }
3948
3949 if (false == vertex_shader_code.empty())
3950 {
3951 vs_c_str = vertex_shader_code.c_str();
3952 }
3953
3954 /* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3955 if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3956 {
3957 n_varyings = 0;
3958 }
3959
3960 /* Build */
3961 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);
3962 }
3963
3964 /** Prepare collection of tested shader stages
3965 *
3966 */
prepareShaderStages()3967 void GPUShaderFP64Test2::prepareShaderStages()
3968 {
3969 /* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3970 if (0 != m_pDispatchCompute)
3971 {
3972 m_shader_stages.push_back(COMPUTE_SHADER);
3973 }
3974
3975 m_shader_stages.push_back(FRAGMENT_SHADER);
3976 m_shader_stages.push_back(GEOMETRY_SHADER);
3977 m_shader_stages.push_back(TESS_CTRL_SHADER);
3978 m_shader_stages.push_back(TESS_EVAL_SHADER);
3979 m_shader_stages.push_back(VERTEX_SHADER);
3980 }
3981
3982 /** Prepare source code for "tested" shader stage
3983 *
3984 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3985 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
3986 * @param in_variable_definitions String that will replace IN_VARIABLE_DEFINITION token
3987 * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
3988 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
3989 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3990 * @param out_source_code Shader source code
3991 **/
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) const3992 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
3993 const glw::GLchar* uniform_definitions,
3994 const glw::GLchar* in_variable_definitions,
3995 const glw::GLchar* out_variable_definitions,
3996 const glw::GLchar* uniform_verification,
3997 const glw::GLchar* stage_specific_main_body,
3998 std::string& out_source_code) const
3999 {
4000 /* Shader template */
4001 static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4002 "\n"
4003 "precision highp float;\n"
4004 "\n"
4005 "STAGE_SPECIFIC_LAYOUT"
4006 "UNIFORM_DEFINITIONS"
4007 "IN_VARIABLE_DEFINITION"
4008 "OUT_VARIABLE_DEFINITION"
4009 "\n"
4010 "void main()\n"
4011 "{\n"
4012 "UNIFORM_VERIFICATION"
4013 "STAGE_SPECIFIC_MAIN_BODY"
4014 "}\n"
4015 "\n";
4016
4017 std::string string = test_shader_template_code;
4018
4019 /* Tokens */
4020 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
4021 static const glw::GLchar* in_var_token = "IN_VARIABLE_DEFINITION";
4022 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
4023 static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4024 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4025 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4026
4027 size_t search_position = 0;
4028
4029 /* Replace tokens */
4030 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4031 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4032 Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4033 Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4034 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4035 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4036
4037 /* Store resuls */
4038 out_source_code = string;
4039 }
4040
4041 /** Prepare source code for "tested" compute shaders
4042 *
4043 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
4044 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4045 * @param out_source_code Source code
4046 **/
prepareTestComputeShader(const glw::GLchar* uniform_definitions, const glw::GLchar* uniform_verification, std::string& out_source_code) const4047 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4048 const glw::GLchar* uniform_verification,
4049 std::string& out_source_code) const
4050 {
4051 /* Shader template */
4052 static const glw::GLchar* test_shader_template_code =
4053 "#version 420 core\n"
4054 "#extension GL_ARB_compute_shader : require\n"
4055 "#extension GL_ARB_shader_image_load_store : require\n"
4056 "\n"
4057 "precision highp float;\n"
4058 "\n"
4059 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4060 "\n"
4061 "UNIFORM_DEFINITIONS"
4062 "layout(r32i) writeonly uniform iimage2D result;\n"
4063 "\n"
4064 "void main()\n"
4065 "{\n"
4066 "UNIFORM_VERIFICATION"
4067 "\n"
4068 " imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4069 "}\n"
4070 "\n";
4071
4072 std::string string = test_shader_template_code;
4073
4074 /* Tokens */
4075 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4076 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4077
4078 size_t search_position = 0;
4079
4080 /* Replace tokens */
4081 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4082 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083
4084 /* Store resuls */
4085 out_source_code = string;
4086 }
4087
4088 /** Prepare source code which defines uniforms for tested shader stage
4089 *
4090 * @param shader_stage Shader stage id
4091 * @param uniform_type Details of uniform type
4092 * @param out_source_code Source code
4093 **/
prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type, std::string& out_source_code) const4094 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4095 std::string& out_source_code) const
4096 {
4097 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4098 std::stringstream stream;
4099
4100 /*
4101 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4102 * {
4103 * TYPE_NAME uniform_array[N_UNIFORMS];
4104 * };
4105 */
4106 stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4107 "{\n";
4108
4109 stream << " " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4110
4111 stream << "};\n\n";
4112
4113 out_source_code = stream.str();
4114 }
4115
4116 /** Prepare uniform buffer for test
4117 *
4118 * @param shader_stage Shader stage id
4119 * @param uniform_type Details of uniform type
4120 * @param program_info Program object info
4121 **/
prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type, const Utils::programInfo& program_info) const4122 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4123 const Utils::programInfo& program_info) const
4124 {
4125 glw::GLint buffer_size = 0;
4126 glw::GLuint element_ordinal = 1;
4127 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4128 const glw::GLuint n_columns = uniform_type.m_n_columns;
4129 const glw::GLuint n_rows = uniform_type.m_n_rows;
4130 const glw::GLuint n_elements = n_columns * n_rows;
4131 uniformDetails uniform_details;
4132 const glw::GLuint program_id = program_info.m_program_object_id;
4133 const glw::GLint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4134 std::vector<glw::GLubyte> uniform_buffer_data;
4135 glw::GLuint uniform_block_index = 0;
4136
4137 /* Get uniform details */
4138 inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4139
4140 /* Uniform offset and strides */
4141 const glw::GLuint array_stride = uniform_details.m_array_stride;
4142 const glw::GLuint matrix_stride = uniform_details.m_matrix_stride;
4143 const glw::GLuint uniform_offset = uniform_details.m_offset;
4144
4145 /* Prepare storage for buffer data */
4146 uniform_buffer_data.resize(buffer_size);
4147
4148 /* Prepare uniform data */
4149 for (glw::GLint i = 0; i < n_uniforms; ++i)
4150 {
4151 const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4152
4153 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4154 {
4155 const glw::GLuint column = element / n_rows;
4156 const glw::GLuint column_elem = element % n_rows;
4157 const glw::GLdouble value = element_ordinal;
4158 const glw::GLuint value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4159 column_elem * sizeof(glw::GLdouble));
4160 glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4161
4162 *value_dst = value;
4163 }
4164 }
4165
4166 /* Update uniform buffer with new set of data */
4167 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4168 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4169
4170 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4171 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4172
4173 /* Bind uniform block to uniform buffer */
4174 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4175 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4176
4177 gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4178 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4179 }
4180
4181 /** Prepare collection of tested uniform types
4182 *
4183 **/
prepareUniformTypes()4184 void GPUShaderFP64Test2::prepareUniformTypes()
4185 {
4186 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4187 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4188 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4189 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4190 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4191 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4192 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4193 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4194 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4195 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4196 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4197 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4198 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4199 }
4200
4201 /** Prepare source code that verifes uniform values
4202 *
4203 * @param shader_stage Shader stage id
4204 * @param uniform_type Details of uniform type
4205 * @param out_source_code Source code
4206 **/
prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type, std::string& out_source_code) const4207 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4208 std::string& out_source_code) const
4209 {
4210 glw::GLuint element_ordinal = 1;
4211 const glw::GLuint n_columns = uniform_type.m_n_columns;
4212 const glw::GLuint n_rows = uniform_type.m_n_rows;
4213 const glw::GLuint n_elements = n_columns * n_rows;
4214 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4215 std::stringstream stream;
4216
4217 /*
4218 * int verification_result = M_RESULT_SUCCESS;
4219 *
4220 * for (int i = 0; i < N_UNIFORMS; ++i)
4221 * {
4222 * if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4223 * {
4224 * verification_result = M_RESULT_FAILURE
4225 * }
4226 * }
4227 */
4228 stream << " int verification_result = " << m_result_success << ";\n"
4229 "\n"
4230 " for (int i = 0; i < "
4231 << n_uniforms << "; ++i)\n"
4232 " {\n"
4233 " if ("
4234 << uniform_type.m_type_name << "(";
4235
4236 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4237 {
4238 stream << "i * (" << n_elements << ") + " << element + 1;
4239
4240 if (n_elements != element + 1)
4241 {
4242 stream << ", ";
4243 }
4244 }
4245
4246 stream << ") != uniform_array[i])\n"
4247 " {\n"
4248 " verification_result = "
4249 << m_result_failure << ";\n"
4250 " }\n"
4251 " }\n";
4252
4253 out_source_code = stream.str();
4254 }
4255
4256 /** Execute test for given combination of "tested" shader stage and uniform type
4257 *
4258 * @param shader_stage Tested shader stage id
4259 * @param uniform_type Tested uniform type
4260 *
4261 * @return true if test passed, false otherwise
4262 **/
test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const4263 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4264 {
4265 const glw::GLenum draw_primitive = getDrawPrimitiveType(shader_stage);
4266 static const glw::GLint first_vertex = 0;
4267 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4268 const glw::GLsizei n_vertices = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4269 Utils::programInfo program_info(m_context);
4270 bool result = true;
4271
4272 /* Prepare program */
4273 prepareProgram(shader_stage, uniform_type, program_info);
4274
4275 gl.useProgram(program_info.m_program_object_id);
4276 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4277
4278 /* Prepare uniform buffer and bind it with uniform block */
4279 prepareUniforms(shader_stage, uniform_type, program_info);
4280
4281 /* Prepare storage for test results */
4282 testBegin(program_info.m_program_object_id, shader_stage);
4283
4284 /* Execute */
4285 if (COMPUTE_SHADER == shader_stage)
4286 {
4287 m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4288 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4289 }
4290 else
4291 {
4292 gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4293 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4294 }
4295
4296 /* Clean after test */
4297 testEnd(shader_stage);
4298
4299 /* Check results */
4300 if (false == verifyResults(shader_stage))
4301 {
4302 m_context.getTestContext().getLog()
4303 << tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4304 << ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4305
4306 result = false;
4307 }
4308
4309 return result;
4310 }
4311
4312 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4313 *
4314 * @param program_id Program object id
4315 * @param shader_stage Tested shader stage id
4316 **/
testBegin(glw::GLuint program_id, shaderStage shader_stage) const4317 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4318 {
4319 std::vector<glw::GLint> buffer_data;
4320 const glw::GLenum captured_primitive = getCapturedPrimitiveType(shader_stage);
4321 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4322
4323 /* Prepare buffer filled with m_result_failure */
4324 buffer_data.resize(m_n_captured_results);
4325 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4326 {
4327 buffer_data[i] = m_result_failure;
4328 }
4329
4330 /* Prepare buffer for test results */
4331 switch (shader_stage)
4332 {
4333 case GEOMETRY_SHADER:
4334 case TESS_CTRL_SHADER:
4335 case TESS_EVAL_SHADER:
4336 case VERTEX_SHADER:
4337
4338 /* Verify getTransformFeedbackVarying results */
4339 {
4340 glw::GLsizei size = 0;
4341 glw::GLenum type = 0;
4342 glw::GLchar name[16];
4343
4344 gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4345 name);
4346 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4347
4348 if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4349 {
4350 m_context.getTestContext().getLog()
4351 << tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4352 << " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4353 << ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4354
4355 TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4356 }
4357 }
4358
4359 /* Create/clean transform feedback buffer */
4360 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4361 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4362
4363 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4364 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4365
4366 /* Set up transform feedback buffer */
4367 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4368 m_transform_feedback_buffer_size);
4369 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4370
4371 gl.beginTransformFeedback(captured_primitive);
4372 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4373
4374 break;
4375
4376 case FRAGMENT_SHADER:
4377
4378 /* Clean texture */
4379 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4380 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4381
4382 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4383 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4384 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4385
4386 /* Set up texture as color attachment 0 */
4387 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4388 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4389
4390 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4391 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4392
4393 gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4394 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4395
4396 break;
4397
4398 case COMPUTE_SHADER:
4399
4400 /* Clean texture */
4401 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4402 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4403
4404 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4405 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4406 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4407
4408 glw::GLint location = gl.getUniformLocation(program_id, "result");
4409 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4410
4411 if (-1 == location)
4412 {
4413 TCU_FAIL("Inactive uniform \"result\"");
4414 }
4415
4416 gl.uniform1i(location, 0 /* first image unit */);
4417 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4418
4419 /* Bind texture to first image unit */
4420 gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4421 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4422 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4423
4424 break;
4425 }
4426 }
4427
4428 /** Unbind transform feedback buffer, framebuffer or image unit
4429 *
4430 * @param shader_stage Tested shader stage id
4431 **/
testEnd(shaderStage shader_stage) const4432 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4433 {
4434 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4435
4436 switch (shader_stage)
4437 {
4438 case GEOMETRY_SHADER:
4439 case TESS_CTRL_SHADER:
4440 case TESS_EVAL_SHADER:
4441 case VERTEX_SHADER:
4442
4443 gl.endTransformFeedback();
4444
4445 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4446
4447 break;
4448
4449 case FRAGMENT_SHADER:
4450
4451 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4452 0 /* level */);
4453
4454 gl.bindTexture(GL_TEXTURE_2D, 0);
4455
4456 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4457
4458 break;
4459
4460 case COMPUTE_SHADER:
4461
4462 gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4463 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4464
4465 break;
4466 }
4467 }
4468
4469 /** Initialize OpenGL objects for test
4470 *
4471 **/
testInit()4472 void GPUShaderFP64Test2::testInit()
4473 {
4474 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4475
4476 /* The test is in 4.0 group. However:
4477 * - compute_shader is core since 4.3
4478 * - compute_shader require at least version 4.2 of GL */
4479 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4480 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4481 {
4482 m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4483 }
4484
4485 /* Tesselation patch set up */
4486 gl.patchParameteri(GL_PATCH_VERTICES, 1);
4487 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4488
4489 /* Generate FBO */
4490 gl.genFramebuffers(1, &m_framebuffer_id);
4491 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4492
4493 /* Prepare texture */
4494 gl.genTextures(1, &m_texture_id);
4495 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4496
4497 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4498 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4499
4500 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4501 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4502
4503 /* Prepare transform feedback buffer */
4504 gl.genBuffers(1, &m_transform_feedback_buffer_id);
4505 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4506
4507 /* Generate uniform buffer */
4508 gl.genBuffers(1, &m_uniform_buffer_id);
4509 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4510
4511 /* Prepare VAO */
4512 gl.genVertexArrays(1, &m_vertex_array_object_id);
4513 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4514
4515 gl.bindVertexArray(m_vertex_array_object_id);
4516 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4517 }
4518
4519 /** Result verification, expected result is that whole buffer is filled with m_result_success
4520 *
4521 * @param shader_stage Tested shader stage id
4522 **/
verifyResults(shaderStage shader_stage) const4523 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4524 {
4525 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4526
4527 if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4528 {
4529 /* Verify contents of texture */
4530
4531 /* Prepare storage for testure data */
4532 std::vector<glw::GLint> image_data;
4533 image_data.resize(m_texture_width * m_texture_height);
4534
4535 /* Get texture contents */
4536 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4537 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4538
4539 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4540 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4541
4542 for (glw::GLuint y = 0; y < m_texture_width; ++y)
4543 {
4544 for (glw::GLuint x = 0; x < m_texture_height; ++x)
4545 {
4546 const glw::GLuint offset = y * m_texture_width + x;
4547 const glw::GLint value = image_data[offset];
4548
4549 if (m_result_success != value)
4550 {
4551 m_context.getTestContext().getLog()
4552 << tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4553 << tcu::TestLog::EndMessage;
4554
4555 return false;
4556 }
4557 }
4558 }
4559
4560 return true;
4561 }
4562 else
4563 {
4564 /* Verify contents of transform feedback buffer */
4565
4566 bool result = true;
4567
4568 /* Get transform feedback data */
4569 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4570 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4571
4572 glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4573 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4574
4575 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4576 {
4577 const glw::GLint value = feedback_data[i];
4578
4579 if (m_result_success != value)
4580 {
4581 m_context.getTestContext().getLog() << tcu::TestLog::Message
4582 << "Error. Transform feedback buffer contents are wrong at " << i
4583 << tcu::TestLog::EndMessage;
4584
4585 result = false;
4586 break;
4587 }
4588 }
4589
4590 /* Unmap transform feedback buffer */
4591 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4592 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4593
4594 return result;
4595 }
4596 }
4597
4598 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4599 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4600 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4601
4602 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name = "UniformBlock";
4603 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4604
4605 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result = "fs_out_fs_result";
4606 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result = "gs_fs_gs_result";
4607 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result = "gs_fs_tcs_result";
4608 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result = "gs_fs_tes_result";
4609 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result = "gs_fs_vs_result";
4610 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4611 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result = "tcs_tes_vs_result";
4612 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result = "tes_gs_tcs_result";
4613 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result = "tes_gs_tes_result";
4614 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result = "tes_gs_vs_result";
4615 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result = "vs_tcs_vs_result";
4616
4617 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4618 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset = -1;
4619 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride = -1;
4620 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4621
4622 /** Constructor
4623 *
4624 * @param context Test context
4625 **/
GPUShaderFP64Test3(deqp::Context& context)4626 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4627 : TestCase(context, "named_uniform_blocks",
4628 "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4629 {
4630 /* Nothing to be done */
4631 }
4632
4633 /** Deinitialize test
4634 *
4635 **/
deinit()4636 void GPUShaderFP64Test3::deinit()
4637 {
4638 /* GL entry points */
4639 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4640
4641 /* Clean programs */
4642 m_packed_program.deinit(m_context);
4643 m_shared_program.deinit(m_context);
4644 m_std140_program.deinit(m_context);
4645
4646 /* Clean frambuffer */
4647 if (0 != m_framebuffer_id)
4648 {
4649 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4650 gl.deleteFramebuffers(1, &m_framebuffer_id);
4651
4652 m_framebuffer_id = 0;
4653 }
4654
4655 /* Clean texture */
4656 if (0 != m_color_texture_id)
4657 {
4658 gl.bindTexture(GL_TEXTURE_2D, 0);
4659 gl.deleteTextures(1, &m_color_texture_id);
4660
4661 m_color_texture_id = 0;
4662 }
4663
4664 /* Clean buffers */
4665 if (0 != m_transform_feedback_buffer_id)
4666 {
4667 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4668 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4669
4670 m_transform_feedback_buffer_id = 0;
4671 }
4672
4673 if (0 != m_uniform_buffer_id)
4674 {
4675 gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4676 gl.deleteBuffers(1, &m_uniform_buffer_id);
4677
4678 m_uniform_buffer_id = 0;
4679 }
4680
4681 /* Clean VAO */
4682 if (0 != m_vertex_array_object_id)
4683 {
4684 gl.bindVertexArray(0);
4685 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4686
4687 m_vertex_array_object_id = 0;
4688 }
4689 }
4690
4691 /** Execute test
4692 *
4693 * @return tcu::TestNode::STOP
4694 **/
iterate()4695 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4696 {
4697 bool result = true;
4698
4699 /* Check if extension is supported */
4700 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4701 {
4702 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4703 }
4704
4705 /* Initialize test */
4706 testInit();
4707
4708 /* Test "packed" uniform buffer layout */
4709 if (false == test(PACKED))
4710 {
4711 result = false;
4712 }
4713
4714 /* Test "shared" uniform buffer layout */
4715 if (false == test(SHARED))
4716 {
4717 result = false;
4718 }
4719
4720 /* Test "std140" uniform buffer layout */
4721 if (false == test(STD140))
4722 {
4723 result = false;
4724 }
4725
4726 /* Set result */
4727 if (true == result)
4728 {
4729 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4730 }
4731 else
4732 {
4733 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4734 }
4735
4736 /* Done */
4737 return tcu::TestNode::STOP;
4738 }
4739
4740 /** Constructor
4741 *
4742 **/
programInfo()4743 GPUShaderFP64Test3::programInfo::programInfo()
4744 : m_fragment_shader_id(0)
4745 , m_geometry_shader_id(0)
4746 , m_program_object_id(0)
4747 , m_tesselation_control_shader_id(0)
4748 , m_tesselation_evaluation_shader_id(0)
4749 , m_vertex_shader_id(0)
4750 , m_buffer_size(0)
4751 , m_uniform_block_index(0)
4752 {
4753 /* Nothing to be done here */
4754 }
4755
4756 /** Compile shader
4757 *
4758 * @param context Test context
4759 * @param shader_id Shader object id
4760 * @param shader_code Shader source code
4761 **/
compile(deqp::Context& context, glw::GLuint shader_id, const glw::GLchar* shader_code) const4762 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4763 const glw::GLchar* shader_code) const
4764 {
4765 /* GL entry points */
4766 const glw::Functions& gl = context.getRenderContext().getFunctions();
4767
4768 /* Compilation status */
4769 glw::GLint status = GL_FALSE;
4770
4771 /* Set source code */
4772 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4773 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4774
4775 /* Compile */
4776 gl.compileShader(shader_id);
4777 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4778
4779 /* Get compilation status */
4780 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4781 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4782
4783 /* Log compilation error */
4784 if (GL_TRUE != status)
4785 {
4786 glw::GLint length = 0;
4787 std::vector<glw::GLchar> message;
4788
4789 /* Error log length */
4790 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4791 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4792
4793 /* Prepare storage */
4794 message.resize(length);
4795
4796 /* Get error log */
4797 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4798 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4799
4800 /* Log */
4801 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4802 << &message[0] << "\nShader source\n"
4803 << shader_code << tcu::TestLog::EndMessage;
4804
4805 TCU_FAIL("Failed to compile shader");
4806 }
4807 }
4808
4809 /** Cleans program and attached shaders
4810 *
4811 * @param context Test context
4812 **/
deinit(deqp::Context& context)4813 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4814 {
4815 /* GL entry points */
4816 const glw::Functions& gl = context.getRenderContext().getFunctions();
4817
4818 /* Restore default program */
4819 gl.useProgram(0);
4820
4821 /* Clean program object */
4822 if (0 != m_program_object_id)
4823 {
4824 gl.deleteProgram(m_program_object_id);
4825 m_program_object_id = 0;
4826 }
4827
4828 /* Clean shaders */
4829 if (0 != m_fragment_shader_id)
4830 {
4831 gl.deleteShader(m_fragment_shader_id);
4832 m_fragment_shader_id = 0;
4833 }
4834
4835 if (0 != m_geometry_shader_id)
4836 {
4837 gl.deleteShader(m_geometry_shader_id);
4838 m_geometry_shader_id = 0;
4839 }
4840
4841 if (0 != m_tesselation_control_shader_id)
4842 {
4843 gl.deleteShader(m_tesselation_control_shader_id);
4844 m_tesselation_control_shader_id = 0;
4845 }
4846
4847 if (0 != m_tesselation_evaluation_shader_id)
4848 {
4849 gl.deleteShader(m_tesselation_evaluation_shader_id);
4850 m_tesselation_evaluation_shader_id = 0;
4851 }
4852
4853 if (0 != m_vertex_shader_id)
4854 {
4855 gl.deleteShader(m_vertex_shader_id);
4856 m_vertex_shader_id = 0;
4857 }
4858 }
4859
4860 /** Build program and query for uniform layout
4861 *
4862 * @param context Test context
4863 * @param uniform_details Collection of uniform details
4864 * @param fragment_shader_code Fragment shader source code
4865 * @param geometry_shader_code Geometry shader source code
4866 * @param tesselation_control_shader_code Tesselation control shader source code
4867 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4868 * @param vertex_shader_code Vertex shader source code
4869 **/
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)4870 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4871 const glw::GLchar* fragment_shader_code,
4872 const glw::GLchar* geometry_shader_code,
4873 const glw::GLchar* tesselation_control_shader_code,
4874 const glw::GLchar* tesselation_evaluation_shader_code,
4875 const glw::GLchar* vertex_shader_code)
4876 {
4877 /* GL entry points */
4878 const glw::Functions& gl = context.getRenderContext().getFunctions();
4879
4880 /* Names of varyings to be captured with transform feedback */
4881 static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4882 m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4883 static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4884
4885 /* Create shader objects */
4886 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
4887 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
4888 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
4889 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4890 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
4891 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4892
4893 /* Create program object */
4894 m_program_object_id = gl.createProgram();
4895 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4896
4897 /* Set up names of varyings to be captured with transform feedback */
4898 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4899 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4900
4901 /* Compile shaders */
4902 compile(context, m_fragment_shader_id, fragment_shader_code);
4903 compile(context, m_geometry_shader_id, geometry_shader_code);
4904 compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4905 compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4906 compile(context, m_vertex_shader_id, vertex_shader_code);
4907
4908 /* Link program */
4909 link(context);
4910
4911 /* Inspect program object */
4912 /* Get index of named uniform block */
4913 m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4914 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4915
4916 if (GL_INVALID_INDEX == m_uniform_block_index)
4917 {
4918 TCU_FAIL("Unifom block is inactive");
4919 }
4920
4921 /* Get size of named uniform block */
4922 gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4923 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4924
4925 if (0 == m_buffer_size)
4926 {
4927 TCU_FAIL("Unifom block size is 0");
4928 }
4929
4930 /* Get information about "double precision" uniforms */
4931 for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4932 end != it; ++it)
4933 {
4934 const glw::GLchar* uniform_name = 0;
4935 std::string uniform_name_str;
4936 std::stringstream uniform_name_stream;
4937 glw::GLuint index = 0;
4938 glw::GLint offset = 0;
4939 glw::GLint matrix_stride = 0;
4940
4941 /* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4942 uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4943
4944 uniform_name_str = uniform_name_stream.str();
4945 uniform_name = uniform_name_str.c_str();
4946
4947 /* Get index of uniform */
4948 gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4949 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4950
4951 if (GL_INVALID_INDEX == index)
4952 {
4953 TCU_FAIL("Unifom is inactive");
4954 }
4955
4956 /* Get offset of uniform */
4957 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4958 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4959
4960 if (m_invalid_uniform_offset == offset)
4961 {
4962 TCU_FAIL("Unifom has invalid offset");
4963 }
4964
4965 m_uniform_offsets.push_back(offset);
4966
4967 /* Get matrix stride of uniform */
4968 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4969 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4970
4971 if (m_invalid_uniform_matrix_stride == offset)
4972 {
4973 TCU_FAIL("Unifom has invalid matrix stride");
4974 }
4975
4976 m_uniform_matrix_strides.push_back(matrix_stride);
4977 }
4978 }
4979
4980 /** Attach shaders and link program
4981 *
4982 * @param context Test context
4983 **/
link(deqp::Context& context) const4984 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4985 {
4986 /* GL entry points */
4987 const glw::Functions& gl = context.getRenderContext().getFunctions();
4988
4989 /* Link status */
4990 glw::GLint status = GL_FALSE;
4991
4992 /* Attach shaders */
4993 gl.attachShader(m_program_object_id, m_fragment_shader_id);
4994 gl.attachShader(m_program_object_id, m_geometry_shader_id);
4995 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
4996 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
4997 gl.attachShader(m_program_object_id, m_vertex_shader_id);
4998 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
4999
5000 /* Link */
5001 gl.linkProgram(m_program_object_id);
5002 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5003
5004 /* Get link status */
5005 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5006 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5007
5008 /* Log link error */
5009 if (GL_TRUE != status)
5010 {
5011 glw::GLint length = 0;
5012 std::vector<glw::GLchar> message;
5013
5014 /* Get error log length */
5015 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5016 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5017
5018 message.resize(length);
5019
5020 /* Get error log */
5021 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5022 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5023
5024 /* Log */
5025 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5026 << &message[0] << tcu::TestLog::EndMessage;
5027
5028 TCU_FAIL("Failed to link program");
5029 }
5030 }
5031
5032 /** Returns "predefined" values that will be used to fill uniform data
5033 *
5034 * @param type_ordinal Ordinal number of "double precision" uniform type
5035 * @param element Index of element in uniform
5036 *
5037 * @return "Predefined" value
5038 **/
getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const5039 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5040 {
5041 return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5042 ((m_base_element - (glw::GLdouble)element) / 4.0);
5043 }
5044
5045 /** Returns a reference of programInfo instance specific for given buffer layout
5046 *
5047 * @param uniform_data_layout Buffer layout
5048 *
5049 * @return Reference to an instance of programInfo
5050 **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5051 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5052 {
5053 const programInfo* program_info = 0;
5054
5055 switch (uniform_data_layout)
5056 {
5057 case PACKED:
5058
5059 program_info = &m_packed_program;
5060
5061 break;
5062
5063 case SHARED:
5064
5065 program_info = &m_shared_program;
5066
5067 break;
5068
5069 case STD140:
5070
5071 program_info = &m_std140_program;
5072
5073 break;
5074 }
5075
5076 return *program_info;
5077 }
5078
5079 /** Get "name" of buffer layout
5080 *
5081 * @param uniform_data_layout Buffer layout
5082 *
5083 * @return "Name" of layout
5084 **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5085 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5086 {
5087 const glw::GLchar* layout = "";
5088
5089 switch (uniform_data_layout)
5090 {
5091 case PACKED:
5092 layout = "packed";
5093 break;
5094 case SHARED:
5095 layout = "shared";
5096 break;
5097 case STD140:
5098 layout = "std140";
5099 break;
5100 }
5101
5102 return layout;
5103 }
5104
5105 /** Prepare programInfo instance for specific buffer layout
5106 *
5107 * @param program_info Instance of programInfo
5108 * @param uniform_data_layout Buffer layout
5109 **/
prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const5110 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5111 {
5112 /* Storage for shader source code */
5113 std::stringstream fragment_shader_code;
5114 std::stringstream geometry_shader_code;
5115 std::stringstream tess_control_shader_code;
5116 std::stringstream tess_eval_shader_code;
5117 std::stringstream vertex_shader_code;
5118
5119 /* Write preambles */
5120 writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5121 writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5122 writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5123 writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5124 writePreamble(vertex_shader_code, VERTEX_SHADER);
5125
5126 /* Write definition of named uniform block */
5127 writeUniformBlock(fragment_shader_code, uniform_data_layout);
5128 writeUniformBlock(geometry_shader_code, uniform_data_layout);
5129 writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5130 writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5131 writeUniformBlock(vertex_shader_code, uniform_data_layout);
5132
5133 /* Write definitions of varyings */
5134 writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5135 writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5136 writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5137 writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5138 writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5139
5140 /* Write main routine */
5141 writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5142 writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5143 writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5144 writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5145 writeMainBody(vertex_shader_code, VERTEX_SHADER);
5146
5147 /* Init programInfo instance */
5148 program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5149 geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5150 tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5151 }
5152
5153 /** Prepare uniform buffer
5154 *
5155 * @param program_info Instance of programInfo
5156 * @param verify_offsets If uniform offsets should be verified against expected values
5157 *
5158 * @return false if uniform offsets verification result is failure, true otherwise
5159 **/
prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const5160 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5161 {
5162 const glw::GLuint buffer_size = program_info.m_buffer_size;
5163 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5164 bool offset_verification_result = true;
5165 glw::GLuint type_ordinal = 1;
5166 std::vector<uniformDetails>::const_iterator it_uniform_details = m_uniform_details.begin();
5167 std::vector<glw::GLint>::const_iterator it_uniform_offsets = program_info.m_uniform_offsets.begin();
5168 std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5169
5170 /* Prepare storage for uniform buffer data */
5171 std::vector<glw::GLubyte> buffer_data;
5172 buffer_data.resize(buffer_size);
5173
5174 /* For each "double precision" uniform */
5175 for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5176 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5177 {
5178 const glw::GLint matrix_stride = *it_uniform_matrix_strides;
5179 const glw::GLuint n_columns = it_uniform_details->m_n_columns;
5180 const glw::GLuint n_elements = it_uniform_details->m_n_elements;
5181 const glw::GLuint column_length = n_elements / n_columns;
5182 const glw::GLint uniform_offset = *it_uniform_offsets;
5183
5184 /* For each element of uniform */
5185 for (glw::GLuint element = 0; element < n_elements; ++element)
5186 {
5187 const glw::GLuint column = element / column_length;
5188 const glw::GLuint column_elem = element % column_length;
5189 const glw::GLdouble value = getExpectedValue(type_ordinal, element);
5190 const glw::GLuint value_offset =
5191 static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5192
5193 glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5194
5195 /* Store value */
5196 *value_dst = value;
5197 }
5198
5199 /* Uniform offset verification */
5200 if (true == verify_offsets)
5201 {
5202 const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5203
5204 if (expected_offset != uniform_offset)
5205 {
5206 if (true == offset_verification_result)
5207 {
5208 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5209 }
5210
5211 m_context.getTestContext().getLog()
5212 << tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5213 << " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5214 << tcu::TestLog::EndMessage;
5215
5216 offset_verification_result = false;
5217 }
5218 }
5219 }
5220
5221 /* Update uniform buffer with prepared data */
5222 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5223 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5224
5225 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5226 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5227
5228 /* Bind uniform buffer as data source for named uniform block */
5229 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5230 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5231
5232 gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5233 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5234
5235 /* Done */
5236 return offset_verification_result;
5237 }
5238
5239 /** Prepare data, execute draw call and verify results
5240 *
5241 * @param uniform_data_layout
5242 *
5243 * @return true if test pass, false otherwise
5244 **/
test(uniformDataLayout uniform_data_layout) const5245 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5246 {
5247 bool are_offsets_verified = (STD140 == uniform_data_layout);
5248 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5249 bool offset_verification_result = true;
5250 const programInfo& program_info = getProgramInfo(uniform_data_layout);
5251 bool result = true;
5252
5253 /* Set up program */
5254 gl.useProgram(program_info.m_program_object_id);
5255 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5256
5257 /* Prepare uniform buffer */
5258 offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5259
5260 if (true == are_offsets_verified && false == offset_verification_result)
5261 {
5262 /* Offsets verification failure was already reported, add info about buffer layout */
5263 m_context.getTestContext().getLog() << tcu::TestLog::Message
5264 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5265 << tcu::TestLog::EndMessage;
5266
5267 result = false;
5268 }
5269
5270 /* Set up transform feedback buffer */
5271 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5272 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5273
5274 /* Begin transform feedback */
5275 gl.beginTransformFeedback(GL_POINTS);
5276 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5277
5278 /* Execute draw call for singe vertex */
5279 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5280 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5281
5282 /* Stop transform feedback */
5283 gl.endTransformFeedback();
5284 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5285
5286 /* Verify results */
5287 if (false == verifyResults())
5288 {
5289 /* Result verificatioon failure was already reported, add info about layout */
5290 m_context.getTestContext().getLog() << tcu::TestLog::Message
5291 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5292 << tcu::TestLog::EndMessage;
5293
5294 result = false;
5295 }
5296
5297 /* Done */
5298 return result;
5299 }
5300
testInit()5301 void GPUShaderFP64Test3::testInit()
5302 {
5303 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5304
5305 /* Uniform block declaration with std140 offsets calculated
5306 * | align | loc_req | begins | ends | offset in bytes | imp |
5307 * ivec3 unused1[3] | 4 | 12 | 0 | 12 | 0 | |
5308 * double double_value | 2 | 2 | 12 | 14 | 48 | XXX |
5309 * bool unused2 | 1 | 1 | 14 | 15 | 56 | |
5310 * dvec2 dvec2_value | 4 | 4 | 16 | 20 | 64 | XXX |
5311 * bvec3 unused3 | 4 | 4 | 20 | 24 | 80 | |
5312 * dvec3 dvec3_value | 8 | 8 | 24 | 32 | 96 | XXX |
5313 * int unused4[3] | 4 | 12 | 32 | 44 | 128 | |
5314 * dvec4 dvec4_value | 8 | 8 | 48 | 56 | 192 | XXX |
5315 * bool unused5 | 1 | 1 | 56 | 57 | 224 | |
5316 * bool unused6[2] | 4 | 8 | 60 | 68 | 240 | |
5317 * dmat2 dmat2_value | 4 | 8 | 68 | 76 | 272 | XXX |
5318 * dmat3 dmat3_value | 8 | 24 | 80 | 104 | 320 | XXX |
5319 * bool unused7 | 1 | 1 | 104 | 105 | 416 | |
5320 * dmat4 dmat4_value | 8 | 32 | 112 | 144 | 448 | XXX |
5321 * dmat2x3 dmat2x3_value | 8 | 16 | 144 | 160 | 576 | XXX |
5322 * uvec3 unused8 | 4 | 4 | 160 | 164 | 640 | |
5323 * dmat2x4 dmat2x4_value | 8 | 16 | 168 | 184 | 672 | XXX |
5324 * dmat3x2 dmat3x2_value | 4 | 12 | 184 | 196 | 736 | XXX |
5325 * bool unused9 | 1 | 1 | 196 | 197 | 784 | |
5326 * dmat3x4 dmat3x4_value | 8 | 24 | 200 | 224 | 800 | XXX |
5327 * int unused10 | 1 | 1 | 224 | 225 | 896 | |
5328 * dmat4x2 dmat4x2_value | 4 | 16 | 228 | 244 | 912 | XXX |
5329 * dmat4x3 dmat4x3_value | 8 | 32 | 248 | 280 | 992 | XXX |
5330 */
5331
5332 /* Prepare "double precision" unfiorms' details */
5333 m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5334 1 /* n_elements */, "double" /* type_name */));
5335 m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5336 2 /* n_elements */, "dvec2" /* type_name */));
5337 m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5338 3 /* n_elements */, "dvec3" /* type_name */));
5339 m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5340 4 /* n_elements */, "dvec4" /* type_name */));
5341 m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5342 4 /* n_elements */, "dmat2" /* type_name */));
5343 m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5344 9 /* n_elements */, "dmat3" /* type_name */));
5345 m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5346 16 /* n_elements */, "dmat4" /* type_name */));
5347 m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5348 6 /* n_elements */, "dmat2x3" /* type_name */));
5349 m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5350 8 /* n_elements */, "dmat2x4" /* type_name */));
5351 m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5352 6 /* n_elements */, "dmat3x2" /* type_name */));
5353 m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5354 12 /* n_elements */, "dmat3x4" /* type_name */));
5355 m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5356 8 /* n_elements */, "dmat4x2" /* type_name */));
5357 m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5358 12 /* n_elements */, "dmat4x3" /* type_name */));
5359
5360 /* Get random values for getExpectedValue */
5361 m_base_element = (glw::GLdouble)(rand() % 13);
5362 m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5363
5364 /* Prepare programInfos for all buffer layouts */
5365 prepareProgram(m_packed_program, PACKED);
5366 prepareProgram(m_shared_program, SHARED);
5367 prepareProgram(m_std140_program, STD140);
5368
5369 /* Generate buffers */
5370 gl.genBuffers(1, &m_transform_feedback_buffer_id);
5371 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5372
5373 gl.genBuffers(1, &m_uniform_buffer_id);
5374 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5375
5376 /* Prepare transform feedback buffer */
5377 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5378 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5379
5380 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5381 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5382
5383 /* Prepare texture for color attachment 0 */
5384 gl.genTextures(1, &m_color_texture_id);
5385 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5386
5387 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5388 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5389
5390 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5391 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5392
5393 /* Prepare FBO with color attachment 0 */
5394 gl.genFramebuffers(1, &m_framebuffer_id);
5395 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5396
5397 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5398 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5399
5400 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5401 0 /* level */);
5402 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5403
5404 gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5405 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5406
5407 /* Prepare VAO */
5408 gl.genVertexArrays(1, &m_vertex_array_object_id);
5409 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5410
5411 gl.bindVertexArray(m_vertex_array_object_id);
5412 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5413
5414 /* Tesselation patch set up */
5415 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5416 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5417 }
5418
5419 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5420 *
5421 * @return true if all values are as expected, false otherwise
5422 **/
verifyResults() const5423 bool GPUShaderFP64Test3::verifyResults() const
5424 {
5425 glw::GLint* feedback_data = 0;
5426 bool fragment_shader_result = false;
5427 bool geometry_shader_result = false;
5428 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5429 bool tess_ctrl_shader_result = false;
5430 bool tess_eval_shader_result = false;
5431 bool vertex_shader_result = false;
5432
5433 /* Prepare storage for testure data */
5434 std::vector<glw::GLint> image_data;
5435 image_data.resize(1);
5436
5437 /* Get texture contents */
5438 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5439 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5440
5441 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5442 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5443
5444 /* Get transform feedback data */
5445 feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5446 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5447
5448 /* Verify results */
5449 fragment_shader_result = (m_result_success == image_data[0]);
5450 geometry_shader_result = (m_result_success == feedback_data[0]);
5451 tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5452 tess_eval_shader_result = (m_result_success == feedback_data[2]);
5453 vertex_shader_result = (m_result_success == feedback_data[3]);
5454
5455 /* Unmap transform feedback buffer */
5456 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5457 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5458
5459 /* Set result */
5460 if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5461 tess_eval_shader_result && vertex_shader_result))
5462 {
5463 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5464
5465 m_context.getTestContext().getLog() << tcu::TestLog::Message
5466 << "Vertex shader stage result: " << vertex_shader_result
5467 << tcu::TestLog::EndMessage;
5468
5469 m_context.getTestContext().getLog() << tcu::TestLog::Message
5470 << "Tesselation control shader stage result: " << tess_ctrl_shader_result
5471 << tcu::TestLog::EndMessage;
5472
5473 m_context.getTestContext().getLog() << tcu::TestLog::Message
5474 << "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5475 << tcu::TestLog::EndMessage;
5476
5477 m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 << "Geometry shader stage result: " << geometry_shader_result
5479 << tcu::TestLog::EndMessage;
5480
5481 m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 << "Fragment shader stage result: " << fragment_shader_result
5483 << tcu::TestLog::EndMessage;
5484
5485 return false;
5486 }
5487 else
5488 {
5489 return true;
5490 }
5491 }
5492
5493 /** Write main routine of <shader_stage> shader to stream
5494 *
5495 * @param stream Output stream with source code of shader
5496 * @param shader_stage Shader stage
5497 **/
writeMainBody(std::ostream& stream, shaderStage shader_stage) const5498 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5499 {
5500 glw::GLuint type_ordinal = 1;
5501 const glw::GLchar* varying_name = "";
5502
5503 /* Select name for varying that will hold result of "that" shader_stage */
5504 switch (shader_stage)
5505 {
5506 case FRAGMENT_SHADER:
5507 varying_name = m_varying_name_fs_out_fs_result;
5508 break;
5509 case GEOMETRY_SHADER:
5510 varying_name = m_varying_name_gs_fs_gs_result;
5511 break;
5512 case TESS_CONTROL_SHADER:
5513 varying_name = m_varying_name_tcs_tes_tcs_result;
5514 break;
5515 case TESS_EVAL_SHADER:
5516 varying_name = m_varying_name_tes_gs_tes_result;
5517 break;
5518 case VERTEX_SHADER:
5519 varying_name = m_varying_name_vs_tcs_vs_result;
5520 break;
5521 }
5522
5523 /* void main() */
5524 stream << "void main()\n"
5525 "{\n";
5526
5527 /* Tesselation levels output */
5528 if (TESS_CONTROL_SHADER == shader_stage)
5529 {
5530 stream << "gl_TessLevelOuter[0] = 1.0;\n"
5531 "gl_TessLevelOuter[1] = 1.0;\n"
5532 "gl_TessLevelOuter[2] = 1.0;\n"
5533 "gl_TessLevelOuter[3] = 1.0;\n"
5534 "gl_TessLevelInner[0] = 1.0;\n"
5535 "gl_TessLevelInner[1] = 1.0;\n"
5536 "\n";
5537 }
5538
5539 /* For each "double precision" uniform
5540 *
5541 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5542 * {
5543 * VARYING_NAME = m_result_failure;
5544 * }
5545 */
5546 for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5547 end != it; ++it, ++type_ordinal)
5548 {
5549 stream << " ";
5550
5551 /* First comparison is done with if, next with else if */
5552 if (1 != type_ordinal)
5553 {
5554 stream << "else ";
5555 }
5556
5557 /* if (TYPE_NAME( */
5558 stream << "if (" << it->m_type_name << "(";
5559
5560 /* PREDIFINED_VALUES */
5561 for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5562 {
5563 stream << getExpectedValue(type_ordinal, element);
5564
5565 /* Separate with comma */
5566 if (it->m_n_elements != element + 1)
5567 {
5568 stream << ", ";
5569 }
5570 }
5571
5572 /*
5573 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5574 * {
5575 * VARYING_NAME
5576 */
5577 stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5578 " {\n"
5579 " "
5580 << varying_name;
5581
5582 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5583 if (TESS_CONTROL_SHADER == shader_stage)
5584 {
5585 stream << "[gl_InvocationID]";
5586 }
5587
5588 /*
5589 * = m_result_failure;
5590 * }
5591 */
5592 stream << " = " << m_result_failure << ";\n"
5593 << " }\n";
5594 }
5595
5596 /* If all comparisons are ok
5597 *
5598 * else
5599 * {
5600 * VARYING_NAME = m_result_success;
5601 * }
5602 */
5603
5604 /*
5605 * else
5606 * {
5607 * VARYING_NAME
5608 */
5609 stream << " else\n"
5610 " {\n"
5611 " "
5612 << varying_name;
5613
5614 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5615 if (TESS_CONTROL_SHADER == shader_stage)
5616 {
5617 stream << "[gl_InvocationID]";
5618 }
5619
5620 /*
5621 * = m_result_success;
5622 * }
5623 *
5624 */
5625 stream << " = " << m_result_success << ";\n"
5626 << " }\n"
5627 << "\n";
5628
5629 /* For each pair of "input/output" varyings
5630 *
5631 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5632 **/
5633 writeVaryingPassthrough(stream, shader_stage);
5634
5635 /* Geometry shader have to emit vertex */
5636 if (GEOMETRY_SHADER == shader_stage)
5637 {
5638 stream << "\n"
5639 "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5640 "EmitVertex();\n"
5641 "EndPrimitive();\n";
5642 }
5643
5644 /* Close scope of main */
5645 stream << "}\n\n";
5646 }
5647
5648 /** Write shader preamble to stream
5649 *
5650 * @param stream Output stream with source code of shader
5651 * @param shader_stage Shader stage
5652 **/
writePreamble(std::ostream& stream, shaderStage shader_stage) const5653 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5654 {
5655 stream << "#version 400 core\n"
5656 "\n"
5657 "precision highp float;\n"
5658 "\n";
5659
5660 switch (shader_stage)
5661 {
5662 case FRAGMENT_SHADER:
5663 break;
5664 case GEOMETRY_SHADER:
5665 stream << "layout(points) in;\n"
5666 "layout(points, max_vertices = 1) out;\n"
5667 "\n";
5668 break;
5669 case TESS_CONTROL_SHADER:
5670 stream << "layout(vertices = 1) out;\n"
5671 "\n";
5672 break;
5673 case TESS_EVAL_SHADER:
5674 stream << "layout(isolines, point_mode) in;\n"
5675 "\n";
5676 break;
5677 case VERTEX_SHADER:
5678 break;
5679 }
5680 }
5681
5682 /** Write name uniform blcok definition with specific layout to stream
5683 *
5684 * @param stream Output stream with source code of shader
5685 * @param uniform_data_layout Buffer layout
5686 **/
writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const5687 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5688 {
5689 const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5690
5691 stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5692 "{\n"
5693 " ivec3 unused1[3];\n"
5694 " double double_value;\n"
5695 " bool unused2;\n"
5696 " dvec2 dvec2_value;\n"
5697 " bvec3 unused3;\n"
5698 " dvec3 dvec3_value;\n"
5699 " int unused4[3];\n"
5700 " dvec4 dvec4_value;\n"
5701 " bool unused5;\n"
5702 " bool unused6[2];\n"
5703 " dmat2 dmat2_value;\n"
5704 " dmat3 dmat3_value;\n"
5705 " bool unused7;\n"
5706 " dmat4 dmat4_value;\n"
5707 " dmat2x3 dmat2x3_value;\n"
5708 " uvec3 unused8;\n"
5709 " dmat2x4 dmat2x4_value;\n"
5710 " dmat3x2 dmat3x2_value;\n"
5711 " bool unused9;\n"
5712 " dmat3x4 dmat3x4_value;\n"
5713 " int unused10;\n"
5714 " dmat4x2 dmat4x2_value;\n"
5715 " dmat4x3 dmat4x3_value;\n"
5716 "} "
5717 << m_uniform_block_instance_name << ";\n";
5718
5719 stream << "\n";
5720 }
5721
5722 /** Write definitions of varyings specific for given <shader_stage> to stream
5723 *
5724 * @param stream Output stream with source code of shader
5725 * @param shader_stage Shader stage
5726 **/
writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const5727 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5728 {
5729 static const glw::GLchar* const varying_type = "int";
5730
5731 switch (shader_stage)
5732 {
5733 case FRAGMENT_SHADER:
5734
5735 /* In */
5736 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5737 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5738 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5739 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5740
5741 stream << "\n";
5742
5743 /* Out */
5744 stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5745
5746 break;
5747
5748 case GEOMETRY_SHADER:
5749
5750 /* In */
5751 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5752 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5753 stream << "in " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5754
5755 stream << "\n";
5756
5757 /* Out */
5758 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5759 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5760 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5761 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5762
5763 break;
5764
5765 case TESS_CONTROL_SHADER:
5766
5767 /* In */
5768 stream << "in " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5769
5770 stream << "\n";
5771
5772 /* Out */
5773 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5774 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5775
5776 break;
5777
5778 case TESS_EVAL_SHADER:
5779
5780 /* In */
5781 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5782 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5783
5784 stream << "\n";
5785
5786 /* Out */
5787 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5788 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5789 stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5790
5791 break;
5792
5793 case VERTEX_SHADER:
5794
5795 /* Out */
5796 stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5797
5798 break;
5799 }
5800
5801 stream << "\n";
5802 }
5803
5804 /** Write passthrough code of "input/output" varying pairs to stream
5805 *
5806 * @param stream Output stream with source code of shader
5807 * @param shader_stage Shader stage
5808 **/
writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const5809 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5810 {
5811 switch (shader_stage)
5812 {
5813 case FRAGMENT_SHADER:
5814 break;
5815
5816 case GEOMETRY_SHADER:
5817
5818 stream << " " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5819 stream << " " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5820 stream << " " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5821
5822 break;
5823
5824 case TESS_CONTROL_SHADER:
5825
5826 stream << " " << m_varying_name_tcs_tes_vs_result
5827 << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5828
5829 break;
5830
5831 case TESS_EVAL_SHADER:
5832
5833 stream << " " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5834 stream << " " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5835
5836 break;
5837
5838 case VERTEX_SHADER:
5839
5840 break;
5841 }
5842 }
5843
5844 /** Constructor. Sets all uniform locations to -1 and sets all
5845 * values to 0.
5846 */
_data()5847 GPUShaderFP64Test4::_data::_data()
5848 {
5849 memset(&uniform_double, 0, sizeof(uniform_double));
5850 memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5851 memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5852 memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5853 memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5854 memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5855 memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5856
5857 uniform_location_double = -1;
5858 uniform_location_double_arr[0] = -1;
5859 uniform_location_double_arr[1] = -1;
5860 uniform_location_dvec2 = -1;
5861 uniform_location_dvec2_arr[0] = -1;
5862 uniform_location_dvec2_arr[1] = -1;
5863 uniform_location_dvec3 = -1;
5864 uniform_location_dvec3_arr[0] = -1;
5865 uniform_location_dvec3_arr[1] = -1;
5866 uniform_location_dvec4 = -1;
5867 uniform_location_dvec4_arr[0] = -1;
5868 uniform_location_dvec4_arr[1] = -1;
5869 }
5870
5871 /** Constructor
5872 *
5873 * @param context Rendering context.
5874 */
GPUShaderFP64Test4(deqp::Context& context)5875 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5876 : TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5877 " report correct properties of & values assigned to double-precision uniforms.")
5878 , m_has_test_passed(true)
5879 , m_uniform_name_buffer(0)
5880 , m_cs_id(0)
5881 , m_fs_id(0)
5882 , m_gs_id(0)
5883 , m_po_cs_id(0)
5884 , m_po_noncs_id(0)
5885 , m_tc_id(0)
5886 , m_te_id(0)
5887 , m_vs_id(0)
5888 {
5889 /* Left blank intentionally */
5890 }
5891
5892 /** Deinitializes all GL objects, as well as releases all bufers, that may
5893 * have beenallocated or created during test execution.
5894 **/
deinit()5895 void GPUShaderFP64Test4::deinit()
5896 {
5897 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5898
5899 if (m_cs_id != 0)
5900 {
5901 gl.deleteShader(m_cs_id);
5902
5903 m_cs_id = 0;
5904 }
5905
5906 if (m_fs_id != 0)
5907 {
5908 gl.deleteShader(m_fs_id);
5909
5910 m_fs_id = 0;
5911 }
5912
5913 if (m_gs_id != 0)
5914 {
5915 gl.deleteShader(m_gs_id);
5916
5917 m_gs_id = 0;
5918 }
5919
5920 if (m_po_cs_id != 0)
5921 {
5922 gl.deleteProgram(m_po_cs_id);
5923
5924 m_po_cs_id = 0;
5925 }
5926
5927 if (m_po_noncs_id != 0)
5928 {
5929 gl.deleteProgram(m_po_noncs_id);
5930
5931 m_po_noncs_id = 0;
5932 }
5933
5934 if (m_tc_id != 0)
5935 {
5936 gl.deleteShader(m_tc_id);
5937
5938 m_tc_id = 0;
5939 }
5940
5941 if (m_te_id != 0)
5942 {
5943 gl.deleteShader(m_te_id);
5944
5945 m_te_id = 0;
5946 }
5947
5948 if (m_uniform_name_buffer != DE_NULL)
5949 {
5950 delete[] m_uniform_name_buffer;
5951
5952 m_uniform_name_buffer = DE_NULL;
5953 }
5954
5955 if (m_vs_id != 0)
5956 {
5957 gl.deleteShader(m_vs_id);
5958
5959 m_vs_id = 0;
5960 }
5961 }
5962
5963 /** Generates double-precision values for all uniforms defined for all program objects
5964 * used by the test.
5965 *
5966 * This function DOES NOT use any GL API. It only calculates & stores the values
5967 * in internal storage for further usage.
5968 */
generateUniformValues()5969 void GPUShaderFP64Test4::generateUniformValues()
5970 {
5971 _stage_data* stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5972 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5973
5974 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5975 {
5976 _stage_data* stage_ptr = stages[n_stage];
5977
5978 /* Iterate through all uniform components and assign them double values */
5979 double* double_ptrs[] = {
5980 &stage_ptr->uniform_structure_arrays[0].uniform_double,
5981 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5982 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5983 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5984 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5985 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
5986 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
5987 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
5988 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
5989 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
5990 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
5991 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
5992 &stage_ptr->uniform_structure_arrays[1].uniform_double,
5993 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
5994 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
5995 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
5996 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
5997 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
5998 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
5999 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6000 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6001 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6002 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6003 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6004 &stage_ptr->uniforms.uniform_double,
6005 stage_ptr->uniforms.uniform_double_arr + 0,
6006 stage_ptr->uniforms.uniform_double_arr + 1,
6007 stage_ptr->uniforms.uniform_dvec2 + 0,
6008 stage_ptr->uniforms.uniform_dvec2 + 1,
6009 stage_ptr->uniforms.uniform_dvec2_arr + 0,
6010 stage_ptr->uniforms.uniform_dvec2_arr + 1,
6011 stage_ptr->uniforms.uniform_dvec2_arr + 2,
6012 stage_ptr->uniforms.uniform_dvec2_arr + 3,
6013 stage_ptr->uniforms.uniform_dvec3 + 0,
6014 stage_ptr->uniforms.uniform_dvec3 + 1,
6015 stage_ptr->uniforms.uniform_dvec3 + 2,
6016 stage_ptr->uniforms.uniform_dvec3_arr + 0,
6017 stage_ptr->uniforms.uniform_dvec3_arr + 1,
6018 stage_ptr->uniforms.uniform_dvec3_arr + 2,
6019 stage_ptr->uniforms.uniform_dvec3_arr + 3,
6020 stage_ptr->uniforms.uniform_dvec3_arr + 4,
6021 stage_ptr->uniforms.uniform_dvec3_arr + 5,
6022 stage_ptr->uniforms.uniform_dvec4 + 0,
6023 stage_ptr->uniforms.uniform_dvec4 + 1,
6024 stage_ptr->uniforms.uniform_dvec4 + 2,
6025 stage_ptr->uniforms.uniform_dvec4 + 3,
6026 stage_ptr->uniforms.uniform_dvec4_arr + 0,
6027 stage_ptr->uniforms.uniform_dvec4_arr + 1,
6028 stage_ptr->uniforms.uniform_dvec4_arr + 2,
6029 stage_ptr->uniforms.uniform_dvec4_arr + 3,
6030 stage_ptr->uniforms.uniform_dvec4_arr + 4,
6031 stage_ptr->uniforms.uniform_dvec4_arr + 5,
6032 stage_ptr->uniforms.uniform_dvec4_arr + 6,
6033 stage_ptr->uniforms.uniform_dvec4_arr + 7,
6034 };
6035 const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6036
6037 for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6038 {
6039 double* double_ptr = double_ptrs[n_double_ptr];
6040
6041 /* Generate the value. Use magic numbers to generate a set of double-precision
6042 * floating-point numbers.
6043 */
6044 static int seed = 16762362;
6045
6046 *double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6047
6048 seed += 751;
6049 } /* for (all pointers to double variables) */
6050 } /* for (all stages) */
6051 }
6052
6053 /** Initializes all program & shader objects required to run the test. The function also
6054 * retrieves locations of all uniforms defined by both program objects.
6055 **/
initProgramObjects()6056 void GPUShaderFP64Test4::initProgramObjects()
6057 {
6058 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6059
6060 /* Create program & shader objects */
6061
6062 /* Compute shader support and GL 4.2 required */
6063 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6064 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6065 {
6066 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6067 }
6068
6069 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6070 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6071 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6072 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6073 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6074 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6075
6076 /* m_cs_id is initialized only if compute shaders are supported */
6077 if (0 != m_cs_id)
6078 {
6079 m_po_cs_id = gl.createProgram();
6080 }
6081
6082 m_po_noncs_id = gl.createProgram();
6083 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6084
6085 /* Configure compute shader body */
6086 const char* cs_body = "#version 420\n"
6087 "#extension GL_ARB_compute_shader : require\n"
6088 "\n"
6089 "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6090 "\n"
6091 "layout(rgba32f) uniform image2D testImage;\n"
6092 "\n"
6093 "uniform double cs_double;\n"
6094 "uniform dvec2 cs_dvec2;\n"
6095 "uniform dvec3 cs_dvec3;\n"
6096 "uniform dvec4 cs_dvec4;\n"
6097 "uniform double cs_double_arr[2];\n"
6098 "uniform dvec2 cs_dvec2_arr [2];\n"
6099 "uniform dvec3 cs_dvec3_arr [2];\n"
6100 "uniform dvec4 cs_dvec4_arr [2];\n"
6101 "\n"
6102 "uniform struct cs_struct\n"
6103 "{\n"
6104 " double struct_double;\n"
6105 " dvec2 struct_dvec2;\n"
6106 " dvec3 struct_dvec3;\n"
6107 " dvec4 struct_dvec4;\n"
6108 "} cs_array[2];\n"
6109 "\n"
6110 "void main()\n"
6111 "{\n"
6112 " double tmp = cs_double * cs_dvec2.x * cs_dvec3.y "
6113 " * cs_dvec4.z *\n"
6114 " cs_double_arr[0] * cs_dvec2_arr[0].x * "
6115 "cs_dvec3_arr[0].z * cs_dvec4_arr[0].w *\n"
6116 " cs_double_arr[1] * cs_dvec2_arr[1].x * "
6117 "cs_dvec3_arr[1].z * cs_dvec4_arr[1].w *\n"
6118 " cs_array[0].struct_double * cs_array[0].struct_dvec2.y * "
6119 "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6120 " cs_array[1].struct_double * cs_array[1].struct_dvec2.y * "
6121 "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6122 "\n"
6123 " imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6124 "}\n";
6125
6126 /* m_cs_id is initialized only if compute shaders are supported */
6127 if (0 != m_cs_id)
6128 {
6129 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6130 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6131 }
6132
6133 /* Configure vertex shader body */
6134 const char* vs_body = "#version 400\n"
6135 "\n"
6136 "uniform double vs_double;\n"
6137 "uniform dvec2 vs_dvec2;\n"
6138 "uniform dvec3 vs_dvec3;\n"
6139 "uniform dvec4 vs_dvec4;\n"
6140 "uniform double vs_double_arr[2];\n"
6141 "uniform dvec2 vs_dvec2_arr [2];\n"
6142 "uniform dvec3 vs_dvec3_arr [2];\n"
6143 "uniform dvec4 vs_dvec4_arr [2];\n"
6144 "\n"
6145 "uniform struct vs_struct\n"
6146 "{\n"
6147 " double struct_double;\n"
6148 " dvec2 struct_dvec2;\n"
6149 " dvec3 struct_dvec3;\n"
6150 " dvec4 struct_dvec4;\n"
6151 "} vs_array[2];\n"
6152 "\n"
6153 "void main()\n"
6154 "{\n"
6155 " if (vs_double * vs_dvec2.x * vs_dvec3.x "
6156 "* vs_dvec4.x *\n"
6157 " vs_double_arr[0] * vs_dvec2_arr[0].x * vs_dvec3_arr[0].x "
6158 "* vs_dvec4_arr[0].x *\n"
6159 " vs_double_arr[1] * vs_dvec2_arr[1].x * vs_dvec3_arr[1].x "
6160 "* vs_dvec4_arr[1].x *\n"
6161 " vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6162 "* vs_array[0].struct_dvec4.x *\n"
6163 " vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6164 "* vs_array[1].struct_dvec4.x > 1.0)\n"
6165 " {\n"
6166 " gl_Position = vec4(0);\n"
6167 " }\n"
6168 " else\n"
6169 " {\n"
6170 " gl_Position = vec4(1);\n"
6171 " }\n"
6172 "}\n";
6173
6174 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6175 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6176
6177 /* Configure tessellation control shader body */
6178 const char* tc_body = "#version 400\n"
6179 "\n"
6180 "uniform double tc_double;\n"
6181 "uniform dvec2 tc_dvec2;\n"
6182 "uniform dvec3 tc_dvec3;\n"
6183 "uniform dvec4 tc_dvec4;\n"
6184 "uniform double tc_double_arr[2];\n"
6185 "uniform dvec2 tc_dvec2_arr [2];\n"
6186 "uniform dvec3 tc_dvec3_arr [2];\n"
6187 "uniform dvec4 tc_dvec4_arr [2];\n"
6188 "\n"
6189 "uniform struct tc_struct\n"
6190 "{\n"
6191 " double struct_double;\n"
6192 " dvec2 struct_dvec2;\n"
6193 " dvec3 struct_dvec3;\n"
6194 " dvec4 struct_dvec4;\n"
6195 "} tc_array[2];\n"
6196 "\n"
6197 "layout(vertices = 4) out;\n"
6198 "\n"
6199 "void main()\n"
6200 "{\n"
6201 " gl_TessLevelOuter[0] = (tc_double > 1.0) ? 2.0 : 3.0;\n"
6202 " gl_TessLevelOuter[1] = (tc_dvec2.x > 1.0) ? 3.0 : 4.0;\n"
6203 " gl_TessLevelOuter[2] = (tc_dvec3.x > 1.0) ? 4.0 : 5.0;\n"
6204 " gl_TessLevelOuter[3] = (tc_dvec4.x > 1.0) ? 5.0 : 6.0;\n"
6205 " gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6206 " gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6207 "\n"
6208 " if (tc_dvec2_arr[0].y * tc_dvec2_arr[1].y *\n"
6209 " tc_dvec3_arr[0].z * tc_dvec3_arr[1].z *\n"
6210 " tc_dvec4_arr[0].z * tc_dvec4_arr[1].z *\n"
6211 " tc_array[0].struct_double * tc_array[0].struct_dvec2.x * \n"
6212 " tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6213 " tc_array[1].struct_double * tc_array[1].struct_dvec2.x * \n"
6214 " tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6215 " {\n"
6216 " gl_TessLevelInner[1] = 3.0;\n"
6217 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
6218 " }\n"
6219 " else\n"
6220 " {\n"
6221 " gl_TessLevelInner[1] = 0.0;\n"
6222 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position + vec4(1);\n"
6223 " }\n"
6224 "}\n";
6225
6226 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6227 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6228
6229 /* Configure tessellation evaluation shader body */
6230 const char* te_body = "#version 400\n"
6231 "\n"
6232 "uniform double te_double;\n"
6233 "uniform dvec2 te_dvec2;\n"
6234 "uniform dvec3 te_dvec3;\n"
6235 "uniform dvec4 te_dvec4;\n"
6236 "uniform double te_double_arr[2];\n"
6237 "uniform dvec2 te_dvec2_arr [2];\n"
6238 "uniform dvec3 te_dvec3_arr [2];\n"
6239 "uniform dvec4 te_dvec4_arr [2];\n"
6240 "\n"
6241 "uniform struct te_struct\n"
6242 "{\n"
6243 " double struct_double;\n"
6244 " dvec2 struct_dvec2;\n"
6245 " dvec3 struct_dvec3;\n"
6246 " dvec4 struct_dvec4;\n"
6247 "} te_array[2];\n"
6248 "\n"
6249 "layout(triangles) in;\n"
6250 "\n"
6251 "void main()\n"
6252 "{\n"
6253 " if (te_double * te_dvec2.x * te_dvec3.x "
6254 "* te_dvec4.x *\n"
6255 " te_double_arr[0] * te_dvec2_arr[0].x * te_dvec3_arr[0].x "
6256 "* te_dvec4_arr[0].x *\n"
6257 " te_double_arr[1] * te_dvec2_arr[1].x * te_dvec3_arr[1].x "
6258 "* te_dvec4_arr[1].x *\n"
6259 " te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6260 "* te_array[0].struct_dvec4.x *\n"
6261 " te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6262 "* te_array[1].struct_dvec4.x > 1.0)\n"
6263 " {\n"
6264 " gl_Position = gl_in[0].gl_Position;\n"
6265 " }\n"
6266 " else\n"
6267 " {\n"
6268 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6269 " }\n"
6270 "}\n";
6271
6272 gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6273 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6274
6275 /* Configure geometry shader body */
6276 const char* gs_body = "#version 400\n"
6277 "\n"
6278 "uniform double gs_double;\n"
6279 "uniform dvec2 gs_dvec2;\n"
6280 "uniform dvec3 gs_dvec3;\n"
6281 "uniform dvec4 gs_dvec4;\n"
6282 "uniform double gs_double_arr[2];\n"
6283 "uniform dvec2 gs_dvec2_arr [2];\n"
6284 "uniform dvec3 gs_dvec3_arr [2];\n"
6285 "uniform dvec4 gs_dvec4_arr [2];\n"
6286 "\n"
6287 "uniform struct gs_struct\n"
6288 "{\n"
6289 " double struct_double;\n"
6290 " dvec2 struct_dvec2;\n"
6291 " dvec3 struct_dvec3;\n"
6292 " dvec4 struct_dvec4;\n"
6293 "} gs_array[2];\n"
6294 "\n"
6295 "layout (points) in;\n"
6296 "layout (points, max_vertices = 1) out;\n"
6297 "\n"
6298 "void main()\n"
6299 "{\n"
6300 " if (gs_double * gs_dvec2.x * gs_dvec3.x "
6301 "* gs_dvec4.x *\n"
6302 " gs_double_arr[0] * gs_dvec2_arr[0].x * gs_dvec3_arr[0].x "
6303 "* gs_dvec4_arr[0].x *\n"
6304 " gs_double_arr[1] * gs_dvec2_arr[1].x * gs_dvec3_arr[1].x "
6305 "* gs_dvec4_arr[1].x *\n"
6306 " gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6307 "* gs_array[0].struct_dvec4.x *\n"
6308 " gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6309 "* gs_array[1].struct_dvec4.x > 1.0)\n"
6310 " {\n"
6311 " gl_Position = gl_in[0].gl_Position;\n"
6312 " }\n"
6313 " else\n"
6314 " {\n"
6315 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6316 " }\n"
6317 "\n"
6318 " EmitVertex();\n"
6319 "}\n";
6320
6321 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6322 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6323
6324 /* Configure fragment shader body */
6325 const char* fs_body = "#version 400\n"
6326 "\n"
6327 "uniform double fs_double;\n"
6328 "uniform dvec2 fs_dvec2;\n"
6329 "uniform dvec3 fs_dvec3;\n"
6330 "uniform dvec4 fs_dvec4;\n"
6331 "uniform double fs_double_arr[2];\n"
6332 "uniform dvec2 fs_dvec2_arr [2];\n"
6333 "uniform dvec3 fs_dvec3_arr [2];\n"
6334 "uniform dvec4 fs_dvec4_arr [2];\n"
6335 "\n"
6336 "uniform struct fs_struct\n"
6337 "{\n"
6338 " double struct_double;\n"
6339 " dvec2 struct_dvec2;\n"
6340 " dvec3 struct_dvec3;\n"
6341 " dvec4 struct_dvec4;\n"
6342 "} fs_array[2];\n"
6343 "\n"
6344 "out vec4 result;\n"
6345 "\n"
6346 "void main()\n"
6347 "{\n"
6348 " if (fs_double * fs_dvec2.x * fs_dvec3.x "
6349 "* fs_dvec4.x *\n"
6350 " fs_double_arr[0] * fs_dvec2_arr[0].x * fs_dvec3_arr[0].x "
6351 "* fs_dvec4_arr[0].x *\n"
6352 " fs_double_arr[1] * fs_dvec2_arr[1].x * fs_dvec3_arr[1].x "
6353 "* fs_dvec4_arr[1].x *\n"
6354 " fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6355 "* fs_array[0].struct_dvec4.x *\n"
6356 " fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6357 "* fs_array[1].struct_dvec4.x > 1.0)\n"
6358 " {\n"
6359 " result = vec4(0.0);\n"
6360 " }\n"
6361 " else\n"
6362 " {\n"
6363 " result = vec4(1.0);\n"
6364 " }\n"
6365 "}\n";
6366
6367 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6368 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6369
6370 /* Compile the shaders */
6371 const glw::GLuint shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6372 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6373
6374 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6375 {
6376 glw::GLint compile_status = GL_FALSE;
6377 glw::GLuint so_id = shaders[n_shader];
6378
6379 /* Skip compute shader if not supported */
6380 if (0 == so_id)
6381 {
6382 continue;
6383 }
6384
6385 gl.compileShader(so_id);
6386 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6387
6388 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6389 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6390
6391 if (compile_status != GL_TRUE)
6392 {
6393 TCU_FAIL("Shader compilation failed");
6394 }
6395
6396 if (so_id == m_cs_id)
6397 {
6398 gl.attachShader(m_po_cs_id, so_id);
6399 }
6400 else
6401 {
6402 gl.attachShader(m_po_noncs_id, so_id);
6403 }
6404
6405 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6406 } /* for (all shaders) */
6407
6408 /* Link the program */
6409 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6410 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6411 glw::GLint link_status = GL_FALSE;
6412
6413 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6414 {
6415 glw::GLuint po_id = programs[n_program];
6416
6417 /* Skip compute shader program if not supported */
6418 if (0 == po_id)
6419 {
6420 continue;
6421 }
6422
6423 gl.linkProgram(po_id);
6424 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6425
6426 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6427 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6428
6429 if (link_status != GL_TRUE)
6430 {
6431 TCU_FAIL("Program linking failed");
6432 }
6433 } /* for (both program objects) */
6434
6435 /* Retrieve uniform locations */
6436 _stage_data* cs_stage_data[] = { &m_data_cs };
6437 static const char* cs_uniform_prefixes[] = { "cs_" };
6438 static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6439
6440 _stage_data* noncs_stage_data[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6441 static const char* noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6442 static const unsigned int n_noncs_uniform_prefixes =
6443 sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6444
6445 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6446 {
6447 unsigned int n_uniform_prefixes = DE_NULL;
6448 glw::GLuint po_id = programs[n_program];
6449 _stage_data** stages_data = DE_NULL;
6450 const char** uniform_prefixes = DE_NULL;
6451
6452 if (n_program == 0)
6453 {
6454 stages_data = cs_stage_data;
6455 uniform_prefixes = cs_uniform_prefixes;
6456 n_uniform_prefixes = n_cs_uniform_prefixes;
6457 }
6458 else
6459 {
6460 stages_data = noncs_stage_data;
6461 uniform_prefixes = noncs_uniform_prefixes;
6462 n_uniform_prefixes = n_noncs_uniform_prefixes;
6463 }
6464
6465 /* Skip compute shader program if not supported */
6466 if (0 == po_id)
6467 {
6468 continue;
6469 }
6470
6471 /* Uniform names used by the test program consist of a prefix (different for each
6472 * shader stage) and a common part.
6473 */
6474 for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6475 {
6476 _stage_data* stage_data = stages_data[n_uniform_prefix];
6477 std::string uniform_prefix = std::string(uniform_prefixes[n_uniform_prefix]);
6478 std::string uniform_double_name = uniform_prefix + "double";
6479 std::string uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6480 std::string uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6481 std::string uniform_dvec2_name = uniform_prefix + "dvec2";
6482 std::string uniform_dvec2_arr0_name = uniform_prefix + "dvec2_arr[0]";
6483 std::string uniform_dvec2_arr1_name = uniform_prefix + "dvec2_arr[1]";
6484 std::string uniform_dvec3_name = uniform_prefix + "dvec3";
6485 std::string uniform_dvec3_arr0_name = uniform_prefix + "dvec3_arr[0]";
6486 std::string uniform_dvec3_arr1_name = uniform_prefix + "dvec3_arr[1]";
6487 std::string uniform_dvec4_name = uniform_prefix + "dvec4";
6488 std::string uniform_dvec4_arr0_name = uniform_prefix + "dvec4_arr[0]";
6489 std::string uniform_dvec4_arr1_name = uniform_prefix + "dvec4_arr[1]";
6490 std::string uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6491 std::string uniform_arr0_dvec2_name = uniform_prefix + "array[0].struct_dvec2";
6492 std::string uniform_arr0_dvec3_name = uniform_prefix + "array[0].struct_dvec3";
6493 std::string uniform_arr0_dvec4_name = uniform_prefix + "array[0].struct_dvec4";
6494 std::string uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6495 std::string uniform_arr1_dvec2_name = uniform_prefix + "array[1].struct_dvec2";
6496 std::string uniform_arr1_dvec3_name = uniform_prefix + "array[1].struct_dvec3";
6497 std::string uniform_arr1_dvec4_name = uniform_prefix + "array[1].struct_dvec4";
6498
6499 /* Retrieve uniform locations */
6500 stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6501 stage_data->uniforms.uniform_location_double_arr[0] =
6502 gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6503 stage_data->uniforms.uniform_location_double_arr[1] =
6504 gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6505 stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6506 stage_data->uniforms.uniform_location_dvec2_arr[0] =
6507 gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6508 stage_data->uniforms.uniform_location_dvec2_arr[1] =
6509 gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6510 stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6511 stage_data->uniforms.uniform_location_dvec3_arr[0] =
6512 gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6513 stage_data->uniforms.uniform_location_dvec3_arr[1] =
6514 gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6515 stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6516 stage_data->uniforms.uniform_location_dvec4_arr[0] =
6517 gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6518 stage_data->uniforms.uniform_location_dvec4_arr[1] =
6519 gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6520 stage_data->uniform_structure_arrays[0].uniform_location_double =
6521 gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6522 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6523 gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6524 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6525 gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6526 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6527 gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6528 stage_data->uniform_structure_arrays[1].uniform_location_double =
6529 gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6530 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6531 gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6532 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6533 gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6534 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6535 gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6536 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6537
6538 if (stage_data->uniforms.uniform_location_double == -1 ||
6539 stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6540 stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6541 stage_data->uniforms.uniform_location_dvec2 == -1 ||
6542 stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6543 stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6544 stage_data->uniforms.uniform_location_dvec3 == -1 ||
6545 stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6546 stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6547 stage_data->uniforms.uniform_location_dvec4 == -1 ||
6548 stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6549 stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6550 stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6551 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6552 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6553 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6554 stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6555 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6556 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6557 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6558 {
6559 TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6560 }
6561
6562 /* Make sure locations of subsequent items in array uniforms are correct */
6563 if (stage_data->uniforms.uniform_location_double_arr[1] !=
6564 (stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6565 stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6566 (stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6567 stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6568 (stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6569 stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6570 (stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6571 {
6572 m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6573 " double_arr[0]:"
6574 << stage_data->uniforms.uniform_location_double_arr[0]
6575 << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6576 << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6577 << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6578 << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6579 << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6580 << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6581 << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6582 << tcu::TestLog::EndMessage;
6583
6584 TCU_FAIL("Double-precision uniform array item locations are invalid.");
6585 }
6586 } /* for (all uniform prefixes) */
6587 } /* for (both program objects) */
6588 }
6589
6590 /** Initializes all objects required to run the test. */
initTest()6591 void GPUShaderFP64Test4::initTest()
6592 {
6593 initProgramObjects();
6594
6595 generateUniformValues();
6596 initUniformValues();
6597 }
6598
6599 /** Assigns values generated by generateUniformValues() to uniforms defined by
6600 * both program objects.
6601 **/
initUniformValues()6602 void GPUShaderFP64Test4::initUniformValues()
6603 {
6604 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6605
6606 /* Iterate through all programs */
6607 _stage_data* cs_stages[] = { &m_data_cs };
6608 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6609 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6610 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6611
6612 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6613 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6614
6615 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6616 {
6617 glw::GLuint po_id = programs[n_program];
6618 unsigned int n_stages = 0;
6619 _stage_data** stage_data = DE_NULL;
6620
6621 if (po_id == m_po_cs_id)
6622 {
6623 n_stages = n_cs_stages;
6624 stage_data = cs_stages;
6625 }
6626 else
6627 {
6628 n_stages = n_noncs_stages;
6629 stage_data = noncs_stages;
6630 }
6631
6632 /* Skip compute shader program if not supported */
6633 if (0 == po_id)
6634 {
6635 continue;
6636 }
6637
6638 gl.useProgram(po_id);
6639 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6640
6641 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6642 {
6643 /* Iterate through all uniforms */
6644 _stage_data* stage_ptr = stage_data[n_stage];
6645
6646 gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6647 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6648 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6649 gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6650 stage_ptr->uniform_structure_arrays[0].uniform_double);
6651 gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6652 stage_ptr->uniform_structure_arrays[1].uniform_double);
6653 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6654
6655 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6656 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6657 stage_ptr->uniforms.uniform_dvec2_arr + 0);
6658 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6659 stage_ptr->uniforms.uniform_dvec2_arr + 2);
6660 gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6661 stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6662 gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6663 stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6664 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6665
6666 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6667 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6668 stage_ptr->uniforms.uniform_dvec3_arr + 0);
6669 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6670 stage_ptr->uniforms.uniform_dvec3_arr + 3);
6671 gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6672 stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6673 gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6674 stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6675 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6676
6677 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6678 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6679 stage_ptr->uniforms.uniform_dvec4_arr + 0);
6680 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6681 stage_ptr->uniforms.uniform_dvec4_arr + 4);
6682 gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6683 stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6684 gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6685 stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6686 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6687 } /* for (all shader stages) */
6688 } /* for (both program objects) */
6689 }
6690
6691 /** Executes test iteration.
6692 *
6693 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6694 */
iterate()6695 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6696 {
6697 /* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6698
6699 /* Initialize all objects required to run the test */
6700 initTest();
6701
6702 /* Verify the implementation reports correct values for all stages we've configured */
6703 m_has_test_passed &= verifyUniformValues();
6704
6705 /* Is this also the case when "program interface query" mechanism is used? */
6706 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6707 {
6708 m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6709 }
6710
6711 /* We're done */
6712 if (m_has_test_passed)
6713 {
6714 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6715 }
6716 else
6717 {
6718 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6719 }
6720
6721 return STOP;
6722 }
6723
6724 /** Verifies that:
6725 *
6726 * a) glGetProgramResourceIndex()
6727 * b) glGetProgramResourceiv()
6728 * c) glGetProgramResourceName()
6729 *
6730 * functions return correct values for double-precision uniforms.
6731 *
6732 * @return true if the verification was passed, false otherwise.
6733 */
verifyProgramInterfaceQuerySupport()6734 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6735 {
6736 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6737 bool result = true;
6738
6739 /* Iterate through all programs */
6740 const char* cs_prefixes[] = { "cs_" };
6741 _stage_data* cs_stages[] = { &m_data_cs };
6742 const char* noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6743 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6744 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6745 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6746
6747 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6748 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6749
6750 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6751 {
6752 glw::GLuint po_id = programs[n_program];
6753 unsigned int n_stages = 0;
6754 const char** stage_prefixes = DE_NULL;
6755 _stage_data** stage_data = DE_NULL;
6756
6757 if (po_id == m_po_cs_id)
6758 {
6759 n_stages = n_cs_stages;
6760 stage_data = cs_stages;
6761 stage_prefixes = cs_prefixes;
6762 }
6763 else
6764 {
6765 n_stages = n_noncs_stages;
6766 stage_data = noncs_stages;
6767 stage_prefixes = noncs_prefixes;
6768 }
6769
6770 /* Skip compute shader program if not supported */
6771 if (0 == po_id)
6772 {
6773 continue;
6774 }
6775
6776 /* Determine maximum uniform name length */
6777 glw::GLint max_uniform_name_length = 0;
6778
6779 gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6780 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6781
6782 /* Allocate a buffer we will use to hold uniform names */
6783 m_uniform_name_buffer = new char[max_uniform_name_length];
6784
6785 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6786 {
6787 /* Iterate through all uniforms */
6788 _stage_data* stage_ptr = stage_data[n_stage];
6789 const char* stage_prefix = stage_prefixes[n_stage];
6790
6791 /* Construct an array that will be used to run the test in an automated manner */
6792 _program_interface_query_test_item uniforms[] = {
6793 /* array size */ /* name */ /* type */ /* location */
6794 { 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6795 { 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6796 { 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6797 { 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6798 { 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6799 { 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6800 { 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6801 { 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6802 { 1, "array[0].struct_double", GL_DOUBLE,
6803 stage_ptr->uniform_structure_arrays->uniform_location_double },
6804 { 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6805 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6806 { 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6807 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6808 { 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6809 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6810 { 1, "array[1].struct_double", GL_DOUBLE,
6811 stage_ptr->uniform_structure_arrays->uniform_location_double },
6812 { 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6813 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6814 { 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6815 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6816 { 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6817 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6818 };
6819 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6820
6821 /* Prefix the names with stage-specific string */
6822 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6823 {
6824 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6825
6826 current_item.name = std::string(stage_prefix) + current_item.name;
6827 } /* for (all uniform descriptors) */
6828
6829 const glw::GLenum properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6830 const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6831
6832 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6833 {
6834 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6835 glw::GLint n_written_items = 0;
6836 glw::GLint retrieved_array_size = 0;
6837 glw::GLint retrieved_name_length = 0;
6838 glw::GLenum retrieved_type = GL_NONE;
6839 glw::GLint temp_buffer[2] = { 0, GL_NONE };
6840
6841 /* Retrieve index of the iteration-specific uniform */
6842 glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6843 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6844
6845 /* Make sure glGetProgramResourceName() returns correct values */
6846 memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6847
6848 gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6849 resource_index, max_uniform_name_length, &retrieved_name_length,
6850 m_uniform_name_buffer);
6851 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6852
6853 if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6854 memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6855 {
6856 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6857 << resource_index << "]"
6858 ": expected:["
6859 << current_item.name << "]"
6860 ", reported:["
6861 << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6862
6863 result = false;
6864 continue;
6865 }
6866
6867 /* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6868 gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6869 resource_index, n_properties, properties,
6870 sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6871 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6872
6873 if (n_written_items != n_properties)
6874 {
6875 TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6876 }
6877
6878 /* For clarity, copy the retrieved values to separate variables */
6879 retrieved_array_size = temp_buffer[0];
6880 retrieved_type = temp_buffer[1];
6881
6882 /* Verify the values */
6883 if (retrieved_array_size != current_item.expected_array_size)
6884 {
6885 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6886 << current_item.name << "]"
6887 << ": expected:[" << current_item.expected_array_size << "]"
6888 ", reported:["
6889 << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6890
6891 result = false;
6892 }
6893
6894 if (retrieved_type != current_item.expected_type)
6895 {
6896 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6897 << current_item.name << "]"
6898 << ": expected:[" << current_item.expected_type << "]"
6899 ", reported:["
6900 << retrieved_type << "]" << tcu::TestLog::EndMessage;
6901
6902 result = false;
6903 }
6904 } /* for (all uniforms) */
6905 } /* for (all shader stages) */
6906
6907 /* We're now OK to release the buffer we used to hold uniform names for
6908 * the program */
6909 if (m_uniform_name_buffer != DE_NULL)
6910 {
6911 delete[] m_uniform_name_buffer;
6912
6913 m_uniform_name_buffer = DE_NULL;
6914 }
6915 } /* for (both program objects) */
6916
6917 return result;
6918 }
6919
6920 /** Verifies glGetUniform*() calls return correct values assigned to
6921 * double-precision uniforms.
6922 *
6923 * @return true if all values reported by OpenGL were found to be correct,
6924 * false otherwise.
6925 **/
verifyUniformValues()6926 bool GPUShaderFP64Test4::verifyUniformValues()
6927 {
6928 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6929 bool result = true;
6930
6931 /* Iterate through all programs */
6932 _stage_data* cs_stages[] = { &m_data_cs };
6933 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6934 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6935 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6936
6937 const glw::GLuint programs[] = {
6938 m_po_noncs_id, m_po_cs_id,
6939 };
6940 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6941
6942 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6943 {
6944 glw::GLuint po_id = programs[n_program];
6945 unsigned int n_stages = 0;
6946 _stage_data** stage_data = DE_NULL;
6947
6948 if (po_id == m_po_cs_id)
6949 {
6950 n_stages = n_cs_stages;
6951 stage_data = cs_stages;
6952 }
6953 else
6954 {
6955 n_stages = n_noncs_stages;
6956 stage_data = noncs_stages;
6957 }
6958
6959 /* Skip compute shader program if not supported */
6960 if (0 == po_id)
6961 {
6962 continue;
6963 }
6964
6965 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6966 {
6967 /* Iterate through all uniforms */
6968 _stage_data* stage_ptr = stage_data[n_stage];
6969
6970 /* Set up arrays that we will guide the automated testing */
6971 const uniform_value_pair double_uniforms[] = {
6972 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6973 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6974 stage_ptr->uniforms.uniform_double_arr + 0),
6975 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6976 stage_ptr->uniforms.uniform_double_arr + 1),
6977 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6978 &stage_ptr->uniform_structure_arrays[0].uniform_double),
6979 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6980 &stage_ptr->uniform_structure_arrays[1].uniform_double)
6981 };
6982 const uniform_value_pair dvec2_uniforms[] = {
6983 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6984 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6985 stage_ptr->uniforms.uniform_dvec2_arr + 0),
6986 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6987 stage_ptr->uniforms.uniform_dvec2_arr + 2),
6988 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6989 stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6990 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6991 stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6992 };
6993 const uniform_value_pair dvec3_uniforms[] = {
6994 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6995 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6996 stage_ptr->uniforms.uniform_dvec3_arr + 0),
6997 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6998 stage_ptr->uniforms.uniform_dvec3_arr + 3),
6999 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
7000 stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
7001 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
7002 stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7003 };
7004 const uniform_value_pair dvec4_uniforms[] = {
7005 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7006 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7007 stage_ptr->uniforms.uniform_dvec4_arr + 0),
7008 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7009 stage_ptr->uniforms.uniform_dvec4_arr + 4),
7010 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7011 stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7012 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7013 stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7014 };
7015
7016 /* Iterate over all uniforms and verify the values reported by the API */
7017 double returned_double_data[4];
7018 float returned_float_data[4];
7019 int returned_int_data[4];
7020 unsigned int returned_uint_data[4];
7021
7022 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7023 {
7024 const uniform_value_pair* current_uv_pairs = NULL;
7025 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7026 unsigned int n_pairs = 0;
7027
7028 switch (n_type)
7029 {
7030 case 0: /* double */
7031 {
7032 current_uv_pairs = double_uniforms;
7033 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7034
7035 break;
7036 }
7037
7038 case 1: /* dvec2 */
7039 {
7040 current_uv_pairs = dvec2_uniforms;
7041 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7042
7043 break;
7044 }
7045
7046 case 2: /* dvec3 */
7047 {
7048 current_uv_pairs = dvec3_uniforms;
7049 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7050
7051 break;
7052 }
7053
7054 case 3: /* dvec4 */
7055 {
7056 current_uv_pairs = dvec4_uniforms;
7057 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7058
7059 break;
7060 }
7061
7062 default:
7063 {
7064 TCU_FAIL("Invalid type index requested");
7065 }
7066 } /* switch (n_type) */
7067
7068 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7069 {
7070 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair];
7071 glw::GLint uniform_location = current_uv_pair.first;
7072 const double* uniform_value = current_uv_pair.second;
7073
7074 /* Retrieve the values from the GL implementation*/
7075 gl.getUniformdv(po_id, uniform_location, returned_double_data);
7076 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7077
7078 gl.getUniformfv(po_id, uniform_location, returned_float_data);
7079 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7080
7081 gl.getUniformiv(po_id, uniform_location, returned_int_data);
7082 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7083
7084 gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7085 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7086
7087 /* Make sure the values reported match the reference values */
7088 bool can_continue = true;
7089 const float epsilon = 1e-5f;
7090
7091 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7092 {
7093 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7094 {
7095 m_testCtx.getLog()
7096 << tcu::TestLog::Message
7097 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7098 << uniform_location << "]"
7099 " and component ["
7100 << n_component << "]"
7101 ": retrieved:["
7102 << returned_double_data[n_component] << "]"
7103 ", expected:["
7104 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7105
7106 result = false;
7107 }
7108
7109 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7110 {
7111 m_testCtx.getLog()
7112 << tcu::TestLog::Message
7113 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7114 << uniform_location << "]"
7115 " and component ["
7116 << n_component << "]"
7117 ": retrieved:["
7118 << returned_float_data[n_component] << "]"
7119 ", expected:["
7120 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7121
7122 result = false;
7123 }
7124
7125 /* ints */
7126 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7127 unsigned int rounded_uniform_value_uint =
7128 (unsigned int)(uniform_value[n_component] > 0.0) ?
7129 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7130 0;
7131
7132 if (returned_int_data[n_component] != rounded_uniform_value_sint)
7133 {
7134 m_testCtx.getLog()
7135 << tcu::TestLog::Message
7136 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7137 << uniform_location << "]"
7138 " and component ["
7139 << n_component << "]"
7140 ": retrieved:["
7141 << returned_int_data[n_component] << "]"
7142 ", expected:["
7143 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7144
7145 result = false;
7146 }
7147
7148 if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7149 {
7150 m_testCtx.getLog()
7151 << tcu::TestLog::Message
7152 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7153 << uniform_location << "]"
7154 " and component ["
7155 << n_component << "]"
7156 ": retrieved:["
7157 << returned_uint_data[n_component] << "]"
7158 ", expected:["
7159 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7160
7161 result = false;
7162 }
7163 } /* for (all components) */
7164 } /* for (all uniform+value pairs) */
7165 } /* for (all 4 uniform types) */
7166 } /* for (all shader stages) */
7167 } /* for (both program objects) */
7168
7169 /* All done! */
7170 return result;
7171 }
7172
7173 /** Constructor
7174 *
7175 * @param context Rendering context.
7176 */
GPUShaderFP64Test5(deqp::Context& context)7177 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7178 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7179 " floating-point variables work correctly")
7180 , m_base_value_bo_data(DE_NULL)
7181 , m_base_value_bo_id(0)
7182 , m_has_test_passed(true)
7183 , m_po_base_value_attribute_location(-1)
7184 , m_po_id(0)
7185 , m_vao_id(0)
7186 , m_vs_id(0)
7187 , m_xfb_bo_id(0)
7188 , m_xfb_bo_size(0)
7189 {
7190 /* Set up base value array (as per test spec) */
7191 m_base_values[0] = -25.12065f;
7192 m_base_values[1] = 0.0f;
7193 m_base_values[2] = 0.001f;
7194 m_base_values[3] = 1.0f;
7195 m_base_values[4] = 256.78901f;
7196
7197 /* Set up swizzle matrix */
7198 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7199 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7200 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7201 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7202 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7203 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7204 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7205 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7206 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7207 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7208 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7209 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7210 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7211 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7212 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7213 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7214 }
7215
deinit()7216 void GPUShaderFP64Test5::deinit()
7217 {
7218 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7219
7220 if (m_base_value_bo_data != DE_NULL)
7221 {
7222 delete[] m_base_value_bo_data;
7223
7224 m_base_value_bo_data = DE_NULL;
7225 }
7226
7227 if (m_base_value_bo_id != 0)
7228 {
7229 gl.deleteBuffers(1, &m_base_value_bo_id);
7230
7231 m_base_value_bo_id = 0;
7232 }
7233
7234 if (m_vao_id != 0)
7235 {
7236 gl.deleteVertexArrays(1, &m_vao_id);
7237
7238 m_vao_id = 0;
7239 }
7240
7241 if (m_xfb_bo_id != 0)
7242 {
7243 gl.deleteBuffers(1, &m_xfb_bo_id);
7244
7245 m_xfb_bo_id = 0;
7246 }
7247
7248 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7249 * take care of it here
7250 */
7251 deinitInteration();
7252 }
7253
7254 /** Deinitializes all buffers and GL objects that may have been generated
7255 * during test execution.
7256 **/
deinitInteration()7257 void GPUShaderFP64Test5::deinitInteration()
7258 {
7259 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7260
7261 if (m_po_id != 0)
7262 {
7263 gl.deleteProgram(m_po_id);
7264
7265 m_po_id = 0;
7266 }
7267
7268 if (m_vs_id != 0)
7269 {
7270 gl.deleteShader(m_vs_id);
7271
7272 m_vs_id = 0;
7273 }
7274 }
7275
7276 /** Executes a single test case iteration using user-provided test case descriptor.
7277 *
7278 * This function may throw a TestError exception if GL implementation misbehaves.
7279 *
7280 * @param test_case Test case descriptor to use.
7281 *
7282 * @return true if the values returned by GL implementation were found to be valid,
7283 * false otherwise.
7284 **/
executeIteration(const _test_case& test_case)7285 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7286 {
7287 bool result = true;
7288
7289 /* Convert the base values array to the type of input attribute we'll be using
7290 * for the iteration.
7291 */
7292 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7293
7294 if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7295 {
7296 /* bools are actually represented by ints, since bool varyings are not allowed */
7297 base_value_type = Utils::VARIABLE_TYPE_INT;
7298 }
7299
7300 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7301 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7302
7303 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7304
7305 unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7306
7307 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7308 {
7309 switch (base_value_type)
7310 {
7311 case Utils::VARIABLE_TYPE_DOUBLE:
7312 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7313 break;
7314 case Utils::VARIABLE_TYPE_FLOAT:
7315 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7316 break;
7317 case Utils::VARIABLE_TYPE_INT:
7318 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7319 break;
7320 case Utils::VARIABLE_TYPE_UINT:
7321 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7322 break;
7323
7324 default:
7325 {
7326 TCU_FAIL("Unrecognized base value type");
7327 }
7328 }
7329
7330 base_value_traveller_ptr += base_value_component_size;
7331 } /* for (all base values) */
7332
7333 /* Update buffer object storage with the data we've just finished preparing. */
7334 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7335
7336 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7337 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7338
7339 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7340 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7341
7342 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7343 * new data is interpreted correctly.
7344 */
7345 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7346 {
7347 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */
7348 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7349 0, /* stride */
7350 DE_NULL); /* pointer */
7351 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7352 }
7353 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7354 {
7355 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */
7356 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7357 DE_NULL); /* pointer */
7358 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7359 }
7360 else
7361 {
7362 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7363
7364 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7365 GL_DOUBLE, 0, /* stride */
7366 DE_NULL); /* pointer */
7367 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7368 }
7369
7370 gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7371 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7372
7373 /* Execute the draw call */
7374 gl.useProgram(m_po_id);
7375 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7376
7377 gl.beginTransformFeedback(GL_POINTS);
7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7379 {
7380 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7381 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7382 }
7383 gl.endTransformFeedback();
7384 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7385
7386 /* Map the XFB buffer object into process space */
7387 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7388
7389 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7390 DE_ASSERT(xfb_data_ptr != NULL);
7391
7392 /* Verify the data */
7393 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7394
7395 /* Unmap the XFB BO */
7396 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7397 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7398
7399 /** Good to release the data buffer at this point */
7400 if (m_base_value_bo_data != DE_NULL)
7401 {
7402 delete[] m_base_value_bo_data;
7403
7404 m_base_value_bo_data = DE_NULL;
7405 }
7406
7407 /* All done */
7408 return result;
7409 }
7410
7411 /** Returns properties of a swizzle operator described by @param type swizzle type.
7412 *
7413 * @param out_swizzle_string Deref will be used to store a GLSL literal
7414 * corresponding to the specific swizzle operator.
7415 * Must not be NULL.
7416 * @param out_n_components Deref will be used to store the amount of components
7417 * used by the operator. Must not be NULL.
7418 * @param out_component_order Deref will be used to store up to 4 integer values,
7419 * corresponding to component indices described by the
7420 * operator for a particular position. Must not be NULL.
7421 **/
getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string, unsigned int* out_n_components, unsigned int* out_component_order)7422 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7423 unsigned int* out_n_components, unsigned int* out_component_order)
7424 {
7425 unsigned int result_component_order[4] = { 0 };
7426 unsigned int result_n_components = 0;
7427 std::string result_swizzle_string;
7428
7429 switch (type)
7430 {
7431 case SWIZZLE_TYPE_NONE:
7432 {
7433 result_swizzle_string = "";
7434 result_n_components = 0;
7435
7436 break;
7437 }
7438
7439 case SWIZZLE_TYPE_XWZY:
7440 {
7441 result_swizzle_string = "xwzy";
7442 result_n_components = 4;
7443 result_component_order[0] = 0;
7444 result_component_order[1] = 3;
7445 result_component_order[2] = 2;
7446 result_component_order[3] = 1;
7447
7448 break;
7449 }
7450
7451 case SWIZZLE_TYPE_XZXY:
7452 {
7453 result_swizzle_string = "xzxy";
7454 result_n_components = 4;
7455 result_component_order[0] = 0;
7456 result_component_order[1] = 2;
7457 result_component_order[2] = 0;
7458 result_component_order[3] = 1;
7459
7460 break;
7461 }
7462
7463 case SWIZZLE_TYPE_XZY:
7464 {
7465 result_swizzle_string = "xzy";
7466 result_n_components = 3;
7467 result_component_order[0] = 0;
7468 result_component_order[1] = 2;
7469 result_component_order[2] = 1;
7470
7471 break;
7472 }
7473
7474 case SWIZZLE_TYPE_XZYW:
7475 {
7476 result_swizzle_string = "xzyw";
7477 result_n_components = 4;
7478 result_component_order[0] = 0;
7479 result_component_order[1] = 2;
7480 result_component_order[2] = 1;
7481 result_component_order[3] = 3;
7482
7483 break;
7484 }
7485
7486 case SWIZZLE_TYPE_Y:
7487 {
7488 result_swizzle_string = "y";
7489 result_n_components = 1;
7490 result_component_order[0] = 1;
7491
7492 break;
7493 }
7494
7495 case SWIZZLE_TYPE_YX:
7496 {
7497 result_swizzle_string = "yx";
7498 result_n_components = 2;
7499 result_component_order[0] = 1;
7500 result_component_order[1] = 0;
7501
7502 break;
7503 }
7504
7505 case SWIZZLE_TYPE_YXX:
7506 {
7507 result_swizzle_string = "yxx";
7508 result_n_components = 3;
7509 result_component_order[0] = 1;
7510 result_component_order[1] = 0;
7511 result_component_order[2] = 0;
7512
7513 break;
7514 }
7515
7516 case SWIZZLE_TYPE_YXXY:
7517 {
7518 result_swizzle_string = "yxxy";
7519 result_n_components = 4;
7520 result_component_order[0] = 1;
7521 result_component_order[1] = 0;
7522 result_component_order[2] = 0;
7523 result_component_order[3] = 1;
7524
7525 break;
7526 }
7527
7528 case SWIZZLE_TYPE_Z:
7529 {
7530 result_swizzle_string = "z";
7531 result_n_components = 1;
7532 result_component_order[0] = 2;
7533
7534 break;
7535 }
7536
7537 case SWIZZLE_TYPE_ZY:
7538 {
7539 result_swizzle_string = "zy";
7540 result_n_components = 2;
7541 result_component_order[0] = 2;
7542 result_component_order[1] = 1;
7543
7544 break;
7545 }
7546
7547 case SWIZZLE_TYPE_W:
7548 {
7549 result_swizzle_string = "w";
7550 result_n_components = 1;
7551 result_component_order[0] = 3;
7552
7553 break;
7554 }
7555
7556 case SWIZZLE_TYPE_WX:
7557 {
7558 result_swizzle_string = "wx";
7559 result_n_components = 2;
7560 result_component_order[0] = 3;
7561 result_component_order[1] = 0;
7562
7563 break;
7564 }
7565
7566 default:
7567 {
7568 TCU_FAIL("Unrecognized swizzle type");
7569 }
7570 } /* switch (type) */
7571
7572 if (out_swizzle_string != DE_NULL)
7573 {
7574 *out_swizzle_string = result_swizzle_string;
7575 }
7576
7577 if (out_n_components != DE_NULL)
7578 {
7579 *out_n_components = result_n_components;
7580 }
7581
7582 if (out_component_order != DE_NULL)
7583 {
7584 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7585 }
7586 }
7587
7588 /** Returns body of a vertex shader that should be used for particular test case,
7589 * given user-specified test case descriptor.
7590 *
7591 * @param test_case Descriptor to use for the query.
7592 *
7593 * @return Requested data.
7594 **/
getVertexShaderBody(const _test_case& test_case)7595 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7596 {
7597 std::stringstream result;
7598 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7599 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type);
7600 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7601 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7602 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type);
7603
7604 /* Add version preamble */
7605 result << "#version 420\n"
7606 "\n";
7607
7608 /* Declare output variables. Note that boolean output variables are not supported, so we need
7609 * to handle that special case correctly */
7610 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7611 {
7612 result << "out int result;\n";
7613 }
7614 else
7615 {
7616 result << "out " << dst_type_string << " result;\n";
7617 }
7618
7619 /* Declare input variables. Handle the bool case exclusively. */
7620 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7621 {
7622 /* Use ints for bools. We will cast them to bool in the code later. */
7623 result << "in int base_value;\n";
7624 }
7625 else
7626 {
7627 result << "in " << base_type_string << " base_value;\n";
7628 }
7629
7630 /* Declare main() and construct the value we will be casting from.
7631 *
7632 * Note: Addition operations on bool values cause an implicit conversion to int
7633 * which is not allowed. Hence, we skip these operations for this special
7634 * case.
7635 */
7636 result << "void main()\n"
7637 "{\n"
7638 << src_type_string << " lside_value = ";
7639
7640 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7641 {
7642 result << src_type_string << "(0 != ";
7643 }
7644 else
7645 {
7646 result << src_type_string << "(";
7647 }
7648
7649 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7650 {
7651 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7652 {
7653 result << "base_value + " << n_component;
7654
7655 if (n_component != (n_src_components - 1))
7656 {
7657 result << ", ";
7658 }
7659 } /* for (all components) */
7660 }
7661 else
7662 {
7663 DE_ASSERT(n_src_components == 1);
7664
7665 result << "base_value";
7666 }
7667
7668 result << ");\n";
7669
7670 /* Perform the casting operation. Add swizzle operator if possible. */
7671 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7672 {
7673 /* Handle the bool case exclusively */
7674 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7675 {
7676 result << "result = (bool(lside_value) == false) ? 0 : 1";
7677 }
7678 else
7679 {
7680 result << "result = (lside_value == false) ? 0 : 1";
7681 }
7682 }
7683 else
7684 {
7685 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7686 {
7687 result << "result = " << dst_type_string << "(lside_value)";
7688 }
7689 else
7690 {
7691 result << "result = lside_value";
7692 }
7693 }
7694
7695 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7696 {
7697 /* Add a swizzle operator */
7698 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7699 DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7700
7701 unsigned int swizzle_component_order[4] = { 0 };
7702 unsigned int swizzle_n_components = 0;
7703 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7704 std::string swizzle_string;
7705
7706 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7707
7708 if (swizzle_n_components > 0)
7709 {
7710 result << "." << swizzle_string;
7711 }
7712 }
7713
7714 /* Close the shader implementation. */
7715 result << ";\n"
7716 "}\n";
7717
7718 return result.str();
7719 }
7720
7721 /** Initializes program & shader objects needed to run the iteration, given
7722 * user-specified test case descriptor.
7723 *
7724 * This function can throw a TestError exception if a GL error is detected
7725 * during execution.
7726 *
7727 * @param test_case Descriptor to use for the iteration.
7728 **/
initIteration(_test_case& test_case)7729 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7730 {
7731 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7732
7733 /* Create program & shader objects */
7734 m_po_id = gl.createProgram();
7735 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7736
7737 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7738 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7739
7740 /* Configure shader body */
7741 std::string body = getVertexShaderBody(test_case);
7742 const char* body_raw_ptr = body.c_str();
7743
7744 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7745 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7746
7747 /* Store it in the test case descriptor for logging purposes */
7748 test_case.shader_body = body;
7749
7750 /* Compile the shader */
7751 glw::GLint compile_status = GL_FALSE;
7752
7753 gl.compileShader(m_vs_id);
7754 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7755
7756 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7757 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7758
7759 if (compile_status != GL_TRUE)
7760 {
7761 TCU_FAIL("Shader compilation failed");
7762 }
7763
7764 /* Attach the shader to the program obejct */
7765 gl.attachShader(m_po_id, m_vs_id);
7766 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7767
7768 /* Configure XFB for the program object */
7769 const char* xfb_varying_name = "result";
7770
7771 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7772 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7773
7774 /* Link the program object */
7775 glw::GLint link_status = GL_FALSE;
7776
7777 gl.linkProgram(m_po_id);
7778 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7779
7780 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7781 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7782
7783 if (link_status != GL_TRUE)
7784 {
7785 TCU_FAIL("Program linking failed");
7786 }
7787
7788 /* Retrieve attribute locations */
7789 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7790 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7791
7792 if (m_po_base_value_attribute_location == -1)
7793 {
7794 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7795 }
7796 }
7797
7798 /** Initializes GL objects used by all test cases.
7799 *
7800 * This function may throw a TestError exception if GL implementation reports
7801 * an error at any point.
7802 **/
initTest()7803 void GPUShaderFP64Test5::initTest()
7804 {
7805 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7806
7807 /* Generate buffer object IDs */
7808 gl.genBuffers(1, &m_base_value_bo_id);
7809 gl.genBuffers(1, &m_xfb_bo_id);
7810 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7811
7812 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7813 * will never eat up more than 1 double (as per test spec) and we will be drawing
7814 * as many points in a single draw call as there are defined in m_base_values array.
7815 */
7816 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7817
7818 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7819 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7820
7821 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7822 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7823
7824 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7825 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7826 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7827 */
7828 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7829
7830 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7831 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7832
7833 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7834 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7835
7836 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7837 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7838
7839 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7840 m_xfb_bo_size = xfb_bo_size;
7841
7842 /* Generate a vertex array object we will need to use for the draw calls */
7843 gl.genVertexArrays(1, &m_vao_id);
7844 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7845
7846 gl.bindVertexArray(m_vao_id);
7847 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7848 }
7849
7850 /** Executes test iteration.
7851 *
7852 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7853 */
iterate()7854 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7855 {
7856 /* Do not execute the test if GL_ARB_texture_view is not supported */
7857 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7858 {
7859 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7860 }
7861
7862 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7863 {
7864 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7865 }
7866
7867 /* Initialize GL objects needed to run the tests */
7868 initTest();
7869
7870 /* Build iteration array to run the tests in an automated manner */
7871 _test_case test_cases[] = {
7872 /* test case type */ /* source type */ /* destination type */
7873 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7874 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7875 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7876 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7877 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7878 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7879 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7880 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7881 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7882 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7883 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7884 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7885 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7886 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7887 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7888 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7889 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7890 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7891 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7892 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7893 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7894
7895 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7896 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7897 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7898 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7899 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7900 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7901 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7902 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7903 };
7904 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7905
7906 /* Execute all iterations */
7907 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7908 {
7909 _test_case& test_case = test_cases[n_test_case];
7910
7911 /* Initialize a program object we will use to perform the casting */
7912 initIteration(test_case);
7913
7914 /* Use the program object to XFB the results */
7915 m_has_test_passed &= executeIteration(test_case);
7916
7917 /* Release the GL Resource for this sub test */
7918 deinitInteration();
7919
7920 } /* for (all test cases) */
7921 /* We're done */
7922 if (m_has_test_passed)
7923 {
7924 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7925 }
7926 else
7927 {
7928 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7929 }
7930
7931 return STOP;
7932 }
7933
7934 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7935 * for which the data have been generated.
7936 *
7937 * @param data_ptr Buffer holding the data XFBed out by the shader.
7938 * @param test_case Descriptor of the test case, for which the vertex shader was
7939 * generated.
7940 *
7941 * @return true if the data were found to be valid, false otherwise.
7942 **/
verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)7943 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7944 {
7945 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
7946 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
7947 const float epsilon = 1e-5f;
7948 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7949 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7950 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7951 bool result = true;
7952 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE;
7953 unsigned int swizzle_order[4] = { 0 };
7954 const unsigned char* traveller_ptr = data_ptr;
7955
7956 if (!Utils::isMatrixVariableType(test_case.src_type))
7957 {
7958 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7959 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7960
7961 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7962
7963 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7964 DE_NULL, /* out_n_components */
7965 swizzle_order);
7966 }
7967
7968 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7969 {
7970 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7971 {
7972 unsigned int n_swizzled_component = n_result_component;
7973
7974 if (swizzle_operator != SWIZZLE_TYPE_NONE)
7975 {
7976 n_swizzled_component =
7977 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7978 }
7979
7980 switch (base_dst_type)
7981 {
7982 case Utils::VARIABLE_TYPE_BOOL:
7983 case Utils::VARIABLE_TYPE_INT:
7984 {
7985 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7986 double expected_value = ref_expected_value;
7987 int result_value = *((int*)traveller_ptr);
7988
7989 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7990 {
7991 if (expected_value != 0.0)
7992 {
7993 expected_value = 1.0;
7994 }
7995 }
7996
7997 if (result_value != (int)expected_value)
7998 {
7999 m_testCtx.getLog() << tcu::TestLog::Message
8000 << "Invalid boolean/integer value obtained when doing an "
8001 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8002 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8003 << "]"
8004 ", component index: ["
8005 << n_swizzled_component << "]"
8006 ", value: ["
8007 << ref_expected_value << "]"
8008 " to GLSL type ["
8009 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8010 ", retrieved value: ["
8011 << result_value << "]"
8012 ", expected value: ["
8013 << (int)expected_value << "]"
8014 ", shader used:\n"
8015 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8016
8017 result = false;
8018 }
8019
8020 traveller_ptr += sizeof(int);
8021 break;
8022 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8023
8024 case Utils::VARIABLE_TYPE_DOUBLE:
8025 {
8026 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8027 double expected_value = ref_expected_value;
8028 double result_value = *((double*)traveller_ptr);
8029
8030 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8031 {
8032 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8033 }
8034 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8035 {
8036 expected_value = (int)expected_value;
8037 }
8038 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8039 {
8040 // Negative values in base values array when converted to unsigned int will be ZERO
8041 // Addition operations done inside the shader in such cases will operate on ZERO rather
8042 // than the negative value being passed.
8043 // Replicate the sequence of conversion and addition operations done on the
8044 // shader input, to calculate the expected values in XFB data in the
8045 // problematic cases.
8046 if (expected_value < 0)
8047 {
8048 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8049 }
8050 expected_value = (unsigned int)expected_value;
8051 }
8052
8053 traveller_ptr += sizeof(double);
8054 if (de::abs(result_value - expected_value) > epsilon)
8055 {
8056 m_testCtx.getLog() << tcu::TestLog::Message
8057 << "Invalid double-precision floating-point value obtained when doing an "
8058 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8059 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8060 << "]"
8061 ", component index: ["
8062 << n_swizzled_component << "]"
8063 ", value: ["
8064 << ref_expected_value << "]"
8065 " to GLSL type ["
8066 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8067 ", retrieved value: ["
8068 << std::setprecision(16) << result_value << "]"
8069 ", expected value: ["
8070 << std::setprecision(16) << expected_value << "]"
8071 ", shader used:\n"
8072 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8073
8074 result = false;
8075 }
8076
8077 break;
8078 } /* VARIABLE_TYPE_DOUBLE case */
8079
8080 case Utils::VARIABLE_TYPE_FLOAT:
8081 {
8082 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8083 float expected_value = ref_expected_value;
8084 float result_value = *((float*)traveller_ptr);
8085
8086 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8087 {
8088 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8089 }
8090 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8091 {
8092 expected_value = (float)((int)expected_value);
8093 }
8094 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8095 {
8096 expected_value = (float)((unsigned int)expected_value);
8097 }
8098
8099 traveller_ptr += sizeof(float);
8100 if (de::abs(result_value - expected_value) > epsilon)
8101 {
8102 m_testCtx.getLog() << tcu::TestLog::Message
8103 << "Invalid single-precision floating-point value obtained when doing an "
8104 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8105 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8106 << "]"
8107 ", component index: ["
8108 << n_swizzled_component << "]"
8109 ", value: ["
8110 << ref_expected_value << "]"
8111 " to GLSL type ["
8112 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8113 ", retrieved value: ["
8114 << std::setprecision(16) << result_value << "]"
8115 ", expected value: ["
8116 << std::setprecision(16) << expected_value << "]"
8117 ", shader used:\n"
8118 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8119
8120 result = false;
8121 }
8122
8123 break;
8124 } /* VARIABLE_TYPE_FLOAT case */
8125
8126 case Utils::VARIABLE_TYPE_UINT:
8127 {
8128 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8129 double expected_value = ref_expected_value;
8130 unsigned int result_value = *((unsigned int*)traveller_ptr);
8131
8132 traveller_ptr += sizeof(unsigned int);
8133 if (result_value != (unsigned int)expected_value)
8134 {
8135 if (expected_value < 0.0)
8136 {
8137 // It is undefined to convert a negative floating-point value to an uint.
8138 break;
8139 }
8140
8141 m_testCtx.getLog() << tcu::TestLog::Message
8142 << "Invalid unsigned integer value obtained when doing an "
8143 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8144 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8145 << "]"
8146 ", component index: ["
8147 << n_swizzled_component << "]"
8148 ", value: ["
8149 << ref_expected_value << "]"
8150 " to GLSL type ["
8151 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8152 ", retrieved value: ["
8153 << result_value << "]"
8154 ", expected value: ["
8155 << (unsigned int)expected_value << "]"
8156 ", shader used:\n"
8157 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8158
8159 result = false;
8160 }
8161
8162 break;
8163 } /* VARIABLE_TYPE_UINT case */
8164
8165 default:
8166 {
8167 TCU_FAIL("Unrecognized variable type");
8168 }
8169 } /* switch (test_case.dst_type) */
8170 } /* for (all result components) */
8171 } /* for (all base values) */
8172
8173 return result;
8174 }
8175
8176 /** Constructor
8177 *
8178 * @param context Rendering context.
8179 */
GPUShaderFP64Test6(deqp::Context& context)8180 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8181 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8182 "during compilation time.")
8183 , m_cs_id(0)
8184 , m_fs_id(0)
8185 , m_gs_id(0)
8186 , m_tc_id(0)
8187 , m_te_id(0)
8188 , m_vs_id(0)
8189 , m_has_test_passed(true)
8190 {
8191 }
8192
8193 /** Deinitializes all buffers and GL objects that may have been generated
8194 * during test execution.
8195 **/
deinit()8196 void GPUShaderFP64Test6::deinit()
8197 {
8198 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8199
8200 if (m_cs_id != 0)
8201 {
8202 gl.deleteShader(m_cs_id);
8203
8204 m_cs_id = 0;
8205 }
8206
8207 if (m_fs_id != 0)
8208 {
8209 gl.deleteShader(m_fs_id);
8210
8211 m_fs_id = 0;
8212 }
8213
8214 if (m_gs_id != 0)
8215 {
8216 gl.deleteShader(m_gs_id);
8217
8218 m_gs_id = 0;
8219 }
8220
8221 if (m_tc_id != 0)
8222 {
8223 gl.deleteShader(m_tc_id);
8224
8225 m_tc_id = 0;
8226 }
8227
8228 if (m_te_id != 0)
8229 {
8230 gl.deleteShader(m_te_id);
8231
8232 m_te_id = 0;
8233 }
8234
8235 if (m_vs_id != 0)
8236 {
8237 gl.deleteShader(m_vs_id);
8238
8239 m_vs_id = 0;
8240 }
8241 }
8242
8243 /** Executes a single test case.
8244 *
8245 * This function can throw TestError exceptions if GL implementation reports
8246 * an error.
8247 *
8248 * @param test_case Test case descriptor.
8249 *
8250 * @return true if test case passed, false otherwise.
8251 **/
executeIteration(const _test_case& test_case)8252 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8253 {
8254 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8255 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8256 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8257 bool result = true;
8258 const char* stage_body = NULL;
8259 const char* stage_name = NULL;
8260
8261 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8262 {
8263 const glw::GLuint so_id = so_ids[n_so_id];
8264
8265 /* Skip compute shader if it is not supported */
8266 if (0 == so_id)
8267 {
8268 continue;
8269 }
8270
8271 /* Compile the shader */
8272 gl.compileShader(so_id);
8273 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8274
8275 /* Has the compilation failed as expected? */
8276 glw::GLint compile_status = GL_TRUE;
8277
8278 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8279 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8280
8281 if (compile_status == GL_TRUE)
8282 {
8283 /* What is the current stage's name? */
8284 if (so_id == m_cs_id)
8285 {
8286 stage_body = test_case.cs_shader_body.c_str();
8287 stage_name = "Compute shader";
8288 }
8289 else if (so_id == m_fs_id)
8290 {
8291 stage_body = test_case.fs_shader_body.c_str();
8292 stage_name = "Fragment shader";
8293 }
8294 else if (so_id == m_gs_id)
8295 {
8296 stage_body = test_case.gs_shader_body.c_str();
8297 stage_name = "Geometry shader";
8298 }
8299 else if (so_id == m_tc_id)
8300 {
8301 stage_body = test_case.tc_shader_body.c_str();
8302 stage_name = "Tessellation control shader";
8303 }
8304 else if (so_id == m_te_id)
8305 {
8306 stage_body = test_case.te_shader_body.c_str();
8307 stage_name = "Tessellation evaluation shader";
8308 }
8309 else if (so_id == m_vs_id)
8310 {
8311 stage_body = test_case.vs_shader_body.c_str();
8312 stage_name = "Vertex shader";
8313 }
8314 else
8315 {
8316 /* Doesn't make much sense to throw exceptions here so.. */
8317 stage_body = "";
8318 stage_name = "[?]";
8319 }
8320
8321 /* This shader should have never compiled successfully! */
8322 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8323 << " has been compiled successfully, even though the shader was malformed."
8324 " Following is shader body:\n"
8325 << stage_body << tcu::TestLog::EndMessage;
8326
8327 result = false;
8328 }
8329 } /* for (all shader objects) */
8330
8331 return result;
8332 }
8333
8334 /** Retrieves body of a compute shader that should be used for the purpose of
8335 * user-specified test case.
8336 *
8337 * @param test_case Test case descriptor to use.
8338 *
8339 * @return Requested string.
8340 **/
getComputeShaderBody(const _test_case& test_case)8341 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8342 {
8343 std::stringstream result_sstream;
8344
8345 /* Add pre-amble */
8346 result_sstream << "#version 420\n"
8347 "#extension GL_ARB_compute_shader : require\n"
8348 "\n"
8349 "layout(local_size_x = 6) in;\n"
8350 "\n"
8351 "void main()\n"
8352 "{\n";
8353
8354 /* Add local variable declarations */
8355 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8356
8357 if (test_case.src_array_size > 1)
8358 {
8359 result_sstream << "[" << test_case.src_array_size << "]";
8360 }
8361
8362 result_sstream << ";\n";
8363
8364 if (test_case.wrap_dst_type_in_structure)
8365 {
8366 result_sstream << "struct\n"
8367 "{\n"
8368 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8369 }
8370 else
8371 {
8372 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8373 }
8374
8375 result_sstream << ";\n";
8376
8377 if (test_case.wrap_dst_type_in_structure)
8378 {
8379 result_sstream << "\n} dst;\n";
8380 }
8381
8382 /* Add actual body */
8383 result_sstream << "dst = src;\n"
8384 "}\n";
8385
8386 /* Return the body */
8387 return result_sstream.str();
8388 }
8389
8390 /** Retrieves body of a fragment shader that should be used for the purpose of
8391 * user-specified test case.
8392 *
8393 * @param test_case Test case descriptor to use.
8394 *
8395 * @return Requested string.
8396 **/
getFragmentShaderBody(const _test_case& test_case)8397 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8398 {
8399 std::stringstream result_sstream;
8400
8401 /* Add pre-amble */
8402 result_sstream << "#version 420\n"
8403 "\n"
8404 "void main()\n"
8405 "{\n";
8406
8407 /* Add local variable declarations */
8408 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8409
8410 if (test_case.src_array_size > 1)
8411 {
8412 result_sstream << "[" << test_case.src_array_size << "]";
8413 }
8414
8415 result_sstream << ";\n";
8416
8417 if (test_case.wrap_dst_type_in_structure)
8418 {
8419 result_sstream << "struct\n"
8420 "{\n"
8421 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8422 }
8423 else
8424 {
8425 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8426 }
8427
8428 result_sstream << ";\n";
8429
8430 if (test_case.wrap_dst_type_in_structure)
8431 {
8432 result_sstream << "\n} dst;\n";
8433 }
8434
8435 /* Add actual body */
8436 result_sstream << "dst = src;\n"
8437 "}\n";
8438
8439 /* Return the body */
8440 return result_sstream.str();
8441 }
8442
8443 /** Retrieves body of a geometry shader that should be used for the purpose of
8444 * user-specified test case.
8445 *
8446 * @param test_case Test case descriptor to use.
8447 *
8448 * @return Requested string.
8449 **/
getGeometryShaderBody(const _test_case& test_case)8450 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8451 {
8452 std::stringstream result_sstream;
8453
8454 /* Add preamble */
8455 result_sstream << "#version 420\n"
8456 "\n"
8457 "layout(points) in;\n"
8458 "layout(max_vertices=1, points) out;\n"
8459 "\n"
8460 "void main()\n"
8461 "{\n";
8462
8463 /* Add local variable declarations */
8464 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8465
8466 if (test_case.src_array_size > 1)
8467 {
8468 result_sstream << "[" << test_case.src_array_size << "]";
8469 }
8470
8471 result_sstream << ";\n";
8472
8473 if (test_case.wrap_dst_type_in_structure)
8474 {
8475 result_sstream << "struct\n"
8476 "{\n"
8477 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8478 }
8479 else
8480 {
8481 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8482 }
8483
8484 result_sstream << ";\n"
8485 "\n";
8486
8487 if (test_case.wrap_dst_type_in_structure)
8488 {
8489 result_sstream << "} dst;\n";
8490 }
8491
8492 /* Add actual body */
8493 result_sstream << "dst = src;\n"
8494 "}\n";
8495
8496 /* We're done! */
8497 return result_sstream.str();
8498 }
8499
8500 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8501 * user-specified test case.
8502 *
8503 * @param test_case Test case descriptor to use.
8504 *
8505 * @return Requested string.
8506 **/
getTessellationControlShaderBody(const _test_case& test_case)8507 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8508 {
8509 std::stringstream result_sstream;
8510
8511 /* Add preamble */
8512 result_sstream << "#version 420\n"
8513 "\n"
8514 "layout(vertices=4) out;\n"
8515 "\n"
8516 "void main()\n"
8517 "{\n";
8518
8519 /* Add local variable declarations. */
8520 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8521
8522 if (test_case.src_array_size > 1)
8523 {
8524 result_sstream << "[" << test_case.src_array_size << "]";
8525 }
8526
8527 result_sstream << ";\n";
8528
8529 if (test_case.wrap_dst_type_in_structure)
8530 {
8531 result_sstream << "struct\n"
8532 "{\n"
8533 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8534 }
8535 else
8536 {
8537 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8538 }
8539
8540 if (test_case.wrap_dst_type_in_structure)
8541 {
8542 result_sstream << ";\n"
8543 "} dst;\n";
8544 }
8545 else
8546 {
8547 result_sstream << ";\n";
8548 }
8549
8550 /* Continue with the actual body. */
8551 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8552 "gl_TessLevelOuter[1] = 1.0;\n"
8553 "dst = src;\n"
8554 "}\n";
8555
8556 /* Return the body */
8557 return result_sstream.str();
8558 }
8559
8560 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8561 * user-specified test case.
8562 *
8563 * @param test_case Test case descriptor to use.
8564 *
8565 * @return Requested string.
8566 **/
getTessellationEvaluationShaderBody(const _test_case& test_case)8567 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8568 {
8569 std::stringstream result_sstream;
8570
8571 /* Add preamble */
8572 result_sstream << "#version 420\n"
8573 "\n"
8574 "layout(isolines) in;\n"
8575 "\n"
8576 "void main()\n"
8577 "{\n";
8578
8579 /* Add local variable declarations */
8580 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8581
8582 if (test_case.src_array_size > 1)
8583 {
8584 result_sstream << "[" << test_case.src_array_size << "]";
8585 }
8586
8587 result_sstream << ";\n";
8588
8589 if (test_case.wrap_dst_type_in_structure)
8590 {
8591 result_sstream << "struct\n"
8592 "{\n"
8593 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8594 }
8595 else
8596 {
8597 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8598 }
8599
8600 if (test_case.wrap_dst_type_in_structure)
8601 {
8602 result_sstream << ";\n"
8603 "} dst;\n";
8604 }
8605 else
8606 {
8607 result_sstream << ";\n";
8608 }
8609
8610 /* Continue with the actual body. */
8611 result_sstream << "dst = src;\n";
8612
8613 /* Complete the body */
8614 result_sstream << "}\n";
8615
8616 /* Return the body */
8617 return result_sstream.str();
8618 }
8619
8620 /** Retrieves body of a vertex shader that should be used for the purpose of
8621 * user-specified test case.
8622 *
8623 * @param test_case Test case descriptor to use.
8624 *
8625 * @return Requested string.
8626 **/
getVertexShaderBody(const _test_case& test_case)8627 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8628 {
8629 std::stringstream result_sstream;
8630
8631 /* Add preamble */
8632 result_sstream << "#version 420\n"
8633 "\n"
8634 "void main()\n"
8635 "{\n";
8636
8637 /* Add local variables */
8638 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8639
8640 if (test_case.src_array_size > 1)
8641 {
8642 result_sstream << "[" << test_case.src_array_size << "]";
8643 }
8644
8645 result_sstream << ";\n";
8646
8647 if (test_case.wrap_dst_type_in_structure)
8648 {
8649 result_sstream << "struct\n"
8650 "{\n"
8651 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8652 }
8653 else
8654 {
8655 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8656 }
8657
8658 if (test_case.wrap_dst_type_in_structure)
8659 {
8660 result_sstream << ";\n"
8661 "} dst;\n";
8662 }
8663 else
8664 {
8665 result_sstream << ";\n";
8666 }
8667
8668 /* Start actual body */
8669 result_sstream << "dst = src;\n"
8670 "gl_Position = vec4(1.0);\n"
8671 "}";
8672
8673 return result_sstream.str();
8674 }
8675
8676 /** Initializes shader objects required to run the test. */
initTest()8677 void GPUShaderFP64Test6::initTest()
8678 {
8679 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8680
8681 /* Generate shader objects */
8682
8683 /* Compute shader support and GL 4.2 required */
8684 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8685 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8686 {
8687 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8688 }
8689
8690 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8691 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8692 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8693 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8694 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8695
8696 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8697 }
8698
8699 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8700 *
8701 * @param test_case Test case descriptor to generate the shader bodies for.
8702 **/
initIteration(_test_case& test_case)8703 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8704 {
8705 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8706
8707 test_case.cs_shader_body = getComputeShaderBody(test_case);
8708 test_case.fs_shader_body = getFragmentShaderBody(test_case);
8709 test_case.gs_shader_body = getGeometryShaderBody(test_case);
8710 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8711 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8712 test_case.vs_shader_body = getVertexShaderBody(test_case);
8713
8714 /* Assign the bodies to relevant shaders */
8715 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8716 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8717 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8718 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8719 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8720 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8721
8722 /* m_cs_id is initialized only if compute_shader is supported */
8723 if (0 != m_cs_id)
8724 {
8725 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8726 }
8727
8728 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8729 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8730 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8731 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8732 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8733 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8734 }
8735
8736 /** Executes test iteration.
8737 *
8738 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8739 */
iterate()8740 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8741 {
8742 /* Do not execute the test if GL_ARB_texture_view is not supported */
8743 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8744 {
8745 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8746 }
8747
8748 /* Initialize GL objects needed to run the tests */
8749 initTest();
8750
8751 /* Build iteration array to run the tests in an automated manner */
8752 _test_case test_cases[] = {
8753 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8754 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8755 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8756 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8757 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8758 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8759 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8760 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8761 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8762 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8763 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8764 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8765 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8766 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8767 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8768 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8769 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8770 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8771 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8772 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8773 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8774 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8775 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8776 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8777 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8778 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8779 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8780 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8781 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8782 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8783 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8784 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8785 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8786 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8787 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8788 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8789 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8790 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8791 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8792 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8793 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8794 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8795 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8796 };
8797 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8798
8799 /* Execute all iterations */
8800 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8801 {
8802 _test_case& test_case = test_cases[n_test_case];
8803
8804 /* Initialize a program object we will use to perform the casting */
8805 initIteration(test_case);
8806
8807 /* Use the program object to XFB the results */
8808 m_has_test_passed &= executeIteration(test_case);
8809
8810 } /* for (all test cases) */
8811
8812 /* We're done */
8813 if (m_has_test_passed)
8814 {
8815 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8816 }
8817 else
8818 {
8819 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8820 }
8821
8822 return STOP;
8823 }
8824
8825 /** Constructor
8826 *
8827 * @param context Rendering context.
8828 */
GPUShaderFP64Test7(deqp::Context& context)8829 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8830 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8831 "in all shader stages.")
8832 , m_are_double_inputs_supported(false)
8833 , m_fbo_id(0)
8834 , m_fs_id(0)
8835 , m_gs_id(0)
8836 , m_has_test_passed(true)
8837 , m_n_max_components_per_stage(0)
8838 , m_n_xfb_varyings(0)
8839 , m_po_id(0)
8840 , m_tc_id(0)
8841 , m_te_id(0)
8842 , m_to_id(0)
8843 , m_to_data(NULL)
8844 , m_to_height(4)
8845 , m_to_width(4)
8846 , m_xfb_bo_id(0)
8847 , m_xfb_varyings(NULL)
8848 , m_vao_id(0)
8849 , m_vs_id(0)
8850 {
8851 }
8852
8853 /** Compiles all shaders attached to test program object and links it.
8854 *
8855 * @param variables
8856 *
8857 * @return true if the process was executed successfully, false otherwise.
8858 */
buildTestProgram(_variables& variables)8859 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8860 {
8861 std::string fs_body = getFragmentShaderBody(variables);
8862 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8863 std::string gs_body = getGeometryShaderBody(variables);
8864 std::string tc_body = getTessellationControlShaderBody(variables);
8865 std::string te_body = getTessellationEvaluationShaderBody(variables);
8866 std::string vs_body = getVertexShaderBody(variables);
8867 bool result = false;
8868
8869 /* Try to link the program object */
8870 glw::GLint link_status = GL_FALSE;
8871
8872 /* Compile the shaders */
8873 if (!compileShader(m_fs_id, fs_body))
8874 {
8875 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8876
8877 goto end;
8878 }
8879
8880 if (!compileShader(m_gs_id, gs_body))
8881 {
8882 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8883
8884 goto end;
8885 }
8886
8887 if (!compileShader(m_tc_id, tc_body))
8888 {
8889 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8890 << tcu::TestLog::EndMessage;
8891
8892 goto end;
8893 }
8894
8895 if (!compileShader(m_te_id, te_body))
8896 {
8897 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8898 << tcu::TestLog::EndMessage;
8899
8900 goto end;
8901 }
8902
8903 if (!compileShader(m_vs_id, vs_body))
8904 {
8905 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8906
8907 goto end;
8908 }
8909
8910 /* Configure XFB */
8911 releaseXFBVaryingNames();
8912 generateXFBVaryingNames(variables);
8913
8914 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8915
8916 gl.linkProgram(m_po_id);
8917
8918 /* Have we succeeded? */
8919 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8920
8921 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8922 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8923
8924 if (link_status != GL_TRUE)
8925 {
8926 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8927 << tcu::TestLog::EndMessage;
8928
8929 goto end;
8930 }
8931
8932 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8933 if (m_are_double_inputs_supported)
8934 {
8935 const size_t n_variables = variables.size();
8936
8937 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8938 {
8939 _variable& current_variable = variables[n_variable];
8940 std::stringstream attribute_name_sstream;
8941
8942 attribute_name_sstream << "in_vs_variable" << n_variable;
8943
8944 if (current_variable.array_size > 1)
8945 {
8946 attribute_name_sstream << "[0]";
8947 }
8948
8949 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8950
8951 if (current_variable.attribute_location == -1)
8952 {
8953 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8954 << attribute_name_sstream.str().c_str()
8955 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8956
8957 m_has_test_passed = false;
8958 goto end;
8959 }
8960 } /* for (all test variables) */
8961 } /* if (m_are_double_inputs_supported) */
8962
8963 m_current_fs_body = fs_body;
8964 m_current_gs_body = gs_body;
8965 m_current_tc_body = tc_body;
8966 m_current_te_body = te_body;
8967 m_current_vs_body = vs_body;
8968
8969 result = true;
8970
8971 end:
8972 return result;
8973 }
8974
8975 /** Updates shader object's body and then compiles the shader.
8976 *
8977 * @param body Body to use for the shader.
8978 *
8979 * @return true if the shader compiled successfully, false otherwise.
8980 **/
compileShader(glw::GLint shader_id, const std::string& body)8981 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8982 {
8983 const char* body_raw_ptr = body.c_str();
8984 glw::GLint compile_status = GL_FALSE;
8985 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8986
8987 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8988 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8989
8990 gl.compileShader(shader_id);
8991 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8992
8993 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8994 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8995
8996 return (compile_status == GL_TRUE);
8997 }
8998
8999 /** Configure storage of a buffer object used for capturing XFB data.
9000 *
9001 * @param variables Holds descriptor for all variables used for the iteration the
9002 * BO is being configured for. Storage size will be directly related
9003 * to the number of the variables and their type.
9004 */
configureXFBBuffer(const _variables& variables)9005 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9006 {
9007 DE_ASSERT(m_n_xfb_varyings != 0);
9008
9009 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9010 * The test only draws a single patch, and triangles are caught by transform feed-back.
9011 * Let's initialize the storage, according to the list of variables that will be used
9012 * for the test run.
9013 */
9014 unsigned int bo_size = 0;
9015
9016 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9017 variables_iterator++)
9018 {
9019 const _variable& variable = *variables_iterator;
9020 unsigned int n_bytes_needed = static_cast<unsigned int>(
9021 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9022
9023 bo_size += n_bytes_needed;
9024 } /* for (all variables) */
9025
9026 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9027
9028 /* Set up the BO storage */
9029 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9030
9031 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9032 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9033 }
9034
9035 /** Deinitializes all buffers and GL objects that may have been generated
9036 * during test execution.
9037 **/
deinit()9038 void GPUShaderFP64Test7::deinit()
9039 {
9040 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9041
9042 if (m_fbo_id != 0)
9043 {
9044 gl.deleteFramebuffers(1, &m_fbo_id);
9045
9046 m_fbo_id = 0;
9047 }
9048
9049 if (m_fs_id != 0)
9050 {
9051 gl.deleteShader(m_fs_id);
9052
9053 m_fs_id = 0;
9054 }
9055
9056 if (m_gs_id != 0)
9057 {
9058 gl.deleteShader(m_gs_id);
9059
9060 m_gs_id = 0;
9061 }
9062
9063 if (m_po_id != 0)
9064 {
9065 gl.deleteProgram(m_po_id);
9066
9067 m_po_id = 0;
9068 }
9069
9070 if (m_tc_id != 0)
9071 {
9072 gl.deleteShader(m_tc_id);
9073
9074 m_tc_id = 0;
9075 }
9076
9077 if (m_te_id != 0)
9078 {
9079 gl.deleteShader(m_te_id);
9080
9081 m_te_id = 0;
9082 }
9083
9084 if (m_to_data != NULL)
9085 {
9086 delete[] m_to_data;
9087
9088 m_to_data = NULL;
9089 }
9090
9091 if (m_to_id != 0)
9092 {
9093 gl.deleteTextures(1, &m_to_id);
9094
9095 m_to_id = 0;
9096 }
9097
9098 if (m_xfb_bo_id != 0)
9099 {
9100 gl.deleteBuffers(1, &m_xfb_bo_id);
9101
9102 m_xfb_bo_id = 0;
9103 }
9104
9105 if (m_xfb_varyings != DE_NULL)
9106 {
9107 releaseXFBVaryingNames();
9108 }
9109
9110 if (m_vao_id != 0)
9111 {
9112 gl.deleteVertexArrays(1, &m_vao_id);
9113
9114 m_vao_id = 0;
9115 }
9116
9117 if (m_vs_id != 0)
9118 {
9119 gl.deleteShader(m_vs_id);
9120
9121 m_vs_id = 0;
9122 }
9123 }
9124
9125 /** Executes the functional part of the test (case a) from the test spec)
9126 *
9127 * @param variables Vector of variable descriptors defining properties of
9128 * variables that should be used for the iteration.
9129 *
9130 * @return true if the test passed, false otherwise.
9131 **/
executeFunctionalTest(_variables& variables)9132 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9133 {
9134 bool result = true;
9135
9136 /* Build the test program */
9137 if (!buildTestProgram(variables))
9138 {
9139 return false;
9140 }
9141
9142 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9143 if (m_are_double_inputs_supported)
9144 {
9145 setInputAttributeValues(variables);
9146 }
9147
9148 /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9149 * only, if a data mismatch is detected.
9150 */
9151 configureXFBBuffer(variables);
9152
9153 /* Issue a draw call using the test program */
9154 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9155
9156 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9157 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9158
9159 gl.clear(GL_COLOR_BUFFER_BIT);
9160 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9161
9162 gl.useProgram(m_po_id);
9163 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9164
9165 gl.viewport(0, /* x */
9166 0, /* y */
9167 m_to_width, m_to_height);
9168 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9169
9170 gl.beginTransformFeedback(GL_TRIANGLES);
9171 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9172 {
9173 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9174 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9175 }
9176 gl.endTransformFeedback();
9177 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9178
9179 /* Verify color attachment contents */
9180 const float epsilon = 1.0f / 255.0f;
9181
9182 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9183 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9184
9185 for (unsigned int y = 0; y < m_to_height; ++y)
9186 {
9187 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9188
9189 for (unsigned int x = 0; x < m_to_width; ++x)
9190 {
9191 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9192
9193 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9194 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9195 {
9196 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9197 << ")"
9198 "; expected:(0, 255, 0, 0), found: ("
9199 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9200 << ", " << (int)pixel_ptr[3]
9201 << "), with the following variable types used as varyings:"
9202 << tcu::TestLog::EndMessage;
9203
9204 /* List the variable types that failed the test */
9205 const size_t n_variables = variables.size();
9206
9207 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9208 {
9209 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9210 << Utils::getVariableTypeString(variables[n_variable].type)
9211 << " (array size:" << variables[n_variable].array_size << ")"
9212 << tcu::TestLog::EndMessage;
9213 } /* for (all variable types) */
9214
9215 /* Log the variable contents */
9216 logVariableContents(variables);
9217
9218 /* Log shaders used for the iteration */
9219 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9220 "\n"
9221 "(VS):\n"
9222 << m_current_vs_body.c_str() << "\n"
9223 << "(TC):\n"
9224 "\n"
9225 << m_current_tc_body.c_str() << "\n"
9226 "(TE):\n"
9227 "\n"
9228 << m_current_te_body.c_str() << "\n"
9229 "(GS):\n"
9230 << m_current_gs_body.c_str() << "\n"
9231 "(FS):\n"
9232 "\n"
9233 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9234
9235 result = false;
9236
9237 goto end;
9238 }
9239 } /* for (all columns) */
9240 } /* for (all rows) */
9241
9242 /* All done! */
9243 end:
9244 return result;
9245 }
9246
9247 /** Takes user-input vector of test variables and allocates & fills an array of strings
9248 * holding names of geometry shader stage varyings that should be captured during
9249 * transform feedback operation. The array will be stored in m_xfb_varyings.
9250 *
9251 * @param variables Holds all test variable descriptors to be used for the iteration.
9252 */
generateXFBVaryingNames(const _variables& variables)9253 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9254 {
9255 unsigned int n_variable = 0;
9256 unsigned int n_varying = 0;
9257 unsigned int n_varyings = 0;
9258
9259 if (m_xfb_varyings != NULL)
9260 {
9261 releaseXFBVaryingNames();
9262 }
9263
9264 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9265 ++variables_iterator)
9266 {
9267 const _variable& variable = *variables_iterator;
9268
9269 n_varyings += variable.array_size;
9270 }
9271
9272 m_xfb_varyings = new glw::GLchar*[n_varyings];
9273
9274 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9275 ++variables_iterator, ++n_variable)
9276 {
9277 const _variable& variable = *variables_iterator;
9278
9279 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9280 {
9281 std::stringstream varying_sstream;
9282 size_t varying_length;
9283
9284 varying_sstream << "gs_variable" << n_variable;
9285
9286 if (variable.array_size > 1)
9287 {
9288 varying_sstream << "[" << array_index << "]";
9289 }
9290
9291 /* Store the varying name */
9292 varying_length = varying_sstream.str().length();
9293 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9294
9295 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9296 m_xfb_varyings[n_varying][varying_length] = 0;
9297 } /* for (all array indices) */
9298 } /* for (all varyings) */
9299
9300 m_n_xfb_varyings = n_varyings;
9301 }
9302
9303 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9304 * without using the "flat" keyword. (case c) )
9305 *
9306 * @param input_variable_type Variable type to use for input variable declaration.
9307 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9308 * of the arrayed variable.
9309 *
9310 * @return Requested string.
9311 **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput( Utils::_variable_type input_variable_type, unsigned int array_size)9312 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9313 Utils::_variable_type input_variable_type, unsigned int array_size)
9314 {
9315 std::stringstream result_sstream;
9316 std::stringstream array_index_stringstream;
9317 std::stringstream array_size_stringstream;
9318
9319 if (array_size > 1)
9320 {
9321 array_index_stringstream << "[0]";
9322 array_size_stringstream << "[" << array_size << "]";
9323 }
9324
9325 if (Utils::isMatrixVariableType(input_variable_type))
9326 {
9327 array_index_stringstream << "[0].x";
9328 }
9329 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9330 {
9331 array_index_stringstream << "[0]";
9332 }
9333
9334 result_sstream << "#version 400\n"
9335 "\n"
9336 "in "
9337 << Utils::getVariableTypeString(input_variable_type) << " test_input"
9338 << array_size_stringstream.str() << ";\n"
9339 "\n"
9340 "out float test_output;\n"
9341 "\n"
9342 "void main()\n"
9343 "{\n"
9344 " if (test_input"
9345 << array_index_stringstream.str() << " > 2.0)\n"
9346 " {\n"
9347 " test_output = 1.0;\n"
9348 " }\n"
9349 " else\n"
9350 " {\n"
9351 " test_output = 3.0;\n"
9352 " }\n"
9353 "}\n";
9354
9355 return result_sstream.str();
9356 }
9357
9358 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9359 *
9360 * @param input_variable_type Variable type to use for input variable declaration.
9361 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9362 * of the arrayed variable.
9363 *
9364 * @return Requested string.
9365 **/
getCodeOfFragmentShaderWithDoublePrecisionOutput( Utils::_variable_type output_variable_type, unsigned int array_size)9366 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9367 Utils::_variable_type output_variable_type, unsigned int array_size)
9368 {
9369 std::stringstream array_index_sstream;
9370 std::stringstream array_size_sstream;
9371 std::stringstream result_sstream;
9372 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9373
9374 if (array_size > 1)
9375 {
9376 array_index_sstream << "[0]";
9377 array_size_sstream << "[" << array_size << "]";
9378 }
9379
9380 result_sstream << "#version 400\n"
9381 "\n"
9382 "out "
9383 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9384 "\n"
9385 "void main()\n"
9386 "{\n"
9387 " test_output"
9388 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9389 "}\n";
9390
9391 return result_sstream.str();
9392 }
9393
9394 /** Retrieves body of a fragment shader that uses user-specified set of variables
9395 * to declare contents of input & output block.
9396 *
9397 * @param variables As per description.
9398 *
9399 * @return Requested string.
9400 **/
getFragmentShaderBody(const _variables& variables)9401 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9402 {
9403 std::stringstream result_sstream;
9404
9405 /* Form the pre-amble */
9406 result_sstream << "#version 400\n"
9407 "\n"
9408
9409 /* Add input block */
9410 << "in GS_DATA\n"
9411 "{\n"
9412 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9413 "\n"
9414
9415 /* Add output variable */
9416 << "out vec4 result;\n"
9417 "\n"
9418
9419 /* Add main() definition */
9420 "void main()\n"
9421 "{\n"
9422 "const double epsilon = 1e-5;\n"
9423 "\n"
9424 "result = vec4(1, 0, 0, 0);\n"
9425 "\n";
9426
9427 /* Determine expected values first */
9428 unsigned int base_counter = 1;
9429 const size_t n_variables = variables.size();
9430
9431 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9432 {
9433 unsigned int variable_array_size = variables[n_variable].array_size;
9434 Utils::_variable_type variable_type = variables[n_variable].type;
9435 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9436 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9437
9438 std::stringstream array_size_sstream;
9439
9440 if (variable_array_size > 1)
9441 {
9442 array_size_sstream << "[" << variable_array_size << "]";
9443 }
9444
9445 /* Local variable declaration */
9446 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9447 << ";\n"
9448 "\n";
9449
9450 /* Set expected values */
9451 for (unsigned int index = 0; index < variable_array_size; ++index)
9452 {
9453 std::stringstream array_index_sstream;
9454
9455 if (variable_array_size > 1)
9456 {
9457 array_index_sstream << "[" << index << "]";
9458 }
9459
9460 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9461 << variable_type_string << "(";
9462
9463 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9464 {
9465 unsigned int expected_value =
9466 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9467
9468 if (m_are_double_inputs_supported)
9469 {
9470 /* VS input attributes */
9471 //expected_value += (base_counter + 6);
9472 expected_value -= 1;
9473 }
9474
9475 result_sstream << expected_value;
9476
9477 if (n_component != (n_variable_type_components - 1))
9478 {
9479 result_sstream << ", ";
9480 }
9481
9482 ++base_counter;
9483 } /* for (all components) */
9484
9485 result_sstream << ");\n";
9486 } /* for (all array indices) */
9487
9488 result_sstream << "\n";
9489 } /* for (all variable types) */
9490
9491 /* Now that we know the expected values, do a huge conditional check to verify if all
9492 * input variables carry correct information.
9493 */
9494 result_sstream << "if (";
9495
9496 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9497 {
9498 unsigned int variable_array_size = variables[n_variable].array_size;
9499 Utils::_variable_type variable_type = variables[n_variable].type;
9500 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type);
9501 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9502 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9503
9504 for (unsigned int index = 0; index < variable_array_size; ++index)
9505 {
9506 std::stringstream array_index_sstream;
9507
9508 if (variable_array_size > 1)
9509 {
9510 array_index_sstream << "[" << index << "]";
9511 }
9512
9513 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9514 {
9515 std::stringstream component_index_sstream;
9516
9517 if (n_variable_type_components > 1)
9518 {
9519 component_index_sstream << "[" << n_component << "]";
9520 }
9521
9522 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9523
9524 if (is_variable_type_matrix)
9525 {
9526 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9527 const unsigned int column = n_component % n_columns;
9528 const unsigned int row = n_component / n_columns;
9529
9530 result_sstream << "[" << column << "]"
9531 "."
9532 << Utils::getComponentAtIndex(row);
9533 }
9534 else
9535 {
9536 result_sstream << component_index_sstream.str();
9537 }
9538
9539 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9540
9541 if (is_variable_type_matrix)
9542 {
9543 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9544 const unsigned int column = n_component % n_columns;
9545 const unsigned int row = n_component / n_columns;
9546
9547 result_sstream << "[" << column << "]"
9548 "."
9549 << Utils::getComponentAtIndex(row);
9550 }
9551 else
9552 {
9553 result_sstream << component_index_sstream.str();
9554 }
9555
9556 result_sstream << ") <= epsilon &&";
9557 } /* for (all components) */
9558 } /* for (all array indices) */
9559 } /* for (all variable types) */
9560
9561 result_sstream << "true)\n"
9562 "{\n"
9563 " result = vec4(0, 1, 0, 0);\n"
9564 "}\n"
9565 "}\n";
9566
9567 /* All done */
9568 return result_sstream.str();
9569 }
9570
9571 /** Retrieves body of a geometry shader that uses user-specified set of variables
9572 * to declare contents of input & output block.
9573 *
9574 * @param variables As per description.
9575 *
9576 * @return Requested string.
9577 **/
getGeometryShaderBody(const _variables& variables)9578 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9579 {
9580 std::stringstream result_sstream;
9581
9582 /* Form the pre-amble */
9583 result_sstream << "#version 400\n"
9584 "\n"
9585 "layout(triangles) in;\n"
9586 "layout(triangle_strip, max_vertices=4) out;\n"
9587 "\n"
9588
9589 /* Add the input block */
9590 "in TE_DATA\n"
9591 "{\n"
9592 << getVariableDeclarations("te", variables) << "} in_data[];\n"
9593 "\n"
9594
9595 /* Add the output block */
9596 "out GS_DATA\n"
9597 "{\n"
9598 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9599 "\n"
9600
9601 /* Declare main() function */
9602 "void main()\n"
9603 "{\n";
9604
9605 /* Take input variables, add a predefined value and forward them to output variables */
9606 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9607 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
9608 const unsigned int n_quad_vertices =
9609 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9610 const size_t n_variables = variables.size();
9611
9612 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9613 {
9614 unsigned int counter = 4;
9615 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9616
9617 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9618 {
9619 unsigned int variable_array_size = variables[n_variable].array_size;
9620 Utils::_variable_type variable_type = variables[n_variable].type;
9621 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9622 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9623
9624 for (unsigned int index = 0; index < variable_array_size; ++index)
9625 {
9626 std::stringstream array_index_sstream;
9627
9628 if (variable_array_size > 1)
9629 {
9630 array_index_sstream << "[" << index << "]";
9631 }
9632
9633 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9634 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9635 << variable_type_string << "(";
9636
9637 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9638 {
9639 result_sstream << (counter++);
9640
9641 if (n_component != (n_variable_type_components - 1))
9642 {
9643 result_sstream << ", ";
9644 }
9645 } /* for (all components) */
9646
9647 result_sstream << ");\n";
9648 } /* for (all array indices) */
9649 } /* for (all variable types) */
9650
9651 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9652 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9653 "EmitVertex();\n";
9654 } /* for (all emitted quad vertices) */
9655
9656 result_sstream << "EndPrimitive();\n"
9657 "}\n";
9658
9659 /* All done */
9660 return result_sstream.str();
9661 }
9662
9663 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9664 * to declare contents of input & output block.
9665 *
9666 * @param variables As per description.
9667 *
9668 * @return Requested string.
9669 **/
getTessellationControlShaderBody(const _variables& variables)9670 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9671 {
9672 std::stringstream result_sstream;
9673
9674 /* Form the pre-amble */
9675 result_sstream << "#version 400\n"
9676 "\n"
9677 "layout (vertices=4) out;\n"
9678
9679 /* Declare input block */
9680 "in VS_DATA\n"
9681 "{\n"
9682 << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9683
9684 /* Declare output block */
9685 "out TC_DATA\n"
9686 "{\n"
9687 << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9688 "\n"
9689
9690 /* Define main() */
9691 "void main()\n"
9692 "{\n"
9693 " gl_TessLevelInner[0] = 1;\n"
9694 " gl_TessLevelInner[1] = 1;\n"
9695 " gl_TessLevelOuter[0] = 1;\n"
9696 " gl_TessLevelOuter[1] = 1;\n"
9697 " gl_TessLevelOuter[2] = 1;\n"
9698 " gl_TessLevelOuter[3] = 1;\n"
9699 "\n";
9700
9701 /* Take input variables, add a predefined value and forward them to output variables */
9702 const size_t n_variables = variables.size();
9703 unsigned int counter = 2;
9704
9705 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9706 {
9707 unsigned int variable_array_size = variables[n_variable].array_size;
9708 Utils::_variable_type variable_type = variables[n_variable].type;
9709 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9710 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9711
9712 for (unsigned int index = 0; index < variable_array_size; ++index)
9713 {
9714 std::stringstream array_index_sstream;
9715
9716 if (variable_array_size > 1)
9717 {
9718 array_index_sstream << "[" << index << "]";
9719 }
9720
9721 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9722 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9723 << variable_type_string << "(";
9724
9725 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9726 {
9727 result_sstream << (counter++);
9728
9729 if (n_component != (n_variable_type_components - 1))
9730 {
9731 result_sstream << ", ";
9732 }
9733 }
9734
9735 result_sstream << ");\n";
9736 } /* for (all array indices) */
9737 } /* for (all variable types) */
9738
9739 result_sstream << "}\n";
9740
9741 /* We're done */
9742 return result_sstream.str();
9743 }
9744
9745 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9746 * to declare contents of input & output block.
9747 *
9748 * @param variables As per description.
9749 *
9750 * @return Requested string.
9751 **/
getTessellationEvaluationShaderBody(const _variables& variables)9752 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9753 {
9754 std::stringstream result_sstream;
9755
9756 /* Form the pre-amble */
9757 result_sstream << "#version 400\n"
9758 "\n"
9759 "layout(quads) in;\n"
9760 "\n"
9761
9762 /* Define input block */
9763 "in TC_DATA\n"
9764 "{\n"
9765 << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9766 "\n"
9767
9768 /* Define output block */
9769 "out TE_DATA\n"
9770 "{\n"
9771 << getVariableDeclarations("te", variables) << "};\n"
9772 "\n"
9773
9774 /* Define main() */
9775 "void main()\n"
9776 "{\n";
9777
9778 /* Take input variables, add a predefined value and forward them to output variables */
9779 const size_t n_variables = variables.size();
9780 unsigned int counter = 3;
9781
9782 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9783 {
9784 unsigned int variable_array_size = variables[n_variable].array_size;
9785 Utils::_variable_type variable_type = variables[n_variable].type;
9786 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9787 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9788
9789 for (unsigned int index = 0; index < variable_array_size; ++index)
9790 {
9791 std::stringstream array_index_sstream;
9792
9793 if (variable_array_size > 1)
9794 {
9795 array_index_sstream << "[" << index << "]";
9796 }
9797
9798 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9799 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9800
9801 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9802 {
9803 result_sstream << (counter++);
9804
9805 if (n_component != (n_variable_type_components - 1))
9806 {
9807 result_sstream << ", ";
9808 }
9809 } /* for (all components) */
9810
9811 result_sstream << ");\n";
9812 } /* for (all array indices) */
9813 } /* for (all variable types) */
9814
9815 result_sstream << "}\n";
9816
9817 /* All done */
9818 return result_sstream.str();
9819 }
9820
9821 /** Returns a string containing declarations of user-specified set of variables.
9822 * Each declaration can optionally use a layot qualifier requested by the caller.
9823 *
9824 * @param prefix Prefix to use for variable names.
9825 * @param variables List of variables to declare in the result string.
9826 * @param explicit_locations true if each declaration should explicitly define location
9827 * of the variable ( eg. (layout location=X) )
9828 * @param layout_qualifier Optional qualifier to use for the declaration. Must not
9829 * be NULL.
9830 *
9831 * @return Requested string.
9832 **/
getVariableDeclarations(const char* prefix, const _variables& variables, const char* layout_qualifier)9833 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9834 const char* layout_qualifier)
9835 {
9836 std::stringstream result_sstream;
9837
9838 /* Define output variables */
9839 const size_t n_variables = variables.size();
9840
9841 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9842 {
9843 unsigned int variable_array_size = variables[n_variable].array_size;
9844 Utils::_variable_type variable_type = variables[n_variable].type;
9845 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9846
9847 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9848
9849 if (variable_array_size > 1)
9850 {
9851 result_sstream << "[" << variable_array_size << "]";
9852 }
9853
9854 result_sstream << ";\n";
9855 } /* for (all user-specified variable types) */
9856
9857 return result_sstream.str();
9858 }
9859
9860 /** Retrieves body of a vertex shader that uses user-specified set of variables
9861 * to declare contents of input & output block.
9862 *
9863 * @param variables As per description.
9864 *
9865 * @return Requested string.
9866 **/
getVertexShaderBody(const _variables& variables)9867 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9868 {
9869 std::stringstream result_sstream;
9870
9871 /* Form pre-amble */
9872 result_sstream << "#version 400\n"
9873 "\n";
9874
9875 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9876 if (m_are_double_inputs_supported)
9877 {
9878 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9879 << getVariableDeclarations("in_vs", variables, "in");
9880 }
9881
9882 /* Define output variables */
9883 result_sstream << "out VS_DATA\n"
9884 "{\n"
9885 << getVariableDeclarations("vs", variables);
9886
9887 /* Define main() */
9888 result_sstream << "};\n"
9889 "\n"
9890 "void main()\n"
9891 "{\n";
9892
9893 /* Set output variable values */
9894 unsigned int counter = 1;
9895 const size_t n_variables = variables.size();
9896
9897 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9898 {
9899 unsigned int variable_array_size = variables[n_variable].array_size;
9900 Utils::_variable_type variable_type = variables[n_variable].type;
9901 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9902 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9903
9904 for (unsigned int index = 0; index < variable_array_size; ++index)
9905 {
9906 if (variable_array_size == 1)
9907 {
9908 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9909 }
9910 else
9911 {
9912 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9913 << " = " << variable_type_string << "(";
9914 }
9915
9916 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9917 {
9918 result_sstream << (double)(counter++);
9919
9920 /* Use input attributes, if available */
9921 if (m_are_double_inputs_supported)
9922 {
9923 result_sstream << " + in_vs_variable" << n_variable;
9924
9925 if (variable_array_size > 1)
9926 {
9927 result_sstream << "[" << index << "]";
9928 }
9929
9930 if (Utils::isMatrixVariableType(variables[n_variable].type))
9931 {
9932 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9933 const unsigned int column = n_component % n_columns;
9934 const unsigned int row = n_component / n_columns;
9935
9936 result_sstream << "[" << (column) << "]"
9937 "."
9938 << Utils::getComponentAtIndex(row);
9939 }
9940 else if (n_variable_type_components > 1)
9941 {
9942 result_sstream << "[" << n_component << "]";
9943 }
9944 }
9945
9946 if (n_component != (n_variable_type_components - 1))
9947 {
9948 result_sstream << ", ";
9949 }
9950 } /* for (all components) */
9951
9952 result_sstream << ");\n";
9953 }
9954 } /* for (all variable types) */
9955
9956 /* We will be using geometry shader to lay out the actual vertices so
9957 * the only thing we need to make sure is that the vertex never gets
9958 * culled.
9959 */
9960 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9961 "}\n";
9962
9963 /* That's it */
9964 return result_sstream.str();
9965 }
9966
9967 /** Initializes shader objects required to run the test. */
initTest()9968 void GPUShaderFP64Test7::initTest()
9969 {
9970 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9971
9972 /* Are double-precision input variables supported? */
9973 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9974
9975 /* Create a vertex array object */
9976 gl.genVertexArrays(1, &m_vao_id);
9977 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9978
9979 gl.bindVertexArray(m_vao_id);
9980 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9981
9982 /* Create a texture object we will use as FBO's color attachment */
9983 gl.genTextures(1, &m_to_id);
9984 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9985
9986 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9987 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9988
9989 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9990 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9991
9992 /* Allocate temporary buffer to hold the texture data we will be reading
9993 * from color attachment. */
9994 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9995
9996 /* Create and set up a framebuffer object */
9997 gl.genFramebuffers(1, &m_fbo_id);
9998 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9999
10000 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
10001 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
10002
10003 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10004 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10005
10006 /* Create all shader objects */
10007 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10008 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10009 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10010 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10011 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10012 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10013
10014 /* Create test program object */
10015 m_po_id = gl.createProgram();
10016 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10017
10018 /* Attach the shaders to the program object */
10019 gl.attachShader(m_po_id, m_fs_id);
10020 gl.attachShader(m_po_id, m_gs_id);
10021 gl.attachShader(m_po_id, m_tc_id);
10022 gl.attachShader(m_po_id, m_te_id);
10023 gl.attachShader(m_po_id, m_vs_id);
10024 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10025
10026 /* The test passes double-precision values through the whole rendering pipeline.
10027 * This translates to a notable amount of components that we would need to transfer
10028 * all values in one fell swoop. The number is large enough to exceed minimum
10029 * capabilities as described for OpenGL 4.0 implementations.
10030 * For that reason, the test executes in turns. Each turn is allocated as many
10031 * double-precision scalar/matrix values as supported by the tested GL implementation.
10032 */
10033 glw::GLint gl_max_fragment_input_components_value = 0;
10034 glw::GLint gl_max_geometry_input_components_value = 0;
10035 glw::GLint gl_max_geometry_output_components_value = 0;
10036 glw::GLint gl_max_tess_control_input_components_value = 0;
10037 glw::GLint gl_max_tess_control_output_components_value = 0;
10038 glw::GLint gl_max_tess_evaluation_input_components_value = 0;
10039 glw::GLint gl_max_tess_evaluation_output_components_value = 0;
10040 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10041 glw::GLint gl_max_vertex_output_components_value = 0;
10042
10043 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10044 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10045 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10046 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10047 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10048 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10049 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10050 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10051 &gl_max_transform_feedback_interleaved_components_value);
10052 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10053 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10054
10055 m_n_max_components_per_stage =
10056 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10057 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10058 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10059 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10060 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10061 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10062 m_n_max_components_per_stage =
10063 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10064 m_n_max_components_per_stage =
10065 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10066
10067 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10068 * the input patch */
10069 gl.patchParameteri(GL_PATCH_VERTICES, 1);
10070
10071 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10072
10073 /* Initialize a BO we will use to hold XFB data */
10074 gl.genBuffers(1, &m_xfb_bo_id);
10075 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10076
10077 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10078 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10079
10080 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10081 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10082 }
10083
10084 /** Executes test iteration.
10085 *
10086 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10087 */
iterate()10088 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10089 {
10090 /* Do not execute the test if GL_ARB_texture_view is not supported */
10091 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10092 {
10093 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10094 }
10095
10096 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10097 {
10098 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10099 }
10100
10101 /* Initialize GL objects required to run the test */
10102 initTest();
10103
10104 /* Check the negative cases first */
10105 const Utils::_variable_type double_variable_types[] = {
10106 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10107 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10108 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10109 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10110 Utils::VARIABLE_TYPE_DMAT4X3,
10111 };
10112 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10113
10114 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10115 ++n_double_variable_type)
10116 {
10117 for (unsigned int array_size = 1; array_size < 3; ++array_size)
10118 {
10119 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10120
10121 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10122 {
10123 m_testCtx.getLog() << tcu::TestLog::Message
10124 << "A fragment shader with double-precision output variable compiled successfully."
10125 << tcu::TestLog::EndMessage;
10126
10127 m_has_test_passed = false;
10128 }
10129
10130 if (compileShader(m_fs_id,
10131 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10132 {
10133 m_testCtx.getLog()
10134 << tcu::TestLog::Message
10135 << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10136 " compiled successfully."
10137 << tcu::TestLog::EndMessage;
10138
10139 m_has_test_passed = false;
10140 }
10141 }
10142 } /* for (all variable types) */
10143
10144 /* Execute functional test. Split the run into as many iterations as necessary
10145 * so that we do not exceed GL implementation's capabilities. */
10146 unsigned int n_tested_variables = 0;
10147 _variables variables_to_test;
10148
10149 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10150 {
10151 glw::GLint total_n_used_components = 0;
10152
10153 /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10154 * of varying components that can be used for all shadr stages.
10155 */
10156 while (total_n_used_components < m_n_max_components_per_stage &&
10157 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10158 {
10159 _variable new_variable;
10160 unsigned int n_type_components = 0;
10161 glw::GLint n_used_components = 0;
10162
10163 new_variable.array_size =
10164 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10165 new_variable.type = double_variable_types[n_tested_variables / 2];
10166
10167 /* Double-precision varyings can use twice as many components as single-precision FPs */
10168 n_type_components = 4 /* components per location */ *
10169 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10170 n_used_components = n_type_components * new_variable.array_size * 2;
10171
10172 /* Do we have enough space? */
10173 if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10174 {
10175 if (n_used_components > m_n_max_components_per_stage)
10176 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10177 n_tested_variables++;
10178 }
10179 break;
10180 }
10181
10182 /* We can safely test the type in current iteration */
10183 total_n_used_components += n_used_components;
10184 n_tested_variables++;
10185
10186 variables_to_test.push_back(new_variable);
10187 }
10188
10189 if (variables_to_test.size() > 0)
10190 {
10191 m_has_test_passed &= executeFunctionalTest(variables_to_test);
10192
10193 variables_to_test.clear();
10194 }
10195 }
10196
10197 /* We're done */
10198 if (m_has_test_passed)
10199 {
10200 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10201 }
10202 else
10203 {
10204 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10205 }
10206
10207 return STOP;
10208 }
10209
10210 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables& variables)10211 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10212 {
10213 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10214 std::stringstream log_sstream;
10215
10216 log_sstream << "Test variable values as retrieved from geometry shader:\n";
10217
10218 /* Map the XFB BO contents into process space */
10219 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10220
10221 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10222
10223 /* Read the variable contents. We only care about the set of varyings emitted
10224 * for first vertex in the geometry shader */
10225 unsigned int n_varying = 0;
10226 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10227
10228 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10229 ++variables_iterator, ++n_varying)
10230 {
10231 const _variable& variable = *variables_iterator;
10232 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10233 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10234
10235 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10236 {
10237 log_sstream << "gs_variable" << n_varying;
10238
10239 if (variable.array_size > 1)
10240 {
10241 log_sstream << "[" << array_index << "]";
10242 }
10243
10244 log_sstream << ": (";
10245
10246 for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10247 {
10248 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10249
10250 if (n_component != (n_components - 1))
10251 {
10252 log_sstream << ", ";
10253 }
10254
10255 traveller_ptr += sizeof(double);
10256 }
10257
10258 log_sstream << ")\n";
10259 } /* for (all array indices) */
10260 } /* for (all variables) */
10261
10262 /* Unmap the BO */
10263 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10264 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10265
10266 /* Pass the logged stream into the framework */
10267 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10268 }
10269
10270 /** De-allocates an arary holding strings representing names of varyings that
10271 * should be used for transform feed-back.
10272 **/
releaseXFBVaryingNames()10273 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10274 {
10275 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10276 {
10277 delete[] m_xfb_varyings[n_varying];
10278 }
10279
10280 delete[] m_xfb_varyings;
10281 m_xfb_varyings = DE_NULL;
10282
10283 m_n_xfb_varyings = 0;
10284 }
10285
10286 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10287 * Takes a list of test variables used for current iteration and assigns increasing values
10288 * to subsequent input attributes of the test program.
10289 *
10290 * @param variables Test variables of the current iteration.
10291 */
setInputAttributeValues(const _variables& variables)10292 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10293 {
10294 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10295
10296 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10297 variable_iterator++)
10298 {
10299 const _variable& variable = *variable_iterator;
10300 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type);
10301 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10302 unsigned int n_components = 0;
10303 unsigned int n_columns = 1;
10304
10305 if (is_matrix_type)
10306 {
10307 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type);
10308 n_components = n_total_components / n_columns;
10309
10310 DE_ASSERT(n_total_components % n_columns == 0);
10311 }
10312 else
10313 {
10314 n_components = n_total_components;
10315 }
10316
10317 DE_ASSERT(n_components >= 1 && n_components <= 4);
10318
10319 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10320 {
10321 const double data[] = { -1, -1, -1, -1 };
10322
10323 switch (n_components)
10324 {
10325 case 1:
10326 {
10327 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10328 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10329
10330 break;
10331 }
10332
10333 case 2:
10334 {
10335 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10336 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10337
10338 break;
10339 }
10340
10341 case 3:
10342 {
10343 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10344 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10345
10346 break;
10347 }
10348
10349 case 4:
10350 {
10351 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10352 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10353
10354 break;
10355 }
10356
10357 default:
10358 {
10359 TCU_FAIL("Unrecognized number of components");
10360 }
10361 } /* switch (n_components) */
10362
10363 /* Make sure VAAs are disabled */
10364 gl.disableVertexAttribArray(variable.attribute_location + index);
10365 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10366 } /* for (all array indices) */
10367 } /* for (all variables) */
10368 }
10369
10370 /** Constructor
10371 *
10372 * @param context Rendering context.
10373 */
GPUShaderFP64Test8(deqp::Context& context)10374 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10375 : TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10376 "are accepted during compilation stage")
10377 , m_cs_id(0)
10378 , m_fs_id(0)
10379 , m_gs_id(0)
10380 , m_tc_id(0)
10381 , m_te_id(0)
10382 , m_vs_id(0)
10383 , m_has_test_passed(true)
10384 {
10385 }
10386
10387 /** Deinitializes all buffers and GL objects that may have been generated
10388 * during test execution.
10389 **/
deinit()10390 void GPUShaderFP64Test8::deinit()
10391 {
10392 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10393
10394 if (m_cs_id != 0)
10395 {
10396 gl.deleteShader(m_cs_id);
10397
10398 m_cs_id = 0;
10399 }
10400
10401 if (m_fs_id != 0)
10402 {
10403 gl.deleteShader(m_fs_id);
10404
10405 m_fs_id = 0;
10406 }
10407
10408 if (m_gs_id != 0)
10409 {
10410 gl.deleteShader(m_gs_id);
10411
10412 m_gs_id = 0;
10413 }
10414
10415 if (m_tc_id != 0)
10416 {
10417 gl.deleteShader(m_tc_id);
10418
10419 m_tc_id = 0;
10420 }
10421
10422 if (m_te_id != 0)
10423 {
10424 gl.deleteShader(m_te_id);
10425
10426 m_te_id = 0;
10427 }
10428
10429 if (m_vs_id != 0)
10430 {
10431 gl.deleteShader(m_vs_id);
10432
10433 m_vs_id = 0;
10434 }
10435 }
10436
10437 /** Executes a single test case.
10438 *
10439 * This function can throw TestError exceptions if GL implementation reports
10440 * an error.
10441 *
10442 * @param test_case Test case descriptor.
10443 *
10444 * @return true if test case passed, false otherwise.
10445 **/
executeIteration(const _test_case& test_case)10446 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10447 {
10448 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10449 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10450 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
10451 bool result = true;
10452 const char* stage_body = NULL;
10453 const char* stage_name = NULL;
10454
10455 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10456 {
10457 const glw::GLuint so_id = so_ids[n_so_id];
10458
10459 /* Skip compute shader if it is not supported */
10460 if (0 == so_id)
10461 {
10462 continue;
10463 }
10464
10465 /* Compile the shader */
10466 gl.compileShader(so_id);
10467 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10468
10469 /* Has the compilation succeeded as expected? */
10470 glw::GLint compile_status = GL_FALSE;
10471
10472 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10473 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10474
10475 if (compile_status == GL_FALSE)
10476 {
10477 /* What is the current stage's name? */
10478 if (so_id == m_cs_id)
10479 {
10480 stage_body = test_case.cs_shader_body.c_str();
10481 stage_name = "Compute shader";
10482 }
10483 else if (so_id == m_fs_id)
10484 {
10485 stage_body = test_case.fs_shader_body.c_str();
10486 stage_name = "Fragment shader";
10487 }
10488 else if (so_id == m_gs_id)
10489 {
10490 stage_body = test_case.gs_shader_body.c_str();
10491 stage_name = "Geometry shader";
10492 }
10493 else if (so_id == m_tc_id)
10494 {
10495 stage_body = test_case.tc_shader_body.c_str();
10496 stage_name = "Tessellation control shader";
10497 }
10498 else if (so_id == m_te_id)
10499 {
10500 stage_body = test_case.te_shader_body.c_str();
10501 stage_name = "Tessellation evaluation shader";
10502 }
10503 else if (so_id == m_vs_id)
10504 {
10505 stage_body = test_case.vs_shader_body.c_str();
10506 stage_name = "Vertex shader";
10507 }
10508 else
10509 {
10510 /* Doesn't make much sense to throw exceptions here so.. */
10511 stage_body = "";
10512 stage_name = "[?]";
10513 }
10514
10515 /* This shader should have never failed to compile! */
10516 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10517 << " has not compiled successfully, even though the shader is valid."
10518 " Following is shader's body:\n"
10519 << stage_body << tcu::TestLog::EndMessage;
10520
10521 result = false;
10522 }
10523 } /* for (all shader objects) */
10524
10525 return result;
10526 }
10527
10528 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10529 * type.
10530 *
10531 * @param variable_type Variable type to return valid argument lists for.
10532 **/
getArgumentListsForVariableType( const Utils::_variable_type& variable_type)10533 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10534 const Utils::_variable_type& variable_type)
10535 {
10536 const Utils::_variable_type matrix_types[] = {
10537 Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10538 Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10539 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10540 };
10541 const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10542 Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10543 const unsigned int n_matrix_types = sizeof(matrix_types) / sizeof(matrix_types[0]);
10544 const unsigned int n_scalar_types = sizeof(scalar_types) / sizeof(scalar_types[0]);
10545 const int n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10546
10547 /* Construct the argument list tree root. Each node carries a counter that tells how many components
10548 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10549 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10550 * used to define a subsequent argument, and its counter is increased by the amount of components
10551 * described by the type.
10552 */
10553 _argument_list_tree_node root;
10554
10555 root.n_components_used = 0;
10556 root.parent = NULL;
10557 root.type = variable_type;
10558
10559 /* Fill till all leaves use up all available components */
10560 _argument_list_tree_node_queue nodes_queue;
10561
10562 nodes_queue.push(&root);
10563
10564 do
10565 {
10566 /* Pop the first item in the queue */
10567 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10568 nodes_queue.pop();
10569
10570 /* Matrix variable types can be defined by a combination of non-matrix variable types OR
10571 * a single matrix variable type.
10572 *
10573 * Let's handle the latter case first.
10574 */
10575 const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10576
10577 if (Utils::isMatrixVariableType(current_node_ptr->type))
10578 {
10579 /* Iterate through all known matrix types. All the types can be used
10580 * as a constructor, assuming only one value is used to define new matrix's
10581 * contents. */
10582 for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10583 {
10584 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10585
10586 /* Construct a new child node. Since GLSL spec clearly states we must not use more
10587 * than one constructor argument if the only argument is a matrix type, mark the node
10588 * as if it defined all available components.
10589 */
10590 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10591
10592 new_subnode->n_components_used = n_total_components;
10593 new_subnode->parent = current_node_ptr;
10594 new_subnode->type = new_argument_type;
10595
10596 /* Add the descriptor to node list but do not add it to the queue. This would be
10597 * a redundant operation, since no new children nodes would have been assigned to
10598 * this node anyway.
10599 */
10600 current_node_ptr->children.push_back(new_subnode);
10601 } /* for (all matrix types) */
10602 } /* if (current node's type is a matrix) */
10603
10604 /* Now for a combination of non-matrix variable types.. */
10605 if (!Utils::isMatrixVariableType(current_node_ptr->type))
10606 {
10607 /* Iterate through all known scalar types */
10608 for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10609 {
10610 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10611 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10612
10613 /* Only use the scalar type if we don't exceed the amount of components we can define
10614 * for requested type.
10615 */
10616 if (n_new_argument_components <= n_components_remaining)
10617 {
10618 /* Form new node descriptor */
10619 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10620
10621 new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10622 new_subnode->parent = current_node_ptr;
10623 new_subnode->type = new_argument_type;
10624
10625 current_node_ptr->children.push_back(new_subnode);
10626 nodes_queue.push(new_subnode);
10627 }
10628 } /* for (all scalar types) */
10629 } /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10630 } while (nodes_queue.size() > 0);
10631
10632 /* To construct the argument lists, traverse the tree. Each path from root to child
10633 * gives us a single argument list.
10634 *
10635 * First, identify leaf nodes.
10636 */
10637 _argument_list_tree_nodes leaf_nodes;
10638
10639 nodes_queue.push(&root);
10640
10641 do
10642 {
10643 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10644 nodes_queue.pop();
10645
10646 if (current_node_ptr->children.size() == 0)
10647 {
10648 /* This is a leaf node !*/
10649 leaf_nodes.push_back(current_node_ptr);
10650 }
10651 else
10652 {
10653 /* Throw all children nodes to the queue */
10654 const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10655
10656 for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10657 {
10658 nodes_queue.push(current_node_ptr->children[n_children_node]);
10659 } /* for (all children nodes) */
10660 }
10661 } while (nodes_queue.size() > 0);
10662
10663 /* For all leaf nodes, move up the tree and construct the argument lists. */
10664 const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10665 _argument_lists result;
10666
10667 for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10668 {
10669 _argument_list argument_list;
10670 _argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10671
10672 do
10673 {
10674 if (current_node_ptr != &root)
10675 {
10676 if (argument_list.size() == 0)
10677 {
10678 argument_list.push_back(current_node_ptr->type);
10679 }
10680 else
10681 {
10682 argument_list.insert(argument_list.begin(), current_node_ptr->type);
10683 }
10684 }
10685
10686 current_node_ptr = current_node_ptr->parent;
10687 } while (current_node_ptr != NULL);
10688
10689 result.push_back(argument_list);
10690 } /* for (all leaf nodes) */
10691
10692 return result;
10693 }
10694
10695 /** Retrieves body of a compute shader that should be used for the purpose of
10696 * user-specified test case.
10697 *
10698 * @param test_case Test case descriptor to use.
10699 *
10700 * @return Requested string.
10701 **/
getComputeShaderBody(const _test_case& test_case)10702 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10703 {
10704 std::stringstream result_sstream;
10705
10706 /* Form the body */
10707 result_sstream << "#version 420\n"
10708 "#extension GL_ARB_compute_shader : require\n"
10709 "\n"
10710 "layout(local_size_x = 1) in;\n"
10711 "\n"
10712 "void main()\n"
10713 "{\n"
10714 << getGeneralBody(test_case) << "}\n";
10715
10716 /* Return the body */
10717 return result_sstream.str();
10718 }
10719
10720 /** Retrieves body of a fragment shader that should be used for the purpose of
10721 * user-specified test case.
10722 *
10723 * @param test_case Test case descriptor to use.
10724 *
10725 * @return Requested string.
10726 **/
getFragmentShaderBody(const _test_case& test_case)10727 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10728 {
10729 std::stringstream result_sstream;
10730
10731 /* Form the body */
10732 result_sstream << "#version 420\n"
10733 "\n"
10734 "void main()\n"
10735 "{\n"
10736 << getGeneralBody(test_case) << "}\n"
10737 "\n";
10738
10739 /* Return the body */
10740 return result_sstream.str();
10741 }
10742
10743 /** Returns a GLSL line that defines and initializes a variable as described by
10744 * user-specified test case descriptor.
10745 *
10746 * @param test_case Test case descriptor to use for the query.
10747 *
10748 * @return As per description
10749 **/
getGeneralBody(const _test_case& test_case)10750 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10751 {
10752 std::stringstream result_sstream;
10753
10754 /* Form the body */
10755 std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10756
10757 result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10758
10759 for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10760 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10761 {
10762 const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10763 std::string argument_variable_type_string = Utils::getVariableTypeString(argument_variable_type);
10764 const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10765
10766 if (argument_list_iterator != test_case.argument_list.begin())
10767 {
10768 result_sstream << ", ";
10769 }
10770
10771 result_sstream << argument_variable_type_string << "(";
10772
10773 for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10774 {
10775 result_sstream << (double)(n_component + 1);
10776
10777 if (n_component != (argument_n_components - 1))
10778 {
10779 result_sstream << ", ";
10780 }
10781 } /* for (all argument components) */
10782
10783 result_sstream << ")";
10784 } /* for (all arguments) */
10785
10786 result_sstream << ");\n";
10787
10788 return result_sstream.str();
10789 }
10790
10791 /** Retrieves body of a geometry shader that should be used for the purpose of
10792 * user-specified test case.
10793 *
10794 * @param test_case Test case descriptor to use.
10795 *
10796 * @return Requested string.
10797 **/
getGeometryShaderBody(const _test_case& test_case)10798 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10799 {
10800 std::stringstream result_sstream;
10801
10802 /* Form the body */
10803 result_sstream << "#version 420\n"
10804 "\n"
10805 "layout(points) in;\n"
10806 "layout(max_vertices=1, points) out;\n"
10807 "\n"
10808 "void main()\n"
10809 "{\n"
10810 << getGeneralBody(test_case) << "}\n"
10811 "\n";
10812
10813 /* We're done! */
10814 return result_sstream.str();
10815 }
10816
10817 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10818 * user-specified test case.
10819 *
10820 * @param test_case Test case descriptor to use.
10821 *
10822 * @return Requested string.
10823 **/
getTessellationControlShaderBody(const _test_case& test_case)10824 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10825 {
10826 std::stringstream result_sstream;
10827
10828 /* Form the body */
10829 result_sstream << "#version 420\n"
10830 "\n"
10831 "layout(vertices=4) out;\n"
10832 "\n"
10833 "void main()\n"
10834 "{\n"
10835 << getGeneralBody(test_case) << "}\n"
10836 "\n";
10837
10838 /* Return the body */
10839 return result_sstream.str();
10840 }
10841
10842 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10843 * user-specified test case.
10844 *
10845 * @param test_case Test case descriptor to use.
10846 *
10847 * @return Requested string.
10848 **/
getTessellationEvaluationShaderBody(const _test_case& test_case)10849 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10850 {
10851 std::stringstream result_sstream;
10852
10853 /* Form the body */
10854 result_sstream << "#version 420\n"
10855 "\n"
10856 "layout(isolines) in;\n"
10857 "\n"
10858 "void main()\n"
10859 "{\n"
10860 << getGeneralBody(test_case) << "}\n"
10861 "\n";
10862
10863 /* Return the body */
10864 return result_sstream.str();
10865 }
10866
10867 /** Retrieves body of a vertex shader that should be used for the purpose of
10868 * user-specified test case.
10869 *
10870 * @param test_case Test case descriptor to use.
10871 *
10872 * @return Requested string.
10873 **/
getVertexShaderBody(const _test_case& test_case)10874 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10875 {
10876 std::stringstream result_sstream;
10877
10878 /* Form the body */
10879 result_sstream << "#version 420\n"
10880 "\n"
10881 "void main()\n"
10882 "{\n"
10883 << getGeneralBody(test_case) << "}\n"
10884 "\n";
10885
10886 return result_sstream.str();
10887 }
10888
10889 /** Initializes shader objects required to run the test. */
initTest()10890 void GPUShaderFP64Test8::initTest()
10891 {
10892 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10893
10894 /* Generate shader objects */
10895
10896 /* Compute shader support and GL 4.2 required */
10897 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10898 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10899 {
10900 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10901 }
10902
10903 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10904 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10905 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10906 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10907 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10908
10909 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10910 }
10911
10912 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10913 *
10914 * @param test_case Test case descriptor to generate the shader bodies for.
10915 **/
initIteration(_test_case& test_case)10916 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10917 {
10918 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10919
10920 test_case.cs_shader_body = getComputeShaderBody(test_case);
10921 test_case.fs_shader_body = getFragmentShaderBody(test_case);
10922 test_case.gs_shader_body = getGeometryShaderBody(test_case);
10923 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10924 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10925 test_case.vs_shader_body = getVertexShaderBody(test_case);
10926
10927 /* Assign the bodies to relevant shaders */
10928 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10929 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10930 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10931 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10932 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10933 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10934
10935 /* m_cs_id is initialized only if compute_shader is supported */
10936 if (0 != m_cs_id)
10937 {
10938 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10939 }
10940
10941 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10942 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10943 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10944 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10945 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10946 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10947 }
10948
10949 /** Executes test iteration.
10950 *
10951 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10952 */
iterate()10953 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10954 {
10955 /* Do not execute the test if GL_ARB_texture_view is not supported */
10956 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10957 {
10958 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10959 }
10960
10961 /* Initialize GL objects needed to run the tests */
10962 initTest();
10963
10964 /* Build iteration array to run the tests in an automated manner */
10965 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10966 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10967 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10968 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10969 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10970 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10971 Utils::VARIABLE_TYPE_DVEC4 };
10972 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10973
10974 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10975 {
10976 const Utils::_variable_type variable_type = variable_types[n_variable_type];
10977
10978 /* Construct a set of argument lists valid for the variable type considered */
10979 _argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10980
10981 for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10982 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10983 {
10984 /* Constructor thwe test case descriptor */
10985 _test_case test_case;
10986
10987 test_case.argument_list = *argument_list_iterator;
10988 test_case.type = variable_type;
10989
10990 /* Initialize a program object we will use to perform the casting */
10991 initIteration(test_case);
10992
10993 /* See if the shader compiles. */
10994 m_has_test_passed &= executeIteration(test_case);
10995 } /* for (all argument lists) */
10996 } /* for (all variable types) */
10997
10998 /* We're done */
10999 if (m_has_test_passed)
11000 {
11001 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11002 }
11003 else
11004 {
11005 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11006 }
11007
11008 return STOP;
11009 }
11010
11011 /** Constructor.
11012 *
11013 * @param context Rendering context.
11014 *
11015 **/
GPUShaderFP64Test9(deqp::Context& context)11016 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11017 : TestCase(context, "operators", "Verifies that general and relational operators work "
11018 "correctly when used against double-precision floating-"
11019 "point types.")
11020 , m_has_test_passed(true)
11021 , m_po_id(0)
11022 , m_xfb_bo_id(0)
11023 , m_vao_id(0)
11024 , m_vs_id(0)
11025 {
11026 /* Left blank intentionally */
11027 }
11028
11029 /** Deinitializes all ES objects that may have been created during
11030 * test execution.
11031 **/
deinit()11032 void GPUShaderFP64Test9::deinit()
11033 {
11034 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11035
11036 if (m_po_id != 0)
11037 {
11038 gl.deleteProgram(m_po_id);
11039
11040 m_po_id = 0;
11041 }
11042
11043 if (m_xfb_bo_id != 0)
11044 {
11045 gl.deleteBuffers(1, &m_xfb_bo_id);
11046
11047 m_xfb_bo_id = 0;
11048 }
11049
11050 if (m_vao_id != 0)
11051 {
11052 gl.deleteVertexArrays(1, &m_vao_id);
11053
11054 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11055 }
11056
11057 if (m_vs_id != 0)
11058 {
11059 gl.deleteShader(m_vs_id);
11060
11061 m_vs_id = 0;
11062 }
11063 }
11064
11065 /** Executes a single test iteration using user-specified test case properties.
11066 *
11067 * @param test_case Test case descriptor.
11068 *
11069 * @return true if the pass was successful, false if the test should fail.
11070 **/
executeTestIteration(const _test_case& test_case)11071 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11072 {
11073 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11074 bool result = true;
11075
11076 /* Activate the test program object */
11077 gl.useProgram(m_po_id);
11078 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11079
11080 /* Draw a single point with XFB enabled */
11081 gl.beginTransformFeedback(GL_POINTS);
11082 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11083 {
11084 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11085 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11086 }
11087 gl.endTransformFeedback();
11088 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11089
11090 /* Map the XFB BO into process space */
11091 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11092
11093 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11094
11095 result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11096
11097 /* Unmap the BO */
11098 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11099 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11100
11101 return result;
11102 }
11103
11104 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11105 * under user-specified location.
11106 *
11107 * @param matrix_a_type Type of the l-side matrix.
11108 * @param matrix_a_data Row-ordered data of l-side matrix.
11109 * @param matrix_b_type Type of the r-side matrix.
11110 * @param matrix_b_data Row-ordered data of r-side matrix.
11111 * @param out_result_ptr Deref to be used to store the multiplication result.
11112 **/
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)11113 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11114 const std::vector<double>& matrix_a_data,
11115 const Utils::_variable_type& matrix_b_type,
11116 const std::vector<double>& matrix_b_data, double* out_result_ptr)
11117 {
11118 (void)matrix_b_type;
11119 using namespace tcu;
11120 /* To keep the code maintainable, we only consider cases relevant for this test */
11121 switch (matrix_a_type)
11122 {
11123 case Utils::VARIABLE_TYPE_DMAT2:
11124 {
11125 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11126
11127 tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11128 tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11129 tcu::Matrix2d result;
11130
11131 matrix_a = transpose(matrix_a);
11132 matrix_b = transpose(matrix_b);
11133 result = matrix_a * matrix_b;
11134
11135 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11136 break;
11137 }
11138
11139 case Utils::VARIABLE_TYPE_DMAT2X3:
11140 {
11141 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11142
11143 tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11144 tcu::Matrix<double, 3, 2> matrix_a_transposed;
11145 tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11146 tcu::Matrix<double, 2, 3> matrix_b_transposed;
11147 tcu::Matrix<double, 3, 3> result;
11148
11149 matrix_a_transposed = transpose(matrix_a);
11150 matrix_b_transposed = transpose(matrix_b);
11151 result = matrix_a_transposed * matrix_b_transposed;
11152
11153 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11154 break;
11155 }
11156
11157 case Utils::VARIABLE_TYPE_DMAT2X4:
11158 {
11159 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11160
11161 tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11162 tcu::Matrix<double, 4, 2> matrix_a_transposed;
11163 tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11164 tcu::Matrix<double, 2, 4> matrix_b_transposed;
11165 tcu::Matrix<double, 4, 4> result;
11166
11167 matrix_a_transposed = transpose(matrix_a);
11168 matrix_b_transposed = transpose(matrix_b);
11169 result = matrix_a_transposed * matrix_b_transposed;
11170
11171 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11172 break;
11173 }
11174
11175 case Utils::VARIABLE_TYPE_DMAT3:
11176 {
11177 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11178
11179 tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11180 tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11181 tcu::Matrix<double, 3, 3> result;
11182
11183 matrix_a = transpose(matrix_a);
11184 matrix_b = transpose(matrix_b);
11185 result = matrix_a * matrix_b;
11186
11187 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11188 break;
11189 }
11190
11191 case Utils::VARIABLE_TYPE_DMAT3X2:
11192 {
11193 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11194
11195 tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11196 tcu::Matrix<double, 2, 3> matrix_a_transposed;
11197 tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11198 tcu::Matrix<double, 3, 2> matrix_b_transposed;
11199 tcu::Matrix<double, 2, 2> result;
11200
11201 matrix_a_transposed = transpose(matrix_a);
11202 matrix_b_transposed = transpose(matrix_b);
11203 result = matrix_a_transposed * matrix_b_transposed;
11204
11205 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11206 break;
11207 }
11208
11209 case Utils::VARIABLE_TYPE_DMAT3X4:
11210 {
11211 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11212
11213 tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11214 tcu::Matrix<double, 4, 3> matrix_a_transposed;
11215 tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11216 tcu::Matrix<double, 3, 4> matrix_b_transposed;
11217 tcu::Matrix<double, 4, 4> result;
11218
11219 matrix_a_transposed = transpose(matrix_a);
11220 matrix_b_transposed = transpose(matrix_b);
11221 result = matrix_a_transposed * matrix_b_transposed;
11222
11223 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11224 break;
11225 }
11226
11227 case Utils::VARIABLE_TYPE_DMAT4:
11228 {
11229 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11230
11231 tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11232 tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11233 tcu::Matrix<double, 4, 4> result;
11234
11235 matrix_a = transpose(matrix_a);
11236 matrix_b = transpose(matrix_b);
11237 result = matrix_a * matrix_b;
11238
11239 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11240 break;
11241 }
11242
11243 case Utils::VARIABLE_TYPE_DMAT4X2:
11244 {
11245 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11246
11247 tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11248 tcu::Matrix<double, 2, 4> matrix_a_transposed;
11249 tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11250 tcu::Matrix<double, 4, 2> matrix_b_transposed;
11251 tcu::Matrix<double, 2, 2> result;
11252
11253 matrix_a_transposed = transpose(matrix_a);
11254 matrix_b_transposed = transpose(matrix_b);
11255 result = matrix_a_transposed * matrix_b_transposed;
11256
11257 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11258 break;
11259 }
11260
11261 case Utils::VARIABLE_TYPE_DMAT4X3:
11262 {
11263 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11264
11265 tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11266 tcu::Matrix<double, 3, 4> matrix_a_transposed;
11267 tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11268 tcu::Matrix<double, 4, 3> matrix_b_transposed;
11269 tcu::Matrix<double, 3, 3> result;
11270
11271 matrix_a_transposed = transpose(matrix_a);
11272 matrix_b_transposed = transpose(matrix_b);
11273 result = matrix_a_transposed * matrix_b_transposed;
11274
11275 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11276 break;
11277 }
11278
11279 default:
11280 {
11281 TCU_FAIL("Unrecognized matrix A type");
11282 }
11283 } /* switch (matrix_a_type) */
11284 }
11285
11286 /** Returns GLSL operator representation of the user-specified operation.
11287 *
11288 * @param operation_type Internal operation type to retrieve the operator for.
11289 *
11290 * @return As per description.
11291 **/
getOperatorForOperationType(const _operation_type& operation_type)11292 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11293 {
11294 const char* result = NULL;
11295
11296 switch (operation_type)
11297 {
11298 case OPERATION_TYPE_ADDITION:
11299 result = "+";
11300 break;
11301 case OPERATION_TYPE_DIVISION:
11302 result = "/";
11303 break;
11304 case OPERATION_TYPE_MULTIPLICATION:
11305 result = "*";
11306 break;
11307 case OPERATION_TYPE_SUBTRACTION:
11308 result = "-";
11309 break;
11310
11311 case OPERATION_TYPE_PRE_DECREMENTATION:
11312 case OPERATION_TYPE_POST_DECREMENTATION:
11313 {
11314 result = "--";
11315
11316 break;
11317 }
11318
11319 case OPERATION_TYPE_PRE_INCREMENTATION:
11320 case OPERATION_TYPE_POST_INCREMENTATION:
11321 {
11322 result = "++";
11323
11324 break;
11325 }
11326
11327 default:
11328 {
11329 TCU_FAIL("Unrecognized operation type");
11330 }
11331 } /* switch(operation_type) */
11332
11333 return result;
11334 }
11335
11336 /** Returns a string representing user-specified operation type.
11337 *
11338 * @param operation_type Operation type to return the literal for.
11339 *
11340 * @return Requested string.
11341 **/
getOperationTypeString(const _operation_type& operation_type)11342 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11343 {
11344 std::string result = "[?]";
11345
11346 switch (operation_type)
11347 {
11348 case OPERATION_TYPE_ADDITION:
11349 result = "addition";
11350 break;
11351 case OPERATION_TYPE_DIVISION:
11352 result = "division";
11353 break;
11354 case OPERATION_TYPE_MULTIPLICATION:
11355 result = "multiplication";
11356 break;
11357 case OPERATION_TYPE_SUBTRACTION:
11358 result = "subtraction";
11359 break;
11360 case OPERATION_TYPE_PRE_DECREMENTATION:
11361 result = "pre-decrementation";
11362 break;
11363 case OPERATION_TYPE_PRE_INCREMENTATION:
11364 result = "pre-incrementation";
11365 break;
11366 case OPERATION_TYPE_POST_DECREMENTATION:
11367 result = "post-decrementation";
11368 break;
11369 case OPERATION_TYPE_POST_INCREMENTATION:
11370 result = "post-incrementation";
11371 break;
11372
11373 default:
11374 {
11375 TCU_FAIL("Unrecognized operation type");
11376 }
11377 }
11378
11379 return result;
11380 }
11381
11382 /** Returns body of a vertex shader that should be used for user-specified test case
11383 * descriptor.
11384 *
11385 * @param test_case Test case descriptor.
11386 *
11387 * @return Requested GLSL shader body.
11388 **/
getVertexShaderBody(_test_case& test_case)11389 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11390 {
11391 std::stringstream result_sstream;
11392 std::string result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11393 std::string variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11394 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11395 const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11396
11397 /* If we are to multiply matrices, we will need to use a different type
11398 * for the result variable if either of the matrices is not square.
11399 */
11400 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11401 Utils::isMatrixVariableType(test_case.variable_type))
11402 {
11403 Utils::_variable_type result_variable_type;
11404 Utils::_variable_type transposed_matrix_variable_type =
11405 Utils::getTransposedMatrixVariableType(test_case.variable_type);
11406
11407 result_variable_type =
11408 Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11409 result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11410
11411 test_case.result_variable_type = result_variable_type;
11412 }
11413
11414 /* Form the pre-amble */
11415 result_sstream << "#version 400\n"
11416 "\n"
11417
11418 /* Add output variables */
11419 "out "
11420 << result_variable_type_string << " result;\n"
11421 "out ivec2 result_lt;\n"
11422 "out ivec2 result_lte;\n"
11423 "out ivec2 result_gt;\n"
11424 "out ivec2 result_gte;\n"
11425 "void main()\n"
11426 "{\n";
11427
11428 /* Form reference values */
11429 result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11430
11431 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11432 {
11433 result_sstream << (n_variable_component + 1);
11434
11435 if (n_variable_component != (n_variable_components - 1))
11436 {
11437 result_sstream << ", ";
11438 }
11439 } /* for (all variable components) */
11440
11441 result_sstream << ");\n";
11442
11443 for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11444 ++n_ref2_case)
11445 {
11446 Utils::_variable_type compatible_variable_type = test_case.variable_type;
11447
11448 if (Utils::isMatrixVariableType(compatible_variable_type) &&
11449 test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11450 {
11451 compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11452 }
11453
11454 std::string ref2_variable_type_fp_string =
11455 Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11456 std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11457 std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11458 std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11459
11460 result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11461
11462 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11463 ++n_variable_component)
11464 {
11465 result_sstream << (n_variable_components - (n_variable_component + 1));
11466
11467 if (n_variable_component != (n_variable_components - 1))
11468 {
11469 result_sstream << ", ";
11470 }
11471 } /* for (all variable components) */
11472
11473 result_sstream << ");\n";
11474 } /* for (both reference2 declarations) */
11475
11476 /* Add actual body */
11477 result_sstream << "\n"
11478 "result = ";
11479
11480 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11481 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11482 {
11483 result_sstream << getOperatorForOperationType(test_case.operation_type);
11484 }
11485
11486 result_sstream << "reference1 ";
11487
11488 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11489 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11490 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11491 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11492 {
11493 if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11494 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11495 {
11496 result_sstream << getOperatorForOperationType(test_case.operation_type);
11497 }
11498 }
11499 else
11500 {
11501 result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11502 }
11503
11504 result_sstream << ";\n";
11505
11506 if (Utils::isScalarVariableType(test_case.variable_type))
11507 {
11508 result_sstream << "result_lt [0] = (reference1 < reference2) ? 1 : 0;\n"
11509 "result_lt [1] = (reference1 < reference2f) ? 1 : 0;\n"
11510 "result_lte[0] = (reference1 <= reference2) ? 1 : 0;\n"
11511 "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11512 "result_gt [0] = (reference1 > reference2) ? 1 : 0;\n"
11513 "result_gt [1] = (reference1 > reference2f) ? 1 : 0;\n"
11514 "result_gte[0] = (reference1 >= reference2) ? 1 : 0;\n"
11515 "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11516 }
11517 else
11518 {
11519 result_sstream << "result_lt [0] = 1;\n"
11520 "result_lt [1] = 1;\n"
11521 "result_lte[0] = 1;\n"
11522 "result_lte[1] = 1;\n"
11523 "result_gt [0] = 1;\n"
11524 "result_gt [1] = 1;\n"
11525 "result_gte[0] = 1;\n"
11526 "result_gte[1] = 1;\n";
11527 }
11528
11529 result_sstream << "}\n";
11530
11531 /* All done */
11532 return result_sstream.str();
11533 }
11534
11535 /** Initializes all GL objects required to run the test.
11536 *
11537 * This function can throw a TestError exception if the implementation misbehaves.
11538 */
initTest()11539 void GPUShaderFP64Test9::initTest()
11540 {
11541 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11542
11543 /* Create program & vertex shader objects */
11544 m_po_id = gl.createProgram();
11545 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11546
11547 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11548
11549 /* Attach the shader to the program */
11550 gl.attachShader(m_po_id, m_vs_id);
11551 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11552
11553 /* Set up a buffer object */
11554 gl.genBuffers(1, &m_xfb_bo_id);
11555 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11556
11557 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11558 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11559
11560 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11561 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11562
11563 /* Set up a vertex array object */
11564 gl.genVertexArrays(1, &m_vao_id);
11565 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11566
11567 gl.bindVertexArray(m_vao_id);
11568 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11569 }
11570
11571 /** Initializes all GL objects required to run an iteration described by
11572 * user-specified test case descriptor.
11573 *
11574 * @param test_case Test case descriptor to use for the initialization.
11575 **/
initTestIteration(_test_case& test_case)11576 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11577 {
11578 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11579 std::string vs_body = getVertexShaderBody(test_case);
11580 const char* vs_body_raw_ptr = vs_body.c_str();
11581
11582 /* Store the shader's body */
11583 test_case.vs_body = vs_body;
11584
11585 /* Try to compile the shader */
11586 glw::GLint compile_status = GL_FALSE;
11587
11588 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11589 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11590
11591 gl.compileShader(m_vs_id);
11592 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11593
11594 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11595 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11596
11597 if (compile_status != GL_TRUE)
11598 {
11599 TCU_FAIL("Test shader compilation failed.");
11600 }
11601
11602 /* Configure XFB */
11603 const char* xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11604 const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11605
11606 gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11607 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11608
11609 /* Try to link the program */
11610 glw::GLint link_status = GL_FALSE;
11611
11612 gl.linkProgram(m_po_id);
11613 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11614
11615 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11616 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11617
11618 if (link_status != GL_TRUE)
11619 {
11620 TCU_FAIL("Test program linking failure");
11621 }
11622
11623 /* Set up XFB BO data storage */
11624 const unsigned int result_variable_size = static_cast<unsigned int>(
11625 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11626 const unsigned int xfb_bo_size = static_cast<unsigned int>(
11627 result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11628
11629 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11630 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11631 }
11632
11633 /** Executes test iteration.
11634 *
11635 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11636 */
iterate()11637 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11638 {
11639 /* Do not execute the test if GL_ARB_texture_view is not supported */
11640 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11641 {
11642 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11643 }
11644
11645 /* Initialize all ES objects required to run all the checks */
11646 initTest();
11647
11648 /* Iterate through all variable types we want to test */
11649 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
11650 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11651 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11652 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
11653 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11654 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
11655 Utils::VARIABLE_TYPE_DVEC4 };
11656 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11657
11658 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11659 {
11660 /* Iterate through all operation types we want to check */
11661 for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11662 {
11663 _operation_type operation_type = (_operation_type)n_operation_type;
11664 const Utils::_variable_type& variable_type = variable_types[n_variable_type];
11665
11666 /* Construct test case descriptor */
11667 _test_case test_case;
11668
11669 test_case.operation_type = operation_type;
11670 test_case.result_variable_type = variable_type;
11671 test_case.variable_type = variable_type;
11672
11673 /* Run the iteration */
11674 initTestIteration(test_case);
11675
11676 m_has_test_passed &= executeTestIteration(test_case);
11677 } /* for (all operation types) */
11678 } /* for (all variable types) */
11679
11680 /* All done. */
11681 if (m_has_test_passed)
11682 {
11683 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11684 }
11685 else
11686 {
11687 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11688 }
11689
11690 return STOP;
11691 }
11692
11693 /** Verifies data XFBed out by the draw call for user-specified test case
11694 * descriptor.
11695 *
11696 * @param test_case Test case descriptor
11697 * @param xfb_data Buffer holding the data XFBed out during the draw call.
11698 * Must not be NULL.
11699 *
11700 * @return true if the data was found to be correct, false otherwise.
11701 **/
verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)11702 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11703 {
11704 const double epsilon = 1e-5;
11705 const unsigned int n_result_components =
11706 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11707 bool result = true;
11708 const double* xfb_data_result = (const double*)xfb_data;
11709 const int* xfb_data_result_lt = (const int*)(xfb_data_result + n_result_components);
11710 const int* xfb_data_result_lte = (const int*)xfb_data_result_lt + 2; /* cast/non-cast cases */
11711 const int* xfb_data_result_gt = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11712 const int* xfb_data_result_gte = (const int*)xfb_data_result_gt + 2; /* cast/non-cast cases */
11713
11714 /* Prepare reference values */
11715 int modifier;
11716 std::vector<double> reference1;
11717 std::vector<double> reference2;
11718
11719 if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11720 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11721 {
11722 modifier = 1;
11723 }
11724 else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11725 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11726 {
11727 modifier = -1;
11728 }
11729 else
11730 {
11731 modifier = 0;
11732 }
11733
11734 if (Utils::isMatrixVariableType(test_case.variable_type))
11735 {
11736 /* Matrices may be of different sizes so we need to compute the
11737 * reference values separately for each matrix
11738 */
11739 const Utils::_variable_type matrix_a_type = test_case.variable_type;
11740 const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11741 const unsigned int n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11742 const unsigned int n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11743
11744 for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11745 {
11746 reference1.push_back(modifier + n_component + 1);
11747 }
11748
11749 for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11750 {
11751 reference2.push_back(n_matrix_b_components - (n_component + 1));
11752 }
11753 } /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11754 else
11755 {
11756 /* Generate as many components as will be expected for the result variable */
11757 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11758 {
11759 reference1.push_back(modifier + n_result_component + 1);
11760 reference2.push_back(n_result_components - (n_result_component + 1));
11761 }
11762 }
11763
11764 /* Verify the result value(s) */
11765 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11766 Utils::isMatrixVariableType(test_case.variable_type))
11767 {
11768 /* Matrix multiplication */
11769 double expected_result_data[4 * 4];
11770 Utils::_variable_type matrix_a_type = test_case.variable_type;
11771 Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11772
11773 getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11774
11775 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11776 {
11777 if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11778 {
11779 std::stringstream log_sstream;
11780
11781 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11782 << Utils::getVariableTypeString(matrix_b_type)
11783 << " matrix multiplication was incorrect; expected:(";
11784
11785 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11786 ++n_logged_component)
11787 {
11788 log_sstream << expected_result_data[n_logged_component];
11789
11790 if (n_logged_component != (n_result_components - 1))
11791 {
11792 log_sstream << ", ";
11793 }
11794 } /* for (all components to be logged) */
11795
11796 log_sstream << "), retrieved:(";
11797
11798 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11799 ++n_logged_component)
11800 {
11801 log_sstream << xfb_data_result[n_logged_component];
11802
11803 if (n_logged_component != (n_result_components - 1))
11804 {
11805 log_sstream << ", ";
11806 }
11807 } /* for (all components to be logged) */
11808
11809 log_sstream << ")";
11810
11811 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11812
11813 result = false;
11814 break;
11815 }
11816 } /* for (all result components) */
11817 } /* if (dealing with matrix multiplication) */
11818 else
11819 {
11820 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11821 {
11822 double expected_value = reference1[n_component];
11823
11824 switch (test_case.operation_type)
11825 {
11826 case OPERATION_TYPE_ADDITION:
11827 expected_value += reference2[n_component];
11828 break;
11829 case OPERATION_TYPE_DIVISION:
11830 expected_value /= reference2[n_component];
11831 break;
11832 case OPERATION_TYPE_MULTIPLICATION:
11833 expected_value *= reference2[n_component];
11834 break;
11835 case OPERATION_TYPE_SUBTRACTION:
11836 expected_value -= reference2[n_component];
11837 break;
11838
11839 case OPERATION_TYPE_PRE_DECREMENTATION:
11840 case OPERATION_TYPE_PRE_INCREMENTATION:
11841 {
11842 /* Modifier already applied */
11843 break;
11844 }
11845
11846 case OPERATION_TYPE_POST_DECREMENTATION:
11847 case OPERATION_TYPE_POST_INCREMENTATION:
11848 {
11849 /* Need to reverse the modification for the purpose of the following check */
11850 expected_value -= modifier;
11851
11852 break;
11853 }
11854
11855 default:
11856 {
11857 TCU_FAIL("Unrecognized operation type");
11858 }
11859 } /* switch (test_case.operation_type) */
11860
11861 if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11862 {
11863 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11864 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11865
11866 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11867 << variable_type_string << "]"
11868 " and operation type ["
11869 << operation_type_string << "]"
11870 " were found invalid."
11871 << tcu::TestLog::EndMessage;
11872
11873 result = false;
11874 break;
11875 } /* if (test case failed) */
11876 } /* for (all components) */
11877 }
11878
11879 /* Verify the comparison operation results */
11880 if (Utils::isScalarVariableType(test_case.variable_type))
11881 {
11882 DE_ASSERT(n_result_components == 1);
11883
11884 const bool expected_result_lt[2] = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11885 const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11886 const bool expected_result_gt[2] = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11887 const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11888
11889 if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11890 (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11891 {
11892 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11893 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11894
11895 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11896 "variable type ["
11897 << variable_type_string << "]"
11898 "and operation type ["
11899 << operation_type_string << "]"
11900 "was found invalid; expected:("
11901 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11902 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11903 << tcu::TestLog::EndMessage;
11904
11905 result = false;
11906 }
11907
11908 if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11909 (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11910 {
11911 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11912 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11913
11914 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11915 "variable type ["
11916 << variable_type_string << "]"
11917 "and operation type ["
11918 << operation_type_string << "]"
11919 "was found invalid; expected:("
11920 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11921 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11922 << tcu::TestLog::EndMessage;
11923
11924 result = false;
11925 }
11926
11927 if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11928 (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11929 {
11930 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11931 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11932
11933 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11934 "variable type ["
11935 << variable_type_string << "]"
11936 "and operation type ["
11937 << operation_type_string << "]"
11938 "was found invalid; expected:("
11939 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11940 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11941 << tcu::TestLog::EndMessage;
11942
11943 result = false;
11944 }
11945
11946 if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11947 (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11948 {
11949 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11950 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11951
11952 m_testCtx.getLog() << tcu::TestLog::Message
11953 << "Values reported for greater-than-or-equal operator used for "
11954 "variable type ["
11955 << variable_type_string << "]"
11956 "and operation type ["
11957 << operation_type_string << "]"
11958 "was found invalid; expected:("
11959 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11960 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11961 << tcu::TestLog::EndMessage;
11962
11963 result = false;
11964 }
11965 } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11966 else
11967 {
11968 if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11969 xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11970 xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11971 {
11972 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11973 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11974
11975 m_testCtx.getLog() << tcu::TestLog::Message
11976 << "Invalid value was reported for matrix variable type, for which "
11977 " operator checks are not executed; variable type ["
11978 << variable_type_string << "]"
11979 "and operation type ["
11980 << operation_type_string << "]" << tcu::TestLog::EndMessage;
11981
11982 result = false;
11983 }
11984 }
11985
11986 return result;
11987 }
11988
11989 namespace TypeHelpers
11990 {
11991 /** Get base type for reference types
11992 *
11993 * @tparam T type
11994 **/
11995 template <typename T>
11996 class referenceToType
11997 {
11998 public:
11999 typedef T result;
12000 };
12001
12002 template <typename T>
12003 class referenceToType<const T&>
12004 {
12005 public:
12006 typedef T result;
12007 };
12008
12009 /** Maps variable type with enumeration Utils::_variable_type
12010 *
12011 * @tparam T type
12012 **/
12013 template <typename T>
12014 class typeInfo;
12015
12016 template <>
12017 class typeInfo<glw::GLboolean>
12018 {
12019 public:
12020 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12021 };
12022
12023 template <>
12024 class typeInfo<glw::GLdouble>
12025 {
12026 public:
12027 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12028 };
12029
12030 template <>
12031 class typeInfo<tcu::UVec2>
12032 {
12033 public:
12034 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12035 };
12036
12037 template <>
12038 class typeInfo<tcu::UVec3>
12039 {
12040 public:
12041 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12042 };
12043
12044 template <>
12045 class typeInfo<tcu::UVec4>
12046 {
12047 public:
12048 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12049 };
12050
12051 template <>
12052 class typeInfo<tcu::DVec2>
12053 {
12054 public:
12055 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12056 };
12057
12058 template <>
12059 class typeInfo<tcu::DVec3>
12060 {
12061 public:
12062 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12063 };
12064
12065 template <>
12066 class typeInfo<tcu::DVec4>
12067 {
12068 public:
12069 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12070 };
12071
12072 template <>
12073 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12074 {
12075 public:
12076 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12077 };
12078
12079 template <>
12080 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12081 {
12082 public:
12083 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12084 };
12085
12086 template <>
12087 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12088 {
12089 public:
12090 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12091 };
12092
12093 template <>
12094 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12095 {
12096 public:
12097 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12098 };
12099
12100 template <>
12101 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12102 {
12103 public:
12104 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12105 };
12106
12107 template <>
12108 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12109 {
12110 public:
12111 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12112 };
12113
12114 template <>
12115 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12116 {
12117 public:
12118 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12119 };
12120
12121 template <>
12122 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12123 {
12124 public:
12125 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12126 };
12127
12128 template <>
12129 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12130 {
12131 public:
12132 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12133 };
12134 } /* TypeHelpers */
12135
12136 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12137 *
12138 **/
12139 namespace Math
12140 {
12141 template <typename T>
12142 static T clamp(T x, T minVal, T maxVal);
12143
12144 template <int Size>
12145 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12146
12147 template <int Size>
12148 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12149
12150 template <typename T>
12151 static T determinant(T val);
12152
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12155
12156 template <typename T>
12157 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12158
12159 template <typename T>
12160 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12161
12162 template <int Size>
12163 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12164 glw::GLuint column, glw::GLuint row);
12165
12166 template <int Size>
12167 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12168 const tcu::Vector<glw::GLdouble, Size>& right);
12169
12170 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12171
12172 static glw::GLdouble fract(glw::GLdouble val);
12173
12174 template <typename T>
12175 static T frexp(T val, glw::GLint& exp);
12176
12177 template <int Size>
12178 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12179 const tcu::Vector<glw::GLdouble, Size>& right);
12180
12181 template <int Size>
12182 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12183 const tcu::Vector<glw::GLdouble, Size>& right);
12184
12185 template <int Size>
12186 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12187
12188 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12189
12190 static glw::GLuint isinf_impl(glw::GLdouble val);
12191
12192 static glw::GLuint isnan_impl(glw::GLdouble val);
12193
12194 template <typename T>
12195 static T ldexp(T val, glw::GLint exp);
12196
12197 template <int Size>
12198 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12199 const tcu::Vector<glw::GLdouble, Size>& right);
12200
12201 template <int Size>
12202 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12203 const tcu::Vector<glw::GLdouble, Size>& right);
12204
12205 template <typename T>
12206 static T max(T left, T right);
12207
12208 template <typename T>
12209 static T min(T left, T right);
12210
12211 template <int Size>
12212 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12213 glw::GLuint row);
12214
12215 template <typename T>
12216 static T mix(T left, T right, T weight);
12217
12218 template <typename T>
12219 static T mod(T left, T right);
12220
12221 template <typename T>
12222 static T modf(T val, T& integer);
12223
12224 template <typename T>
12225 static T multiply(T left, T right);
12226
12227 template <int Size>
12228 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12229 const tcu::Vector<glw::GLdouble, Size>& right);
12230
12231 template <int Cols, int Rows>
12232 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12233 const tcu::Vector<glw::GLdouble, Cols>& right);
12234
12235 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12236
12237 template <typename T>
12238 static T round(T t);
12239
12240 template <typename T>
12241 static T roundEven(T t);
12242
12243 template <typename T>
12244 static T sign(T t);
12245
12246 template <typename T>
12247 static T smoothStep(T e0, T e1, T val);
12248
12249 template <typename T>
12250 static T step(T edge, T val);
12251
12252 template <typename T, int Rows, int Cols>
12253 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12254
12255 template <typename T>
12256 static T trunc(T t);
12257
12258 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12259
12260 template <typename T>
clamp(T x, T minVal, T maxVal)12261 static T clamp(T x, T minVal, T maxVal)
12262 {
12263 return min(max(x, minVal), maxVal);
12264 }
12265
12266 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)12267 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12268 {
12269 tcu::Matrix<glw::GLdouble, Size, Size> result;
12270
12271 for (glw::GLuint c = 0; c < Size; ++c)
12272 {
12273 for (glw::GLuint r = 0; r < Size; ++r)
12274 {
12275 const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12276
12277 result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12278 }
12279 }
12280
12281 return result;
12282 }
12283
12284 template <int Size>
convertBvecToUvec(const tcu::Vector<bool, Size>& src)12285 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12286 {
12287 tcu::Vector<glw::GLuint, Size> result;
12288
12289 for (glw::GLint i = 0; i < Size; ++i)
12290 {
12291 if (GL_FALSE != src[i])
12292 {
12293 result[i] = 1;
12294 }
12295 else
12296 {
12297 result[i] = 0;
12298 }
12299 }
12300
12301 return result;
12302 }
12303
12304 template <typename T>
det2(T _00, T _10, T _01, T _11)12305 static T det2(T _00, T _10, T _01, T _11)
12306 {
12307 return _00 * _11 - _01 * _10;
12308 }
12309
12310 template <typename T>
det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)12311 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12312 {
12313 return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12314 }
12315
12316 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)12317 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,
12318 T _33)
12319 {
12320 return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12321 _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12322 _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12323 _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12324 }
12325
12326 template <typename T>
determinant(T val)12327 static T determinant(T val)
12328 {
12329 return val;
12330 }
12331
12332 template <typename T>
determinant(const tcu::Matrix<T, 2, 2>& mat)12333 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12334 {
12335 return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12336 }
12337
12338 template <typename T>
determinant(const tcu::Matrix<T, 3, 3>& mat)12339 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12340 {
12341 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));
12342 }
12343
12344 template <typename T>
determinant(const tcu::Matrix<T, 4, 4>& mat)12345 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12346 {
12347 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),
12348 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12349 }
12350
12351 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column, glw::GLuint row)12352 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12353 glw::GLuint column, glw::GLuint row)
12354 {
12355 // GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12356 #if (DE_COMPILER == DE_COMPILER_GCC)
12357 # pragma GCC diagnostic push
12358 # pragma GCC diagnostic ignored "-Warray-bounds"
12359 #endif
12360
12361 const glw::GLint eCol = static_cast<glw::GLint>(column);
12362 const glw::GLint eRow = static_cast<glw::GLint>(row);
12363
12364 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12365
12366 for (glw::GLint c = 0; c < Size; ++c)
12367 {
12368 /* Skip eliminated column */
12369 if (eCol == c)
12370 {
12371 continue;
12372 }
12373
12374 for (glw::GLint r = 0; r < Size; ++r)
12375 {
12376 /* Skip eliminated row */
12377 if (eRow == r)
12378 {
12379 continue;
12380 }
12381
12382 const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12383 const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12384
12385 result(r + r_offset, c + c_offset) = matrix(r, c);
12386 }
12387 }
12388
12389 return result;
12390
12391 #if (DE_COMPILER == DE_COMPILER_GCC)
12392 # pragma GCC diagnostic pop
12393 #endif
12394 }
12395
12396 template <int Size>
equal(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12397 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12398 const tcu::Vector<glw::GLdouble, Size>& right)
12399 {
12400 return convertBvecToUvec(tcu::equal(left, right));
12401 }
12402
fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)12403 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12404 {
12405 return a * b + c;
12406 }
12407
fract(glw::GLdouble val)12408 static glw::GLdouble fract(glw::GLdouble val)
12409 {
12410 return val - floor(val);
12411 }
12412
12413 template <typename T>
frexp(T val, glw::GLint& exp)12414 static T frexp(T val, glw::GLint& exp)
12415 {
12416 return ::frexp(val, &exp);
12417 }
12418
12419 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12420 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12421 const tcu::Vector<glw::GLdouble, Size>& right)
12422 {
12423 return convertBvecToUvec(tcu::greaterThan(left, right));
12424 }
12425
12426 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12427 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12428 const tcu::Vector<glw::GLdouble, Size>& right)
12429 {
12430 return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12431 }
12432
12433 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)12434 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12435 {
12436 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix);
12437 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12438 const glw::GLdouble det = determinant(matrix);
12439 const glw::GLdouble inv_det = 1.0 / det;
12440
12441 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12442
12443 return result;
12444 }
12445
inverseSqrt(glw::GLdouble val)12446 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12447 {
12448 const glw::GLdouble root = sqrt(val);
12449
12450 return (1.0 / root);
12451 }
12452
isinf_impl(glw::GLdouble val)12453 static glw::GLuint isinf_impl(glw::GLdouble val)
12454 {
12455 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12456
12457 return ((infinity == val) || (-infinity == val));
12458 }
12459
isnan_impl(glw::GLdouble val)12460 static glw::GLuint isnan_impl(glw::GLdouble val)
12461 {
12462 return val != val;
12463 }
12464
12465 template <typename T>
ldexp(T val, glw::GLint exp)12466 static T ldexp(T val, glw::GLint exp)
12467 {
12468 return ::ldexp(val, exp);
12469 }
12470
12471 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12472 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12473 const tcu::Vector<glw::GLdouble, Size>& right)
12474 {
12475 return convertBvecToUvec(tcu::lessThan(left, right));
12476 }
12477
12478 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12479 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12480 const tcu::Vector<glw::GLdouble, Size>& right)
12481 {
12482 return convertBvecToUvec(tcu::lessThanEqual(left, right));
12483 }
12484
12485 template <typename T>
max(T left, T right)12486 static T max(T left, T right)
12487 {
12488 return (left >= right) ? left : right;
12489 }
12490
12491 template <typename T>
min(T left, T right)12492 static T min(T left, T right)
12493 {
12494 return (left <= right) ? left : right;
12495 }
12496
12497 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column, glw::GLuint row)12498 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12499 glw::GLuint row)
12500 {
12501 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12502
12503 return determinant(eliminated);
12504 }
12505
12506 template <>
minor_impl(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)12507 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12508 {
12509 const glw::GLuint r = (0 == row) ? 1 : 0;
12510 const glw::GLuint c = (0 == column) ? 1 : 0;
12511
12512 return matrix(r, c);
12513 }
12514
12515 template <typename T>
mix(T left, T right, T weight)12516 static T mix(T left, T right, T weight)
12517 {
12518 return left * (1 - weight) + right * (weight);
12519 }
12520
12521 template <typename T>
mod(T left, T right)12522 static T mod(T left, T right)
12523 {
12524 const T div_res = left / right;
12525 const T floored = floor(div_res);
12526
12527 return left - right * floored;
12528 }
12529
12530 template <typename T>
modf(T val, T& integer)12531 static T modf(T val, T& integer)
12532 {
12533 return ::modf(val, &integer);
12534 }
12535
12536 template <typename T>
multiply(T left, T right)12537 static T multiply(T left, T right)
12538 {
12539 T result = left * right;
12540
12541 return result;
12542 }
12543
12544 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble, Size>& left, const tcu::Vector<glw::GLdouble, Size>& right)12545 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12546 const tcu::Vector<glw::GLdouble, Size>& right)
12547 {
12548 return convertBvecToUvec(tcu::notEqual(left, right));
12549 }
12550
12551 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left, const tcu::Vector<glw::GLdouble, Cols>& right)12552 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12553 const tcu::Vector<glw::GLdouble, Cols>& right)
12554 {
12555 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12556 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12557 tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12558
12559 for (glw::GLuint i = 0; i < Rows; ++i)
12560 {
12561 left_mat(i, 0) = left[i];
12562 }
12563
12564 for (glw::GLuint i = 0; i < Cols; ++i)
12565 {
12566 right_mat(0, i) = right[i];
12567 }
12568
12569 result = left_mat * right_mat;
12570
12571 return result;
12572 }
12573
packDouble2x32(const tcu::UVec2& in)12574 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12575 {
12576 const glw::GLuint buffer[2] = { in[0], in[1] };
12577 glw::GLdouble result;
12578 memcpy(&result, buffer, sizeof(result));
12579 return result;
12580 }
12581
12582 template <typename T>
round(T t)12583 static T round(T t)
12584 {
12585 T frac = fract(t);
12586 T res = t - frac;
12587
12588 if (((T)0.5) < frac)
12589 {
12590 res += ((T)1.0);
12591 }
12592
12593 return res;
12594 }
12595
12596 template <typename T>
roundEven(T t)12597 static T roundEven(T t)
12598 {
12599 T frac = fract(t);
12600 T res = t - frac;
12601
12602 if (((T)0.5) < frac)
12603 {
12604 res += ((T)1.0);
12605 }
12606 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12607 {
12608 res += ((T)1.0);
12609 }
12610
12611 return res;
12612 }
12613
12614 template <typename T>
sign(T t)12615 static T sign(T t)
12616 {
12617 if (0 > t)
12618 {
12619 return -1;
12620 }
12621 else if (0 == t)
12622 {
12623 return 0;
12624 }
12625 else
12626 {
12627 return 1;
12628 }
12629 }
12630
12631 template <typename T>
smoothStep(T e0, T e1, T val)12632 static T smoothStep(T e0, T e1, T val)
12633 {
12634 if (e0 >= val)
12635 {
12636 return 0;
12637 }
12638
12639 if (e1 <= val)
12640 {
12641 return 1;
12642 }
12643
12644 T temp = (val - e0) / (e1 - e0);
12645
12646 T result = temp * temp * (3 - 2 * temp);
12647
12648 return result;
12649 }
12650
12651 template <typename T>
step(T edge, T val)12652 static T step(T edge, T val)
12653 {
12654 if (edge > val)
12655 {
12656 return 0;
12657 }
12658 else
12659 {
12660 return 1;
12661 }
12662 }
12663
12664 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T, Rows, Cols>& matrix)12665 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12666 {
12667 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12668
12669 return result;
12670 }
12671
12672 template <typename T>
trunc(T t)12673 static T trunc(T t)
12674 {
12675 const T abs_value = de::abs(t);
12676 const T result_value = floor(abs_value);
12677
12678 const T result = sign(t) * result_value;
12679
12680 return result;
12681 }
12682
unpackDouble2x32(const glw::GLdouble& val)12683 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12684 {
12685 glw::GLuint* ptr = (glw::GLuint*)&val;
12686 tcu::UVec2 result(ptr[0], ptr[1]);
12687
12688 return result;
12689 }
12690 } /* Math */
12691
12692 /** Enumeration of tested functions
12693 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12694 * For example "max" can be called for (dvec3, double).
12695 **/
12696 enum FunctionEnum
12697 {
12698 FUNCTION_ABS = 0,
12699 FUNCTION_CEIL,
12700 FUNCTION_CLAMP,
12701 FUNCTION_CLAMP_AGAINST_SCALAR,
12702 FUNCTION_CROSS,
12703 FUNCTION_DETERMINANT,
12704 FUNCTION_DISTANCE,
12705 FUNCTION_DOT,
12706 FUNCTION_EQUAL,
12707 FUNCTION_FACEFORWARD,
12708 FUNCTION_FLOOR,
12709 FUNCTION_FMA,
12710 FUNCTION_FRACT,
12711 FUNCTION_FREXP,
12712 FUNCTION_GREATERTHAN,
12713 FUNCTION_GREATERTHANEQUAL,
12714 FUNCTION_INVERSE,
12715 FUNCTION_INVERSESQRT,
12716 FUNCTION_LDEXP,
12717 FUNCTION_LESSTHAN,
12718 FUNCTION_LESSTHANEQUAL,
12719 FUNCTION_LENGTH,
12720 FUNCTION_MATRIXCOMPMULT,
12721 FUNCTION_MAX,
12722 FUNCTION_MAX_AGAINST_SCALAR,
12723 FUNCTION_MIN,
12724 FUNCTION_MIN_AGAINST_SCALAR,
12725 FUNCTION_MIX,
12726 FUNCTION_MOD,
12727 FUNCTION_MOD_AGAINST_SCALAR,
12728 FUNCTION_MODF,
12729 FUNCTION_NORMALIZE,
12730 FUNCTION_NOTEQUAL,
12731 FUNCTION_OUTERPRODUCT,
12732 FUNCTION_PACKDOUBLE2X32,
12733 FUNCTION_REFLECT,
12734 FUNCTION_REFRACT,
12735 FUNCTION_ROUND,
12736 FUNCTION_ROUNDEVEN,
12737 FUNCTION_SIGN,
12738 FUNCTION_SMOOTHSTEP,
12739 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12740 FUNCTION_SQRT,
12741 FUNCTION_STEP,
12742 FUNCTION_STEP_AGAINST_SCALAR,
12743 FUNCTION_TRANSPOSE,
12744 FUNCTION_TRUNC,
12745 FUNCTION_UNPACKDOUBLE2X32,
12746 FUNCTION_ISNAN,
12747 FUNCTION_ISINF,
12748 };
12749
12750 struct TypeDefinition
12751 {
12752 std::string name;
12753 glw::GLuint n_columns;
12754 glw::GLuint n_rows;
12755 };
12756
12757 /** Implementation of BuiltinFunctionTest test, description follows:
12758 *
12759 * Verify double-precision support in common functions works correctly.
12760 * All double-precision types that apply for particular cases should
12761 * be tested for the following functions:
12762 *
12763 * - abs();
12764 * - ceil();
12765 * - clamp();
12766 * - cross();
12767 * - determinant();
12768 * - distance();
12769 * - dot();
12770 * - equal();
12771 * - faceforward();
12772 * - floor();
12773 * - fma();
12774 * - fract();
12775 * - frexp();
12776 * - greaterThan();
12777 * - greaterThanEqual();
12778 * - inverse();
12779 * - inversesqrt();
12780 * - ldexp();
12781 * - lessThan();
12782 * - lessThanEqual();
12783 * - length();
12784 * - matrixCompMult();
12785 * - max();
12786 * - min();
12787 * - mix();
12788 * - mod();
12789 * - modf();
12790 * - normalize();
12791 * - notEqual();
12792 * - outerProduct();
12793 * - packDouble2x32();
12794 * - reflect();
12795 * - refract();
12796 * - round();
12797 * - roundEven();
12798 * - sign();
12799 * - smoothstep();
12800 * - sqrt();
12801 * - step();
12802 * - transpose();
12803 * - trunc();
12804 * - unpackDouble2x32();
12805 * - isnan();
12806 * - isinf();
12807 *
12808 * The test should work by creating a program object (for each case
12809 * considered), to which a vertex shader should be attached. The
12810 * shader should define input variables that should be used as
12811 * arguments for the function in question. The result of the
12812 * operation should then be XFBed back to the test, where the
12813 * value should be verified.
12814 *
12815 * Reference function implementation from pre-DEQP CTS framework
12816 * should be ported to C for verification purposes where available.
12817 *
12818 * The test should use 1024 different scalar/vector/matrix argument
12819 * combinations. It should pass if all functions are determined
12820 * to work correctly for all argument combinations used.
12821 **/
12822 class BuiltinFunctionTest : public deqp::TestCase
12823 {
12824 public:
12825 /* Public methods */
12826 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12827 TypeDefinition typeDefinition);
12828
12829 virtual void deinit();
12830 virtual tcu::TestNode::IterateResult iterate();
12831
12832 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12833 *
12834 **/
12835 class functionObject
12836 {
12837 public:
12838 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12839 Utils::_variable_type result_type);
12840
~functionObject()12841 virtual ~functionObject()
12842 {
12843 }
12844
12845 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12846
12847 virtual glw::GLuint getArgumentCount() const = 0;
12848 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12849 glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12850 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12851 glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12852 glw::GLuint getArgumentStride() const;
12853 glw::GLuint getArgumentStride(glw::GLuint argument) const;
12854 FunctionEnum getFunctionEnum() const;
12855 const glw::GLchar* getName() const;
12856 glw::GLuint getResultComponents(glw::GLuint result) const;
12857 virtual glw::GLuint getResultCount() const;
12858 glw::GLuint getResultOffset(glw::GLuint result) const;
12859 virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12860 glw::GLuint getResultStride(glw::GLuint result) const;
12861 glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12862 glw::GLuint getResultStride() const;
12863
12864 protected:
12865 const FunctionEnum m_function_enum;
12866 const glw::GLchar* m_function_name;
12867 const glw::GLvoid* m_p_function;
12868 const Utils::_variable_type m_res_type;
12869 };
12870
12871 private:
12872 /* Private types */
12873 /** General type enumeration
12874 *
12875 **/
12876 enum generalType
12877 {
12878 SCALAR = 0,
12879 VECTOR,
12880 MATRIX,
12881 };
12882
12883 /** Details of variable type
12884 *
12885 **/
12886 struct typeDetails
12887 {
12888 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12889
12890 generalType m_general_type;
12891 glw::GLuint m_n_columns;
12892 glw::GLuint m_n_rows;
12893 glw::GLenum m_type;
12894 std::string m_type_name;
12895 };
12896
12897 /* Typedefs for gl.uniform* function pointers */
12898 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12899 const glw::GLdouble*);
12900 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12901 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12902 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12903
12904 /* Private methods */
12905 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12906
12907 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12908
12909 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
12910 const functionObject& function_object) const;
12911
12912 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
12913 const functionObject& function_object) const;
12914
12915 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
12916 const functionObject& function_object) const;
12917
12918 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
12919 const functionObject& function_object) const;
12920
12921 const glw::GLchar* getUniformName(glw::GLuint argument) const;
12922 const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12923
12924 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12925
12926 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12927
12928 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12929
12930 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12931 glw::GLubyte* buffer);
12932
12933 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12934
12935 void prepareTestData(const functionObject& function_object);
12936 void prepareVertexShaderCode(const functionObject& function_object);
12937
12938 bool test(FunctionEnum function, const typeDetails& type);
12939
12940 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12941
12942 void testInit();
12943
12944 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12945 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12946 const glw::GLvoid* result_src);
12947
12948 bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12949
12950 /* Private constants */
12951 static const glw::GLdouble m_epsilon;
12952 static const glw::GLuint m_n_veritces;
12953
12954 /* Private fields */
12955 glw::GLuint m_transform_feedback_buffer_id;
12956 glw::GLuint m_vertex_array_object_id;
12957
12958 std::vector<glw::GLubyte> m_expected_results_data;
12959 FunctionEnum m_function;
12960 TypeDefinition m_typeDefinition;
12961 std::vector<glw::GLubyte> m_argument_data;
12962 std::string m_vertex_shader_code;
12963 };
12964
12965 /* Constants used by BuiltinFunctionTest */
12966 /** Khronos Bug #14010
12967 * Using an epsilon value for comparing floating points is error prone.
12968 * Rather than writing a new floating point comparison function, I am
12969 * increasing the epsilon value to allow greater orders of magnitude
12970 * of floating point values.
12971 **/
12972 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002;
12973 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
12974
12975 /** Implementations of function objects required by "BuiltinFunctionTest"
12976 *
12977 **/
12978 namespace FunctionObject
12979 {
12980 /** Maps variable type with enumeration Utils::_variable_type
12981 *
12982 * @tparam T type
12983 **/
12984 template <typename T>
12985 class typeInfo
12986 {
12987 public:
12988 static const Utils::_variable_type variable_type =
12989 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12990 };
12991
12992 /** Place data from <in> into <buffer>
12993 *
12994 * @param buffer Buffer
12995 * @param in Input data
12996 **/
12997 template <typename T>
12998 class pack
12999 {
13000 public:
set(glw::GLvoid* buffer, const T& in)13001 static void set(glw::GLvoid* buffer, const T& in)
13002 {
13003 *(T*)buffer = in;
13004 }
13005 };
13006
13007 /** Place tcu::Matrix data from <in> into <buffer>
13008 *
13009 * @param buffer Buffer
13010 * @param in Input data
13011 **/
13012 template <int Cols, int Rows>
13013 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13014 {
13015 public:
set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)13016 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13017 {
13018 glw::GLdouble* data = (glw::GLdouble*)buffer;
13019
13020 for (glw::GLint column = 0; column < Cols; ++column)
13021 {
13022 for (glw::GLint row = 0; row < Rows; ++row)
13023 {
13024 glw::GLint index = column * Rows + row;
13025
13026 data[index] = in(row, column);
13027 }
13028 }
13029 }
13030 };
13031
13032 /** Get data of <out> from <buffer>
13033 *
13034 * @param buffer Buffer
13035 * @param out Output data
13036 **/
13037 template <typename T>
13038 class unpack
13039 {
13040 public:
get(const glw::GLvoid* buffer, T& out)13041 static void get(const glw::GLvoid* buffer, T& out)
13042 {
13043 out = *(T*)buffer;
13044 }
13045 };
13046
13047 /** Get tcu::Matrix data from <buffer>
13048 *
13049 * @param buffer Buffer
13050 * @param out Output data
13051 **/
13052 template <int Cols, int Rows>
13053 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13054 {
13055 public:
get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)13056 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13057 {
13058 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13059
13060 for (glw::GLint column = 0; column < Cols; ++column)
13061 {
13062 for (glw::GLint row = 0; row < Rows; ++row)
13063 {
13064 glw::GLint index = column * Rows + row;
13065
13066 out(row, column) = data[index];
13067 }
13068 }
13069 }
13070 };
13071
13072 /** Base of unary function classes
13073 *
13074 **/
13075 class unaryBase : public BuiltinFunctionTest::functionObject
13076 {
13077 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)13078 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13079 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13080 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13081 {
13082 }
13083
getArgumentCount() const13084 virtual glw::GLuint getArgumentCount() const
13085 {
13086 return 1;
13087 }
13088
getArgumentType(glw::GLuint ) const13089 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13090 {
13091 return m_arg_type;
13092 }
13093
13094 protected:
13095 const Utils::_variable_type m_arg_type;
13096 };
13097
13098 /** Unary function class. It treats input argument as one variable.
13099 *
13100 * @tparam ResT Type of result
13101 * @tparam ArgT Type of argument
13102 **/
13103 template <typename ResT, typename ArgT>
13104 class unary : public unaryBase
13105 {
13106 public:
13107 typedef ResT (*functionPointer)(const ArgT&);
13108
unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13109 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13110 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13111 typeInfo<ArgT>::variable_type)
13112 {
13113 }
13114
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13115 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13116 {
13117 ResT result;
13118 ArgT arg;
13119
13120 unpack<ArgT>::get(argument_src, arg);
13121
13122 functionPointer p_function = (functionPointer)m_p_function;
13123
13124 result = p_function(arg);
13125
13126 pack<ResT>::set(result_dst, result);
13127 }
13128 };
13129
13130 /** Unary function class. It treats input argument as separate components.
13131 *
13132 * @tparam ResT Type of result
13133 **/
13134 template <typename ResT>
13135 class unaryByComponent : public unaryBase
13136 {
13137 public:
13138 typedef ResT (*functionPointer)(glw::GLdouble);
13139
unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer, const Utils::_variable_type res_type, const Utils::_variable_type arg_type)13140 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13141 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13142 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13143 {
13144 }
13145
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13146 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13147 {
13148 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13149 ResT* p_result = (ResT*)result_dst;
13150 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src;
13151
13152 functionPointer p_function = (functionPointer)m_p_function;
13153
13154 for (glw::GLuint component = 0; component < n_components; ++component)
13155 {
13156 p_result[component] = p_function(p_arg[component]);
13157 }
13158 }
13159 };
13160
13161 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13162 *
13163 * @tparam ResT Type of result
13164 * @tparam ArgT Type of argument
13165 * @tparam OutT Type of output parameter
13166 **/
13167 template <typename ResT, typename ArgT, typename OutT>
13168 class unaryWithOutputByComponent : public unaryBase
13169 {
13170 public:
13171 typedef ResT (*functionPointer)(ArgT, OutT&);
13172
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)13173 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13174 functionPointer function_pointer, const Utils::_variable_type res_type,
13175 const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13176 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13177 , m_out_type(out_type)
13178 {
13179 }
13180
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13181 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13182 {
13183 ResT* p_result = (ResT*)result_dst;
13184 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13185 ArgT* p_arg = (ArgT*)argument_src;
13186
13187 const glw::GLuint n_components_0 = getArgumentComponents(0);
13188 const glw::GLuint n_components_1 = getResultComponents(1);
13189 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13190
13191 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13192 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13193
13194 functionPointer p_function = (functionPointer)m_p_function;
13195
13196 for (glw::GLuint component = 0; component < n_components; ++component)
13197 {
13198 const ArgT first_arg = p_arg[component * component_step_0];
13199 OutT& second_arg = p_out[component * component_step_1];
13200
13201 p_result[component] = p_function(first_arg, second_arg);
13202 }
13203 }
13204
getResultCount() const13205 glw::GLuint getResultCount() const
13206 {
13207 return 2;
13208 }
13209
getResultType(glw::GLuint result) const13210 Utils::_variable_type getResultType(glw::GLuint result) const
13211 {
13212 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13213
13214 switch (result)
13215 {
13216 case 0:
13217 type = m_res_type;
13218 break;
13219 case 1:
13220 type = m_out_type;
13221 break;
13222 default:
13223 TCU_FAIL("Not implemented");
13224 break;
13225 }
13226
13227 return type;
13228 }
13229
13230 protected:
13231 const Utils::_variable_type m_out_type;
13232 };
13233
13234 /** Base of binary function classes.
13235 *
13236 **/
13237 class binaryBase : public BuiltinFunctionTest::functionObject
13238 {
13239 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)13240 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13241 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13242 const Utils::_variable_type arg_2_type)
13243 : functionObject(function_enum, function_name, function_pointer, res_type)
13244 , m_arg_1_type(arg_1_type)
13245 , m_arg_2_type(arg_2_type)
13246 {
13247 }
13248
getArgumentCount() const13249 virtual glw::GLuint getArgumentCount() const
13250 {
13251 return 2;
13252 }
13253
getArgumentType(glw::GLuint argument) const13254 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13255 {
13256 switch (argument)
13257 {
13258 case 0:
13259 return m_arg_1_type;
13260 case 1:
13261 return m_arg_2_type;
13262 default:
13263 return Utils::VARIABLE_TYPE_UNKNOWN;
13264 }
13265 }
13266
13267 protected:
13268 const Utils::_variable_type m_arg_1_type;
13269 const Utils::_variable_type m_arg_2_type;
13270 };
13271
13272 /** Binary function class. It treats input arguments as two variables.
13273 *
13274 * @param ResT Type of result
13275 * @param Arg1T Type of first argument
13276 * @param Arg2T Type of second argument
13277 **/
13278 template <typename ResT, typename Arg1T, typename Arg2T>
13279 class binary : public binaryBase
13280 {
13281 public:
13282 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13283
binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13284 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13285 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13286 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13287 {
13288 }
13289
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13290 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13291 {
13292 const glw::GLuint argument_1_stride = getArgumentStride(0);
13293
13294 functionPointer p_function = (functionPointer)m_p_function;
13295
13296 Arg1T arg_1;
13297 Arg2T arg_2;
13298 ResT result;
13299
13300 unpack<Arg1T>::get(argument_src, arg_1);
13301 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13302
13303 result = p_function(arg_1, arg_2);
13304
13305 pack<ResT>::set(result_dst, result);
13306 }
13307 };
13308
13309 /** Binary function class. It treats input arguments as separate components.
13310 *
13311 * @param ResT Type of result
13312 * @param Arg1T Type of first argument
13313 * @param Arg2T Type of second argument
13314 **/
13315 template <typename ResT, typename Arg1T, typename Arg2T>
13316 class binaryByComponent : public binaryBase
13317 {
13318 public:
13319 typedef ResT (*functionPointer)(Arg1T, Arg2T);
13320
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)13321 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13322 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13323 const Utils::_variable_type arg_2_type)
13324 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13325 {
13326 }
13327
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13328 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13329 {
13330 ResT* p_result = (ResT*)result_dst;
13331 Arg1T* p_arg_1 = (Arg1T*)argument_src;
13332 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13333
13334 const glw::GLuint n_components_0 = getArgumentComponents(0);
13335 const glw::GLuint n_components_1 = getArgumentComponents(1);
13336 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13337
13338 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13339 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13340
13341 functionPointer p_function = (functionPointer)m_p_function;
13342
13343 for (glw::GLuint component = 0; component < n_components; ++component)
13344 {
13345 const Arg1T first_arg = p_arg_1[component * component_step_0];
13346 const Arg2T second_arg = p_arg_2[component * component_step_1];
13347
13348 p_result[component] = p_function(first_arg, second_arg);
13349 }
13350 }
13351 };
13352
13353 /** Base of tenary function classes.
13354 *
13355 **/
13356 class tenaryBase : public BuiltinFunctionTest::functionObject
13357 {
13358 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)13359 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13360 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13361 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13362 : functionObject(function_enum, function_name, function_pointer, res_type)
13363 , m_arg_1_type(arg_1_type)
13364 , m_arg_2_type(arg_2_type)
13365 , m_arg_3_type(arg_3_type)
13366 {
13367 }
13368
getArgumentCount() const13369 virtual glw::GLuint getArgumentCount() const
13370 {
13371 return 3;
13372 }
13373
getArgumentType(glw::GLuint argument) const13374 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13375 {
13376 switch (argument)
13377 {
13378 case 0:
13379 return m_arg_1_type;
13380 case 1:
13381 return m_arg_2_type;
13382 case 2:
13383 return m_arg_3_type;
13384 default:
13385 return Utils::VARIABLE_TYPE_UNKNOWN;
13386 }
13387 }
13388
13389 protected:
13390 const Utils::_variable_type m_arg_1_type;
13391 const Utils::_variable_type m_arg_2_type;
13392 const Utils::_variable_type m_arg_3_type;
13393 };
13394
13395 /** Tenary function class. It treats input arguments as three variables.
13396 *
13397 * @param ResT Type of result
13398 * @param Arg1T Type of first argument
13399 * @param Arg2T Type of second argument
13400 * @param Arg3T Type of third argument
13401 **/
13402 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13403 class tenary : public tenaryBase
13404 {
13405 public:
13406 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13407 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13408 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13409 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13410
tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)13411 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13412 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13413 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13414 {
13415 }
13416
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13417 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13418 {
13419 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13420 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13421
13422 functionPointer p_function = (functionPointer)m_p_function;
13423
13424 arg1T arg_1;
13425 arg2T arg_2;
13426 arg3T arg_3;
13427 ResT result;
13428
13429 unpack<arg1T>::get(argument_src, arg_1);
13430 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13431 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13432
13433 result = p_function(arg_1, arg_2, arg_3);
13434
13435 pack<ResT>::set(result_dst, result);
13436 }
13437 };
13438
13439 /** Tenary function class. It treats input arguments as separate components.
13440 *
13441
13442 **/
13443 class tenaryByComponent : public tenaryBase
13444 {
13445 public:
13446 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13447
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)13448 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13449 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13450 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13451 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13452 arg_3_type)
13453 {
13454 }
13455
call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const13456 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13457 {
13458 glw::GLdouble* p_result = (glw::GLdouble*)result_dst;
13459 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src;
13460
13461 const glw::GLuint n_components_0 = getArgumentComponents(0);
13462 const glw::GLuint n_components_1 = getArgumentComponents(1);
13463 const glw::GLuint n_components_2 = getArgumentComponents(2);
13464 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2);
13465
13466 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13467 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13468 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13469
13470 functionPointer p_function = (functionPointer)m_p_function;
13471
13472 for (glw::GLuint component = 0; component < n_components; ++component)
13473 {
13474 const glw::GLdouble first_arg = p_arg[component * component_step_0];
13475 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13476 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13477
13478 p_result[component] = p_function(first_arg, second_arg, third_arg);
13479 }
13480 }
13481 };
13482 } /* FunctionObject */
13483
13484 /** Constructor.
13485 *
13486 * @param context Rendering context.
13487 **/
BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function, TypeDefinition typeDefinition)13488 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13489 TypeDefinition typeDefinition)
13490 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13491 , m_transform_feedback_buffer_id(0)
13492 , m_vertex_array_object_id(0)
13493 , m_function(function)
13494 , m_typeDefinition(typeDefinition)
13495 {
13496 /* Nothing to be done here */
13497 }
13498
13499 /** Deinitializes all GL objects that may have been created during test execution.
13500 *
13501 **/
deinit()13502 void BuiltinFunctionTest::deinit()
13503 {
13504 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13505
13506 /* Clean buffers */
13507 if (0 != m_transform_feedback_buffer_id)
13508 {
13509 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13510 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13511 m_transform_feedback_buffer_id = 0;
13512 }
13513
13514 /* Clean VAO */
13515 if (0 != m_vertex_array_object_id)
13516 {
13517 gl.bindVertexArray(0);
13518 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13519 m_vertex_array_object_id = 0;
13520 }
13521 }
13522
13523 /** Execute test
13524 *
13525 * @return tcu::TestNode::STOP
13526 **/
iterate()13527 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13528 {
13529 /* Check if extension is supported */
13530 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13531 {
13532 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13533 }
13534
13535 testInit();
13536
13537 /* Verify result */
13538 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13539 if (test(m_function, type))
13540 {
13541 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13542 }
13543 else
13544 {
13545 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13546 }
13547
13548 /* Done */
13549 return tcu::TestNode::STOP;
13550 }
13551
13552 /** Constructor
13553 *
13554 * @param function_enum Function enumeration
13555 * @param function_name Function name
13556 * @param function_pointer Pointer to routine that wiil be executed
13557 * @param result_type Type of result
13558 **/
functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer, Utils::_variable_type result_type)13559 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13560 glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13561 : m_function_enum(function_enum)
13562 , m_function_name(function_name)
13563 , m_p_function(function_pointer)
13564 , m_res_type(result_type)
13565 {
13566 /* Nothing to be done here */
13567 }
13568
13569 /** Get number of components for <argument>
13570 *
13571 * @param argument Argument ordinal, starts with 0
13572 *
13573 * @return Number of components
13574 **/
getArgumentComponents(glw::GLuint argument) const13575 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13576 {
13577 const Utils::_variable_type type = getArgumentType(argument);
13578 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13579
13580 return n_components;
13581 }
13582
13583 /** Get size in bytes of single component of <argument>
13584 *
13585 * @param argument Argument ordinal, starts with 0
13586 *
13587 * @return Size of component
13588 **/
getArgumentComponentSize(glw::GLuint argument) const13589 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13590 {
13591 const Utils::_variable_type type = getArgumentType(argument);
13592 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13593 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13594
13595 return base_type_size;
13596 }
13597
13598 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13599 *
13600 * @param argument Argument ordinal, starts with 0
13601 *
13602 * @return Offset of arguemnt's data
13603 **/
getArgumentOffset(glw::GLuint argument) const13604 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13605 {
13606 glw::GLuint result = 0;
13607
13608 for (glw::GLuint i = 0; i < argument; ++i)
13609 {
13610 result += getArgumentStride(i);
13611 }
13612
13613 return result;
13614 }
13615
13616 /** Get stride in bytes of all arguments
13617 *
13618 * @return Stride of all arguments
13619 **/
getArgumentStride() const13620 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13621 {
13622 const glw::GLuint n_args = getArgumentCount();
13623 glw::GLuint result = 0;
13624
13625 for (glw::GLuint i = 0; i < n_args; ++i)
13626 {
13627 result += getArgumentStride(i);
13628 }
13629
13630 return result;
13631 }
13632
13633 /** Get stride in bytes of <argument>
13634 *
13635 * @param argument Argument ordinal, starts with 0
13636 *
13637 * @return Stride of argument
13638 **/
getArgumentStride(glw::GLuint argument) const13639 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13640 {
13641 const glw::GLuint component_size = getArgumentComponentSize(argument);
13642 const glw::GLuint n_components = getArgumentComponents(argument);
13643
13644 return n_components * component_size;
13645 }
13646
13647 /** Get function enumeration
13648 *
13649 * @return Function enumeration
13650 **/
getFunctionEnum() const13651 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13652 {
13653 return m_function_enum;
13654 }
13655
13656 /** Get function name
13657 *
13658 * @return Function name
13659 **/
getName() const13660 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13661 {
13662 return m_function_name;
13663 }
13664
13665 /** Get number of components for <result>
13666 *
13667 * @param result Result ordinal, starts with 0
13668 *
13669 * @return Number of components
13670 **/
getResultComponents(glw::GLuint result) const13671 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13672 {
13673 const Utils::_variable_type type = getResultType(result);
13674 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13675
13676 return n_components;
13677 }
13678
13679 /** Get number of results
13680 *
13681 * @return Number of results
13682 **/
getResultCount() const13683 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13684 {
13685 return 1;
13686 }
13687
13688 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13689 *
13690 * @param result Result ordinal, starts with 0
13691 *
13692 * @return Offset
13693 **/
getResultOffset(glw::GLuint result) const13694 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13695 {
13696 glw::GLuint offset = 0;
13697
13698 for (glw::GLuint i = 0; i < result; ++i)
13699 {
13700 offset += getResultStride(i);
13701 offset = deAlign32(offset, getBaseTypeSize(i));
13702 }
13703
13704 return offset;
13705 }
13706
13707 /** Get stride in bytes of <result>.
13708 *
13709 * @param result Result ordinal, starts with 0
13710 *
13711 * @return Stride
13712 **/
getResultStride(glw::GLuint result) const13713 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13714 {
13715 const Utils::_variable_type type = getResultType(result);
13716 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13717
13718 return n_components * getBaseTypeSize(result);
13719 }
13720
13721 /** Get size in bytes of <result> base component.
13722 *
13723 * @param result Result ordinal, starts with 0
13724 *
13725 * @return Alignment
13726 **/
getBaseTypeSize(glw::GLuint result) const13727 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13728 {
13729 const Utils::_variable_type type = getResultType(result);
13730 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13731 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13732
13733 return base_type_size;
13734 }
13735
13736 /** Get stride in bytes of all results.
13737 *
13738 * @return Stride
13739 **/
getResultStride() const13740 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13741 {
13742 const glw::GLuint n_results = getResultCount();
13743 glw::GLuint stride = 0;
13744 glw::GLuint maxAlignment = 0;
13745
13746 for (glw::GLuint i = 0; i < n_results; ++i)
13747 {
13748 const glw::GLuint alignment = getBaseTypeSize(i);
13749 stride += getResultStride(i);
13750 stride = deAlign32(stride, alignment);
13751 maxAlignment = deMaxu32(maxAlignment, alignment);
13752 }
13753
13754 // The stride of all results must also be aligned,
13755 // so results for next vertex are aligned.
13756 return deAlign32(stride, maxAlignment);
13757 }
13758
13759 /** Get type of <result>.
13760 *
13761 * @param result Result ordinal, starts with 0
13762 *
13763 * @return Type
13764 **/
getResultType(glw::GLuint ) const13765 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13766 {
13767 return m_res_type;
13768 }
13769
13770 /** Constructor
13771 *
13772 * @param n_columns Number of columns
13773 * @param n_rows Number of rows
13774 **/
typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)13775 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13776 : m_n_columns(n_columns), m_n_rows(n_rows)
13777 {
13778 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13779 m_type = Utils::getGLDataTypeOfVariableType(type);
13780 m_type_name = Utils::getVariableTypeString(type);
13781
13782 if (1 == m_n_columns)
13783 {
13784 if (1 == m_n_rows)
13785 {
13786 m_general_type = SCALAR;
13787 }
13788 else
13789 {
13790 m_general_type = VECTOR;
13791 }
13792 }
13793 else
13794 {
13795 m_general_type = MATRIX;
13796 }
13797 }
13798
13799 /** Compare two values
13800 *
13801 * @param type Type of values
13802 * @param left Pointer to left value
13803 * @param right Pointer to right value
13804 *
13805 * @return true if values are equal, false otherwise
13806 **/
compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)13807 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13808 {
13809 bool result = true;
13810
13811 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13812 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13813
13814 switch (base_type)
13815 {
13816 case Utils::VARIABLE_TYPE_DOUBLE:
13817
13818 {
13819 const glw::GLdouble* left_values = (glw::GLdouble*)left;
13820 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13821
13822 for (glw::GLuint component = 0; component < n_components; ++component)
13823 {
13824 const glw::GLdouble left_value = left_values[component];
13825 const glw::GLdouble right_value = right_values[component];
13826
13827 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13828 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13829 {
13830 result = false;
13831 break;
13832 }
13833 }
13834 }
13835
13836 break;
13837
13838 case Utils::VARIABLE_TYPE_INT:
13839
13840 {
13841 const glw::GLint* left_values = (glw::GLint*)left;
13842 const glw::GLint* right_values = (glw::GLint*)right;
13843
13844 for (glw::GLuint component = 0; component < n_components; ++component)
13845 {
13846 const glw::GLint left_value = left_values[component];
13847 const glw::GLint right_value = right_values[component];
13848
13849 if (left_value != right_value)
13850 {
13851 result = false;
13852 break;
13853 }
13854 }
13855 }
13856
13857 break;
13858
13859 case Utils::VARIABLE_TYPE_UINT:
13860
13861 {
13862 const glw::GLuint* left_values = (glw::GLuint*)left;
13863 const glw::GLuint* right_values = (glw::GLuint*)right;
13864
13865 for (glw::GLuint component = 0; component < n_components; ++component)
13866 {
13867 const glw::GLuint left_value = left_values[component];
13868 const glw::GLuint right_value = right_values[component];
13869
13870 if (left_value != right_value)
13871 {
13872 result = false;
13873 break;
13874 }
13875 }
13876 }
13877
13878 break;
13879
13880 default:
13881
13882 TCU_FAIL("Not implemented");
13883 }
13884
13885 return result;
13886 }
13887
13888 /** Create instance of function object for given function enumeration and type
13889 *
13890 * @param function Function enumeration
13891 * @param type Type details
13892 *
13893 * @return Create object
13894 **/
getFunctionObject(FunctionEnum function, const typeDetails& type)13895 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
13896 const typeDetails& type)
13897 {
13898 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13899 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13900 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13901 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13902 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13903 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13904 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13905 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13906 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13907
13908 const glw::GLuint n_columns = type.m_n_columns;
13909 const glw::GLuint n_rows = type.m_n_rows;
13910 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1);
13911 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13912 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows);
13913 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows);
13914
13915 switch (function)
13916 {
13917 case FUNCTION_ABS:
13918
13919 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13920 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13921
13922 case FUNCTION_CEIL:
13923
13924 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13925 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13926
13927 case FUNCTION_CLAMP:
13928
13929 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13930 variable_type /* arg1_type */, variable_type /* arg2_type */,
13931 variable_type /* arg3_type */);
13932
13933 case FUNCTION_CLAMP_AGAINST_SCALAR:
13934
13935 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13936 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13937 scalar_type /* arg3_type */);
13938
13939 case FUNCTION_CROSS:
13940
13941 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13942 function, "cross", tcu::cross);
13943
13944 case FUNCTION_DETERMINANT:
13945
13946 switch (variable_type)
13947 {
13948 case Utils::VARIABLE_TYPE_DMAT2:
13949 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13950 Math::determinant);
13951 case Utils::VARIABLE_TYPE_DMAT3:
13952 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13953 Math::determinant);
13954 case Utils::VARIABLE_TYPE_DMAT4:
13955 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13956 Math::determinant);
13957 default:
13958 TCU_FAIL("Not implemented");
13959 }
13960
13961 case FUNCTION_DISTANCE:
13962
13963 switch (variable_type)
13964 {
13965 case Utils::VARIABLE_TYPE_DVEC2:
13966 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13967 function, "distance", tcu::distance);
13968 case Utils::VARIABLE_TYPE_DVEC3:
13969 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13970 function, "distance", tcu::distance);
13971 case Utils::VARIABLE_TYPE_DVEC4:
13972 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13973 function, "distance", tcu::distance);
13974 default:
13975 break;
13976 }
13977
13978 break;
13979
13980 case FUNCTION_DOT:
13981
13982 switch (variable_type)
13983 {
13984 case Utils::VARIABLE_TYPE_DVEC2:
13985 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13986 function, "dot", tcu::dot);
13987 case Utils::VARIABLE_TYPE_DVEC3:
13988 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13989 function, "dot", tcu::dot);
13990 case Utils::VARIABLE_TYPE_DVEC4:
13991 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13992 function, "dot", tcu::dot);
13993 default:
13994 break;
13995 }
13996
13997 break;
13998
13999 case FUNCTION_EQUAL:
14000
14001 switch (variable_type)
14002 {
14003 case Utils::VARIABLE_TYPE_DVEC2:
14004 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14005 function, "equal", Math::equal);
14006 case Utils::VARIABLE_TYPE_DVEC3:
14007 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14008 function, "equal", Math::equal);
14009 case Utils::VARIABLE_TYPE_DVEC4:
14010 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14011 function, "equal", Math::equal);
14012 default:
14013 break;
14014 }
14015
14016 break;
14017
14018 case FUNCTION_FACEFORWARD:
14019
14020 switch (variable_type)
14021 {
14022 case Utils::VARIABLE_TYPE_DVEC2:
14023 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14024 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14025 function, "faceforward", tcu::faceForward);
14026 case Utils::VARIABLE_TYPE_DVEC3:
14027 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14028 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14029 function, "faceforward", tcu::faceForward);
14030 case Utils::VARIABLE_TYPE_DVEC4:
14031 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14032 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14033 function, "faceforward", tcu::faceForward);
14034 default:
14035 break;
14036 }
14037
14038 break;
14039
14040 case FUNCTION_FLOOR:
14041
14042 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14043 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14044
14045 case FUNCTION_FMA:
14046
14047 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */,
14048 variable_type /* arg1_type */, variable_type /* arg2_type */,
14049 variable_type /* arg3_type */);
14050
14051 case FUNCTION_FRACT:
14052
14053 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14054 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14055
14056 case FUNCTION_FREXP:
14057
14058 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14059 glw::GLint /* OutT */>(
14060 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14061 int_type /* out_type */);
14062
14063 case FUNCTION_GREATERTHAN:
14064
14065 switch (variable_type)
14066 {
14067 case Utils::VARIABLE_TYPE_DVEC2:
14068 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14069 function, "greaterThan", Math::greaterThan);
14070 case Utils::VARIABLE_TYPE_DVEC3:
14071 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14072 function, "greaterThan", Math::greaterThan);
14073 case Utils::VARIABLE_TYPE_DVEC4:
14074 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14075 function, "greaterThan", Math::greaterThan);
14076 default:
14077 break;
14078 }
14079
14080 break;
14081
14082 case FUNCTION_GREATERTHANEQUAL:
14083
14084 switch (variable_type)
14085 {
14086 case Utils::VARIABLE_TYPE_DVEC2:
14087 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14088 function, "greaterThanEqual", Math::greaterThanEqual);
14089 case Utils::VARIABLE_TYPE_DVEC3:
14090 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14091 function, "greaterThanEqual", Math::greaterThanEqual);
14092 case Utils::VARIABLE_TYPE_DVEC4:
14093 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14094 function, "greaterThanEqual", Math::greaterThanEqual);
14095 default:
14096 break;
14097 }
14098
14099 break;
14100
14101 case FUNCTION_INVERSE:
14102
14103 switch (variable_type)
14104 {
14105 case Utils::VARIABLE_TYPE_DMAT2:
14106 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14107 case Utils::VARIABLE_TYPE_DMAT3:
14108 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14109 case Utils::VARIABLE_TYPE_DMAT4:
14110 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14111 default:
14112 break;
14113 }
14114
14115 break;
14116
14117 case FUNCTION_INVERSESQRT:
14118
14119 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14120 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14121
14122 case FUNCTION_LDEXP:
14123
14124 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14125 glw::GLint /* Arg2T */>(
14126 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */,
14127 int_type /* arg2_type */);
14128
14129 case FUNCTION_LESSTHAN:
14130
14131 switch (variable_type)
14132 {
14133 case Utils::VARIABLE_TYPE_DVEC2:
14134 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14135 function, "lessThan", Math::lessThan);
14136 case Utils::VARIABLE_TYPE_DVEC3:
14137 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14138 function, "lessThan", Math::lessThan);
14139 case Utils::VARIABLE_TYPE_DVEC4:
14140 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14141 function, "lessThan", Math::lessThan);
14142 default:
14143 break;
14144 }
14145
14146 break;
14147
14148 case FUNCTION_LESSTHANEQUAL:
14149
14150 switch (variable_type)
14151 {
14152 case Utils::VARIABLE_TYPE_DVEC2:
14153 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14154 function, "lessThanEqual", Math::lessThanEqual);
14155 case Utils::VARIABLE_TYPE_DVEC3:
14156 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14157 function, "lessThanEqual", Math::lessThanEqual);
14158 case Utils::VARIABLE_TYPE_DVEC4:
14159 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14160 function, "lessThanEqual", Math::lessThanEqual);
14161 default:
14162 break;
14163 }
14164
14165 break;
14166
14167 case FUNCTION_LENGTH:
14168
14169 switch (variable_type)
14170 {
14171 case Utils::VARIABLE_TYPE_DVEC2:
14172 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14173 tcu::length);
14174 case Utils::VARIABLE_TYPE_DVEC3:
14175 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14176 tcu::length);
14177 case Utils::VARIABLE_TYPE_DVEC4:
14178 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14179 tcu::length);
14180 default:
14181 break;
14182 }
14183
14184 break;
14185
14186 case FUNCTION_MATRIXCOMPMULT:
14187
14188 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14189 glw::GLdouble /* Arg2T */>(
14190 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */,
14191 variable_type /* arg2_type */);
14192
14193 case FUNCTION_MAX:
14194
14195 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14196 glw::GLdouble /* Arg2T */>(
14197 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14198 variable_type /* arg2_type */);
14199
14200 case FUNCTION_MAX_AGAINST_SCALAR:
14201
14202 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14203 glw::GLdouble /* Arg2T */>(
14204 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14205 scalar_type /* arg2_type */);
14206
14207 case FUNCTION_MIN:
14208
14209 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14210 glw::GLdouble /* Arg2T */>(
14211 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14212 variable_type /* arg2_type */);
14213
14214 case FUNCTION_MIN_AGAINST_SCALAR:
14215
14216 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14217 glw::GLdouble /* Arg2T */>(
14218 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14219 scalar_type /* arg2_type */);
14220
14221 case FUNCTION_MIX:
14222
14223 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */,
14224 variable_type /* arg1_type */, variable_type /* arg2_type */,
14225 variable_type /* arg3_type */);
14226
14227 case FUNCTION_MOD:
14228
14229 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14230 glw::GLdouble /* Arg2T */>(
14231 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14232 variable_type /* arg2_type */);
14233
14234 case FUNCTION_MOD_AGAINST_SCALAR:
14235
14236 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14237 glw::GLdouble /* Arg2T */>(
14238 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14239 scalar_type /* arg2_type */);
14240
14241 case FUNCTION_MODF:
14242
14243 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14244 glw::GLdouble /* OutT */>(
14245 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14246 variable_type /* out_type */);
14247
14248 case FUNCTION_NORMALIZE:
14249
14250 switch (variable_type)
14251 {
14252 case Utils::VARIABLE_TYPE_DVEC2:
14253 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14254 tcu::normalize);
14255 case Utils::VARIABLE_TYPE_DVEC3:
14256 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14257 tcu::normalize);
14258 case Utils::VARIABLE_TYPE_DVEC4:
14259 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14260 tcu::normalize);
14261 default:
14262 break;
14263 }
14264
14265 break;
14266
14267 case FUNCTION_NOTEQUAL:
14268
14269 switch (variable_type)
14270 {
14271 case Utils::VARIABLE_TYPE_DVEC2:
14272 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14273 function, "notEqual", Math::notEqual);
14274 case Utils::VARIABLE_TYPE_DVEC3:
14275 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14276 function, "notEqual", Math::notEqual);
14277 case Utils::VARIABLE_TYPE_DVEC4:
14278 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14279 function, "notEqual", Math::notEqual);
14280 default:
14281 break;
14282 }
14283
14284 break;
14285
14286 case FUNCTION_OUTERPRODUCT:
14287
14288 switch (variable_type)
14289 {
14290 case Utils::VARIABLE_TYPE_DMAT2:
14291 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 function, "outerProduct", Math::outerProduct);
14293 case Utils::VARIABLE_TYPE_DMAT2X3:
14294 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14295 function, "outerProduct", Math::outerProduct);
14296 case Utils::VARIABLE_TYPE_DMAT2X4:
14297 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14298 function, "outerProduct", Math::outerProduct);
14299 case Utils::VARIABLE_TYPE_DMAT3:
14300 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 function, "outerProduct", Math::outerProduct);
14302 case Utils::VARIABLE_TYPE_DMAT3X2:
14303 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14304 function, "outerProduct", Math::outerProduct);
14305 case Utils::VARIABLE_TYPE_DMAT3X4:
14306 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14307 function, "outerProduct", Math::outerProduct);
14308 case Utils::VARIABLE_TYPE_DMAT4:
14309 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 function, "outerProduct", Math::outerProduct);
14311 case Utils::VARIABLE_TYPE_DMAT4X2:
14312 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14313 function, "outerProduct", Math::outerProduct);
14314 case Utils::VARIABLE_TYPE_DMAT4X3:
14315 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14316 function, "outerProduct", Math::outerProduct);
14317 default:
14318 break;
14319 }
14320
14321 break;
14322
14323 case FUNCTION_PACKDOUBLE2X32:
14324
14325 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14326 Math::packDouble2x32);
14327
14328 case FUNCTION_REFLECT:
14329
14330 switch (variable_type)
14331 {
14332 case Utils::VARIABLE_TYPE_DVEC2:
14333 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14334 function, "reflect", tcu::reflect);
14335 case Utils::VARIABLE_TYPE_DVEC3:
14336 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14337 function, "reflect", tcu::reflect);
14338 case Utils::VARIABLE_TYPE_DVEC4:
14339 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14340 function, "reflect", tcu::reflect);
14341 default:
14342 break;
14343 }
14344
14345 break;
14346
14347 case FUNCTION_REFRACT:
14348
14349 switch (variable_type)
14350 {
14351 case Utils::VARIABLE_TYPE_DVEC2:
14352 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14353 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14354 function, "refract", tcu::refract);
14355 case Utils::VARIABLE_TYPE_DVEC3:
14356 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14357 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14358 function, "refract", tcu::refract);
14359 case Utils::VARIABLE_TYPE_DVEC4:
14360 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14361 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14362 function, "refract", tcu::refract);
14363 default:
14364 break;
14365 }
14366
14367 break;
14368
14369 case FUNCTION_ROUND:
14370
14371 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14372 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14373
14374 case FUNCTION_ROUNDEVEN:
14375
14376 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14377 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14378
14379 case FUNCTION_SIGN:
14380
14381 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14382 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14383
14384 case FUNCTION_SMOOTHSTEP:
14385
14386 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14387 variable_type /* res_type */, variable_type /* arg1_type */,
14388 variable_type /* arg2_type */, variable_type /* arg3_type */);
14389
14390 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14391
14392 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14393 variable_type /* res_type */, scalar_type /* arg1_type */,
14394 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14395
14396 case FUNCTION_SQRT:
14397
14398 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14399 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14400
14401 case FUNCTION_STEP:
14402
14403 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14404 glw::GLdouble /* Arg2T */>(
14405 function, "step", Math::step, variable_type /* res_type */, variable_type /* arg1_type */,
14406 variable_type /* arg2_type */);
14407
14408 case FUNCTION_STEP_AGAINST_SCALAR:
14409
14410 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14411 glw::GLdouble /* Arg2T */>(
14412 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */,
14413 variable_type /* arg2_type */);
14414
14415 case FUNCTION_TRANSPOSE:
14416
14417 switch (variable_type)
14418 {
14419 case Utils::VARIABLE_TYPE_DMAT2:
14420 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14421 Math::transpose);
14422 case Utils::VARIABLE_TYPE_DMAT2X3:
14423 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14424 Math::transpose);
14425 case Utils::VARIABLE_TYPE_DMAT2X4:
14426 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14427 Math::transpose);
14428 case Utils::VARIABLE_TYPE_DMAT3:
14429 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14430 Math::transpose);
14431 case Utils::VARIABLE_TYPE_DMAT3X2:
14432 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14433 Math::transpose);
14434 case Utils::VARIABLE_TYPE_DMAT3X4:
14435 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14436 Math::transpose);
14437 case Utils::VARIABLE_TYPE_DMAT4:
14438 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14439 Math::transpose);
14440 case Utils::VARIABLE_TYPE_DMAT4X2:
14441 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14442 Math::transpose);
14443 case Utils::VARIABLE_TYPE_DMAT4X3:
14444 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14445 Math::transpose);
14446 default:
14447 break;
14448 }
14449
14450 break;
14451
14452 case FUNCTION_TRUNC:
14453
14454 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14455 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14456
14457 case FUNCTION_UNPACKDOUBLE2X32:
14458
14459 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14460 Math::unpackDouble2x32);
14461
14462 case FUNCTION_ISNAN:
14463
14464 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14465 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14466
14467 case FUNCTION_ISINF:
14468
14469 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14470 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14471
14472 default:
14473 TCU_FAIL("Not implemented");
14474 return 0;
14475 }
14476
14477 TCU_FAIL("Not implemented");
14478 return 0;
14479 }
14480
14481 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14482 *
14483 * @param argument Argument index
14484 * @param function_object Function object
14485 *
14486 * @return Function pointer
14487 **/
getUniformFunctionForDMat( glw::GLuint argument, const functionObject& function_object) const14488 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14489 glw::GLuint argument, const functionObject& function_object) const
14490 {
14491 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14492 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14493
14494 switch (argument_type)
14495 {
14496 case Utils::VARIABLE_TYPE_DMAT2:
14497 return gl.uniformMatrix2dv;
14498 case Utils::VARIABLE_TYPE_DMAT2X3:
14499 return gl.uniformMatrix2x3dv;
14500 case Utils::VARIABLE_TYPE_DMAT2X4:
14501 return gl.uniformMatrix2x4dv;
14502 case Utils::VARIABLE_TYPE_DMAT3:
14503 return gl.uniformMatrix3dv;
14504 case Utils::VARIABLE_TYPE_DMAT3X2:
14505 return gl.uniformMatrix3x2dv;
14506 case Utils::VARIABLE_TYPE_DMAT3X4:
14507 return gl.uniformMatrix3x4dv;
14508 case Utils::VARIABLE_TYPE_DMAT4:
14509 return gl.uniformMatrix4dv;
14510 case Utils::VARIABLE_TYPE_DMAT4X2:
14511 return gl.uniformMatrix4x2dv;
14512 case Utils::VARIABLE_TYPE_DMAT4X3:
14513 return gl.uniformMatrix4x3dv;
14514 default:
14515 break;
14516 }
14517
14518 TCU_FAIL("Not implemented");
14519 return 0;
14520 }
14521
14522 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14523 *
14524 * @param argument Argument index
14525 * @param function_object Function object
14526 *
14527 * @return Function pointer
14528 **/
getUniformFunctionForDVec( glw::GLuint argument, const functionObject& function_object) const14529 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14530 glw::GLuint argument, const functionObject& function_object) const
14531 {
14532 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14533 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14534
14535 switch (argument_type)
14536 {
14537 case Utils::VARIABLE_TYPE_DOUBLE:
14538 return gl.uniform1dv;
14539 case Utils::VARIABLE_TYPE_DVEC2:
14540 return gl.uniform2dv;
14541 case Utils::VARIABLE_TYPE_DVEC3:
14542 return gl.uniform3dv;
14543 case Utils::VARIABLE_TYPE_DVEC4:
14544 return gl.uniform4dv;
14545 default:
14546 TCU_FAIL("Not implemented");
14547 }
14548
14549 return 0;
14550 }
14551
14552 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14553 *
14554 * @param argument Argument index
14555 * @param function_object Function object
14556 *
14557 * @return Function pointer
14558 **/
getUniformFunctionForIVec( glw::GLuint argument, const functionObject& function_object) const14559 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14560 glw::GLuint argument, const functionObject& function_object) const
14561 {
14562 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14563 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14564
14565 switch (argument_type)
14566 {
14567 case Utils::VARIABLE_TYPE_INT:
14568 return gl.uniform1iv;
14569 case Utils::VARIABLE_TYPE_IVEC2:
14570 return gl.uniform2iv;
14571 case Utils::VARIABLE_TYPE_IVEC3:
14572 return gl.uniform3iv;
14573 case Utils::VARIABLE_TYPE_IVEC4:
14574 return gl.uniform4iv;
14575 default:
14576 TCU_FAIL("Not implemented");
14577 }
14578
14579 return 0;
14580 }
14581
14582 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14583 *
14584 * @param argument Argument index
14585 * @param function_object Function object
14586 *
14587 * @return Function pointer
14588 **/
getUniformFunctionForUVec( glw::GLuint argument, const functionObject& function_object) const14589 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14590 glw::GLuint argument, const functionObject& function_object) const
14591 {
14592 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14593 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14594
14595 switch (argument_type)
14596 {
14597 case Utils::VARIABLE_TYPE_UVEC2:
14598 return gl.uniform2uiv;
14599 default:
14600 TCU_FAIL("Not implemented");
14601 }
14602
14603 return 0;
14604 }
14605
14606 /** Get name of uniform that will be used as <argument>.
14607 *
14608 * @param argument Argument index
14609 *
14610 * @return Name of uniform
14611 **/
getUniformName(glw::GLuint argument) const14612 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14613 {
14614 switch (argument)
14615 {
14616 case 0:
14617 return "uniform_0";
14618 case 1:
14619 return "uniform_1";
14620 case 2:
14621 return "uniform_2";
14622 default:
14623 TCU_FAIL("Not implemented");
14624 return 0;
14625 }
14626 }
14627
14628 /** Get name of varying that will be used as <result>.
14629 *
14630 * @param result Result index
14631 *
14632 * @return Name of varying
14633 **/
getVaryingName(glw::GLuint result) const14634 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14635 {
14636 switch (result)
14637 {
14638 case 0:
14639 return "result_0";
14640 case 1:
14641 return "result_1";
14642 case 2:
14643 return "result_2";
14644 default:
14645 TCU_FAIL("Not implemented");
14646 return 0;
14647 }
14648 }
14649
14650 /** Check if given combination of function and type is implemented
14651 *
14652 * @param function Function enumeration
14653 * @param type Type details
14654 *
14655 * @return true if function is available for given type, false otherwise
14656 **/
isFunctionImplemented(FunctionEnum function, const typeDetails& type) const14657 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14658 {
14659 static const bool look_up_table[][3] = {
14660 /* SCALAR, VECTOR, MATRIX */
14661 /* FUNCTION_ABS: */ { true, true, false },
14662 /* FUNCTION_CEIL: */ { true, true, false },
14663 /* FUNCTION_CLAMP: */ { true, true, false },
14664 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false },
14665 /* FUNCTION_CROSS: */ { false, true, false },
14666 /* FUNCTION_DETERMINANT: */ { false, false, true },
14667 /* FUNCTION_DISTANCE: */ { false, true, false },
14668 /* FUNCTION_DOT: */ { false, true, false },
14669 /* FUNCTION_EQUAL: */ { false, true, false },
14670 /* FUNCTION_FACEFORWARD: */ { false, true, false },
14671 /* FUNCTION_FLOOR: */ { true, true, false },
14672 /* FUNCTION_FMA: */ { true, true, false },
14673 /* FUNCTION_FRACT: */ { true, true, false },
14674 /* FUNCTION_FREXP: */ { true, true, false },
14675 /* FUNCTION_GREATERTHAN: */ { false, true, false },
14676 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false },
14677 /* FUNCTION_INVERSE: */ { false, false, true },
14678 /* FUNCTION_INVERSESQRT: */ { true, true, false },
14679 /* FUNCTION_LDEXP: */ { true, true, false },
14680 /* FUNCTION_LESSTHAN: */ { false, true, false },
14681 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false },
14682 /* FUNCTION_LENGTH: */ { false, true, false },
14683 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true },
14684 /* FUNCTION_MAX: */ { true, true, false },
14685 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false },
14686 /* FUNCTION_MIN: */ { true, true, false },
14687 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false },
14688 /* FUNCTION_MIX: */ { true, true, false },
14689 /* FUNCTION_MOD: */ { true, true, false },
14690 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false },
14691 /* FUNCTION_MODF: */ { true, true, false },
14692 /* FUNCTION_NORMALIZE: */ { false, true, false },
14693 /* FUNCTION_NOTEQUAL: */ { false, true, false },
14694 /* FUNCTION_OUTERPRODUCT: */ { false, false, true },
14695 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false },
14696 /* FUNCTION_REFLECT: */ { false, true, false },
14697 /* FUNCTION_REFRACT: */ { false, true, false },
14698 /* FUNCTION_ROUND: */ { true, true, false },
14699 /* FUNCTION_ROUNDEVEN: */ { true, true, false },
14700 /* FUNCTION_SIGN: */ { true, false, false },
14701 /* FUNCTION_SMOOTHSTEP: */ { true, true, false },
14702 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14703 /* FUNCTION_SQRT: */ { true, true, false },
14704 /* FUNCTION_STEP: */ { true, true, false },
14705 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false },
14706 /* FUNCTION_TRANSPOSE: */ { false, false, false },
14707 /* FUNCTION_TRUNC: */ { true, true, false },
14708 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false },
14709 /* FUNCTION_ISNAN: */ { true, true, false },
14710 /* FUNCTION_ISINF: */ { true, true, false },
14711 };
14712
14713 bool result = look_up_table[function][type.m_general_type];
14714
14715 if (true == result)
14716 {
14717 switch (function)
14718 {
14719 case FUNCTION_CROSS: /* Only 3 element vectors */
14720 result = (3 == type.m_n_rows);
14721 break;
14722 case FUNCTION_DETERMINANT: /* Only square matrices */
14723 case FUNCTION_INVERSE:
14724 result = (type.m_n_columns == type.m_n_rows);
14725 break;
14726 default:
14727 break;
14728 }
14729 }
14730
14731 return result;
14732 }
14733
14734 /** Logs variable of given type: name (type) [values]
14735 *
14736 * @param buffer Source of data
14737 * @param name Name of variable
14738 * @param type Type of variable
14739 **/
logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const14740 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14741 Utils::_variable_type type) const
14742 {
14743 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14744 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
14745 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14746
14747 message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14748
14749 for (glw::GLuint component = 0; component < n_components; ++component)
14750 {
14751 if (0 != component)
14752 {
14753 message << ", ";
14754 }
14755
14756 switch (base_type)
14757 {
14758 case Utils::VARIABLE_TYPE_DOUBLE:
14759 message << ((glw::GLdouble*)buffer)[component];
14760 break;
14761 case Utils::VARIABLE_TYPE_INT:
14762 message << ((glw::GLint*)buffer)[component];
14763 break;
14764 case Utils::VARIABLE_TYPE_UINT:
14765 message << ((glw::GLuint*)buffer)[component];
14766 break;
14767 default:
14768 TCU_FAIL("Not implemented");
14769 }
14770 }
14771
14772 message << "]" << tcu::TestLog::EndMessage;
14773 }
14774
14775 /** Prepare input arguments, data are stored in <buffer>
14776 *
14777 * @param function_object Function object
14778 * @param vertex Vertex index
14779 * @param buffer Buffer pointer
14780 **/
prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer)14781 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14782 glw::GLubyte* buffer)
14783 {
14784 const glw::GLuint n_arguments = function_object.getArgumentCount();
14785
14786 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14787 {
14788 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14789
14790 prepareComponents(function_object, vertex, argument, buffer + offset);
14791 }
14792 }
14793
14794 /** Prepare components for given <function_object>, <vertex> and <argument>
14795 *
14796 * @param function_object Function object
14797 * @param vertex Vertex index
14798 * @param argument Argument index
14799 * @param buffer Buffer pointer
14800 **/
prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument, glw::GLubyte* buffer)14801 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14802 glw::GLuint argument, glw::GLubyte* buffer)
14803 {
14804 glw::GLuint argument_index[3] = { 0 };
14805 glw::GLuint argument_reset[3] = { 0 };
14806 glw::GLuint argument_step[3] = { 0 };
14807 glw::GLdouble double_argument_start[3] = { 0.0 };
14808 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14809 glw::GLuint int_argument_start = -4;
14810 const glw::GLuint n_arguments = function_object.getArgumentCount();
14811 const glw::GLuint n_components = function_object.getArgumentComponents(argument);
14812 glw::GLuint uint_argument_start = 0;
14813
14814 switch (n_arguments)
14815 {
14816 case 1:
14817 argument_step[0] = 1;
14818 argument_reset[0] = 1024;
14819 double_argument_start[0] = -511.5;
14820 break;
14821 case 2:
14822 argument_step[0] = 32;
14823 argument_step[1] = 1;
14824 argument_reset[0] = 32;
14825 argument_reset[1] = 32;
14826 double_argument_start[0] = -15.5;
14827 double_argument_start[1] = -15.5;
14828 break;
14829 case 3:
14830 argument_step[0] = 64;
14831 argument_step[1] = 8;
14832 argument_step[2] = 1;
14833 argument_reset[0] = 16;
14834 argument_reset[1] = 8;
14835 argument_reset[2] = 8;
14836 double_argument_start[0] = -7.5;
14837 double_argument_start[1] = -3.5;
14838 double_argument_start[2] = -3.5;
14839 break;
14840 default:
14841 TCU_FAIL("Not implemented");
14842 return;
14843 }
14844
14845 switch (function_object.getFunctionEnum())
14846 {
14847 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14848 case FUNCTION_CLAMP_AGAINST_SCALAR:
14849 double_argument_start[2] = 4.5;
14850 break;
14851 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14852 double_argument_start[0] = 16.5;
14853 break;
14854 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14855 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14856 argument_step[0] = 1;
14857 argument_step[1] = 8;
14858 argument_step[2] = 64;
14859 argument_reset[0] = 8;
14860 argument_reset[1] = 8;
14861 argument_reset[2] = 16;
14862 double_argument_start[0] = -3.5;
14863 double_argument_start[1] = 4.5;
14864 double_argument_start[2] = -7.5;
14865 break;
14866 default:
14867 break;
14868 }
14869
14870 for (glw::GLuint i = 0; i < n_arguments; ++i)
14871 {
14872 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14873 }
14874
14875 switch (base_arg_type)
14876 {
14877 case Utils::VARIABLE_TYPE_DOUBLE:
14878 {
14879 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14880
14881 double_argument_start[argument] += argument_index[argument];
14882
14883 for (glw::GLuint component = 0; component < n_components; ++component)
14884 {
14885 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14886
14887 switch (function_object.getFunctionEnum())
14888 {
14889 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14890 if (0.5 == Math::fract(value))
14891 {
14892 value += 0.01;
14893 }
14894 break;
14895 default:
14896 break;
14897 }
14898
14899 argument_dst[component] = value;
14900 }
14901 }
14902 break;
14903 case Utils::VARIABLE_TYPE_INT:
14904 {
14905 glw::GLint* argument_dst = (glw::GLint*)buffer;
14906
14907 uint_argument_start += argument_index[argument];
14908
14909 for (glw::GLuint component = 0; component < n_components; ++component)
14910 {
14911 const glw::GLint value = int_argument_start + component;
14912
14913 argument_dst[component] = value;
14914 }
14915 }
14916 break;
14917 case Utils::VARIABLE_TYPE_UINT:
14918 {
14919 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14920
14921 uint_argument_start += argument_index[argument];
14922
14923 for (glw::GLuint component = 0; component < n_components; ++component)
14924 {
14925 const glw::GLuint value = uint_argument_start + component;
14926
14927 argument_dst[component] = value;
14928 }
14929 }
14930 break;
14931 default:
14932 TCU_FAIL("Not implemented");
14933 return;
14934 }
14935 }
14936
14937 /** Prepare programInfo for given functionObject
14938 *
14939 * @param function_object Function object
14940 * @param out_program_info Program info
14941 **/
prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)14942 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14943 {
14944 const glw::GLuint n_varying_names = function_object.getResultCount();
14945 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14946
14947 prepareVertexShaderCode(function_object);
14948
14949 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14950 varying_names, n_varying_names);
14951 }
14952
14953 /** Prepare input data and expected results for given function object
14954 *
14955 * @param function_object Function object
14956 **/
prepareTestData(const functionObject& function_object)14957 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14958 {
14959 const glw::GLuint result_stride = function_object.getResultStride();
14960 const glw::GLuint result_buffer_size = result_stride * m_n_veritces;
14961 const glw::GLuint argument_stride = function_object.getArgumentStride();
14962 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14963
14964 m_argument_data.clear();
14965 m_expected_results_data.clear();
14966
14967 m_argument_data.resize(argument_buffer_size);
14968 m_expected_results_data.resize(result_buffer_size);
14969
14970 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14971 {
14972 const glw::GLuint result_offset = vertex * result_stride;
14973 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset];
14974 const glw::GLuint argument_offset = vertex * argument_stride;
14975 glw::GLubyte* argument_dst = &m_argument_data[argument_offset];
14976
14977 prepareArgument(function_object, vertex, argument_dst);
14978 function_object.call(result_dst, argument_dst);
14979 }
14980 }
14981
14982 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14983 *
14984 * @param function_object Function object
14985 **/
prepareVertexShaderCode(const functionObject& function_object)14986 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14987 {
14988 static const glw::GLchar* shader_template_code = "#version 400 core\n"
14989 "\n"
14990 "precision highp float;\n"
14991 "\n"
14992 "ARGUMENT_DEFINITION"
14993 "\n"
14994 "RESULT_DEFINITION"
14995 "\n"
14996 "void main()\n"
14997 "{\n"
14998 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14999 "}\n"
15000 "\n";
15001
15002 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15003 static const glw::GLchar* argument_token = "ARGUMENT";
15004 static const glw::GLchar* function_name_token = "FUNCTION_NAME";
15005 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION";
15006 static const glw::GLchar* result_name_token = "RESULT_NAME";
15007 static const glw::GLchar* result_type_token = "RESULT_TYPE";
15008 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME";
15009 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE";
15010
15011 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15012 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT";
15013 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT";
15014 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15015
15016 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15017 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument);
15018 const glw::GLuint n_arguments = function_object.getArgumentCount();
15019 const glw::GLuint n_results = function_object.getResultCount();
15020 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition);
15021 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0));
15022
15023 size_t search_position = 0;
15024 std::string string = shader_template_code;
15025
15026 /* Replace ARGUMENT_DEFINITION with definitions */
15027 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15028 {
15029 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15030 const glw::GLchar* uniform_name = getUniformName(argument);
15031 std::string uniform_type = Utils::getVariableTypeString(argument_type);
15032
15033 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15034
15035 search_position -= argument_definition_length;
15036
15037 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15038 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15039 }
15040
15041 /* Remove ARGUMENT_DEFINITION */
15042 Utils::replaceToken(argument_definition_token, search_position, "", string);
15043
15044 /* Replace RESULT_DEFINITION with definitions */
15045 for (glw::GLuint result = 0; result < n_results; ++result)
15046 {
15047 Utils::_variable_type variable_type = function_object.getResultType(result);
15048 const glw::GLchar* varying_name = getVaryingName(result);
15049 std::string varying_type = Utils::getVariableTypeString(variable_type);
15050
15051 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15052
15053 search_position -= result_definition_length;
15054
15055 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15056 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15057 }
15058
15059 /* Remove RESULT_DEFINITION */
15060 Utils::replaceToken(result_definition_token, search_position, "", string);
15061
15062 /* Replace RESULT_NAME */
15063 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15064
15065 /* Replace RESULT_TYPE */
15066 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15067
15068 /* Replace FUNCTION_NAME */
15069 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15070
15071 /* Replace ARGUMENT with list of arguments */
15072 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15073 {
15074 const glw::GLchar* uniform_name = getUniformName(argument);
15075
15076 if (0 == argument)
15077 {
15078 Utils::replaceToken(argument_token, search_position, first_argument, string);
15079 }
15080 else
15081 {
15082 Utils::replaceToken(argument_token, search_position, argument_str, string);
15083 }
15084
15085 search_position -= first_argument_length;
15086
15087 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15088 }
15089
15090 for (glw::GLuint result = 1; result < n_results; ++result)
15091 {
15092 const glw::GLchar* varying_name = getVaryingName(result);
15093
15094 Utils::replaceToken(argument_token, search_position, argument_str, string);
15095
15096 search_position -= first_argument_length;
15097
15098 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15099 }
15100
15101 /* Remove ARGUMENT */
15102 Utils::replaceToken(argument_token, search_position, "", string);
15103
15104 m_vertex_shader_code = string;
15105 }
15106
15107 /** Test single function with one type
15108 *
15109 * param function Function enumeration
15110 * param type Type details
15111 *
15112 * @return true if test pass (or function is not available for <type>), false otherwise
15113 **/
test(FunctionEnum function, const typeDetails& type)15114 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15115 {
15116 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15117
15118 /* Skip if function is not implemented for type */
15119 if (false == isFunctionImplemented(function, type))
15120 {
15121 return true;
15122 }
15123
15124 Utils::programInfo program(m_context);
15125 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15126
15127 prepareProgram(*function_object, program);
15128 prepareTestData(*function_object);
15129
15130 /* Set up program */
15131 gl.useProgram(program.m_program_object_id);
15132 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15133
15134 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15135 {
15136 testBegin(*function_object, program.m_program_object_id, vertex);
15137
15138 gl.beginTransformFeedback(GL_POINTS);
15139 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15140
15141 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15142 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15143
15144 gl.endTransformFeedback();
15145 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15146
15147 if (false == verifyResults(*function_object, vertex))
15148 {
15149 return false;
15150 }
15151 }
15152
15153 return true;
15154 }
15155
15156 /** Update transform feedback buffer and uniforms
15157 *
15158 * @param function_object Function object
15159 * @param program_id Program object id
15160 * @param vertex Vertex index
15161 **/
testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)15162 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15163 {
15164 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15165 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15166 const glw::GLuint n_arguments = function_object.getArgumentCount();
15167 const glw::GLuint result_buffer_size = function_object.getResultStride();
15168 const glw::GLuint vertex_offset = arguments_stride * vertex;
15169
15170 /* Update transform feedback buffer */
15171 std::vector<glw::GLubyte> transform_feedback_buffer_data;
15172 transform_feedback_buffer_data.resize(result_buffer_size);
15173
15174 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15175 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15176
15177 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15178 GL_DYNAMIC_COPY);
15179 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15180
15181 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15182 result_buffer_size);
15183 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15184
15185 /* Update VAO */
15186 gl.bindVertexArray(m_vertex_array_object_id);
15187 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15188
15189 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15190 {
15191 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15192 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15193 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type);
15194 const glw::GLchar* uniform_name = getUniformName(argument);
15195 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name);
15196 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15197
15198 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15199
15200 if (-1 == uniform_location)
15201 {
15202 TCU_FAIL("Inactive uniform");
15203 }
15204
15205 if (1 == n_columns)
15206 {
15207 switch (Utils::getBaseVariableType(argument_type))
15208 {
15209 case Utils::VARIABLE_TYPE_DOUBLE:
15210 {
15211 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15212
15213 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15214 }
15215 break;
15216 case Utils::VARIABLE_TYPE_UINT:
15217 {
15218 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15219
15220 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15221 }
15222 break;
15223 case Utils::VARIABLE_TYPE_INT:
15224 {
15225 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15226
15227 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15228 }
15229 break;
15230 default:
15231 TCU_FAIL("Not implemented");
15232 }
15233 }
15234 else
15235 {
15236 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15237
15238 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15239 }
15240 }
15241 }
15242
15243 /** Init GL obejcts
15244 *
15245 **/
testInit()15246 void BuiltinFunctionTest::testInit()
15247 {
15248 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15249
15250 gl.genBuffers(1, &m_transform_feedback_buffer_id);
15251 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15252
15253 gl.genVertexArrays(1, &m_vertex_array_object_id);
15254 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15255
15256 gl.enable(GL_RASTERIZER_DISCARD);
15257 }
15258
15259 /** Checks if function result is an acceptable edge case
15260 *
15261 * @param function_object Function object
15262 * @param vertex Vertex index
15263 *
15264 * @return true if all results are as expected, false otherwise
15265 **/
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)15266 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15267 const Utils::_variable_type result_type,
15268 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15269 {
15270 FunctionEnum function_type = function_object.getFunctionEnum();
15271 switch (function_type)
15272 {
15273 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15274 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15275 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15276 case FUNCTION_MOD:
15277 case FUNCTION_MOD_AGAINST_SCALAR:
15278 {
15279 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15280 const glw::GLuint vertex_offset = arguments_stride * vertex;
15281 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0);
15282 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1);
15283 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset;
15284 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset;
15285 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index];
15286 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index];
15287 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15288 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15289 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15290 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src);
15291 bool edge_case_present = false;
15292 bool recheck = false;
15293
15294 // verify if there is a mod(a, a) case and prepare new expected result
15295 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15296 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15297 for (glw::GLuint component = 0; component < n_components; ++component)
15298 {
15299 glw::GLdouble expected_result_component = expected_result[component];
15300 glw::GLdouble actual_result_component = actual_result[component];
15301 glw::GLdouble argument_1_component = argument_1[component];
15302 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15303
15304 // if coresponding components of arguments are equal and if component of first argument
15305 // and component of result are equal then expected result must be corrected
15306 bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15307 round(argument_1_component / argument_2_component));
15308 edge_case_present = possible_edge_case &&
15309 (m_epsilon > de::abs(argument_2_component - actual_result_component));
15310 recheck |= edge_case_present;
15311 corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15312 }
15313
15314 // recheck test result with corrected expected result
15315 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15316 }
15317 default:
15318 return false;
15319 }
15320 }
15321
15322 /** Compare contents of transform feedback buffer with expected results
15323 *
15324 * @param function_object Function object
15325 * @param vertex Vertex index
15326 *
15327 * @return true if all results are as expected, false otherwise
15328 **/
verifyResults(const functionObject& function_object, glw::GLuint vertex)15329 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15330 {
15331 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15332 bool test_result = true;
15333 const glw::GLuint n_results = function_object.getResultCount();
15334 const glw::GLuint results_stride = function_object.getResultStride();
15335 const glw::GLuint results_offset = vertex * results_stride;
15336 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset];
15337
15338 /* Get transform feedback data */
15339 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15340 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15341
15342 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15343 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15344
15345 for (glw::GLuint result = 0; result < n_results; ++result)
15346 {
15347 const Utils::_variable_type result_type = function_object.getResultType(result);
15348 const glw::GLuint result_offset = function_object.getResultOffset(result);
15349
15350 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15351 const glw::GLvoid* result_src = feedback_data + result_offset;
15352
15353 if (compare(result_type, expected_result_src, result_src))
15354 continue;
15355
15356 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15357 {
15358 test_result = false;
15359 break;
15360 }
15361 }
15362
15363 /* Unmap transform feedback buffer */
15364 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15365 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15366
15367 if (false == test_result)
15368 {
15369 const glw::GLuint argument_stride = function_object.getArgumentStride();
15370 const glw::GLuint arguments_offset = vertex * argument_stride;
15371
15372 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15373 << tcu::TestLog::EndMessage;
15374
15375 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15376 << tcu::TestLog::EndMessage;
15377
15378 for (glw::GLuint result = 0; result < n_results; ++result)
15379 {
15380 const Utils::_variable_type result_type = function_object.getResultType(result);
15381 const glw::GLuint result_offset = function_object.getResultOffset(result);
15382
15383 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15384 const glw::GLvoid* result_src = feedback_data + result_offset;
15385
15386 logVariableType(result_src, "Result", result_type);
15387 logVariableType(expected_result_src, "Expected result", result_type);
15388 }
15389
15390 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15391 {
15392 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15393 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset];
15394
15395 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15396 }
15397
15398 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15399 << m_vertex_shader_code << tcu::TestLog::EndMessage;
15400 }
15401
15402 return test_result;
15403 }
15404
15405 /** Constructor.
15406 *
15407 * @param context Rendering context.
15408 **/
GPUShaderFP64Tests(deqp::Context& context)15409 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15410 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15411 {
15412 /* Left blank on purpose */
15413 }
15414
15415 /** Initializes a texture_storage_multisample test group.
15416 *
15417 **/
init(void)15418 void GPUShaderFP64Tests::init(void)
15419 {
15420 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15421 fp64->addChild(new GPUShaderFP64Test1(m_context));
15422 fp64->addChild(new GPUShaderFP64Test2(m_context));
15423 fp64->addChild(new GPUShaderFP64Test3(m_context));
15424 fp64->addChild(new GPUShaderFP64Test4(m_context));
15425 fp64->addChild(new GPUShaderFP64Test5(m_context));
15426 fp64->addChild(new GPUShaderFP64Test6(m_context));
15427 fp64->addChild(new GPUShaderFP64Test7(m_context));
15428 fp64->addChild(new GPUShaderFP64Test8(m_context));
15429 fp64->addChild(new GPUShaderFP64Test9(m_context));
15430 addChild(fp64);
15431
15432 TypeDefinition typeDefinition[] =
15433 {
15434 { "double", 1, 1 },
15435 { "dvec2", 1, 2 },
15436 { "dvec3", 1, 3 },
15437 { "dvec4", 1, 4 },
15438 { "dmat2", 2, 2 },
15439 { "dmat2x3", 2, 3 },
15440 { "dmat2x4", 2, 4 },
15441 { "dmat3x2", 3, 2 },
15442 { "dmat3", 3, 3 },
15443 { "dmat3x4", 3, 4 },
15444 { "dmat4x2", 4, 2 },
15445 { "dmat4x3", 4, 3 },
15446 { "dmat4", 4, 4 }
15447 };
15448
15449 struct BuiltinFunctions
15450 {
15451 std::string name;
15452 FunctionEnum function;
15453 } builtinFunctions[] = {
15454 { "abs", FUNCTION_ABS },
15455 { "ceil", FUNCTION_CEIL },
15456 { "clamp", FUNCTION_CLAMP },
15457 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR },
15458 { "cross", FUNCTION_CROSS },
15459 { "determinant", FUNCTION_DETERMINANT },
15460 { "distance", FUNCTION_DISTANCE },
15461 { "dot", FUNCTION_DOT },
15462 { "equal", FUNCTION_EQUAL },
15463 { "faceforward", FUNCTION_FACEFORWARD },
15464 { "floor", FUNCTION_FLOOR },
15465 { "fma", FUNCTION_FMA },
15466 { "fract", FUNCTION_FRACT },
15467 { "frexp", FUNCTION_FREXP },
15468 { "greaterthan", FUNCTION_GREATERTHAN },
15469 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL },
15470 { "inverse", FUNCTION_INVERSE },
15471 { "inversesqrt", FUNCTION_INVERSESQRT },
15472 { "ldexp", FUNCTION_LDEXP },
15473 { "lessthan", FUNCTION_LESSTHAN },
15474 { "lessthanequal", FUNCTION_LESSTHANEQUAL },
15475 { "length", FUNCTION_LENGTH },
15476 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT },
15477 { "max", FUNCTION_MAX },
15478 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR },
15479 { "min", FUNCTION_MIN },
15480 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR },
15481 { "mix", FUNCTION_MIX },
15482 { "mod", FUNCTION_MOD },
15483 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR },
15484 { "modf", FUNCTION_MODF },
15485 { "normalize", FUNCTION_NORMALIZE },
15486 { "notequal", FUNCTION_NOTEQUAL },
15487 { "outerproduct", FUNCTION_OUTERPRODUCT },
15488 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 },
15489 { "reflect", FUNCTION_REFLECT },
15490 { "refract", FUNCTION_REFRACT },
15491 { "round", FUNCTION_ROUND },
15492 { "roundeven", FUNCTION_ROUNDEVEN },
15493 { "sign", FUNCTION_SIGN },
15494 { "smoothstep", FUNCTION_SMOOTHSTEP },
15495 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15496 { "sqrt", FUNCTION_SQRT },
15497 { "step", FUNCTION_STEP },
15498 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR },
15499 { "transpose", FUNCTION_TRANSPOSE },
15500 { "trunc", FUNCTION_TRUNC },
15501 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 },
15502 { "isnan", FUNCTION_ISNAN },
15503 { "isinf", FUNCTION_ISINF }
15504 };
15505
15506 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15507 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15508 {
15509 const BuiltinFunctions& bf = builtinFunctions[i];
15510 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15511 {
15512 std::string caseName = bf.name + "_" + typeDefinition[j].name;
15513 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15514 }
15515 }
15516 addChild(builin);
15517 }
15518
15519 } /* glcts namespace */
15520