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 dummy1[3] | 4 | 12 | 0 | 12 | 0 | |
5308 * double double_value | 2 | 2 | 12 | 14 | 48 | XXX |
5309 * bool dummy2 | 1 | 1 | 14 | 15 | 56 | |
5310 * dvec2 dvec2_value | 4 | 4 | 16 | 20 | 64 | XXX |
5311 * bvec3 dummy3 | 4 | 4 | 20 | 24 | 80 | |
5312 * dvec3 dvec3_value | 8 | 8 | 24 | 32 | 96 | XXX |
5313 * int dummy4[3] | 4 | 12 | 32 | 44 | 128 | |
5314 * dvec4 dvec4_value | 8 | 8 | 48 | 56 | 192 | XXX |
5315 * bool dummy5 | 1 | 1 | 56 | 57 | 224 | |
5316 * bool dummy6[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 dummy7 | 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 dummy8 | 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 dummy9 | 1 | 1 | 196 | 197 | 784 | |
5326 * dmat3x4 dmat3x4_value | 8 | 24 | 200 | 224 | 800 | XXX |
5327 * int dummy10 | 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 dummy1[3];\n"
5694 " double double_value;\n"
5695 " bool dummy2;\n"
5696 " dvec2 dvec2_value;\n"
5697 " bvec3 dummy3;\n"
5698 " dvec3 dvec3_value;\n"
5699 " int dummy4[3];\n"
5700 " dvec4 dvec4_value;\n"
5701 " bool dummy5;\n"
5702 " bool dummy6[2];\n"
5703 " dmat2 dmat2_value;\n"
5704 " dmat3 dmat3_value;\n"
5705 " bool dummy7;\n"
5706 " dmat4 dmat4_value;\n"
5707 " dmat2x3 dmat2x3_value;\n"
5708 " uvec3 dummy8;\n"
5709 " dmat2x4 dmat2x4_value;\n"
5710 " dmat3x2 dmat3x2_value;\n"
5711 " bool dummy9;\n"
5712 " dmat3x4 dmat3x4_value;\n"
5713 " int dummy10;\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 " }\n"
6218 "}\n";
6219
6220 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body, DE_NULL /* length */);
6221 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6222
6223 /* Configure tessellation evaluation shader body */
6224 const char* te_body = "#version 400\n"
6225 "\n"
6226 "uniform double te_double;\n"
6227 "uniform dvec2 te_dvec2;\n"
6228 "uniform dvec3 te_dvec3;\n"
6229 "uniform dvec4 te_dvec4;\n"
6230 "uniform double te_double_arr[2];\n"
6231 "uniform dvec2 te_dvec2_arr [2];\n"
6232 "uniform dvec3 te_dvec3_arr [2];\n"
6233 "uniform dvec4 te_dvec4_arr [2];\n"
6234 "\n"
6235 "uniform struct te_struct\n"
6236 "{\n"
6237 " double struct_double;\n"
6238 " dvec2 struct_dvec2;\n"
6239 " dvec3 struct_dvec3;\n"
6240 " dvec4 struct_dvec4;\n"
6241 "} te_array[2];\n"
6242 "\n"
6243 "layout(triangles) in;\n"
6244 "\n"
6245 "void main()\n"
6246 "{\n"
6247 " if (te_double * te_dvec2.x * te_dvec3.x "
6248 "* te_dvec4.x *\n"
6249 " te_double_arr[0] * te_dvec2_arr[0].x * te_dvec3_arr[0].x "
6250 "* te_dvec4_arr[0].x *\n"
6251 " te_double_arr[1] * te_dvec2_arr[1].x * te_dvec3_arr[1].x "
6252 "* te_dvec4_arr[1].x *\n"
6253 " te_array[0].struct_double * te_array[0].struct_dvec2.x * te_array[0].struct_dvec3.x "
6254 "* te_array[0].struct_dvec4.x *\n"
6255 " te_array[1].struct_double * te_array[1].struct_dvec2.x * te_array[1].struct_dvec3.x "
6256 "* te_array[1].struct_dvec4.x > 1.0)\n"
6257 " {\n"
6258 " gl_Position = gl_in[0].gl_Position;\n"
6259 " }\n"
6260 " else\n"
6261 " {\n"
6262 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6263 " }\n"
6264 "}\n";
6265
6266 gl.shaderSource(m_te_id, 1 /* count */, &te_body, DE_NULL /* length */);
6267 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6268
6269 /* Configure geometry shader body */
6270 const char* gs_body = "#version 400\n"
6271 "\n"
6272 "uniform double gs_double;\n"
6273 "uniform dvec2 gs_dvec2;\n"
6274 "uniform dvec3 gs_dvec3;\n"
6275 "uniform dvec4 gs_dvec4;\n"
6276 "uniform double gs_double_arr[2];\n"
6277 "uniform dvec2 gs_dvec2_arr [2];\n"
6278 "uniform dvec3 gs_dvec3_arr [2];\n"
6279 "uniform dvec4 gs_dvec4_arr [2];\n"
6280 "\n"
6281 "uniform struct gs_struct\n"
6282 "{\n"
6283 " double struct_double;\n"
6284 " dvec2 struct_dvec2;\n"
6285 " dvec3 struct_dvec3;\n"
6286 " dvec4 struct_dvec4;\n"
6287 "} gs_array[2];\n"
6288 "\n"
6289 "layout (points) in;\n"
6290 "layout (points, max_vertices = 1) out;\n"
6291 "\n"
6292 "void main()\n"
6293 "{\n"
6294 " if (gs_double * gs_dvec2.x * gs_dvec3.x "
6295 "* gs_dvec4.x *\n"
6296 " gs_double_arr[0] * gs_dvec2_arr[0].x * gs_dvec3_arr[0].x "
6297 "* gs_dvec4_arr[0].x *\n"
6298 " gs_double_arr[1] * gs_dvec2_arr[1].x * gs_dvec3_arr[1].x "
6299 "* gs_dvec4_arr[1].x *\n"
6300 " gs_array[0].struct_double * gs_array[0].struct_dvec2.x * gs_array[0].struct_dvec3.x "
6301 "* gs_array[0].struct_dvec4.x *\n"
6302 " gs_array[1].struct_double * gs_array[1].struct_dvec2.x * gs_array[1].struct_dvec3.x "
6303 "* gs_array[1].struct_dvec4.x > 1.0)\n"
6304 " {\n"
6305 " gl_Position = gl_in[0].gl_Position;\n"
6306 " }\n"
6307 " else\n"
6308 " {\n"
6309 " gl_Position = gl_in[0].gl_Position + vec4(1);\n"
6310 " }\n"
6311 "\n"
6312 " EmitVertex();\n"
6313 "}\n";
6314
6315 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body, DE_NULL /* length */);
6316 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6317
6318 /* Configure fragment shader body */
6319 const char* fs_body = "#version 400\n"
6320 "\n"
6321 "uniform double fs_double;\n"
6322 "uniform dvec2 fs_dvec2;\n"
6323 "uniform dvec3 fs_dvec3;\n"
6324 "uniform dvec4 fs_dvec4;\n"
6325 "uniform double fs_double_arr[2];\n"
6326 "uniform dvec2 fs_dvec2_arr [2];\n"
6327 "uniform dvec3 fs_dvec3_arr [2];\n"
6328 "uniform dvec4 fs_dvec4_arr [2];\n"
6329 "\n"
6330 "uniform struct fs_struct\n"
6331 "{\n"
6332 " double struct_double;\n"
6333 " dvec2 struct_dvec2;\n"
6334 " dvec3 struct_dvec3;\n"
6335 " dvec4 struct_dvec4;\n"
6336 "} fs_array[2];\n"
6337 "\n"
6338 "out vec4 result;\n"
6339 "\n"
6340 "void main()\n"
6341 "{\n"
6342 " if (fs_double * fs_dvec2.x * fs_dvec3.x "
6343 "* fs_dvec4.x *\n"
6344 " fs_double_arr[0] * fs_dvec2_arr[0].x * fs_dvec3_arr[0].x "
6345 "* fs_dvec4_arr[0].x *\n"
6346 " fs_double_arr[1] * fs_dvec2_arr[1].x * fs_dvec3_arr[1].x "
6347 "* fs_dvec4_arr[1].x *\n"
6348 " fs_array[0].struct_double * fs_array[0].struct_dvec2.x * fs_array[0].struct_dvec3.x "
6349 "* fs_array[0].struct_dvec4.x *\n"
6350 " fs_array[1].struct_double * fs_array[1].struct_dvec2.x * fs_array[1].struct_dvec3.x "
6351 "* fs_array[1].struct_dvec4.x > 1.0)\n"
6352 " {\n"
6353 " result = vec4(0.0);\n"
6354 " }\n"
6355 " else\n"
6356 " {\n"
6357 " result = vec4(1.0);\n"
6358 " }\n"
6359 "}\n";
6360
6361 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body, DE_NULL /* length */);
6362 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed");
6363
6364 /* Compile the shaders */
6365 const glw::GLuint shaders[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
6366 const unsigned int n_shaders = sizeof(shaders) / sizeof(shaders[0]);
6367
6368 for (unsigned int n_shader = 0; n_shader < n_shaders; ++n_shader)
6369 {
6370 glw::GLint compile_status = GL_FALSE;
6371 glw::GLuint so_id = shaders[n_shader];
6372
6373 /* Skip compute shader if not supported */
6374 if (0 == so_id)
6375 {
6376 continue;
6377 }
6378
6379 gl.compileShader(so_id);
6380 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed");
6381
6382 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
6383 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed");
6384
6385 if (compile_status != GL_TRUE)
6386 {
6387 TCU_FAIL("Shader compilation failed");
6388 }
6389
6390 if (so_id == m_cs_id)
6391 {
6392 gl.attachShader(m_po_cs_id, so_id);
6393 }
6394 else
6395 {
6396 gl.attachShader(m_po_noncs_id, so_id);
6397 }
6398
6399 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
6400 } /* for (all shaders) */
6401
6402 /* Link the program */
6403 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6404 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6405 glw::GLint link_status = GL_FALSE;
6406
6407 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6408 {
6409 glw::GLuint po_id = programs[n_program];
6410
6411 /* Skip compute shader program if not supported */
6412 if (0 == po_id)
6413 {
6414 continue;
6415 }
6416
6417 gl.linkProgram(po_id);
6418 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
6419
6420 gl.getProgramiv(po_id, GL_LINK_STATUS, &link_status);
6421 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed");
6422
6423 if (link_status != GL_TRUE)
6424 {
6425 TCU_FAIL("Program linking failed");
6426 }
6427 } /* for (both program objects) */
6428
6429 /* Retrieve uniform locations */
6430 _stage_data* cs_stage_data[] = { &m_data_cs };
6431 static const char* cs_uniform_prefixes[] = { "cs_" };
6432 static const unsigned int n_cs_uniform_prefixes = sizeof(cs_uniform_prefixes) / sizeof(cs_uniform_prefixes[0]);
6433
6434 _stage_data* noncs_stage_data[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6435 static const char* noncs_uniform_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6436 static const unsigned int n_noncs_uniform_prefixes =
6437 sizeof(noncs_uniform_prefixes) / sizeof(noncs_uniform_prefixes[0]);
6438
6439 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6440 {
6441 unsigned int n_uniform_prefixes = DE_NULL;
6442 glw::GLuint po_id = programs[n_program];
6443 _stage_data** stages_data = DE_NULL;
6444 const char** uniform_prefixes = DE_NULL;
6445
6446 if (n_program == 0)
6447 {
6448 stages_data = cs_stage_data;
6449 uniform_prefixes = cs_uniform_prefixes;
6450 n_uniform_prefixes = n_cs_uniform_prefixes;
6451 }
6452 else
6453 {
6454 stages_data = noncs_stage_data;
6455 uniform_prefixes = noncs_uniform_prefixes;
6456 n_uniform_prefixes = n_noncs_uniform_prefixes;
6457 }
6458
6459 /* Skip compute shader program if not supported */
6460 if (0 == po_id)
6461 {
6462 continue;
6463 }
6464
6465 /* Uniform names used by the test program consist of a prefix (different for each
6466 * shader stage) and a common part.
6467 */
6468 for (unsigned int n_uniform_prefix = 0; n_uniform_prefix < n_uniform_prefixes; ++n_uniform_prefix)
6469 {
6470 _stage_data* stage_data = stages_data[n_uniform_prefix];
6471 std::string uniform_prefix = std::string(uniform_prefixes[n_uniform_prefix]);
6472 std::string uniform_double_name = uniform_prefix + "double";
6473 std::string uniform_double_arr0_name = uniform_prefix + "double_arr[0]";
6474 std::string uniform_double_arr1_name = uniform_prefix + "double_arr[1]";
6475 std::string uniform_dvec2_name = uniform_prefix + "dvec2";
6476 std::string uniform_dvec2_arr0_name = uniform_prefix + "dvec2_arr[0]";
6477 std::string uniform_dvec2_arr1_name = uniform_prefix + "dvec2_arr[1]";
6478 std::string uniform_dvec3_name = uniform_prefix + "dvec3";
6479 std::string uniform_dvec3_arr0_name = uniform_prefix + "dvec3_arr[0]";
6480 std::string uniform_dvec3_arr1_name = uniform_prefix + "dvec3_arr[1]";
6481 std::string uniform_dvec4_name = uniform_prefix + "dvec4";
6482 std::string uniform_dvec4_arr0_name = uniform_prefix + "dvec4_arr[0]";
6483 std::string uniform_dvec4_arr1_name = uniform_prefix + "dvec4_arr[1]";
6484 std::string uniform_arr0_double_name = uniform_prefix + "array[0].struct_double";
6485 std::string uniform_arr0_dvec2_name = uniform_prefix + "array[0].struct_dvec2";
6486 std::string uniform_arr0_dvec3_name = uniform_prefix + "array[0].struct_dvec3";
6487 std::string uniform_arr0_dvec4_name = uniform_prefix + "array[0].struct_dvec4";
6488 std::string uniform_arr1_double_name = uniform_prefix + "array[1].struct_double";
6489 std::string uniform_arr1_dvec2_name = uniform_prefix + "array[1].struct_dvec2";
6490 std::string uniform_arr1_dvec3_name = uniform_prefix + "array[1].struct_dvec3";
6491 std::string uniform_arr1_dvec4_name = uniform_prefix + "array[1].struct_dvec4";
6492
6493 /* Retrieve uniform locations */
6494 stage_data->uniforms.uniform_location_double = gl.getUniformLocation(po_id, uniform_double_name.c_str());
6495 stage_data->uniforms.uniform_location_double_arr[0] =
6496 gl.getUniformLocation(po_id, uniform_double_arr0_name.c_str());
6497 stage_data->uniforms.uniform_location_double_arr[1] =
6498 gl.getUniformLocation(po_id, uniform_double_arr1_name.c_str());
6499 stage_data->uniforms.uniform_location_dvec2 = gl.getUniformLocation(po_id, uniform_dvec2_name.c_str());
6500 stage_data->uniforms.uniform_location_dvec2_arr[0] =
6501 gl.getUniformLocation(po_id, uniform_dvec2_arr0_name.c_str());
6502 stage_data->uniforms.uniform_location_dvec2_arr[1] =
6503 gl.getUniformLocation(po_id, uniform_dvec2_arr1_name.c_str());
6504 stage_data->uniforms.uniform_location_dvec3 = gl.getUniformLocation(po_id, uniform_dvec3_name.c_str());
6505 stage_data->uniforms.uniform_location_dvec3_arr[0] =
6506 gl.getUniformLocation(po_id, uniform_dvec3_arr0_name.c_str());
6507 stage_data->uniforms.uniform_location_dvec3_arr[1] =
6508 gl.getUniformLocation(po_id, uniform_dvec3_arr1_name.c_str());
6509 stage_data->uniforms.uniform_location_dvec4 = gl.getUniformLocation(po_id, uniform_dvec4_name.c_str());
6510 stage_data->uniforms.uniform_location_dvec4_arr[0] =
6511 gl.getUniformLocation(po_id, uniform_dvec4_arr0_name.c_str());
6512 stage_data->uniforms.uniform_location_dvec4_arr[1] =
6513 gl.getUniformLocation(po_id, uniform_dvec4_arr1_name.c_str());
6514 stage_data->uniform_structure_arrays[0].uniform_location_double =
6515 gl.getUniformLocation(po_id, uniform_arr0_double_name.c_str());
6516 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 =
6517 gl.getUniformLocation(po_id, uniform_arr0_dvec2_name.c_str());
6518 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 =
6519 gl.getUniformLocation(po_id, uniform_arr0_dvec3_name.c_str());
6520 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 =
6521 gl.getUniformLocation(po_id, uniform_arr0_dvec4_name.c_str());
6522 stage_data->uniform_structure_arrays[1].uniform_location_double =
6523 gl.getUniformLocation(po_id, uniform_arr1_double_name.c_str());
6524 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 =
6525 gl.getUniformLocation(po_id, uniform_arr1_dvec2_name.c_str());
6526 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 =
6527 gl.getUniformLocation(po_id, uniform_arr1_dvec3_name.c_str());
6528 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 =
6529 gl.getUniformLocation(po_id, uniform_arr1_dvec4_name.c_str());
6530 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
6531
6532 if (stage_data->uniforms.uniform_location_double == -1 ||
6533 stage_data->uniforms.uniform_location_double_arr[0] == -1 ||
6534 stage_data->uniforms.uniform_location_double_arr[1] == -1 ||
6535 stage_data->uniforms.uniform_location_dvec2 == -1 ||
6536 stage_data->uniforms.uniform_location_dvec2_arr[0] == -1 ||
6537 stage_data->uniforms.uniform_location_dvec2_arr[1] == -1 ||
6538 stage_data->uniforms.uniform_location_dvec3 == -1 ||
6539 stage_data->uniforms.uniform_location_dvec3_arr[0] == -1 ||
6540 stage_data->uniforms.uniform_location_dvec3_arr[1] == -1 ||
6541 stage_data->uniforms.uniform_location_dvec4 == -1 ||
6542 stage_data->uniforms.uniform_location_dvec4_arr[0] == -1 ||
6543 stage_data->uniforms.uniform_location_dvec4_arr[1] == -1 ||
6544 stage_data->uniform_structure_arrays[0].uniform_location_double == -1 ||
6545 stage_data->uniform_structure_arrays[0].uniform_location_dvec2 == -1 ||
6546 stage_data->uniform_structure_arrays[0].uniform_location_dvec3 == -1 ||
6547 stage_data->uniform_structure_arrays[0].uniform_location_dvec4 == -1 ||
6548 stage_data->uniform_structure_arrays[1].uniform_location_double == -1 ||
6549 stage_data->uniform_structure_arrays[1].uniform_location_dvec2 == -1 ||
6550 stage_data->uniform_structure_arrays[1].uniform_location_dvec3 == -1 ||
6551 stage_data->uniform_structure_arrays[1].uniform_location_dvec4 == -1)
6552 {
6553 TCU_FAIL("At least one uniform is considered inactive which is invalid.");
6554 }
6555
6556 /* Make sure locations of subsequent items in array uniforms are correct */
6557 if (stage_data->uniforms.uniform_location_double_arr[1] !=
6558 (stage_data->uniforms.uniform_location_double_arr[0] + 1) ||
6559 stage_data->uniforms.uniform_location_dvec2_arr[1] !=
6560 (stage_data->uniforms.uniform_location_dvec2_arr[0] + 1) ||
6561 stage_data->uniforms.uniform_location_dvec3_arr[1] !=
6562 (stage_data->uniforms.uniform_location_dvec3_arr[0] + 1) ||
6563 stage_data->uniforms.uniform_location_dvec4_arr[1] !=
6564 (stage_data->uniforms.uniform_location_dvec4_arr[0] + 1))
6565 {
6566 m_testCtx.getLog() << tcu::TestLog::Message << "Uniform locations:"
6567 " double_arr[0]:"
6568 << stage_data->uniforms.uniform_location_double_arr[0]
6569 << " double_arr[1]:" << stage_data->uniforms.uniform_location_double_arr[1]
6570 << " dvec2_arr[0]:" << stage_data->uniforms.uniform_location_dvec2_arr[0]
6571 << " dvec2_arr[1]:" << stage_data->uniforms.uniform_location_dvec2_arr[1]
6572 << " dvec3_arr[0]:" << stage_data->uniforms.uniform_location_dvec3_arr[0]
6573 << " dvec3_arr[1]:" << stage_data->uniforms.uniform_location_dvec3_arr[1]
6574 << " dvec4_arr[0]:" << stage_data->uniforms.uniform_location_dvec4_arr[0]
6575 << " dvec4_arr[1]:" << stage_data->uniforms.uniform_location_dvec4_arr[1]
6576 << tcu::TestLog::EndMessage;
6577
6578 TCU_FAIL("Double-precision uniform array item locations are invalid.");
6579 }
6580 } /* for (all uniform prefixes) */
6581 } /* for (both program objects) */
6582 }
6583
6584 /** Initializes all objects required to run the test. */
initTest()6585 void GPUShaderFP64Test4::initTest()
6586 {
6587 initProgramObjects();
6588
6589 generateUniformValues();
6590 initUniformValues();
6591 }
6592
6593 /** Assigns values generated by generateUniformValues() to uniforms defined by
6594 * both program objects.
6595 **/
initUniformValues()6596 void GPUShaderFP64Test4::initUniformValues()
6597 {
6598 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6599
6600 /* Iterate through all programs */
6601 _stage_data* cs_stages[] = { &m_data_cs };
6602 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6603 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6604 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6605
6606 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6607 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6608
6609 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6610 {
6611 glw::GLuint po_id = programs[n_program];
6612 unsigned int n_stages = 0;
6613 _stage_data** stage_data = DE_NULL;
6614
6615 if (po_id == m_po_cs_id)
6616 {
6617 n_stages = n_cs_stages;
6618 stage_data = cs_stages;
6619 }
6620 else
6621 {
6622 n_stages = n_noncs_stages;
6623 stage_data = noncs_stages;
6624 }
6625
6626 /* Skip compute shader program if not supported */
6627 if (0 == po_id)
6628 {
6629 continue;
6630 }
6631
6632 gl.useProgram(po_id);
6633 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
6634
6635 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6636 {
6637 /* Iterate through all uniforms */
6638 _stage_data* stage_ptr = stage_data[n_stage];
6639
6640 gl.uniform1d(stage_ptr->uniforms.uniform_location_double, stage_ptr->uniforms.uniform_double);
6641 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[0], stage_ptr->uniforms.uniform_double_arr[0]);
6642 gl.uniform1d(stage_ptr->uniforms.uniform_location_double_arr[1], stage_ptr->uniforms.uniform_double_arr[1]);
6643 gl.uniform1d(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6644 stage_ptr->uniform_structure_arrays[0].uniform_double);
6645 gl.uniform1d(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6646 stage_ptr->uniform_structure_arrays[1].uniform_double);
6647 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform1d() call(s) failed.");
6648
6649 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2, 1 /* count */, stage_ptr->uniforms.uniform_dvec2);
6650 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[0], 1 /* count */,
6651 stage_ptr->uniforms.uniform_dvec2_arr + 0);
6652 gl.uniform2dv(stage_ptr->uniforms.uniform_location_dvec2_arr[1], 1 /* count */,
6653 stage_ptr->uniforms.uniform_dvec2_arr + 2);
6654 gl.uniform2dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2, 1 /* count */,
6655 stage_ptr->uniform_structure_arrays[0].uniform_dvec2);
6656 gl.uniform2dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2, 1 /* count */,
6657 stage_ptr->uniform_structure_arrays[1].uniform_dvec2);
6658 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform2dv() call(s) failed.");
6659
6660 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3, 1 /* count */, stage_ptr->uniforms.uniform_dvec3);
6661 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[0], 1 /* count */,
6662 stage_ptr->uniforms.uniform_dvec3_arr + 0);
6663 gl.uniform3dv(stage_ptr->uniforms.uniform_location_dvec3_arr[1], 1 /* count */,
6664 stage_ptr->uniforms.uniform_dvec3_arr + 3);
6665 gl.uniform3dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3, 1 /* count */,
6666 stage_ptr->uniform_structure_arrays[0].uniform_dvec3);
6667 gl.uniform3dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3, 1 /* count */,
6668 stage_ptr->uniform_structure_arrays[1].uniform_dvec3);
6669 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform3dv() call(s) failed.");
6670
6671 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4, 1 /* count */, stage_ptr->uniforms.uniform_dvec4);
6672 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[0], 1 /* count */,
6673 stage_ptr->uniforms.uniform_dvec4_arr + 0);
6674 gl.uniform4dv(stage_ptr->uniforms.uniform_location_dvec4_arr[1], 1 /* count */,
6675 stage_ptr->uniforms.uniform_dvec4_arr + 4);
6676 gl.uniform4dv(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4, 1 /* count */,
6677 stage_ptr->uniform_structure_arrays[0].uniform_dvec4);
6678 gl.uniform4dv(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4, 1 /* count */,
6679 stage_ptr->uniform_structure_arrays[1].uniform_dvec4);
6680 GLU_EXPECT_NO_ERROR(gl.getError(), "gluniform4dv() call(s) failed.");
6681 } /* for (all shader stages) */
6682 } /* for (both program objects) */
6683 }
6684
6685 /** Executes test iteration.
6686 *
6687 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
6688 */
iterate()6689 tcu::TestNode::IterateResult GPUShaderFP64Test4::iterate()
6690 {
6691 /* This test does not verify GL_ARB_gpu_shader_fp64 support on purpose */
6692
6693 /* Initialize all objects required to run the test */
6694 initTest();
6695
6696 /* Verify the implementation reports correct values for all stages we've configured */
6697 m_has_test_passed &= verifyUniformValues();
6698
6699 /* Is this also the case when "program interface query" mechanism is used? */
6700 if (m_context.getContextInfo().isExtensionSupported("GL_ARB_program_interface_query"))
6701 {
6702 m_has_test_passed &= verifyProgramInterfaceQuerySupport();
6703 }
6704
6705 /* We're done */
6706 if (m_has_test_passed)
6707 {
6708 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6709 }
6710 else
6711 {
6712 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6713 }
6714
6715 return STOP;
6716 }
6717
6718 /** Verifies that:
6719 *
6720 * a) glGetProgramResourceIndex()
6721 * b) glGetProgramResourceiv()
6722 * c) glGetProgramResourceName()
6723 *
6724 * functions return correct values for double-precision uniforms.
6725 *
6726 * @return true if the verification was passed, false otherwise.
6727 */
verifyProgramInterfaceQuerySupport()6728 bool GPUShaderFP64Test4::verifyProgramInterfaceQuerySupport()
6729 {
6730 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6731 bool result = true;
6732
6733 /* Iterate through all programs */
6734 const char* cs_prefixes[] = { "cs_" };
6735 _stage_data* cs_stages[] = { &m_data_cs };
6736 const char* noncs_prefixes[] = { "fs_", "gs_", "tc_", "te_", "vs_" };
6737 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6738 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6739 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6740
6741 const glw::GLuint programs[] = { m_po_cs_id, m_po_noncs_id };
6742 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6743
6744 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6745 {
6746 glw::GLuint po_id = programs[n_program];
6747 unsigned int n_stages = 0;
6748 const char** stage_prefixes = DE_NULL;
6749 _stage_data** stage_data = DE_NULL;
6750
6751 if (po_id == m_po_cs_id)
6752 {
6753 n_stages = n_cs_stages;
6754 stage_data = cs_stages;
6755 stage_prefixes = cs_prefixes;
6756 }
6757 else
6758 {
6759 n_stages = n_noncs_stages;
6760 stage_data = noncs_stages;
6761 stage_prefixes = noncs_prefixes;
6762 }
6763
6764 /* Skip compute shader program if not supported */
6765 if (0 == po_id)
6766 {
6767 continue;
6768 }
6769
6770 /* Determine maximum uniform name length */
6771 glw::GLint max_uniform_name_length = 0;
6772
6773 gl.getProgramInterfaceiv(po_id, GL_UNIFORM, GL_MAX_NAME_LENGTH, &max_uniform_name_length);
6774 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInterfaceiv() call failed.");
6775
6776 /* Allocate a buffer we will use to hold uniform names */
6777 m_uniform_name_buffer = new char[max_uniform_name_length];
6778
6779 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6780 {
6781 /* Iterate through all uniforms */
6782 _stage_data* stage_ptr = stage_data[n_stage];
6783 const char* stage_prefix = stage_prefixes[n_stage];
6784
6785 /* Construct an array that will be used to run the test in an automated manner */
6786 _program_interface_query_test_item uniforms[] = {
6787 /* array size */ /* name */ /* type */ /* location */
6788 { 1, "double", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double },
6789 { 2, "double_arr[0]", GL_DOUBLE, stage_ptr->uniforms.uniform_location_double_arr[0] },
6790 { 1, "dvec2", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2 },
6791 { 2, "dvec2_arr[0]", GL_DOUBLE_VEC2, stage_ptr->uniforms.uniform_location_dvec2_arr[0] },
6792 { 1, "dvec3", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3 },
6793 { 2, "dvec3_arr[0]", GL_DOUBLE_VEC3, stage_ptr->uniforms.uniform_location_dvec3_arr[0] },
6794 { 1, "dvec4", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4 },
6795 { 2, "dvec4_arr[0]", GL_DOUBLE_VEC4, stage_ptr->uniforms.uniform_location_dvec4_arr[0] },
6796 { 1, "array[0].struct_double", GL_DOUBLE,
6797 stage_ptr->uniform_structure_arrays->uniform_location_double },
6798 { 1, "array[0].struct_dvec2", GL_DOUBLE_VEC2,
6799 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6800 { 1, "array[0].struct_dvec3", GL_DOUBLE_VEC3,
6801 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6802 { 1, "array[0].struct_dvec4", GL_DOUBLE_VEC4,
6803 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6804 { 1, "array[1].struct_double", GL_DOUBLE,
6805 stage_ptr->uniform_structure_arrays->uniform_location_double },
6806 { 1, "array[1].struct_dvec2", GL_DOUBLE_VEC2,
6807 stage_ptr->uniform_structure_arrays->uniform_location_dvec2 },
6808 { 1, "array[1].struct_dvec3", GL_DOUBLE_VEC3,
6809 stage_ptr->uniform_structure_arrays->uniform_location_dvec3 },
6810 { 1, "array[1].struct_dvec4", GL_DOUBLE_VEC4,
6811 stage_ptr->uniform_structure_arrays->uniform_location_dvec4 },
6812 };
6813 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
6814
6815 /* Prefix the names with stage-specific string */
6816 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6817 {
6818 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6819
6820 current_item.name = std::string(stage_prefix) + current_item.name;
6821 } /* for (all uniform descriptors) */
6822
6823 const glw::GLenum properties[] = { GL_ARRAY_SIZE, GL_TYPE };
6824 const unsigned int n_properties = sizeof(properties) / sizeof(properties[0]);
6825
6826 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
6827 {
6828 _program_interface_query_test_item& current_item = uniforms[n_uniform];
6829 glw::GLint n_written_items = 0;
6830 glw::GLint retrieved_array_size = 0;
6831 glw::GLint retrieved_name_length = 0;
6832 glw::GLenum retrieved_type = GL_NONE;
6833 glw::GLint temp_buffer[2] = { 0, GL_NONE };
6834
6835 /* Retrieve index of the iteration-specific uniform */
6836 glw::GLuint resource_index = gl.getProgramResourceIndex(po_id, GL_UNIFORM, current_item.name.c_str());
6837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceIndex() call failed.");
6838
6839 /* Make sure glGetProgramResourceName() returns correct values */
6840 memset(m_uniform_name_buffer, 0, max_uniform_name_length);
6841
6842 gl.getProgramResourceName(po_id, GL_UNIFORM, /* interface */
6843 resource_index, max_uniform_name_length, &retrieved_name_length,
6844 m_uniform_name_buffer);
6845 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceName() call failed.");
6846
6847 if (current_item.name.length() != (glw::GLuint)retrieved_name_length ||
6848 memcmp(m_uniform_name_buffer, current_item.name.c_str(), retrieved_name_length) != 0)
6849 {
6850 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid uniform name was reported at index ["
6851 << resource_index << "]"
6852 ": expected:["
6853 << current_item.name << "]"
6854 ", reported:["
6855 << m_uniform_name_buffer << "]" << tcu::TestLog::EndMessage;
6856
6857 result = false;
6858 continue;
6859 }
6860
6861 /* Make sure glGetProgramResourceiv() returns correct values for GL_TYPE and GL_ARRAY_SIZE queries */
6862 gl.getProgramResourceiv(po_id, GL_UNIFORM, /* interface */
6863 resource_index, n_properties, properties,
6864 sizeof(temp_buffer) / sizeof(temp_buffer[0]), &n_written_items, temp_buffer);
6865 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramResourceiv() call failed.");
6866
6867 if (n_written_items != n_properties)
6868 {
6869 TCU_FAIL("Invalid amount of items were reported by glGetProgramResourceiv() call.");
6870 }
6871
6872 /* For clarity, copy the retrieved values to separate variables */
6873 retrieved_array_size = temp_buffer[0];
6874 retrieved_type = temp_buffer[1];
6875
6876 /* Verify the values */
6877 if (retrieved_array_size != current_item.expected_array_size)
6878 {
6879 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid array size reported for uniform ["
6880 << current_item.name << "]"
6881 << ": expected:[" << current_item.expected_array_size << "]"
6882 ", reported:["
6883 << retrieved_array_size << "]" << tcu::TestLog::EndMessage;
6884
6885 result = false;
6886 }
6887
6888 if (retrieved_type != current_item.expected_type)
6889 {
6890 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid type reported for uniform ["
6891 << current_item.name << "]"
6892 << ": expected:[" << current_item.expected_type << "]"
6893 ", reported:["
6894 << retrieved_type << "]" << tcu::TestLog::EndMessage;
6895
6896 result = false;
6897 }
6898 } /* for (all uniforms) */
6899 } /* for (all shader stages) */
6900
6901 /* We're now OK to release the buffer we used to hold uniform names for
6902 * the program */
6903 if (m_uniform_name_buffer != DE_NULL)
6904 {
6905 delete[] m_uniform_name_buffer;
6906
6907 m_uniform_name_buffer = DE_NULL;
6908 }
6909 } /* for (both program objects) */
6910
6911 return result;
6912 }
6913
6914 /** Verifies glGetUniform*() calls return correct values assigned to
6915 * double-precision uniforms.
6916 *
6917 * @return true if all values reported by OpenGL were found to be correct,
6918 * false otherwise.
6919 **/
verifyUniformValues()6920 bool GPUShaderFP64Test4::verifyUniformValues()
6921 {
6922 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6923 bool result = true;
6924
6925 /* Iterate through all programs */
6926 _stage_data* cs_stages[] = { &m_data_cs };
6927 _stage_data* noncs_stages[] = { &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
6928 const unsigned int n_cs_stages = sizeof(cs_stages) / sizeof(cs_stages[0]);
6929 const unsigned int n_noncs_stages = sizeof(noncs_stages) / sizeof(noncs_stages[0]);
6930
6931 const glw::GLuint programs[] = {
6932 m_po_noncs_id, m_po_cs_id,
6933 };
6934 const unsigned int n_programs = sizeof(programs) / sizeof(programs[0]);
6935
6936 /* Set up rounding for the tests */
6937 deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
6938
6939 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6940 {
6941 glw::GLuint po_id = programs[n_program];
6942 unsigned int n_stages = 0;
6943 _stage_data** stage_data = DE_NULL;
6944
6945 if (po_id == m_po_cs_id)
6946 {
6947 n_stages = n_cs_stages;
6948 stage_data = cs_stages;
6949 }
6950 else
6951 {
6952 n_stages = n_noncs_stages;
6953 stage_data = noncs_stages;
6954 }
6955
6956 /* Skip compute shader program if not supported */
6957 if (0 == po_id)
6958 {
6959 continue;
6960 }
6961
6962 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6963 {
6964 /* Iterate through all uniforms */
6965 _stage_data* stage_ptr = stage_data[n_stage];
6966
6967 /* Set up arrays that we will guide the automated testing */
6968 const uniform_value_pair double_uniforms[] = {
6969 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6970 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6971 stage_ptr->uniforms.uniform_double_arr + 0),
6972 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6973 stage_ptr->uniforms.uniform_double_arr + 1),
6974 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6975 &stage_ptr->uniform_structure_arrays[0].uniform_double),
6976 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6977 &stage_ptr->uniform_structure_arrays[1].uniform_double)
6978 };
6979 const uniform_value_pair dvec2_uniforms[] = {
6980 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6981 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6982 stage_ptr->uniforms.uniform_dvec2_arr + 0),
6983 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6984 stage_ptr->uniforms.uniform_dvec2_arr + 2),
6985 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6986 stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6987 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6988 stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6989 };
6990 const uniform_value_pair dvec3_uniforms[] = {
6991 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6992 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6993 stage_ptr->uniforms.uniform_dvec3_arr + 0),
6994 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6995 stage_ptr->uniforms.uniform_dvec3_arr + 3),
6996 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
6997 stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
6998 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
6999 stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7000 };
7001 const uniform_value_pair dvec4_uniforms[] = {
7002 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7003 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7004 stage_ptr->uniforms.uniform_dvec4_arr + 0),
7005 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7006 stage_ptr->uniforms.uniform_dvec4_arr + 4),
7007 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7008 stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7009 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7010 stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7011 };
7012
7013 /* Iterate over all uniforms and verify the values reported by the API */
7014 double returned_double_data[4];
7015 float returned_float_data[4];
7016 int returned_int_data[4];
7017 unsigned int returned_uint_data[4];
7018
7019 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7020 {
7021 const uniform_value_pair* current_uv_pairs = NULL;
7022 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7023 unsigned int n_pairs = 0;
7024
7025 switch (n_type)
7026 {
7027 case 0: /* double */
7028 {
7029 current_uv_pairs = double_uniforms;
7030 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7031
7032 break;
7033 }
7034
7035 case 1: /* dvec2 */
7036 {
7037 current_uv_pairs = dvec2_uniforms;
7038 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7039
7040 break;
7041 }
7042
7043 case 2: /* dvec3 */
7044 {
7045 current_uv_pairs = dvec3_uniforms;
7046 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7047
7048 break;
7049 }
7050
7051 case 3: /* dvec4 */
7052 {
7053 current_uv_pairs = dvec4_uniforms;
7054 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7055
7056 break;
7057 }
7058
7059 default:
7060 {
7061 TCU_FAIL("Invalid type index requested");
7062 }
7063 } /* switch (n_type) */
7064
7065 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7066 {
7067 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair];
7068 glw::GLint uniform_location = current_uv_pair.first;
7069 const double* uniform_value = current_uv_pair.second;
7070
7071 /* Retrieve the values from the GL implementation*/
7072 gl.getUniformdv(po_id, uniform_location, returned_double_data);
7073 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7074
7075 gl.getUniformfv(po_id, uniform_location, returned_float_data);
7076 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7077
7078 gl.getUniformiv(po_id, uniform_location, returned_int_data);
7079 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7080
7081 gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7082 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7083
7084 /* Make sure the values reported match the reference values */
7085 bool can_continue = true;
7086 const float epsilon = 1e-5f;
7087
7088 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7089 {
7090 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7091 {
7092 m_testCtx.getLog()
7093 << tcu::TestLog::Message
7094 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7095 << uniform_location << "]"
7096 " and component ["
7097 << n_component << "]"
7098 ": retrieved:["
7099 << returned_double_data[n_component] << "]"
7100 ", expected:["
7101 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7102
7103 result = false;
7104 }
7105
7106 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7107 {
7108 m_testCtx.getLog()
7109 << tcu::TestLog::Message
7110 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7111 << uniform_location << "]"
7112 " and component ["
7113 << n_component << "]"
7114 ": retrieved:["
7115 << returned_float_data[n_component] << "]"
7116 ", expected:["
7117 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7118
7119 result = false;
7120 }
7121
7122 /* ints */
7123 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7124 unsigned int rounded_uniform_value_uint =
7125 (unsigned int)(uniform_value[n_component] > 0.0) ?
7126 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7127 0;
7128
7129 if (returned_int_data[n_component] != rounded_uniform_value_sint)
7130 {
7131 m_testCtx.getLog()
7132 << tcu::TestLog::Message
7133 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7134 << uniform_location << "]"
7135 " and component ["
7136 << n_component << "]"
7137 ": retrieved:["
7138 << returned_int_data[n_component] << "]"
7139 ", expected:["
7140 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7141
7142 result = false;
7143 }
7144
7145 if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7146 {
7147 m_testCtx.getLog()
7148 << tcu::TestLog::Message
7149 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7150 << uniform_location << "]"
7151 " and component ["
7152 << n_component << "]"
7153 ": retrieved:["
7154 << returned_uint_data[n_component] << "]"
7155 ", expected:["
7156 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7157
7158 result = false;
7159 }
7160 } /* for (all components) */
7161 } /* for (all uniform+value pairs) */
7162 } /* for (all 4 uniform types) */
7163 } /* for (all shader stages) */
7164 } /* for (both program objects) */
7165
7166 /* All done! */
7167 return result;
7168 }
7169
7170 /** Constructor
7171 *
7172 * @param context Rendering context.
7173 */
GPUShaderFP64Test5(deqp::Context & context)7174 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7175 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7176 " floating-point variables work correctly")
7177 , m_base_value_bo_data(DE_NULL)
7178 , m_base_value_bo_id(0)
7179 , m_has_test_passed(true)
7180 , m_po_base_value_attribute_location(-1)
7181 , m_po_id(0)
7182 , m_vao_id(0)
7183 , m_vs_id(0)
7184 , m_xfb_bo_id(0)
7185 , m_xfb_bo_size(0)
7186 {
7187 /* Set up base value array (as per test spec) */
7188 m_base_values[0] = -25.12065f;
7189 m_base_values[1] = 0.0f;
7190 m_base_values[2] = 0.001f;
7191 m_base_values[3] = 1.0f;
7192 m_base_values[4] = 256.78901f;
7193
7194 /* Set up swizzle matrix */
7195 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7196 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7197 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7198 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7199 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7200 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7201 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7202 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7203 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7204 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7205 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7206 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7207 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7208 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7209 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7210 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7211 }
7212
deinit()7213 void GPUShaderFP64Test5::deinit()
7214 {
7215 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7216
7217 if (m_base_value_bo_data != DE_NULL)
7218 {
7219 delete[] m_base_value_bo_data;
7220
7221 m_base_value_bo_data = DE_NULL;
7222 }
7223
7224 if (m_base_value_bo_id != 0)
7225 {
7226 gl.deleteBuffers(1, &m_base_value_bo_id);
7227
7228 m_base_value_bo_id = 0;
7229 }
7230
7231 if (m_vao_id != 0)
7232 {
7233 gl.deleteVertexArrays(1, &m_vao_id);
7234
7235 m_vao_id = 0;
7236 }
7237
7238 if (m_xfb_bo_id != 0)
7239 {
7240 gl.deleteBuffers(1, &m_xfb_bo_id);
7241
7242 m_xfb_bo_id = 0;
7243 }
7244
7245 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7246 * take care of it here
7247 */
7248 deinitInteration();
7249 }
7250
7251 /** Deinitializes all buffers and GL objects that may have been generated
7252 * during test execution.
7253 **/
deinitInteration()7254 void GPUShaderFP64Test5::deinitInteration()
7255 {
7256 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7257
7258 if (m_po_id != 0)
7259 {
7260 gl.deleteProgram(m_po_id);
7261
7262 m_po_id = 0;
7263 }
7264
7265 if (m_vs_id != 0)
7266 {
7267 gl.deleteShader(m_vs_id);
7268
7269 m_vs_id = 0;
7270 }
7271 }
7272
7273 /** Executes a single test case iteration using user-provided test case descriptor.
7274 *
7275 * This function may throw a TestError exception if GL implementation misbehaves.
7276 *
7277 * @param test_case Test case descriptor to use.
7278 *
7279 * @return true if the values returned by GL implementation were found to be valid,
7280 * false otherwise.
7281 **/
executeIteration(const _test_case & test_case)7282 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7283 {
7284 bool result = true;
7285
7286 /* Convert the base values array to the type of input attribute we'll be using
7287 * for the iteration.
7288 */
7289 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7290
7291 if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7292 {
7293 /* bools are actually represented by ints, since bool varyings are not allowed */
7294 base_value_type = Utils::VARIABLE_TYPE_INT;
7295 }
7296
7297 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7298 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7299
7300 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7301
7302 unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7303
7304 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7305 {
7306 switch (base_value_type)
7307 {
7308 case Utils::VARIABLE_TYPE_DOUBLE:
7309 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7310 break;
7311 case Utils::VARIABLE_TYPE_FLOAT:
7312 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7313 break;
7314 case Utils::VARIABLE_TYPE_INT:
7315 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7316 break;
7317 case Utils::VARIABLE_TYPE_UINT:
7318 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7319 break;
7320
7321 default:
7322 {
7323 TCU_FAIL("Unrecognized base value type");
7324 }
7325 }
7326
7327 base_value_traveller_ptr += base_value_component_size;
7328 } /* for (all base values) */
7329
7330 /* Update buffer object storage with the data we've just finished preparing. */
7331 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7332
7333 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7334 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7335
7336 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7337 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7338
7339 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7340 * new data is interpreted correctly.
7341 */
7342 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7343 {
7344 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */
7345 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7346 0, /* stride */
7347 DE_NULL); /* pointer */
7348 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7349 }
7350 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7351 {
7352 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */
7353 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7354 DE_NULL); /* pointer */
7355 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7356 }
7357 else
7358 {
7359 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7360
7361 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7362 GL_DOUBLE, 0, /* stride */
7363 DE_NULL); /* pointer */
7364 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7365 }
7366
7367 gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7368 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7369
7370 /* Execute the draw call */
7371 gl.useProgram(m_po_id);
7372 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7373
7374 gl.beginTransformFeedback(GL_POINTS);
7375 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7376 {
7377 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7379 }
7380 gl.endTransformFeedback();
7381 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7382
7383 /* Map the XFB buffer object into process space */
7384 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7385
7386 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7387 DE_ASSERT(xfb_data_ptr != NULL);
7388
7389 /* Verify the data */
7390 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7391
7392 /* Unmap the XFB BO */
7393 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7394 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7395
7396 /** Good to release the data buffer at this point */
7397 if (m_base_value_bo_data != DE_NULL)
7398 {
7399 delete[] m_base_value_bo_data;
7400
7401 m_base_value_bo_data = DE_NULL;
7402 }
7403
7404 /* All done */
7405 return result;
7406 }
7407
7408 /** Returns properties of a swizzle operator described by @param type swizzle type.
7409 *
7410 * @param out_swizzle_string Deref will be used to store a GLSL literal
7411 * corresponding to the specific swizzle operator.
7412 * Must not be NULL.
7413 * @param out_n_components Deref will be used to store the amount of components
7414 * used by the operator. Must not be NULL.
7415 * @param out_component_order Deref will be used to store up to 4 integer values,
7416 * corresponding to component indices described by the
7417 * operator for a particular position. Must not be NULL.
7418 **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7419 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7420 unsigned int* out_n_components, unsigned int* out_component_order)
7421 {
7422 unsigned int result_component_order[4] = { 0 };
7423 unsigned int result_n_components = 0;
7424 std::string result_swizzle_string;
7425
7426 switch (type)
7427 {
7428 case SWIZZLE_TYPE_NONE:
7429 {
7430 result_swizzle_string = "";
7431 result_n_components = 0;
7432
7433 break;
7434 }
7435
7436 case SWIZZLE_TYPE_XWZY:
7437 {
7438 result_swizzle_string = "xwzy";
7439 result_n_components = 4;
7440 result_component_order[0] = 0;
7441 result_component_order[1] = 3;
7442 result_component_order[2] = 2;
7443 result_component_order[3] = 1;
7444
7445 break;
7446 }
7447
7448 case SWIZZLE_TYPE_XZXY:
7449 {
7450 result_swizzle_string = "xzxy";
7451 result_n_components = 4;
7452 result_component_order[0] = 0;
7453 result_component_order[1] = 2;
7454 result_component_order[2] = 0;
7455 result_component_order[3] = 1;
7456
7457 break;
7458 }
7459
7460 case SWIZZLE_TYPE_XZY:
7461 {
7462 result_swizzle_string = "xzy";
7463 result_n_components = 3;
7464 result_component_order[0] = 0;
7465 result_component_order[1] = 2;
7466 result_component_order[2] = 1;
7467
7468 break;
7469 }
7470
7471 case SWIZZLE_TYPE_XZYW:
7472 {
7473 result_swizzle_string = "xzyw";
7474 result_n_components = 4;
7475 result_component_order[0] = 0;
7476 result_component_order[1] = 2;
7477 result_component_order[2] = 1;
7478 result_component_order[3] = 3;
7479
7480 break;
7481 }
7482
7483 case SWIZZLE_TYPE_Y:
7484 {
7485 result_swizzle_string = "y";
7486 result_n_components = 1;
7487 result_component_order[0] = 1;
7488
7489 break;
7490 }
7491
7492 case SWIZZLE_TYPE_YX:
7493 {
7494 result_swizzle_string = "yx";
7495 result_n_components = 2;
7496 result_component_order[0] = 1;
7497 result_component_order[1] = 0;
7498
7499 break;
7500 }
7501
7502 case SWIZZLE_TYPE_YXX:
7503 {
7504 result_swizzle_string = "yxx";
7505 result_n_components = 3;
7506 result_component_order[0] = 1;
7507 result_component_order[1] = 0;
7508 result_component_order[2] = 0;
7509
7510 break;
7511 }
7512
7513 case SWIZZLE_TYPE_YXXY:
7514 {
7515 result_swizzle_string = "yxxy";
7516 result_n_components = 4;
7517 result_component_order[0] = 1;
7518 result_component_order[1] = 0;
7519 result_component_order[2] = 0;
7520 result_component_order[3] = 1;
7521
7522 break;
7523 }
7524
7525 case SWIZZLE_TYPE_Z:
7526 {
7527 result_swizzle_string = "z";
7528 result_n_components = 1;
7529 result_component_order[0] = 2;
7530
7531 break;
7532 }
7533
7534 case SWIZZLE_TYPE_ZY:
7535 {
7536 result_swizzle_string = "zy";
7537 result_n_components = 2;
7538 result_component_order[0] = 2;
7539 result_component_order[1] = 1;
7540
7541 break;
7542 }
7543
7544 case SWIZZLE_TYPE_W:
7545 {
7546 result_swizzle_string = "w";
7547 result_n_components = 1;
7548 result_component_order[0] = 3;
7549
7550 break;
7551 }
7552
7553 case SWIZZLE_TYPE_WX:
7554 {
7555 result_swizzle_string = "wx";
7556 result_n_components = 2;
7557 result_component_order[0] = 3;
7558 result_component_order[1] = 0;
7559
7560 break;
7561 }
7562
7563 default:
7564 {
7565 TCU_FAIL("Unrecognized swizzle type");
7566 }
7567 } /* switch (type) */
7568
7569 if (out_swizzle_string != DE_NULL)
7570 {
7571 *out_swizzle_string = result_swizzle_string;
7572 }
7573
7574 if (out_n_components != DE_NULL)
7575 {
7576 *out_n_components = result_n_components;
7577 }
7578
7579 if (out_component_order != DE_NULL)
7580 {
7581 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7582 }
7583 }
7584
7585 /** Returns body of a vertex shader that should be used for particular test case,
7586 * given user-specified test case descriptor.
7587 *
7588 * @param test_case Descriptor to use for the query.
7589 *
7590 * @return Requested data.
7591 **/
getVertexShaderBody(const _test_case & test_case)7592 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7593 {
7594 std::stringstream result;
7595 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7596 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type);
7597 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7598 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7599 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type);
7600
7601 /* Add version preamble */
7602 result << "#version 420\n"
7603 "\n";
7604
7605 /* Declare output variables. Note that boolean output variables are not supported, so we need
7606 * to handle that special case correctly */
7607 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7608 {
7609 result << "out int result;\n";
7610 }
7611 else
7612 {
7613 result << "out " << dst_type_string << " result;\n";
7614 }
7615
7616 /* Declare input variables. Handle the bool case exclusively. */
7617 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7618 {
7619 /* Use ints for bools. We will cast them to bool in the code later. */
7620 result << "in int base_value;\n";
7621 }
7622 else
7623 {
7624 result << "in " << base_type_string << " base_value;\n";
7625 }
7626
7627 /* Declare main() and construct the value we will be casting from.
7628 *
7629 * Note: Addition operations on bool values cause an implicit conversion to int
7630 * which is not allowed. Hence, we skip these operations for this special
7631 * case.
7632 */
7633 result << "void main()\n"
7634 "{\n"
7635 << src_type_string << " lside_value = ";
7636
7637 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7638 {
7639 result << src_type_string << "(0 != ";
7640 }
7641 else
7642 {
7643 result << src_type_string << "(";
7644 }
7645
7646 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7647 {
7648 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7649 {
7650 result << "base_value + " << n_component;
7651
7652 if (n_component != (n_src_components - 1))
7653 {
7654 result << ", ";
7655 }
7656 } /* for (all components) */
7657 }
7658 else
7659 {
7660 DE_ASSERT(n_src_components == 1);
7661
7662 result << "base_value";
7663 }
7664
7665 result << ");\n";
7666
7667 /* Perform the casting operation. Add swizzle operator if possible. */
7668 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7669 {
7670 /* Handle the bool case exclusively */
7671 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7672 {
7673 result << "result = (bool(lside_value) == false) ? 0 : 1";
7674 }
7675 else
7676 {
7677 result << "result = (lside_value == false) ? 0 : 1";
7678 }
7679 }
7680 else
7681 {
7682 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7683 {
7684 result << "result = " << dst_type_string << "(lside_value)";
7685 }
7686 else
7687 {
7688 result << "result = lside_value";
7689 }
7690 }
7691
7692 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7693 {
7694 /* Add a swizzle operator */
7695 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7696 DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7697
7698 unsigned int swizzle_component_order[4] = { 0 };
7699 unsigned int swizzle_n_components = 0;
7700 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7701 std::string swizzle_string;
7702
7703 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7704
7705 if (swizzle_n_components > 0)
7706 {
7707 result << "." << swizzle_string;
7708 }
7709 }
7710
7711 /* Close the shader implementation. */
7712 result << ";\n"
7713 "}\n";
7714
7715 return result.str();
7716 }
7717
7718 /** Initializes program & shader objects needed to run the iteration, given
7719 * user-specified test case descriptor.
7720 *
7721 * This function can throw a TestError exception if a GL error is detected
7722 * during execution.
7723 *
7724 * @param test_case Descriptor to use for the iteration.
7725 **/
initIteration(_test_case & test_case)7726 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7727 {
7728 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7729
7730 /* Create program & shader objects */
7731 m_po_id = gl.createProgram();
7732 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7733
7734 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7735 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7736
7737 /* Configure shader body */
7738 std::string body = getVertexShaderBody(test_case);
7739 const char* body_raw_ptr = body.c_str();
7740
7741 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7742 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7743
7744 /* Store it in the test case descriptor for logging purposes */
7745 test_case.shader_body = body;
7746
7747 /* Compile the shader */
7748 glw::GLint compile_status = GL_FALSE;
7749
7750 gl.compileShader(m_vs_id);
7751 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7752
7753 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7754 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7755
7756 if (compile_status != GL_TRUE)
7757 {
7758 TCU_FAIL("Shader compilation failed");
7759 }
7760
7761 /* Attach the shader to the program obejct */
7762 gl.attachShader(m_po_id, m_vs_id);
7763 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7764
7765 /* Configure XFB for the program object */
7766 const char* xfb_varying_name = "result";
7767
7768 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7769 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7770
7771 /* Link the program object */
7772 glw::GLint link_status = GL_FALSE;
7773
7774 gl.linkProgram(m_po_id);
7775 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7776
7777 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7778 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7779
7780 if (link_status != GL_TRUE)
7781 {
7782 TCU_FAIL("Program linking failed");
7783 }
7784
7785 /* Retrieve attribute locations */
7786 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7787 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7788
7789 if (m_po_base_value_attribute_location == -1)
7790 {
7791 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7792 }
7793 }
7794
7795 /** Initializes GL objects used by all test cases.
7796 *
7797 * This function may throw a TestError exception if GL implementation reports
7798 * an error at any point.
7799 **/
initTest()7800 void GPUShaderFP64Test5::initTest()
7801 {
7802 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7803
7804 /* Generate buffer object IDs */
7805 gl.genBuffers(1, &m_base_value_bo_id);
7806 gl.genBuffers(1, &m_xfb_bo_id);
7807 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7808
7809 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7810 * will never eat up more than 1 double (as per test spec) and we will be drawing
7811 * as many points in a single draw call as there are defined in m_base_values array.
7812 */
7813 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7814
7815 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7816 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7817
7818 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7819 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7820
7821 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7822 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7823 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7824 */
7825 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7826
7827 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7828 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7829
7830 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7831 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7832
7833 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7834 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7835
7836 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7837 m_xfb_bo_size = xfb_bo_size;
7838
7839 /* Generate a vertex array object we will need to use for the draw calls */
7840 gl.genVertexArrays(1, &m_vao_id);
7841 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7842
7843 gl.bindVertexArray(m_vao_id);
7844 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7845 }
7846
7847 /** Executes test iteration.
7848 *
7849 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7850 */
iterate()7851 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7852 {
7853 /* Do not execute the test if GL_ARB_texture_view is not supported */
7854 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7855 {
7856 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7857 }
7858
7859 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7860 {
7861 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7862 }
7863
7864 /* Initialize GL objects needed to run the tests */
7865 initTest();
7866
7867 /* Build iteration array to run the tests in an automated manner */
7868 _test_case test_cases[] = {
7869 /* test case type */ /* source type */ /* destination type */
7870 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7871 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7872 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7873 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7874 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7875 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7876 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7877 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7878 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7879 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7880 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7881 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7882 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7883 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7884 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7885 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7886 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7887 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7888 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7889 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7890 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7891
7892 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7893 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7894 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7895 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7896 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7897 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7898 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7899 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7900 };
7901 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7902
7903 /* Execute all iterations */
7904 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7905 {
7906 _test_case& test_case = test_cases[n_test_case];
7907
7908 /* Initialize a program object we will use to perform the casting */
7909 initIteration(test_case);
7910
7911 /* Use the program object to XFB the results */
7912 m_has_test_passed &= executeIteration(test_case);
7913
7914 /* Release the GL Resource for this sub test */
7915 deinitInteration();
7916
7917 } /* for (all test cases) */
7918 /* We're done */
7919 if (m_has_test_passed)
7920 {
7921 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7922 }
7923 else
7924 {
7925 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7926 }
7927
7928 return STOP;
7929 }
7930
7931 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7932 * for which the data have been generated.
7933 *
7934 * @param data_ptr Buffer holding the data XFBed out by the shader.
7935 * @param test_case Descriptor of the test case, for which the vertex shader was
7936 * generated.
7937 *
7938 * @return true if the data were found to be valid, false otherwise.
7939 **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7940 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7941 {
7942 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
7943 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
7944 const float epsilon = 1e-5f;
7945 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7946 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7947 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7948 bool result = true;
7949 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE;
7950 unsigned int swizzle_order[4] = { 0 };
7951 const unsigned char* traveller_ptr = data_ptr;
7952
7953 if (!Utils::isMatrixVariableType(test_case.src_type))
7954 {
7955 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7956 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7957
7958 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7959
7960 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7961 DE_NULL, /* out_n_components */
7962 swizzle_order);
7963 }
7964
7965 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7966 {
7967 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7968 {
7969 unsigned int n_swizzled_component = n_result_component;
7970
7971 if (swizzle_operator != SWIZZLE_TYPE_NONE)
7972 {
7973 n_swizzled_component =
7974 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7975 }
7976
7977 switch (base_dst_type)
7978 {
7979 case Utils::VARIABLE_TYPE_BOOL:
7980 case Utils::VARIABLE_TYPE_INT:
7981 {
7982 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7983 double expected_value = ref_expected_value;
7984 int result_value = *((int*)traveller_ptr);
7985
7986 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7987 {
7988 if (expected_value != 0.0)
7989 {
7990 expected_value = 1.0;
7991 }
7992 }
7993
7994 if (result_value != (int)expected_value)
7995 {
7996 m_testCtx.getLog() << tcu::TestLog::Message
7997 << "Invalid boolean/integer value obtained when doing an "
7998 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
7999 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8000 << "]"
8001 ", component index: ["
8002 << n_swizzled_component << "]"
8003 ", value: ["
8004 << ref_expected_value << "]"
8005 " to GLSL type ["
8006 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8007 ", retrieved value: ["
8008 << result_value << "]"
8009 ", expected value: ["
8010 << (int)expected_value << "]"
8011 ", shader used:\n"
8012 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8013
8014 result = false;
8015 }
8016
8017 traveller_ptr += sizeof(int);
8018 break;
8019 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8020
8021 case Utils::VARIABLE_TYPE_DOUBLE:
8022 {
8023 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8024 double expected_value = ref_expected_value;
8025 double result_value = *((double*)traveller_ptr);
8026
8027 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8028 {
8029 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8030 }
8031 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8032 {
8033 expected_value = (int)expected_value;
8034 }
8035 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8036 {
8037 // Negative values in base values array when converted to unsigned int will be ZERO
8038 // Addition operations done inside the shader in such cases will operate on ZERO rather
8039 // than the negative value being passed.
8040 // Replicate the sequence of conversion and addition operations done on the
8041 // shader input, to calculate the expected values in XFB data in the
8042 // problematic cases.
8043 if (expected_value < 0)
8044 {
8045 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8046 }
8047 expected_value = (unsigned int)expected_value;
8048 }
8049
8050 traveller_ptr += sizeof(double);
8051 if (de::abs(result_value - expected_value) > epsilon)
8052 {
8053 m_testCtx.getLog() << tcu::TestLog::Message
8054 << "Invalid double-precision floating-point value obtained when doing an "
8055 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8056 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8057 << "]"
8058 ", component index: ["
8059 << n_swizzled_component << "]"
8060 ", value: ["
8061 << ref_expected_value << "]"
8062 " to GLSL type ["
8063 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8064 ", retrieved value: ["
8065 << std::setprecision(16) << result_value << "]"
8066 ", expected value: ["
8067 << std::setprecision(16) << expected_value << "]"
8068 ", shader used:\n"
8069 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8070
8071 result = false;
8072 }
8073
8074 break;
8075 } /* VARIABLE_TYPE_DOUBLE case */
8076
8077 case Utils::VARIABLE_TYPE_FLOAT:
8078 {
8079 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8080 float expected_value = ref_expected_value;
8081 float result_value = *((float*)traveller_ptr);
8082
8083 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8084 {
8085 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8086 }
8087 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8088 {
8089 expected_value = (float)((int)expected_value);
8090 }
8091 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8092 {
8093 expected_value = (float)((unsigned int)expected_value);
8094 }
8095
8096 traveller_ptr += sizeof(float);
8097 if (de::abs(result_value - expected_value) > epsilon)
8098 {
8099 m_testCtx.getLog() << tcu::TestLog::Message
8100 << "Invalid single-precision floating-point value obtained when doing an "
8101 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8102 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8103 << "]"
8104 ", component index: ["
8105 << n_swizzled_component << "]"
8106 ", value: ["
8107 << ref_expected_value << "]"
8108 " to GLSL type ["
8109 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8110 ", retrieved value: ["
8111 << std::setprecision(16) << result_value << "]"
8112 ", expected value: ["
8113 << std::setprecision(16) << expected_value << "]"
8114 ", shader used:\n"
8115 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8116
8117 result = false;
8118 }
8119
8120 break;
8121 } /* VARIABLE_TYPE_FLOAT case */
8122
8123 case Utils::VARIABLE_TYPE_UINT:
8124 {
8125 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8126 double expected_value = ref_expected_value;
8127 unsigned int result_value = *((unsigned int*)traveller_ptr);
8128
8129 traveller_ptr += sizeof(unsigned int);
8130 if (result_value != (unsigned int)expected_value)
8131 {
8132 if (expected_value < 0.0)
8133 {
8134 // It is undefined to convert a negative floating-point value to an uint.
8135 break;
8136 }
8137
8138 m_testCtx.getLog() << tcu::TestLog::Message
8139 << "Invalid unsigned integer value obtained when doing an "
8140 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8141 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8142 << "]"
8143 ", component index: ["
8144 << n_swizzled_component << "]"
8145 ", value: ["
8146 << ref_expected_value << "]"
8147 " to GLSL type ["
8148 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8149 ", retrieved value: ["
8150 << result_value << "]"
8151 ", expected value: ["
8152 << (unsigned int)expected_value << "]"
8153 ", shader used:\n"
8154 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8155
8156 result = false;
8157 }
8158
8159 break;
8160 } /* VARIABLE_TYPE_UINT case */
8161
8162 default:
8163 {
8164 TCU_FAIL("Unrecognized variable type");
8165 }
8166 } /* switch (test_case.dst_type) */
8167 } /* for (all result components) */
8168 } /* for (all base values) */
8169
8170 return result;
8171 }
8172
8173 /** Constructor
8174 *
8175 * @param context Rendering context.
8176 */
GPUShaderFP64Test6(deqp::Context & context)8177 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8178 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8179 "during compilation time.")
8180 , m_cs_id(0)
8181 , m_fs_id(0)
8182 , m_gs_id(0)
8183 , m_tc_id(0)
8184 , m_te_id(0)
8185 , m_vs_id(0)
8186 , m_has_test_passed(true)
8187 {
8188 }
8189
8190 /** Deinitializes all buffers and GL objects that may have been generated
8191 * during test execution.
8192 **/
deinit()8193 void GPUShaderFP64Test6::deinit()
8194 {
8195 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8196
8197 if (m_cs_id != 0)
8198 {
8199 gl.deleteShader(m_cs_id);
8200
8201 m_cs_id = 0;
8202 }
8203
8204 if (m_fs_id != 0)
8205 {
8206 gl.deleteShader(m_fs_id);
8207
8208 m_fs_id = 0;
8209 }
8210
8211 if (m_gs_id != 0)
8212 {
8213 gl.deleteShader(m_gs_id);
8214
8215 m_gs_id = 0;
8216 }
8217
8218 if (m_tc_id != 0)
8219 {
8220 gl.deleteShader(m_tc_id);
8221
8222 m_tc_id = 0;
8223 }
8224
8225 if (m_te_id != 0)
8226 {
8227 gl.deleteShader(m_te_id);
8228
8229 m_te_id = 0;
8230 }
8231
8232 if (m_vs_id != 0)
8233 {
8234 gl.deleteShader(m_vs_id);
8235
8236 m_vs_id = 0;
8237 }
8238 }
8239
8240 /** Executes a single test case.
8241 *
8242 * This function can throw TestError exceptions if GL implementation reports
8243 * an error.
8244 *
8245 * @param test_case Test case descriptor.
8246 *
8247 * @return true if test case passed, false otherwise.
8248 **/
executeIteration(const _test_case & test_case)8249 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8250 {
8251 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8252 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8253 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8254 bool result = true;
8255 const char* stage_body = NULL;
8256 const char* stage_name = NULL;
8257
8258 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8259 {
8260 const glw::GLuint so_id = so_ids[n_so_id];
8261
8262 /* Skip compute shader if it is not supported */
8263 if (0 == so_id)
8264 {
8265 continue;
8266 }
8267
8268 /* Compile the shader */
8269 gl.compileShader(so_id);
8270 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8271
8272 /* Has the compilation failed as expected? */
8273 glw::GLint compile_status = GL_TRUE;
8274
8275 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8276 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8277
8278 if (compile_status == GL_TRUE)
8279 {
8280 /* What is the current stage's name? */
8281 if (so_id == m_cs_id)
8282 {
8283 stage_body = test_case.cs_shader_body.c_str();
8284 stage_name = "Compute shader";
8285 }
8286 else if (so_id == m_fs_id)
8287 {
8288 stage_body = test_case.fs_shader_body.c_str();
8289 stage_name = "Fragment shader";
8290 }
8291 else if (so_id == m_gs_id)
8292 {
8293 stage_body = test_case.gs_shader_body.c_str();
8294 stage_name = "Geometry shader";
8295 }
8296 else if (so_id == m_tc_id)
8297 {
8298 stage_body = test_case.tc_shader_body.c_str();
8299 stage_name = "Tessellation control shader";
8300 }
8301 else if (so_id == m_te_id)
8302 {
8303 stage_body = test_case.te_shader_body.c_str();
8304 stage_name = "Tessellation evaluation shader";
8305 }
8306 else if (so_id == m_vs_id)
8307 {
8308 stage_body = test_case.vs_shader_body.c_str();
8309 stage_name = "Vertex shader";
8310 }
8311 else
8312 {
8313 /* Doesn't make much sense to throw exceptions here so.. */
8314 stage_body = "";
8315 stage_name = "[?]";
8316 }
8317
8318 /* This shader should have never compiled successfully! */
8319 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8320 << " has been compiled successfully, even though the shader was malformed."
8321 " Following is shader body:\n"
8322 << stage_body << tcu::TestLog::EndMessage;
8323
8324 result = false;
8325 }
8326 } /* for (all shader objects) */
8327
8328 return result;
8329 }
8330
8331 /** Retrieves body of a compute shader that should be used for the purpose of
8332 * user-specified test case.
8333 *
8334 * @param test_case Test case descriptor to use.
8335 *
8336 * @return Requested string.
8337 **/
getComputeShaderBody(const _test_case & test_case)8338 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8339 {
8340 std::stringstream result_sstream;
8341
8342 /* Add pre-amble */
8343 result_sstream << "#version 420\n"
8344 "#extension GL_ARB_compute_shader : require\n"
8345 "\n"
8346 "layout(local_size_x = 6) in;\n"
8347 "\n"
8348 "void main()\n"
8349 "{\n";
8350
8351 /* Add local variable declarations */
8352 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8353
8354 if (test_case.src_array_size > 1)
8355 {
8356 result_sstream << "[" << test_case.src_array_size << "]";
8357 }
8358
8359 result_sstream << ";\n";
8360
8361 if (test_case.wrap_dst_type_in_structure)
8362 {
8363 result_sstream << "struct\n"
8364 "{\n"
8365 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8366 }
8367 else
8368 {
8369 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8370 }
8371
8372 result_sstream << ";\n";
8373
8374 if (test_case.wrap_dst_type_in_structure)
8375 {
8376 result_sstream << "\n} dst;\n";
8377 }
8378
8379 /* Add actual body */
8380 result_sstream << "dst = src;\n"
8381 "}\n";
8382
8383 /* Return the body */
8384 return result_sstream.str();
8385 }
8386
8387 /** Retrieves body of a fragment shader that should be used for the purpose of
8388 * user-specified test case.
8389 *
8390 * @param test_case Test case descriptor to use.
8391 *
8392 * @return Requested string.
8393 **/
getFragmentShaderBody(const _test_case & test_case)8394 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8395 {
8396 std::stringstream result_sstream;
8397
8398 /* Add pre-amble */
8399 result_sstream << "#version 420\n"
8400 "\n"
8401 "void main()\n"
8402 "{\n";
8403
8404 /* Add local variable declarations */
8405 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8406
8407 if (test_case.src_array_size > 1)
8408 {
8409 result_sstream << "[" << test_case.src_array_size << "]";
8410 }
8411
8412 result_sstream << ";\n";
8413
8414 if (test_case.wrap_dst_type_in_structure)
8415 {
8416 result_sstream << "struct\n"
8417 "{\n"
8418 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8419 }
8420 else
8421 {
8422 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8423 }
8424
8425 result_sstream << ";\n";
8426
8427 if (test_case.wrap_dst_type_in_structure)
8428 {
8429 result_sstream << "\n} dst;\n";
8430 }
8431
8432 /* Add actual body */
8433 result_sstream << "dst = src;\n"
8434 "}\n";
8435
8436 /* Return the body */
8437 return result_sstream.str();
8438 }
8439
8440 /** Retrieves body of a geometry shader that should be used for the purpose of
8441 * user-specified test case.
8442 *
8443 * @param test_case Test case descriptor to use.
8444 *
8445 * @return Requested string.
8446 **/
getGeometryShaderBody(const _test_case & test_case)8447 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8448 {
8449 std::stringstream result_sstream;
8450
8451 /* Add preamble */
8452 result_sstream << "#version 420\n"
8453 "\n"
8454 "layout(points) in;\n"
8455 "layout(max_vertices=1, points) out;\n"
8456 "\n"
8457 "void main()\n"
8458 "{\n";
8459
8460 /* Add local variable declarations */
8461 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8462
8463 if (test_case.src_array_size > 1)
8464 {
8465 result_sstream << "[" << test_case.src_array_size << "]";
8466 }
8467
8468 result_sstream << ";\n";
8469
8470 if (test_case.wrap_dst_type_in_structure)
8471 {
8472 result_sstream << "struct\n"
8473 "{\n"
8474 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8475 }
8476 else
8477 {
8478 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8479 }
8480
8481 result_sstream << ";\n"
8482 "\n";
8483
8484 if (test_case.wrap_dst_type_in_structure)
8485 {
8486 result_sstream << "} dst;\n";
8487 }
8488
8489 /* Add actual body */
8490 result_sstream << "dst = src;\n"
8491 "}\n";
8492
8493 /* We're done! */
8494 return result_sstream.str();
8495 }
8496
8497 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8498 * user-specified test case.
8499 *
8500 * @param test_case Test case descriptor to use.
8501 *
8502 * @return Requested string.
8503 **/
getTessellationControlShaderBody(const _test_case & test_case)8504 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8505 {
8506 std::stringstream result_sstream;
8507
8508 /* Add preamble */
8509 result_sstream << "#version 420\n"
8510 "\n"
8511 "layout(vertices=4) out;\n"
8512 "\n"
8513 "void main()\n"
8514 "{\n";
8515
8516 /* Add local variable declarations. */
8517 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8518
8519 if (test_case.src_array_size > 1)
8520 {
8521 result_sstream << "[" << test_case.src_array_size << "]";
8522 }
8523
8524 result_sstream << ";\n";
8525
8526 if (test_case.wrap_dst_type_in_structure)
8527 {
8528 result_sstream << "struct\n"
8529 "{\n"
8530 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8531 }
8532 else
8533 {
8534 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8535 }
8536
8537 if (test_case.wrap_dst_type_in_structure)
8538 {
8539 result_sstream << ";\n"
8540 "} dst;\n";
8541 }
8542 else
8543 {
8544 result_sstream << ";\n";
8545 }
8546
8547 /* Continue with the actual body. */
8548 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8549 "gl_TessLevelOuter[1] = 1.0;\n"
8550 "dst = src;\n"
8551 "}\n";
8552
8553 /* Return the body */
8554 return result_sstream.str();
8555 }
8556
8557 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8558 * user-specified test case.
8559 *
8560 * @param test_case Test case descriptor to use.
8561 *
8562 * @return Requested string.
8563 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8564 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8565 {
8566 std::stringstream result_sstream;
8567
8568 /* Add preamble */
8569 result_sstream << "#version 420\n"
8570 "\n"
8571 "layout(isolines) in;\n"
8572 "\n"
8573 "void main()\n"
8574 "{\n";
8575
8576 /* Add local variable declarations */
8577 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8578
8579 if (test_case.src_array_size > 1)
8580 {
8581 result_sstream << "[" << test_case.src_array_size << "]";
8582 }
8583
8584 result_sstream << ";\n";
8585
8586 if (test_case.wrap_dst_type_in_structure)
8587 {
8588 result_sstream << "struct\n"
8589 "{\n"
8590 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8591 }
8592 else
8593 {
8594 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8595 }
8596
8597 if (test_case.wrap_dst_type_in_structure)
8598 {
8599 result_sstream << ";\n"
8600 "} dst;\n";
8601 }
8602 else
8603 {
8604 result_sstream << ";\n";
8605 }
8606
8607 /* Continue with the actual body. */
8608 result_sstream << "dst = src;\n";
8609
8610 /* Complete the body */
8611 result_sstream << "}\n";
8612
8613 /* Return the body */
8614 return result_sstream.str();
8615 }
8616
8617 /** Retrieves body of a vertex shader that should be used for the purpose of
8618 * user-specified test case.
8619 *
8620 * @param test_case Test case descriptor to use.
8621 *
8622 * @return Requested string.
8623 **/
getVertexShaderBody(const _test_case & test_case)8624 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8625 {
8626 std::stringstream result_sstream;
8627
8628 /* Add preamble */
8629 result_sstream << "#version 420\n"
8630 "\n"
8631 "void main()\n"
8632 "{\n";
8633
8634 /* Add local variables */
8635 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8636
8637 if (test_case.src_array_size > 1)
8638 {
8639 result_sstream << "[" << test_case.src_array_size << "]";
8640 }
8641
8642 result_sstream << ";\n";
8643
8644 if (test_case.wrap_dst_type_in_structure)
8645 {
8646 result_sstream << "struct\n"
8647 "{\n"
8648 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8649 }
8650 else
8651 {
8652 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8653 }
8654
8655 if (test_case.wrap_dst_type_in_structure)
8656 {
8657 result_sstream << ";\n"
8658 "} dst;\n";
8659 }
8660 else
8661 {
8662 result_sstream << ";\n";
8663 }
8664
8665 /* Start actual body */
8666 result_sstream << "dst = src;\n"
8667 "gl_Position = vec4(1.0);\n"
8668 "}";
8669
8670 return result_sstream.str();
8671 }
8672
8673 /** Initializes shader objects required to run the test. */
initTest()8674 void GPUShaderFP64Test6::initTest()
8675 {
8676 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8677
8678 /* Generate shader objects */
8679
8680 /* Compute shader support and GL 4.2 required */
8681 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8682 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8683 {
8684 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8685 }
8686
8687 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8688 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8689 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8690 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8691 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8692
8693 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8694 }
8695
8696 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8697 *
8698 * @param test_case Test case descriptor to generate the shader bodies for.
8699 **/
initIteration(_test_case & test_case)8700 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8701 {
8702 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8703
8704 test_case.cs_shader_body = getComputeShaderBody(test_case);
8705 test_case.fs_shader_body = getFragmentShaderBody(test_case);
8706 test_case.gs_shader_body = getGeometryShaderBody(test_case);
8707 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8708 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8709 test_case.vs_shader_body = getVertexShaderBody(test_case);
8710
8711 /* Assign the bodies to relevant shaders */
8712 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8713 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8714 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8715 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8716 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8717 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8718
8719 /* m_cs_id is initialized only if compute_shader is supported */
8720 if (0 != m_cs_id)
8721 {
8722 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8723 }
8724
8725 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8726 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8727 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8728 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8729 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8730 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8731 }
8732
8733 /** Executes test iteration.
8734 *
8735 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8736 */
iterate()8737 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8738 {
8739 /* Do not execute the test if GL_ARB_texture_view is not supported */
8740 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8741 {
8742 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8743 }
8744
8745 /* Initialize GL objects needed to run the tests */
8746 initTest();
8747
8748 /* Build iteration array to run the tests in an automated manner */
8749 _test_case test_cases[] = {
8750 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8751 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8752 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8753 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8754 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8755 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8756 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8757 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8758 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8759 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8760 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8761 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8762 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8763 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8764 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8765 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8766 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8767 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8768 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8769 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8770 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8771 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8772 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8773 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8774 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8775 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8776 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8777 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8778 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8779 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8780 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8781 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8782 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8783 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8784 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8785 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8786 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8787 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8788 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8789 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8790 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8791 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8792 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8793 };
8794 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8795
8796 /* Execute all iterations */
8797 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8798 {
8799 _test_case& test_case = test_cases[n_test_case];
8800
8801 /* Initialize a program object we will use to perform the casting */
8802 initIteration(test_case);
8803
8804 /* Use the program object to XFB the results */
8805 m_has_test_passed &= executeIteration(test_case);
8806
8807 } /* for (all test cases) */
8808
8809 /* We're done */
8810 if (m_has_test_passed)
8811 {
8812 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8813 }
8814 else
8815 {
8816 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8817 }
8818
8819 return STOP;
8820 }
8821
8822 /** Constructor
8823 *
8824 * @param context Rendering context.
8825 */
GPUShaderFP64Test7(deqp::Context & context)8826 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8827 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8828 "in all shader stages.")
8829 , m_are_double_inputs_supported(false)
8830 , m_fbo_id(0)
8831 , m_fs_id(0)
8832 , m_gs_id(0)
8833 , m_has_test_passed(true)
8834 , m_n_max_components_per_stage(0)
8835 , m_n_xfb_varyings(0)
8836 , m_po_id(0)
8837 , m_tc_id(0)
8838 , m_te_id(0)
8839 , m_to_id(0)
8840 , m_to_data(NULL)
8841 , m_to_height(4)
8842 , m_to_width(4)
8843 , m_xfb_bo_id(0)
8844 , m_xfb_varyings(NULL)
8845 , m_vao_id(0)
8846 , m_vs_id(0)
8847 {
8848 }
8849
8850 /** Compiles all shaders attached to test program object and links it.
8851 *
8852 * @param variables
8853 *
8854 * @return true if the process was executed successfully, false otherwise.
8855 */
buildTestProgram(_variables & variables)8856 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8857 {
8858 std::string fs_body = getFragmentShaderBody(variables);
8859 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8860 std::string gs_body = getGeometryShaderBody(variables);
8861 std::string tc_body = getTessellationControlShaderBody(variables);
8862 std::string te_body = getTessellationEvaluationShaderBody(variables);
8863 std::string vs_body = getVertexShaderBody(variables);
8864 bool result = false;
8865
8866 /* Try to link the program object */
8867 glw::GLint link_status = GL_FALSE;
8868
8869 /* Compile the shaders */
8870 if (!compileShader(m_fs_id, fs_body))
8871 {
8872 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8873
8874 goto end;
8875 }
8876
8877 if (!compileShader(m_gs_id, gs_body))
8878 {
8879 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8880
8881 goto end;
8882 }
8883
8884 if (!compileShader(m_tc_id, tc_body))
8885 {
8886 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8887 << tcu::TestLog::EndMessage;
8888
8889 goto end;
8890 }
8891
8892 if (!compileShader(m_te_id, te_body))
8893 {
8894 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8895 << tcu::TestLog::EndMessage;
8896
8897 goto end;
8898 }
8899
8900 if (!compileShader(m_vs_id, vs_body))
8901 {
8902 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8903
8904 goto end;
8905 }
8906
8907 /* Configure XFB */
8908 releaseXFBVaryingNames();
8909 generateXFBVaryingNames(variables);
8910
8911 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8912
8913 gl.linkProgram(m_po_id);
8914
8915 /* Have we succeeded? */
8916 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8917
8918 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8919 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8920
8921 if (link_status != GL_TRUE)
8922 {
8923 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8924 << tcu::TestLog::EndMessage;
8925
8926 goto end;
8927 }
8928
8929 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8930 if (m_are_double_inputs_supported)
8931 {
8932 const size_t n_variables = variables.size();
8933
8934 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8935 {
8936 _variable& current_variable = variables[n_variable];
8937 std::stringstream attribute_name_sstream;
8938
8939 attribute_name_sstream << "in_vs_variable" << n_variable;
8940
8941 if (current_variable.array_size > 1)
8942 {
8943 attribute_name_sstream << "[0]";
8944 }
8945
8946 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8947
8948 if (current_variable.attribute_location == -1)
8949 {
8950 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8951 << attribute_name_sstream.str().c_str()
8952 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8953
8954 m_has_test_passed = false;
8955 goto end;
8956 }
8957 } /* for (all test variables) */
8958 } /* if (m_are_double_inputs_supported) */
8959
8960 m_current_fs_body = fs_body;
8961 m_current_gs_body = gs_body;
8962 m_current_tc_body = tc_body;
8963 m_current_te_body = te_body;
8964 m_current_vs_body = vs_body;
8965
8966 result = true;
8967
8968 end:
8969 return result;
8970 }
8971
8972 /** Updates shader object's body and then compiles the shader.
8973 *
8974 * @param body Body to use for the shader.
8975 *
8976 * @return true if the shader compiled successfully, false otherwise.
8977 **/
compileShader(glw::GLint shader_id,const std::string & body)8978 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8979 {
8980 const char* body_raw_ptr = body.c_str();
8981 glw::GLint compile_status = GL_FALSE;
8982 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8983
8984 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8985 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8986
8987 gl.compileShader(shader_id);
8988 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8989
8990 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8992
8993 return (compile_status == GL_TRUE);
8994 }
8995
8996 /** Configure storage of a buffer object used for capturing XFB data.
8997 *
8998 * @param variables Holds descriptor for all variables used for the iteration the
8999 * BO is being configured for. Storage size will be directly related
9000 * to the number of the variables and their type.
9001 */
configureXFBBuffer(const _variables & variables)9002 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9003 {
9004 DE_ASSERT(m_n_xfb_varyings != 0);
9005
9006 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9007 * The test only draws a single patch, and triangles are caught by transform feed-back.
9008 * Let's initialize the storage, according to the list of variables that will be used
9009 * for the test run.
9010 */
9011 unsigned int bo_size = 0;
9012
9013 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9014 variables_iterator++)
9015 {
9016 const _variable& variable = *variables_iterator;
9017 unsigned int n_bytes_needed = static_cast<unsigned int>(
9018 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9019
9020 bo_size += n_bytes_needed;
9021 } /* for (all variables) */
9022
9023 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9024
9025 /* Set up the BO storage */
9026 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9027
9028 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9030 }
9031
9032 /** Deinitializes all buffers and GL objects that may have been generated
9033 * during test execution.
9034 **/
deinit()9035 void GPUShaderFP64Test7::deinit()
9036 {
9037 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9038
9039 if (m_fbo_id != 0)
9040 {
9041 gl.deleteFramebuffers(1, &m_fbo_id);
9042
9043 m_fbo_id = 0;
9044 }
9045
9046 if (m_fs_id != 0)
9047 {
9048 gl.deleteShader(m_fs_id);
9049
9050 m_fs_id = 0;
9051 }
9052
9053 if (m_gs_id != 0)
9054 {
9055 gl.deleteShader(m_gs_id);
9056
9057 m_gs_id = 0;
9058 }
9059
9060 if (m_po_id != 0)
9061 {
9062 gl.deleteProgram(m_po_id);
9063
9064 m_po_id = 0;
9065 }
9066
9067 if (m_tc_id != 0)
9068 {
9069 gl.deleteShader(m_tc_id);
9070
9071 m_tc_id = 0;
9072 }
9073
9074 if (m_te_id != 0)
9075 {
9076 gl.deleteShader(m_te_id);
9077
9078 m_te_id = 0;
9079 }
9080
9081 if (m_to_data != NULL)
9082 {
9083 delete[] m_to_data;
9084
9085 m_to_data = NULL;
9086 }
9087
9088 if (m_to_id != 0)
9089 {
9090 gl.deleteTextures(1, &m_to_id);
9091
9092 m_to_id = 0;
9093 }
9094
9095 if (m_xfb_bo_id != 0)
9096 {
9097 gl.deleteBuffers(1, &m_xfb_bo_id);
9098
9099 m_xfb_bo_id = 0;
9100 }
9101
9102 if (m_xfb_varyings != DE_NULL)
9103 {
9104 releaseXFBVaryingNames();
9105 }
9106
9107 if (m_vao_id != 0)
9108 {
9109 gl.deleteVertexArrays(1, &m_vao_id);
9110
9111 m_vao_id = 0;
9112 }
9113
9114 if (m_vs_id != 0)
9115 {
9116 gl.deleteShader(m_vs_id);
9117
9118 m_vs_id = 0;
9119 }
9120 }
9121
9122 /** Executes the functional part of the test (case a) from the test spec)
9123 *
9124 * @param variables Vector of variable descriptors defining properties of
9125 * variables that should be used for the iteration.
9126 *
9127 * @return true if the test passed, false otherwise.
9128 **/
executeFunctionalTest(_variables & variables)9129 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9130 {
9131 bool result = true;
9132
9133 /* Build the test program */
9134 if (!buildTestProgram(variables))
9135 {
9136 return false;
9137 }
9138
9139 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9140 if (m_are_double_inputs_supported)
9141 {
9142 setInputAttributeValues(variables);
9143 }
9144
9145 /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9146 * only, if a data mismatch is detected.
9147 */
9148 configureXFBBuffer(variables);
9149
9150 /* Issue a draw call using the test program */
9151 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9152
9153 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9154 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9155
9156 gl.clear(GL_COLOR_BUFFER_BIT);
9157 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9158
9159 gl.useProgram(m_po_id);
9160 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9161
9162 gl.viewport(0, /* x */
9163 0, /* y */
9164 m_to_width, m_to_height);
9165 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9166
9167 gl.beginTransformFeedback(GL_TRIANGLES);
9168 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9169 {
9170 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9171 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9172 }
9173 gl.endTransformFeedback();
9174 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9175
9176 /* Verify color attachment contents */
9177 const float epsilon = 1.0f / 255.0f;
9178
9179 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9180 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9181
9182 for (unsigned int y = 0; y < m_to_height; ++y)
9183 {
9184 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9185
9186 for (unsigned int x = 0; x < m_to_width; ++x)
9187 {
9188 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9189
9190 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9191 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9192 {
9193 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9194 << ")"
9195 "; expected:(0, 255, 0, 0), found: ("
9196 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9197 << ", " << (int)pixel_ptr[3]
9198 << "), with the following variable types used as varyings:"
9199 << tcu::TestLog::EndMessage;
9200
9201 /* List the variable types that failed the test */
9202 const size_t n_variables = variables.size();
9203
9204 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9205 {
9206 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9207 << Utils::getVariableTypeString(variables[n_variable].type)
9208 << " (array size:" << variables[n_variable].array_size << ")"
9209 << tcu::TestLog::EndMessage;
9210 } /* for (all variable types) */
9211
9212 /* Log the variable contents */
9213 logVariableContents(variables);
9214
9215 /* Log shaders used for the iteration */
9216 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9217 "\n"
9218 "(VS):\n"
9219 << m_current_vs_body.c_str() << "\n"
9220 << "(TC):\n"
9221 "\n"
9222 << m_current_tc_body.c_str() << "\n"
9223 "(TE):\n"
9224 "\n"
9225 << m_current_te_body.c_str() << "\n"
9226 "(GS):\n"
9227 << m_current_gs_body.c_str() << "\n"
9228 "(FS):\n"
9229 "\n"
9230 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9231
9232 result = false;
9233
9234 goto end;
9235 }
9236 } /* for (all columns) */
9237 } /* for (all rows) */
9238
9239 /* All done! */
9240 end:
9241 return result;
9242 }
9243
9244 /** Takes user-input vector of test variables and allocates & fills an array of strings
9245 * holding names of geometry shader stage varyings that should be captured during
9246 * transform feedback operation. The array will be stored in m_xfb_varyings.
9247 *
9248 * @param variables Holds all test variable descriptors to be used for the iteration.
9249 */
generateXFBVaryingNames(const _variables & variables)9250 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9251 {
9252 unsigned int n_variable = 0;
9253 unsigned int n_varying = 0;
9254 unsigned int n_varyings = 0;
9255
9256 if (m_xfb_varyings != NULL)
9257 {
9258 releaseXFBVaryingNames();
9259 }
9260
9261 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9262 ++variables_iterator)
9263 {
9264 const _variable& variable = *variables_iterator;
9265
9266 n_varyings += variable.array_size;
9267 }
9268
9269 m_xfb_varyings = new glw::GLchar*[n_varyings];
9270
9271 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9272 ++variables_iterator, ++n_variable)
9273 {
9274 const _variable& variable = *variables_iterator;
9275
9276 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9277 {
9278 std::stringstream varying_sstream;
9279 size_t varying_length;
9280
9281 varying_sstream << "gs_variable" << n_variable;
9282
9283 if (variable.array_size > 1)
9284 {
9285 varying_sstream << "[" << array_index << "]";
9286 }
9287
9288 /* Store the varying name */
9289 varying_length = varying_sstream.str().length();
9290 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9291
9292 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9293 m_xfb_varyings[n_varying][varying_length] = 0;
9294 } /* for (all array indices) */
9295 } /* for (all varyings) */
9296
9297 m_n_xfb_varyings = n_varyings;
9298 }
9299
9300 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9301 * without using the "flat" keyword. (case c) )
9302 *
9303 * @param input_variable_type Variable type to use for input variable declaration.
9304 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9305 * of the arrayed variable.
9306 *
9307 * @return Requested string.
9308 **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9309 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9310 Utils::_variable_type input_variable_type, unsigned int array_size)
9311 {
9312 std::stringstream result_sstream;
9313 std::stringstream array_index_stringstream;
9314 std::stringstream array_size_stringstream;
9315
9316 if (array_size > 1)
9317 {
9318 array_index_stringstream << "[0]";
9319 array_size_stringstream << "[" << array_size << "]";
9320 }
9321
9322 if (Utils::isMatrixVariableType(input_variable_type))
9323 {
9324 array_index_stringstream << "[0].x";
9325 }
9326 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9327 {
9328 array_index_stringstream << "[0]";
9329 }
9330
9331 result_sstream << "#version 400\n"
9332 "\n"
9333 "in "
9334 << Utils::getVariableTypeString(input_variable_type) << " test_input"
9335 << array_size_stringstream.str() << ";\n"
9336 "\n"
9337 "out float test_output;\n"
9338 "\n"
9339 "void main()\n"
9340 "{\n"
9341 " if (test_input"
9342 << array_index_stringstream.str() << " > 2.0)\n"
9343 " {\n"
9344 " test_output = 1.0;\n"
9345 " }\n"
9346 " else\n"
9347 " {\n"
9348 " test_output = 3.0;\n"
9349 " }\n"
9350 "}\n";
9351
9352 return result_sstream.str();
9353 }
9354
9355 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9356 *
9357 * @param input_variable_type Variable type to use for input variable declaration.
9358 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9359 * of the arrayed variable.
9360 *
9361 * @return Requested string.
9362 **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9363 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9364 Utils::_variable_type output_variable_type, unsigned int array_size)
9365 {
9366 std::stringstream array_index_sstream;
9367 std::stringstream array_size_sstream;
9368 std::stringstream result_sstream;
9369 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9370
9371 if (array_size > 1)
9372 {
9373 array_index_sstream << "[0]";
9374 array_size_sstream << "[" << array_size << "]";
9375 }
9376
9377 result_sstream << "#version 400\n"
9378 "\n"
9379 "out "
9380 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9381 "\n"
9382 "void main()\n"
9383 "{\n"
9384 " test_output"
9385 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9386 "}\n";
9387
9388 return result_sstream.str();
9389 }
9390
9391 /** Retrieves body of a fragment shader that uses user-specified set of variables
9392 * to declare contents of input & output block.
9393 *
9394 * @param variables As per description.
9395 *
9396 * @return Requested string.
9397 **/
getFragmentShaderBody(const _variables & variables)9398 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9399 {
9400 std::stringstream result_sstream;
9401
9402 /* Form the pre-amble */
9403 result_sstream << "#version 400\n"
9404 "\n"
9405
9406 /* Add input block */
9407 << "in GS_DATA\n"
9408 "{\n"
9409 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9410 "\n"
9411
9412 /* Add output variable */
9413 << "out vec4 result;\n"
9414 "\n"
9415
9416 /* Add main() definition */
9417 "void main()\n"
9418 "{\n"
9419 "const double epsilon = 1e-5;\n"
9420 "\n"
9421 "result = vec4(1, 0, 0, 0);\n"
9422 "\n";
9423
9424 /* Determine expected values first */
9425 unsigned int base_counter = 1;
9426 const size_t n_variables = variables.size();
9427
9428 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9429 {
9430 unsigned int variable_array_size = variables[n_variable].array_size;
9431 Utils::_variable_type variable_type = variables[n_variable].type;
9432 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9433 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9434
9435 std::stringstream array_size_sstream;
9436
9437 if (variable_array_size > 1)
9438 {
9439 array_size_sstream << "[" << variable_array_size << "]";
9440 }
9441
9442 /* Local variable declaration */
9443 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9444 << ";\n"
9445 "\n";
9446
9447 /* Set expected values */
9448 for (unsigned int index = 0; index < variable_array_size; ++index)
9449 {
9450 std::stringstream array_index_sstream;
9451
9452 if (variable_array_size > 1)
9453 {
9454 array_index_sstream << "[" << index << "]";
9455 }
9456
9457 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9458 << variable_type_string << "(";
9459
9460 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9461 {
9462 unsigned int expected_value =
9463 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9464
9465 if (m_are_double_inputs_supported)
9466 {
9467 /* VS input attributes */
9468 //expected_value += (base_counter + 6);
9469 expected_value -= 1;
9470 }
9471
9472 result_sstream << expected_value;
9473
9474 if (n_component != (n_variable_type_components - 1))
9475 {
9476 result_sstream << ", ";
9477 }
9478
9479 ++base_counter;
9480 } /* for (all components) */
9481
9482 result_sstream << ");\n";
9483 } /* for (all array indices) */
9484
9485 result_sstream << "\n";
9486 } /* for (all variable types) */
9487
9488 /* Now that we know the expected values, do a huge conditional check to verify if all
9489 * input variables carry correct information.
9490 */
9491 result_sstream << "if (";
9492
9493 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9494 {
9495 unsigned int variable_array_size = variables[n_variable].array_size;
9496 Utils::_variable_type variable_type = variables[n_variable].type;
9497 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type);
9498 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9499 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9500
9501 for (unsigned int index = 0; index < variable_array_size; ++index)
9502 {
9503 std::stringstream array_index_sstream;
9504
9505 if (variable_array_size > 1)
9506 {
9507 array_index_sstream << "[" << index << "]";
9508 }
9509
9510 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9511 {
9512 std::stringstream component_index_sstream;
9513
9514 if (n_variable_type_components > 1)
9515 {
9516 component_index_sstream << "[" << n_component << "]";
9517 }
9518
9519 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9520
9521 if (is_variable_type_matrix)
9522 {
9523 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9524 const unsigned int column = n_component % n_columns;
9525 const unsigned int row = n_component / n_columns;
9526
9527 result_sstream << "[" << column << "]"
9528 "."
9529 << Utils::getComponentAtIndex(row);
9530 }
9531 else
9532 {
9533 result_sstream << component_index_sstream.str();
9534 }
9535
9536 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9537
9538 if (is_variable_type_matrix)
9539 {
9540 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9541 const unsigned int column = n_component % n_columns;
9542 const unsigned int row = n_component / n_columns;
9543
9544 result_sstream << "[" << column << "]"
9545 "."
9546 << Utils::getComponentAtIndex(row);
9547 }
9548 else
9549 {
9550 result_sstream << component_index_sstream.str();
9551 }
9552
9553 result_sstream << ") <= epsilon &&";
9554 } /* for (all components) */
9555 } /* for (all array indices) */
9556 } /* for (all variable types) */
9557
9558 result_sstream << "true)\n"
9559 "{\n"
9560 " result = vec4(0, 1, 0, 0);\n"
9561 "}\n"
9562 "}\n";
9563
9564 /* All done */
9565 return result_sstream.str();
9566 }
9567
9568 /** Retrieves body of a geometry shader that uses user-specified set of variables
9569 * to declare contents of input & output block.
9570 *
9571 * @param variables As per description.
9572 *
9573 * @return Requested string.
9574 **/
getGeometryShaderBody(const _variables & variables)9575 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9576 {
9577 std::stringstream result_sstream;
9578
9579 /* Form the pre-amble */
9580 result_sstream << "#version 400\n"
9581 "\n"
9582 "layout(triangles) in;\n"
9583 "layout(triangle_strip, max_vertices=4) out;\n"
9584 "\n"
9585
9586 /* Add the input block */
9587 "in TE_DATA\n"
9588 "{\n"
9589 << getVariableDeclarations("te", variables) << "} in_data[];\n"
9590 "\n"
9591
9592 /* Add the output block */
9593 "out GS_DATA\n"
9594 "{\n"
9595 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9596 "\n"
9597
9598 /* Declare main() function */
9599 "void main()\n"
9600 "{\n";
9601
9602 /* Take input variables, add a predefined value and forward them to output variables */
9603 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9604 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
9605 const unsigned int n_quad_vertices =
9606 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9607 const size_t n_variables = variables.size();
9608
9609 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9610 {
9611 unsigned int counter = 4;
9612 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9613
9614 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9615 {
9616 unsigned int variable_array_size = variables[n_variable].array_size;
9617 Utils::_variable_type variable_type = variables[n_variable].type;
9618 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9619 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9620
9621 for (unsigned int index = 0; index < variable_array_size; ++index)
9622 {
9623 std::stringstream array_index_sstream;
9624
9625 if (variable_array_size > 1)
9626 {
9627 array_index_sstream << "[" << index << "]";
9628 }
9629
9630 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9631 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9632 << variable_type_string << "(";
9633
9634 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9635 {
9636 result_sstream << (counter++);
9637
9638 if (n_component != (n_variable_type_components - 1))
9639 {
9640 result_sstream << ", ";
9641 }
9642 } /* for (all components) */
9643
9644 result_sstream << ");\n";
9645 } /* for (all array indices) */
9646 } /* for (all variable types) */
9647
9648 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9649 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9650 "EmitVertex();\n";
9651 } /* for (all emitted quad vertices) */
9652
9653 result_sstream << "EndPrimitive();\n"
9654 "}\n";
9655
9656 /* All done */
9657 return result_sstream.str();
9658 }
9659
9660 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9661 * to declare contents of input & output block.
9662 *
9663 * @param variables As per description.
9664 *
9665 * @return Requested string.
9666 **/
getTessellationControlShaderBody(const _variables & variables)9667 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9668 {
9669 std::stringstream result_sstream;
9670
9671 /* Form the pre-amble */
9672 result_sstream << "#version 400\n"
9673 "\n"
9674 "layout (vertices=4) out;\n"
9675
9676 /* Declare input block */
9677 "in VS_DATA\n"
9678 "{\n"
9679 << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9680
9681 /* Declare output block */
9682 "out TC_DATA\n"
9683 "{\n"
9684 << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9685 "\n"
9686
9687 /* Define main() */
9688 "void main()\n"
9689 "{\n"
9690 " gl_TessLevelInner[0] = 1;\n"
9691 " gl_TessLevelInner[1] = 1;\n"
9692 " gl_TessLevelOuter[0] = 1;\n"
9693 " gl_TessLevelOuter[1] = 1;\n"
9694 " gl_TessLevelOuter[2] = 1;\n"
9695 " gl_TessLevelOuter[3] = 1;\n"
9696 "\n";
9697
9698 /* Take input variables, add a predefined value and forward them to output variables */
9699 const size_t n_variables = variables.size();
9700 unsigned int counter = 2;
9701
9702 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9703 {
9704 unsigned int variable_array_size = variables[n_variable].array_size;
9705 Utils::_variable_type variable_type = variables[n_variable].type;
9706 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9707 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9708
9709 for (unsigned int index = 0; index < variable_array_size; ++index)
9710 {
9711 std::stringstream array_index_sstream;
9712
9713 if (variable_array_size > 1)
9714 {
9715 array_index_sstream << "[" << index << "]";
9716 }
9717
9718 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9719 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9720 << variable_type_string << "(";
9721
9722 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9723 {
9724 result_sstream << (counter++);
9725
9726 if (n_component != (n_variable_type_components - 1))
9727 {
9728 result_sstream << ", ";
9729 }
9730 }
9731
9732 result_sstream << ");\n";
9733 } /* for (all array indices) */
9734 } /* for (all variable types) */
9735
9736 result_sstream << "}\n";
9737
9738 /* We're done */
9739 return result_sstream.str();
9740 }
9741
9742 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9743 * to declare contents of input & output block.
9744 *
9745 * @param variables As per description.
9746 *
9747 * @return Requested string.
9748 **/
getTessellationEvaluationShaderBody(const _variables & variables)9749 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9750 {
9751 std::stringstream result_sstream;
9752
9753 /* Form the pre-amble */
9754 result_sstream << "#version 400\n"
9755 "\n"
9756 "layout(quads) in;\n"
9757 "\n"
9758
9759 /* Define input block */
9760 "in TC_DATA\n"
9761 "{\n"
9762 << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9763 "\n"
9764
9765 /* Define output block */
9766 "out TE_DATA\n"
9767 "{\n"
9768 << getVariableDeclarations("te", variables) << "};\n"
9769 "\n"
9770
9771 /* Define main() */
9772 "void main()\n"
9773 "{\n";
9774
9775 /* Take input variables, add a predefined value and forward them to output variables */
9776 const size_t n_variables = variables.size();
9777 unsigned int counter = 3;
9778
9779 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9780 {
9781 unsigned int variable_array_size = variables[n_variable].array_size;
9782 Utils::_variable_type variable_type = variables[n_variable].type;
9783 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9784 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9785
9786 for (unsigned int index = 0; index < variable_array_size; ++index)
9787 {
9788 std::stringstream array_index_sstream;
9789
9790 if (variable_array_size > 1)
9791 {
9792 array_index_sstream << "[" << index << "]";
9793 }
9794
9795 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9796 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9797
9798 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9799 {
9800 result_sstream << (counter++);
9801
9802 if (n_component != (n_variable_type_components - 1))
9803 {
9804 result_sstream << ", ";
9805 }
9806 } /* for (all components) */
9807
9808 result_sstream << ");\n";
9809 } /* for (all array indices) */
9810 } /* for (all variable types) */
9811
9812 result_sstream << "}\n";
9813
9814 /* All done */
9815 return result_sstream.str();
9816 }
9817
9818 /** Returns a string containing declarations of user-specified set of variables.
9819 * Each declaration can optionally use a layot qualifier requested by the caller.
9820 *
9821 * @param prefix Prefix to use for variable names.
9822 * @param variables List of variables to declare in the result string.
9823 * @param explicit_locations true if each declaration should explicitly define location
9824 * of the variable ( eg. (layout location=X) )
9825 * @param layout_qualifier Optional qualifier to use for the declaration. Must not
9826 * be NULL.
9827 *
9828 * @return Requested string.
9829 **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9830 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9831 const char* layout_qualifier)
9832 {
9833 std::stringstream result_sstream;
9834
9835 /* Define output variables */
9836 const size_t n_variables = variables.size();
9837
9838 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9839 {
9840 unsigned int variable_array_size = variables[n_variable].array_size;
9841 Utils::_variable_type variable_type = variables[n_variable].type;
9842 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9843
9844 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9845
9846 if (variable_array_size > 1)
9847 {
9848 result_sstream << "[" << variable_array_size << "]";
9849 }
9850
9851 result_sstream << ";\n";
9852 } /* for (all user-specified variable types) */
9853
9854 return result_sstream.str();
9855 }
9856
9857 /** Retrieves body of a vertex shader that uses user-specified set of variables
9858 * to declare contents of input & output block.
9859 *
9860 * @param variables As per description.
9861 *
9862 * @return Requested string.
9863 **/
getVertexShaderBody(const _variables & variables)9864 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9865 {
9866 std::stringstream result_sstream;
9867
9868 /* Form pre-amble */
9869 result_sstream << "#version 400\n"
9870 "\n";
9871
9872 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9873 if (m_are_double_inputs_supported)
9874 {
9875 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9876 << getVariableDeclarations("in_vs", variables, "in");
9877 }
9878
9879 /* Define output variables */
9880 result_sstream << "out VS_DATA\n"
9881 "{\n"
9882 << getVariableDeclarations("vs", variables);
9883
9884 /* Define main() */
9885 result_sstream << "};\n"
9886 "\n"
9887 "void main()\n"
9888 "{\n";
9889
9890 /* Set output variable values */
9891 unsigned int counter = 1;
9892 const size_t n_variables = variables.size();
9893
9894 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9895 {
9896 unsigned int variable_array_size = variables[n_variable].array_size;
9897 Utils::_variable_type variable_type = variables[n_variable].type;
9898 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9899 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9900
9901 for (unsigned int index = 0; index < variable_array_size; ++index)
9902 {
9903 if (variable_array_size == 1)
9904 {
9905 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9906 }
9907 else
9908 {
9909 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9910 << " = " << variable_type_string << "(";
9911 }
9912
9913 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9914 {
9915 result_sstream << (double)(counter++);
9916
9917 /* Use input attributes, if available */
9918 if (m_are_double_inputs_supported)
9919 {
9920 result_sstream << " + in_vs_variable" << n_variable;
9921
9922 if (variable_array_size > 1)
9923 {
9924 result_sstream << "[" << index << "]";
9925 }
9926
9927 if (Utils::isMatrixVariableType(variables[n_variable].type))
9928 {
9929 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9930 const unsigned int column = n_component % n_columns;
9931 const unsigned int row = n_component / n_columns;
9932
9933 result_sstream << "[" << (column) << "]"
9934 "."
9935 << Utils::getComponentAtIndex(row);
9936 }
9937 else if (n_variable_type_components > 1)
9938 {
9939 result_sstream << "[" << n_component << "]";
9940 }
9941 }
9942
9943 if (n_component != (n_variable_type_components - 1))
9944 {
9945 result_sstream << ", ";
9946 }
9947 } /* for (all components) */
9948
9949 result_sstream << ");\n";
9950 }
9951 } /* for (all variable types) */
9952
9953 /* We will be using geometry shader to lay out the actual vertices so
9954 * the only thing we need to make sure is that the vertex never gets
9955 * culled.
9956 */
9957 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9958 "}\n";
9959
9960 /* That's it */
9961 return result_sstream.str();
9962 }
9963
9964 /** Initializes shader objects required to run the test. */
initTest()9965 void GPUShaderFP64Test7::initTest()
9966 {
9967 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9968
9969 /* Are double-precision input variables supported? */
9970 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9971
9972 /* Create a vertex array object */
9973 gl.genVertexArrays(1, &m_vao_id);
9974 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9975
9976 gl.bindVertexArray(m_vao_id);
9977 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9978
9979 /* Create a texture object we will use as FBO's color attachment */
9980 gl.genTextures(1, &m_to_id);
9981 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9982
9983 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9984 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9985
9986 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9987 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9988
9989 /* Allocate temporary buffer to hold the texture data we will be reading
9990 * from color attachment. */
9991 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9992
9993 /* Create and set up a framebuffer object */
9994 gl.genFramebuffers(1, &m_fbo_id);
9995 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9996
9997 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9998 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
9999
10000 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10001 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10002
10003 /* Create all shader objects */
10004 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10005 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10006 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10007 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10008 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10009 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10010
10011 /* Create test program object */
10012 m_po_id = gl.createProgram();
10013 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10014
10015 /* Attach the shaders to the program object */
10016 gl.attachShader(m_po_id, m_fs_id);
10017 gl.attachShader(m_po_id, m_gs_id);
10018 gl.attachShader(m_po_id, m_tc_id);
10019 gl.attachShader(m_po_id, m_te_id);
10020 gl.attachShader(m_po_id, m_vs_id);
10021 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10022
10023 /* The test passes double-precision values through the whole rendering pipeline.
10024 * This translates to a notable amount of components that we would need to transfer
10025 * all values in one fell swoop. The number is large enough to exceed minimum
10026 * capabilities as described for OpenGL 4.0 implementations.
10027 * For that reason, the test executes in turns. Each turn is allocated as many
10028 * double-precision scalar/matrix values as supported by the tested GL implementation.
10029 */
10030 glw::GLint gl_max_fragment_input_components_value = 0;
10031 glw::GLint gl_max_geometry_input_components_value = 0;
10032 glw::GLint gl_max_geometry_output_components_value = 0;
10033 glw::GLint gl_max_tess_control_input_components_value = 0;
10034 glw::GLint gl_max_tess_control_output_components_value = 0;
10035 glw::GLint gl_max_tess_evaluation_input_components_value = 0;
10036 glw::GLint gl_max_tess_evaluation_output_components_value = 0;
10037 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10038 glw::GLint gl_max_vertex_output_components_value = 0;
10039
10040 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10041 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10042 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10043 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10044 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10045 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10046 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10047 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10048 &gl_max_transform_feedback_interleaved_components_value);
10049 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10050 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10051
10052 m_n_max_components_per_stage =
10053 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10054 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10055 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10056 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10057 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10058 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10059 m_n_max_components_per_stage =
10060 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10061 m_n_max_components_per_stage =
10062 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10063
10064 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10065 * the input patch */
10066 gl.patchParameteri(GL_PATCH_VERTICES, 1);
10067
10068 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10069
10070 /* Initialize a BO we will use to hold XFB data */
10071 gl.genBuffers(1, &m_xfb_bo_id);
10072 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10073
10074 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10075 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10076
10077 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10078 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10079 }
10080
10081 /** Executes test iteration.
10082 *
10083 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10084 */
iterate()10085 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10086 {
10087 /* Do not execute the test if GL_ARB_texture_view is not supported */
10088 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10089 {
10090 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10091 }
10092
10093 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10094 {
10095 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10096 }
10097
10098 /* Initialize GL objects required to run the test */
10099 initTest();
10100
10101 /* Check the negative cases first */
10102 const Utils::_variable_type double_variable_types[] = {
10103 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10104 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10105 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10106 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10107 Utils::VARIABLE_TYPE_DMAT4X3,
10108 };
10109 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10110
10111 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10112 ++n_double_variable_type)
10113 {
10114 for (unsigned int array_size = 1; array_size < 3; ++array_size)
10115 {
10116 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10117
10118 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10119 {
10120 m_testCtx.getLog() << tcu::TestLog::Message
10121 << "A fragment shader with double-precision output variable compiled successfully."
10122 << tcu::TestLog::EndMessage;
10123
10124 m_has_test_passed = false;
10125 }
10126
10127 if (compileShader(m_fs_id,
10128 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10129 {
10130 m_testCtx.getLog()
10131 << tcu::TestLog::Message
10132 << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10133 " compiled successfully."
10134 << tcu::TestLog::EndMessage;
10135
10136 m_has_test_passed = false;
10137 }
10138 }
10139 } /* for (all variable types) */
10140
10141 /* Execute functional test. Split the run into as many iterations as necessary
10142 * so that we do not exceed GL implementation's capabilities. */
10143 unsigned int n_tested_variables = 0;
10144 _variables variables_to_test;
10145
10146 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10147 {
10148 glw::GLint total_n_used_components = 0;
10149
10150 /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10151 * of varying components that can be used for all shadr stages.
10152 */
10153 while (total_n_used_components < m_n_max_components_per_stage &&
10154 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10155 {
10156 _variable new_variable;
10157 unsigned int n_type_components = 0;
10158 glw::GLint n_used_components = 0;
10159
10160 new_variable.array_size =
10161 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10162 new_variable.type = double_variable_types[n_tested_variables / 2];
10163
10164 /* Double-precision varyings can use twice as many components as single-precision FPs */
10165 n_type_components = 4 /* components per location */ *
10166 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10167 n_used_components = n_type_components * new_variable.array_size * 2;
10168
10169 /* Do we have enough space? */
10170 if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10171 {
10172 if (n_used_components > m_n_max_components_per_stage)
10173 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10174 n_tested_variables++;
10175 }
10176 break;
10177 }
10178
10179 /* We can safely test the type in current iteration */
10180 total_n_used_components += n_used_components;
10181 n_tested_variables++;
10182
10183 variables_to_test.push_back(new_variable);
10184 }
10185
10186 if (variables_to_test.size() > 0)
10187 {
10188 m_has_test_passed &= executeFunctionalTest(variables_to_test);
10189
10190 variables_to_test.clear();
10191 }
10192 }
10193
10194 /* We're done */
10195 if (m_has_test_passed)
10196 {
10197 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10198 }
10199 else
10200 {
10201 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10202 }
10203
10204 return STOP;
10205 }
10206
10207 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10208 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10209 {
10210 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10211 std::stringstream log_sstream;
10212
10213 log_sstream << "Test variable values as retrieved from geometry shader:\n";
10214
10215 /* Map the XFB BO contents into process space */
10216 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10217
10218 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10219
10220 /* Read the variable contents. We only care about the set of varyings emitted
10221 * for first vertex in the geometry shader */
10222 unsigned int n_varying = 0;
10223 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10224
10225 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10226 ++variables_iterator, ++n_varying)
10227 {
10228 const _variable& variable = *variables_iterator;
10229 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10230 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10231
10232 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10233 {
10234 log_sstream << "gs_variable" << n_varying;
10235
10236 if (variable.array_size > 1)
10237 {
10238 log_sstream << "[" << array_index << "]";
10239 }
10240
10241 log_sstream << ": (";
10242
10243 for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10244 {
10245 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10246
10247 if (n_component != (n_components - 1))
10248 {
10249 log_sstream << ", ";
10250 }
10251
10252 traveller_ptr += sizeof(double);
10253 }
10254
10255 log_sstream << ")\n";
10256 } /* for (all array indices) */
10257 } /* for (all variables) */
10258
10259 /* Unmap the BO */
10260 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10261 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10262
10263 /* Pass the logged stream into the framework */
10264 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10265 }
10266
10267 /** De-allocates an arary holding strings representing names of varyings that
10268 * should be used for transform feed-back.
10269 **/
releaseXFBVaryingNames()10270 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10271 {
10272 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10273 {
10274 delete[] m_xfb_varyings[n_varying];
10275 }
10276
10277 delete[] m_xfb_varyings;
10278 m_xfb_varyings = DE_NULL;
10279
10280 m_n_xfb_varyings = 0;
10281 }
10282
10283 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10284 * Takes a list of test variables used for current iteration and assigns increasing values
10285 * to subsequent input attributes of the test program.
10286 *
10287 * @param variables Test variables of the current iteration.
10288 */
setInputAttributeValues(const _variables & variables)10289 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10290 {
10291 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10292 unsigned int counter = 6;
10293
10294 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10295 variable_iterator++)
10296 {
10297 const _variable& variable = *variable_iterator;
10298 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type);
10299 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10300 unsigned int n_components = 0;
10301 unsigned int n_columns = 1;
10302
10303 if (is_matrix_type)
10304 {
10305 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type);
10306 n_components = n_total_components / n_columns;
10307
10308 DE_ASSERT(n_total_components % n_columns == 0);
10309 }
10310 else
10311 {
10312 n_components = n_total_components;
10313 }
10314
10315 DE_ASSERT(n_components >= 1 && n_components <= 4);
10316
10317 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10318 {
10319 const double data[] = { -1, -1, -1, -1 };
10320
10321 switch (n_components)
10322 {
10323 case 1:
10324 {
10325 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10326 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10327
10328 break;
10329 }
10330
10331 case 2:
10332 {
10333 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10334 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10335
10336 break;
10337 }
10338
10339 case 3:
10340 {
10341 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10342 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10343
10344 break;
10345 }
10346
10347 case 4:
10348 {
10349 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10350 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10351
10352 break;
10353 }
10354
10355 default:
10356 {
10357 TCU_FAIL("Unrecognized number of components");
10358 }
10359 } /* switch (n_components) */
10360
10361 /* Make sure VAAs are disabled */
10362 gl.disableVertexAttribArray(variable.attribute_location + index);
10363 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10364
10365 counter += n_components;
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 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12356
12357 for (glw::GLuint c = 0; c < Size; ++c)
12358 {
12359 /* Skip eliminated column */
12360 if (column == c)
12361 {
12362 continue;
12363 }
12364
12365 for (glw::GLuint r = 0; r < Size; ++r)
12366 {
12367 /* Skip eliminated row */
12368 if (row == r)
12369 {
12370 continue;
12371 }
12372
12373 const glw::GLint r_offset = (r > row) ? -1 : 0;
12374 const glw::GLint c_offset = (c > column) ? -1 : 0;
12375
12376 result(r + r_offset, c + c_offset) = matrix(r, c);
12377 }
12378 }
12379
12380 return result;
12381 }
12382
12383 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12384 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12385 const tcu::Vector<glw::GLdouble, Size>& right)
12386 {
12387 return convertBvecToUvec(tcu::equal(left, right));
12388 }
12389
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12390 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12391 {
12392 return a * b + c;
12393 }
12394
fract(glw::GLdouble val)12395 static glw::GLdouble fract(glw::GLdouble val)
12396 {
12397 return val - floor(val);
12398 }
12399
12400 template <typename T>
frexp(T val,glw::GLint & exp)12401 static T frexp(T val, glw::GLint& exp)
12402 {
12403 return ::frexp(val, &exp);
12404 }
12405
12406 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12407 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12408 const tcu::Vector<glw::GLdouble, Size>& right)
12409 {
12410 return convertBvecToUvec(tcu::greaterThan(left, right));
12411 }
12412
12413 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12415 const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12418 }
12419
12420 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12421 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12422 {
12423 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix);
12424 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12425 const glw::GLdouble det = determinant(matrix);
12426 const glw::GLdouble inv_det = 1.0 / det;
12427
12428 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12429
12430 return result;
12431 }
12432
inverseSqrt(glw::GLdouble val)12433 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12434 {
12435 const glw::GLdouble root = sqrt(val);
12436
12437 return (1.0 / root);
12438 }
12439
isinf_impl(glw::GLdouble val)12440 static glw::GLuint isinf_impl(glw::GLdouble val)
12441 {
12442 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12443
12444 return ((infinity == val) || (-infinity == val));
12445 }
12446
isnan_impl(glw::GLdouble val)12447 static glw::GLuint isnan_impl(glw::GLdouble val)
12448 {
12449 return val != val;
12450 }
12451
12452 template <typename T>
ldexp(T val,glw::GLint exp)12453 static T ldexp(T val, glw::GLint exp)
12454 {
12455 return ::ldexp(val, exp);
12456 }
12457
12458 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12459 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12460 const tcu::Vector<glw::GLdouble, Size>& right)
12461 {
12462 return convertBvecToUvec(tcu::lessThan(left, right));
12463 }
12464
12465 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12466 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12467 const tcu::Vector<glw::GLdouble, Size>& right)
12468 {
12469 return convertBvecToUvec(tcu::lessThanEqual(left, right));
12470 }
12471
12472 template <typename T>
max(T left,T right)12473 static T max(T left, T right)
12474 {
12475 return (left >= right) ? left : right;
12476 }
12477
12478 template <typename T>
min(T left,T right)12479 static T min(T left, T right)
12480 {
12481 return (left <= right) ? left : right;
12482 }
12483
12484 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12485 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12486 glw::GLuint row)
12487 {
12488 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12489
12490 return determinant(eliminated);
12491 }
12492
12493 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12494 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12495 {
12496 const glw::GLuint r = (0 == row) ? 1 : 0;
12497 const glw::GLuint c = (0 == column) ? 1 : 0;
12498
12499 return matrix(r, c);
12500 }
12501
12502 template <typename T>
mix(T left,T right,T weight)12503 static T mix(T left, T right, T weight)
12504 {
12505 return left * (1 - weight) + right * (weight);
12506 }
12507
12508 template <typename T>
mod(T left,T right)12509 static T mod(T left, T right)
12510 {
12511 const T div_res = left / right;
12512 const T floored = floor(div_res);
12513
12514 return left - right * floored;
12515 }
12516
12517 template <typename T>
modf(T val,T & integer)12518 static T modf(T val, T& integer)
12519 {
12520 return ::modf(val, &integer);
12521 }
12522
12523 template <typename T>
multiply(T left,T right)12524 static T multiply(T left, T right)
12525 {
12526 T result = left * right;
12527
12528 return result;
12529 }
12530
12531 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12532 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12533 const tcu::Vector<glw::GLdouble, Size>& right)
12534 {
12535 return convertBvecToUvec(tcu::notEqual(left, right));
12536 }
12537
12538 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12539 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12540 const tcu::Vector<glw::GLdouble, Cols>& right)
12541 {
12542 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12543 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12544 tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12545
12546 for (glw::GLuint i = 0; i < Rows; ++i)
12547 {
12548 left_mat(i, 0) = left[i];
12549 }
12550
12551 for (glw::GLuint i = 0; i < Cols; ++i)
12552 {
12553 right_mat(0, i) = right[i];
12554 }
12555
12556 result = left_mat * right_mat;
12557
12558 return result;
12559 }
12560
packDouble2x32(const tcu::UVec2 & in)12561 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12562 {
12563 const glw::GLuint buffer[2] = { in[0], in[1] };
12564 glw::GLdouble result;
12565 memcpy(&result, buffer, sizeof(result));
12566 return result;
12567 }
12568
12569 template <typename T>
round(T t)12570 static T round(T t)
12571 {
12572 T frac = fract(t);
12573 T res = t - frac;
12574
12575 if (((T)0.5) < frac)
12576 {
12577 res += ((T)1.0);
12578 }
12579
12580 return res;
12581 }
12582
12583 template <typename T>
roundEven(T t)12584 static T roundEven(T t)
12585 {
12586 T frac = fract(t);
12587 T res = t - frac;
12588
12589 if (((T)0.5) < frac)
12590 {
12591 res += ((T)1.0);
12592 }
12593 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12594 {
12595 res += ((T)1.0);
12596 }
12597
12598 return res;
12599 }
12600
12601 template <typename T>
sign(T t)12602 static T sign(T t)
12603 {
12604 if (0 > t)
12605 {
12606 return -1;
12607 }
12608 else if (0 == t)
12609 {
12610 return 0;
12611 }
12612 else
12613 {
12614 return 1;
12615 }
12616 }
12617
12618 template <typename T>
smoothStep(T e0,T e1,T val)12619 static T smoothStep(T e0, T e1, T val)
12620 {
12621 if (e0 >= val)
12622 {
12623 return 0;
12624 }
12625
12626 if (e1 <= val)
12627 {
12628 return 1;
12629 }
12630
12631 T temp = (val - e0) / (e1 - e0);
12632
12633 T result = temp * temp * (3 - 2 * temp);
12634
12635 return result;
12636 }
12637
12638 template <typename T>
step(T edge,T val)12639 static T step(T edge, T val)
12640 {
12641 if (edge > val)
12642 {
12643 return 0;
12644 }
12645 else
12646 {
12647 return 1;
12648 }
12649 }
12650
12651 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12652 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12653 {
12654 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12655
12656 return result;
12657 }
12658
12659 template <typename T>
trunc(T t)12660 static T trunc(T t)
12661 {
12662 const T abs_value = de::abs(t);
12663 const T result_value = floor(abs_value);
12664
12665 const T result = sign(t) * result_value;
12666
12667 return result;
12668 }
12669
unpackDouble2x32(const glw::GLdouble & val)12670 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12671 {
12672 glw::GLuint* ptr = (glw::GLuint*)&val;
12673 tcu::UVec2 result(ptr[0], ptr[1]);
12674
12675 return result;
12676 }
12677 } /* Math */
12678
12679 /** Enumeration of tested functions
12680 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12681 * For example "max" can be called for (dvec3, double).
12682 **/
12683 enum FunctionEnum
12684 {
12685 FUNCTION_ABS = 0,
12686 FUNCTION_CEIL,
12687 FUNCTION_CLAMP,
12688 FUNCTION_CLAMP_AGAINST_SCALAR,
12689 FUNCTION_CROSS,
12690 FUNCTION_DETERMINANT,
12691 FUNCTION_DISTANCE,
12692 FUNCTION_DOT,
12693 FUNCTION_EQUAL,
12694 FUNCTION_FACEFORWARD,
12695 FUNCTION_FLOOR,
12696 FUNCTION_FMA,
12697 FUNCTION_FRACT,
12698 FUNCTION_FREXP,
12699 FUNCTION_GREATERTHAN,
12700 FUNCTION_GREATERTHANEQUAL,
12701 FUNCTION_INVERSE,
12702 FUNCTION_INVERSESQRT,
12703 FUNCTION_LDEXP,
12704 FUNCTION_LESSTHAN,
12705 FUNCTION_LESSTHANEQUAL,
12706 FUNCTION_LENGTH,
12707 FUNCTION_MATRIXCOMPMULT,
12708 FUNCTION_MAX,
12709 FUNCTION_MAX_AGAINST_SCALAR,
12710 FUNCTION_MIN,
12711 FUNCTION_MIN_AGAINST_SCALAR,
12712 FUNCTION_MIX,
12713 FUNCTION_MOD,
12714 FUNCTION_MOD_AGAINST_SCALAR,
12715 FUNCTION_MODF,
12716 FUNCTION_NORMALIZE,
12717 FUNCTION_NOTEQUAL,
12718 FUNCTION_OUTERPRODUCT,
12719 FUNCTION_PACKDOUBLE2X32,
12720 FUNCTION_REFLECT,
12721 FUNCTION_REFRACT,
12722 FUNCTION_ROUND,
12723 FUNCTION_ROUNDEVEN,
12724 FUNCTION_SIGN,
12725 FUNCTION_SMOOTHSTEP,
12726 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12727 FUNCTION_SQRT,
12728 FUNCTION_STEP,
12729 FUNCTION_STEP_AGAINST_SCALAR,
12730 FUNCTION_TRANSPOSE,
12731 FUNCTION_TRUNC,
12732 FUNCTION_UNPACKDOUBLE2X32,
12733 FUNCTION_ISNAN,
12734 FUNCTION_ISINF,
12735 };
12736
12737 struct TypeDefinition
12738 {
12739 std::string name;
12740 glw::GLuint n_columns;
12741 glw::GLuint n_rows;
12742 };
12743
12744 /** Implementation of BuiltinFunctionTest test, description follows:
12745 *
12746 * Verify double-precision support in common functions works correctly.
12747 * All double-precision types that apply for particular cases should
12748 * be tested for the following functions:
12749 *
12750 * - abs();
12751 * - ceil();
12752 * - clamp();
12753 * - cross();
12754 * - determinant();
12755 * - distance();
12756 * - dot();
12757 * - equal();
12758 * - faceforward();
12759 * - floor();
12760 * - fma();
12761 * - fract();
12762 * - frexp();
12763 * - greaterThan();
12764 * - greaterThanEqual();
12765 * - inverse();
12766 * - inversesqrt();
12767 * - ldexp();
12768 * - lessThan();
12769 * - lessThanEqual();
12770 * - length();
12771 * - matrixCompMult();
12772 * - max();
12773 * - min();
12774 * - mix();
12775 * - mod();
12776 * - modf();
12777 * - normalize();
12778 * - notEqual();
12779 * - outerProduct();
12780 * - packDouble2x32();
12781 * - reflect();
12782 * - refract();
12783 * - round();
12784 * - roundEven();
12785 * - sign();
12786 * - smoothstep();
12787 * - sqrt();
12788 * - step();
12789 * - transpose();
12790 * - trunc();
12791 * - unpackDouble2x32();
12792 * - isnan();
12793 * - isinf();
12794 *
12795 * The test should work by creating a program object (for each case
12796 * considered), to which a vertex shader should be attached. The
12797 * shader should define input variables that should be used as
12798 * arguments for the function in question. The result of the
12799 * operation should then be XFBed back to the test, where the
12800 * value should be verified.
12801 *
12802 * Reference function implementation from pre-DEQP CTS framework
12803 * should be ported to C for verification purposes where available.
12804 *
12805 * The test should use 1024 different scalar/vector/matrix argument
12806 * combinations. It should pass if all functions are determined
12807 * to work correctly for all argument combinations used.
12808 **/
12809 class BuiltinFunctionTest : public deqp::TestCase
12810 {
12811 public:
12812 /* Public methods */
12813 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12814 TypeDefinition typeDefinition);
12815
12816 virtual void deinit();
12817 virtual tcu::TestNode::IterateResult iterate();
12818
12819 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12820 *
12821 **/
12822 class functionObject
12823 {
12824 public:
12825 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12826 Utils::_variable_type result_type);
12827
~functionObject()12828 virtual ~functionObject()
12829 {
12830 }
12831
12832 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12833
12834 virtual glw::GLuint getArgumentCount() const = 0;
12835 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12836 glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12837 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12838 glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12839 glw::GLuint getArgumentStride() const;
12840 glw::GLuint getArgumentStride(glw::GLuint argument) const;
12841 FunctionEnum getFunctionEnum() const;
12842 const glw::GLchar* getName() const;
12843 glw::GLuint getResultComponents(glw::GLuint result) const;
12844 virtual glw::GLuint getResultCount() const;
12845 glw::GLuint getResultOffset(glw::GLuint result) const;
12846 virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12847 glw::GLuint getResultStride(glw::GLuint result) const;
12848 glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12849 glw::GLuint getResultStride() const;
12850
12851 protected:
12852 const FunctionEnum m_function_enum;
12853 const glw::GLchar* m_function_name;
12854 const glw::GLvoid* m_p_function;
12855 const Utils::_variable_type m_res_type;
12856 };
12857
12858 private:
12859 /* Private types */
12860 /** General type enumeration
12861 *
12862 **/
12863 enum generalType
12864 {
12865 SCALAR = 0,
12866 VECTOR,
12867 MATRIX,
12868 };
12869
12870 /** Details of variable type
12871 *
12872 **/
12873 struct typeDetails
12874 {
12875 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12876
12877 generalType m_general_type;
12878 glw::GLuint m_n_columns;
12879 glw::GLuint m_n_rows;
12880 glw::GLenum m_type;
12881 std::string m_type_name;
12882 };
12883
12884 /* Typedefs for gl.uniform* function pointers */
12885 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12886 const glw::GLdouble*);
12887 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12888 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12889 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12890
12891 /* Private methods */
12892 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12893
12894 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12895
12896 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
12897 const functionObject& function_object) const;
12898
12899 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
12900 const functionObject& function_object) const;
12901
12902 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
12903 const functionObject& function_object) const;
12904
12905 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
12906 const functionObject& function_object) const;
12907
12908 const glw::GLchar* getUniformName(glw::GLuint argument) const;
12909 const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12910
12911 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12912
12913 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12914
12915 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12916
12917 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12918 glw::GLubyte* buffer);
12919
12920 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12921
12922 void prepareTestData(const functionObject& function_object);
12923 void prepareVertexShaderCode(const functionObject& function_object);
12924
12925 bool test(FunctionEnum function, const typeDetails& type);
12926
12927 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12928
12929 void testInit();
12930
12931 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12932 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12933 const glw::GLvoid* result_src);
12934
12935 bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12936
12937 /* Private constants */
12938 static const glw::GLdouble m_epsilon;
12939 static const glw::GLuint m_n_veritces;
12940
12941 /* Private fields */
12942 glw::GLuint m_transform_feedback_buffer_id;
12943 glw::GLuint m_vertex_array_object_id;
12944
12945 std::vector<glw::GLubyte> m_expected_results_data;
12946 FunctionEnum m_function;
12947 TypeDefinition m_typeDefinition;
12948 std::vector<glw::GLubyte> m_argument_data;
12949 std::string m_vertex_shader_code;
12950 };
12951
12952 /* Constants used by BuiltinFunctionTest */
12953 /** Khronos Bug #14010
12954 * Using an epsilon value for comparing floating points is error prone.
12955 * Rather than writing a new floating point comparison function, I am
12956 * increasing the epsilon value to allow greater orders of magnitude
12957 * of floating point values.
12958 **/
12959 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002;
12960 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
12961
12962 /** Implementations of function objects required by "BuiltinFunctionTest"
12963 *
12964 **/
12965 namespace FunctionObject
12966 {
12967 /** Maps variable type with enumeration Utils::_variable_type
12968 *
12969 * @tparam T type
12970 **/
12971 template <typename T>
12972 class typeInfo
12973 {
12974 public:
12975 static const Utils::_variable_type variable_type =
12976 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12977 };
12978
12979 /** Place data from <in> into <buffer>
12980 *
12981 * @param buffer Buffer
12982 * @param in Input data
12983 **/
12984 template <typename T>
12985 class pack
12986 {
12987 public:
set(glw::GLvoid * buffer,const T & in)12988 static void set(glw::GLvoid* buffer, const T& in)
12989 {
12990 *(T*)buffer = in;
12991 }
12992 };
12993
12994 /** Place tcu::Matrix data from <in> into <buffer>
12995 *
12996 * @param buffer Buffer
12997 * @param in Input data
12998 **/
12999 template <int Cols, int Rows>
13000 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13001 {
13002 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13003 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13004 {
13005 glw::GLdouble* data = (glw::GLdouble*)buffer;
13006
13007 for (glw::GLint column = 0; column < Cols; ++column)
13008 {
13009 for (glw::GLint row = 0; row < Rows; ++row)
13010 {
13011 glw::GLint index = column * Rows + row;
13012
13013 data[index] = in(row, column);
13014 }
13015 }
13016 }
13017 };
13018
13019 /** Get data of <out> from <buffer>
13020 *
13021 * @param buffer Buffer
13022 * @param out Output data
13023 **/
13024 template <typename T>
13025 class unpack
13026 {
13027 public:
get(const glw::GLvoid * buffer,T & out)13028 static void get(const glw::GLvoid* buffer, T& out)
13029 {
13030 out = *(T*)buffer;
13031 }
13032 };
13033
13034 /** Get tcu::Matrix data from <buffer>
13035 *
13036 * @param buffer Buffer
13037 * @param out Output data
13038 **/
13039 template <int Cols, int Rows>
13040 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13041 {
13042 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13043 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13044 {
13045 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13046
13047 for (glw::GLint column = 0; column < Cols; ++column)
13048 {
13049 for (glw::GLint row = 0; row < Rows; ++row)
13050 {
13051 glw::GLint index = column * Rows + row;
13052
13053 out(row, column) = data[index];
13054 }
13055 }
13056 }
13057 };
13058
13059 /** Base of unary function classes
13060 *
13061 **/
13062 class unaryBase : public BuiltinFunctionTest::functionObject
13063 {
13064 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)13065 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13066 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13067 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13068 {
13069 }
13070
getArgumentCount() const13071 virtual glw::GLuint getArgumentCount() const
13072 {
13073 return 1;
13074 }
13075
getArgumentType(glw::GLuint) const13076 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13077 {
13078 return m_arg_type;
13079 }
13080
13081 protected:
13082 const Utils::_variable_type m_arg_type;
13083 };
13084
13085 /** Unary function class. It treats input argument as one variable.
13086 *
13087 * @tparam ResT Type of result
13088 * @tparam ArgT Type of argument
13089 **/
13090 template <typename ResT, typename ArgT>
13091 class unary : public unaryBase
13092 {
13093 public:
13094 typedef ResT (*functionPointer)(const ArgT&);
13095
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13096 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13097 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13098 typeInfo<ArgT>::variable_type)
13099 {
13100 }
13101
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13102 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13103 {
13104 ResT result;
13105 ArgT arg;
13106
13107 unpack<ArgT>::get(argument_src, arg);
13108
13109 functionPointer p_function = (functionPointer)m_p_function;
13110
13111 result = p_function(arg);
13112
13113 pack<ResT>::set(result_dst, result);
13114 }
13115 };
13116
13117 /** Unary function class. It treats input argument as separate components.
13118 *
13119 * @tparam ResT Type of result
13120 **/
13121 template <typename ResT>
13122 class unaryByComponent : public unaryBase
13123 {
13124 public:
13125 typedef ResT (*functionPointer)(glw::GLdouble);
13126
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13127 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13128 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13129 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13130 {
13131 }
13132
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13133 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13134 {
13135 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13136 ResT* p_result = (ResT*)result_dst;
13137 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src;
13138
13139 functionPointer p_function = (functionPointer)m_p_function;
13140
13141 for (glw::GLuint component = 0; component < n_components; ++component)
13142 {
13143 p_result[component] = p_function(p_arg[component]);
13144 }
13145 }
13146 };
13147
13148 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13149 *
13150 * @tparam ResT Type of result
13151 * @tparam ArgT Type of argument
13152 * @tparam OutT Type of output parameter
13153 **/
13154 template <typename ResT, typename ArgT, typename OutT>
13155 class unaryWithOutputByComponent : public unaryBase
13156 {
13157 public:
13158 typedef ResT (*functionPointer)(ArgT, OutT&);
13159
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)13160 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13161 functionPointer function_pointer, const Utils::_variable_type res_type,
13162 const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13163 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13164 , m_out_type(out_type)
13165 {
13166 }
13167
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13168 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13169 {
13170 ResT* p_result = (ResT*)result_dst;
13171 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13172 ArgT* p_arg = (ArgT*)argument_src;
13173
13174 const glw::GLuint n_components_0 = getArgumentComponents(0);
13175 const glw::GLuint n_components_1 = getResultComponents(1);
13176 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13177
13178 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13179 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13180
13181 functionPointer p_function = (functionPointer)m_p_function;
13182
13183 for (glw::GLuint component = 0; component < n_components; ++component)
13184 {
13185 const ArgT first_arg = p_arg[component * component_step_0];
13186 OutT& second_arg = p_out[component * component_step_1];
13187
13188 p_result[component] = p_function(first_arg, second_arg);
13189 }
13190 }
13191
getResultCount() const13192 glw::GLuint getResultCount() const
13193 {
13194 return 2;
13195 }
13196
getResultType(glw::GLuint result) const13197 Utils::_variable_type getResultType(glw::GLuint result) const
13198 {
13199 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13200
13201 switch (result)
13202 {
13203 case 0:
13204 type = m_res_type;
13205 break;
13206 case 1:
13207 type = m_out_type;
13208 break;
13209 default:
13210 TCU_FAIL("Not implemented");
13211 break;
13212 }
13213
13214 return type;
13215 }
13216
13217 protected:
13218 const Utils::_variable_type m_out_type;
13219 };
13220
13221 /** Base of binary function classes.
13222 *
13223 **/
13224 class binaryBase : public BuiltinFunctionTest::functionObject
13225 {
13226 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)13227 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13228 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13229 const Utils::_variable_type arg_2_type)
13230 : functionObject(function_enum, function_name, function_pointer, res_type)
13231 , m_arg_1_type(arg_1_type)
13232 , m_arg_2_type(arg_2_type)
13233 {
13234 }
13235
getArgumentCount() const13236 virtual glw::GLuint getArgumentCount() const
13237 {
13238 return 2;
13239 }
13240
getArgumentType(glw::GLuint argument) const13241 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13242 {
13243 switch (argument)
13244 {
13245 case 0:
13246 return m_arg_1_type;
13247 case 1:
13248 return m_arg_2_type;
13249 default:
13250 return Utils::VARIABLE_TYPE_UNKNOWN;
13251 }
13252 }
13253
13254 protected:
13255 const Utils::_variable_type m_arg_1_type;
13256 const Utils::_variable_type m_arg_2_type;
13257 };
13258
13259 /** Binary function class. It treats input arguments as two variables.
13260 *
13261 * @param ResT Type of result
13262 * @param Arg1T Type of first argument
13263 * @param Arg2T Type of second argument
13264 **/
13265 template <typename ResT, typename Arg1T, typename Arg2T>
13266 class binary : public binaryBase
13267 {
13268 public:
13269 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13270
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13271 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13272 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13273 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13274 {
13275 }
13276
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13277 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13278 {
13279 const glw::GLuint argument_1_stride = getArgumentStride(0);
13280
13281 functionPointer p_function = (functionPointer)m_p_function;
13282
13283 Arg1T arg_1;
13284 Arg2T arg_2;
13285 ResT result;
13286
13287 unpack<Arg1T>::get(argument_src, arg_1);
13288 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13289
13290 result = p_function(arg_1, arg_2);
13291
13292 pack<ResT>::set(result_dst, result);
13293 }
13294 };
13295
13296 /** Binary function class. It treats input arguments as separate components.
13297 *
13298 * @param ResT Type of result
13299 * @param Arg1T Type of first argument
13300 * @param Arg2T Type of second argument
13301 **/
13302 template <typename ResT, typename Arg1T, typename Arg2T>
13303 class binaryByComponent : public binaryBase
13304 {
13305 public:
13306 typedef ResT (*functionPointer)(Arg1T, Arg2T);
13307
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)13308 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13309 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13310 const Utils::_variable_type arg_2_type)
13311 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13312 {
13313 }
13314
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13315 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13316 {
13317 ResT* p_result = (ResT*)result_dst;
13318 Arg1T* p_arg_1 = (Arg1T*)argument_src;
13319 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13320
13321 const glw::GLuint n_components_0 = getArgumentComponents(0);
13322 const glw::GLuint n_components_1 = getArgumentComponents(1);
13323 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13324
13325 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13326 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13327
13328 functionPointer p_function = (functionPointer)m_p_function;
13329
13330 for (glw::GLuint component = 0; component < n_components; ++component)
13331 {
13332 const Arg1T first_arg = p_arg_1[component * component_step_0];
13333 const Arg2T second_arg = p_arg_2[component * component_step_1];
13334
13335 p_result[component] = p_function(first_arg, second_arg);
13336 }
13337 }
13338 };
13339
13340 /** Base of tenary function classes.
13341 *
13342 **/
13343 class tenaryBase : public BuiltinFunctionTest::functionObject
13344 {
13345 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)13346 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13347 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13348 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13349 : functionObject(function_enum, function_name, function_pointer, res_type)
13350 , m_arg_1_type(arg_1_type)
13351 , m_arg_2_type(arg_2_type)
13352 , m_arg_3_type(arg_3_type)
13353 {
13354 }
13355
getArgumentCount() const13356 virtual glw::GLuint getArgumentCount() const
13357 {
13358 return 3;
13359 }
13360
getArgumentType(glw::GLuint argument) const13361 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13362 {
13363 switch (argument)
13364 {
13365 case 0:
13366 return m_arg_1_type;
13367 case 1:
13368 return m_arg_2_type;
13369 case 2:
13370 return m_arg_3_type;
13371 default:
13372 return Utils::VARIABLE_TYPE_UNKNOWN;
13373 }
13374 }
13375
13376 protected:
13377 const Utils::_variable_type m_arg_1_type;
13378 const Utils::_variable_type m_arg_2_type;
13379 const Utils::_variable_type m_arg_3_type;
13380 };
13381
13382 /** Tenary function class. It treats input arguments as three variables.
13383 *
13384 * @param ResT Type of result
13385 * @param Arg1T Type of first argument
13386 * @param Arg2T Type of second argument
13387 * @param Arg3T Type of third argument
13388 **/
13389 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13390 class tenary : public tenaryBase
13391 {
13392 public:
13393 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13394 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13395 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13396 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13397
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13398 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13399 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13400 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13401 {
13402 }
13403
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13404 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13405 {
13406 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13407 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13408
13409 functionPointer p_function = (functionPointer)m_p_function;
13410
13411 arg1T arg_1;
13412 arg2T arg_2;
13413 arg3T arg_3;
13414 ResT result;
13415
13416 unpack<arg1T>::get(argument_src, arg_1);
13417 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13418 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13419
13420 result = p_function(arg_1, arg_2, arg_3);
13421
13422 pack<ResT>::set(result_dst, result);
13423 }
13424 };
13425
13426 /** Tenary function class. It treats input arguments as separate components.
13427 *
13428
13429 **/
13430 class tenaryByComponent : public tenaryBase
13431 {
13432 public:
13433 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13434
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)13435 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13436 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13437 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13438 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13439 arg_3_type)
13440 {
13441 }
13442
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13443 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13444 {
13445 glw::GLdouble* p_result = (glw::GLdouble*)result_dst;
13446 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src;
13447
13448 const glw::GLuint n_components_0 = getArgumentComponents(0);
13449 const glw::GLuint n_components_1 = getArgumentComponents(1);
13450 const glw::GLuint n_components_2 = getArgumentComponents(2);
13451 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2);
13452
13453 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13454 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13455 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13456
13457 functionPointer p_function = (functionPointer)m_p_function;
13458
13459 for (glw::GLuint component = 0; component < n_components; ++component)
13460 {
13461 const glw::GLdouble first_arg = p_arg[component * component_step_0];
13462 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13463 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13464
13465 p_result[component] = p_function(first_arg, second_arg, third_arg);
13466 }
13467 }
13468 };
13469 } /* FunctionObject */
13470
13471 /** Constructor.
13472 *
13473 * @param context Rendering context.
13474 **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13475 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13476 TypeDefinition typeDefinition)
13477 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13478 , m_transform_feedback_buffer_id(0)
13479 , m_vertex_array_object_id(0)
13480 , m_function(function)
13481 , m_typeDefinition(typeDefinition)
13482 {
13483 /* Nothing to be done here */
13484 }
13485
13486 /** Deinitializes all GL objects that may have been created during test execution.
13487 *
13488 **/
deinit()13489 void BuiltinFunctionTest::deinit()
13490 {
13491 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13492
13493 /* Clean buffers */
13494 if (0 != m_transform_feedback_buffer_id)
13495 {
13496 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13497 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13498 m_transform_feedback_buffer_id = 0;
13499 }
13500
13501 /* Clean VAO */
13502 if (0 != m_vertex_array_object_id)
13503 {
13504 gl.bindVertexArray(0);
13505 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13506 m_vertex_array_object_id = 0;
13507 }
13508 }
13509
13510 /** Execute test
13511 *
13512 * @return tcu::TestNode::STOP
13513 **/
iterate()13514 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13515 {
13516 /* Check if extension is supported */
13517 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13518 {
13519 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13520 }
13521
13522 testInit();
13523
13524 /* Verify result */
13525 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13526 if (test(m_function, type))
13527 {
13528 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13529 }
13530 else
13531 {
13532 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13533 }
13534
13535 /* Done */
13536 return tcu::TestNode::STOP;
13537 }
13538
13539 /** Constructor
13540 *
13541 * @param function_enum Function enumeration
13542 * @param function_name Function name
13543 * @param function_pointer Pointer to routine that wiil be executed
13544 * @param result_type Type of result
13545 **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13546 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13547 glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13548 : m_function_enum(function_enum)
13549 , m_function_name(function_name)
13550 , m_p_function(function_pointer)
13551 , m_res_type(result_type)
13552 {
13553 /* Nothing to be done here */
13554 }
13555
13556 /** Get number of components for <argument>
13557 *
13558 * @param argument Argument ordinal, starts with 0
13559 *
13560 * @return Number of components
13561 **/
getArgumentComponents(glw::GLuint argument) const13562 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13563 {
13564 const Utils::_variable_type type = getArgumentType(argument);
13565 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13566
13567 return n_components;
13568 }
13569
13570 /** Get size in bytes of single component of <argument>
13571 *
13572 * @param argument Argument ordinal, starts with 0
13573 *
13574 * @return Size of component
13575 **/
getArgumentComponentSize(glw::GLuint argument) const13576 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13577 {
13578 const Utils::_variable_type type = getArgumentType(argument);
13579 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13580 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13581
13582 return base_type_size;
13583 }
13584
13585 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13586 *
13587 * @param argument Argument ordinal, starts with 0
13588 *
13589 * @return Offset of arguemnt's data
13590 **/
getArgumentOffset(glw::GLuint argument) const13591 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13592 {
13593 glw::GLuint result = 0;
13594
13595 for (glw::GLuint i = 0; i < argument; ++i)
13596 {
13597 result += getArgumentStride(i);
13598 }
13599
13600 return result;
13601 }
13602
13603 /** Get stride in bytes of all arguments
13604 *
13605 * @return Stride of all arguments
13606 **/
getArgumentStride() const13607 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13608 {
13609 const glw::GLuint n_args = getArgumentCount();
13610 glw::GLuint result = 0;
13611
13612 for (glw::GLuint i = 0; i < n_args; ++i)
13613 {
13614 result += getArgumentStride(i);
13615 }
13616
13617 return result;
13618 }
13619
13620 /** Get stride in bytes of <argument>
13621 *
13622 * @param argument Argument ordinal, starts with 0
13623 *
13624 * @return Stride of argument
13625 **/
getArgumentStride(glw::GLuint argument) const13626 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13627 {
13628 const glw::GLuint component_size = getArgumentComponentSize(argument);
13629 const glw::GLuint n_components = getArgumentComponents(argument);
13630
13631 return n_components * component_size;
13632 }
13633
13634 /** Get function enumeration
13635 *
13636 * @return Function enumeration
13637 **/
getFunctionEnum() const13638 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13639 {
13640 return m_function_enum;
13641 }
13642
13643 /** Get function name
13644 *
13645 * @return Function name
13646 **/
getName() const13647 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13648 {
13649 return m_function_name;
13650 }
13651
13652 /** Get number of components for <result>
13653 *
13654 * @param result Result ordinal, starts with 0
13655 *
13656 * @return Number of components
13657 **/
getResultComponents(glw::GLuint result) const13658 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13659 {
13660 const Utils::_variable_type type = getResultType(result);
13661 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13662
13663 return n_components;
13664 }
13665
13666 /** Get number of results
13667 *
13668 * @return Number of results
13669 **/
getResultCount() const13670 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13671 {
13672 return 1;
13673 }
13674
13675 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13676 *
13677 * @param result Result ordinal, starts with 0
13678 *
13679 * @return Offset
13680 **/
getResultOffset(glw::GLuint result) const13681 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13682 {
13683 glw::GLuint offset = 0;
13684
13685 for (glw::GLuint i = 0; i < result; ++i)
13686 {
13687 offset += getResultStride(i);
13688 offset = deAlign32(offset, getBaseTypeSize(i));
13689 }
13690
13691 return offset;
13692 }
13693
13694 /** Get stride in bytes of <result>.
13695 *
13696 * @param result Result ordinal, starts with 0
13697 *
13698 * @return Stride
13699 **/
getResultStride(glw::GLuint result) const13700 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13701 {
13702 const Utils::_variable_type type = getResultType(result);
13703 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13704
13705 return n_components * getBaseTypeSize(result);
13706 }
13707
13708 /** Get size in bytes of <result> base component.
13709 *
13710 * @param result Result ordinal, starts with 0
13711 *
13712 * @return Alignment
13713 **/
getBaseTypeSize(glw::GLuint result) const13714 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13715 {
13716 const Utils::_variable_type type = getResultType(result);
13717 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13718 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13719
13720 return base_type_size;
13721 }
13722
13723 /** Get stride in bytes of all results.
13724 *
13725 * @return Stride
13726 **/
getResultStride() const13727 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13728 {
13729 const glw::GLuint n_results = getResultCount();
13730 glw::GLuint stride = 0;
13731 glw::GLuint maxAlignment = 0;
13732
13733 for (glw::GLuint i = 0; i < n_results; ++i)
13734 {
13735 const glw::GLuint alignment = getBaseTypeSize(i);
13736 stride += getResultStride(i);
13737 stride = deAlign32(stride, alignment);
13738 maxAlignment = deMaxu32(maxAlignment, alignment);
13739 }
13740
13741 // The stride of all results must also be aligned,
13742 // so results for next vertex are aligned.
13743 return deAlign32(stride, maxAlignment);
13744 }
13745
13746 /** Get type of <result>.
13747 *
13748 * @param result Result ordinal, starts with 0
13749 *
13750 * @return Type
13751 **/
getResultType(glw::GLuint) const13752 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13753 {
13754 return m_res_type;
13755 }
13756
13757 /** Constructor
13758 *
13759 * @param n_columns Number of columns
13760 * @param n_rows Number of rows
13761 **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13762 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13763 : m_n_columns(n_columns), m_n_rows(n_rows)
13764 {
13765 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13766 m_type = Utils::getGLDataTypeOfVariableType(type);
13767 m_type_name = Utils::getVariableTypeString(type);
13768
13769 if (1 == m_n_columns)
13770 {
13771 if (1 == m_n_rows)
13772 {
13773 m_general_type = SCALAR;
13774 }
13775 else
13776 {
13777 m_general_type = VECTOR;
13778 }
13779 }
13780 else
13781 {
13782 m_general_type = MATRIX;
13783 }
13784 }
13785
13786 /** Compare two values
13787 *
13788 * @param type Type of values
13789 * @param left Pointer to left value
13790 * @param right Pointer to right value
13791 *
13792 * @return true if values are equal, false otherwise
13793 **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13794 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13795 {
13796 bool result = true;
13797
13798 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13799 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13800
13801 switch (base_type)
13802 {
13803 case Utils::VARIABLE_TYPE_DOUBLE:
13804
13805 {
13806 const glw::GLdouble* left_values = (glw::GLdouble*)left;
13807 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13808
13809 for (glw::GLuint component = 0; component < n_components; ++component)
13810 {
13811 const glw::GLdouble left_value = left_values[component];
13812 const glw::GLdouble right_value = right_values[component];
13813
13814 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13815 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13816 {
13817 result = false;
13818 break;
13819 }
13820 }
13821 }
13822
13823 break;
13824
13825 case Utils::VARIABLE_TYPE_INT:
13826
13827 {
13828 const glw::GLint* left_values = (glw::GLint*)left;
13829 const glw::GLint* right_values = (glw::GLint*)right;
13830
13831 for (glw::GLuint component = 0; component < n_components; ++component)
13832 {
13833 const glw::GLint left_value = left_values[component];
13834 const glw::GLint right_value = right_values[component];
13835
13836 if (left_value != right_value)
13837 {
13838 result = false;
13839 break;
13840 }
13841 }
13842 }
13843
13844 break;
13845
13846 case Utils::VARIABLE_TYPE_UINT:
13847
13848 {
13849 const glw::GLuint* left_values = (glw::GLuint*)left;
13850 const glw::GLuint* right_values = (glw::GLuint*)right;
13851
13852 for (glw::GLuint component = 0; component < n_components; ++component)
13853 {
13854 const glw::GLuint left_value = left_values[component];
13855 const glw::GLuint right_value = right_values[component];
13856
13857 if (left_value != right_value)
13858 {
13859 result = false;
13860 break;
13861 }
13862 }
13863 }
13864
13865 break;
13866
13867 default:
13868
13869 TCU_FAIL("Not implemented");
13870 }
13871
13872 return result;
13873 }
13874
13875 /** Create instance of function object for given function enumeration and type
13876 *
13877 * @param function Function enumeration
13878 * @param type Type details
13879 *
13880 * @return Create object
13881 **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13882 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
13883 const typeDetails& type)
13884 {
13885 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13886 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13887 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13888 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13889 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13890 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13891 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13892 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13893 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13894
13895 const glw::GLuint n_columns = type.m_n_columns;
13896 const glw::GLuint n_rows = type.m_n_rows;
13897 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1);
13898 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13899 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows);
13900 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows);
13901
13902 switch (function)
13903 {
13904 case FUNCTION_ABS:
13905
13906 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13907 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13908
13909 case FUNCTION_CEIL:
13910
13911 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13912 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13913
13914 case FUNCTION_CLAMP:
13915
13916 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13917 variable_type /* arg1_type */, variable_type /* arg2_type */,
13918 variable_type /* arg3_type */);
13919
13920 case FUNCTION_CLAMP_AGAINST_SCALAR:
13921
13922 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13923 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13924 scalar_type /* arg3_type */);
13925
13926 case FUNCTION_CROSS:
13927
13928 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13929 function, "cross", tcu::cross);
13930
13931 case FUNCTION_DETERMINANT:
13932
13933 switch (variable_type)
13934 {
13935 case Utils::VARIABLE_TYPE_DMAT2:
13936 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13937 Math::determinant);
13938 case Utils::VARIABLE_TYPE_DMAT3:
13939 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13940 Math::determinant);
13941 case Utils::VARIABLE_TYPE_DMAT4:
13942 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13943 Math::determinant);
13944 default:
13945 TCU_FAIL("Not implemented");
13946 }
13947
13948 case FUNCTION_DISTANCE:
13949
13950 switch (variable_type)
13951 {
13952 case Utils::VARIABLE_TYPE_DVEC2:
13953 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13954 function, "distance", tcu::distance);
13955 case Utils::VARIABLE_TYPE_DVEC3:
13956 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13957 function, "distance", tcu::distance);
13958 case Utils::VARIABLE_TYPE_DVEC4:
13959 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13960 function, "distance", tcu::distance);
13961 default:
13962 break;
13963 }
13964
13965 break;
13966
13967 case FUNCTION_DOT:
13968
13969 switch (variable_type)
13970 {
13971 case Utils::VARIABLE_TYPE_DVEC2:
13972 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13973 function, "dot", tcu::dot);
13974 case Utils::VARIABLE_TYPE_DVEC3:
13975 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13976 function, "dot", tcu::dot);
13977 case Utils::VARIABLE_TYPE_DVEC4:
13978 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13979 function, "dot", tcu::dot);
13980 default:
13981 break;
13982 }
13983
13984 break;
13985
13986 case FUNCTION_EQUAL:
13987
13988 switch (variable_type)
13989 {
13990 case Utils::VARIABLE_TYPE_DVEC2:
13991 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13992 function, "equal", Math::equal);
13993 case Utils::VARIABLE_TYPE_DVEC3:
13994 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13995 function, "equal", Math::equal);
13996 case Utils::VARIABLE_TYPE_DVEC4:
13997 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13998 function, "equal", Math::equal);
13999 default:
14000 break;
14001 }
14002
14003 break;
14004
14005 case FUNCTION_FACEFORWARD:
14006
14007 switch (variable_type)
14008 {
14009 case Utils::VARIABLE_TYPE_DVEC2:
14010 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14011 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14012 function, "faceforward", tcu::faceForward);
14013 case Utils::VARIABLE_TYPE_DVEC3:
14014 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14015 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14016 function, "faceforward", tcu::faceForward);
14017 case Utils::VARIABLE_TYPE_DVEC4:
14018 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14019 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14020 function, "faceforward", tcu::faceForward);
14021 default:
14022 break;
14023 }
14024
14025 break;
14026
14027 case FUNCTION_FLOOR:
14028
14029 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14030 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14031
14032 case FUNCTION_FMA:
14033
14034 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */,
14035 variable_type /* arg1_type */, variable_type /* arg2_type */,
14036 variable_type /* arg3_type */);
14037
14038 case FUNCTION_FRACT:
14039
14040 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14041 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14042
14043 case FUNCTION_FREXP:
14044
14045 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14046 glw::GLint /* OutT */>(
14047 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14048 int_type /* out_type */);
14049
14050 case FUNCTION_GREATERTHAN:
14051
14052 switch (variable_type)
14053 {
14054 case Utils::VARIABLE_TYPE_DVEC2:
14055 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14056 function, "greaterThan", Math::greaterThan);
14057 case Utils::VARIABLE_TYPE_DVEC3:
14058 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14059 function, "greaterThan", Math::greaterThan);
14060 case Utils::VARIABLE_TYPE_DVEC4:
14061 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14062 function, "greaterThan", Math::greaterThan);
14063 default:
14064 break;
14065 }
14066
14067 break;
14068
14069 case FUNCTION_GREATERTHANEQUAL:
14070
14071 switch (variable_type)
14072 {
14073 case Utils::VARIABLE_TYPE_DVEC2:
14074 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14075 function, "greaterThanEqual", Math::greaterThanEqual);
14076 case Utils::VARIABLE_TYPE_DVEC3:
14077 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14078 function, "greaterThanEqual", Math::greaterThanEqual);
14079 case Utils::VARIABLE_TYPE_DVEC4:
14080 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14081 function, "greaterThanEqual", Math::greaterThanEqual);
14082 default:
14083 break;
14084 }
14085
14086 break;
14087
14088 case FUNCTION_INVERSE:
14089
14090 switch (variable_type)
14091 {
14092 case Utils::VARIABLE_TYPE_DMAT2:
14093 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14094 case Utils::VARIABLE_TYPE_DMAT3:
14095 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14096 case Utils::VARIABLE_TYPE_DMAT4:
14097 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14098 default:
14099 break;
14100 }
14101
14102 break;
14103
14104 case FUNCTION_INVERSESQRT:
14105
14106 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14107 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14108
14109 case FUNCTION_LDEXP:
14110
14111 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14112 glw::GLint /* Arg2T */>(
14113 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */,
14114 int_type /* arg2_type */);
14115
14116 case FUNCTION_LESSTHAN:
14117
14118 switch (variable_type)
14119 {
14120 case Utils::VARIABLE_TYPE_DVEC2:
14121 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14122 function, "lessThan", Math::lessThan);
14123 case Utils::VARIABLE_TYPE_DVEC3:
14124 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14125 function, "lessThan", Math::lessThan);
14126 case Utils::VARIABLE_TYPE_DVEC4:
14127 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14128 function, "lessThan", Math::lessThan);
14129 default:
14130 break;
14131 }
14132
14133 break;
14134
14135 case FUNCTION_LESSTHANEQUAL:
14136
14137 switch (variable_type)
14138 {
14139 case Utils::VARIABLE_TYPE_DVEC2:
14140 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14141 function, "lessThanEqual", Math::lessThanEqual);
14142 case Utils::VARIABLE_TYPE_DVEC3:
14143 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14144 function, "lessThanEqual", Math::lessThanEqual);
14145 case Utils::VARIABLE_TYPE_DVEC4:
14146 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14147 function, "lessThanEqual", Math::lessThanEqual);
14148 default:
14149 break;
14150 }
14151
14152 break;
14153
14154 case FUNCTION_LENGTH:
14155
14156 switch (variable_type)
14157 {
14158 case Utils::VARIABLE_TYPE_DVEC2:
14159 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14160 tcu::length);
14161 case Utils::VARIABLE_TYPE_DVEC3:
14162 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14163 tcu::length);
14164 case Utils::VARIABLE_TYPE_DVEC4:
14165 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14166 tcu::length);
14167 default:
14168 break;
14169 }
14170
14171 break;
14172
14173 case FUNCTION_MATRIXCOMPMULT:
14174
14175 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14176 glw::GLdouble /* Arg2T */>(
14177 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */,
14178 variable_type /* arg2_type */);
14179
14180 case FUNCTION_MAX:
14181
14182 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14183 glw::GLdouble /* Arg2T */>(
14184 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14185 variable_type /* arg2_type */);
14186
14187 case FUNCTION_MAX_AGAINST_SCALAR:
14188
14189 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14190 glw::GLdouble /* Arg2T */>(
14191 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14192 scalar_type /* arg2_type */);
14193
14194 case FUNCTION_MIN:
14195
14196 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14197 glw::GLdouble /* Arg2T */>(
14198 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14199 variable_type /* arg2_type */);
14200
14201 case FUNCTION_MIN_AGAINST_SCALAR:
14202
14203 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14204 glw::GLdouble /* Arg2T */>(
14205 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14206 scalar_type /* arg2_type */);
14207
14208 case FUNCTION_MIX:
14209
14210 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */,
14211 variable_type /* arg1_type */, variable_type /* arg2_type */,
14212 variable_type /* arg3_type */);
14213
14214 case FUNCTION_MOD:
14215
14216 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14217 glw::GLdouble /* Arg2T */>(
14218 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14219 variable_type /* arg2_type */);
14220
14221 case FUNCTION_MOD_AGAINST_SCALAR:
14222
14223 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14224 glw::GLdouble /* Arg2T */>(
14225 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14226 scalar_type /* arg2_type */);
14227
14228 case FUNCTION_MODF:
14229
14230 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14231 glw::GLdouble /* OutT */>(
14232 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14233 variable_type /* out_type */);
14234
14235 case FUNCTION_NORMALIZE:
14236
14237 switch (variable_type)
14238 {
14239 case Utils::VARIABLE_TYPE_DVEC2:
14240 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14241 tcu::normalize);
14242 case Utils::VARIABLE_TYPE_DVEC3:
14243 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14244 tcu::normalize);
14245 case Utils::VARIABLE_TYPE_DVEC4:
14246 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14247 tcu::normalize);
14248 default:
14249 break;
14250 }
14251
14252 break;
14253
14254 case FUNCTION_NOTEQUAL:
14255
14256 switch (variable_type)
14257 {
14258 case Utils::VARIABLE_TYPE_DVEC2:
14259 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14260 function, "notEqual", Math::notEqual);
14261 case Utils::VARIABLE_TYPE_DVEC3:
14262 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14263 function, "notEqual", Math::notEqual);
14264 case Utils::VARIABLE_TYPE_DVEC4:
14265 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14266 function, "notEqual", Math::notEqual);
14267 default:
14268 break;
14269 }
14270
14271 break;
14272
14273 case FUNCTION_OUTERPRODUCT:
14274
14275 switch (variable_type)
14276 {
14277 case Utils::VARIABLE_TYPE_DMAT2:
14278 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14279 function, "outerProduct", Math::outerProduct);
14280 case Utils::VARIABLE_TYPE_DMAT2X3:
14281 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14282 function, "outerProduct", Math::outerProduct);
14283 case Utils::VARIABLE_TYPE_DMAT2X4:
14284 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14285 function, "outerProduct", Math::outerProduct);
14286 case Utils::VARIABLE_TYPE_DMAT3:
14287 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14288 function, "outerProduct", Math::outerProduct);
14289 case Utils::VARIABLE_TYPE_DMAT3X2:
14290 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14291 function, "outerProduct", Math::outerProduct);
14292 case Utils::VARIABLE_TYPE_DMAT3X4:
14293 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14294 function, "outerProduct", Math::outerProduct);
14295 case Utils::VARIABLE_TYPE_DMAT4:
14296 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14297 function, "outerProduct", Math::outerProduct);
14298 case Utils::VARIABLE_TYPE_DMAT4X2:
14299 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14300 function, "outerProduct", Math::outerProduct);
14301 case Utils::VARIABLE_TYPE_DMAT4X3:
14302 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14303 function, "outerProduct", Math::outerProduct);
14304 default:
14305 break;
14306 }
14307
14308 break;
14309
14310 case FUNCTION_PACKDOUBLE2X32:
14311
14312 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14313 Math::packDouble2x32);
14314
14315 case FUNCTION_REFLECT:
14316
14317 switch (variable_type)
14318 {
14319 case Utils::VARIABLE_TYPE_DVEC2:
14320 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14321 function, "reflect", tcu::reflect);
14322 case Utils::VARIABLE_TYPE_DVEC3:
14323 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14324 function, "reflect", tcu::reflect);
14325 case Utils::VARIABLE_TYPE_DVEC4:
14326 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14327 function, "reflect", tcu::reflect);
14328 default:
14329 break;
14330 }
14331
14332 break;
14333
14334 case FUNCTION_REFRACT:
14335
14336 switch (variable_type)
14337 {
14338 case Utils::VARIABLE_TYPE_DVEC2:
14339 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14340 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14341 function, "refract", tcu::refract);
14342 case Utils::VARIABLE_TYPE_DVEC3:
14343 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14344 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14345 function, "refract", tcu::refract);
14346 case Utils::VARIABLE_TYPE_DVEC4:
14347 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14348 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14349 function, "refract", tcu::refract);
14350 default:
14351 break;
14352 }
14353
14354 break;
14355
14356 case FUNCTION_ROUND:
14357
14358 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14359 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14360
14361 case FUNCTION_ROUNDEVEN:
14362
14363 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14364 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14365
14366 case FUNCTION_SIGN:
14367
14368 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14369 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14370
14371 case FUNCTION_SMOOTHSTEP:
14372
14373 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14374 variable_type /* res_type */, variable_type /* arg1_type */,
14375 variable_type /* arg2_type */, variable_type /* arg3_type */);
14376
14377 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14378
14379 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14380 variable_type /* res_type */, scalar_type /* arg1_type */,
14381 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14382
14383 case FUNCTION_SQRT:
14384
14385 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14386 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14387
14388 case FUNCTION_STEP:
14389
14390 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14391 glw::GLdouble /* Arg2T */>(
14392 function, "step", Math::step, variable_type /* res_type */, variable_type /* arg1_type */,
14393 variable_type /* arg2_type */);
14394
14395 case FUNCTION_STEP_AGAINST_SCALAR:
14396
14397 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14398 glw::GLdouble /* Arg2T */>(
14399 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */,
14400 variable_type /* arg2_type */);
14401
14402 case FUNCTION_TRANSPOSE:
14403
14404 switch (variable_type)
14405 {
14406 case Utils::VARIABLE_TYPE_DMAT2:
14407 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14408 Math::transpose);
14409 case Utils::VARIABLE_TYPE_DMAT2X3:
14410 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14411 Math::transpose);
14412 case Utils::VARIABLE_TYPE_DMAT2X4:
14413 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14414 Math::transpose);
14415 case Utils::VARIABLE_TYPE_DMAT3:
14416 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14417 Math::transpose);
14418 case Utils::VARIABLE_TYPE_DMAT3X2:
14419 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14420 Math::transpose);
14421 case Utils::VARIABLE_TYPE_DMAT3X4:
14422 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14423 Math::transpose);
14424 case Utils::VARIABLE_TYPE_DMAT4:
14425 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14426 Math::transpose);
14427 case Utils::VARIABLE_TYPE_DMAT4X2:
14428 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14429 Math::transpose);
14430 case Utils::VARIABLE_TYPE_DMAT4X3:
14431 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14432 Math::transpose);
14433 default:
14434 break;
14435 }
14436
14437 break;
14438
14439 case FUNCTION_TRUNC:
14440
14441 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14442 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14443
14444 case FUNCTION_UNPACKDOUBLE2X32:
14445
14446 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14447 Math::unpackDouble2x32);
14448
14449 case FUNCTION_ISNAN:
14450
14451 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14452 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14453
14454 case FUNCTION_ISINF:
14455
14456 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14457 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14458
14459 default:
14460 TCU_FAIL("Not implemented");
14461 return 0;
14462 }
14463
14464 TCU_FAIL("Not implemented");
14465 return 0;
14466 }
14467
14468 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14469 *
14470 * @param argument Argument index
14471 * @param function_object Function object
14472 *
14473 * @return Function pointer
14474 **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14475 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14476 glw::GLuint argument, const functionObject& function_object) const
14477 {
14478 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14479 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14480
14481 switch (argument_type)
14482 {
14483 case Utils::VARIABLE_TYPE_DMAT2:
14484 return gl.uniformMatrix2dv;
14485 case Utils::VARIABLE_TYPE_DMAT2X3:
14486 return gl.uniformMatrix2x3dv;
14487 case Utils::VARIABLE_TYPE_DMAT2X4:
14488 return gl.uniformMatrix2x4dv;
14489 case Utils::VARIABLE_TYPE_DMAT3:
14490 return gl.uniformMatrix3dv;
14491 case Utils::VARIABLE_TYPE_DMAT3X2:
14492 return gl.uniformMatrix3x2dv;
14493 case Utils::VARIABLE_TYPE_DMAT3X4:
14494 return gl.uniformMatrix3x4dv;
14495 case Utils::VARIABLE_TYPE_DMAT4:
14496 return gl.uniformMatrix4dv;
14497 case Utils::VARIABLE_TYPE_DMAT4X2:
14498 return gl.uniformMatrix4x2dv;
14499 case Utils::VARIABLE_TYPE_DMAT4X3:
14500 return gl.uniformMatrix4x3dv;
14501 default:
14502 break;
14503 }
14504
14505 TCU_FAIL("Not implemented");
14506 return 0;
14507 }
14508
14509 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14510 *
14511 * @param argument Argument index
14512 * @param function_object Function object
14513 *
14514 * @return Function pointer
14515 **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14516 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14517 glw::GLuint argument, const functionObject& function_object) const
14518 {
14519 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14520 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14521
14522 switch (argument_type)
14523 {
14524 case Utils::VARIABLE_TYPE_DOUBLE:
14525 return gl.uniform1dv;
14526 case Utils::VARIABLE_TYPE_DVEC2:
14527 return gl.uniform2dv;
14528 case Utils::VARIABLE_TYPE_DVEC3:
14529 return gl.uniform3dv;
14530 case Utils::VARIABLE_TYPE_DVEC4:
14531 return gl.uniform4dv;
14532 default:
14533 TCU_FAIL("Not implemented");
14534 }
14535
14536 return 0;
14537 }
14538
14539 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14540 *
14541 * @param argument Argument index
14542 * @param function_object Function object
14543 *
14544 * @return Function pointer
14545 **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14546 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14547 glw::GLuint argument, const functionObject& function_object) const
14548 {
14549 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14550 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14551
14552 switch (argument_type)
14553 {
14554 case Utils::VARIABLE_TYPE_INT:
14555 return gl.uniform1iv;
14556 case Utils::VARIABLE_TYPE_IVEC2:
14557 return gl.uniform2iv;
14558 case Utils::VARIABLE_TYPE_IVEC3:
14559 return gl.uniform3iv;
14560 case Utils::VARIABLE_TYPE_IVEC4:
14561 return gl.uniform4iv;
14562 default:
14563 TCU_FAIL("Not implemented");
14564 }
14565
14566 return 0;
14567 }
14568
14569 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14570 *
14571 * @param argument Argument index
14572 * @param function_object Function object
14573 *
14574 * @return Function pointer
14575 **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14576 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14577 glw::GLuint argument, const functionObject& function_object) const
14578 {
14579 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14580 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14581
14582 switch (argument_type)
14583 {
14584 case Utils::VARIABLE_TYPE_UVEC2:
14585 return gl.uniform2uiv;
14586 default:
14587 TCU_FAIL("Not implemented");
14588 }
14589
14590 return 0;
14591 }
14592
14593 /** Get name of uniform that will be used as <argument>.
14594 *
14595 * @param argument Argument index
14596 *
14597 * @return Name of uniform
14598 **/
getUniformName(glw::GLuint argument) const14599 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14600 {
14601 switch (argument)
14602 {
14603 case 0:
14604 return "uniform_0";
14605 case 1:
14606 return "uniform_1";
14607 case 2:
14608 return "uniform_2";
14609 default:
14610 TCU_FAIL("Not implemented");
14611 return 0;
14612 }
14613 }
14614
14615 /** Get name of varying that will be used as <result>.
14616 *
14617 * @param result Result index
14618 *
14619 * @return Name of varying
14620 **/
getVaryingName(glw::GLuint result) const14621 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14622 {
14623 switch (result)
14624 {
14625 case 0:
14626 return "result_0";
14627 case 1:
14628 return "result_1";
14629 case 2:
14630 return "result_2";
14631 default:
14632 TCU_FAIL("Not implemented");
14633 return 0;
14634 }
14635 }
14636
14637 /** Check if given combination of function and type is implemented
14638 *
14639 * @param function Function enumeration
14640 * @param type Type details
14641 *
14642 * @return true if function is available for given type, false otherwise
14643 **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14644 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14645 {
14646 static const bool look_up_table[][3] = {
14647 /* SCALAR, VECTOR, MATRIX */
14648 /* FUNCTION_ABS: */ { true, true, false },
14649 /* FUNCTION_CEIL: */ { true, true, false },
14650 /* FUNCTION_CLAMP: */ { true, true, false },
14651 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false },
14652 /* FUNCTION_CROSS: */ { false, true, false },
14653 /* FUNCTION_DETERMINANT: */ { false, false, true },
14654 /* FUNCTION_DISTANCE: */ { false, true, false },
14655 /* FUNCTION_DOT: */ { false, true, false },
14656 /* FUNCTION_EQUAL: */ { false, true, false },
14657 /* FUNCTION_FACEFORWARD: */ { false, true, false },
14658 /* FUNCTION_FLOOR: */ { true, true, false },
14659 /* FUNCTION_FMA: */ { true, true, false },
14660 /* FUNCTION_FRACT: */ { true, true, false },
14661 /* FUNCTION_FREXP: */ { true, true, false },
14662 /* FUNCTION_GREATERTHAN: */ { false, true, false },
14663 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false },
14664 /* FUNCTION_INVERSE: */ { false, false, true },
14665 /* FUNCTION_INVERSESQRT: */ { true, true, false },
14666 /* FUNCTION_LDEXP: */ { true, true, false },
14667 /* FUNCTION_LESSTHAN: */ { false, true, false },
14668 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false },
14669 /* FUNCTION_LENGTH: */ { false, true, false },
14670 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true },
14671 /* FUNCTION_MAX: */ { true, true, false },
14672 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false },
14673 /* FUNCTION_MIN: */ { true, true, false },
14674 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false },
14675 /* FUNCTION_MIX: */ { true, true, false },
14676 /* FUNCTION_MOD: */ { true, true, false },
14677 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false },
14678 /* FUNCTION_MODF: */ { true, true, false },
14679 /* FUNCTION_NORMALIZE: */ { false, true, false },
14680 /* FUNCTION_NOTEQUAL: */ { false, true, false },
14681 /* FUNCTION_OUTERPRODUCT: */ { false, false, true },
14682 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false },
14683 /* FUNCTION_REFLECT: */ { false, true, false },
14684 /* FUNCTION_REFRACT: */ { false, true, false },
14685 /* FUNCTION_ROUND: */ { true, true, false },
14686 /* FUNCTION_ROUNDEVEN: */ { true, true, false },
14687 /* FUNCTION_SIGN: */ { true, false, false },
14688 /* FUNCTION_SMOOTHSTEP: */ { true, true, false },
14689 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14690 /* FUNCTION_SQRT: */ { true, true, false },
14691 /* FUNCTION_STEP: */ { true, true, false },
14692 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false },
14693 /* FUNCTION_TRANSPOSE: */ { false, false, false },
14694 /* FUNCTION_TRUNC: */ { true, true, false },
14695 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false },
14696 /* FUNCTION_ISNAN: */ { true, true, false },
14697 /* FUNCTION_ISINF: */ { true, true, false },
14698 };
14699
14700 bool result = look_up_table[function][type.m_general_type];
14701
14702 if (true == result)
14703 {
14704 switch (function)
14705 {
14706 case FUNCTION_CROSS: /* Only 3 element vectors */
14707 result = (3 == type.m_n_rows);
14708 break;
14709 case FUNCTION_DETERMINANT: /* Only square matrices */
14710 case FUNCTION_INVERSE:
14711 result = (type.m_n_columns == type.m_n_rows);
14712 break;
14713 default:
14714 break;
14715 }
14716 }
14717
14718 return result;
14719 }
14720
14721 /** Logs variable of given type: name (type) [values]
14722 *
14723 * @param buffer Source of data
14724 * @param name Name of variable
14725 * @param type Type of variable
14726 **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14727 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14728 Utils::_variable_type type) const
14729 {
14730 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14731 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
14732 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14733
14734 message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14735
14736 for (glw::GLuint component = 0; component < n_components; ++component)
14737 {
14738 if (0 != component)
14739 {
14740 message << ", ";
14741 }
14742
14743 switch (base_type)
14744 {
14745 case Utils::VARIABLE_TYPE_DOUBLE:
14746 message << ((glw::GLdouble*)buffer)[component];
14747 break;
14748 case Utils::VARIABLE_TYPE_INT:
14749 message << ((glw::GLint*)buffer)[component];
14750 break;
14751 case Utils::VARIABLE_TYPE_UINT:
14752 message << ((glw::GLuint*)buffer)[component];
14753 break;
14754 default:
14755 TCU_FAIL("Not implemented");
14756 }
14757 }
14758
14759 message << "]" << tcu::TestLog::EndMessage;
14760 }
14761
14762 /** Prepare input arguments, data are stored in <buffer>
14763 *
14764 * @param function_object Function object
14765 * @param vertex Vertex index
14766 * @param buffer Buffer pointer
14767 **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14768 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14769 glw::GLubyte* buffer)
14770 {
14771 const glw::GLuint n_arguments = function_object.getArgumentCount();
14772
14773 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14774 {
14775 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14776
14777 prepareComponents(function_object, vertex, argument, buffer + offset);
14778 }
14779 }
14780
14781 /** Prepare components for given <function_object>, <vertex> and <argument>
14782 *
14783 * @param function_object Function object
14784 * @param vertex Vertex index
14785 * @param argument Argument index
14786 * @param buffer Buffer pointer
14787 **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14788 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14789 glw::GLuint argument, glw::GLubyte* buffer)
14790 {
14791 glw::GLuint argument_index[3] = { 0 };
14792 glw::GLuint argument_reset[3] = { 0 };
14793 glw::GLuint argument_step[3] = { 0 };
14794 glw::GLdouble double_argument_start[3] = { 0.0 };
14795 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14796 glw::GLuint int_argument_start = -4;
14797 const glw::GLuint n_arguments = function_object.getArgumentCount();
14798 const glw::GLuint n_components = function_object.getArgumentComponents(argument);
14799 glw::GLuint uint_argument_start = 0;
14800
14801 switch (n_arguments)
14802 {
14803 case 1:
14804 argument_step[0] = 1;
14805 argument_reset[0] = 1024;
14806 double_argument_start[0] = -511.5;
14807 break;
14808 case 2:
14809 argument_step[0] = 32;
14810 argument_step[1] = 1;
14811 argument_reset[0] = 32;
14812 argument_reset[1] = 32;
14813 double_argument_start[0] = -15.5;
14814 double_argument_start[1] = -15.5;
14815 break;
14816 case 3:
14817 argument_step[0] = 64;
14818 argument_step[1] = 8;
14819 argument_step[2] = 1;
14820 argument_reset[0] = 16;
14821 argument_reset[1] = 8;
14822 argument_reset[2] = 8;
14823 double_argument_start[0] = -7.5;
14824 double_argument_start[1] = -3.5;
14825 double_argument_start[2] = -3.5;
14826 break;
14827 default:
14828 TCU_FAIL("Not implemented");
14829 return;
14830 }
14831
14832 switch (function_object.getFunctionEnum())
14833 {
14834 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14835 case FUNCTION_CLAMP_AGAINST_SCALAR:
14836 double_argument_start[2] = 4.5;
14837 break;
14838 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14839 double_argument_start[0] = 16.5;
14840 break;
14841 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14842 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14843 argument_step[0] = 1;
14844 argument_step[1] = 8;
14845 argument_step[2] = 64;
14846 argument_reset[0] = 8;
14847 argument_reset[1] = 8;
14848 argument_reset[2] = 16;
14849 double_argument_start[0] = -3.5;
14850 double_argument_start[1] = 4.5;
14851 double_argument_start[2] = -7.5;
14852 break;
14853 default:
14854 break;
14855 }
14856
14857 for (glw::GLuint i = 0; i < n_arguments; ++i)
14858 {
14859 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14860 }
14861
14862 switch (base_arg_type)
14863 {
14864 case Utils::VARIABLE_TYPE_DOUBLE:
14865 {
14866 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14867
14868 double_argument_start[argument] += argument_index[argument];
14869
14870 for (glw::GLuint component = 0; component < n_components; ++component)
14871 {
14872 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14873
14874 switch (function_object.getFunctionEnum())
14875 {
14876 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14877 if (0.5 == Math::fract(value))
14878 {
14879 value += 0.01;
14880 }
14881 break;
14882 default:
14883 break;
14884 }
14885
14886 argument_dst[component] = value;
14887 }
14888 }
14889 break;
14890 case Utils::VARIABLE_TYPE_INT:
14891 {
14892 glw::GLint* argument_dst = (glw::GLint*)buffer;
14893
14894 uint_argument_start += argument_index[argument];
14895
14896 for (glw::GLuint component = 0; component < n_components; ++component)
14897 {
14898 const glw::GLint value = int_argument_start + component;
14899
14900 argument_dst[component] = value;
14901 }
14902 }
14903 break;
14904 case Utils::VARIABLE_TYPE_UINT:
14905 {
14906 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14907
14908 uint_argument_start += argument_index[argument];
14909
14910 for (glw::GLuint component = 0; component < n_components; ++component)
14911 {
14912 const glw::GLuint value = uint_argument_start + component;
14913
14914 argument_dst[component] = value;
14915 }
14916 }
14917 break;
14918 default:
14919 TCU_FAIL("Not implemented");
14920 return;
14921 }
14922 }
14923
14924 /** Prepare programInfo for given functionObject
14925 *
14926 * @param function_object Function object
14927 * @param out_program_info Program info
14928 **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14929 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14930 {
14931 const glw::GLuint n_varying_names = function_object.getResultCount();
14932 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14933
14934 prepareVertexShaderCode(function_object);
14935
14936 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14937 varying_names, n_varying_names);
14938 }
14939
14940 /** Prepare input data and expected results for given function object
14941 *
14942 * @param function_object Function object
14943 **/
prepareTestData(const functionObject & function_object)14944 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14945 {
14946 const glw::GLuint result_stride = function_object.getResultStride();
14947 const glw::GLuint result_buffer_size = result_stride * m_n_veritces;
14948 const glw::GLuint argument_stride = function_object.getArgumentStride();
14949 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14950
14951 m_argument_data.clear();
14952 m_expected_results_data.clear();
14953
14954 m_argument_data.resize(argument_buffer_size);
14955 m_expected_results_data.resize(result_buffer_size);
14956
14957 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14958 {
14959 const glw::GLuint result_offset = vertex * result_stride;
14960 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset];
14961 const glw::GLuint argument_offset = vertex * argument_stride;
14962 glw::GLubyte* argument_dst = &m_argument_data[argument_offset];
14963
14964 prepareArgument(function_object, vertex, argument_dst);
14965 function_object.call(result_dst, argument_dst);
14966 }
14967 }
14968
14969 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14970 *
14971 * @param function_object Function object
14972 **/
prepareVertexShaderCode(const functionObject & function_object)14973 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14974 {
14975 static const glw::GLchar* shader_template_code = "#version 400 core\n"
14976 "\n"
14977 "precision highp float;\n"
14978 "\n"
14979 "ARGUMENT_DEFINITION"
14980 "\n"
14981 "RESULT_DEFINITION"
14982 "\n"
14983 "void main()\n"
14984 "{\n"
14985 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14986 "}\n"
14987 "\n";
14988
14989 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
14990 static const glw::GLchar* argument_token = "ARGUMENT";
14991 static const glw::GLchar* function_name_token = "FUNCTION_NAME";
14992 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION";
14993 static const glw::GLchar* result_name_token = "RESULT_NAME";
14994 static const glw::GLchar* result_type_token = "RESULT_TYPE";
14995 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME";
14996 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE";
14997
14998 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
14999 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT";
15000 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT";
15001 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15002
15003 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15004 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument);
15005 const glw::GLuint n_arguments = function_object.getArgumentCount();
15006 const glw::GLuint n_results = function_object.getResultCount();
15007 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition);
15008 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0));
15009
15010 size_t search_position = 0;
15011 std::string string = shader_template_code;
15012
15013 /* Replace ARGUMENT_DEFINITION with definitions */
15014 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15015 {
15016 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15017 const glw::GLchar* uniform_name = getUniformName(argument);
15018 std::string uniform_type = Utils::getVariableTypeString(argument_type);
15019
15020 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15021
15022 search_position -= argument_definition_length;
15023
15024 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15025 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15026 }
15027
15028 /* Remove ARGUMENT_DEFINITION */
15029 Utils::replaceToken(argument_definition_token, search_position, "", string);
15030
15031 /* Replace RESULT_DEFINITION with definitions */
15032 for (glw::GLuint result = 0; result < n_results; ++result)
15033 {
15034 Utils::_variable_type variable_type = function_object.getResultType(result);
15035 const glw::GLchar* varying_name = getVaryingName(result);
15036 std::string varying_type = Utils::getVariableTypeString(variable_type);
15037
15038 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15039
15040 search_position -= result_definition_length;
15041
15042 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15043 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15044 }
15045
15046 /* Remove RESULT_DEFINITION */
15047 Utils::replaceToken(result_definition_token, search_position, "", string);
15048
15049 /* Replace RESULT_NAME */
15050 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15051
15052 /* Replace RESULT_TYPE */
15053 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15054
15055 /* Replace FUNCTION_NAME */
15056 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15057
15058 /* Replace ARGUMENT with list of arguments */
15059 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15060 {
15061 const glw::GLchar* uniform_name = getUniformName(argument);
15062
15063 if (0 == argument)
15064 {
15065 Utils::replaceToken(argument_token, search_position, first_argument, string);
15066 }
15067 else
15068 {
15069 Utils::replaceToken(argument_token, search_position, argument_str, string);
15070 }
15071
15072 search_position -= first_argument_length;
15073
15074 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15075 }
15076
15077 for (glw::GLuint result = 1; result < n_results; ++result)
15078 {
15079 const glw::GLchar* varying_name = getVaryingName(result);
15080
15081 Utils::replaceToken(argument_token, search_position, argument_str, string);
15082
15083 search_position -= first_argument_length;
15084
15085 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15086 }
15087
15088 /* Remove ARGUMENT */
15089 Utils::replaceToken(argument_token, search_position, "", string);
15090
15091 m_vertex_shader_code = string;
15092 }
15093
15094 /** Test single function with one type
15095 *
15096 * param function Function enumeration
15097 * param type Type details
15098 *
15099 * @return true if test pass (or function is not available for <type>), false otherwise
15100 **/
test(FunctionEnum function,const typeDetails & type)15101 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15102 {
15103 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15104
15105 /* Skip if function is not implemented for type */
15106 if (false == isFunctionImplemented(function, type))
15107 {
15108 return true;
15109 }
15110
15111 Utils::programInfo program(m_context);
15112 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15113
15114 prepareProgram(*function_object, program);
15115 prepareTestData(*function_object);
15116
15117 /* Set up program */
15118 gl.useProgram(program.m_program_object_id);
15119 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15120
15121 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15122 {
15123 testBegin(*function_object, program.m_program_object_id, vertex);
15124
15125 gl.beginTransformFeedback(GL_POINTS);
15126 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15127
15128 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15129 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15130
15131 gl.endTransformFeedback();
15132 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15133
15134 if (false == verifyResults(*function_object, vertex))
15135 {
15136 return false;
15137 }
15138 }
15139
15140 return true;
15141 }
15142
15143 /** Update transform feedback buffer and uniforms
15144 *
15145 * @param function_object Function object
15146 * @param program_id Program object id
15147 * @param vertex Vertex index
15148 **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15149 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15150 {
15151 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15152 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15153 const glw::GLuint n_arguments = function_object.getArgumentCount();
15154 const glw::GLuint result_buffer_size = function_object.getResultStride();
15155 const glw::GLuint vertex_offset = arguments_stride * vertex;
15156
15157 /* Update transform feedback buffer */
15158 std::vector<glw::GLubyte> transform_feedback_buffer_data;
15159 transform_feedback_buffer_data.resize(result_buffer_size);
15160
15161 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15162 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15163
15164 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15165 GL_DYNAMIC_COPY);
15166 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15167
15168 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15169 result_buffer_size);
15170 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15171
15172 /* Update VAO */
15173 gl.bindVertexArray(m_vertex_array_object_id);
15174 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15175
15176 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15177 {
15178 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15179 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15180 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type);
15181 const glw::GLchar* uniform_name = getUniformName(argument);
15182 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name);
15183 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15184
15185 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15186
15187 if (-1 == uniform_location)
15188 {
15189 TCU_FAIL("Inactive uniform");
15190 }
15191
15192 if (1 == n_columns)
15193 {
15194 switch (Utils::getBaseVariableType(argument_type))
15195 {
15196 case Utils::VARIABLE_TYPE_DOUBLE:
15197 {
15198 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15199
15200 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15201 }
15202 break;
15203 case Utils::VARIABLE_TYPE_UINT:
15204 {
15205 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15206
15207 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15208 }
15209 break;
15210 case Utils::VARIABLE_TYPE_INT:
15211 {
15212 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15213
15214 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15215 }
15216 break;
15217 default:
15218 TCU_FAIL("Not implemented");
15219 }
15220 }
15221 else
15222 {
15223 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15224
15225 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15226 }
15227 }
15228 }
15229
15230 /** Init GL obejcts
15231 *
15232 **/
testInit()15233 void BuiltinFunctionTest::testInit()
15234 {
15235 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15236
15237 gl.genBuffers(1, &m_transform_feedback_buffer_id);
15238 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15239
15240 gl.genVertexArrays(1, &m_vertex_array_object_id);
15241 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15242
15243 gl.enable(GL_RASTERIZER_DISCARD);
15244 }
15245
15246 /** Checks if function result is an acceptable edge case
15247 *
15248 * @param function_object Function object
15249 * @param vertex Vertex index
15250 *
15251 * @return true if all results are as expected, false otherwise
15252 **/
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)15253 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15254 const Utils::_variable_type result_type,
15255 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15256 {
15257 FunctionEnum function_type = function_object.getFunctionEnum();
15258 switch (function_type)
15259 {
15260 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15261 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15262 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15263 case FUNCTION_MOD:
15264 case FUNCTION_MOD_AGAINST_SCALAR:
15265 {
15266 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15267 const glw::GLuint vertex_offset = arguments_stride * vertex;
15268 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0);
15269 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1);
15270 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset;
15271 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset;
15272 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index];
15273 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index];
15274 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15275 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15276 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15277 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src);
15278 bool edge_case_present = false;
15279 bool recheck = false;
15280
15281 // verify if there is a mod(a, a) case and prepare new expected result
15282 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15283 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15284 for (glw::GLuint component = 0; component < n_components; ++component)
15285 {
15286 glw::GLdouble expected_result_component = expected_result[component];
15287 glw::GLdouble actual_result_component = actual_result[component];
15288 glw::GLdouble argument_1_component = argument_1[component];
15289 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15290
15291 // if coresponding components of arguments are equal and if component of first argument
15292 // and component of result are equal then expected result must be corrected
15293 edge_case_present = (m_epsilon > de::abs(argument_1_component - argument_2_component)) &&
15294 (m_epsilon > de::abs(argument_1_component - actual_result_component));
15295 recheck |= edge_case_present;
15296 corrected_expected_result[component] = edge_case_present ? argument_1_component : expected_result_component;
15297 }
15298
15299 // recheck test result with corrected expected result
15300 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15301 }
15302 default:
15303 return false;
15304 }
15305 }
15306
15307 /** Compare contents of transform feedback buffer with expected results
15308 *
15309 * @param function_object Function object
15310 * @param vertex Vertex index
15311 *
15312 * @return true if all results are as expected, false otherwise
15313 **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15314 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15315 {
15316 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15317 bool test_result = true;
15318 const glw::GLuint n_results = function_object.getResultCount();
15319 const glw::GLuint results_stride = function_object.getResultStride();
15320 const glw::GLuint results_offset = vertex * results_stride;
15321 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset];
15322
15323 /* Get transform feedback data */
15324 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15325 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15326
15327 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15328 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15329
15330 for (glw::GLuint result = 0; result < n_results; ++result)
15331 {
15332 const Utils::_variable_type result_type = function_object.getResultType(result);
15333 const glw::GLuint result_offset = function_object.getResultOffset(result);
15334
15335 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15336 const glw::GLvoid* result_src = feedback_data + result_offset;
15337
15338 if (compare(result_type, expected_result_src, result_src))
15339 continue;
15340
15341 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15342 {
15343 test_result = false;
15344 break;
15345 }
15346 }
15347
15348 /* Unmap transform feedback buffer */
15349 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15350 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15351
15352 if (false == test_result)
15353 {
15354 const glw::GLuint argument_stride = function_object.getArgumentStride();
15355 const glw::GLuint arguments_offset = vertex * argument_stride;
15356
15357 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15358 << tcu::TestLog::EndMessage;
15359
15360 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15361 << tcu::TestLog::EndMessage;
15362
15363 for (glw::GLuint result = 0; result < n_results; ++result)
15364 {
15365 const Utils::_variable_type result_type = function_object.getResultType(result);
15366 const glw::GLuint result_offset = function_object.getResultOffset(result);
15367
15368 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15369 const glw::GLvoid* result_src = feedback_data + result_offset;
15370
15371 logVariableType(result_src, "Result", result_type);
15372 logVariableType(expected_result_src, "Expected result", result_type);
15373 }
15374
15375 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15376 {
15377 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15378 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset];
15379
15380 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15381 }
15382
15383 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15384 << m_vertex_shader_code << tcu::TestLog::EndMessage;
15385 }
15386
15387 return test_result;
15388 }
15389
15390 /** Constructor.
15391 *
15392 * @param context Rendering context.
15393 **/
GPUShaderFP64Tests(deqp::Context & context)15394 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15395 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15396 {
15397 /* Left blank on purpose */
15398 }
15399
15400 /** Initializes a texture_storage_multisample test group.
15401 *
15402 **/
init(void)15403 void GPUShaderFP64Tests::init(void)
15404 {
15405 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15406 fp64->addChild(new GPUShaderFP64Test1(m_context));
15407 fp64->addChild(new GPUShaderFP64Test2(m_context));
15408 fp64->addChild(new GPUShaderFP64Test3(m_context));
15409 fp64->addChild(new GPUShaderFP64Test4(m_context));
15410 fp64->addChild(new GPUShaderFP64Test5(m_context));
15411 fp64->addChild(new GPUShaderFP64Test6(m_context));
15412 fp64->addChild(new GPUShaderFP64Test7(m_context));
15413 fp64->addChild(new GPUShaderFP64Test8(m_context));
15414 fp64->addChild(new GPUShaderFP64Test9(m_context));
15415 addChild(fp64);
15416
15417 TypeDefinition typeDefinition[] =
15418 {
15419 { "double", 1, 1 },
15420 { "dvec2", 1, 2 },
15421 { "dvec3", 1, 3 },
15422 { "dvec4", 1, 4 },
15423 { "dmat2", 2, 2 },
15424 { "dmat2x3", 2, 3 },
15425 { "dmat2x4", 2, 4 },
15426 { "dmat3x2", 3, 2 },
15427 { "dmat3", 3, 3 },
15428 { "dmat3x4", 3, 4 },
15429 { "dmat4x2", 4, 2 },
15430 { "dmat4x3", 4, 3 },
15431 { "dmat4", 4, 4 }
15432 };
15433
15434 struct BuiltinFunctions
15435 {
15436 std::string name;
15437 FunctionEnum function;
15438 } builtinFunctions[] = {
15439 { "abs", FUNCTION_ABS },
15440 { "ceil", FUNCTION_CEIL },
15441 { "clamp", FUNCTION_CLAMP },
15442 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR },
15443 { "cross", FUNCTION_CROSS },
15444 { "determinant", FUNCTION_DETERMINANT },
15445 { "distance", FUNCTION_DISTANCE },
15446 { "dot", FUNCTION_DOT },
15447 { "equal", FUNCTION_EQUAL },
15448 { "faceforward", FUNCTION_FACEFORWARD },
15449 { "floor", FUNCTION_FLOOR },
15450 { "fma", FUNCTION_FMA },
15451 { "fract", FUNCTION_FRACT },
15452 { "frexp", FUNCTION_FREXP },
15453 { "greaterthan", FUNCTION_GREATERTHAN },
15454 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL },
15455 { "inverse", FUNCTION_INVERSE },
15456 { "inversesqrt", FUNCTION_INVERSESQRT },
15457 { "ldexp", FUNCTION_LDEXP },
15458 { "lessthan", FUNCTION_LESSTHAN },
15459 { "lessthanequal", FUNCTION_LESSTHANEQUAL },
15460 { "length", FUNCTION_LENGTH },
15461 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT },
15462 { "max", FUNCTION_MAX },
15463 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR },
15464 { "min", FUNCTION_MIN },
15465 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR },
15466 { "mix", FUNCTION_MIX },
15467 { "mod", FUNCTION_MOD },
15468 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR },
15469 { "modf", FUNCTION_MODF },
15470 { "normalize", FUNCTION_NORMALIZE },
15471 { "notequal", FUNCTION_NOTEQUAL },
15472 { "outerproduct", FUNCTION_OUTERPRODUCT },
15473 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 },
15474 { "reflect", FUNCTION_REFLECT },
15475 { "refract", FUNCTION_REFRACT },
15476 { "round", FUNCTION_ROUND },
15477 { "roundeven", FUNCTION_ROUNDEVEN },
15478 { "sign", FUNCTION_SIGN },
15479 { "smoothstep", FUNCTION_SMOOTHSTEP },
15480 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15481 { "sqrt", FUNCTION_SQRT },
15482 { "step", FUNCTION_STEP },
15483 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR },
15484 { "transpose", FUNCTION_TRANSPOSE },
15485 { "trunc", FUNCTION_TRUNC },
15486 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 },
15487 { "isnan", FUNCTION_ISNAN },
15488 { "isinf", FUNCTION_ISINF }
15489 };
15490
15491 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15492 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15493 {
15494 const BuiltinFunctions& bf = builtinFunctions[i];
15495 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15496 {
15497 std::string caseName = bf.name + "_" + typeDefinition[j].name;
15498 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15499 }
15500 }
15501 addChild(builin);
15502 }
15503
15504 } /* glcts namespace */
15505