1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 /**
25 * \file gl4GPUShaderFP64Tests.cpp
26 * \brief Implements conformance tests for "GPU Shader FP64" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cGPUShaderFP64Tests.hpp"
30 #include "gluContextInfo.hpp"
31 #include "glwFunctions.hpp"
32 #include "tcuMatrix.hpp"
33 #include "tcuTestLog.hpp"
34
35 #include <iomanip>
36
37 #include "deMath.h"
38 #include "deUniquePtr.hpp"
39 #include "tcuMatrixUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41
42 #include <cstdlib>
43 #include <cstring>
44 #include <limits>
45 #include <memory>
46
47 namespace gl4cts
48 {
49
50 const glw::GLenum Utils::programInfo::ARB_COMPUTE_SHADER = 0x91B9;
51
52 /** Constructor
53 *
54 * @param context Test context
55 **/
programInfo(deqp::Context & context)56 Utils::programInfo::programInfo(deqp::Context& context)
57 : m_context(context)
58 , m_compute_shader_id(0)
59 , m_fragment_shader_id(0)
60 , m_geometry_shader_id(0)
61 , m_program_object_id(0)
62 , m_tesselation_control_shader_id(0)
63 , m_tesselation_evaluation_shader_id(0)
64 , m_vertex_shader_id(0)
65 {
66 /* Nothing to be done here */
67 }
68
69 /** Destructor
70 *
71 **/
~programInfo()72 Utils::programInfo::~programInfo()
73 {
74 /* GL entry points */
75 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
76
77 /* Make sure program object is no longer used by GL */
78 gl.useProgram(0);
79
80 /* Clean program object */
81 if (0 != m_program_object_id)
82 {
83 gl.deleteProgram(m_program_object_id);
84 m_program_object_id = 0;
85 }
86
87 /* Clean shaders */
88 if (0 != m_compute_shader_id)
89 {
90 gl.deleteShader(m_compute_shader_id);
91 m_compute_shader_id = 0;
92 }
93
94 if (0 != m_fragment_shader_id)
95 {
96 gl.deleteShader(m_fragment_shader_id);
97 m_fragment_shader_id = 0;
98 }
99
100 if (0 != m_geometry_shader_id)
101 {
102 gl.deleteShader(m_geometry_shader_id);
103 m_geometry_shader_id = 0;
104 }
105
106 if (0 != m_tesselation_control_shader_id)
107 {
108 gl.deleteShader(m_tesselation_control_shader_id);
109 m_tesselation_control_shader_id = 0;
110 }
111
112 if (0 != m_tesselation_evaluation_shader_id)
113 {
114 gl.deleteShader(m_tesselation_evaluation_shader_id);
115 m_tesselation_evaluation_shader_id = 0;
116 }
117
118 if (0 != m_vertex_shader_id)
119 {
120 gl.deleteShader(m_vertex_shader_id);
121 m_vertex_shader_id = 0;
122 }
123 }
124
125 /** Build program
126 *
127 * @param compute_shader_code Compute shader source code
128 * @param fragment_shader_code Fragment shader source code
129 * @param geometry_shader_code Geometry shader source code
130 * @param tesselation_control_shader_code Tesselation control shader source code
131 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
132 * @param vertex_shader_code Vertex shader source code
133 * @param varying_names Array of strings containing names of varyings to be captured with transfrom feedback
134 * @param n_varying_names Number of varyings to be captured with transfrom feedback
135 **/
build(const glw::GLchar * compute_shader_code,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code,const glw::GLchar * const * varying_names,glw::GLuint n_varying_names)136 void Utils::programInfo::build(const glw::GLchar* compute_shader_code, const glw::GLchar* fragment_shader_code,
137 const glw::GLchar* geometry_shader_code,
138 const glw::GLchar* tesselation_control_shader_code,
139 const glw::GLchar* tesselation_evaluation_shader_code,
140 const glw::GLchar* vertex_shader_code, const glw::GLchar* const* varying_names,
141 glw::GLuint n_varying_names)
142 {
143 /* GL entry points */
144 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
145
146 /* Create shader objects and compile */
147 if (0 != compute_shader_code)
148 {
149 m_compute_shader_id = gl.createShader(ARB_COMPUTE_SHADER);
150 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
151
152 compile(m_compute_shader_id, compute_shader_code);
153 }
154
155 if (0 != fragment_shader_code)
156 {
157 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
158 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
159
160 compile(m_fragment_shader_id, fragment_shader_code);
161 }
162
163 if (0 != geometry_shader_code)
164 {
165 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
166 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
167
168 compile(m_geometry_shader_id, geometry_shader_code);
169 }
170
171 if (0 != tesselation_control_shader_code)
172 {
173 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
174 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
175
176 compile(m_tesselation_control_shader_id, tesselation_control_shader_code);
177 }
178
179 if (0 != tesselation_evaluation_shader_code)
180 {
181 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
182 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
183
184 compile(m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
185 }
186
187 if (0 != vertex_shader_code)
188 {
189 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
190 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
191
192 compile(m_vertex_shader_id, vertex_shader_code);
193 }
194
195 /* Create program object */
196 m_program_object_id = gl.createProgram();
197 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
198
199 /* Set up captyured varyings' names */
200 if (0 != n_varying_names)
201 {
202 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
203 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
204 }
205
206 /* Link program */
207 link();
208 }
209
210 /** Compile shader
211 *
212 * @param shader_id Shader object id
213 * @param shader_code Shader source code
214 **/
compile(glw::GLuint shader_id,const glw::GLchar * shader_code) const215 void Utils::programInfo::compile(glw::GLuint shader_id, const glw::GLchar* shader_code) const
216 {
217 /* GL entry points */
218 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
219
220 /* Compilation status */
221 glw::GLint status = GL_FALSE;
222
223 /* Set source code */
224 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
225 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
226
227 /* Compile */
228 gl.compileShader(shader_id);
229 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
230
231 /* Get compilation status */
232 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
233 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
234
235 /* Log compilation error */
236 if (GL_TRUE != status)
237 {
238 glw::GLint length = 0;
239 std::vector<glw::GLchar> message;
240
241 /* Error log length */
242 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
243 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
244
245 /* Prepare storage */
246 message.resize(length);
247
248 /* Get error log */
249 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
250 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
251
252 /* Log */
253 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
254 << &message[0] << "\nShader source\n"
255 << shader_code << tcu::TestLog::EndMessage;
256
257 TCU_FAIL("Failed to compile shader");
258 }
259 }
260
261 /** Attach shaders and link program
262 *
263 **/
link() const264 void Utils::programInfo::link() const
265 {
266 /* GL entry points */
267 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
268
269 /* Link status */
270 glw::GLint status = GL_FALSE;
271
272 /* Attach shaders */
273 if (0 != m_compute_shader_id)
274 {
275 gl.attachShader(m_program_object_id, m_compute_shader_id);
276 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
277 }
278
279 if (0 != m_fragment_shader_id)
280 {
281 gl.attachShader(m_program_object_id, m_fragment_shader_id);
282 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
283 }
284
285 if (0 != m_geometry_shader_id)
286 {
287 gl.attachShader(m_program_object_id, m_geometry_shader_id);
288 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
289 }
290
291 if (0 != m_tesselation_control_shader_id)
292 {
293 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
294 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
295 }
296
297 if (0 != m_tesselation_evaluation_shader_id)
298 {
299 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
300 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
301 }
302
303 if (0 != m_vertex_shader_id)
304 {
305 gl.attachShader(m_program_object_id, m_vertex_shader_id);
306 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
307 }
308
309 /* Link */
310 gl.linkProgram(m_program_object_id);
311 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
312
313 /* Get link status */
314 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
315 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
316
317 /* Log link error */
318 if (GL_TRUE != status)
319 {
320 glw::GLint length = 0;
321 std::vector<glw::GLchar> message;
322
323 /* Get error log length */
324 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
325 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
326
327 message.resize(length);
328
329 /* Get error log */
330 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
331 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
332
333 /* Log */
334 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
335 << &message[0] << tcu::TestLog::EndMessage;
336
337 TCU_FAIL("Failed to link program");
338 }
339 }
340
341 /** Retrieves base type of user-provided variable type. (eg. VARIABLE_TYPE_DOUBLE for double-precision
342 * matrix types.
343 *
344 * @param type Variable type to return base type for.
345 *
346 * @return Requested value or VARAIBLE_TYPE_UNKNOWN if @param type was not recognized.
347 **/
getBaseVariableType(_variable_type type)348 Utils::_variable_type Utils::getBaseVariableType(_variable_type type)
349 {
350 _variable_type result = VARIABLE_TYPE_UNKNOWN;
351
352 switch (type)
353 {
354 case VARIABLE_TYPE_BOOL:
355 {
356 result = VARIABLE_TYPE_BOOL;
357
358 break;
359 }
360
361 case VARIABLE_TYPE_DOUBLE:
362 case VARIABLE_TYPE_DMAT2:
363 case VARIABLE_TYPE_DMAT2X3:
364 case VARIABLE_TYPE_DMAT2X4:
365 case VARIABLE_TYPE_DMAT3:
366 case VARIABLE_TYPE_DMAT3X2:
367 case VARIABLE_TYPE_DMAT3X4:
368 case VARIABLE_TYPE_DMAT4:
369 case VARIABLE_TYPE_DMAT4X2:
370 case VARIABLE_TYPE_DMAT4X3:
371 case VARIABLE_TYPE_DVEC2:
372 case VARIABLE_TYPE_DVEC3:
373 case VARIABLE_TYPE_DVEC4:
374 {
375 result = VARIABLE_TYPE_DOUBLE;
376
377 break;
378 }
379
380 case VARIABLE_TYPE_INT:
381 case VARIABLE_TYPE_IVEC2:
382 case VARIABLE_TYPE_IVEC3:
383 case VARIABLE_TYPE_IVEC4:
384 {
385 result = VARIABLE_TYPE_INT;
386
387 break;
388 }
389
390 case VARIABLE_TYPE_UINT:
391 case VARIABLE_TYPE_UVEC2:
392 case VARIABLE_TYPE_UVEC3:
393 case VARIABLE_TYPE_UVEC4:
394 {
395 result = VARIABLE_TYPE_UINT;
396
397 break;
398 }
399
400 case VARIABLE_TYPE_FLOAT:
401 case VARIABLE_TYPE_MAT2:
402 case VARIABLE_TYPE_MAT2X3:
403 case VARIABLE_TYPE_MAT2X4:
404 case VARIABLE_TYPE_MAT3:
405 case VARIABLE_TYPE_MAT3X2:
406 case VARIABLE_TYPE_MAT3X4:
407 case VARIABLE_TYPE_MAT4:
408 case VARIABLE_TYPE_MAT4X2:
409 case VARIABLE_TYPE_MAT4X3:
410 case VARIABLE_TYPE_VEC2:
411 case VARIABLE_TYPE_VEC3:
412 case VARIABLE_TYPE_VEC4:
413 {
414 result = VARIABLE_TYPE_FLOAT;
415
416 break;
417 }
418
419 default:
420 {
421 TCU_FAIL("Unrecognized variable type");
422 }
423 } /* switch (type) */
424
425 return result;
426 }
427
428 /** Returns size (in bytes) of a single component of a base variable type.
429 *
430 * @param type Base variable type to use for the query.
431 *
432 * @return Requested value or 0 if @param type was not recognized.
433 **/
getBaseVariableTypeComponentSize(_variable_type type)434 unsigned int Utils::getBaseVariableTypeComponentSize(_variable_type type)
435 {
436 unsigned int result = 0;
437
438 switch (type)
439 {
440 case VARIABLE_TYPE_BOOL:
441 result = sizeof(bool);
442 break;
443 case VARIABLE_TYPE_DOUBLE:
444 result = sizeof(double);
445 break;
446 case VARIABLE_TYPE_FLOAT:
447 result = sizeof(float);
448 break;
449 case VARIABLE_TYPE_INT:
450 result = sizeof(int);
451 break;
452 case VARIABLE_TYPE_UINT:
453 result = sizeof(unsigned int);
454 break;
455
456 default:
457 {
458 TCU_FAIL("Unrecognized variable type");
459 }
460 } /* switch (type) */
461
462 return result;
463 }
464
465 /** Returns component, corresponding to user-specified index
466 * (eg. index:0 corresponds to 'x', index:1 corresponds to 'y',
467 * and so on.
468 *
469 * @param index Component index.
470 *
471 * @return As per description.
472 **/
getComponentAtIndex(unsigned int index)473 unsigned char Utils::getComponentAtIndex(unsigned int index)
474 {
475 unsigned char result = '?';
476
477 switch (index)
478 {
479 case 0:
480 result = 'x';
481 break;
482 case 1:
483 result = 'y';
484 break;
485 case 2:
486 result = 'z';
487 break;
488 case 3:
489 result = 'w';
490 break;
491
492 default:
493 {
494 TCU_FAIL("Unrecognized component index");
495 }
496 }
497
498 return result;
499 }
500
501 /** Get _variable_type representing double-precision type with given dimmensions
502 *
503 * @param n_columns Number of columns
504 * @param n_row Number of rows
505 *
506 * @return Corresponding _variable_type
507 **/
getDoubleVariableType(glw::GLuint n_columns,glw::GLuint n_rows)508 Utils::_variable_type Utils::getDoubleVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
509 {
510 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
511
512 static const _variable_type types[4][4] = {
513 { VARIABLE_TYPE_DOUBLE, VARIABLE_TYPE_DVEC2, VARIABLE_TYPE_DVEC3, VARIABLE_TYPE_DVEC4 },
514 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT2, VARIABLE_TYPE_DMAT2X3, VARIABLE_TYPE_DMAT2X4 },
515 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT3X2, VARIABLE_TYPE_DMAT3, VARIABLE_TYPE_DMAT3X4 },
516 { VARIABLE_TYPE_UNKNOWN, VARIABLE_TYPE_DMAT4X2, VARIABLE_TYPE_DMAT4X3, VARIABLE_TYPE_DMAT4 }
517 };
518
519 type = types[n_columns - 1][n_rows - 1];
520
521 return type;
522 }
523
524 /** Returns a single-precision equivalent of a double-precision floating-point variable
525 * type.
526 *
527 * @param type Double-precision variable type. Only VARIABLE_TYPE_D* variable types
528 * are accepted.
529 *
530 * @return Requested GLSL type.
531 **/
getFPVariableTypeStringForVariableType(_variable_type type)532 std::string Utils::getFPVariableTypeStringForVariableType(_variable_type type)
533 {
534 std::string result = "[?]";
535
536 switch (type)
537 {
538 case VARIABLE_TYPE_DOUBLE:
539 result = "float";
540 break;
541 case VARIABLE_TYPE_DMAT2:
542 result = "mat2";
543 break;
544 case VARIABLE_TYPE_DMAT2X3:
545 result = "mat2x3";
546 break;
547 case VARIABLE_TYPE_DMAT2X4:
548 result = "mat2x4";
549 break;
550 case VARIABLE_TYPE_DMAT3:
551 result = "mat3";
552 break;
553 case VARIABLE_TYPE_DMAT3X2:
554 result = "mat3x2";
555 break;
556 case VARIABLE_TYPE_DMAT3X4:
557 result = "mat3x4";
558 break;
559 case VARIABLE_TYPE_DMAT4:
560 result = "mat4";
561 break;
562 case VARIABLE_TYPE_DMAT4X2:
563 result = "mat4x2";
564 break;
565 case VARIABLE_TYPE_DMAT4X3:
566 result = "mat4x3";
567 break;
568 case VARIABLE_TYPE_DVEC2:
569 result = "vec2";
570 break;
571 case VARIABLE_TYPE_DVEC3:
572 result = "vec3";
573 break;
574 case VARIABLE_TYPE_DVEC4:
575 result = "vec4";
576 break;
577
578 default:
579 {
580 TCU_FAIL("Unrecognized variable type");
581 }
582 } /* switch (type) */
583
584 return result;
585 }
586
587 /** Returns GL data type enum corresponding to user-provided base variable type.
588 *
589 * @param type Base variable type to return corresponding GLenum value for.
590 *
591 * @return Corresponding GLenum value or GL_NONE if the input value was not
592 * recognized.
593 **/
getGLDataTypeOfBaseVariableType(_variable_type type)594 glw::GLenum Utils::getGLDataTypeOfBaseVariableType(_variable_type type)
595 {
596 glw::GLenum result = GL_NONE;
597
598 switch (type)
599 {
600 case VARIABLE_TYPE_BOOL:
601 result = GL_BOOL;
602 break;
603 case VARIABLE_TYPE_DOUBLE:
604 result = GL_DOUBLE;
605 break;
606 case VARIABLE_TYPE_FLOAT:
607 result = GL_FLOAT;
608 break;
609 case VARIABLE_TYPE_INT:
610 result = GL_INT;
611 break;
612 case VARIABLE_TYPE_UINT:
613 result = GL_UNSIGNED_INT;
614 break;
615
616 default:
617 {
618 TCU_FAIL("Unrecognized variable type");
619 }
620 }
621
622 return result;
623 }
624
625 /** Return GLenum representing given <type>
626 *
627 * @param type Type of variable
628 *
629 * @return GL enumeration
630 **/
getGLDataTypeOfVariableType(_variable_type type)631 glw::GLenum Utils::getGLDataTypeOfVariableType(_variable_type type)
632 {
633 glw::GLenum result = GL_NONE;
634
635 switch (type)
636 {
637 case VARIABLE_TYPE_BOOL:
638 result = GL_BOOL;
639 break;
640 case VARIABLE_TYPE_DOUBLE:
641 result = GL_DOUBLE;
642 break;
643 case VARIABLE_TYPE_DMAT2:
644 result = GL_DOUBLE_MAT2;
645 break;
646 case VARIABLE_TYPE_DMAT2X3:
647 result = GL_DOUBLE_MAT2x3;
648 break;
649 case VARIABLE_TYPE_DMAT2X4:
650 result = GL_DOUBLE_MAT2x4;
651 break;
652 case VARIABLE_TYPE_DMAT3:
653 result = GL_DOUBLE_MAT3;
654 break;
655 case VARIABLE_TYPE_DMAT3X2:
656 result = GL_DOUBLE_MAT3x2;
657 break;
658 case VARIABLE_TYPE_DMAT3X4:
659 result = GL_DOUBLE_MAT3x4;
660 break;
661 case VARIABLE_TYPE_DMAT4:
662 result = GL_DOUBLE_MAT4;
663 break;
664 case VARIABLE_TYPE_DMAT4X2:
665 result = GL_DOUBLE_MAT4x2;
666 break;
667 case VARIABLE_TYPE_DMAT4X3:
668 result = GL_DOUBLE_MAT4x3;
669 break;
670 case VARIABLE_TYPE_DVEC2:
671 result = GL_DOUBLE_VEC2;
672 break;
673 case VARIABLE_TYPE_DVEC3:
674 result = GL_DOUBLE_VEC3;
675 break;
676 case VARIABLE_TYPE_DVEC4:
677 result = GL_DOUBLE_VEC4;
678 break;
679 case VARIABLE_TYPE_FLOAT:
680 result = GL_FLOAT;
681 break;
682 case VARIABLE_TYPE_INT:
683 result = GL_INT;
684 break;
685 case VARIABLE_TYPE_IVEC2:
686 result = GL_INT_VEC2;
687 break;
688 case VARIABLE_TYPE_IVEC3:
689 result = GL_INT_VEC3;
690 break;
691 case VARIABLE_TYPE_IVEC4:
692 result = GL_INT_VEC4;
693 break;
694 case VARIABLE_TYPE_MAT2:
695 result = GL_FLOAT_MAT2;
696 break;
697 case VARIABLE_TYPE_MAT2X3:
698 result = GL_FLOAT_MAT2x3;
699 break;
700 case VARIABLE_TYPE_MAT2X4:
701 result = GL_FLOAT_MAT2x4;
702 break;
703 case VARIABLE_TYPE_MAT3:
704 result = GL_FLOAT_MAT3;
705 break;
706 case VARIABLE_TYPE_MAT3X2:
707 result = GL_FLOAT_MAT3x2;
708 break;
709 case VARIABLE_TYPE_MAT3X4:
710 result = GL_FLOAT_MAT3x4;
711 break;
712 case VARIABLE_TYPE_MAT4:
713 result = GL_FLOAT_MAT4;
714 break;
715 case VARIABLE_TYPE_MAT4X2:
716 result = GL_FLOAT_MAT4x2;
717 break;
718 case VARIABLE_TYPE_MAT4X3:
719 result = GL_FLOAT_MAT4x3;
720 break;
721 case VARIABLE_TYPE_UINT:
722 result = GL_UNSIGNED_INT;
723 break;
724 case VARIABLE_TYPE_UVEC2:
725 result = GL_UNSIGNED_INT_VEC2;
726 break;
727 case VARIABLE_TYPE_UVEC3:
728 result = GL_UNSIGNED_INT_VEC3;
729 break;
730 case VARIABLE_TYPE_UVEC4:
731 result = GL_UNSIGNED_INT_VEC4;
732 break;
733 case VARIABLE_TYPE_VEC2:
734 result = GL_FLOAT_VEC2;
735 break;
736 case VARIABLE_TYPE_VEC3:
737 result = GL_FLOAT_VEC3;
738 break;
739 case VARIABLE_TYPE_VEC4:
740 result = GL_FLOAT_VEC4;
741 break;
742
743 default:
744 {
745 TCU_FAIL("Unrecognized variable type");
746 }
747 }
748
749 return result;
750 }
751
752 /** Get _variable_type representing integer type with given dimmensions
753 *
754 * @param n_columns Number of columns
755 * @param n_row Number of rows
756 *
757 * @return Corresponding _variable_type
758 **/
getIntVariableType(glw::GLuint n_columns,glw::GLuint n_rows)759 Utils::_variable_type Utils::getIntVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
760 {
761 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
762
763 static const _variable_type types[4] = { VARIABLE_TYPE_INT, VARIABLE_TYPE_IVEC2, VARIABLE_TYPE_IVEC3,
764 VARIABLE_TYPE_IVEC4 };
765
766 if (1 != n_columns)
767 {
768 TCU_FAIL("Not implemented");
769 }
770 else
771 {
772 type = types[n_rows - 1];
773 }
774
775 return type;
776 }
777
778 /** Returns te number of components that variables defined with user-specified type
779 * support. For matrix types, total amount of values accessible for the type will be
780 * returned.
781 *
782 * @param type Variable type to return the described vale for.
783 *
784 * @return As per description or 0 if @param type was not recognized.
785 */
getNumberOfComponentsForVariableType(_variable_type type)786 unsigned int Utils::getNumberOfComponentsForVariableType(_variable_type type)
787 {
788 unsigned int result = 0;
789
790 switch (type)
791 {
792 case VARIABLE_TYPE_BOOL:
793 case VARIABLE_TYPE_DOUBLE:
794 case VARIABLE_TYPE_FLOAT:
795 case VARIABLE_TYPE_INT:
796 case VARIABLE_TYPE_UINT:
797 {
798 result = 1;
799
800 break;
801 }
802
803 case VARIABLE_TYPE_DVEC2:
804 case VARIABLE_TYPE_IVEC2:
805 case VARIABLE_TYPE_UVEC2:
806 case VARIABLE_TYPE_VEC2:
807 {
808 result = 2;
809
810 break;
811 }
812
813 case VARIABLE_TYPE_DVEC3:
814 case VARIABLE_TYPE_IVEC3:
815 case VARIABLE_TYPE_UVEC3:
816 case VARIABLE_TYPE_VEC3:
817 {
818 result = 3;
819
820 break;
821 }
822
823 case VARIABLE_TYPE_DVEC4:
824 case VARIABLE_TYPE_IVEC4:
825 case VARIABLE_TYPE_UVEC4:
826 case VARIABLE_TYPE_VEC4:
827 {
828 result = 4;
829
830 break;
831 }
832
833 case VARIABLE_TYPE_DMAT2:
834 case VARIABLE_TYPE_MAT2:
835 {
836 result = 2 * 2;
837
838 break;
839 }
840
841 case VARIABLE_TYPE_DMAT2X3:
842 case VARIABLE_TYPE_DMAT3X2:
843 case VARIABLE_TYPE_MAT2X3:
844 case VARIABLE_TYPE_MAT3X2:
845 {
846 result = 2 * 3;
847
848 break;
849 }
850
851 case VARIABLE_TYPE_DMAT2X4:
852 case VARIABLE_TYPE_DMAT4X2:
853 case VARIABLE_TYPE_MAT2X4:
854 case VARIABLE_TYPE_MAT4X2:
855 {
856 result = 2 * 4;
857
858 break;
859 }
860
861 case VARIABLE_TYPE_DMAT3:
862 case VARIABLE_TYPE_MAT3:
863 {
864 result = 3 * 3;
865
866 break;
867 }
868
869 case VARIABLE_TYPE_DMAT3X4:
870 case VARIABLE_TYPE_DMAT4X3:
871 case VARIABLE_TYPE_MAT3X4:
872 case VARIABLE_TYPE_MAT4X3:
873 {
874 result = 3 * 4;
875
876 break;
877 }
878
879 case VARIABLE_TYPE_DMAT4:
880 case VARIABLE_TYPE_MAT4:
881 {
882 result = 4 * 4;
883
884 break;
885 }
886
887 default:
888 {
889 TCU_FAIL("Unrecognized type");
890 }
891 } /* switch (type) */
892
893 return result;
894 }
895
896 /** Returns number of columns user-specified matrix variable type describes.
897 *
898 * @param type Variable type to use for the query. Only VARIABLE_TYPE_DMAT*
899 * values are valid.
900 *
901 * @return As per description.
902 **/
getNumberOfColumnsForVariableType(_variable_type type)903 unsigned int Utils::getNumberOfColumnsForVariableType(_variable_type type)
904 {
905 unsigned int result = 0;
906
907 switch (type)
908 {
909 case VARIABLE_TYPE_BOOL:
910 case VARIABLE_TYPE_DOUBLE:
911 case VARIABLE_TYPE_FLOAT:
912 case VARIABLE_TYPE_INT:
913 case VARIABLE_TYPE_UINT:
914 case VARIABLE_TYPE_DVEC2:
915 case VARIABLE_TYPE_IVEC2:
916 case VARIABLE_TYPE_UVEC2:
917 case VARIABLE_TYPE_VEC2:
918 case VARIABLE_TYPE_DVEC3:
919 case VARIABLE_TYPE_IVEC3:
920 case VARIABLE_TYPE_UVEC3:
921 case VARIABLE_TYPE_VEC3:
922 case VARIABLE_TYPE_DVEC4:
923 case VARIABLE_TYPE_IVEC4:
924 case VARIABLE_TYPE_UVEC4:
925 case VARIABLE_TYPE_VEC4:
926 {
927 result = 1;
928
929 break;
930 }
931
932 case VARIABLE_TYPE_DMAT2:
933 case VARIABLE_TYPE_DMAT2X3:
934 case VARIABLE_TYPE_DMAT2X4:
935 case VARIABLE_TYPE_MAT2:
936 case VARIABLE_TYPE_MAT2X3:
937 case VARIABLE_TYPE_MAT2X4:
938 {
939 result = 2;
940
941 break;
942 }
943
944 case VARIABLE_TYPE_DMAT3:
945 case VARIABLE_TYPE_DMAT3X2:
946 case VARIABLE_TYPE_DMAT3X4:
947 case VARIABLE_TYPE_MAT3:
948 case VARIABLE_TYPE_MAT3X2:
949 case VARIABLE_TYPE_MAT3X4:
950 {
951 result = 3;
952
953 break;
954 }
955
956 case VARIABLE_TYPE_DMAT4:
957 case VARIABLE_TYPE_DMAT4X2:
958 case VARIABLE_TYPE_DMAT4X3:
959 case VARIABLE_TYPE_MAT4:
960 case VARIABLE_TYPE_MAT4X2:
961 case VARIABLE_TYPE_MAT4X3:
962 {
963 result = 4;
964
965 break;
966 }
967
968 default:
969 {
970 TCU_FAIL("Unrecognized type");
971 }
972 } /* switch (type) */
973
974 return result;
975 }
976
977 /** Returns maximum number of uniform locations taken by user-specified double-precision
978 * variable type.
979 *
980 * @param type Variable type to use for the query. Only VARIABLE_TYPE_D* values are valid.
981 *
982 * @return As per description.
983 **/
getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)984 unsigned int Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(_variable_type type)
985 {
986 unsigned int result = 0;
987
988 switch (type)
989 {
990 case VARIABLE_TYPE_DOUBLE:
991 result = 1;
992 break;
993 case VARIABLE_TYPE_DVEC2:
994 result = 1;
995 break;
996 case VARIABLE_TYPE_DVEC3:
997 result = 2;
998 break;
999 case VARIABLE_TYPE_DVEC4:
1000 result = 2;
1001 break;
1002 case VARIABLE_TYPE_DMAT2:
1003 result = 2;
1004 break;
1005 case VARIABLE_TYPE_DMAT2X3:
1006 result = 6;
1007 break;
1008 case VARIABLE_TYPE_DMAT2X4:
1009 result = 8;
1010 break;
1011 case VARIABLE_TYPE_DMAT3:
1012 result = 6;
1013 break;
1014 case VARIABLE_TYPE_DMAT3X2:
1015 result = 4;
1016 break;
1017 case VARIABLE_TYPE_DMAT3X4:
1018 result = 8;
1019 break;
1020 case VARIABLE_TYPE_DMAT4:
1021 result = 8;
1022 break;
1023 case VARIABLE_TYPE_DMAT4X2:
1024 result = 4;
1025 break;
1026 case VARIABLE_TYPE_DMAT4X3:
1027 result = 6;
1028 break;
1029
1030 default:
1031 {
1032 TCU_FAIL("Unrecognized type");
1033 }
1034 } /* switch (type) */
1035
1036 return result;
1037 }
1038
1039 /** Get number of rows for given variable type
1040 *
1041 * @param type Type of variable
1042 *
1043 * @return Number of rows
1044 **/
getNumberOfRowsForVariableType(_variable_type type)1045 unsigned int Utils::getNumberOfRowsForVariableType(_variable_type type)
1046 {
1047 unsigned int result = 0;
1048
1049 switch (type)
1050 {
1051 case VARIABLE_TYPE_BOOL:
1052 case VARIABLE_TYPE_DOUBLE:
1053 case VARIABLE_TYPE_FLOAT:
1054 case VARIABLE_TYPE_INT:
1055 case VARIABLE_TYPE_UINT:
1056 {
1057 result = 1;
1058
1059 break;
1060 }
1061
1062 case VARIABLE_TYPE_DVEC2:
1063 case VARIABLE_TYPE_IVEC2:
1064 case VARIABLE_TYPE_UVEC2:
1065 case VARIABLE_TYPE_VEC2:
1066 case VARIABLE_TYPE_DMAT2:
1067 case VARIABLE_TYPE_DMAT3X2:
1068 case VARIABLE_TYPE_DMAT4X2:
1069 case VARIABLE_TYPE_MAT2:
1070 case VARIABLE_TYPE_MAT3X2:
1071 case VARIABLE_TYPE_MAT4X2:
1072 {
1073 result = 2;
1074
1075 break;
1076 }
1077
1078 case VARIABLE_TYPE_DVEC3:
1079 case VARIABLE_TYPE_IVEC3:
1080 case VARIABLE_TYPE_UVEC3:
1081 case VARIABLE_TYPE_VEC3:
1082 case VARIABLE_TYPE_DMAT2X3:
1083 case VARIABLE_TYPE_DMAT3:
1084 case VARIABLE_TYPE_DMAT4X3:
1085 case VARIABLE_TYPE_MAT2X3:
1086 case VARIABLE_TYPE_MAT3:
1087 case VARIABLE_TYPE_MAT4X3:
1088 {
1089 result = 3;
1090
1091 break;
1092 }
1093
1094 case VARIABLE_TYPE_DVEC4:
1095 case VARIABLE_TYPE_IVEC4:
1096 case VARIABLE_TYPE_UVEC4:
1097 case VARIABLE_TYPE_VEC4:
1098 case VARIABLE_TYPE_DMAT2X4:
1099 case VARIABLE_TYPE_DMAT3X4:
1100 case VARIABLE_TYPE_DMAT4:
1101 case VARIABLE_TYPE_MAT2X4:
1102 case VARIABLE_TYPE_MAT3X4:
1103 case VARIABLE_TYPE_MAT4:
1104 {
1105 result = 4;
1106
1107 break;
1108 }
1109
1110 default:
1111 {
1112 TCU_FAIL("Unrecognized type");
1113 }
1114 } /* switch (type) */
1115
1116 return result;
1117 }
1118
1119 /** Returns variable type of a matrix constructed by multiplying two matrices.
1120 *
1121 * @param type_matrix_a L-side matrix type.
1122 * @param type_matrix_b R-side matrix type.
1123 *
1124 * @return As per description.
1125 **/
getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,_variable_type type_matrix_b)1126 Utils::_variable_type Utils::getPostMatrixMultiplicationVariableType(_variable_type type_matrix_a,
1127 _variable_type type_matrix_b)
1128 {
1129 const unsigned int n_a_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_a);
1130 const unsigned int n_a_components = Utils::getNumberOfComponentsForVariableType(type_matrix_a);
1131 const unsigned int n_a_rows = n_a_components / n_a_columns;
1132 const unsigned int n_b_columns = Utils::getNumberOfColumnsForVariableType(type_matrix_b);
1133 const unsigned int n_result_columns = n_b_columns;
1134 const unsigned int n_result_rows = n_a_rows;
1135 Utils::_variable_type result;
1136
1137 switch (n_result_columns)
1138 {
1139 case 2:
1140 {
1141 switch (n_result_rows)
1142 {
1143 case 2:
1144 result = VARIABLE_TYPE_DMAT2;
1145 break;
1146 case 3:
1147 result = VARIABLE_TYPE_DMAT2X3;
1148 break;
1149 case 4:
1150 result = VARIABLE_TYPE_DMAT2X4;
1151 break;
1152
1153 default:
1154 {
1155 TCU_FAIL("Unrecognized amount of rows in result variable");
1156 }
1157 } /* switch (n_result_rows) */
1158
1159 break;
1160 } /* case 2: */
1161
1162 case 3:
1163 {
1164 switch (n_result_rows)
1165 {
1166 case 2:
1167 result = VARIABLE_TYPE_DMAT3X2;
1168 break;
1169 case 3:
1170 result = VARIABLE_TYPE_DMAT3;
1171 break;
1172 case 4:
1173 result = VARIABLE_TYPE_DMAT3X4;
1174 break;
1175
1176 default:
1177 {
1178 TCU_FAIL("Unrecognized amount of rows in result variable");
1179 }
1180 } /* switch (n_result_rows) */
1181
1182 break;
1183 } /* case 3: */
1184
1185 case 4:
1186 {
1187 switch (n_result_rows)
1188 {
1189 case 2:
1190 result = VARIABLE_TYPE_DMAT4X2;
1191 break;
1192 case 3:
1193 result = VARIABLE_TYPE_DMAT4X3;
1194 break;
1195 case 4:
1196 result = VARIABLE_TYPE_DMAT4;
1197 break;
1198
1199 default:
1200 {
1201 TCU_FAIL("Unrecognized amount of rows in result variable");
1202 }
1203 } /* switch (n_result_rows) */
1204
1205 break;
1206 } /* case 4: */
1207
1208 default:
1209 {
1210 TCU_FAIL("Unrecognized amount of columns in result variable");
1211 }
1212 } /* switch (n_result_columns) */
1213
1214 /* Done */
1215 return result;
1216 }
1217
1218 /** Returns a string holding the value represented by user-provided variable, for which
1219 * the data are represented in @param type variable type.
1220 *
1221 * @return As per description.
1222 **/
getStringForVariableTypeValue(_variable_type type,const unsigned char * data_ptr)1223 std::string Utils::getStringForVariableTypeValue(_variable_type type, const unsigned char* data_ptr)
1224 {
1225 std::stringstream result_sstream;
1226
1227 switch (type)
1228 {
1229 case VARIABLE_TYPE_BOOL:
1230 result_sstream << *((bool*)data_ptr);
1231 break;
1232 case VARIABLE_TYPE_DOUBLE:
1233 result_sstream << *((double*)data_ptr);
1234 break;
1235 case VARIABLE_TYPE_FLOAT:
1236 result_sstream << *((float*)data_ptr);
1237 break;
1238 case VARIABLE_TYPE_INT:
1239 result_sstream << *((int*)data_ptr);
1240 break;
1241 case VARIABLE_TYPE_UINT:
1242 result_sstream << *((unsigned int*)data_ptr);
1243 break;
1244
1245 default:
1246 {
1247 TCU_FAIL("Unrecognized variable type requested");
1248 }
1249 } /* switch (type) */
1250
1251 return result_sstream.str();
1252 }
1253
1254 /** Returns variable type of a transposed matrix of user-specified variable type.
1255 *
1256 * @param type Variable type of the matrix to be transposed.
1257 *
1258 * @return Transposed matrix variable type.
1259 **/
getTransposedMatrixVariableType(Utils::_variable_type type)1260 Utils::_variable_type Utils::getTransposedMatrixVariableType(Utils::_variable_type type)
1261 {
1262 Utils::_variable_type result;
1263
1264 switch (type)
1265 {
1266 case VARIABLE_TYPE_DMAT2:
1267 result = VARIABLE_TYPE_DMAT2;
1268 break;
1269 case VARIABLE_TYPE_DMAT2X3:
1270 result = VARIABLE_TYPE_DMAT3X2;
1271 break;
1272 case VARIABLE_TYPE_DMAT2X4:
1273 result = VARIABLE_TYPE_DMAT4X2;
1274 break;
1275 case VARIABLE_TYPE_DMAT3:
1276 result = VARIABLE_TYPE_DMAT3;
1277 break;
1278 case VARIABLE_TYPE_DMAT3X2:
1279 result = VARIABLE_TYPE_DMAT2X3;
1280 break;
1281 case VARIABLE_TYPE_DMAT3X4:
1282 result = VARIABLE_TYPE_DMAT4X3;
1283 break;
1284 case VARIABLE_TYPE_DMAT4:
1285 result = VARIABLE_TYPE_DMAT4;
1286 break;
1287 case VARIABLE_TYPE_DMAT4X2:
1288 result = VARIABLE_TYPE_DMAT2X4;
1289 break;
1290 case VARIABLE_TYPE_DMAT4X3:
1291 result = VARIABLE_TYPE_DMAT3X4;
1292 break;
1293
1294 default:
1295 {
1296 TCU_FAIL("Unrecognized double-precision matrix variable type.");
1297 }
1298 } /* switch (type) */
1299
1300 return result;
1301 }
1302
1303 /** Get _variable_type representing unsigned integer type with given dimmensions
1304 *
1305 * @param n_columns Number of columns
1306 * @param n_row Number of rows
1307 *
1308 * @return Corresponding _variable_type
1309 **/
getUintVariableType(glw::GLuint n_columns,glw::GLuint n_rows)1310 Utils::_variable_type Utils::getUintVariableType(glw::GLuint n_columns, glw::GLuint n_rows)
1311 {
1312 Utils::_variable_type type = VARIABLE_TYPE_UNKNOWN;
1313
1314 static const _variable_type types[4] = { VARIABLE_TYPE_UINT, VARIABLE_TYPE_UVEC2, VARIABLE_TYPE_UVEC3,
1315 VARIABLE_TYPE_UVEC4 };
1316
1317 if (1 != n_columns)
1318 {
1319 TCU_FAIL("Not implemented");
1320 }
1321 else
1322 {
1323 type = types[n_rows - 1];
1324 }
1325
1326 return type;
1327 }
1328
1329 /** Returns a literal corresponding to a GLSL keyword describing user-specified
1330 * variable type.
1331 *
1332 * @param type Variable type to use for the query.
1333 *
1334 * @return Requested GLSL keyword or [?] if @param type was not recognized.
1335 **/
getVariableTypeString(_variable_type type)1336 std::string Utils::getVariableTypeString(_variable_type type)
1337 {
1338 std::string result = "[?]";
1339
1340 switch (type)
1341 {
1342 case VARIABLE_TYPE_BOOL:
1343 result = "bool";
1344 break;
1345 case VARIABLE_TYPE_BVEC2:
1346 result = "bvec2";
1347 break;
1348 case VARIABLE_TYPE_BVEC3:
1349 result = "bvec3";
1350 break;
1351 case VARIABLE_TYPE_BVEC4:
1352 result = "bvec4";
1353 break;
1354 case VARIABLE_TYPE_DOUBLE:
1355 result = "double";
1356 break;
1357 case VARIABLE_TYPE_DMAT2:
1358 result = "dmat2";
1359 break;
1360 case VARIABLE_TYPE_DMAT2X3:
1361 result = "dmat2x3";
1362 break;
1363 case VARIABLE_TYPE_DMAT2X4:
1364 result = "dmat2x4";
1365 break;
1366 case VARIABLE_TYPE_DMAT3:
1367 result = "dmat3";
1368 break;
1369 case VARIABLE_TYPE_DMAT3X2:
1370 result = "dmat3x2";
1371 break;
1372 case VARIABLE_TYPE_DMAT3X4:
1373 result = "dmat3x4";
1374 break;
1375 case VARIABLE_TYPE_DMAT4:
1376 result = "dmat4";
1377 break;
1378 case VARIABLE_TYPE_DMAT4X2:
1379 result = "dmat4x2";
1380 break;
1381 case VARIABLE_TYPE_DMAT4X3:
1382 result = "dmat4x3";
1383 break;
1384 case VARIABLE_TYPE_DVEC2:
1385 result = "dvec2";
1386 break;
1387 case VARIABLE_TYPE_DVEC3:
1388 result = "dvec3";
1389 break;
1390 case VARIABLE_TYPE_DVEC4:
1391 result = "dvec4";
1392 break;
1393 case VARIABLE_TYPE_FLOAT:
1394 result = "float";
1395 break;
1396 case VARIABLE_TYPE_INT:
1397 result = "int";
1398 break;
1399 case VARIABLE_TYPE_IVEC2:
1400 result = "ivec2";
1401 break;
1402 case VARIABLE_TYPE_IVEC3:
1403 result = "ivec3";
1404 break;
1405 case VARIABLE_TYPE_IVEC4:
1406 result = "ivec4";
1407 break;
1408 case VARIABLE_TYPE_MAT2:
1409 result = "mat2";
1410 break;
1411 case VARIABLE_TYPE_MAT2X3:
1412 result = "mat2x3";
1413 break;
1414 case VARIABLE_TYPE_MAT2X4:
1415 result = "mat2x4";
1416 break;
1417 case VARIABLE_TYPE_MAT3:
1418 result = "mat3";
1419 break;
1420 case VARIABLE_TYPE_MAT3X2:
1421 result = "mat3x2";
1422 break;
1423 case VARIABLE_TYPE_MAT3X4:
1424 result = "mat3x4";
1425 break;
1426 case VARIABLE_TYPE_MAT4:
1427 result = "mat4";
1428 break;
1429 case VARIABLE_TYPE_MAT4X2:
1430 result = "mat4x2";
1431 break;
1432 case VARIABLE_TYPE_MAT4X3:
1433 result = "mat4x3";
1434 break;
1435 case VARIABLE_TYPE_UINT:
1436 result = "uint";
1437 break;
1438 case VARIABLE_TYPE_UVEC2:
1439 result = "uvec2";
1440 break;
1441 case VARIABLE_TYPE_UVEC3:
1442 result = "uvec3";
1443 break;
1444 case VARIABLE_TYPE_UVEC4:
1445 result = "uvec4";
1446 break;
1447 case VARIABLE_TYPE_VEC2:
1448 result = "vec2";
1449 break;
1450 case VARIABLE_TYPE_VEC3:
1451 result = "vec3";
1452 break;
1453 case VARIABLE_TYPE_VEC4:
1454 result = "vec4";
1455 break;
1456
1457 default:
1458 {
1459 TCU_FAIL("Unrecognized variable type");
1460 }
1461 } /* switch (type) */
1462
1463 return result;
1464 }
1465
1466 /** Check if GL context meets version requirements
1467 *
1468 * @param gl Functions
1469 * @param required_major Minimum required MAJOR_VERSION
1470 * @param required_minor Minimum required MINOR_VERSION
1471 *
1472 * @return true if GL context version is at least as requested, false otherwise
1473 **/
isGLVersionAtLeast(const glw::Functions & gl,glw::GLint required_major,glw::GLint required_minor)1474 bool Utils::isGLVersionAtLeast(const glw::Functions& gl, glw::GLint required_major, glw::GLint required_minor)
1475 {
1476 glw::GLint major = 0;
1477 glw::GLint minor = 0;
1478
1479 gl.getIntegerv(GL_MAJOR_VERSION, &major);
1480 gl.getIntegerv(GL_MINOR_VERSION, &minor);
1481
1482 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1483
1484 if (major > required_major)
1485 {
1486 /* Major is higher than required one */
1487 return true;
1488 }
1489 else if (major == required_major)
1490 {
1491 if (minor >= required_minor)
1492 {
1493 /* Major is equal to required one */
1494 /* Minor is higher than or equal to required one */
1495 return true;
1496 }
1497 else
1498 {
1499 /* Major is equal to required one */
1500 /* Minor is lower than required one */
1501 return false;
1502 }
1503 }
1504 else
1505 {
1506 /* Major is lower than required one */
1507 return false;
1508 }
1509 }
1510
1511 /** Tells whether user-specified variable type corresponds to a matrix type.
1512 *
1513 * @param type Variable type to use for the query.
1514 *
1515 * @return true if the variable type describes a matrix, false otherwise.
1516 **/
isMatrixVariableType(_variable_type type)1517 bool Utils::isMatrixVariableType(_variable_type type)
1518 {
1519 return (type == VARIABLE_TYPE_MAT2 || type == VARIABLE_TYPE_MAT3 || type == VARIABLE_TYPE_MAT4 ||
1520 type == VARIABLE_TYPE_MAT2X3 || type == VARIABLE_TYPE_MAT2X4 || type == VARIABLE_TYPE_MAT3X2 ||
1521 type == VARIABLE_TYPE_MAT3X4 || type == VARIABLE_TYPE_MAT4X2 || type == VARIABLE_TYPE_MAT4X3 ||
1522 type == VARIABLE_TYPE_DMAT2 || type == VARIABLE_TYPE_DMAT3 || type == VARIABLE_TYPE_DMAT4 ||
1523 type == VARIABLE_TYPE_DMAT2X3 || type == VARIABLE_TYPE_DMAT2X4 || type == VARIABLE_TYPE_DMAT3X2 ||
1524 type == VARIABLE_TYPE_DMAT3X4 || type == VARIABLE_TYPE_DMAT4X2 || type == VARIABLE_TYPE_DMAT4X3);
1525 }
1526
1527 /** Tells whether user-specified variable type is scalar.
1528 *
1529 * @return true if @param type is a scalar variable type, false otherwise.
1530 **/
isScalarVariableType(_variable_type type)1531 bool Utils::isScalarVariableType(_variable_type type)
1532 {
1533 bool result = false;
1534
1535 switch (type)
1536 {
1537 case VARIABLE_TYPE_BOOL:
1538 result = true;
1539 break;
1540 case VARIABLE_TYPE_DOUBLE:
1541 result = true;
1542 break;
1543 case VARIABLE_TYPE_FLOAT:
1544 result = true;
1545 break;
1546 case VARIABLE_TYPE_INT:
1547 result = true;
1548 break;
1549 case VARIABLE_TYPE_UINT:
1550 result = true;
1551 break;
1552 default:
1553 break;
1554 } /* switch (type) */
1555
1556 return result;
1557 }
1558
1559 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1560 *
1561 * @param token Token string
1562 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1563 * @param text String that will be used as replacement for <token>
1564 * @param string String to work on
1565 **/
replaceToken(const glw::GLchar * token,size_t & search_position,const glw::GLchar * text,std::string & string)1566 void Utils::replaceToken(const glw::GLchar* token, size_t& search_position, const glw::GLchar* text,
1567 std::string& string)
1568 {
1569 const size_t text_length = strlen(text);
1570 const size_t token_length = strlen(token);
1571 const size_t token_position = string.find(token, search_position);
1572
1573 string.replace(token_position, token_length, text, text_length);
1574
1575 search_position = token_position + text_length;
1576 }
1577
1578 /** Constructor.
1579 *
1580 * @param context Rendering context.
1581 *
1582 **/
GPUShaderFP64Test1(deqp::Context & context)1583 GPUShaderFP64Test1::GPUShaderFP64Test1(deqp::Context& context)
1584 : TestCase(context, "errors", "Verifies that various erroneous conditions related to double-precision "
1585 "float uniform support & glUniform*() / glUniformMatrix*() API "
1586 " are reported correctly.")
1587 , m_has_test_passed(true)
1588 , m_po_bool_arr_uniform_location(0)
1589 , m_po_bool_uniform_location(0)
1590 , m_po_bvec2_arr_uniform_location(0)
1591 , m_po_bvec2_uniform_location(0)
1592 , m_po_bvec3_arr_uniform_location(0)
1593 , m_po_bvec3_uniform_location(0)
1594 , m_po_bvec4_arr_uniform_location(0)
1595 , m_po_bvec4_uniform_location(0)
1596 , m_po_dmat2_arr_uniform_location(0)
1597 , m_po_dmat2_uniform_location(0)
1598 , m_po_dmat2x3_arr_uniform_location(0)
1599 , m_po_dmat2x3_uniform_location(0)
1600 , m_po_dmat2x4_arr_uniform_location(0)
1601 , m_po_dmat2x4_uniform_location(0)
1602 , m_po_dmat3_arr_uniform_location(0)
1603 , m_po_dmat3_uniform_location(0)
1604 , m_po_dmat3x2_arr_uniform_location(0)
1605 , m_po_dmat3x2_uniform_location(0)
1606 , m_po_dmat3x4_arr_uniform_location(0)
1607 , m_po_dmat3x4_uniform_location(0)
1608 , m_po_dmat4_arr_uniform_location(0)
1609 , m_po_dmat4_uniform_location(0)
1610 , m_po_dmat4x2_arr_uniform_location(0)
1611 , m_po_dmat4x2_uniform_location(0)
1612 , m_po_dmat4x3_arr_uniform_location(0)
1613 , m_po_dmat4x3_uniform_location(0)
1614 , m_po_double_arr_uniform_location(0)
1615 , m_po_double_uniform_location(0)
1616 , m_po_dvec2_arr_uniform_location(0)
1617 , m_po_dvec2_uniform_location(0)
1618 , m_po_dvec3_arr_uniform_location(0)
1619 , m_po_dvec3_uniform_location(0)
1620 , m_po_dvec4_arr_uniform_location(0)
1621 , m_po_dvec4_uniform_location(0)
1622 , m_po_float_arr_uniform_location(0)
1623 , m_po_float_uniform_location(0)
1624 , m_po_int_arr_uniform_location(0)
1625 , m_po_int_uniform_location(0)
1626 , m_po_ivec2_arr_uniform_location(0)
1627 , m_po_ivec2_uniform_location(0)
1628 , m_po_ivec3_arr_uniform_location(0)
1629 , m_po_ivec3_uniform_location(0)
1630 , m_po_ivec4_arr_uniform_location(0)
1631 , m_po_ivec4_uniform_location(0)
1632 , m_po_sampler_uniform_location(0)
1633 , m_po_uint_arr_uniform_location(0)
1634 , m_po_uint_uniform_location(0)
1635 , m_po_uvec2_arr_uniform_location(0)
1636 , m_po_uvec2_uniform_location(0)
1637 , m_po_uvec3_arr_uniform_location(0)
1638 , m_po_uvec3_uniform_location(0)
1639 , m_po_uvec4_arr_uniform_location(0)
1640 , m_po_uvec4_uniform_location(0)
1641 , m_po_vec2_arr_uniform_location(0)
1642 , m_po_vec2_uniform_location(0)
1643 , m_po_vec3_arr_uniform_location(0)
1644 , m_po_vec3_uniform_location(0)
1645 , m_po_vec4_arr_uniform_location(0)
1646 , m_po_vec4_uniform_location(0)
1647 , m_po_id(0)
1648 , m_vs_id(0)
1649 {
1650 /* Left blank intentionally */
1651 }
1652
1653 /** Deinitializes all GL objects that may have been created during
1654 * test execution.
1655 **/
deinit()1656 void GPUShaderFP64Test1::deinit()
1657 {
1658 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1659
1660 if (m_po_id != 0)
1661 {
1662 gl.deleteProgram(m_po_id);
1663
1664 m_po_id = 0;
1665 }
1666
1667 if (m_vs_id != 0)
1668 {
1669 gl.deleteShader(m_vs_id);
1670
1671 m_vs_id = 0;
1672 }
1673 }
1674
1675 /** Returns a string describing GL API function represented by user-provided enum.
1676 *
1677 * @param func Uniform function to return the string for.
1678 *
1679 * @return As per description. [?] will be returned if the function was not recognized.
1680 **/
getUniformFunctionString(_uniform_function func)1681 const char* GPUShaderFP64Test1::getUniformFunctionString(_uniform_function func)
1682 {
1683 const char* result = "[?]";
1684
1685 switch (func)
1686 {
1687 case UNIFORM_FUNCTION_1D:
1688 result = "glUniform1d";
1689 break;
1690 case UNIFORM_FUNCTION_1DV:
1691 result = "glUniform1dv";
1692 break;
1693 case UNIFORM_FUNCTION_2D:
1694 result = "glUniform2d";
1695 break;
1696 case UNIFORM_FUNCTION_2DV:
1697 result = "glUniform2dv";
1698 break;
1699 case UNIFORM_FUNCTION_3D:
1700 result = "glUniform3d";
1701 break;
1702 case UNIFORM_FUNCTION_3DV:
1703 result = "glUniform3dv";
1704 break;
1705 case UNIFORM_FUNCTION_4D:
1706 result = "glUniform4d";
1707 break;
1708 case UNIFORM_FUNCTION_4DV:
1709 result = "glUniform4dv";
1710 break;
1711 case UNIFORM_FUNCTION_MATRIX2DV:
1712 result = "glUniformMatrix2dv";
1713 break;
1714 case UNIFORM_FUNCTION_MATRIX2X3DV:
1715 result = "glUniformMatrix2x3dv";
1716 break;
1717 case UNIFORM_FUNCTION_MATRIX2X4DV:
1718 result = "glUniformMatrix2x4dv";
1719 break;
1720 case UNIFORM_FUNCTION_MATRIX3DV:
1721 result = "glUniformMatrix3dv";
1722 break;
1723 case UNIFORM_FUNCTION_MATRIX3X2DV:
1724 result = "glUniformMatrix3x2dv";
1725 break;
1726 case UNIFORM_FUNCTION_MATRIX3X4DV:
1727 result = "glUniformMatrix3x4dv";
1728 break;
1729 case UNIFORM_FUNCTION_MATRIX4DV:
1730 result = "glUniformMatrix4dv";
1731 break;
1732 case UNIFORM_FUNCTION_MATRIX4X2DV:
1733 result = "glUniformMatrix4x2dv";
1734 break;
1735 case UNIFORM_FUNCTION_MATRIX4X3DV:
1736 result = "glUniformMatrix4x3dv";
1737 break;
1738 default:
1739 break;
1740 }
1741
1742 return result;
1743 }
1744
1745 /** Returns name of an uniform bound to user-provided location.
1746 *
1747 * @param location Location of the uniform to return the name for.
1748 *
1749 * @return As per description. [?] will be returned if the location was not
1750 * recognized.
1751 **/
getUniformNameForLocation(glw::GLint location)1752 const char* GPUShaderFP64Test1::getUniformNameForLocation(glw::GLint location)
1753 {
1754 const char* result = "[?]";
1755
1756 if (location == m_po_bool_arr_uniform_location)
1757 result = "uniform_bool_arr";
1758 else if (location == m_po_bool_uniform_location)
1759 result = "uniform_bool";
1760 else if (location == m_po_bvec2_arr_uniform_location)
1761 result = "uniform_bvec2_arr";
1762 else if (location == m_po_bvec2_uniform_location)
1763 result = "uniform_bvec2";
1764 else if (location == m_po_bvec3_arr_uniform_location)
1765 result = "uniform_bvec3_arr";
1766 else if (location == m_po_bvec3_uniform_location)
1767 result = "uniform_bvec3";
1768 else if (location == m_po_bvec4_arr_uniform_location)
1769 result = "uniform_bvec4_arr";
1770 else if (location == m_po_bvec4_uniform_location)
1771 result = "uniform_bvec4";
1772 else if (location == m_po_dmat2_arr_uniform_location)
1773 result = "uniform_dmat2_arr";
1774 else if (location == m_po_dmat2_uniform_location)
1775 result = "uniform_dmat2";
1776 else if (location == m_po_dmat2x3_arr_uniform_location)
1777 result = "uniform_dmat2x3_arr";
1778 else if (location == m_po_dmat2x3_uniform_location)
1779 result = "uniform_dmat2x3";
1780 else if (location == m_po_dmat2x4_arr_uniform_location)
1781 result = "uniform_dmat2x4_arr";
1782 else if (location == m_po_dmat2x4_uniform_location)
1783 result = "uniform_dmat2x4";
1784 else if (location == m_po_dmat3_arr_uniform_location)
1785 result = "uniform_dmat3_arr";
1786 else if (location == m_po_dmat3_uniform_location)
1787 result = "uniform_dmat3";
1788 else if (location == m_po_dmat3x2_arr_uniform_location)
1789 result = "uniform_dmat3x2_arr";
1790 else if (location == m_po_dmat3x2_uniform_location)
1791 result = "uniform_dmat3x2";
1792 else if (location == m_po_dmat3x4_arr_uniform_location)
1793 result = "uniform_dmat3x4_arr";
1794 else if (location == m_po_dmat3x4_uniform_location)
1795 result = "uniform_dmat3x4";
1796 else if (location == m_po_dmat4_arr_uniform_location)
1797 result = "uniform_dmat4_arr";
1798 else if (location == m_po_dmat4_uniform_location)
1799 result = "uniform_dmat4";
1800 else if (location == m_po_dmat4x2_arr_uniform_location)
1801 result = "uniform_dmat4x2_arr";
1802 else if (location == m_po_dmat4x2_uniform_location)
1803 result = "uniform_dmat4x2";
1804 else if (location == m_po_dmat4x3_arr_uniform_location)
1805 result = "uniform_dmat4x3_arr";
1806 else if (location == m_po_dmat4x3_uniform_location)
1807 result = "uniform_dmat4x3";
1808 else if (location == m_po_double_arr_uniform_location)
1809 result = "uniform_double_arr";
1810 else if (location == m_po_double_uniform_location)
1811 result = "uniform_double";
1812 else if (location == m_po_dvec2_arr_uniform_location)
1813 result = "uniform_dvec2_arr";
1814 else if (location == m_po_dvec2_uniform_location)
1815 result = "uniform_dvec2";
1816 else if (location == m_po_dvec3_arr_uniform_location)
1817 result = "uniform_dvec3_arr";
1818 else if (location == m_po_dvec3_uniform_location)
1819 result = "uniform_dvec3";
1820 else if (location == m_po_dvec4_arr_uniform_location)
1821 result = "uniform_dvec4_arr";
1822 else if (location == m_po_dvec4_uniform_location)
1823 result = "uniform_dvec4";
1824 else if (location == m_po_float_arr_uniform_location)
1825 result = "uniform_float_arr";
1826 else if (location == m_po_float_uniform_location)
1827 result = "uniform_float";
1828 else if (location == m_po_int_arr_uniform_location)
1829 result = "uniform_int_arr";
1830 else if (location == m_po_int_uniform_location)
1831 result = "uniform_int";
1832 else if (location == m_po_ivec2_arr_uniform_location)
1833 result = "uniform_ivec2_arr";
1834 else if (location == m_po_ivec2_uniform_location)
1835 result = "uniform_ivec2";
1836 else if (location == m_po_ivec3_arr_uniform_location)
1837 result = "uniform_ivec3_arr";
1838 else if (location == m_po_ivec3_uniform_location)
1839 result = "uniform_ivec3";
1840 else if (location == m_po_ivec4_arr_uniform_location)
1841 result = "uniform_ivec4_arr";
1842 else if (location == m_po_ivec4_uniform_location)
1843 result = "uniform_ivec4";
1844 else if (location == m_po_uint_arr_uniform_location)
1845 result = "uniform_uint_arr";
1846 else if (location == m_po_uint_uniform_location)
1847 result = "uniform_uint";
1848 else if (location == m_po_uvec2_arr_uniform_location)
1849 result = "uniform_uvec2_arr";
1850 else if (location == m_po_uvec2_uniform_location)
1851 result = "uniform_uvec2";
1852 else if (location == m_po_uvec3_arr_uniform_location)
1853 result = "uniform_uvec3_arr";
1854 else if (location == m_po_uvec3_uniform_location)
1855 result = "uniform_uvec3";
1856 else if (location == m_po_uvec4_arr_uniform_location)
1857 result = "uniform_uvec4_arr";
1858 else if (location == m_po_uvec4_uniform_location)
1859 result = "uniform_uvec4";
1860 else if (location == m_po_vec2_arr_uniform_location)
1861 result = "uniform_vec2_arr";
1862 else if (location == m_po_vec2_uniform_location)
1863 result = "uniform_vec2";
1864 else if (location == m_po_vec3_arr_uniform_location)
1865 result = "uniform_vec3_arr";
1866 else if (location == m_po_vec3_uniform_location)
1867 result = "uniform_vec3";
1868 else if (location == m_po_vec4_arr_uniform_location)
1869 result = "uniform_vec4_arr";
1870 else if (location == m_po_vec4_uniform_location)
1871 result = "uniform_vec4";
1872
1873 return result;
1874 }
1875
1876 /** Initializes all GL objects required to run the test. Also extracts locations of all
1877 * uniforms used by the test.
1878 *
1879 * This function can throw a TestError exception if the implementation misbehaves.
1880 */
initTest()1881 void GPUShaderFP64Test1::initTest()
1882 {
1883 glw::GLint compile_status = GL_FALSE;
1884 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1885 glw::GLint link_status = GL_FALSE;
1886
1887 /* Set up a program object using all new double-precision types */
1888 const char* vs_body =
1889 "#version 400\n"
1890 "\n"
1891 "uniform bool uniform_bool;\n"
1892 "uniform bvec2 uniform_bvec2;\n"
1893 "uniform bvec3 uniform_bvec3;\n"
1894 "uniform bvec4 uniform_bvec4;\n"
1895 "uniform dmat2 uniform_dmat2;\n"
1896 "uniform dmat2x3 uniform_dmat2x3;\n"
1897 "uniform dmat2x4 uniform_dmat2x4;\n"
1898 "uniform dmat3 uniform_dmat3;\n"
1899 "uniform dmat3x2 uniform_dmat3x2;\n"
1900 "uniform dmat3x4 uniform_dmat3x4;\n"
1901 "uniform dmat4 uniform_dmat4;\n"
1902 "uniform dmat4x2 uniform_dmat4x2;\n"
1903 "uniform dmat4x3 uniform_dmat4x3;\n"
1904 "uniform double uniform_double;\n"
1905 "uniform dvec2 uniform_dvec2;\n"
1906 "uniform dvec3 uniform_dvec3;\n"
1907 "uniform dvec4 uniform_dvec4;\n"
1908 "uniform float uniform_float;\n"
1909 "uniform int uniform_int;\n"
1910 "uniform ivec2 uniform_ivec2;\n"
1911 "uniform ivec3 uniform_ivec3;\n"
1912 "uniform ivec4 uniform_ivec4;\n"
1913 "uniform sampler2D uniform_sampler;\n"
1914 "uniform uint uniform_uint;\n"
1915 "uniform uvec2 uniform_uvec2;\n"
1916 "uniform uvec3 uniform_uvec3;\n"
1917 "uniform uvec4 uniform_uvec4;\n"
1918 "uniform vec2 uniform_vec2;\n"
1919 "uniform vec3 uniform_vec3;\n"
1920 "uniform vec4 uniform_vec4;\n"
1921 "uniform bool uniform_bool_arr [2];\n"
1922 "uniform bvec2 uniform_bvec2_arr [2];\n"
1923 "uniform bvec3 uniform_bvec3_arr [2];\n"
1924 "uniform bvec4 uniform_bvec4_arr [2];\n"
1925 "uniform dmat2 uniform_dmat2_arr [2];\n"
1926 "uniform dmat2x3 uniform_dmat2x3_arr[2];\n"
1927 "uniform dmat2x4 uniform_dmat2x4_arr[2];\n"
1928 "uniform dmat3 uniform_dmat3_arr [2];\n"
1929 "uniform dmat3x2 uniform_dmat3x2_arr[2];\n"
1930 "uniform dmat3x4 uniform_dmat3x4_arr[2];\n"
1931 "uniform dmat4 uniform_dmat4_arr [2];\n"
1932 "uniform dmat4x2 uniform_dmat4x2_arr[2];\n"
1933 "uniform dmat4x3 uniform_dmat4x3_arr[2];\n"
1934 "uniform double uniform_double_arr [2];\n"
1935 "uniform dvec2 uniform_dvec2_arr [2];\n"
1936 "uniform dvec3 uniform_dvec3_arr [2];\n"
1937 "uniform dvec4 uniform_dvec4_arr [2];\n"
1938 "uniform float uniform_float_arr [2];\n"
1939 "uniform int uniform_int_arr [2];\n"
1940 "uniform ivec2 uniform_ivec2_arr [2];\n"
1941 "uniform ivec3 uniform_ivec3_arr [2];\n"
1942 "uniform ivec4 uniform_ivec4_arr [2];\n"
1943 "uniform uint uniform_uint_arr [2];\n"
1944 "uniform uvec2 uniform_uvec2_arr [2];\n"
1945 "uniform uvec3 uniform_uvec3_arr [2];\n"
1946 "uniform uvec4 uniform_uvec4_arr [2];\n"
1947 "uniform vec2 uniform_vec2_arr [2];\n"
1948 "uniform vec3 uniform_vec3_arr [2];\n"
1949 "uniform vec4 uniform_vec4_arr [2];\n"
1950 "\n"
1951 "void main()\n"
1952 "{\n"
1953 " gl_Position = vec4(0) + texture(uniform_sampler, vec2(0) );\n"
1954 "\n"
1955 " if (uniform_bool && uniform_bvec2.y && uniform_bvec3.z && uniform_bvec4.w &&\n"
1956 " uniform_bool_arr[1] && uniform_bvec2_arr[1].y && uniform_bvec3_arr[1].z && uniform_bvec4_arr[1].w)\n"
1957 " {\n"
1958 " double sum = uniform_dmat2 [0].x + uniform_dmat2x3 [0].x + uniform_dmat2x4 [0].x +\n"
1959 " uniform_dmat3 [0].x + uniform_dmat3x2 [0].x + uniform_dmat3x4 [0].x +\n"
1960 " uniform_dmat4 [0].x + uniform_dmat4x2 [0].x + uniform_dmat4x3 [0].x +\n"
1961 " uniform_dmat2_arr[0][0].x + uniform_dmat2x3_arr[0][0].x + uniform_dmat2x4_arr[0][0].x +\n"
1962 " uniform_dmat3_arr[0][0].x + uniform_dmat3x2_arr[0][0].x + uniform_dmat3x4_arr[0][0].x +\n"
1963 " uniform_dmat4_arr[0][0].x + uniform_dmat4x2_arr[0][0].x + uniform_dmat4x3_arr[0][0].x +\n"
1964 " uniform_double + uniform_double_arr [0] +\n"
1965 " uniform_dvec2.x + uniform_dvec3.x + uniform_dvec4.x +\n"
1966 " uniform_dvec2_arr[0].x + uniform_dvec3_arr[0].x + uniform_dvec4_arr[0].x;\n"
1967 " int sum2 = uniform_int + uniform_ivec2.x + uniform_ivec3.x +\n"
1968 " uniform_ivec4.x + uniform_ivec2_arr[0].x + uniform_ivec3_arr[0].x +\n"
1969 " uniform_ivec4_arr[0].x + uniform_int_arr[0];\n"
1970 " uint sum3 = uniform_uint + uniform_uvec2.x + uniform_uvec3.x +\n"
1971 " uniform_uvec4.x + uniform_uint_arr[0] + uniform_uvec2_arr[0].x +\n"
1972 " uniform_uvec3_arr[0].x + uniform_uvec4_arr[0].x;\n"
1973 " float sum4 = uniform_float + uniform_float_arr[0] + \n"
1974 " uniform_vec2.x + uniform_vec2_arr[0].x + \n"
1975 " uniform_vec3.x + uniform_vec3_arr[0].x + \n"
1976 " uniform_vec4.x + uniform_vec4_arr[0].x;\n"
1977 "\n"
1978 " if (sum * sum4 > intBitsToFloat(sum2) * uintBitsToFloat(sum3) )\n"
1979 " {\n"
1980 " gl_Position = vec4(1);\n"
1981 " }\n"
1982 " }\n"
1983 "}\n";
1984
1985 m_po_id = gl.createProgram();
1986 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1987
1988 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1989 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
1990
1991 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
1992 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
1993
1994 gl.compileShader(m_vs_id);
1995 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
1996
1997 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
1998 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
1999
2000 if (compile_status != GL_TRUE)
2001 {
2002 TCU_FAIL("Shader compilation failed.");
2003 }
2004
2005 gl.attachShader(m_po_id, m_vs_id);
2006 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
2007
2008 gl.linkProgram(m_po_id);
2009 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
2010
2011 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
2012 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
2013
2014 if (link_status != GL_TRUE)
2015 {
2016 TCU_FAIL("Program linking failed.");
2017 }
2018
2019 m_po_bool_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool_arr[0]");
2020 m_po_bool_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bool");
2021 m_po_bvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2_arr[0]");
2022 m_po_bvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec2");
2023 m_po_bvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3_arr[0]");
2024 m_po_bvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec3");
2025 m_po_bvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4_arr[0]");
2026 m_po_bvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_bvec4");
2027 m_po_dmat2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2_arr[0]");
2028 m_po_dmat2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2");
2029 m_po_dmat2x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3_arr[0]");
2030 m_po_dmat2x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x3");
2031 m_po_dmat2x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4_arr[0]");
2032 m_po_dmat2x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat2x4");
2033 m_po_dmat3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3_arr[0]");
2034 m_po_dmat3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3");
2035 m_po_dmat3x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2_arr[0]");
2036 m_po_dmat3x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x2");
2037 m_po_dmat3x4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4_arr[0]");
2038 m_po_dmat3x4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat3x4");
2039 m_po_dmat4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4_arr[0]");
2040 m_po_dmat4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4");
2041 m_po_dmat4x2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2_arr[0]");
2042 m_po_dmat4x2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x2");
2043 m_po_dmat4x3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3_arr[0]");
2044 m_po_dmat4x3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dmat4x3");
2045 m_po_double_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double_arr[0]");
2046 m_po_double_uniform_location = gl.getUniformLocation(m_po_id, "uniform_double");
2047 m_po_dvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2_arr[0]");
2048 m_po_dvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec2");
2049 m_po_dvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3_arr[0]");
2050 m_po_dvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec3");
2051 m_po_dvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4_arr[0]");
2052 m_po_dvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_dvec4");
2053 m_po_float_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float_arr[0]");
2054 m_po_float_uniform_location = gl.getUniformLocation(m_po_id, "uniform_float");
2055 m_po_int_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int_arr[0]");
2056 m_po_int_uniform_location = gl.getUniformLocation(m_po_id, "uniform_int");
2057 m_po_ivec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2_arr[0]");
2058 m_po_ivec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec2");
2059 m_po_ivec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3_arr[0]");
2060 m_po_ivec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec3");
2061 m_po_ivec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4_arr[0]");
2062 m_po_ivec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_ivec4");
2063 m_po_sampler_uniform_location = gl.getUniformLocation(m_po_id, "uniform_sampler");
2064 m_po_uint_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint_arr[0]");
2065 m_po_uint_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uint");
2066 m_po_uvec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2_arr[0]");
2067 m_po_uvec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec2");
2068 m_po_uvec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3_arr[0]");
2069 m_po_uvec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec3");
2070 m_po_uvec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4_arr[0]");
2071 m_po_uvec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_uvec4");
2072 m_po_vec2_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2_arr[0]");
2073 m_po_vec2_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec2");
2074 m_po_vec3_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3_arr[0]");
2075 m_po_vec3_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec3");
2076 m_po_vec4_arr_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4_arr[0]");
2077 m_po_vec4_uniform_location = gl.getUniformLocation(m_po_id, "uniform_vec4");
2078 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call(s) failed.");
2079
2080 if (m_po_bool_arr_uniform_location == -1 || m_po_bool_uniform_location == -1 ||
2081 m_po_bvec2_arr_uniform_location == -1 || m_po_bvec2_uniform_location == -1 ||
2082 m_po_bvec3_arr_uniform_location == -1 || m_po_bvec3_uniform_location == -1 ||
2083 m_po_bvec4_arr_uniform_location == -1 || m_po_bvec4_uniform_location == -1 ||
2084 m_po_dmat2_arr_uniform_location == -1 || m_po_dmat2_uniform_location == -1 ||
2085 m_po_dmat2x3_arr_uniform_location == -1 || m_po_dmat2x3_uniform_location == -1 ||
2086 m_po_dmat2x4_arr_uniform_location == -1 || m_po_dmat2x4_uniform_location == -1 ||
2087 m_po_dmat3_arr_uniform_location == -1 || m_po_dmat3_uniform_location == -1 ||
2088 m_po_dmat3x2_arr_uniform_location == -1 || m_po_dmat3x2_uniform_location == -1 ||
2089 m_po_dmat3x4_arr_uniform_location == -1 || m_po_dmat3x4_uniform_location == -1 ||
2090 m_po_dmat4_arr_uniform_location == -1 || m_po_dmat4_uniform_location == -1 ||
2091 m_po_dmat4x2_arr_uniform_location == -1 || m_po_dmat4x2_uniform_location == -1 ||
2092 m_po_dmat4x3_arr_uniform_location == -1 || m_po_dmat4x3_uniform_location == -1 ||
2093 m_po_double_arr_uniform_location == -1 || m_po_double_uniform_location == -1 ||
2094 m_po_dvec2_arr_uniform_location == -1 || m_po_dvec2_uniform_location == -1 ||
2095 m_po_dvec3_arr_uniform_location == -1 || m_po_dvec3_uniform_location == -1 ||
2096 m_po_dvec4_arr_uniform_location == -1 || m_po_dvec4_uniform_location == -1 ||
2097 m_po_float_arr_uniform_location == -1 || m_po_float_uniform_location == -1 ||
2098 m_po_int_arr_uniform_location == -1 || m_po_int_uniform_location == -1 ||
2099 m_po_ivec2_arr_uniform_location == -1 || m_po_ivec2_uniform_location == -1 ||
2100 m_po_ivec3_arr_uniform_location == -1 || m_po_ivec3_uniform_location == -1 ||
2101 m_po_ivec4_arr_uniform_location == -1 || m_po_ivec4_uniform_location == -1 ||
2102 m_po_sampler_uniform_location == -1 || m_po_uint_arr_uniform_location == -1 ||
2103 m_po_uint_uniform_location == -1 || m_po_uvec2_arr_uniform_location == -1 ||
2104 m_po_uvec2_uniform_location == -1 || m_po_uvec3_arr_uniform_location == -1 ||
2105 m_po_uvec3_uniform_location == -1 || m_po_uvec4_arr_uniform_location == -1 ||
2106 m_po_uvec4_uniform_location == -1 || m_po_vec2_arr_uniform_location == -1 || m_po_vec2_uniform_location == -1 ||
2107 m_po_vec3_arr_uniform_location == -1 || m_po_vec3_uniform_location == -1 ||
2108 m_po_vec4_arr_uniform_location == -1 || m_po_vec4_uniform_location == -1)
2109 {
2110 TCU_FAIL("At last one of the required uniforms is considered inactive.");
2111 }
2112 }
2113
2114 /** Tells wheter uniform at user-specified location represents a double-precision
2115 * matrix uniform.
2116 *
2117 * @param uniform_location Location of the uniform to use for the query.
2118 *
2119 * @return Requested information.
2120 **/
isMatrixUniform(glw::GLint uniform_location)2121 bool GPUShaderFP64Test1::isMatrixUniform(glw::GLint uniform_location)
2122 {
2123 return (uniform_location == m_po_dmat2_uniform_location || uniform_location == m_po_dmat2x3_uniform_location ||
2124 uniform_location == m_po_dmat2x4_uniform_location || uniform_location == m_po_dmat3_uniform_location ||
2125 uniform_location == m_po_dmat3x2_uniform_location || uniform_location == m_po_dmat3x4_uniform_location ||
2126 uniform_location == m_po_dmat4_uniform_location || uniform_location == m_po_dmat4x2_uniform_location ||
2127 uniform_location == m_po_dmat4x3_uniform_location);
2128 }
2129
2130 /** Tells whether user-specified uniform function corresponds to one of the
2131 * functions in glUniformMatrix*() class.
2132 *
2133 * @param func Uniform function enum to use for the query.
2134 *
2135 * @return true if the specified enum represents one of the glUniformMatrix*() functions,
2136 * false otherwise.
2137 **/
isMatrixUniformFunction(_uniform_function func)2138 bool GPUShaderFP64Test1::isMatrixUniformFunction(_uniform_function func)
2139 {
2140 return (func == UNIFORM_FUNCTION_MATRIX2DV || func == UNIFORM_FUNCTION_MATRIX2X3DV ||
2141 func == UNIFORM_FUNCTION_MATRIX2X4DV || func == UNIFORM_FUNCTION_MATRIX3DV ||
2142 func == UNIFORM_FUNCTION_MATRIX3X2DV || func == UNIFORM_FUNCTION_MATRIX3X4DV ||
2143 func == UNIFORM_FUNCTION_MATRIX4DV || func == UNIFORM_FUNCTION_MATRIX4X2DV ||
2144 func == UNIFORM_FUNCTION_MATRIX4X3DV);
2145 }
2146
2147 /** Executes test iteration.
2148 *
2149 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
2150 */
iterate()2151 tcu::TestNode::IterateResult GPUShaderFP64Test1::iterate()
2152 {
2153 /* Do not execute the test if GL_ARB_texture_view is not supported */
2154 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
2155 {
2156 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
2157 }
2158
2159 /* Initialize all ES objects required to run all the checks */
2160 initTest();
2161
2162 /* Make sure GL_INVALID_OPERATION is generated by glUniform*() and
2163 * glUniformMatrix*() functions if there is no current program object.
2164 */
2165 m_has_test_passed &= verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO();
2166
2167 /* Make sure GL_INVALID_OPERATION is generated by glUniform*() if
2168 * the size of the uniform variable declared in the shader does not
2169 * match the size indicated by the command.
2170 */
2171 m_has_test_passed &= verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions();
2172
2173 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2174 * glUniformMatrix*() are used to load a uniform variable of type
2175 * bool, bvec2, bvec3, bvec4, float, int, ivec2, ivec3, ivec4,
2176 * unsigned int, uvec2, uvec3, uvec4, vec2, vec3, vec4 or an array
2177 * of these.
2178 */
2179 m_has_test_passed &= verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions();
2180
2181 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2182 * glUniformMatrix*() are used to load incompatible double-typed
2183 * uniforms, as presented below:
2184 *
2185 * I. double-typed uniform configured by glUniform2d();
2186 * II. double-typed uniform configured by glUniform3d();
2187 * III. double-typed uniform configured by glUniform4d();
2188 * IV. double-typed uniform configured by glUniformMatrix*();
2189 * V. dvec2-typed uniform configured by glUniform1d();
2190 * VI. dvec2-typed uniform configured by glUniform3d();
2191 * VII. dvec2-typed uniform configured by glUniform4d();
2192 * VIII. dvec2-typed uniform configured by glUniformMatrix*();
2193 *
2194 * (etc.)
2195 *
2196 */
2197 m_has_test_passed &= verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions();
2198
2199 /* Make sure GL_INVALID_OPERATION is generated if <location> of
2200 * glUniform*() and glUniformMatrix*() is an invalid uniform
2201 * location for the current program object and location is not
2202 * equal to -1.
2203 */
2204 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation();
2205
2206 /* Make sure GL_INVALID_VALUE is generated if <count> of
2207 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2208 * negative.
2209 */
2210 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount();
2211
2212 /* Make sure GL_INVALID_OPERATION is generated if <count> of
2213 * glUniform*() (*dv() functions only) and glUniformMatrix*() is
2214 * greater than 1 and the indicated uniform variable is not an
2215 * array variable.
2216 */
2217 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount();
2218
2219 /* Make sure GL_INVALID_OPERATION is generated if a sampler is
2220 * loaded by glUniform*() and glUniformMatrix*().
2221 */
2222 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers();
2223
2224 /* Make sure GL_INVALID_OPERATION is generated if glUniform*() and
2225 * glUniformMatrix*() is used to load values for uniforms of
2226 * boolean types.
2227 */
2228 m_has_test_passed &= verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans();
2229
2230 if (m_has_test_passed)
2231 {
2232 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2233 }
2234 else
2235 {
2236 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2237 }
2238
2239 return STOP;
2240 }
2241
2242 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2243 * glUniformMatrix*dv() functions is used to load a boolean uniform.
2244 *
2245 * @return true if the implementation was found to behave as expected, false otherwise.
2246 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()2247 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForBooleans()
2248 {
2249 const double double_data[] = {
2250 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2251 };
2252 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2253 bool result = true;
2254 glw::GLint uniform_locations[] = { m_po_bool_arr_uniform_location, m_po_bool_uniform_location,
2255 m_po_bvec2_arr_uniform_location, m_po_bvec2_uniform_location,
2256 m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2257 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location };
2258 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2259
2260 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2261 ++n_uniform_function)
2262 {
2263 const _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2264
2265 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2266 {
2267 const glw::GLint uniform_location = uniform_locations[n_uniform_location];
2268
2269 switch (uniform_function)
2270 {
2271 case UNIFORM_FUNCTION_1D:
2272 gl.uniform1d(uniform_location, 0.0);
2273 break;
2274 case UNIFORM_FUNCTION_2D:
2275 gl.uniform2d(uniform_location, 0.0, 1.0);
2276 break;
2277 case UNIFORM_FUNCTION_3D:
2278 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
2279 break;
2280 case UNIFORM_FUNCTION_4D:
2281 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
2282 break;
2283
2284 case UNIFORM_FUNCTION_1DV:
2285 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2286 break;
2287 case UNIFORM_FUNCTION_2DV:
2288 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2289 break;
2290 case UNIFORM_FUNCTION_3DV:
2291 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2292 break;
2293 case UNIFORM_FUNCTION_4DV:
2294 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2295 break;
2296
2297 case UNIFORM_FUNCTION_MATRIX2DV:
2298 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2299 break;
2300 case UNIFORM_FUNCTION_MATRIX2X3DV:
2301 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2302 break;
2303 case UNIFORM_FUNCTION_MATRIX2X4DV:
2304 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2305 break;
2306 case UNIFORM_FUNCTION_MATRIX3DV:
2307 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2308 break;
2309 case UNIFORM_FUNCTION_MATRIX3X2DV:
2310 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2311 break;
2312 case UNIFORM_FUNCTION_MATRIX3X4DV:
2313 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2314 break;
2315 case UNIFORM_FUNCTION_MATRIX4DV:
2316 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2317 break;
2318 case UNIFORM_FUNCTION_MATRIX4X2DV:
2319 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2320 break;
2321 case UNIFORM_FUNCTION_MATRIX4X3DV:
2322 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2323 break;
2324
2325 default:
2326 {
2327 TCU_FAIL("Unrecognized uniform function");
2328 }
2329 }
2330
2331 /* Make sure GL_INVALID_OPERATION was generated by the call */
2332 const glw::GLenum error_code = gl.getError();
2333
2334 if (error_code != GL_INVALID_OPERATION)
2335 {
2336 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2337 << "() did not generate an error"
2338 " when applied against a boolean uniform."
2339 << tcu::TestLog::EndMessage;
2340
2341 result = false;
2342 }
2343 } /* for (all bool uniforms) */
2344 } /* for (all uniform functions) */
2345
2346 return result;
2347 }
2348
2349 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2350 * glUniformMatrix*dv() functions is used to load a sampler2D uniform.
2351 *
2352 * @return true if the implementation was found to behave as expected, false otherwise.
2353 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()2354 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsForSamplers()
2355 {
2356 const double double_data[] = {
2357 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2358 };
2359 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2360 bool result = true;
2361
2362 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2363 ++n_uniform_function)
2364 {
2365 _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2366
2367 switch (uniform_function)
2368 {
2369 case UNIFORM_FUNCTION_1D:
2370 gl.uniform1d(m_po_sampler_uniform_location, 0.0);
2371 break;
2372 case UNIFORM_FUNCTION_2D:
2373 gl.uniform2d(m_po_sampler_uniform_location, 0.0, 1.0);
2374 break;
2375 case UNIFORM_FUNCTION_3D:
2376 gl.uniform3d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0);
2377 break;
2378 case UNIFORM_FUNCTION_4D:
2379 gl.uniform4d(m_po_sampler_uniform_location, 0.0, 1.0, 2.0, 3.0);
2380 break;
2381
2382 case UNIFORM_FUNCTION_1DV:
2383 gl.uniform1dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2384 break;
2385 case UNIFORM_FUNCTION_2DV:
2386 gl.uniform2dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2387 break;
2388 case UNIFORM_FUNCTION_3DV:
2389 gl.uniform3dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2390 break;
2391 case UNIFORM_FUNCTION_4DV:
2392 gl.uniform4dv(m_po_sampler_uniform_location, 1 /* count */, double_data);
2393 break;
2394
2395 case UNIFORM_FUNCTION_MATRIX2DV:
2396 gl.uniformMatrix2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2397 break;
2398 case UNIFORM_FUNCTION_MATRIX2X3DV:
2399 gl.uniformMatrix2x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2400 break;
2401 case UNIFORM_FUNCTION_MATRIX2X4DV:
2402 gl.uniformMatrix2x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2403 break;
2404 case UNIFORM_FUNCTION_MATRIX3DV:
2405 gl.uniformMatrix3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2406 break;
2407 case UNIFORM_FUNCTION_MATRIX3X2DV:
2408 gl.uniformMatrix3x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2409 break;
2410 case UNIFORM_FUNCTION_MATRIX3X4DV:
2411 gl.uniformMatrix3x4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2412 break;
2413 case UNIFORM_FUNCTION_MATRIX4DV:
2414 gl.uniformMatrix4dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2415 break;
2416 case UNIFORM_FUNCTION_MATRIX4X2DV:
2417 gl.uniformMatrix4x2dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2418 break;
2419 case UNIFORM_FUNCTION_MATRIX4X3DV:
2420 gl.uniformMatrix4x3dv(m_po_sampler_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2421 break;
2422
2423 default:
2424 {
2425 TCU_FAIL("Unrecognized uniform function");
2426 }
2427 }
2428
2429 /* Make sure GL_INVALID_OPERATION was generated by the call */
2430 const glw::GLenum error_code = gl.getError();
2431
2432 if (error_code != GL_INVALID_OPERATION)
2433 {
2434 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2435 << "() did not generate an error"
2436 " when applied against a sampler uniform."
2437 << tcu::TestLog::EndMessage;
2438
2439 result = false;
2440 }
2441 } /* for (all uniform functions) */
2442
2443 return result;
2444 }
2445
2446 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*dv() or
2447 * glUniformMatrix*dv() functions is used to load a compatible uniform using an
2448 * invalid <count> argument.
2449 *
2450 * @return true if the implementation was found to behave as expected, false otherwise.
2451 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()2452 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidCount()
2453 {
2454 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
2455 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2456 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2457 bool result = true;
2458 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV,
2459 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV,
2460 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2461 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2462 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2463 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2464 UNIFORM_FUNCTION_MATRIX4X3DV };
2465 const glw::GLint uniforms[] = {
2466 m_po_bool_uniform_location, m_po_bvec2_uniform_location, m_po_bvec3_uniform_location,
2467 m_po_bvec4_uniform_location, m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location,
2468 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location, m_po_dmat3x2_uniform_location,
2469 m_po_dmat3x4_uniform_location, m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location,
2470 m_po_dmat4x3_uniform_location, m_po_double_uniform_location, m_po_dvec2_uniform_location,
2471 m_po_dvec3_uniform_location, m_po_dvec4_uniform_location, m_po_float_uniform_location,
2472 m_po_int_uniform_location, m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
2473 m_po_ivec4_uniform_location, m_po_uint_uniform_location, m_po_uvec2_uniform_location,
2474 m_po_uvec3_uniform_location, m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
2475 m_po_vec3_uniform_location, m_po_vec4_uniform_location
2476 };
2477
2478 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2479 const unsigned int n_uniforms = sizeof(uniforms) / sizeof(uniforms[0]);
2480
2481 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2482 {
2483 _uniform_function uniform_function = uniform_functions[n_uniform_function];
2484
2485 for (unsigned int n_uniform = 0; n_uniform < n_uniforms; ++n_uniform)
2486 {
2487 glw::GLint uniform_location = uniforms[n_uniform];
2488
2489 /* Make sure we only use glUniformMatrix*() functions with matrix uniforms,
2490 * and glUniform*() functions with vector uniforms.
2491 */
2492 bool is_matrix_uniform = isMatrixUniform(uniform_location);
2493
2494 if (((false == is_matrix_uniform) && (true == isMatrixUniformFunction(uniform_function))) ||
2495 ((true == is_matrix_uniform) && (false == isMatrixUniformFunction(uniform_function))))
2496 {
2497 continue;
2498 }
2499
2500 /* Issue the call with an invalid <count> argument */
2501 switch (uniform_function)
2502 {
2503 case UNIFORM_FUNCTION_1DV:
2504 gl.uniform1dv(uniform_location, 2, double_values);
2505 break;
2506 case UNIFORM_FUNCTION_2DV:
2507 gl.uniform2dv(uniform_location, 2, double_values);
2508 break;
2509 case UNIFORM_FUNCTION_3DV:
2510 gl.uniform3dv(uniform_location, 2, double_values);
2511 break;
2512 case UNIFORM_FUNCTION_4DV:
2513 gl.uniform4dv(uniform_location, 2, double_values);
2514 break;
2515 case UNIFORM_FUNCTION_MATRIX2DV:
2516 gl.uniformMatrix2dv(uniform_location, 2, GL_FALSE, double_values);
2517 break;
2518 case UNIFORM_FUNCTION_MATRIX2X3DV:
2519 gl.uniformMatrix2x3dv(uniform_location, 2, GL_FALSE, double_values);
2520 break;
2521 case UNIFORM_FUNCTION_MATRIX2X4DV:
2522 gl.uniformMatrix2x4dv(uniform_location, 2, GL_FALSE, double_values);
2523 break;
2524 case UNIFORM_FUNCTION_MATRIX3DV:
2525 gl.uniformMatrix3dv(uniform_location, 2, GL_FALSE, double_values);
2526 break;
2527 case UNIFORM_FUNCTION_MATRIX3X2DV:
2528 gl.uniformMatrix3x2dv(uniform_location, 2, GL_FALSE, double_values);
2529 break;
2530 case UNIFORM_FUNCTION_MATRIX3X4DV:
2531 gl.uniformMatrix3x4dv(uniform_location, 2, GL_FALSE, double_values);
2532 break;
2533 case UNIFORM_FUNCTION_MATRIX4DV:
2534 gl.uniformMatrix4dv(uniform_location, 2, GL_FALSE, double_values);
2535 break;
2536 case UNIFORM_FUNCTION_MATRIX4X2DV:
2537 gl.uniformMatrix4x2dv(uniform_location, 2, GL_FALSE, double_values);
2538 break;
2539 case UNIFORM_FUNCTION_MATRIX4X3DV:
2540 gl.uniformMatrix4x3dv(uniform_location, 2, GL_FALSE, double_values);
2541 break;
2542
2543 default:
2544 {
2545 TCU_FAIL("Unrecognized uniform function");
2546 }
2547 } /* switch (uniform_function) */
2548
2549 /* Make sure GL_INVALID_VALUE was generated */
2550 glw::GLenum error_code = gl.getError();
2551
2552 if (error_code != GL_INVALID_OPERATION)
2553 {
2554 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2555 << "() "
2556 "was called with an invalid count argument but did not generate a "
2557 "GL_INVALID_OPERATION error"
2558 << tcu::TestLog::EndMessage;
2559
2560 result = false;
2561 }
2562 } /* for (all non-arrayed uniforms) */
2563 } /* for (all uniform functions) */
2564
2565 return result;
2566 }
2567
2568 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2569 * glUniformMatrix*dv() functions is used to load an uniform at an invalid location.
2570 *
2571 * @return true if the implementation was found to behave as expected, false otherwise.
2572 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()2573 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithInvalidLocation()
2574 {
2575 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2576 bool result = true;
2577
2578 /* Find the largest valid uniform location */
2579 const glw::GLint uniform_locations[] = {
2580 m_po_bool_arr_uniform_location, m_po_bool_uniform_location, m_po_bvec2_arr_uniform_location,
2581 m_po_bvec2_uniform_location, m_po_bvec3_arr_uniform_location, m_po_bvec3_uniform_location,
2582 m_po_bvec4_arr_uniform_location, m_po_bvec4_uniform_location, m_po_dmat2_arr_uniform_location,
2583 m_po_dmat2_uniform_location, m_po_dmat2x3_arr_uniform_location, m_po_dmat2x3_uniform_location,
2584 m_po_dmat2x4_arr_uniform_location, m_po_dmat2x4_uniform_location, m_po_dmat3_arr_uniform_location,
2585 m_po_dmat3_uniform_location, m_po_dmat3x2_arr_uniform_location, m_po_dmat3x2_uniform_location,
2586 m_po_dmat3x4_arr_uniform_location, m_po_dmat3x4_uniform_location, m_po_dmat4_arr_uniform_location,
2587 m_po_dmat4_uniform_location, m_po_dmat4x2_arr_uniform_location, m_po_dmat4x2_uniform_location,
2588 m_po_dmat4x3_arr_uniform_location, m_po_dmat4x3_uniform_location, m_po_double_arr_uniform_location,
2589 m_po_double_uniform_location, m_po_dvec2_arr_uniform_location, m_po_dvec2_uniform_location,
2590 m_po_dvec3_arr_uniform_location, m_po_dvec3_uniform_location, m_po_dvec4_arr_uniform_location,
2591 m_po_dvec4_uniform_location, m_po_float_arr_uniform_location, m_po_float_uniform_location,
2592 m_po_int_arr_uniform_location, m_po_int_uniform_location, m_po_ivec2_arr_uniform_location,
2593 m_po_ivec2_uniform_location, m_po_ivec3_arr_uniform_location, m_po_ivec3_uniform_location,
2594 m_po_ivec4_arr_uniform_location, m_po_ivec4_uniform_location, m_po_uint_arr_uniform_location,
2595 m_po_uint_uniform_location, m_po_uvec2_arr_uniform_location, m_po_uvec2_uniform_location,
2596 m_po_uvec3_arr_uniform_location, m_po_uvec3_uniform_location, m_po_uvec4_arr_uniform_location,
2597 m_po_uvec4_uniform_location, m_po_vec2_arr_uniform_location, m_po_vec2_uniform_location,
2598 m_po_vec3_arr_uniform_location, m_po_vec3_uniform_location, m_po_vec4_arr_uniform_location,
2599 m_po_vec4_uniform_location
2600 };
2601 const unsigned int n_uniform_locations = sizeof(uniform_locations) / sizeof(uniform_locations[0]);
2602 glw::GLint valid_uniform_location = -1;
2603
2604 for (unsigned int n_uniform_location = 0; n_uniform_location < n_uniform_locations; ++n_uniform_location)
2605 {
2606 glw::GLint uniform_location = uniform_locations[n_uniform_location];
2607
2608 if (uniform_location > valid_uniform_location)
2609 {
2610 valid_uniform_location = uniform_location;
2611 }
2612 } /* for (all uniform locations) */
2613
2614 /* Iterate through all uniform functions and make sure GL_INVALID_OPERATION error is always generated
2615 * for invalid uniform location that is != -1
2616 */
2617 const double double_data[] = {
2618 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0
2619 };
2620 const glw::GLint invalid_uniform_location = valid_uniform_location + 1;
2621
2622 for (unsigned int n_uniform_function = UNIFORM_FUNCTION_FIRST; n_uniform_function < UNIFORM_FUNCTION_COUNT;
2623 ++n_uniform_function)
2624 {
2625 _uniform_function uniform_function = (_uniform_function)n_uniform_function;
2626
2627 switch (uniform_function)
2628 {
2629 case UNIFORM_FUNCTION_1D:
2630 gl.uniform1d(invalid_uniform_location, 0.0);
2631 break;
2632 case UNIFORM_FUNCTION_2D:
2633 gl.uniform2d(invalid_uniform_location, 0.0, 1.0);
2634 break;
2635 case UNIFORM_FUNCTION_3D:
2636 gl.uniform3d(invalid_uniform_location, 0.0, 1.0, 2.0);
2637 break;
2638 case UNIFORM_FUNCTION_4D:
2639 gl.uniform4d(invalid_uniform_location, 0.0, 1.0, 2.0, 3.0);
2640 break;
2641
2642 case UNIFORM_FUNCTION_1DV:
2643 gl.uniform1dv(invalid_uniform_location, 1 /* count */, double_data);
2644 break;
2645 case UNIFORM_FUNCTION_2DV:
2646 gl.uniform2dv(invalid_uniform_location, 1 /* count */, double_data);
2647 break;
2648 case UNIFORM_FUNCTION_3DV:
2649 gl.uniform3dv(invalid_uniform_location, 1 /* count */, double_data);
2650 break;
2651 case UNIFORM_FUNCTION_4DV:
2652 gl.uniform4dv(invalid_uniform_location, 1 /* count */, double_data);
2653 break;
2654
2655 case UNIFORM_FUNCTION_MATRIX2DV:
2656 gl.uniformMatrix2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2657 break;
2658 case UNIFORM_FUNCTION_MATRIX2X3DV:
2659 gl.uniformMatrix2x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2660 break;
2661 case UNIFORM_FUNCTION_MATRIX2X4DV:
2662 gl.uniformMatrix2x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2663 break;
2664 case UNIFORM_FUNCTION_MATRIX3DV:
2665 gl.uniformMatrix3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2666 break;
2667 case UNIFORM_FUNCTION_MATRIX3X2DV:
2668 gl.uniformMatrix3x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2669 break;
2670 case UNIFORM_FUNCTION_MATRIX3X4DV:
2671 gl.uniformMatrix3x4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2672 break;
2673 case UNIFORM_FUNCTION_MATRIX4DV:
2674 gl.uniformMatrix4dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2675 break;
2676 case UNIFORM_FUNCTION_MATRIX4X2DV:
2677 gl.uniformMatrix4x2dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2678 break;
2679 case UNIFORM_FUNCTION_MATRIX4X3DV:
2680 gl.uniformMatrix4x3dv(invalid_uniform_location, 1 /* count */, GL_FALSE /* transpose */, double_data);
2681 break;
2682
2683 default:
2684 {
2685 TCU_FAIL("Unrecognized uniform function");
2686 }
2687 }
2688
2689 const glw::GLenum error_code = gl.getError();
2690
2691 if (error_code != GL_INVALID_OPERATION)
2692 {
2693 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2694 << "() did not generate an error"
2695 " when passed an invalid uniform location different from -1."
2696 << tcu::TestLog::EndMessage;
2697
2698 result = false;
2699 }
2700 } /* for (all uniform functions) */
2701
2702 return result;
2703 }
2704
2705 /** Verifies GL_INVALID_VALUE is generated if any of the glUniform*dv() or
2706 * glUniformMatrix*dv() functions is used to load a compatible uniform using an
2707 * invalid <count> argument of -1.
2708 *
2709 * @return true if the implementation was found to behave as expected, false otherwise.
2710 **/
verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()2711 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingDoubleUniformFunctionsWithNegativeCount()
2712 {
2713 const glw::GLdouble double_values[16] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0,
2714 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 };
2715 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2716 bool result = true;
2717 const _uniform_function uniform_functions[] = { UNIFORM_FUNCTION_1DV, UNIFORM_FUNCTION_2DV,
2718 UNIFORM_FUNCTION_3DV, UNIFORM_FUNCTION_4DV,
2719 UNIFORM_FUNCTION_MATRIX2DV, UNIFORM_FUNCTION_MATRIX2X3DV,
2720 UNIFORM_FUNCTION_MATRIX2X4DV, UNIFORM_FUNCTION_MATRIX3DV,
2721 UNIFORM_FUNCTION_MATRIX3X2DV, UNIFORM_FUNCTION_MATRIX3X4DV,
2722 UNIFORM_FUNCTION_MATRIX4DV, UNIFORM_FUNCTION_MATRIX4X2DV,
2723 UNIFORM_FUNCTION_MATRIX4X3DV };
2724 const unsigned int n_uniform_functions = sizeof(uniform_functions) / sizeof(uniform_functions[0]);
2725
2726 for (unsigned int n_uniform_function = 0; n_uniform_function < n_uniform_functions; ++n_uniform_function)
2727 {
2728 _uniform_function uniform_function = uniform_functions[n_uniform_function];
2729
2730 switch (uniform_function)
2731 {
2732 case UNIFORM_FUNCTION_1DV:
2733 gl.uniform1dv(m_po_double_arr_uniform_location, -1, double_values);
2734 break;
2735 case UNIFORM_FUNCTION_2DV:
2736 gl.uniform2dv(m_po_dvec2_arr_uniform_location, -1, double_values);
2737 break;
2738 case UNIFORM_FUNCTION_3DV:
2739 gl.uniform3dv(m_po_dvec3_arr_uniform_location, -1, double_values);
2740 break;
2741 case UNIFORM_FUNCTION_4DV:
2742 gl.uniform4dv(m_po_dvec4_arr_uniform_location, -1, double_values);
2743 break;
2744 case UNIFORM_FUNCTION_MATRIX2DV:
2745 gl.uniformMatrix2dv(m_po_dmat2_arr_uniform_location, -1, GL_FALSE, double_values);
2746 break;
2747 case UNIFORM_FUNCTION_MATRIX2X3DV:
2748 gl.uniformMatrix2x3dv(m_po_dmat2x3_arr_uniform_location, -1, GL_FALSE, double_values);
2749 break;
2750 case UNIFORM_FUNCTION_MATRIX2X4DV:
2751 gl.uniformMatrix2x4dv(m_po_dmat2x4_arr_uniform_location, -1, GL_FALSE, double_values);
2752 break;
2753 case UNIFORM_FUNCTION_MATRIX3DV:
2754 gl.uniformMatrix3dv(m_po_dmat3_arr_uniform_location, -1, GL_FALSE, double_values);
2755 break;
2756 case UNIFORM_FUNCTION_MATRIX3X2DV:
2757 gl.uniformMatrix3x2dv(m_po_dmat3x2_arr_uniform_location, -1, GL_FALSE, double_values);
2758 break;
2759 case UNIFORM_FUNCTION_MATRIX3X4DV:
2760 gl.uniformMatrix3x4dv(m_po_dmat3x4_arr_uniform_location, -1, GL_FALSE, double_values);
2761 break;
2762 case UNIFORM_FUNCTION_MATRIX4DV:
2763 gl.uniformMatrix4dv(m_po_dmat4_arr_uniform_location, -1, GL_FALSE, double_values);
2764 break;
2765 case UNIFORM_FUNCTION_MATRIX4X2DV:
2766 gl.uniformMatrix4x2dv(m_po_dmat4x2_arr_uniform_location, -1, GL_FALSE, double_values);
2767 break;
2768 case UNIFORM_FUNCTION_MATRIX4X3DV:
2769 gl.uniformMatrix4x3dv(m_po_dmat4x3_arr_uniform_location, -1, GL_FALSE, double_values);
2770 break;
2771
2772 default:
2773 {
2774 TCU_FAIL("Unrecognized uniform function");
2775 }
2776 } /* switch (uniform_function) */
2777
2778 /* Make sure GL_INVALID_VALUE was generated */
2779 glw::GLenum error_code = gl.getError();
2780
2781 if (error_code != GL_INVALID_VALUE)
2782 {
2783 m_testCtx.getLog() << tcu::TestLog::Message << "Function " << getUniformFunctionString(uniform_function)
2784 << "() "
2785 "was called with a negative count argument but did not generate a "
2786 "GL_INVALID_VALUE error"
2787 << tcu::TestLog::EndMessage;
2788
2789 result = false;
2790 }
2791 } /* for (all uniform functions) */
2792
2793 return result;
2794 }
2795
2796 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d(), glUniform*dv() or
2797 * glUniformMatrix*dv() functions is used to load an uniform that's incompatible with the
2798 * function (as per spec).
2799 *
2800 * @return true if the implementation was found to behave as expected, false otherwise.
2801 **/
verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()2802 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingMismatchedDoubleUniformFunctions()
2803 {
2804 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2805 glw::GLenum error_code = GL_NO_ERROR;
2806 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2807 bool result = true;
2808
2809 const glw::GLint double_uniform_locations[] = { m_po_dmat2_uniform_location, m_po_dmat2x3_uniform_location,
2810 m_po_dmat2x4_uniform_location, m_po_dmat3_uniform_location,
2811 m_po_dmat3x2_uniform_location, m_po_dmat3x4_uniform_location,
2812 m_po_dmat4_uniform_location, m_po_dmat4x2_uniform_location,
2813 m_po_dmat4x3_uniform_location, m_po_double_uniform_location,
2814 m_po_dvec2_uniform_location, m_po_dvec3_uniform_location,
2815 m_po_dvec4_uniform_location };
2816 const unsigned int n_double_uniform_locations =
2817 sizeof(double_uniform_locations) / sizeof(double_uniform_locations[0]);
2818
2819 gl.useProgram(m_po_id);
2820 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2821
2822 for (unsigned int n_uniform_location = 0; n_uniform_location < n_double_uniform_locations; ++n_uniform_location)
2823 {
2824 glw::GLint uniform_location = double_uniform_locations[n_uniform_location];
2825
2826 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
2827 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); function++)
2828 {
2829 _uniform_function e_function = static_cast<_uniform_function>(function);
2830 /* Exclude valid combinations */
2831 if (((uniform_location == m_po_dmat2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2DV)) ||
2832 ((uniform_location == m_po_dmat2x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X3DV)) ||
2833 ((uniform_location == m_po_dmat2x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX2X4DV)) ||
2834 ((uniform_location == m_po_dmat3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3DV)) ||
2835 ((uniform_location == m_po_dmat3x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X2DV)) ||
2836 ((uniform_location == m_po_dmat3x4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX3X4DV)) ||
2837 ((uniform_location == m_po_dmat4_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4DV)) ||
2838 ((uniform_location == m_po_dmat4x2_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X2DV)) ||
2839 ((uniform_location == m_po_dmat4x3_uniform_location) && (e_function == UNIFORM_FUNCTION_MATRIX4X3DV)) ||
2840 ((uniform_location == m_po_double_uniform_location) &&
2841 ((e_function == UNIFORM_FUNCTION_1D) || (e_function == UNIFORM_FUNCTION_1DV))) ||
2842 ((uniform_location == m_po_dvec2_uniform_location) &&
2843 ((e_function == UNIFORM_FUNCTION_2D) || (e_function == UNIFORM_FUNCTION_2DV))) ||
2844 ((uniform_location == m_po_dvec3_uniform_location) &&
2845 ((e_function == UNIFORM_FUNCTION_3D) || (e_function == UNIFORM_FUNCTION_3DV))) ||
2846 ((uniform_location == m_po_dvec4_uniform_location) &&
2847 ((e_function == UNIFORM_FUNCTION_4D) || (e_function == UNIFORM_FUNCTION_4DV))))
2848 {
2849 continue;
2850 }
2851
2852 switch (e_function)
2853 {
2854 case UNIFORM_FUNCTION_1D:
2855 {
2856 gl.uniform1d(uniform_location, double_data[0]);
2857
2858 break;
2859 }
2860
2861 case UNIFORM_FUNCTION_2D:
2862 {
2863 gl.uniform2d(uniform_location, double_data[0], double_data[1]);
2864
2865 break;
2866 }
2867
2868 case UNIFORM_FUNCTION_3D:
2869 {
2870 gl.uniform3d(uniform_location, double_data[0], double_data[1], double_data[2]);
2871
2872 break;
2873 }
2874
2875 case UNIFORM_FUNCTION_4D:
2876 {
2877 gl.uniform4d(uniform_location, double_data[0], double_data[1], double_data[2], double_data[3]);
2878
2879 break;
2880 }
2881
2882 case UNIFORM_FUNCTION_1DV:
2883 gl.uniform1dv(uniform_location, 1 /* count */, double_data);
2884 break;
2885 case UNIFORM_FUNCTION_2DV:
2886 gl.uniform2dv(uniform_location, 1 /* count */, double_data);
2887 break;
2888 case UNIFORM_FUNCTION_3DV:
2889 gl.uniform3dv(uniform_location, 1 /* count */, double_data);
2890 break;
2891 case UNIFORM_FUNCTION_4DV:
2892 gl.uniform4dv(uniform_location, 1 /* count */, double_data);
2893 break;
2894 case UNIFORM_FUNCTION_MATRIX2DV:
2895 gl.uniformMatrix2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2896 break;
2897 case UNIFORM_FUNCTION_MATRIX2X3DV:
2898 gl.uniformMatrix2x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2899 break;
2900 case UNIFORM_FUNCTION_MATRIX2X4DV:
2901 gl.uniformMatrix2x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2902 break;
2903 case UNIFORM_FUNCTION_MATRIX3DV:
2904 gl.uniformMatrix3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2905 break;
2906 case UNIFORM_FUNCTION_MATRIX3X2DV:
2907 gl.uniformMatrix3x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2908 break;
2909 case UNIFORM_FUNCTION_MATRIX3X4DV:
2910 gl.uniformMatrix3x4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2911 break;
2912 case UNIFORM_FUNCTION_MATRIX4DV:
2913 gl.uniformMatrix4dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2914 break;
2915 case UNIFORM_FUNCTION_MATRIX4X2DV:
2916 gl.uniformMatrix4x2dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2917 break;
2918 case UNIFORM_FUNCTION_MATRIX4X3DV:
2919 gl.uniformMatrix4x3dv(uniform_location, 1 /* count */, GL_FALSE, double_data);
2920 break;
2921
2922 default:
2923 {
2924 TCU_FAIL("Unrecognized function");
2925 }
2926 } /* switch (function) */
2927
2928 /* Make sure GL_INVALID_OPERATION error was generated */
2929 error_code = gl.getError();
2930
2931 if (error_code != GL_INVALID_OPERATION)
2932 {
2933 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid error [" << error_code
2934 << "] was generated when a mismatched "
2935 "double-precision uniform function "
2936 << getUniformFunctionString(e_function) << "() was used to configure uniform "
2937 << getUniformNameForLocation(uniform_location) << "." << tcu::TestLog::EndMessage;
2938
2939 result = false;
2940 }
2941 } /* for (all uniform functions) */
2942 } /* for (all uniform locations) */
2943
2944 return result;
2945 }
2946
2947 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
2948 * glUniform*dv() functions is used to load an uniform, size of which is incompatible
2949 * with the function.
2950 *
2951 * @return true if the implementation was found to behave as expected, false otherwise.
2952 **/
verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()2953 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingSizeMismatchedUniformFunctions()
2954 {
2955 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
2956 glw::GLenum error_code = GL_NO_ERROR;
2957 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2958 bool result = true;
2959
2960 const int data[] = {
2961 /* API function */ /* Uniform location */ /* Count (dv functions only) */
2962 (int)UNIFORM_FUNCTION_2D, m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_2DV,
2963 m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_double_uniform_location, 0,
2964 (int)UNIFORM_FUNCTION_3DV, m_po_double_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2965 m_po_double_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_double_uniform_location, 2,
2966 (int)UNIFORM_FUNCTION_1D, m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2967 m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_3D, m_po_dvec2_uniform_location, 0,
2968 (int)UNIFORM_FUNCTION_3DV, m_po_dvec2_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2969 m_po_dvec2_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec2_uniform_location, 2,
2970 (int)UNIFORM_FUNCTION_1D, m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2971 m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec3_uniform_location, 0,
2972 (int)UNIFORM_FUNCTION_2DV, m_po_dvec3_uniform_location, 2, (int)UNIFORM_FUNCTION_4D,
2973 m_po_dvec3_uniform_location, 0, (int)UNIFORM_FUNCTION_4DV, m_po_dvec3_uniform_location, 2,
2974 (int)UNIFORM_FUNCTION_1D, m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_1DV,
2975 m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_2D, m_po_dvec4_uniform_location, 0,
2976 (int)UNIFORM_FUNCTION_2DV, m_po_dvec4_uniform_location, 2, (int)UNIFORM_FUNCTION_3D,
2977 m_po_dvec4_uniform_location, 0, (int)UNIFORM_FUNCTION_3DV, m_po_dvec4_uniform_location, 2,
2978 };
2979 const unsigned int n_checks = sizeof(data) / sizeof(data[0]) / 3 /* entries per row */;
2980
2981 gl.useProgram(m_po_id);
2982 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2983
2984 for (unsigned int n_check = 0; n_check < n_checks; ++n_check)
2985 {
2986 _uniform_function function = (_uniform_function)data[n_check * 3 + 0];
2987 int uniform_location = data[n_check * 3 + 1];
2988 int uniform_count = data[n_check * 3 + 2];
2989
2990 switch (function)
2991 {
2992 case UNIFORM_FUNCTION_1D:
2993 gl.uniform1d(uniform_location, 0.0);
2994 break;
2995 case UNIFORM_FUNCTION_1DV:
2996 gl.uniform1dv(uniform_location, uniform_count, double_data);
2997 break;
2998 case UNIFORM_FUNCTION_2D:
2999 gl.uniform2d(uniform_location, 0.0, 1.0);
3000 break;
3001 case UNIFORM_FUNCTION_2DV:
3002 gl.uniform2dv(uniform_location, uniform_count, double_data);
3003 break;
3004 case UNIFORM_FUNCTION_3D:
3005 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3006 break;
3007 case UNIFORM_FUNCTION_3DV:
3008 gl.uniform3dv(uniform_location, uniform_count, double_data);
3009 break;
3010 case UNIFORM_FUNCTION_4D:
3011 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3012 break;
3013 case UNIFORM_FUNCTION_4DV:
3014 gl.uniform4dv(uniform_location, uniform_count, double_data);
3015 break;
3016
3017 default:
3018 {
3019 DE_ASSERT(false);
3020 }
3021 } /* switch (function) */
3022
3023 error_code = gl.getError();
3024 if (error_code != GL_INVALID_OPERATION)
3025 {
3026 m_testCtx.getLog() << tcu::TestLog::Message << getUniformFunctionString(function)
3027 << "() function did not generate GL_INVALID_OPERATION error when called for"
3028 " a uniform of incompatible size. (check index: "
3029 << n_check << ")" << tcu::TestLog::EndMessage;
3030
3031 result = false;
3032 }
3033 } /* for (all checks) */
3034
3035 return result;
3036 }
3037
3038 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3039 * glUniform*dv() functions is used to load an uniform, type of which is incompatible
3040 * with the function.
3041 *
3042 * @return true if the implementation was found to behave as expected, false otherwise.
3043 **/
verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()3044 bool GPUShaderFP64Test1::verifyErrorGenerationWhenCallingTypeMismatchedUniformFunctions()
3045 {
3046 const double double_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
3047 glw::GLenum error_code = GL_NO_ERROR;
3048 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3049 bool result = true;
3050
3051 const glw::GLint nondouble_uniform_locations[] = { m_po_bool_uniform_location, m_po_bvec2_uniform_location,
3052 m_po_bvec3_uniform_location, m_po_bvec4_uniform_location,
3053 m_po_float_uniform_location, m_po_int_uniform_location,
3054 m_po_ivec2_uniform_location, m_po_ivec3_uniform_location,
3055 m_po_ivec4_uniform_location, m_po_uint_uniform_location,
3056 m_po_uvec2_uniform_location, m_po_uvec3_uniform_location,
3057 m_po_uvec4_uniform_location, m_po_vec2_uniform_location,
3058 m_po_vec3_uniform_location, m_po_vec4_uniform_location };
3059 const unsigned int n_nondouble_uniform_locations =
3060 sizeof(nondouble_uniform_locations) / sizeof(nondouble_uniform_locations[0]);
3061
3062 gl.useProgram(m_po_id);
3063 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3064
3065 for (unsigned int n_uniform_location = 0; n_uniform_location < n_nondouble_uniform_locations; ++n_uniform_location)
3066 {
3067 glw::GLint uniform_location = nondouble_uniform_locations[n_uniform_location];
3068
3069 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST);
3070 function < static_cast<int>(UNIFORM_FUNCTION_COUNT); ++function)
3071 {
3072 switch (static_cast<_uniform_function>(function))
3073 {
3074 case UNIFORM_FUNCTION_1D:
3075 gl.uniform1d(uniform_location, 0.0);
3076 break;
3077 case UNIFORM_FUNCTION_1DV:
3078 gl.uniform1dv(uniform_location, 1, double_data);
3079 break;
3080 case UNIFORM_FUNCTION_2D:
3081 gl.uniform2d(uniform_location, 0.0, 1.0);
3082 break;
3083 case UNIFORM_FUNCTION_2DV:
3084 gl.uniform2dv(uniform_location, 1, double_data);
3085 break;
3086 case UNIFORM_FUNCTION_3D:
3087 gl.uniform3d(uniform_location, 0.0, 1.0, 2.0);
3088 break;
3089 case UNIFORM_FUNCTION_3DV:
3090 gl.uniform3dv(uniform_location, 1, double_data);
3091 break;
3092 case UNIFORM_FUNCTION_4D:
3093 gl.uniform4d(uniform_location, 0.0, 1.0, 2.0, 3.0);
3094 break;
3095 case UNIFORM_FUNCTION_4DV:
3096 gl.uniform4dv(uniform_location, 1, double_data);
3097 break;
3098
3099 case UNIFORM_FUNCTION_MATRIX2DV:
3100 gl.uniformMatrix2dv(uniform_location, 1, GL_FALSE, double_data);
3101 break;
3102 case UNIFORM_FUNCTION_MATRIX2X3DV:
3103 gl.uniformMatrix2x3dv(uniform_location, 1, GL_FALSE, double_data);
3104 break;
3105 case UNIFORM_FUNCTION_MATRIX2X4DV:
3106 gl.uniformMatrix2x4dv(uniform_location, 1, GL_FALSE, double_data);
3107 break;
3108 case UNIFORM_FUNCTION_MATRIX3DV:
3109 gl.uniformMatrix3dv(uniform_location, 1, GL_FALSE, double_data);
3110 break;
3111 case UNIFORM_FUNCTION_MATRIX3X2DV:
3112 gl.uniformMatrix3x2dv(uniform_location, 1, GL_FALSE, double_data);
3113 break;
3114 case UNIFORM_FUNCTION_MATRIX3X4DV:
3115 gl.uniformMatrix3x4dv(uniform_location, 1, GL_FALSE, double_data);
3116 break;
3117 case UNIFORM_FUNCTION_MATRIX4DV:
3118 gl.uniformMatrix4dv(uniform_location, 1, GL_FALSE, double_data);
3119 break;
3120 case UNIFORM_FUNCTION_MATRIX4X2DV:
3121 gl.uniformMatrix4x2dv(uniform_location, 1, GL_FALSE, double_data);
3122 break;
3123 case UNIFORM_FUNCTION_MATRIX4X3DV:
3124 gl.uniformMatrix4x3dv(uniform_location, 1, GL_FALSE, double_data);
3125 break;
3126
3127 default:
3128 {
3129 DE_ASSERT(false);
3130 }
3131 } /* switch (function) */
3132
3133 error_code = gl.getError();
3134 if (error_code != GL_INVALID_OPERATION)
3135 {
3136 m_testCtx.getLog() << tcu::TestLog::Message
3137 << getUniformFunctionString(static_cast<_uniform_function>(function))
3138 << "() function did not generate GL_INVALID_OPERATION error when called for"
3139 " a uniform of incompatible type."
3140 << tcu::TestLog::EndMessage;
3141
3142 result = false;
3143 }
3144 }
3145 } /* for (all checks) */
3146
3147 return result;
3148 }
3149
3150 /** Verifies GL_INVALID_OPERATION is generated if any of the glUniform*d() or
3151 * glUniform*dv() functions are called without a bound program object.
3152 *
3153 * @return true if the implementation was found to behave as expected, false otherwise.
3154 **/
verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()3155 bool GPUShaderFP64Test1::verifyErrorGenerationWhenUniformFunctionsCalledWithoutActivePO()
3156 {
3157 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3158 bool result = true;
3159
3160 for (int function = static_cast<int>(UNIFORM_FUNCTION_FIRST); function < static_cast<int>(UNIFORM_FUNCTION_COUNT);
3161 function++)
3162 {
3163 const double data[] = { 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0 };
3164
3165 switch (static_cast<_uniform_function>(function))
3166 {
3167 case UNIFORM_FUNCTION_1D:
3168 gl.uniform1d(m_po_double_uniform_location, 0.0);
3169 break;
3170 case UNIFORM_FUNCTION_1DV:
3171 gl.uniform1dv(m_po_double_uniform_location, 1, data);
3172 break;
3173 case UNIFORM_FUNCTION_2D:
3174 gl.uniform2d(m_po_dvec2_uniform_location, 0.0, 1.0);
3175 break;
3176 case UNIFORM_FUNCTION_2DV:
3177 gl.uniform2dv(m_po_dvec2_uniform_location, 1, data);
3178 break;
3179 case UNIFORM_FUNCTION_3D:
3180 gl.uniform3d(m_po_dvec3_uniform_location, 0.0, 1.0, 2.0);
3181 break;
3182 case UNIFORM_FUNCTION_3DV:
3183 gl.uniform3dv(m_po_dvec3_uniform_location, 1, data);
3184 break;
3185 case UNIFORM_FUNCTION_4D:
3186 gl.uniform4d(m_po_dvec4_uniform_location, 0.0, 1.0, 2.0, 3.0);
3187 break;
3188 case UNIFORM_FUNCTION_4DV:
3189 gl.uniform4dv(m_po_dvec4_uniform_location, 1, data);
3190 break;
3191
3192 case UNIFORM_FUNCTION_MATRIX2DV:
3193 gl.uniformMatrix2dv(m_po_dmat2_uniform_location, 1, GL_FALSE /* transpose */, data);
3194 break;
3195 case UNIFORM_FUNCTION_MATRIX2X3DV:
3196 gl.uniformMatrix2x3dv(m_po_dmat2x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3197 break;
3198 case UNIFORM_FUNCTION_MATRIX2X4DV:
3199 gl.uniformMatrix2x4dv(m_po_dmat2x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3200 break;
3201 case UNIFORM_FUNCTION_MATRIX3DV:
3202 gl.uniformMatrix3dv(m_po_dmat3_uniform_location, 1, GL_FALSE /* transpose */, data);
3203 break;
3204 case UNIFORM_FUNCTION_MATRIX3X2DV:
3205 gl.uniformMatrix3x2dv(m_po_dmat3x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3206 break;
3207 case UNIFORM_FUNCTION_MATRIX3X4DV:
3208 gl.uniformMatrix3x4dv(m_po_dmat3x4_uniform_location, 1, GL_FALSE /* transpose */, data);
3209 break;
3210 case UNIFORM_FUNCTION_MATRIX4DV:
3211 gl.uniformMatrix4dv(m_po_dmat4_uniform_location, 1, GL_FALSE /* transpose */, data);
3212 break;
3213 case UNIFORM_FUNCTION_MATRIX4X2DV:
3214 gl.uniformMatrix4x2dv(m_po_dmat4x2_uniform_location, 1, GL_FALSE /* transpose */, data);
3215 break;
3216 case UNIFORM_FUNCTION_MATRIX4X3DV:
3217 gl.uniformMatrix4x3dv(m_po_dmat4x3_uniform_location, 1, GL_FALSE /* transpose */, data);
3218 break;
3219
3220 default:
3221 {
3222 TCU_FAIL("Unrecognized uniform function");
3223 }
3224 } /* switch (func) */
3225
3226 /* Query the error code */
3227 glw::GLenum error_code = gl.getError();
3228
3229 if (error_code != GL_INVALID_OPERATION)
3230 {
3231 m_testCtx.getLog() << tcu::TestLog::Message << "Implementation did not return GL_INVALID_OPERATION when "
3232 << getUniformFunctionString(static_cast<_uniform_function>(function))
3233 << "() was called without an active program object" << tcu::TestLog::EndMessage;
3234
3235 result = false;
3236 }
3237 } /* for (all uniform functions) */
3238
3239 return result;
3240 }
3241
3242 /* Defeinitions of static const symbols declared in GPUShaderFP64Test2 */
3243 const glw::GLuint GPUShaderFP64Test2::m_n_captured_results = 1024;
3244 const glw::GLint GPUShaderFP64Test2::m_result_failure = 2;
3245 const glw::GLint GPUShaderFP64Test2::m_result_success = 1;
3246 const glw::GLuint GPUShaderFP64Test2::m_texture_width = 32;
3247 const glw::GLuint GPUShaderFP64Test2::m_texture_height = m_n_captured_results / m_texture_width;
3248 const glw::GLuint GPUShaderFP64Test2::m_transform_feedback_buffer_size =
3249 m_n_captured_results * sizeof(captured_varying_type);
3250 const glw::GLchar* GPUShaderFP64Test2::m_uniform_block_name = "UniformBlock";
3251 const glw::GLenum GPUShaderFP64Test2::ARB_MAX_COMPUTE_UNIFORM_COMPONENTS = 0x8263;
3252
3253 /** Constructor
3254 *
3255 * @param context Test context
3256 **/
GPUShaderFP64Test2(deqp::Context & context)3257 GPUShaderFP64Test2::GPUShaderFP64Test2(deqp::Context& context)
3258 : TestCase(context, "max_uniform_components",
3259 "Verifies that maximum allowed uniform components can be used as double-precision float types")
3260 , m_pDispatchCompute(0)
3261 , m_framebuffer_id(0)
3262 , m_texture_id(0)
3263 , m_transform_feedback_buffer_id(0)
3264 , m_uniform_buffer_id(0)
3265 , m_vertex_array_object_id(0)
3266 {
3267 /* Nothing to be done */
3268 }
3269
3270 /** Deinitialize test
3271 *
3272 **/
deinit()3273 void GPUShaderFP64Test2::deinit()
3274 {
3275 /* GL entry points */
3276 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3277
3278 /* Clean frambuffer */
3279 if (0 != m_framebuffer_id)
3280 {
3281 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
3282 gl.deleteFramebuffers(1, &m_framebuffer_id);
3283 m_framebuffer_id = 0;
3284 }
3285
3286 /* Clean texture */
3287 if (0 != m_texture_id)
3288 {
3289 gl.bindTexture(GL_TEXTURE_2D, 0);
3290 gl.bindImageTexture(0 /* unit */, 0 /* texture */, 0 /* level */, GL_FALSE /* layered */, 0 /* layer */,
3291 GL_READ_ONLY, GL_RGBA8);
3292 gl.deleteTextures(1, &m_texture_id);
3293 m_texture_id = 0;
3294 }
3295
3296 /* Clean buffers */
3297 if (0 != m_transform_feedback_buffer_id)
3298 {
3299 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
3300 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
3301 m_transform_feedback_buffer_id = 0;
3302 }
3303
3304 if (0 != m_uniform_buffer_id)
3305 {
3306 gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
3307 gl.deleteBuffers(1, &m_uniform_buffer_id);
3308 m_uniform_buffer_id = 0;
3309 }
3310
3311 /* Clean VAO */
3312 if (0 != m_vertex_array_object_id)
3313 {
3314 gl.bindVertexArray(0);
3315 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
3316 m_vertex_array_object_id = 0;
3317 }
3318 }
3319
3320 /** Execute test
3321 *
3322 * @return tcu::TestNode::STOP
3323 **/
iterate()3324 tcu::TestNode::IterateResult GPUShaderFP64Test2::iterate()
3325 {
3326 bool result = true;
3327
3328 /* Check if extension is supported */
3329 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
3330 {
3331 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
3332 }
3333
3334 /* Initialize test */
3335 testInit();
3336
3337 prepareShaderStages();
3338 prepareUniformTypes();
3339
3340 /* For all shaders and uniform type combinations */
3341 for (std::vector<shaderStage>::const_iterator shader_stage = m_shader_stages.begin();
3342 m_shader_stages.end() != shader_stage; ++shader_stage)
3343 {
3344 for (std::vector<uniformTypeDetails>::const_iterator uniform_type = m_uniform_types.begin();
3345 m_uniform_types.end() != uniform_type; ++uniform_type)
3346 {
3347 /* Execute test */
3348 if (false == test(*shader_stage, *uniform_type))
3349 {
3350 result = false;
3351 }
3352 }
3353 }
3354
3355 /* Set result */
3356 if (true == result)
3357 {
3358 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
3359 }
3360 else
3361 {
3362 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3363 }
3364
3365 /* Done */
3366 return tcu::TestNode::STOP;
3367 }
3368
3369 /** Constructor
3370 *
3371 * @param n_columns Number of columns
3372 * @param n_rows Number of rows
3373 **/
uniformTypeDetails(glw::GLuint n_columns,glw::GLuint n_rows)3374 GPUShaderFP64Test2::uniformTypeDetails::uniformTypeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
3375 : m_n_columns(n_columns), m_n_rows(n_rows)
3376 {
3377 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
3378
3379 m_type_name = Utils::getVariableTypeString(type);
3380 m_type = Utils::getGLDataTypeOfVariableType(type);
3381 }
3382
3383 /** Get primitive type captured with transform feedback
3384 *
3385 * @param shader_stage Tested shader stage id
3386 *
3387 * @return Primitive type
3388 **/
getCapturedPrimitiveType(shaderStage shader_stage) const3389 glw::GLenum GPUShaderFP64Test2::getCapturedPrimitiveType(shaderStage shader_stage) const
3390 {
3391 switch (shader_stage)
3392 {
3393 case GEOMETRY_SHADER:
3394 case TESS_CTRL_SHADER:
3395 case TESS_EVAL_SHADER:
3396 case VERTEX_SHADER:
3397 return GL_POINTS;
3398
3399 default:
3400 return GL_NONE;
3401 }
3402 }
3403
3404 /** Get primitive type drawn with DrawArrays
3405 *
3406 * @param shader_stage Tested shader stage id
3407 *
3408 * @return Primitive type
3409 **/
getDrawPrimitiveType(shaderStage shader_stage) const3410 glw::GLenum GPUShaderFP64Test2::getDrawPrimitiveType(shaderStage shader_stage) const
3411 {
3412 switch (shader_stage)
3413 {
3414 case FRAGMENT_SHADER:
3415 return GL_TRIANGLE_FAN;
3416
3417 case GEOMETRY_SHADER:
3418 case VERTEX_SHADER:
3419 return GL_POINTS;
3420
3421 case TESS_CTRL_SHADER:
3422 case TESS_EVAL_SHADER:
3423 return GL_PATCHES;
3424
3425 default:
3426 return GL_NONE;
3427 }
3428 }
3429
3430 /** Get maximum allowed number of uniform components
3431 *
3432 * @param shader_stage Tested shader stage id
3433 *
3434 * @return Maxmimum uniform components
3435 **/
getMaxUniformComponents(shaderStage shader_stage) const3436 glw::GLuint GPUShaderFP64Test2::getMaxUniformComponents(shaderStage shader_stage) const
3437 {
3438 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3439 glw::GLint max_uniform_components = 0;
3440 glw::GLenum pname = 0;
3441
3442 switch (shader_stage)
3443 {
3444 case COMPUTE_SHADER:
3445 pname = ARB_MAX_COMPUTE_UNIFORM_COMPONENTS;
3446 break;
3447 case FRAGMENT_SHADER:
3448 pname = GL_MAX_FRAGMENT_UNIFORM_COMPONENTS;
3449 break;
3450 case GEOMETRY_SHADER:
3451 pname = GL_MAX_GEOMETRY_UNIFORM_COMPONENTS;
3452 break;
3453 case TESS_CTRL_SHADER:
3454 pname = GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS;
3455 break;
3456 case TESS_EVAL_SHADER:
3457 pname = GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS;
3458 break;
3459 case VERTEX_SHADER:
3460 pname = GL_MAX_VERTEX_UNIFORM_COMPONENTS;
3461 break;
3462 }
3463
3464 gl.getIntegerv(pname, &max_uniform_components);
3465 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3466
3467 return max_uniform_components;
3468 }
3469
3470 /** Get maximum size allowed for an uniform block
3471 *
3472 * @return Maxmimum uniform block size
3473 **/
getMaxUniformBlockSize() const3474 glw::GLuint GPUShaderFP64Test2::getMaxUniformBlockSize() const
3475 {
3476 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3477 glw::GLint max_uniform_block_size = 0;
3478
3479 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_uniform_block_size);
3480 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
3481
3482 return max_uniform_block_size;
3483 }
3484
3485 /** Get number of components required to store single uniform of given type
3486 *
3487 * @param uniform_type Tested uniform type
3488 *
3489 * @return Number of components
3490 **/
getRequiredComponentsNumber(const uniformTypeDetails & uniform_type) const3491 glw::GLuint GPUShaderFP64Test2::getRequiredComponentsNumber(const uniformTypeDetails& uniform_type) const
3492 {
3493 static const glw::GLuint type_size = 2; /* double takes 2 N */
3494 const glw::GLuint column_length = uniform_type.m_n_rows;
3495
3496 if (1 == uniform_type.m_n_columns)
3497 {
3498 return type_size * column_length;
3499 }
3500 else
3501 {
3502 const glw::GLuint alignment = type_size * ((3 == column_length) ? 4 : column_length);
3503
3504 return alignment * uniform_type.m_n_columns;
3505 }
3506 }
3507
3508 /** Get size used for each member of a uniform array of a given type in a std140 column-major layout
3509 *
3510 * @param uniform_type Tested uniform type
3511 *
3512 * @return Size of a single member
3513 **/
getUniformTypeMemberSize(const uniformTypeDetails & uniform_type) const3514 glw::GLuint GPUShaderFP64Test2::getUniformTypeMemberSize(const uniformTypeDetails& uniform_type) const
3515 {
3516 static const glw::GLuint vec4_size = 4 * Utils::getBaseVariableTypeComponentSize(Utils::VARIABLE_TYPE_FLOAT);
3517 const glw::GLuint column_length = uniform_type.m_n_rows;
3518
3519 /** Size for a layout(std140, column_major) uniform_type uniform[] **/
3520 return vec4_size * ((column_length + 1) / 2) * uniform_type.m_n_columns;
3521 }
3522
3523 /** Get the maximum amount of uniforms to be used in a shader stage for a given type
3524 *
3525 * @param shader_stage Tested shader stage id
3526 * @param uniform_type Tested uniform type
3527 *
3528 * @return Number of components
3529 **/
getAmountUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const3530 glw::GLuint GPUShaderFP64Test2::getAmountUniforms(shaderStage shader_stage,
3531 const uniformTypeDetails& uniform_type) const
3532 {
3533 const glw::GLuint max_uniform_components = getMaxUniformComponents(shader_stage);
3534 const glw::GLuint required_components = getRequiredComponentsNumber(uniform_type);
3535 const glw::GLuint n_uniforms = max_uniform_components / required_components;
3536 const glw::GLuint max_uniform_block_size = getMaxUniformBlockSize();
3537 const glw::GLuint uniform_type_member_size = getUniformTypeMemberSize(uniform_type);
3538 const glw::GLuint max_uniforms = max_uniform_block_size / uniform_type_member_size;
3539
3540 return max_uniforms < n_uniforms ? max_uniforms : n_uniforms;
3541 }
3542
3543 /** Get name of shader stage
3544 *
3545 * @param shader_stage Tested shader stage id
3546 *
3547 * @return Name
3548 **/
getShaderStageName(shaderStage shader_stage) const3549 const glw::GLchar* GPUShaderFP64Test2::getShaderStageName(shaderStage shader_stage) const
3550 {
3551 switch (shader_stage)
3552 {
3553 case COMPUTE_SHADER:
3554 return "compute shader";
3555 case FRAGMENT_SHADER:
3556 return "fragment shader";
3557 case GEOMETRY_SHADER:
3558 return "geometry shader";
3559 case TESS_CTRL_SHADER:
3560 return "tesselation control shader";
3561 case TESS_EVAL_SHADER:
3562 return "tesselation evaluation shader";
3563 case VERTEX_SHADER:
3564 return "vertex shader";
3565 }
3566
3567 return 0;
3568 }
3569
3570 /** Inspect program to get: buffer_size, offset, strides and block index
3571 *
3572 * @param program_id Program id
3573 * @param out_buffer_size Size of uniform buffer
3574 * @param out_uniform_details Uniform offset and strides
3575 * @param uniform_block_index Uniform block index
3576 **/
inspectProgram(glw::GLuint program_id,glw::GLint n_uniforms,const uniformTypeDetails & uniform_type,glw::GLint & out_buffer_size,uniformDetails & out_uniform_details,glw::GLuint & uniform_block_index) const3577 void GPUShaderFP64Test2::inspectProgram(glw::GLuint program_id, glw::GLint n_uniforms,
3578 const uniformTypeDetails& uniform_type, glw::GLint& out_buffer_size,
3579 uniformDetails& out_uniform_details, glw::GLuint& uniform_block_index) const
3580 {
3581 glw::GLint array_stride = 0;
3582 std::vector<glw::GLchar> extracted_uniform_name;
3583 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3584 glw::GLuint index = 0;
3585 glw::GLint matrix_stride = 0;
3586 glw::GLint offset = 0;
3587 glw::GLsizei size = 0;
3588 glw::GLenum type = 0;
3589 const glw::GLchar* uniform_name = 0;
3590 std::string uniform_name_str;
3591 std::stringstream uniform_name_stream;
3592
3593 /* Get index of uniform block */
3594 uniform_block_index = gl.getUniformBlockIndex(program_id, m_uniform_block_name);
3595 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
3596
3597 if (GL_INVALID_INDEX == uniform_block_index)
3598 {
3599 TCU_FAIL("Unifom block is inactive");
3600 }
3601
3602 /* Get size of uniform block */
3603 gl.getActiveUniformBlockiv(program_id, uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &out_buffer_size);
3604 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
3605
3606 if (0 == out_buffer_size)
3607 {
3608 TCU_FAIL("Unifom block size is 0");
3609 }
3610
3611 /* Prepare uniform name */
3612 uniform_name_stream << "uniform_array";
3613
3614 uniform_name_str = uniform_name_stream.str();
3615 uniform_name = uniform_name_str.c_str();
3616
3617 /* Get index of uniform */
3618 gl.getUniformIndices(program_id, 1 /* count */, &uniform_name, &index);
3619 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
3620
3621 if (GL_INVALID_INDEX == index)
3622 {
3623 TCU_FAIL("Unifom is inactive");
3624 }
3625
3626 /* Verify getActiveUniform results */
3627 extracted_uniform_name.resize(uniform_name_str.length() * 2);
3628
3629 gl.getActiveUniform(program_id, index, (glw::GLsizei)(uniform_name_str.length() * 2) /* bufSize */, 0, &size, &type,
3630 &extracted_uniform_name[0]);
3631 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniform");
3632
3633 if ((n_uniforms != size) || (uniform_type.m_type != type))
3634 {
3635 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid GetActiveUniform results."
3636 << " Size: " << size << " expected: " << n_uniforms << ". Type: " << type
3637 << " expected: " << uniform_type.m_type
3638 << ". Name: " << &extracted_uniform_name[0] << tcu::TestLog::EndMessage;
3639
3640 TCU_FAIL("Invalid GetActiveUniform results");
3641 }
3642
3643 /* Get offset of uniform */
3644 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
3645 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3646
3647 if (-1 == offset)
3648 {
3649 TCU_FAIL("Unifom has invalid offset");
3650 }
3651
3652 out_uniform_details.m_offset = offset;
3653
3654 /* Get matrix stride of uniform */
3655 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
3656 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3657
3658 if (-1 == matrix_stride)
3659 {
3660 TCU_FAIL("Unifom has invalid matrix stride");
3661 }
3662
3663 out_uniform_details.m_matrix_stride = matrix_stride;
3664
3665 /* Get array stride of uniform */
3666 gl.getActiveUniformsiv(program_id, 1 /* count */, &index, GL_UNIFORM_ARRAY_STRIDE, &array_stride);
3667 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
3668
3669 if (-1 == matrix_stride)
3670 {
3671 TCU_FAIL("Unifom has invalid matrix stride");
3672 }
3673
3674 out_uniform_details.m_array_stride = array_stride;
3675 }
3676
3677 /** Prepare source code for "boilerplate" shaders
3678 *
3679 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3680 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3681 * @param out_source_code Source code
3682 **/
prepareBoilerplateShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3683 void GPUShaderFP64Test2::prepareBoilerplateShader(const glw::GLchar* stage_specific_layout,
3684 const glw::GLchar* stage_specific_main_body,
3685 std::string& out_source_code) const
3686 {
3687 /* Shader template */
3688 static const glw::GLchar* boilerplate_shader_template_code = "#version 400 core\n"
3689 "\n"
3690 "precision highp float;\n"
3691 "\n"
3692 "STAGE_SPECIFIC_LAYOUT"
3693 "void main()\n"
3694 "{\n"
3695 "STAGE_SPECIFIC_MAIN_BODY"
3696 "}\n"
3697 "\n";
3698
3699 std::string string = boilerplate_shader_template_code;
3700
3701 /* Tokens */
3702 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
3703 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
3704
3705 size_t search_position = 0;
3706
3707 /* Replace tokens */
3708 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
3709 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
3710
3711 /* Store resuls */
3712 out_source_code = string;
3713 }
3714
3715 /** Prepare program for given combination of shader stage and uniform type
3716 *
3717 * @param shader_stage Shader stage
3718 * @param uniform_type Uniform type
3719 * @param out_program_info Instance of programInfo
3720 **/
prepareProgram(shaderStage shader_stage,const uniformTypeDetails & uniform_type,Utils::programInfo & out_program_info) const3721 void GPUShaderFP64Test2::prepareProgram(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
3722 Utils::programInfo& out_program_info) const
3723 {
3724 /* Stage specific layouts */
3725 static const glw::GLchar* geometry_shader_layout_code = "layout(points) in;\n"
3726 "layout(points, max_vertices = 1) out;\n"
3727 "\n";
3728
3729 static const glw::GLchar* tess_ctrl_shader_layout_code = "layout(vertices = 1) out;\n"
3730 "\n";
3731
3732 static const glw::GLchar* tess_eval_shader_layout_code = "layout(isolines, point_mode) in;\n"
3733 "\n";
3734
3735 /* Stage specific main body */
3736 static const glw::GLchar* boilerplate_fragment_shader_body_code = " discard;\n";
3737
3738 static const glw::GLchar* boilerplate_tess_ctrl_shader_body_code = " gl_TessLevelOuter[0] = 1.0;\n"
3739 " gl_TessLevelOuter[1] = 1.0;\n"
3740 " gl_TessLevelOuter[2] = 1.0;\n"
3741 " gl_TessLevelOuter[3] = 1.0;\n"
3742 " gl_TessLevelInner[0] = 1.0;\n"
3743 " gl_TessLevelInner[1] = 1.0;\n";
3744
3745 static const glw::GLchar* boilerplate_vertex_shader_body_code = " gl_Position = vec4(1, 0, 0, 1);\n";
3746
3747 static const glw::GLchar* corner_vertex_shader_body_code = " if (0 == gl_VertexID)\n"
3748 " {\n"
3749 " gl_Position = vec4(-1, -1, 0, 1);\n"
3750 " }\n"
3751 " else if (1 == gl_VertexID)\n"
3752 " {\n"
3753 " gl_Position = vec4(-1, 1, 0, 1);\n"
3754 " }\n"
3755 " else if (2 == gl_VertexID)\n"
3756 " {\n"
3757 " gl_Position = vec4(1, 1, 0, 1);\n"
3758 " }\n"
3759 " else if (3 == gl_VertexID)\n"
3760 " {\n"
3761 " gl_Position = vec4(1, -1, 0, 1);\n"
3762 " }\n";
3763
3764 static const glw::GLchar* passthrough_tess_eval_shader_body_code = " result = tcs_tes_result[0];\n";
3765
3766 static const glw::GLchar* test_shader_body_code = "\n result = verification_result;\n";
3767
3768 static const glw::GLchar* test_geometry_shader_body_code = "\n result = verification_result;\n"
3769 "\n"
3770 " EmitVertex();\n"
3771 " EndPrimitive();\n";
3772
3773 static const glw::GLchar* test_tess_ctrl_shader_body_code =
3774 "\n tcs_tes_result[gl_InvocationID] = verification_result;\n"
3775 "\n"
3776 " gl_TessLevelOuter[0] = 1.0;\n"
3777 " gl_TessLevelOuter[1] = 1.0;\n"
3778 " gl_TessLevelOuter[2] = 1.0;\n"
3779 " gl_TessLevelOuter[3] = 1.0;\n"
3780 " gl_TessLevelInner[0] = 1.0;\n"
3781 " gl_TessLevelInner[1] = 1.0;\n";
3782
3783 /* In variables */
3784 static const glw::GLchar* test_tess_ctrl_shader_in_variable = "in int tcs_tes_result[];\n";
3785
3786 /* Out variables */
3787 static const glw::GLchar* test_fragment_shader_out_variable = "layout(location = 0) out int result;\n";
3788
3789 static const glw::GLchar* test_tess_ctrl_shader_out_variable = "out int tcs_tes_result[];\n";
3790
3791 static const glw::GLchar* test_shader_out_variable = "out int result;\n";
3792
3793 /* Varying name */
3794 static const glw::GLchar* varying_name = "result";
3795 glw::GLuint n_varyings = 1;
3796
3797 /* Storage for ready shaders */
3798 std::string compute_shader_code;
3799 std::string fragment_shader_code;
3800 std::string geometry_shader_code;
3801 std::string tess_ctrl_shader_code;
3802 std::string tess_eval_shader_code;
3803 std::string vertex_shader_code;
3804
3805 /* Storage for uniform definition and verification code */
3806 std::string uniform_definitions;
3807 std::string uniform_verification;
3808
3809 /* Get uniform definition and verification code */
3810 prepareUniformDefinitions(shader_stage, uniform_type, uniform_definitions);
3811 prepareUniformVerification(shader_stage, uniform_type, uniform_verification);
3812
3813 /* Prepare vertex shader */
3814 switch (shader_stage)
3815 {
3816 case FRAGMENT_SHADER:
3817
3818 prepareBoilerplateShader("", corner_vertex_shader_body_code, vertex_shader_code);
3819
3820 break;
3821
3822 case GEOMETRY_SHADER:
3823 case TESS_CTRL_SHADER:
3824 case TESS_EVAL_SHADER:
3825
3826 prepareBoilerplateShader("", boilerplate_vertex_shader_body_code, vertex_shader_code);
3827
3828 break;
3829
3830 case VERTEX_SHADER:
3831
3832 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3833 test_shader_out_variable /* out var */, uniform_verification.c_str() /* verification */,
3834 test_shader_body_code /* body */, vertex_shader_code);
3835
3836 break;
3837
3838 default:
3839 break;
3840 }
3841
3842 /* Prepare fragment shader */
3843 switch (shader_stage)
3844 {
3845 case FRAGMENT_SHADER:
3846
3847 prepareTestShader("" /* layout */, uniform_definitions.c_str() /* uniforms */, "" /* in var */,
3848 test_fragment_shader_out_variable /* out var */,
3849 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3850 fragment_shader_code);
3851
3852 break;
3853
3854 case GEOMETRY_SHADER:
3855 case TESS_CTRL_SHADER:
3856 case TESS_EVAL_SHADER:
3857 case VERTEX_SHADER:
3858
3859 prepareBoilerplateShader("" /* layout */, boilerplate_fragment_shader_body_code /* body */,
3860 fragment_shader_code);
3861
3862 break;
3863
3864 default:
3865 break;
3866 }
3867
3868 /* Prepare compute, tess_ctrl, tess_eval, geometry shaders */
3869 switch (shader_stage)
3870 {
3871 case COMPUTE_SHADER:
3872
3873 prepareTestComputeShader(uniform_definitions.c_str(), uniform_verification.c_str(), compute_shader_code);
3874
3875 break;
3876
3877 case GEOMETRY_SHADER:
3878
3879 prepareTestShader(geometry_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3880 "" /* in var */, test_shader_out_variable /* out var */,
3881 uniform_verification.c_str() /* verification */, test_geometry_shader_body_code /* body */,
3882 geometry_shader_code);
3883
3884 break;
3885
3886 case TESS_CTRL_SHADER:
3887
3888 prepareTestShader(tess_ctrl_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3889 "" /* in var */, test_tess_ctrl_shader_out_variable /* out var */,
3890 uniform_verification.c_str() /* verification */, test_tess_ctrl_shader_body_code /* body */,
3891 tess_ctrl_shader_code);
3892
3893 prepareTestShader(tess_eval_shader_layout_code /* layout */, "" /* uniforms */,
3894 test_tess_ctrl_shader_in_variable /* in var */, test_shader_out_variable /* out var */,
3895 "" /* verification */, passthrough_tess_eval_shader_body_code /* body */,
3896 tess_eval_shader_code);
3897
3898 break;
3899
3900 case TESS_EVAL_SHADER:
3901
3902 prepareBoilerplateShader(tess_ctrl_shader_layout_code /* layout */,
3903 boilerplate_tess_ctrl_shader_body_code /* body */, tess_ctrl_shader_code);
3904
3905 prepareTestShader(tess_eval_shader_layout_code /* layout */, uniform_definitions.c_str() /* uniforms */,
3906 "" /* in var */, test_shader_out_variable /* out var */,
3907 uniform_verification.c_str() /* verification */, test_shader_body_code /* body */,
3908 tess_eval_shader_code);
3909
3910 break;
3911
3912 default:
3913 break;
3914 }
3915
3916 /* Select shaders that will be used by program */
3917 const glw::GLchar* cs_c_str = 0;
3918 const glw::GLchar* fs_c_str = 0;
3919 const glw::GLchar* gs_c_str = 0;
3920 const glw::GLchar* tcs_c_str = 0;
3921 const glw::GLchar* tes_c_str = 0;
3922 const glw::GLchar* vs_c_str = 0;
3923
3924 if (false == compute_shader_code.empty())
3925 {
3926 cs_c_str = compute_shader_code.c_str();
3927 }
3928
3929 if (false == fragment_shader_code.empty())
3930 {
3931 fs_c_str = fragment_shader_code.c_str();
3932 }
3933
3934 if (false == geometry_shader_code.empty())
3935 {
3936 gs_c_str = geometry_shader_code.c_str();
3937 }
3938
3939 if (false == tess_ctrl_shader_code.empty())
3940 {
3941 tcs_c_str = tess_ctrl_shader_code.c_str();
3942 }
3943
3944 if (false == tess_eval_shader_code.empty())
3945 {
3946 tes_c_str = tess_eval_shader_code.c_str();
3947 }
3948
3949 if (false == vertex_shader_code.empty())
3950 {
3951 vs_c_str = vertex_shader_code.c_str();
3952 }
3953
3954 /* Compute and fragment shader results are stored in texture, do not set varyings for transfrom feedback */
3955 if ((COMPUTE_SHADER == shader_stage) || (FRAGMENT_SHADER == shader_stage))
3956 {
3957 n_varyings = 0;
3958 }
3959
3960 /* Build */
3961 out_program_info.build(cs_c_str, fs_c_str, gs_c_str, tcs_c_str, tes_c_str, vs_c_str, &varying_name, n_varyings);
3962 }
3963
3964 /** Prepare collection of tested shader stages
3965 *
3966 */
prepareShaderStages()3967 void GPUShaderFP64Test2::prepareShaderStages()
3968 {
3969 /* m_pDispatchCompute is initialized only if compute_shader are supproted and context is at least 4.2 */
3970 if (0 != m_pDispatchCompute)
3971 {
3972 m_shader_stages.push_back(COMPUTE_SHADER);
3973 }
3974
3975 m_shader_stages.push_back(FRAGMENT_SHADER);
3976 m_shader_stages.push_back(GEOMETRY_SHADER);
3977 m_shader_stages.push_back(TESS_CTRL_SHADER);
3978 m_shader_stages.push_back(TESS_EVAL_SHADER);
3979 m_shader_stages.push_back(VERTEX_SHADER);
3980 }
3981
3982 /** Prepare source code for "tested" shader stage
3983 *
3984 * @param stage_specific_layout String that will replace STAGE_SPECIFIC_LAYOUT token
3985 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
3986 * @param in_variable_definitions String that will replace IN_VARIABLE_DEFINITION token
3987 * @param out_variable_definitions String that will replace OUT_VARIABLE_DEFINITION token
3988 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
3989 * @param stage_specific_main_body String that will replace STAGE_SPECIFIC_MAIN_BODY token
3990 * @param out_source_code Shader source code
3991 **/
prepareTestShader(const glw::GLchar * stage_specific_layout,const glw::GLchar * uniform_definitions,const glw::GLchar * in_variable_definitions,const glw::GLchar * out_variable_definitions,const glw::GLchar * uniform_verification,const glw::GLchar * stage_specific_main_body,std::string & out_source_code) const3992 void GPUShaderFP64Test2::prepareTestShader(const glw::GLchar* stage_specific_layout,
3993 const glw::GLchar* uniform_definitions,
3994 const glw::GLchar* in_variable_definitions,
3995 const glw::GLchar* out_variable_definitions,
3996 const glw::GLchar* uniform_verification,
3997 const glw::GLchar* stage_specific_main_body,
3998 std::string& out_source_code) const
3999 {
4000 /* Shader template */
4001 static const glw::GLchar* test_shader_template_code = "#version 400 core\n"
4002 "\n"
4003 "precision highp float;\n"
4004 "\n"
4005 "STAGE_SPECIFIC_LAYOUT"
4006 "UNIFORM_DEFINITIONS"
4007 "IN_VARIABLE_DEFINITION"
4008 "OUT_VARIABLE_DEFINITION"
4009 "\n"
4010 "void main()\n"
4011 "{\n"
4012 "UNIFORM_VERIFICATION"
4013 "STAGE_SPECIFIC_MAIN_BODY"
4014 "}\n"
4015 "\n";
4016
4017 std::string string = test_shader_template_code;
4018
4019 /* Tokens */
4020 static const glw::GLchar* body_token = "STAGE_SPECIFIC_MAIN_BODY";
4021 static const glw::GLchar* in_var_token = "IN_VARIABLE_DEFINITION";
4022 static const glw::GLchar* layout_token = "STAGE_SPECIFIC_LAYOUT";
4023 static const glw::GLchar* out_var_token = "OUT_VARIABLE_DEFINITION";
4024 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4025 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4026
4027 size_t search_position = 0;
4028
4029 /* Replace tokens */
4030 Utils::replaceToken(layout_token, search_position, stage_specific_layout, string);
4031 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4032 Utils::replaceToken(in_var_token, search_position, in_variable_definitions, string);
4033 Utils::replaceToken(out_var_token, search_position, out_variable_definitions, string);
4034 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4035 Utils::replaceToken(body_token, search_position, stage_specific_main_body, string);
4036
4037 /* Store resuls */
4038 out_source_code = string;
4039 }
4040
4041 /** Prepare source code for "tested" compute shaders
4042 *
4043 * @param uniform_definitions String that will replace UNIFORM_DEFINITIONS token
4044 * @param uniform_verification String that will replace UNIFORM_VERIFICATION token
4045 * @param out_source_code Source code
4046 **/
prepareTestComputeShader(const glw::GLchar * uniform_definitions,const glw::GLchar * uniform_verification,std::string & out_source_code) const4047 void GPUShaderFP64Test2::prepareTestComputeShader(const glw::GLchar* uniform_definitions,
4048 const glw::GLchar* uniform_verification,
4049 std::string& out_source_code) const
4050 {
4051 /* Shader template */
4052 static const glw::GLchar* test_shader_template_code =
4053 "#version 420 core\n"
4054 "#extension GL_ARB_compute_shader : require\n"
4055 "#extension GL_ARB_shader_image_load_store : require\n"
4056 "\n"
4057 "precision highp float;\n"
4058 "\n"
4059 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
4060 "\n"
4061 "UNIFORM_DEFINITIONS"
4062 "layout(r32i) writeonly uniform iimage2D result;\n"
4063 "\n"
4064 "void main()\n"
4065 "{\n"
4066 "UNIFORM_VERIFICATION"
4067 "\n"
4068 " imageStore(result, ivec2(gl_WorkGroupID.xy), ivec4(verification_result, 0, 0, 0));\n"
4069 "}\n"
4070 "\n";
4071
4072 std::string string = test_shader_template_code;
4073
4074 /* Tokens */
4075 static const glw::GLchar* uni_def_token = "UNIFORM_DEFINITIONS";
4076 static const glw::GLchar* uni_ver_token = "UNIFORM_VERIFICATION";
4077
4078 size_t search_position = 0;
4079
4080 /* Replace tokens */
4081 Utils::replaceToken(uni_def_token, search_position, uniform_definitions, string);
4082 Utils::replaceToken(uni_ver_token, search_position, uniform_verification, string);
4083
4084 /* Store resuls */
4085 out_source_code = string;
4086 }
4087
4088 /** Prepare source code which defines uniforms for tested shader stage
4089 *
4090 * @param shader_stage Shader stage id
4091 * @param uniform_type Details of uniform type
4092 * @param out_source_code Source code
4093 **/
prepareUniformDefinitions(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4094 void GPUShaderFP64Test2::prepareUniformDefinitions(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4095 std::string& out_source_code) const
4096 {
4097 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4098 std::stringstream stream;
4099
4100 /*
4101 * layout(std140) uniform M_UNIFORM_BLOCK_NAME
4102 * {
4103 * TYPE_NAME uniform_array[N_UNIFORMS];
4104 * };
4105 */
4106 stream << "layout(std140) uniform " << m_uniform_block_name << "\n"
4107 "{\n";
4108
4109 stream << " " << uniform_type.m_type_name << " uniform_array[" << n_uniforms << "];\n";
4110
4111 stream << "};\n\n";
4112
4113 out_source_code = stream.str();
4114 }
4115
4116 /** Prepare uniform buffer for test
4117 *
4118 * @param shader_stage Shader stage id
4119 * @param uniform_type Details of uniform type
4120 * @param program_info Program object info
4121 **/
prepareUniforms(shaderStage shader_stage,const uniformTypeDetails & uniform_type,const Utils::programInfo & program_info) const4122 void GPUShaderFP64Test2::prepareUniforms(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4123 const Utils::programInfo& program_info) const
4124 {
4125 glw::GLint buffer_size = 0;
4126 glw::GLuint element_ordinal = 1;
4127 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4128 const glw::GLuint n_columns = uniform_type.m_n_columns;
4129 const glw::GLuint n_rows = uniform_type.m_n_rows;
4130 const glw::GLuint n_elements = n_columns * n_rows;
4131 uniformDetails uniform_details;
4132 const glw::GLuint program_id = program_info.m_program_object_id;
4133 const glw::GLint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4134 std::vector<glw::GLubyte> uniform_buffer_data;
4135 glw::GLuint uniform_block_index = 0;
4136
4137 /* Get uniform details */
4138 inspectProgram(program_id, n_uniforms, uniform_type, buffer_size, uniform_details, uniform_block_index);
4139
4140 /* Uniform offset and strides */
4141 const glw::GLuint array_stride = uniform_details.m_array_stride;
4142 const glw::GLuint matrix_stride = uniform_details.m_matrix_stride;
4143 const glw::GLuint uniform_offset = uniform_details.m_offset;
4144
4145 /* Prepare storage for buffer data */
4146 uniform_buffer_data.resize(buffer_size);
4147
4148 /* Prepare uniform data */
4149 for (glw::GLint i = 0; i < n_uniforms; ++i)
4150 {
4151 const glw::GLuint array_entry_offset = uniform_offset + i * array_stride;
4152
4153 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4154 {
4155 const glw::GLuint column = element / n_rows;
4156 const glw::GLuint column_elem = element % n_rows;
4157 const glw::GLdouble value = element_ordinal;
4158 const glw::GLuint value_offset = static_cast<glw::GLuint>(array_entry_offset + column * matrix_stride +
4159 column_elem * sizeof(glw::GLdouble));
4160 glw::GLdouble* value_dst = (glw::GLdouble*)&uniform_buffer_data[value_offset];
4161
4162 *value_dst = value;
4163 }
4164 }
4165
4166 /* Update uniform buffer with new set of data */
4167 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
4168 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4169
4170 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &uniform_buffer_data[0], GL_STATIC_DRAW);
4171 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4172
4173 /* Bind uniform block to uniform buffer */
4174 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0 /* offset */, buffer_size);
4175 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4176
4177 gl.uniformBlockBinding(program_id, uniform_block_index, 0 /* binding */);
4178 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
4179 }
4180
4181 /** Prepare collection of tested uniform types
4182 *
4183 **/
prepareUniformTypes()4184 void GPUShaderFP64Test2::prepareUniformTypes()
4185 {
4186 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 1 /* n_rows */));
4187 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 2 /* n_rows */));
4188 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 3 /* n_rows */));
4189 m_uniform_types.push_back(uniformTypeDetails(1 /* n_columns */, 4 /* n_rows */));
4190 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 2 /* n_rows */));
4191 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 3 /* n_rows */));
4192 m_uniform_types.push_back(uniformTypeDetails(2 /* n_columns */, 4 /* n_rows */));
4193 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 2 /* n_rows */));
4194 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 3 /* n_rows */));
4195 m_uniform_types.push_back(uniformTypeDetails(3 /* n_columns */, 4 /* n_rows */));
4196 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 2 /* n_rows */));
4197 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 3 /* n_rows */));
4198 m_uniform_types.push_back(uniformTypeDetails(4 /* n_columns */, 4 /* n_rows */));
4199 }
4200
4201 /** Prepare source code that verifes uniform values
4202 *
4203 * @param shader_stage Shader stage id
4204 * @param uniform_type Details of uniform type
4205 * @param out_source_code Source code
4206 **/
prepareUniformVerification(shaderStage shader_stage,const uniformTypeDetails & uniform_type,std::string & out_source_code) const4207 void GPUShaderFP64Test2::prepareUniformVerification(shaderStage shader_stage, const uniformTypeDetails& uniform_type,
4208 std::string& out_source_code) const
4209 {
4210 glw::GLuint element_ordinal = 1;
4211 const glw::GLuint n_columns = uniform_type.m_n_columns;
4212 const glw::GLuint n_rows = uniform_type.m_n_rows;
4213 const glw::GLuint n_elements = n_columns * n_rows;
4214 const glw::GLuint n_uniforms = getAmountUniforms(shader_stage, uniform_type);
4215 std::stringstream stream;
4216
4217 /*
4218 * int verification_result = M_RESULT_SUCCESS;
4219 *
4220 * for (int i = 0; i < N_UNIFORMS; ++i)
4221 * {
4222 * if (TYPE_NAME(i * (N_ELEMENTS) + 1) != uniform_array[i])
4223 * {
4224 * verification_result = M_RESULT_FAILURE
4225 * }
4226 * }
4227 */
4228 stream << " int verification_result = " << m_result_success << ";\n"
4229 "\n"
4230 " for (int i = 0; i < "
4231 << n_uniforms << "; ++i)\n"
4232 " {\n"
4233 " if ("
4234 << uniform_type.m_type_name << "(";
4235
4236 for (glw::GLuint element = 0; element < n_elements; ++element, ++element_ordinal)
4237 {
4238 stream << "i * (" << n_elements << ") + " << element + 1;
4239
4240 if (n_elements != element + 1)
4241 {
4242 stream << ", ";
4243 }
4244 }
4245
4246 stream << ") != uniform_array[i])\n"
4247 " {\n"
4248 " verification_result = "
4249 << m_result_failure << ";\n"
4250 " }\n"
4251 " }\n";
4252
4253 out_source_code = stream.str();
4254 }
4255
4256 /** Execute test for given combination of "tested" shader stage and uniform type
4257 *
4258 * @param shader_stage Tested shader stage id
4259 * @param uniform_type Tested uniform type
4260 *
4261 * @return true if test passed, false otherwise
4262 **/
test(shaderStage shader_stage,const uniformTypeDetails & uniform_type) const4263 bool GPUShaderFP64Test2::test(shaderStage shader_stage, const uniformTypeDetails& uniform_type) const
4264 {
4265 const glw::GLenum draw_primitive = getDrawPrimitiveType(shader_stage);
4266 static const glw::GLint first_vertex = 0;
4267 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4268 const glw::GLsizei n_vertices = (FRAGMENT_SHADER == shader_stage) ? 4 : m_n_captured_results;
4269 Utils::programInfo program_info(m_context);
4270 bool result = true;
4271
4272 /* Prepare program */
4273 prepareProgram(shader_stage, uniform_type, program_info);
4274
4275 gl.useProgram(program_info.m_program_object_id);
4276 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
4277
4278 /* Prepare uniform buffer and bind it with uniform block */
4279 prepareUniforms(shader_stage, uniform_type, program_info);
4280
4281 /* Prepare storage for test results */
4282 testBegin(program_info.m_program_object_id, shader_stage);
4283
4284 /* Execute */
4285 if (COMPUTE_SHADER == shader_stage)
4286 {
4287 m_pDispatchCompute(m_texture_width, m_texture_height, 1);
4288 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
4289 }
4290 else
4291 {
4292 gl.drawArrays(draw_primitive, first_vertex, n_vertices);
4293 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
4294 }
4295
4296 /* Clean after test */
4297 testEnd(shader_stage);
4298
4299 /* Check results */
4300 if (false == verifyResults(shader_stage))
4301 {
4302 m_context.getTestContext().getLog()
4303 << tcu::TestLog::Message << "Shader stage: " << getShaderStageName(shader_stage)
4304 << ". Uniform type: " << uniform_type.m_type_name << tcu::TestLog::EndMessage;
4305
4306 result = false;
4307 }
4308
4309 return result;
4310 }
4311
4312 /** Prepare transform feedback buffer, framebuffer or image unit for test results
4313 *
4314 * @param program_id Program object id
4315 * @param shader_stage Tested shader stage id
4316 **/
testBegin(glw::GLuint program_id,shaderStage shader_stage) const4317 void GPUShaderFP64Test2::testBegin(glw::GLuint program_id, shaderStage shader_stage) const
4318 {
4319 std::vector<glw::GLint> buffer_data;
4320 const glw::GLenum captured_primitive = getCapturedPrimitiveType(shader_stage);
4321 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4322
4323 /* Prepare buffer filled with m_result_failure */
4324 buffer_data.resize(m_n_captured_results);
4325 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4326 {
4327 buffer_data[i] = m_result_failure;
4328 }
4329
4330 /* Prepare buffer for test results */
4331 switch (shader_stage)
4332 {
4333 case GEOMETRY_SHADER:
4334 case TESS_CTRL_SHADER:
4335 case TESS_EVAL_SHADER:
4336 case VERTEX_SHADER:
4337
4338 /* Verify getTransformFeedbackVarying results */
4339 {
4340 glw::GLsizei size = 0;
4341 glw::GLenum type = 0;
4342 glw::GLchar name[16];
4343
4344 gl.getTransformFeedbackVarying(program_id, 0 /* index */, 16 /* bufSize */, 0 /* length */, &size, &type,
4345 name);
4346 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTransformFeedbackVarying");
4347
4348 if ((1 != size) || (GL_INT != type) || (0 != strcmp("result", name)))
4349 {
4350 m_context.getTestContext().getLog()
4351 << tcu::TestLog::Message << "Error. Invalid GetTransformFeedbackVarying results."
4352 << " Size: " << size << " expected: " << 1 << ". Type: " << type << " expected: " << GL_INT
4353 << ". Name: " << name << " expected: result" << tcu::TestLog::EndMessage;
4354
4355 TCU_FAIL("Invalid GetTransformFeedbackVarying results");
4356 }
4357 }
4358
4359 /* Create/clean transform feedback buffer */
4360 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4361 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4362
4363 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_size, &buffer_data[0], GL_DYNAMIC_COPY);
4364 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
4365
4366 /* Set up transform feedback buffer */
4367 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
4368 m_transform_feedback_buffer_size);
4369 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
4370
4371 gl.beginTransformFeedback(captured_primitive);
4372 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
4373
4374 break;
4375
4376 case FRAGMENT_SHADER:
4377
4378 /* Clean texture */
4379 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4380 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4381
4382 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4383 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4384 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4385
4386 /* Set up texture as color attachment 0 */
4387 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
4388 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
4389
4390 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /* level */);
4391 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
4392
4393 gl.viewport(0 /* x */, 0 /* y */, m_texture_width, m_texture_height);
4394 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
4395
4396 break;
4397
4398 case COMPUTE_SHADER:
4399
4400 /* Clean texture */
4401 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4402 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4403
4404 gl.texSubImage2D(GL_TEXTURE_2D, 0 /* level */, 0 /* x */, 0 /* y */, m_texture_width, m_texture_height,
4405 GL_RED_INTEGER, GL_INT, &buffer_data[0]);
4406 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4407
4408 glw::GLint location = gl.getUniformLocation(program_id, "result");
4409 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4410
4411 if (-1 == location)
4412 {
4413 TCU_FAIL("Inactive uniform \"result\"");
4414 }
4415
4416 gl.uniform1i(location, 0 /* first image unit */);
4417 GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
4418
4419 /* Bind texture to first image unit */
4420 gl.bindImageTexture(0 /* first image unit */, m_texture_id, 0 /* level */, GL_FALSE /* layered */,
4421 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4422 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
4423
4424 break;
4425 }
4426 }
4427
4428 /** Unbind transform feedback buffer, framebuffer or image unit
4429 *
4430 * @param shader_stage Tested shader stage id
4431 **/
testEnd(shaderStage shader_stage) const4432 void GPUShaderFP64Test2::testEnd(shaderStage shader_stage) const
4433 {
4434 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4435
4436 switch (shader_stage)
4437 {
4438 case GEOMETRY_SHADER:
4439 case TESS_CTRL_SHADER:
4440 case TESS_EVAL_SHADER:
4441 case VERTEX_SHADER:
4442
4443 gl.endTransformFeedback();
4444
4445 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4446
4447 break;
4448
4449 case FRAGMENT_SHADER:
4450
4451 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0 /* texture_id */,
4452 0 /* level */);
4453
4454 gl.bindTexture(GL_TEXTURE_2D, 0);
4455
4456 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4457
4458 break;
4459
4460 case COMPUTE_SHADER:
4461
4462 gl.bindImageTexture(0 /* first image unit */, 0 /* texture_id */, 0 /* level */, GL_FALSE /* layered */,
4463 0 /* layer */, GL_WRITE_ONLY, GL_R32I);
4464
4465 break;
4466 }
4467 }
4468
4469 /** Initialize OpenGL objects for test
4470 *
4471 **/
testInit()4472 void GPUShaderFP64Test2::testInit()
4473 {
4474 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4475
4476 /* The test is in 4.0 group. However:
4477 * - compute_shader is core since 4.3
4478 * - compute_shader require at least version 4.2 of GL */
4479 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
4480 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
4481 {
4482 m_pDispatchCompute = (arbDispatchComputeFunc)gl.dispatchCompute;
4483 }
4484
4485 /* Tesselation patch set up */
4486 gl.patchParameteri(GL_PATCH_VERTICES, 1);
4487 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
4488
4489 /* Generate FBO */
4490 gl.genFramebuffers(1, &m_framebuffer_id);
4491 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
4492
4493 /* Prepare texture */
4494 gl.genTextures(1, &m_texture_id);
4495 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
4496
4497 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4498 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4499
4500 gl.texStorage2D(GL_TEXTURE_2D, 1, GL_R32I, m_texture_width, m_texture_height);
4501 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
4502
4503 /* Prepare transform feedback buffer */
4504 gl.genBuffers(1, &m_transform_feedback_buffer_id);
4505 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4506
4507 /* Generate uniform buffer */
4508 gl.genBuffers(1, &m_uniform_buffer_id);
4509 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
4510
4511 /* Prepare VAO */
4512 gl.genVertexArrays(1, &m_vertex_array_object_id);
4513 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
4514
4515 gl.bindVertexArray(m_vertex_array_object_id);
4516 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
4517 }
4518
4519 /** Result verification, expected result is that whole buffer is filled with m_result_success
4520 *
4521 * @param shader_stage Tested shader stage id
4522 **/
verifyResults(shaderStage shader_stage) const4523 bool GPUShaderFP64Test2::verifyResults(shaderStage shader_stage) const
4524 {
4525 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4526
4527 if ((FRAGMENT_SHADER == shader_stage) || (COMPUTE_SHADER == shader_stage))
4528 {
4529 /* Verify contents of texture */
4530
4531 /* Prepare storage for testure data */
4532 std::vector<glw::GLint> image_data;
4533 image_data.resize(m_texture_width * m_texture_height);
4534
4535 /* Get texture contents */
4536 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
4537 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
4538
4539 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
4540 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
4541
4542 for (glw::GLuint y = 0; y < m_texture_width; ++y)
4543 {
4544 for (glw::GLuint x = 0; x < m_texture_height; ++x)
4545 {
4546 const glw::GLuint offset = y * m_texture_width + x;
4547 const glw::GLint value = image_data[offset];
4548
4549 if (m_result_success != value)
4550 {
4551 m_context.getTestContext().getLog()
4552 << tcu::TestLog::Message << "Error. Texture contents are wrong at (" << x << ", " << y << ")"
4553 << tcu::TestLog::EndMessage;
4554
4555 return false;
4556 }
4557 }
4558 }
4559
4560 return true;
4561 }
4562 else
4563 {
4564 /* Verify contents of transform feedback buffer */
4565
4566 bool result = true;
4567
4568 /* Get transform feedback data */
4569 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
4570 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
4571
4572 glw::GLint* feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
4573 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
4574
4575 for (glw::GLuint i = 0; i < m_n_captured_results; ++i)
4576 {
4577 const glw::GLint value = feedback_data[i];
4578
4579 if (m_result_success != value)
4580 {
4581 m_context.getTestContext().getLog() << tcu::TestLog::Message
4582 << "Error. Transform feedback buffer contents are wrong at " << i
4583 << tcu::TestLog::EndMessage;
4584
4585 result = false;
4586 break;
4587 }
4588 }
4589
4590 /* Unmap transform feedback buffer */
4591 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4592 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
4593
4594 return result;
4595 }
4596 }
4597
4598 /* Definitions of static const fields declared in GPUShaderFP64Test3 */
4599 const glw::GLuint GPUShaderFP64Test3::m_result_failure = 0;
4600 const glw::GLuint GPUShaderFP64Test3::m_result_success = 1;
4601
4602 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_name = "UniformBlock";
4603 const glw::GLchar* GPUShaderFP64Test3::m_uniform_block_instance_name = "uniform_block";
4604
4605 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_fs_out_fs_result = "fs_out_fs_result";
4606 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_gs_result = "gs_fs_gs_result";
4607 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tcs_result = "gs_fs_tcs_result";
4608 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_tes_result = "gs_fs_tes_result";
4609 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_gs_fs_vs_result = "gs_fs_vs_result";
4610 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_tcs_result = "tcs_tes_tcs_result";
4611 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tcs_tes_vs_result = "tcs_tes_vs_result";
4612 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tcs_result = "tes_gs_tcs_result";
4613 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_tes_result = "tes_gs_tes_result";
4614 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_tes_gs_vs_result = "tes_gs_vs_result";
4615 const glw::GLchar* GPUShaderFP64Test3::m_varying_name_vs_tcs_vs_result = "vs_tcs_vs_result";
4616
4617 /* Definitions of static const fields declared in GPUShaderFP64Test3::programInfo */
4618 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_offset = -1;
4619 const glw::GLint GPUShaderFP64Test3::programInfo::m_invalid_uniform_matrix_stride = -1;
4620 const glw::GLint GPUShaderFP64Test3::programInfo::m_non_matrix_uniform_matrix_stride = 0;
4621
4622 /** Constructor
4623 *
4624 * @param context Test context
4625 **/
GPUShaderFP64Test3(deqp::Context & context)4626 GPUShaderFP64Test3::GPUShaderFP64Test3(deqp::Context& context)
4627 : TestCase(context, "named_uniform_blocks",
4628 "Verifies usage of \"double precision\" floats in \"named uniform block\"")
4629 {
4630 /* Nothing to be done */
4631 }
4632
4633 /** Deinitialize test
4634 *
4635 **/
deinit()4636 void GPUShaderFP64Test3::deinit()
4637 {
4638 /* GL entry points */
4639 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4640
4641 /* Clean programs */
4642 m_packed_program.deinit(m_context);
4643 m_shared_program.deinit(m_context);
4644 m_std140_program.deinit(m_context);
4645
4646 /* Clean frambuffer */
4647 if (0 != m_framebuffer_id)
4648 {
4649 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
4650 gl.deleteFramebuffers(1, &m_framebuffer_id);
4651
4652 m_framebuffer_id = 0;
4653 }
4654
4655 /* Clean texture */
4656 if (0 != m_color_texture_id)
4657 {
4658 gl.bindTexture(GL_TEXTURE_2D, 0);
4659 gl.deleteTextures(1, &m_color_texture_id);
4660
4661 m_color_texture_id = 0;
4662 }
4663
4664 /* Clean buffers */
4665 if (0 != m_transform_feedback_buffer_id)
4666 {
4667 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
4668 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
4669
4670 m_transform_feedback_buffer_id = 0;
4671 }
4672
4673 if (0 != m_uniform_buffer_id)
4674 {
4675 gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
4676 gl.deleteBuffers(1, &m_uniform_buffer_id);
4677
4678 m_uniform_buffer_id = 0;
4679 }
4680
4681 /* Clean VAO */
4682 if (0 != m_vertex_array_object_id)
4683 {
4684 gl.bindVertexArray(0);
4685 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
4686
4687 m_vertex_array_object_id = 0;
4688 }
4689 }
4690
4691 /** Execute test
4692 *
4693 * @return tcu::TestNode::STOP
4694 **/
iterate()4695 tcu::TestNode::IterateResult GPUShaderFP64Test3::iterate()
4696 {
4697 bool result = true;
4698
4699 /* Check if extension is supported */
4700 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
4701 {
4702 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
4703 }
4704
4705 /* Initialize test */
4706 testInit();
4707
4708 /* Test "packed" uniform buffer layout */
4709 if (false == test(PACKED))
4710 {
4711 result = false;
4712 }
4713
4714 /* Test "shared" uniform buffer layout */
4715 if (false == test(SHARED))
4716 {
4717 result = false;
4718 }
4719
4720 /* Test "std140" uniform buffer layout */
4721 if (false == test(STD140))
4722 {
4723 result = false;
4724 }
4725
4726 /* Set result */
4727 if (true == result)
4728 {
4729 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
4730 }
4731 else
4732 {
4733 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4734 }
4735
4736 /* Done */
4737 return tcu::TestNode::STOP;
4738 }
4739
4740 /** Constructor
4741 *
4742 **/
programInfo()4743 GPUShaderFP64Test3::programInfo::programInfo()
4744 : m_fragment_shader_id(0)
4745 , m_geometry_shader_id(0)
4746 , m_program_object_id(0)
4747 , m_tesselation_control_shader_id(0)
4748 , m_tesselation_evaluation_shader_id(0)
4749 , m_vertex_shader_id(0)
4750 , m_buffer_size(0)
4751 , m_uniform_block_index(0)
4752 {
4753 /* Nothing to be done here */
4754 }
4755
4756 /** Compile shader
4757 *
4758 * @param context Test context
4759 * @param shader_id Shader object id
4760 * @param shader_code Shader source code
4761 **/
compile(deqp::Context & context,glw::GLuint shader_id,const glw::GLchar * shader_code) const4762 void GPUShaderFP64Test3::programInfo::compile(deqp::Context& context, glw::GLuint shader_id,
4763 const glw::GLchar* shader_code) const
4764 {
4765 /* GL entry points */
4766 const glw::Functions& gl = context.getRenderContext().getFunctions();
4767
4768 /* Compilation status */
4769 glw::GLint status = GL_FALSE;
4770
4771 /* Set source code */
4772 gl.shaderSource(shader_id, 1 /* count */, &shader_code, 0);
4773 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
4774
4775 /* Compile */
4776 gl.compileShader(shader_id);
4777 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
4778
4779 /* Get compilation status */
4780 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &status);
4781 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4782
4783 /* Log compilation error */
4784 if (GL_TRUE != status)
4785 {
4786 glw::GLint length = 0;
4787 std::vector<glw::GLchar> message;
4788
4789 /* Error log length */
4790 gl.getShaderiv(shader_id, GL_INFO_LOG_LENGTH, &length);
4791 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
4792
4793 /* Prepare storage */
4794 message.resize(length);
4795
4796 /* Get error log */
4797 gl.getShaderInfoLog(shader_id, length, 0, &message[0]);
4798 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
4799
4800 /* Log */
4801 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader:\n"
4802 << &message[0] << "\nShader source\n"
4803 << shader_code << tcu::TestLog::EndMessage;
4804
4805 TCU_FAIL("Failed to compile shader");
4806 }
4807 }
4808
4809 /** Cleans program and attached shaders
4810 *
4811 * @param context Test context
4812 **/
deinit(deqp::Context & context)4813 void GPUShaderFP64Test3::programInfo::deinit(deqp::Context& context)
4814 {
4815 /* GL entry points */
4816 const glw::Functions& gl = context.getRenderContext().getFunctions();
4817
4818 /* Restore default program */
4819 gl.useProgram(0);
4820
4821 /* Clean program object */
4822 if (0 != m_program_object_id)
4823 {
4824 gl.deleteProgram(m_program_object_id);
4825 m_program_object_id = 0;
4826 }
4827
4828 /* Clean shaders */
4829 if (0 != m_fragment_shader_id)
4830 {
4831 gl.deleteShader(m_fragment_shader_id);
4832 m_fragment_shader_id = 0;
4833 }
4834
4835 if (0 != m_geometry_shader_id)
4836 {
4837 gl.deleteShader(m_geometry_shader_id);
4838 m_geometry_shader_id = 0;
4839 }
4840
4841 if (0 != m_tesselation_control_shader_id)
4842 {
4843 gl.deleteShader(m_tesselation_control_shader_id);
4844 m_tesselation_control_shader_id = 0;
4845 }
4846
4847 if (0 != m_tesselation_evaluation_shader_id)
4848 {
4849 gl.deleteShader(m_tesselation_evaluation_shader_id);
4850 m_tesselation_evaluation_shader_id = 0;
4851 }
4852
4853 if (0 != m_vertex_shader_id)
4854 {
4855 gl.deleteShader(m_vertex_shader_id);
4856 m_vertex_shader_id = 0;
4857 }
4858 }
4859
4860 /** Build program and query for uniform layout
4861 *
4862 * @param context Test context
4863 * @param uniform_details Collection of uniform details
4864 * @param fragment_shader_code Fragment shader source code
4865 * @param geometry_shader_code Geometry shader source code
4866 * @param tesselation_control_shader_code Tesselation control shader source code
4867 * @param tesselation_evaluation_shader_code Tesselation evaluation shader source code
4868 * @param vertex_shader_code Vertex shader source code
4869 **/
init(deqp::Context & context,const std::vector<uniformDetails> uniform_details,const glw::GLchar * fragment_shader_code,const glw::GLchar * geometry_shader_code,const glw::GLchar * tesselation_control_shader_code,const glw::GLchar * tesselation_evaluation_shader_code,const glw::GLchar * vertex_shader_code)4870 void GPUShaderFP64Test3::programInfo::init(deqp::Context& context, const std::vector<uniformDetails> uniform_details,
4871 const glw::GLchar* fragment_shader_code,
4872 const glw::GLchar* geometry_shader_code,
4873 const glw::GLchar* tesselation_control_shader_code,
4874 const glw::GLchar* tesselation_evaluation_shader_code,
4875 const glw::GLchar* vertex_shader_code)
4876 {
4877 /* GL entry points */
4878 const glw::Functions& gl = context.getRenderContext().getFunctions();
4879
4880 /* Names of varyings to be captured with transform feedback */
4881 static const glw::GLchar* varying_names[] = { m_varying_name_gs_fs_gs_result, m_varying_name_gs_fs_tcs_result,
4882 m_varying_name_gs_fs_tes_result, m_varying_name_gs_fs_vs_result };
4883 static const glw::GLuint n_varying_names = sizeof(varying_names) / sizeof(varying_names[0]);
4884
4885 /* Create shader objects */
4886 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
4887 m_geometry_shader_id = gl.createShader(GL_GEOMETRY_SHADER);
4888 m_tesselation_control_shader_id = gl.createShader(GL_TESS_CONTROL_SHADER);
4889 m_tesselation_evaluation_shader_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
4890 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
4891 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
4892
4893 /* Create program object */
4894 m_program_object_id = gl.createProgram();
4895 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
4896
4897 /* Set up names of varyings to be captured with transform feedback */
4898 gl.transformFeedbackVaryings(m_program_object_id, n_varying_names, varying_names, GL_INTERLEAVED_ATTRIBS);
4899 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
4900
4901 /* Compile shaders */
4902 compile(context, m_fragment_shader_id, fragment_shader_code);
4903 compile(context, m_geometry_shader_id, geometry_shader_code);
4904 compile(context, m_tesselation_control_shader_id, tesselation_control_shader_code);
4905 compile(context, m_tesselation_evaluation_shader_id, tesselation_evaluation_shader_code);
4906 compile(context, m_vertex_shader_id, vertex_shader_code);
4907
4908 /* Link program */
4909 link(context);
4910
4911 /* Inspect program object */
4912 /* Get index of named uniform block */
4913 m_uniform_block_index = gl.getUniformBlockIndex(m_program_object_id, m_uniform_block_name);
4914 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformBlockIndex");
4915
4916 if (GL_INVALID_INDEX == m_uniform_block_index)
4917 {
4918 TCU_FAIL("Unifom block is inactive");
4919 }
4920
4921 /* Get size of named uniform block */
4922 gl.getActiveUniformBlockiv(m_program_object_id, m_uniform_block_index, GL_UNIFORM_BLOCK_DATA_SIZE, &m_buffer_size);
4923 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformBlockiv");
4924
4925 if (0 == m_buffer_size)
4926 {
4927 TCU_FAIL("Unifom block size is 0");
4928 }
4929
4930 /* Get information about "double precision" uniforms */
4931 for (std::vector<uniformDetails>::const_iterator it = uniform_details.begin(), end = uniform_details.end();
4932 end != it; ++it)
4933 {
4934 const glw::GLchar* uniform_name = 0;
4935 std::string uniform_name_str;
4936 std::stringstream uniform_name_stream;
4937 glw::GLuint index = 0;
4938 glw::GLint offset = 0;
4939 glw::GLint matrix_stride = 0;
4940
4941 /* Uniform name = UNIFORM_BLOCK_NAME.UNIFORM_NAME */
4942 uniform_name_stream << m_uniform_block_name << "." << it->m_name;
4943
4944 uniform_name_str = uniform_name_stream.str();
4945 uniform_name = uniform_name_str.c_str();
4946
4947 /* Get index of uniform */
4948 gl.getUniformIndices(m_program_object_id, 1 /* count */, &uniform_name, &index);
4949 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
4950
4951 if (GL_INVALID_INDEX == index)
4952 {
4953 TCU_FAIL("Unifom is inactive");
4954 }
4955
4956 /* Get offset of uniform */
4957 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_OFFSET, &offset);
4958 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4959
4960 if (m_invalid_uniform_offset == offset)
4961 {
4962 TCU_FAIL("Unifom has invalid offset");
4963 }
4964
4965 m_uniform_offsets.push_back(offset);
4966
4967 /* Get matrix stride of uniform */
4968 gl.getActiveUniformsiv(m_program_object_id, 1 /* count */, &index, GL_UNIFORM_MATRIX_STRIDE, &matrix_stride);
4969 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
4970
4971 if (m_invalid_uniform_matrix_stride == offset)
4972 {
4973 TCU_FAIL("Unifom has invalid matrix stride");
4974 }
4975
4976 m_uniform_matrix_strides.push_back(matrix_stride);
4977 }
4978 }
4979
4980 /** Attach shaders and link program
4981 *
4982 * @param context Test context
4983 **/
link(deqp::Context & context) const4984 void GPUShaderFP64Test3::programInfo::link(deqp::Context& context) const
4985 {
4986 /* GL entry points */
4987 const glw::Functions& gl = context.getRenderContext().getFunctions();
4988
4989 /* Link status */
4990 glw::GLint status = GL_FALSE;
4991
4992 /* Attach shaders */
4993 gl.attachShader(m_program_object_id, m_fragment_shader_id);
4994 gl.attachShader(m_program_object_id, m_geometry_shader_id);
4995 gl.attachShader(m_program_object_id, m_tesselation_control_shader_id);
4996 gl.attachShader(m_program_object_id, m_tesselation_evaluation_shader_id);
4997 gl.attachShader(m_program_object_id, m_vertex_shader_id);
4998 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
4999
5000 /* Link */
5001 gl.linkProgram(m_program_object_id);
5002 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
5003
5004 /* Get link status */
5005 gl.getProgramiv(m_program_object_id, GL_LINK_STATUS, &status);
5006 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5007
5008 /* Log link error */
5009 if (GL_TRUE != status)
5010 {
5011 glw::GLint length = 0;
5012 std::vector<glw::GLchar> message;
5013
5014 /* Get error log length */
5015 gl.getProgramiv(m_program_object_id, GL_INFO_LOG_LENGTH, &length);
5016 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
5017
5018 message.resize(length);
5019
5020 /* Get error log */
5021 gl.getProgramInfoLog(m_program_object_id, length, 0, &message[0]);
5022 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
5023
5024 /* Log */
5025 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to link program:\n"
5026 << &message[0] << tcu::TestLog::EndMessage;
5027
5028 TCU_FAIL("Failed to link program");
5029 }
5030 }
5031
5032 /** Returns "predefined" values that will be used to fill uniform data
5033 *
5034 * @param type_ordinal Ordinal number of "double precision" uniform type
5035 * @param element Index of element in uniform
5036 *
5037 * @return "Predefined" value
5038 **/
getExpectedValue(glw::GLuint type_ordinal,glw::GLuint element) const5039 glw::GLdouble GPUShaderFP64Test3::getExpectedValue(glw::GLuint type_ordinal, glw::GLuint element) const
5040 {
5041 return m_base_type_ordinal + (13.0 * (glw::GLdouble)type_ordinal) +
5042 ((m_base_element - (glw::GLdouble)element) / 4.0);
5043 }
5044
5045 /** Returns a reference of programInfo instance specific for given buffer layout
5046 *
5047 * @param uniform_data_layout Buffer layout
5048 *
5049 * @return Reference to an instance of programInfo
5050 **/
getProgramInfo(uniformDataLayout uniform_data_layout) const5051 const GPUShaderFP64Test3::programInfo& GPUShaderFP64Test3::getProgramInfo(uniformDataLayout uniform_data_layout) const
5052 {
5053 const programInfo* program_info = 0;
5054
5055 switch (uniform_data_layout)
5056 {
5057 case PACKED:
5058
5059 program_info = &m_packed_program;
5060
5061 break;
5062
5063 case SHARED:
5064
5065 program_info = &m_shared_program;
5066
5067 break;
5068
5069 case STD140:
5070
5071 program_info = &m_std140_program;
5072
5073 break;
5074 }
5075
5076 return *program_info;
5077 }
5078
5079 /** Get "name" of buffer layout
5080 *
5081 * @param uniform_data_layout Buffer layout
5082 *
5083 * @return "Name" of layout
5084 **/
getUniformLayoutName(uniformDataLayout uniform_data_layout) const5085 const glw::GLchar* GPUShaderFP64Test3::getUniformLayoutName(uniformDataLayout uniform_data_layout) const
5086 {
5087 const glw::GLchar* layout = "";
5088
5089 switch (uniform_data_layout)
5090 {
5091 case PACKED:
5092 layout = "packed";
5093 break;
5094 case SHARED:
5095 layout = "shared";
5096 break;
5097 case STD140:
5098 layout = "std140";
5099 break;
5100 }
5101
5102 return layout;
5103 }
5104
5105 /** Prepare programInfo instance for specific buffer layout
5106 *
5107 * @param program_info Instance of programInfo
5108 * @param uniform_data_layout Buffer layout
5109 **/
prepareProgram(programInfo & program_info,uniformDataLayout uniform_data_layout) const5110 void GPUShaderFP64Test3::prepareProgram(programInfo& program_info, uniformDataLayout uniform_data_layout) const
5111 {
5112 /* Storage for shader source code */
5113 std::stringstream fragment_shader_code;
5114 std::stringstream geometry_shader_code;
5115 std::stringstream tess_control_shader_code;
5116 std::stringstream tess_eval_shader_code;
5117 std::stringstream vertex_shader_code;
5118
5119 /* Write preambles */
5120 writePreamble(fragment_shader_code, FRAGMENT_SHADER);
5121 writePreamble(geometry_shader_code, GEOMETRY_SHADER);
5122 writePreamble(tess_control_shader_code, TESS_CONTROL_SHADER);
5123 writePreamble(tess_eval_shader_code, TESS_EVAL_SHADER);
5124 writePreamble(vertex_shader_code, VERTEX_SHADER);
5125
5126 /* Write definition of named uniform block */
5127 writeUniformBlock(fragment_shader_code, uniform_data_layout);
5128 writeUniformBlock(geometry_shader_code, uniform_data_layout);
5129 writeUniformBlock(tess_control_shader_code, uniform_data_layout);
5130 writeUniformBlock(tess_eval_shader_code, uniform_data_layout);
5131 writeUniformBlock(vertex_shader_code, uniform_data_layout);
5132
5133 /* Write definitions of varyings */
5134 writeVaryingDeclarations(fragment_shader_code, FRAGMENT_SHADER);
5135 writeVaryingDeclarations(geometry_shader_code, GEOMETRY_SHADER);
5136 writeVaryingDeclarations(tess_control_shader_code, TESS_CONTROL_SHADER);
5137 writeVaryingDeclarations(tess_eval_shader_code, TESS_EVAL_SHADER);
5138 writeVaryingDeclarations(vertex_shader_code, VERTEX_SHADER);
5139
5140 /* Write main routine */
5141 writeMainBody(fragment_shader_code, FRAGMENT_SHADER);
5142 writeMainBody(geometry_shader_code, GEOMETRY_SHADER);
5143 writeMainBody(tess_control_shader_code, TESS_CONTROL_SHADER);
5144 writeMainBody(tess_eval_shader_code, TESS_EVAL_SHADER);
5145 writeMainBody(vertex_shader_code, VERTEX_SHADER);
5146
5147 /* Init programInfo instance */
5148 program_info.init(m_context, m_uniform_details, fragment_shader_code.str().c_str(),
5149 geometry_shader_code.str().c_str(), tess_control_shader_code.str().c_str(),
5150 tess_eval_shader_code.str().c_str(), vertex_shader_code.str().c_str());
5151 }
5152
5153 /** Prepare uniform buffer
5154 *
5155 * @param program_info Instance of programInfo
5156 * @param verify_offsets If uniform offsets should be verified against expected values
5157 *
5158 * @return false if uniform offsets verification result is failure, true otherwise
5159 **/
prepareUniformBuffer(const programInfo & program_info,bool verify_offsets) const5160 bool GPUShaderFP64Test3::prepareUniformBuffer(const programInfo& program_info, bool verify_offsets) const
5161 {
5162 const glw::GLuint buffer_size = program_info.m_buffer_size;
5163 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5164 bool offset_verification_result = true;
5165 glw::GLuint type_ordinal = 1;
5166 std::vector<uniformDetails>::const_iterator it_uniform_details = m_uniform_details.begin();
5167 std::vector<glw::GLint>::const_iterator it_uniform_offsets = program_info.m_uniform_offsets.begin();
5168 std::vector<glw::GLint>::const_iterator it_uniform_matrix_strides = program_info.m_uniform_matrix_strides.begin();
5169
5170 /* Prepare storage for uniform buffer data */
5171 std::vector<glw::GLubyte> buffer_data;
5172 buffer_data.resize(buffer_size);
5173
5174 /* For each "double precision" uniform */
5175 for (/* start conditions already set up */; m_uniform_details.end() != it_uniform_details;
5176 ++it_uniform_details, ++it_uniform_offsets, ++it_uniform_matrix_strides, ++type_ordinal)
5177 {
5178 const glw::GLint matrix_stride = *it_uniform_matrix_strides;
5179 const glw::GLuint n_columns = it_uniform_details->m_n_columns;
5180 const glw::GLuint n_elements = it_uniform_details->m_n_elements;
5181 const glw::GLuint column_length = n_elements / n_columns;
5182 const glw::GLint uniform_offset = *it_uniform_offsets;
5183
5184 /* For each element of uniform */
5185 for (glw::GLuint element = 0; element < n_elements; ++element)
5186 {
5187 const glw::GLuint column = element / column_length;
5188 const glw::GLuint column_elem = element % column_length;
5189 const glw::GLdouble value = getExpectedValue(type_ordinal, element);
5190 const glw::GLuint value_offset =
5191 static_cast<glw::GLuint>(uniform_offset + column * matrix_stride + column_elem * sizeof(glw::GLdouble));
5192
5193 glw::GLdouble* value_dst = (glw::GLdouble*)&buffer_data[value_offset];
5194
5195 /* Store value */
5196 *value_dst = value;
5197 }
5198
5199 /* Uniform offset verification */
5200 if (true == verify_offsets)
5201 {
5202 const glw::GLint expected_offset = it_uniform_details->m_expected_std140_offset;
5203
5204 if (expected_offset != uniform_offset)
5205 {
5206 if (true == offset_verification_result)
5207 {
5208 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5209 }
5210
5211 m_context.getTestContext().getLog()
5212 << tcu::TestLog::Message << "Uniform: " << it_uniform_details->m_name
5213 << " has offset: " << uniform_offset << ". Expected offset: " << expected_offset
5214 << tcu::TestLog::EndMessage;
5215
5216 offset_verification_result = false;
5217 }
5218 }
5219 }
5220
5221 /* Update uniform buffer with prepared data */
5222 gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_buffer_id);
5223 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5224
5225 gl.bufferData(GL_UNIFORM_BUFFER, buffer_size, &buffer_data[0], GL_STATIC_DRAW);
5226 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5227
5228 /* Bind uniform buffer as data source for named uniform block */
5229 gl.bindBufferRange(GL_UNIFORM_BUFFER, 0 /* index */, m_uniform_buffer_id, 0, buffer_size);
5230 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
5231
5232 gl.uniformBlockBinding(program_info.m_program_object_id, program_info.m_uniform_block_index, 0 /* binding */);
5233 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformBlockBinding");
5234
5235 /* Done */
5236 return offset_verification_result;
5237 }
5238
5239 /** Prepare data, execute draw call and verify results
5240 *
5241 * @param uniform_data_layout
5242 *
5243 * @return true if test pass, false otherwise
5244 **/
test(uniformDataLayout uniform_data_layout) const5245 bool GPUShaderFP64Test3::test(uniformDataLayout uniform_data_layout) const
5246 {
5247 bool are_offsets_verified = (STD140 == uniform_data_layout);
5248 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5249 bool offset_verification_result = true;
5250 const programInfo& program_info = getProgramInfo(uniform_data_layout);
5251 bool result = true;
5252
5253 /* Set up program */
5254 gl.useProgram(program_info.m_program_object_id);
5255 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5256
5257 /* Prepare uniform buffer */
5258 offset_verification_result = prepareUniformBuffer(program_info, are_offsets_verified);
5259
5260 if (true == are_offsets_verified && false == offset_verification_result)
5261 {
5262 /* Offsets verification failure was already reported, add info about buffer layout */
5263 m_context.getTestContext().getLog() << tcu::TestLog::Message
5264 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5265 << tcu::TestLog::EndMessage;
5266
5267 result = false;
5268 }
5269
5270 /* Set up transform feedback buffer */
5271 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_transform_feedback_buffer_id, 0, 4 * sizeof(glw::GLint));
5272 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
5273
5274 /* Begin transform feedback */
5275 gl.beginTransformFeedback(GL_POINTS);
5276 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5277
5278 /* Execute draw call for singe vertex */
5279 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5280 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5281
5282 /* Stop transform feedback */
5283 gl.endTransformFeedback();
5284 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5285
5286 /* Verify results */
5287 if (false == verifyResults())
5288 {
5289 /* Result verificatioon failure was already reported, add info about layout */
5290 m_context.getTestContext().getLog() << tcu::TestLog::Message
5291 << "Uniform buffer layout: " << getUniformLayoutName(uniform_data_layout)
5292 << tcu::TestLog::EndMessage;
5293
5294 result = false;
5295 }
5296
5297 /* Done */
5298 return result;
5299 }
5300
testInit()5301 void GPUShaderFP64Test3::testInit()
5302 {
5303 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5304
5305 /* Uniform block declaration with std140 offsets calculated
5306 * | align | loc_req | begins | ends | offset in bytes | imp |
5307 * ivec3 unused1[3] | 4 | 12 | 0 | 12 | 0 | |
5308 * double double_value | 2 | 2 | 12 | 14 | 48 | XXX |
5309 * bool unused2 | 1 | 1 | 14 | 15 | 56 | |
5310 * dvec2 dvec2_value | 4 | 4 | 16 | 20 | 64 | XXX |
5311 * bvec3 unused3 | 4 | 4 | 20 | 24 | 80 | |
5312 * dvec3 dvec3_value | 8 | 8 | 24 | 32 | 96 | XXX |
5313 * int unused4[3] | 4 | 12 | 32 | 44 | 128 | |
5314 * dvec4 dvec4_value | 8 | 8 | 48 | 56 | 192 | XXX |
5315 * bool unused5 | 1 | 1 | 56 | 57 | 224 | |
5316 * bool unused6[2] | 4 | 8 | 60 | 68 | 240 | |
5317 * dmat2 dmat2_value | 4 | 8 | 68 | 76 | 272 | XXX |
5318 * dmat3 dmat3_value | 8 | 24 | 80 | 104 | 320 | XXX |
5319 * bool unused7 | 1 | 1 | 104 | 105 | 416 | |
5320 * dmat4 dmat4_value | 8 | 32 | 112 | 144 | 448 | XXX |
5321 * dmat2x3 dmat2x3_value | 8 | 16 | 144 | 160 | 576 | XXX |
5322 * uvec3 unused8 | 4 | 4 | 160 | 164 | 640 | |
5323 * dmat2x4 dmat2x4_value | 8 | 16 | 168 | 184 | 672 | XXX |
5324 * dmat3x2 dmat3x2_value | 4 | 12 | 184 | 196 | 736 | XXX |
5325 * bool unused9 | 1 | 1 | 196 | 197 | 784 | |
5326 * dmat3x4 dmat3x4_value | 8 | 24 | 200 | 224 | 800 | XXX |
5327 * int unused10 | 1 | 1 | 224 | 225 | 896 | |
5328 * dmat4x2 dmat4x2_value | 4 | 16 | 228 | 244 | 912 | XXX |
5329 * dmat4x3 dmat4x3_value | 8 | 32 | 248 | 280 | 992 | XXX |
5330 */
5331
5332 /* Prepare "double precision" unfiorms' details */
5333 m_uniform_details.push_back(uniformDetails(48 /* off */, "double_value" /* name */, 1 /* n_columns */,
5334 1 /* n_elements */, "double" /* type_name */));
5335 m_uniform_details.push_back(uniformDetails(64 /* off */, "dvec2_value" /* name */, 1 /* n_columns */,
5336 2 /* n_elements */, "dvec2" /* type_name */));
5337 m_uniform_details.push_back(uniformDetails(96 /* off */, "dvec3_value" /* name */, 1 /* n_columns */,
5338 3 /* n_elements */, "dvec3" /* type_name */));
5339 m_uniform_details.push_back(uniformDetails(192 /* off */, "dvec4_value" /* name */, 1 /* n_columns */,
5340 4 /* n_elements */, "dvec4" /* type_name */));
5341 m_uniform_details.push_back(uniformDetails(272 /* off */, "dmat2_value" /* name */, 2 /* n_columns */,
5342 4 /* n_elements */, "dmat2" /* type_name */));
5343 m_uniform_details.push_back(uniformDetails(320 /* off */, "dmat3_value" /* name */, 3 /* n_columns */,
5344 9 /* n_elements */, "dmat3" /* type_name */));
5345 m_uniform_details.push_back(uniformDetails(448 /* off */, "dmat4_value" /* name */, 4 /* n_columns */,
5346 16 /* n_elements */, "dmat4" /* type_name */));
5347 m_uniform_details.push_back(uniformDetails(576 /* off */, "dmat2x3_value" /* name */, 2 /* n_columns */,
5348 6 /* n_elements */, "dmat2x3" /* type_name */));
5349 m_uniform_details.push_back(uniformDetails(672 /* off */, "dmat2x4_value" /* name */, 2 /* n_columns */,
5350 8 /* n_elements */, "dmat2x4" /* type_name */));
5351 m_uniform_details.push_back(uniformDetails(736 /* off */, "dmat3x2_value" /* name */, 3 /* n_columns */,
5352 6 /* n_elements */, "dmat3x2" /* type_name */));
5353 m_uniform_details.push_back(uniformDetails(800 /* off */, "dmat3x4_value" /* name */, 3 /* n_columns */,
5354 12 /* n_elements */, "dmat3x4" /* type_name */));
5355 m_uniform_details.push_back(uniformDetails(912 /* off */, "dmat4x2_value" /* name */, 4 /* n_columns */,
5356 8 /* n_elements */, "dmat4x2" /* type_name */));
5357 m_uniform_details.push_back(uniformDetails(992 /* off */, "dmat4x3_value" /* name */, 4 /* n_columns */,
5358 12 /* n_elements */, "dmat4x3" /* type_name */));
5359
5360 /* Get random values for getExpectedValue */
5361 m_base_element = (glw::GLdouble)(rand() % 13);
5362 m_base_type_ordinal = (glw::GLdouble)(rand() % 213);
5363
5364 /* Prepare programInfos for all buffer layouts */
5365 prepareProgram(m_packed_program, PACKED);
5366 prepareProgram(m_shared_program, SHARED);
5367 prepareProgram(m_std140_program, STD140);
5368
5369 /* Generate buffers */
5370 gl.genBuffers(1, &m_transform_feedback_buffer_id);
5371 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5372
5373 gl.genBuffers(1, &m_uniform_buffer_id);
5374 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
5375
5376 /* Prepare transform feedback buffer */
5377 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
5378 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
5379
5380 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 4 * sizeof(glw::GLint), 0 /* data */, GL_DYNAMIC_COPY);
5381 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
5382
5383 /* Prepare texture for color attachment 0 */
5384 gl.genTextures(1, &m_color_texture_id);
5385 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
5386
5387 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5388 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5389
5390 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_R32I, 1 /* width */, 1 /* height */);
5391 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
5392
5393 /* Prepare FBO with color attachment 0 */
5394 gl.genFramebuffers(1, &m_framebuffer_id);
5395 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
5396
5397 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_framebuffer_id);
5398 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
5399
5400 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_texture_id,
5401 0 /* level */);
5402 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture2D");
5403
5404 gl.viewport(0 /* x */, 0 /* y */, 1 /* width */, 1 /* height */);
5405 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
5406
5407 /* Prepare VAO */
5408 gl.genVertexArrays(1, &m_vertex_array_object_id);
5409 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
5410
5411 gl.bindVertexArray(m_vertex_array_object_id);
5412 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
5413
5414 /* Tesselation patch set up */
5415 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5416 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5417 }
5418
5419 /** Verify contents of transform feedback buffer and framebuffer's color attachment 0
5420 *
5421 * @return true if all values are as expected, false otherwise
5422 **/
verifyResults() const5423 bool GPUShaderFP64Test3::verifyResults() const
5424 {
5425 glw::GLint* feedback_data = 0;
5426 bool fragment_shader_result = false;
5427 bool geometry_shader_result = false;
5428 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5429 bool tess_ctrl_shader_result = false;
5430 bool tess_eval_shader_result = false;
5431 bool vertex_shader_result = false;
5432
5433 /* Prepare storage for testure data */
5434 std::vector<glw::GLint> image_data;
5435 image_data.resize(1);
5436
5437 /* Get texture contents */
5438 gl.bindTexture(GL_TEXTURE_2D, m_color_texture_id);
5439 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
5440
5441 gl.getTexImage(GL_TEXTURE_2D, 0 /* level */, GL_RED_INTEGER, GL_INT, &image_data[0]);
5442 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
5443
5444 /* Get transform feedback data */
5445 feedback_data = (glw::GLint*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
5446 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
5447
5448 /* Verify results */
5449 fragment_shader_result = (m_result_success == image_data[0]);
5450 geometry_shader_result = (m_result_success == feedback_data[0]);
5451 tess_ctrl_shader_result = (m_result_success == feedback_data[1]);
5452 tess_eval_shader_result = (m_result_success == feedback_data[2]);
5453 vertex_shader_result = (m_result_success == feedback_data[3]);
5454
5455 /* Unmap transform feedback buffer */
5456 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5457 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
5458
5459 /* Set result */
5460 if (true != (fragment_shader_result && geometry_shader_result && tess_ctrl_shader_result &&
5461 tess_eval_shader_result && vertex_shader_result))
5462 {
5463 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error" << tcu::TestLog::EndMessage;
5464
5465 m_context.getTestContext().getLog() << tcu::TestLog::Message
5466 << "Vertex shader stage result: " << vertex_shader_result
5467 << tcu::TestLog::EndMessage;
5468
5469 m_context.getTestContext().getLog() << tcu::TestLog::Message
5470 << "Tesselation control shader stage result: " << tess_ctrl_shader_result
5471 << tcu::TestLog::EndMessage;
5472
5473 m_context.getTestContext().getLog() << tcu::TestLog::Message
5474 << "Tesselation evaluation shader stage result: " << tess_eval_shader_result
5475 << tcu::TestLog::EndMessage;
5476
5477 m_context.getTestContext().getLog() << tcu::TestLog::Message
5478 << "Geometry shader stage result: " << geometry_shader_result
5479 << tcu::TestLog::EndMessage;
5480
5481 m_context.getTestContext().getLog() << tcu::TestLog::Message
5482 << "Fragment shader stage result: " << fragment_shader_result
5483 << tcu::TestLog::EndMessage;
5484
5485 return false;
5486 }
5487 else
5488 {
5489 return true;
5490 }
5491 }
5492
5493 /** Write main routine of <shader_stage> shader to stream
5494 *
5495 * @param stream Output stream with source code of shader
5496 * @param shader_stage Shader stage
5497 **/
writeMainBody(std::ostream & stream,shaderStage shader_stage) const5498 void GPUShaderFP64Test3::writeMainBody(std::ostream& stream, shaderStage shader_stage) const
5499 {
5500 glw::GLuint type_ordinal = 1;
5501 const glw::GLchar* varying_name = "";
5502
5503 /* Select name for varying that will hold result of "that" shader_stage */
5504 switch (shader_stage)
5505 {
5506 case FRAGMENT_SHADER:
5507 varying_name = m_varying_name_fs_out_fs_result;
5508 break;
5509 case GEOMETRY_SHADER:
5510 varying_name = m_varying_name_gs_fs_gs_result;
5511 break;
5512 case TESS_CONTROL_SHADER:
5513 varying_name = m_varying_name_tcs_tes_tcs_result;
5514 break;
5515 case TESS_EVAL_SHADER:
5516 varying_name = m_varying_name_tes_gs_tes_result;
5517 break;
5518 case VERTEX_SHADER:
5519 varying_name = m_varying_name_vs_tcs_vs_result;
5520 break;
5521 }
5522
5523 /* void main() */
5524 stream << "void main()\n"
5525 "{\n";
5526
5527 /* Tesselation levels output */
5528 if (TESS_CONTROL_SHADER == shader_stage)
5529 {
5530 stream << "gl_TessLevelOuter[0] = 1.0;\n"
5531 "gl_TessLevelOuter[1] = 1.0;\n"
5532 "gl_TessLevelOuter[2] = 1.0;\n"
5533 "gl_TessLevelOuter[3] = 1.0;\n"
5534 "gl_TessLevelInner[0] = 1.0;\n"
5535 "gl_TessLevelInner[1] = 1.0;\n"
5536 "\n";
5537 }
5538
5539 /* For each "double precision" uniform
5540 *
5541 * [else] if (TYPE_NAME(PREDIFINED_VALUES) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5542 * {
5543 * VARYING_NAME = m_result_failure;
5544 * }
5545 */
5546 for (std::vector<uniformDetails>::const_iterator it = m_uniform_details.begin(), end = m_uniform_details.end();
5547 end != it; ++it, ++type_ordinal)
5548 {
5549 stream << " ";
5550
5551 /* First comparison is done with if, next with else if */
5552 if (1 != type_ordinal)
5553 {
5554 stream << "else ";
5555 }
5556
5557 /* if (TYPE_NAME( */
5558 stream << "if (" << it->m_type_name << "(";
5559
5560 /* PREDIFINED_VALUES */
5561 for (glw::GLuint element = 0; element < it->m_n_elements; ++element)
5562 {
5563 stream << getExpectedValue(type_ordinal, element);
5564
5565 /* Separate with comma */
5566 if (it->m_n_elements != element + 1)
5567 {
5568 stream << ", ";
5569 }
5570 }
5571
5572 /*
5573 * ) != NAMED_UNIFORM_BLOCK_NAME.UNIFORM_NAME)
5574 * {
5575 * VARYING_NAME
5576 */
5577 stream << ") != " << m_uniform_block_instance_name << "." << it->m_name << ")\n"
5578 " {\n"
5579 " "
5580 << varying_name;
5581
5582 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5583 if (TESS_CONTROL_SHADER == shader_stage)
5584 {
5585 stream << "[gl_InvocationID]";
5586 }
5587
5588 /*
5589 * = m_result_failure;
5590 * }
5591 */
5592 stream << " = " << m_result_failure << ";\n"
5593 << " }\n";
5594 }
5595
5596 /* If all comparisons are ok
5597 *
5598 * else
5599 * {
5600 * VARYING_NAME = m_result_success;
5601 * }
5602 */
5603
5604 /*
5605 * else
5606 * {
5607 * VARYING_NAME
5608 */
5609 stream << " else\n"
5610 " {\n"
5611 " "
5612 << varying_name;
5613
5614 /* Tesselation control outputs have to be arrays indexed with gl_InvocationID */
5615 if (TESS_CONTROL_SHADER == shader_stage)
5616 {
5617 stream << "[gl_InvocationID]";
5618 }
5619
5620 /*
5621 * = m_result_success;
5622 * }
5623 *
5624 */
5625 stream << " = " << m_result_success << ";\n"
5626 << " }\n"
5627 << "\n";
5628
5629 /* For each pair of "input/output" varyings
5630 *
5631 * OUTPUT_VARYING_NAME = INPUT_VARYING_NAME;
5632 **/
5633 writeVaryingPassthrough(stream, shader_stage);
5634
5635 /* Geometry shader have to emit vertex */
5636 if (GEOMETRY_SHADER == shader_stage)
5637 {
5638 stream << "\n"
5639 "gl_Position = vec4(0.0f, 0.0f, 0.0f, 1.0f);"
5640 "EmitVertex();\n"
5641 "EndPrimitive();\n";
5642 }
5643
5644 /* Close scope of main */
5645 stream << "}\n\n";
5646 }
5647
5648 /** Write shader preamble to stream
5649 *
5650 * @param stream Output stream with source code of shader
5651 * @param shader_stage Shader stage
5652 **/
writePreamble(std::ostream & stream,shaderStage shader_stage) const5653 void GPUShaderFP64Test3::writePreamble(std::ostream& stream, shaderStage shader_stage) const
5654 {
5655 stream << "#version 400 core\n"
5656 "\n"
5657 "precision highp float;\n"
5658 "\n";
5659
5660 switch (shader_stage)
5661 {
5662 case FRAGMENT_SHADER:
5663 break;
5664 case GEOMETRY_SHADER:
5665 stream << "layout(points) in;\n"
5666 "layout(points, max_vertices = 1) out;\n"
5667 "\n";
5668 break;
5669 case TESS_CONTROL_SHADER:
5670 stream << "layout(vertices = 1) out;\n"
5671 "\n";
5672 break;
5673 case TESS_EVAL_SHADER:
5674 stream << "layout(isolines, point_mode) in;\n"
5675 "\n";
5676 break;
5677 case VERTEX_SHADER:
5678 break;
5679 }
5680 }
5681
5682 /** Write name uniform blcok definition with specific layout to stream
5683 *
5684 * @param stream Output stream with source code of shader
5685 * @param uniform_data_layout Buffer layout
5686 **/
writeUniformBlock(std::ostream & stream,uniformDataLayout uniform_data_layout) const5687 void GPUShaderFP64Test3::writeUniformBlock(std::ostream& stream, uniformDataLayout uniform_data_layout) const
5688 {
5689 const glw::GLchar* layout = getUniformLayoutName(uniform_data_layout);
5690
5691 stream << "layout(" << layout << ") uniform " << m_uniform_block_name << "\n"
5692 "{\n"
5693 " ivec3 unused1[3];\n"
5694 " double double_value;\n"
5695 " bool unused2;\n"
5696 " dvec2 dvec2_value;\n"
5697 " bvec3 unused3;\n"
5698 " dvec3 dvec3_value;\n"
5699 " int unused4[3];\n"
5700 " dvec4 dvec4_value;\n"
5701 " bool unused5;\n"
5702 " bool unused6[2];\n"
5703 " dmat2 dmat2_value;\n"
5704 " dmat3 dmat3_value;\n"
5705 " bool unused7;\n"
5706 " dmat4 dmat4_value;\n"
5707 " dmat2x3 dmat2x3_value;\n"
5708 " uvec3 unused8;\n"
5709 " dmat2x4 dmat2x4_value;\n"
5710 " dmat3x2 dmat3x2_value;\n"
5711 " bool unused9;\n"
5712 " dmat3x4 dmat3x4_value;\n"
5713 " int unused10;\n"
5714 " dmat4x2 dmat4x2_value;\n"
5715 " dmat4x3 dmat4x3_value;\n"
5716 "} "
5717 << m_uniform_block_instance_name << ";\n";
5718
5719 stream << "\n";
5720 }
5721
5722 /** Write definitions of varyings specific for given <shader_stage> to stream
5723 *
5724 * @param stream Output stream with source code of shader
5725 * @param shader_stage Shader stage
5726 **/
writeVaryingDeclarations(std::ostream & stream,shaderStage shader_stage) const5727 void GPUShaderFP64Test3::writeVaryingDeclarations(std::ostream& stream, shaderStage shader_stage) const
5728 {
5729 static const glw::GLchar* const varying_type = "int";
5730
5731 switch (shader_stage)
5732 {
5733 case FRAGMENT_SHADER:
5734
5735 /* In */
5736 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5737 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5738 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5739 stream << "flat in " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5740
5741 stream << "\n";
5742
5743 /* Out */
5744 stream << "layout (location = 0) out " << varying_type << " " << m_varying_name_fs_out_fs_result << ";\n";
5745
5746 break;
5747
5748 case GEOMETRY_SHADER:
5749
5750 /* In */
5751 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tcs_result << "[];\n";
5752 stream << "in " << varying_type << " " << m_varying_name_tes_gs_tes_result << "[];\n";
5753 stream << "in " << varying_type << " " << m_varying_name_tes_gs_vs_result << "[];\n";
5754
5755 stream << "\n";
5756
5757 /* Out */
5758 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_gs_result << ";\n";
5759 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tcs_result << ";\n";
5760 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_tes_result << ";\n";
5761 stream << "flat out " << varying_type << " " << m_varying_name_gs_fs_vs_result << ";\n";
5762
5763 break;
5764
5765 case TESS_CONTROL_SHADER:
5766
5767 /* In */
5768 stream << "in " << varying_type << " " << m_varying_name_vs_tcs_vs_result << "[];\n";
5769
5770 stream << "\n";
5771
5772 /* Out */
5773 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5774 stream << "out " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5775
5776 break;
5777
5778 case TESS_EVAL_SHADER:
5779
5780 /* In */
5781 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_tcs_result << "[];\n";
5782 stream << "in " << varying_type << " " << m_varying_name_tcs_tes_vs_result << "[];\n";
5783
5784 stream << "\n";
5785
5786 /* Out */
5787 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tcs_result << ";\n";
5788 stream << "out " << varying_type << " " << m_varying_name_tes_gs_tes_result << ";\n";
5789 stream << "out " << varying_type << " " << m_varying_name_tes_gs_vs_result << ";\n";
5790
5791 break;
5792
5793 case VERTEX_SHADER:
5794
5795 /* Out */
5796 stream << "out " << varying_type << " " << m_varying_name_vs_tcs_vs_result << ";\n";
5797
5798 break;
5799 }
5800
5801 stream << "\n";
5802 }
5803
5804 /** Write passthrough code of "input/output" varying pairs to stream
5805 *
5806 * @param stream Output stream with source code of shader
5807 * @param shader_stage Shader stage
5808 **/
writeVaryingPassthrough(std::ostream & stream,shaderStage shader_stage) const5809 void GPUShaderFP64Test3::writeVaryingPassthrough(std::ostream& stream, shaderStage shader_stage) const
5810 {
5811 switch (shader_stage)
5812 {
5813 case FRAGMENT_SHADER:
5814 break;
5815
5816 case GEOMETRY_SHADER:
5817
5818 stream << " " << m_varying_name_gs_fs_tcs_result << " = " << m_varying_name_tes_gs_tcs_result << "[0];\n";
5819 stream << " " << m_varying_name_gs_fs_tes_result << " = " << m_varying_name_tes_gs_tes_result << "[0];\n";
5820 stream << " " << m_varying_name_gs_fs_vs_result << " = " << m_varying_name_tes_gs_vs_result << "[0];\n";
5821
5822 break;
5823
5824 case TESS_CONTROL_SHADER:
5825
5826 stream << " " << m_varying_name_tcs_tes_vs_result
5827 << "[gl_InvocationID] = " << m_varying_name_vs_tcs_vs_result << "[0];\n";
5828
5829 break;
5830
5831 case TESS_EVAL_SHADER:
5832
5833 stream << " " << m_varying_name_tes_gs_tcs_result << " = " << m_varying_name_tcs_tes_tcs_result << "[0];\n";
5834 stream << " " << m_varying_name_tes_gs_vs_result << " = " << m_varying_name_tcs_tes_vs_result << "[0];\n";
5835
5836 break;
5837
5838 case VERTEX_SHADER:
5839
5840 break;
5841 }
5842 }
5843
5844 /** Constructor. Sets all uniform locations to -1 and sets all
5845 * values to 0.
5846 */
_data()5847 GPUShaderFP64Test4::_data::_data()
5848 {
5849 memset(&uniform_double, 0, sizeof(uniform_double));
5850 memset(uniform_dvec2, 0, sizeof(uniform_dvec2));
5851 memset(uniform_dvec2_arr, 0, sizeof(uniform_dvec2_arr));
5852 memset(uniform_dvec3, 0, sizeof(uniform_dvec3));
5853 memset(uniform_dvec3_arr, 0, sizeof(uniform_dvec3_arr));
5854 memset(uniform_dvec4, 0, sizeof(uniform_dvec4));
5855 memset(uniform_dvec4_arr, 0, sizeof(uniform_dvec4_arr));
5856
5857 uniform_location_double = -1;
5858 uniform_location_double_arr[0] = -1;
5859 uniform_location_double_arr[1] = -1;
5860 uniform_location_dvec2 = -1;
5861 uniform_location_dvec2_arr[0] = -1;
5862 uniform_location_dvec2_arr[1] = -1;
5863 uniform_location_dvec3 = -1;
5864 uniform_location_dvec3_arr[0] = -1;
5865 uniform_location_dvec3_arr[1] = -1;
5866 uniform_location_dvec4 = -1;
5867 uniform_location_dvec4_arr[0] = -1;
5868 uniform_location_dvec4_arr[1] = -1;
5869 }
5870
5871 /** Constructor
5872 *
5873 * @param context Rendering context.
5874 */
GPUShaderFP64Test4(deqp::Context & context)5875 GPUShaderFP64Test4::GPUShaderFP64Test4(deqp::Context& context)
5876 : TestCase(context, "state_query", "Verifies glGet*() calls, as well as \"program interface query\"-specific tools"
5877 " report correct properties of & values assigned to double-precision uniforms.")
5878 , m_has_test_passed(true)
5879 , m_uniform_name_buffer(0)
5880 , m_cs_id(0)
5881 , m_fs_id(0)
5882 , m_gs_id(0)
5883 , m_po_cs_id(0)
5884 , m_po_noncs_id(0)
5885 , m_tc_id(0)
5886 , m_te_id(0)
5887 , m_vs_id(0)
5888 {
5889 /* Left blank intentionally */
5890 }
5891
5892 /** Deinitializes all GL objects, as well as releases all bufers, that may
5893 * have beenallocated or created during test execution.
5894 **/
deinit()5895 void GPUShaderFP64Test4::deinit()
5896 {
5897 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5898
5899 if (m_cs_id != 0)
5900 {
5901 gl.deleteShader(m_cs_id);
5902
5903 m_cs_id = 0;
5904 }
5905
5906 if (m_fs_id != 0)
5907 {
5908 gl.deleteShader(m_fs_id);
5909
5910 m_fs_id = 0;
5911 }
5912
5913 if (m_gs_id != 0)
5914 {
5915 gl.deleteShader(m_gs_id);
5916
5917 m_gs_id = 0;
5918 }
5919
5920 if (m_po_cs_id != 0)
5921 {
5922 gl.deleteProgram(m_po_cs_id);
5923
5924 m_po_cs_id = 0;
5925 }
5926
5927 if (m_po_noncs_id != 0)
5928 {
5929 gl.deleteProgram(m_po_noncs_id);
5930
5931 m_po_noncs_id = 0;
5932 }
5933
5934 if (m_tc_id != 0)
5935 {
5936 gl.deleteShader(m_tc_id);
5937
5938 m_tc_id = 0;
5939 }
5940
5941 if (m_te_id != 0)
5942 {
5943 gl.deleteShader(m_te_id);
5944
5945 m_te_id = 0;
5946 }
5947
5948 if (m_uniform_name_buffer != DE_NULL)
5949 {
5950 delete[] m_uniform_name_buffer;
5951
5952 m_uniform_name_buffer = DE_NULL;
5953 }
5954
5955 if (m_vs_id != 0)
5956 {
5957 gl.deleteShader(m_vs_id);
5958
5959 m_vs_id = 0;
5960 }
5961 }
5962
5963 /** Generates double-precision values for all uniforms defined for all program objects
5964 * used by the test.
5965 *
5966 * This function DOES NOT use any GL API. It only calculates & stores the values
5967 * in internal storage for further usage.
5968 */
generateUniformValues()5969 void GPUShaderFP64Test4::generateUniformValues()
5970 {
5971 _stage_data* stages[] = { &m_data_cs, &m_data_fs, &m_data_gs, &m_data_tc, &m_data_te, &m_data_vs };
5972 const unsigned int n_stages = sizeof(stages) / sizeof(stages[0]);
5973
5974 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
5975 {
5976 _stage_data* stage_ptr = stages[n_stage];
5977
5978 /* Iterate through all uniform components and assign them double values */
5979 double* double_ptrs[] = {
5980 &stage_ptr->uniform_structure_arrays[0].uniform_double,
5981 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 0,
5982 stage_ptr->uniform_structure_arrays[0].uniform_double_arr + 1,
5983 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 0,
5984 stage_ptr->uniform_structure_arrays[0].uniform_dvec2 + 1,
5985 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 0,
5986 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 1,
5987 stage_ptr->uniform_structure_arrays[0].uniform_dvec3 + 2,
5988 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 0,
5989 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 1,
5990 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 2,
5991 stage_ptr->uniform_structure_arrays[0].uniform_dvec4 + 3,
5992 &stage_ptr->uniform_structure_arrays[1].uniform_double,
5993 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 0,
5994 stage_ptr->uniform_structure_arrays[1].uniform_double_arr + 1,
5995 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 0,
5996 stage_ptr->uniform_structure_arrays[1].uniform_dvec2 + 1,
5997 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 0,
5998 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 1,
5999 stage_ptr->uniform_structure_arrays[1].uniform_dvec3 + 2,
6000 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 0,
6001 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 1,
6002 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 2,
6003 stage_ptr->uniform_structure_arrays[1].uniform_dvec4 + 3,
6004 &stage_ptr->uniforms.uniform_double,
6005 stage_ptr->uniforms.uniform_double_arr + 0,
6006 stage_ptr->uniforms.uniform_double_arr + 1,
6007 stage_ptr->uniforms.uniform_dvec2 + 0,
6008 stage_ptr->uniforms.uniform_dvec2 + 1,
6009 stage_ptr->uniforms.uniform_dvec2_arr + 0,
6010 stage_ptr->uniforms.uniform_dvec2_arr + 1,
6011 stage_ptr->uniforms.uniform_dvec2_arr + 2,
6012 stage_ptr->uniforms.uniform_dvec2_arr + 3,
6013 stage_ptr->uniforms.uniform_dvec3 + 0,
6014 stage_ptr->uniforms.uniform_dvec3 + 1,
6015 stage_ptr->uniforms.uniform_dvec3 + 2,
6016 stage_ptr->uniforms.uniform_dvec3_arr + 0,
6017 stage_ptr->uniforms.uniform_dvec3_arr + 1,
6018 stage_ptr->uniforms.uniform_dvec3_arr + 2,
6019 stage_ptr->uniforms.uniform_dvec3_arr + 3,
6020 stage_ptr->uniforms.uniform_dvec3_arr + 4,
6021 stage_ptr->uniforms.uniform_dvec3_arr + 5,
6022 stage_ptr->uniforms.uniform_dvec4 + 0,
6023 stage_ptr->uniforms.uniform_dvec4 + 1,
6024 stage_ptr->uniforms.uniform_dvec4 + 2,
6025 stage_ptr->uniforms.uniform_dvec4 + 3,
6026 stage_ptr->uniforms.uniform_dvec4_arr + 0,
6027 stage_ptr->uniforms.uniform_dvec4_arr + 1,
6028 stage_ptr->uniforms.uniform_dvec4_arr + 2,
6029 stage_ptr->uniforms.uniform_dvec4_arr + 3,
6030 stage_ptr->uniforms.uniform_dvec4_arr + 4,
6031 stage_ptr->uniforms.uniform_dvec4_arr + 5,
6032 stage_ptr->uniforms.uniform_dvec4_arr + 6,
6033 stage_ptr->uniforms.uniform_dvec4_arr + 7,
6034 };
6035 const unsigned int n_double_ptrs = sizeof(double_ptrs) / sizeof(double_ptrs[0]);
6036
6037 for (unsigned int n_double_ptr = 0; n_double_ptr < n_double_ptrs; ++n_double_ptr)
6038 {
6039 double* double_ptr = double_ptrs[n_double_ptr];
6040
6041 /* Generate the value. Use magic numbers to generate a set of double-precision
6042 * floating-point numbers.
6043 */
6044 static int seed = 16762362;
6045
6046 *double_ptr = ((double)(seed % 1732)) / 125.7 * (((seed % 2) == 0) ? 1 : -1);
6047
6048 seed += 751;
6049 } /* for (all pointers to double variables) */
6050 } /* for (all stages) */
6051 }
6052
6053 /** Initializes all program & shader objects required to run the test. The function also
6054 * retrieves locations of all uniforms defined by both program objects.
6055 **/
initProgramObjects()6056 void GPUShaderFP64Test4::initProgramObjects()
6057 {
6058 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6059
6060 /* Create program & shader objects */
6061
6062 /* Compute shader support and GL 4.2 required */
6063 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
6064 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
6065 {
6066 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
6067 }
6068
6069 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
6070 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
6071 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
6072 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
6073 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
6074 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
6075
6076 /* m_cs_id is initialized only if compute shaders are supported */
6077 if (0 != m_cs_id)
6078 {
6079 m_po_cs_id = gl.createProgram();
6080 }
6081
6082 m_po_noncs_id = gl.createProgram();
6083 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
6084
6085 /* Configure compute shader body */
6086 const char* cs_body = "#version 420\n"
6087 "#extension GL_ARB_compute_shader : require\n"
6088 "\n"
6089 "layout(local_size_x = 2, local_size_y = 2, local_size_z = 2) in;\n"
6090 "\n"
6091 "layout(rgba32f) uniform image2D testImage;\n"
6092 "\n"
6093 "uniform double cs_double;\n"
6094 "uniform dvec2 cs_dvec2;\n"
6095 "uniform dvec3 cs_dvec3;\n"
6096 "uniform dvec4 cs_dvec4;\n"
6097 "uniform double cs_double_arr[2];\n"
6098 "uniform dvec2 cs_dvec2_arr [2];\n"
6099 "uniform dvec3 cs_dvec3_arr [2];\n"
6100 "uniform dvec4 cs_dvec4_arr [2];\n"
6101 "\n"
6102 "uniform struct cs_struct\n"
6103 "{\n"
6104 " double struct_double;\n"
6105 " dvec2 struct_dvec2;\n"
6106 " dvec3 struct_dvec3;\n"
6107 " dvec4 struct_dvec4;\n"
6108 "} cs_array[2];\n"
6109 "\n"
6110 "void main()\n"
6111 "{\n"
6112 " double tmp = cs_double * cs_dvec2.x * cs_dvec3.y "
6113 " * cs_dvec4.z *\n"
6114 " cs_double_arr[0] * cs_dvec2_arr[0].x * "
6115 "cs_dvec3_arr[0].z * cs_dvec4_arr[0].w *\n"
6116 " cs_double_arr[1] * cs_dvec2_arr[1].x * "
6117 "cs_dvec3_arr[1].z * cs_dvec4_arr[1].w *\n"
6118 " cs_array[0].struct_double * cs_array[0].struct_dvec2.y * "
6119 "cs_array[0].struct_dvec3.z * cs_array[0].struct_dvec4.w *\n"
6120 " cs_array[1].struct_double * cs_array[1].struct_dvec2.y * "
6121 "cs_array[1].struct_dvec3.z * cs_array[1].struct_dvec4.w;\n"
6122 "\n"
6123 " imageStore(testImage, ivec2(0, 0), (tmp > 1.0) ? vec4(1.0) : vec4(0.0) );\n"
6124 "}\n";
6125
6126 /* m_cs_id is initialized only if compute shaders are supported */
6127 if (0 != m_cs_id)
6128 {
6129 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body, DE_NULL /* length */);
6130 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6131 }
6132
6133 /* Configure vertex shader body */
6134 const char* vs_body = "#version 400\n"
6135 "\n"
6136 "uniform double vs_double;\n"
6137 "uniform dvec2 vs_dvec2;\n"
6138 "uniform dvec3 vs_dvec3;\n"
6139 "uniform dvec4 vs_dvec4;\n"
6140 "uniform double vs_double_arr[2];\n"
6141 "uniform dvec2 vs_dvec2_arr [2];\n"
6142 "uniform dvec3 vs_dvec3_arr [2];\n"
6143 "uniform dvec4 vs_dvec4_arr [2];\n"
6144 "\n"
6145 "uniform struct vs_struct\n"
6146 "{\n"
6147 " double struct_double;\n"
6148 " dvec2 struct_dvec2;\n"
6149 " dvec3 struct_dvec3;\n"
6150 " dvec4 struct_dvec4;\n"
6151 "} vs_array[2];\n"
6152 "\n"
6153 "void main()\n"
6154 "{\n"
6155 " if (vs_double * vs_dvec2.x * vs_dvec3.x "
6156 "* vs_dvec4.x *\n"
6157 " vs_double_arr[0] * vs_dvec2_arr[0].x * vs_dvec3_arr[0].x "
6158 "* vs_dvec4_arr[0].x *\n"
6159 " vs_double_arr[1] * vs_dvec2_arr[1].x * vs_dvec3_arr[1].x "
6160 "* vs_dvec4_arr[1].x *\n"
6161 " vs_array[0].struct_double * vs_array[0].struct_dvec2.x * vs_array[0].struct_dvec3.x "
6162 "* vs_array[0].struct_dvec4.x *\n"
6163 " vs_array[1].struct_double * vs_array[1].struct_dvec2.x * vs_array[1].struct_dvec3.x "
6164 "* vs_array[1].struct_dvec4.x > 1.0)\n"
6165 " {\n"
6166 " gl_Position = vec4(0);\n"
6167 " }\n"
6168 " else\n"
6169 " {\n"
6170 " gl_Position = vec4(1);\n"
6171 " }\n"
6172 "}\n";
6173
6174 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body, DE_NULL /* length */);
6175 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
6176
6177 /* Configure tessellation control shader body */
6178 const char* tc_body = "#version 400\n"
6179 "\n"
6180 "uniform double tc_double;\n"
6181 "uniform dvec2 tc_dvec2;\n"
6182 "uniform dvec3 tc_dvec3;\n"
6183 "uniform dvec4 tc_dvec4;\n"
6184 "uniform double tc_double_arr[2];\n"
6185 "uniform dvec2 tc_dvec2_arr [2];\n"
6186 "uniform dvec3 tc_dvec3_arr [2];\n"
6187 "uniform dvec4 tc_dvec4_arr [2];\n"
6188 "\n"
6189 "uniform struct tc_struct\n"
6190 "{\n"
6191 " double struct_double;\n"
6192 " dvec2 struct_dvec2;\n"
6193 " dvec3 struct_dvec3;\n"
6194 " dvec4 struct_dvec4;\n"
6195 "} tc_array[2];\n"
6196 "\n"
6197 "layout(vertices = 4) out;\n"
6198 "\n"
6199 "void main()\n"
6200 "{\n"
6201 " gl_TessLevelOuter[0] = (tc_double > 1.0) ? 2.0 : 3.0;\n"
6202 " gl_TessLevelOuter[1] = (tc_dvec2.x > 1.0) ? 3.0 : 4.0;\n"
6203 " gl_TessLevelOuter[2] = (tc_dvec3.x > 1.0) ? 4.0 : 5.0;\n"
6204 " gl_TessLevelOuter[3] = (tc_dvec4.x > 1.0) ? 5.0 : 6.0;\n"
6205 " gl_TessLevelInner[0] = (tc_double_arr[0] > 1.0) ? 6.0 : 7.0;\n"
6206 " gl_TessLevelInner[1] = (tc_double_arr[1] > 1.0) ? 7.0 : 8.0;\n"
6207 "\n"
6208 " if (tc_dvec2_arr[0].y * tc_dvec2_arr[1].y *\n"
6209 " tc_dvec3_arr[0].z * tc_dvec3_arr[1].z *\n"
6210 " tc_dvec4_arr[0].z * tc_dvec4_arr[1].z *\n"
6211 " tc_array[0].struct_double * tc_array[0].struct_dvec2.x * \n"
6212 " tc_array[0].struct_dvec3.y * tc_array[0].struct_dvec4.z * \n"
6213 " tc_array[1].struct_double * tc_array[1].struct_dvec2.x * \n"
6214 " tc_array[1].struct_dvec3.y * tc_array[1].struct_dvec4.z > 0.0)\n"
6215 " {\n"
6216 " gl_TessLevelInner[1] = 3.0;\n"
6217 " }\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 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6937 {
6938 glw::GLuint po_id = programs[n_program];
6939 unsigned int n_stages = 0;
6940 _stage_data** stage_data = DE_NULL;
6941
6942 if (po_id == m_po_cs_id)
6943 {
6944 n_stages = n_cs_stages;
6945 stage_data = cs_stages;
6946 }
6947 else
6948 {
6949 n_stages = n_noncs_stages;
6950 stage_data = noncs_stages;
6951 }
6952
6953 /* Skip compute shader program if not supported */
6954 if (0 == po_id)
6955 {
6956 continue;
6957 }
6958
6959 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6960 {
6961 /* Iterate through all uniforms */
6962 _stage_data* stage_ptr = stage_data[n_stage];
6963
6964 /* Set up arrays that we will guide the automated testing */
6965 const uniform_value_pair double_uniforms[] = {
6966 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6967 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6968 stage_ptr->uniforms.uniform_double_arr + 0),
6969 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6970 stage_ptr->uniforms.uniform_double_arr + 1),
6971 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6972 &stage_ptr->uniform_structure_arrays[0].uniform_double),
6973 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6974 &stage_ptr->uniform_structure_arrays[1].uniform_double)
6975 };
6976 const uniform_value_pair dvec2_uniforms[] = {
6977 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6978 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6979 stage_ptr->uniforms.uniform_dvec2_arr + 0),
6980 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6981 stage_ptr->uniforms.uniform_dvec2_arr + 2),
6982 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6983 stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6984 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6985 stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6986 };
6987 const uniform_value_pair dvec3_uniforms[] = {
6988 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6989 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6990 stage_ptr->uniforms.uniform_dvec3_arr + 0),
6991 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6992 stage_ptr->uniforms.uniform_dvec3_arr + 3),
6993 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
6994 stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
6995 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
6996 stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
6997 };
6998 const uniform_value_pair dvec4_uniforms[] = {
6999 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7000 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7001 stage_ptr->uniforms.uniform_dvec4_arr + 0),
7002 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7003 stage_ptr->uniforms.uniform_dvec4_arr + 4),
7004 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7005 stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7006 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7007 stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7008 };
7009
7010 /* Iterate over all uniforms and verify the values reported by the API */
7011 double returned_double_data[4];
7012 float returned_float_data[4];
7013 int returned_int_data[4];
7014 unsigned int returned_uint_data[4];
7015
7016 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7017 {
7018 const uniform_value_pair* current_uv_pairs = NULL;
7019 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7020 unsigned int n_pairs = 0;
7021
7022 switch (n_type)
7023 {
7024 case 0: /* double */
7025 {
7026 current_uv_pairs = double_uniforms;
7027 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7028
7029 break;
7030 }
7031
7032 case 1: /* dvec2 */
7033 {
7034 current_uv_pairs = dvec2_uniforms;
7035 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7036
7037 break;
7038 }
7039
7040 case 2: /* dvec3 */
7041 {
7042 current_uv_pairs = dvec3_uniforms;
7043 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7044
7045 break;
7046 }
7047
7048 case 3: /* dvec4 */
7049 {
7050 current_uv_pairs = dvec4_uniforms;
7051 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7052
7053 break;
7054 }
7055
7056 default:
7057 {
7058 TCU_FAIL("Invalid type index requested");
7059 }
7060 } /* switch (n_type) */
7061
7062 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7063 {
7064 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair];
7065 glw::GLint uniform_location = current_uv_pair.first;
7066 const double* uniform_value = current_uv_pair.second;
7067
7068 /* Retrieve the values from the GL implementation*/
7069 gl.getUniformdv(po_id, uniform_location, returned_double_data);
7070 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7071
7072 gl.getUniformfv(po_id, uniform_location, returned_float_data);
7073 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7074
7075 gl.getUniformiv(po_id, uniform_location, returned_int_data);
7076 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7077
7078 gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7079 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7080
7081 /* Make sure the values reported match the reference values */
7082 bool can_continue = true;
7083 const float epsilon = 1e-5f;
7084
7085 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7086 {
7087 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7088 {
7089 m_testCtx.getLog()
7090 << tcu::TestLog::Message
7091 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7092 << uniform_location << "]"
7093 " and component ["
7094 << n_component << "]"
7095 ": retrieved:["
7096 << returned_double_data[n_component] << "]"
7097 ", expected:["
7098 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7099
7100 result = false;
7101 }
7102
7103 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7104 {
7105 m_testCtx.getLog()
7106 << tcu::TestLog::Message
7107 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7108 << uniform_location << "]"
7109 " and component ["
7110 << n_component << "]"
7111 ": retrieved:["
7112 << returned_float_data[n_component] << "]"
7113 ", expected:["
7114 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7115
7116 result = false;
7117 }
7118
7119 /* ints */
7120 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7121 unsigned int rounded_uniform_value_uint =
7122 (unsigned int)(uniform_value[n_component] > 0.0) ?
7123 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7124 0;
7125
7126 if (returned_int_data[n_component] != rounded_uniform_value_sint)
7127 {
7128 m_testCtx.getLog()
7129 << tcu::TestLog::Message
7130 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7131 << uniform_location << "]"
7132 " and component ["
7133 << n_component << "]"
7134 ": retrieved:["
7135 << returned_int_data[n_component] << "]"
7136 ", expected:["
7137 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7138
7139 result = false;
7140 }
7141
7142 if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7143 {
7144 m_testCtx.getLog()
7145 << tcu::TestLog::Message
7146 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7147 << uniform_location << "]"
7148 " and component ["
7149 << n_component << "]"
7150 ": retrieved:["
7151 << returned_uint_data[n_component] << "]"
7152 ", expected:["
7153 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7154
7155 result = false;
7156 }
7157 } /* for (all components) */
7158 } /* for (all uniform+value pairs) */
7159 } /* for (all 4 uniform types) */
7160 } /* for (all shader stages) */
7161 } /* for (both program objects) */
7162
7163 /* All done! */
7164 return result;
7165 }
7166
7167 /** Constructor
7168 *
7169 * @param context Rendering context.
7170 */
GPUShaderFP64Test5(deqp::Context & context)7171 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7172 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7173 " floating-point variables work correctly")
7174 , m_base_value_bo_data(DE_NULL)
7175 , m_base_value_bo_id(0)
7176 , m_has_test_passed(true)
7177 , m_po_base_value_attribute_location(-1)
7178 , m_po_id(0)
7179 , m_vao_id(0)
7180 , m_vs_id(0)
7181 , m_xfb_bo_id(0)
7182 , m_xfb_bo_size(0)
7183 {
7184 /* Set up base value array (as per test spec) */
7185 m_base_values[0] = -25.12065f;
7186 m_base_values[1] = 0.0f;
7187 m_base_values[2] = 0.001f;
7188 m_base_values[3] = 1.0f;
7189 m_base_values[4] = 256.78901f;
7190
7191 /* Set up swizzle matrix */
7192 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7193 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7194 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7195 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7196 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7197 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7198 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7199 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7200 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7201 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7202 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7203 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7204 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7205 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7206 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7207 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7208 }
7209
deinit()7210 void GPUShaderFP64Test5::deinit()
7211 {
7212 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7213
7214 if (m_base_value_bo_data != DE_NULL)
7215 {
7216 delete[] m_base_value_bo_data;
7217
7218 m_base_value_bo_data = DE_NULL;
7219 }
7220
7221 if (m_base_value_bo_id != 0)
7222 {
7223 gl.deleteBuffers(1, &m_base_value_bo_id);
7224
7225 m_base_value_bo_id = 0;
7226 }
7227
7228 if (m_vao_id != 0)
7229 {
7230 gl.deleteVertexArrays(1, &m_vao_id);
7231
7232 m_vao_id = 0;
7233 }
7234
7235 if (m_xfb_bo_id != 0)
7236 {
7237 gl.deleteBuffers(1, &m_xfb_bo_id);
7238
7239 m_xfb_bo_id = 0;
7240 }
7241
7242 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7243 * take care of it here
7244 */
7245 deinitInteration();
7246 }
7247
7248 /** Deinitializes all buffers and GL objects that may have been generated
7249 * during test execution.
7250 **/
deinitInteration()7251 void GPUShaderFP64Test5::deinitInteration()
7252 {
7253 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7254
7255 if (m_po_id != 0)
7256 {
7257 gl.deleteProgram(m_po_id);
7258
7259 m_po_id = 0;
7260 }
7261
7262 if (m_vs_id != 0)
7263 {
7264 gl.deleteShader(m_vs_id);
7265
7266 m_vs_id = 0;
7267 }
7268 }
7269
7270 /** Executes a single test case iteration using user-provided test case descriptor.
7271 *
7272 * This function may throw a TestError exception if GL implementation misbehaves.
7273 *
7274 * @param test_case Test case descriptor to use.
7275 *
7276 * @return true if the values returned by GL implementation were found to be valid,
7277 * false otherwise.
7278 **/
executeIteration(const _test_case & test_case)7279 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7280 {
7281 bool result = true;
7282
7283 /* Convert the base values array to the type of input attribute we'll be using
7284 * for the iteration.
7285 */
7286 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7287
7288 if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7289 {
7290 /* bools are actually represented by ints, since bool varyings are not allowed */
7291 base_value_type = Utils::VARIABLE_TYPE_INT;
7292 }
7293
7294 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7295 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7296
7297 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7298
7299 unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7300
7301 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7302 {
7303 switch (base_value_type)
7304 {
7305 case Utils::VARIABLE_TYPE_DOUBLE:
7306 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7307 break;
7308 case Utils::VARIABLE_TYPE_FLOAT:
7309 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7310 break;
7311 case Utils::VARIABLE_TYPE_INT:
7312 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7313 break;
7314 case Utils::VARIABLE_TYPE_UINT:
7315 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7316 break;
7317
7318 default:
7319 {
7320 TCU_FAIL("Unrecognized base value type");
7321 }
7322 }
7323
7324 base_value_traveller_ptr += base_value_component_size;
7325 } /* for (all base values) */
7326
7327 /* Update buffer object storage with the data we've just finished preparing. */
7328 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7329
7330 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7331 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7332
7333 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7334 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7335
7336 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7337 * new data is interpreted correctly.
7338 */
7339 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7340 {
7341 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */
7342 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7343 0, /* stride */
7344 DE_NULL); /* pointer */
7345 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7346 }
7347 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7348 {
7349 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */
7350 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7351 DE_NULL); /* pointer */
7352 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7353 }
7354 else
7355 {
7356 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7357
7358 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7359 GL_DOUBLE, 0, /* stride */
7360 DE_NULL); /* pointer */
7361 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7362 }
7363
7364 gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7365 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7366
7367 /* Execute the draw call */
7368 gl.useProgram(m_po_id);
7369 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7370
7371 gl.beginTransformFeedback(GL_POINTS);
7372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7373 {
7374 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7375 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7376 }
7377 gl.endTransformFeedback();
7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7379
7380 /* Map the XFB buffer object into process space */
7381 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7382
7383 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7384 DE_ASSERT(xfb_data_ptr != NULL);
7385
7386 /* Verify the data */
7387 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7388
7389 /* Unmap the XFB BO */
7390 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7391 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7392
7393 /** Good to release the data buffer at this point */
7394 if (m_base_value_bo_data != DE_NULL)
7395 {
7396 delete[] m_base_value_bo_data;
7397
7398 m_base_value_bo_data = DE_NULL;
7399 }
7400
7401 /* All done */
7402 return result;
7403 }
7404
7405 /** Returns properties of a swizzle operator described by @param type swizzle type.
7406 *
7407 * @param out_swizzle_string Deref will be used to store a GLSL literal
7408 * corresponding to the specific swizzle operator.
7409 * Must not be NULL.
7410 * @param out_n_components Deref will be used to store the amount of components
7411 * used by the operator. Must not be NULL.
7412 * @param out_component_order Deref will be used to store up to 4 integer values,
7413 * corresponding to component indices described by the
7414 * operator for a particular position. Must not be NULL.
7415 **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7416 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7417 unsigned int* out_n_components, unsigned int* out_component_order)
7418 {
7419 unsigned int result_component_order[4] = { 0 };
7420 unsigned int result_n_components = 0;
7421 std::string result_swizzle_string;
7422
7423 switch (type)
7424 {
7425 case SWIZZLE_TYPE_NONE:
7426 {
7427 result_swizzle_string = "";
7428 result_n_components = 0;
7429
7430 break;
7431 }
7432
7433 case SWIZZLE_TYPE_XWZY:
7434 {
7435 result_swizzle_string = "xwzy";
7436 result_n_components = 4;
7437 result_component_order[0] = 0;
7438 result_component_order[1] = 3;
7439 result_component_order[2] = 2;
7440 result_component_order[3] = 1;
7441
7442 break;
7443 }
7444
7445 case SWIZZLE_TYPE_XZXY:
7446 {
7447 result_swizzle_string = "xzxy";
7448 result_n_components = 4;
7449 result_component_order[0] = 0;
7450 result_component_order[1] = 2;
7451 result_component_order[2] = 0;
7452 result_component_order[3] = 1;
7453
7454 break;
7455 }
7456
7457 case SWIZZLE_TYPE_XZY:
7458 {
7459 result_swizzle_string = "xzy";
7460 result_n_components = 3;
7461 result_component_order[0] = 0;
7462 result_component_order[1] = 2;
7463 result_component_order[2] = 1;
7464
7465 break;
7466 }
7467
7468 case SWIZZLE_TYPE_XZYW:
7469 {
7470 result_swizzle_string = "xzyw";
7471 result_n_components = 4;
7472 result_component_order[0] = 0;
7473 result_component_order[1] = 2;
7474 result_component_order[2] = 1;
7475 result_component_order[3] = 3;
7476
7477 break;
7478 }
7479
7480 case SWIZZLE_TYPE_Y:
7481 {
7482 result_swizzle_string = "y";
7483 result_n_components = 1;
7484 result_component_order[0] = 1;
7485
7486 break;
7487 }
7488
7489 case SWIZZLE_TYPE_YX:
7490 {
7491 result_swizzle_string = "yx";
7492 result_n_components = 2;
7493 result_component_order[0] = 1;
7494 result_component_order[1] = 0;
7495
7496 break;
7497 }
7498
7499 case SWIZZLE_TYPE_YXX:
7500 {
7501 result_swizzle_string = "yxx";
7502 result_n_components = 3;
7503 result_component_order[0] = 1;
7504 result_component_order[1] = 0;
7505 result_component_order[2] = 0;
7506
7507 break;
7508 }
7509
7510 case SWIZZLE_TYPE_YXXY:
7511 {
7512 result_swizzle_string = "yxxy";
7513 result_n_components = 4;
7514 result_component_order[0] = 1;
7515 result_component_order[1] = 0;
7516 result_component_order[2] = 0;
7517 result_component_order[3] = 1;
7518
7519 break;
7520 }
7521
7522 case SWIZZLE_TYPE_Z:
7523 {
7524 result_swizzle_string = "z";
7525 result_n_components = 1;
7526 result_component_order[0] = 2;
7527
7528 break;
7529 }
7530
7531 case SWIZZLE_TYPE_ZY:
7532 {
7533 result_swizzle_string = "zy";
7534 result_n_components = 2;
7535 result_component_order[0] = 2;
7536 result_component_order[1] = 1;
7537
7538 break;
7539 }
7540
7541 case SWIZZLE_TYPE_W:
7542 {
7543 result_swizzle_string = "w";
7544 result_n_components = 1;
7545 result_component_order[0] = 3;
7546
7547 break;
7548 }
7549
7550 case SWIZZLE_TYPE_WX:
7551 {
7552 result_swizzle_string = "wx";
7553 result_n_components = 2;
7554 result_component_order[0] = 3;
7555 result_component_order[1] = 0;
7556
7557 break;
7558 }
7559
7560 default:
7561 {
7562 TCU_FAIL("Unrecognized swizzle type");
7563 }
7564 } /* switch (type) */
7565
7566 if (out_swizzle_string != DE_NULL)
7567 {
7568 *out_swizzle_string = result_swizzle_string;
7569 }
7570
7571 if (out_n_components != DE_NULL)
7572 {
7573 *out_n_components = result_n_components;
7574 }
7575
7576 if (out_component_order != DE_NULL)
7577 {
7578 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7579 }
7580 }
7581
7582 /** Returns body of a vertex shader that should be used for particular test case,
7583 * given user-specified test case descriptor.
7584 *
7585 * @param test_case Descriptor to use for the query.
7586 *
7587 * @return Requested data.
7588 **/
getVertexShaderBody(const _test_case & test_case)7589 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7590 {
7591 std::stringstream result;
7592 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7593 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type);
7594 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7595 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7596 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type);
7597
7598 /* Add version preamble */
7599 result << "#version 420\n"
7600 "\n";
7601
7602 /* Declare output variables. Note that boolean output variables are not supported, so we need
7603 * to handle that special case correctly */
7604 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7605 {
7606 result << "out int result;\n";
7607 }
7608 else
7609 {
7610 result << "out " << dst_type_string << " result;\n";
7611 }
7612
7613 /* Declare input variables. Handle the bool case exclusively. */
7614 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7615 {
7616 /* Use ints for bools. We will cast them to bool in the code later. */
7617 result << "in int base_value;\n";
7618 }
7619 else
7620 {
7621 result << "in " << base_type_string << " base_value;\n";
7622 }
7623
7624 /* Declare main() and construct the value we will be casting from.
7625 *
7626 * Note: Addition operations on bool values cause an implicit conversion to int
7627 * which is not allowed. Hence, we skip these operations for this special
7628 * case.
7629 */
7630 result << "void main()\n"
7631 "{\n"
7632 << src_type_string << " lside_value = ";
7633
7634 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7635 {
7636 result << src_type_string << "(0 != ";
7637 }
7638 else
7639 {
7640 result << src_type_string << "(";
7641 }
7642
7643 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7644 {
7645 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7646 {
7647 result << "base_value + " << n_component;
7648
7649 if (n_component != (n_src_components - 1))
7650 {
7651 result << ", ";
7652 }
7653 } /* for (all components) */
7654 }
7655 else
7656 {
7657 DE_ASSERT(n_src_components == 1);
7658
7659 result << "base_value";
7660 }
7661
7662 result << ");\n";
7663
7664 /* Perform the casting operation. Add swizzle operator if possible. */
7665 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7666 {
7667 /* Handle the bool case exclusively */
7668 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7669 {
7670 result << "result = (bool(lside_value) == false) ? 0 : 1";
7671 }
7672 else
7673 {
7674 result << "result = (lside_value == false) ? 0 : 1";
7675 }
7676 }
7677 else
7678 {
7679 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7680 {
7681 result << "result = " << dst_type_string << "(lside_value)";
7682 }
7683 else
7684 {
7685 result << "result = lside_value";
7686 }
7687 }
7688
7689 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7690 {
7691 /* Add a swizzle operator */
7692 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7693 DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7694
7695 unsigned int swizzle_component_order[4] = { 0 };
7696 unsigned int swizzle_n_components = 0;
7697 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7698 std::string swizzle_string;
7699
7700 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7701
7702 if (swizzle_n_components > 0)
7703 {
7704 result << "." << swizzle_string;
7705 }
7706 }
7707
7708 /* Close the shader implementation. */
7709 result << ";\n"
7710 "}\n";
7711
7712 return result.str();
7713 }
7714
7715 /** Initializes program & shader objects needed to run the iteration, given
7716 * user-specified test case descriptor.
7717 *
7718 * This function can throw a TestError exception if a GL error is detected
7719 * during execution.
7720 *
7721 * @param test_case Descriptor to use for the iteration.
7722 **/
initIteration(_test_case & test_case)7723 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7724 {
7725 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7726
7727 /* Create program & shader objects */
7728 m_po_id = gl.createProgram();
7729 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7730
7731 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7732 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7733
7734 /* Configure shader body */
7735 std::string body = getVertexShaderBody(test_case);
7736 const char* body_raw_ptr = body.c_str();
7737
7738 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7739 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7740
7741 /* Store it in the test case descriptor for logging purposes */
7742 test_case.shader_body = body;
7743
7744 /* Compile the shader */
7745 glw::GLint compile_status = GL_FALSE;
7746
7747 gl.compileShader(m_vs_id);
7748 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7749
7750 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7751 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7752
7753 if (compile_status != GL_TRUE)
7754 {
7755 TCU_FAIL("Shader compilation failed");
7756 }
7757
7758 /* Attach the shader to the program obejct */
7759 gl.attachShader(m_po_id, m_vs_id);
7760 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7761
7762 /* Configure XFB for the program object */
7763 const char* xfb_varying_name = "result";
7764
7765 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7766 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7767
7768 /* Link the program object */
7769 glw::GLint link_status = GL_FALSE;
7770
7771 gl.linkProgram(m_po_id);
7772 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7773
7774 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7775 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7776
7777 if (link_status != GL_TRUE)
7778 {
7779 TCU_FAIL("Program linking failed");
7780 }
7781
7782 /* Retrieve attribute locations */
7783 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7784 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7785
7786 if (m_po_base_value_attribute_location == -1)
7787 {
7788 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7789 }
7790 }
7791
7792 /** Initializes GL objects used by all test cases.
7793 *
7794 * This function may throw a TestError exception if GL implementation reports
7795 * an error at any point.
7796 **/
initTest()7797 void GPUShaderFP64Test5::initTest()
7798 {
7799 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7800
7801 /* Generate buffer object IDs */
7802 gl.genBuffers(1, &m_base_value_bo_id);
7803 gl.genBuffers(1, &m_xfb_bo_id);
7804 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7805
7806 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7807 * will never eat up more than 1 double (as per test spec) and we will be drawing
7808 * as many points in a single draw call as there are defined in m_base_values array.
7809 */
7810 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7811
7812 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7813 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7814
7815 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7816 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7817
7818 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7819 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7820 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7821 */
7822 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7823
7824 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7825 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7826
7827 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7828 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7829
7830 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7831 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7832
7833 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7834 m_xfb_bo_size = xfb_bo_size;
7835
7836 /* Generate a vertex array object we will need to use for the draw calls */
7837 gl.genVertexArrays(1, &m_vao_id);
7838 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7839
7840 gl.bindVertexArray(m_vao_id);
7841 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7842 }
7843
7844 /** Executes test iteration.
7845 *
7846 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7847 */
iterate()7848 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7849 {
7850 /* Do not execute the test if GL_ARB_texture_view is not supported */
7851 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7852 {
7853 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7854 }
7855
7856 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7857 {
7858 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7859 }
7860
7861 /* Initialize GL objects needed to run the tests */
7862 initTest();
7863
7864 /* Build iteration array to run the tests in an automated manner */
7865 _test_case test_cases[] = {
7866 /* test case type */ /* source type */ /* destination type */
7867 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7868 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7869 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7870 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7871 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7872 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7873 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7874 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7875 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7876 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7877 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7878 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7879 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7880 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7881 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7882 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7883 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7884 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7885 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7886 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7887 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7888
7889 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7890 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7891 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7892 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7893 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7894 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7895 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7896 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7897 };
7898 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7899
7900 /* Execute all iterations */
7901 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7902 {
7903 _test_case& test_case = test_cases[n_test_case];
7904
7905 /* Initialize a program object we will use to perform the casting */
7906 initIteration(test_case);
7907
7908 /* Use the program object to XFB the results */
7909 m_has_test_passed &= executeIteration(test_case);
7910
7911 /* Release the GL Resource for this sub test */
7912 deinitInteration();
7913
7914 } /* for (all test cases) */
7915 /* We're done */
7916 if (m_has_test_passed)
7917 {
7918 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7919 }
7920 else
7921 {
7922 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7923 }
7924
7925 return STOP;
7926 }
7927
7928 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7929 * for which the data have been generated.
7930 *
7931 * @param data_ptr Buffer holding the data XFBed out by the shader.
7932 * @param test_case Descriptor of the test case, for which the vertex shader was
7933 * generated.
7934 *
7935 * @return true if the data were found to be valid, false otherwise.
7936 **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7937 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7938 {
7939 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
7940 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
7941 const float epsilon = 1e-5f;
7942 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7943 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7944 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7945 bool result = true;
7946 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE;
7947 unsigned int swizzle_order[4] = { 0 };
7948 const unsigned char* traveller_ptr = data_ptr;
7949
7950 if (!Utils::isMatrixVariableType(test_case.src_type))
7951 {
7952 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7953 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7954
7955 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7956
7957 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7958 DE_NULL, /* out_n_components */
7959 swizzle_order);
7960 }
7961
7962 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7963 {
7964 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7965 {
7966 unsigned int n_swizzled_component = n_result_component;
7967
7968 if (swizzle_operator != SWIZZLE_TYPE_NONE)
7969 {
7970 n_swizzled_component =
7971 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7972 }
7973
7974 switch (base_dst_type)
7975 {
7976 case Utils::VARIABLE_TYPE_BOOL:
7977 case Utils::VARIABLE_TYPE_INT:
7978 {
7979 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7980 double expected_value = ref_expected_value;
7981 int result_value = *((int*)traveller_ptr);
7982
7983 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7984 {
7985 if (expected_value != 0.0)
7986 {
7987 expected_value = 1.0;
7988 }
7989 }
7990
7991 if (result_value != (int)expected_value)
7992 {
7993 m_testCtx.getLog() << tcu::TestLog::Message
7994 << "Invalid boolean/integer value obtained when doing an "
7995 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
7996 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
7997 << "]"
7998 ", component index: ["
7999 << n_swizzled_component << "]"
8000 ", value: ["
8001 << ref_expected_value << "]"
8002 " to GLSL type ["
8003 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8004 ", retrieved value: ["
8005 << result_value << "]"
8006 ", expected value: ["
8007 << (int)expected_value << "]"
8008 ", shader used:\n"
8009 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8010
8011 result = false;
8012 }
8013
8014 traveller_ptr += sizeof(int);
8015 break;
8016 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8017
8018 case Utils::VARIABLE_TYPE_DOUBLE:
8019 {
8020 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8021 double expected_value = ref_expected_value;
8022 double result_value = *((double*)traveller_ptr);
8023
8024 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8025 {
8026 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8027 }
8028 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8029 {
8030 expected_value = (int)expected_value;
8031 }
8032 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8033 {
8034 // Negative values in base values array when converted to unsigned int will be ZERO
8035 // Addition operations done inside the shader in such cases will operate on ZERO rather
8036 // than the negative value being passed.
8037 // Replicate the sequence of conversion and addition operations done on the
8038 // shader input, to calculate the expected values in XFB data in the
8039 // problematic cases.
8040 if (expected_value < 0)
8041 {
8042 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8043 }
8044 expected_value = (unsigned int)expected_value;
8045 }
8046
8047 traveller_ptr += sizeof(double);
8048 if (de::abs(result_value - expected_value) > epsilon)
8049 {
8050 m_testCtx.getLog() << tcu::TestLog::Message
8051 << "Invalid double-precision floating-point value obtained when doing an "
8052 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8053 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8054 << "]"
8055 ", component index: ["
8056 << n_swizzled_component << "]"
8057 ", value: ["
8058 << ref_expected_value << "]"
8059 " to GLSL type ["
8060 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8061 ", retrieved value: ["
8062 << std::setprecision(16) << result_value << "]"
8063 ", expected value: ["
8064 << std::setprecision(16) << expected_value << "]"
8065 ", shader used:\n"
8066 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8067
8068 result = false;
8069 }
8070
8071 break;
8072 } /* VARIABLE_TYPE_DOUBLE case */
8073
8074 case Utils::VARIABLE_TYPE_FLOAT:
8075 {
8076 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8077 float expected_value = ref_expected_value;
8078 float result_value = *((float*)traveller_ptr);
8079
8080 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8081 {
8082 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8083 }
8084 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8085 {
8086 expected_value = (float)((int)expected_value);
8087 }
8088 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8089 {
8090 expected_value = (float)((unsigned int)expected_value);
8091 }
8092
8093 traveller_ptr += sizeof(float);
8094 if (de::abs(result_value - expected_value) > epsilon)
8095 {
8096 m_testCtx.getLog() << tcu::TestLog::Message
8097 << "Invalid single-precision floating-point value obtained when doing an "
8098 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8099 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8100 << "]"
8101 ", component index: ["
8102 << n_swizzled_component << "]"
8103 ", value: ["
8104 << ref_expected_value << "]"
8105 " to GLSL type ["
8106 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8107 ", retrieved value: ["
8108 << std::setprecision(16) << result_value << "]"
8109 ", expected value: ["
8110 << std::setprecision(16) << expected_value << "]"
8111 ", shader used:\n"
8112 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8113
8114 result = false;
8115 }
8116
8117 break;
8118 } /* VARIABLE_TYPE_FLOAT case */
8119
8120 case Utils::VARIABLE_TYPE_UINT:
8121 {
8122 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8123 double expected_value = ref_expected_value;
8124 unsigned int result_value = *((unsigned int*)traveller_ptr);
8125
8126 traveller_ptr += sizeof(unsigned int);
8127 if (result_value != (unsigned int)expected_value)
8128 {
8129 if (expected_value < 0.0)
8130 {
8131 // It is undefined to convert a negative floating-point value to an uint.
8132 break;
8133 }
8134
8135 m_testCtx.getLog() << tcu::TestLog::Message
8136 << "Invalid unsigned integer value obtained when doing an "
8137 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8138 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8139 << "]"
8140 ", component index: ["
8141 << n_swizzled_component << "]"
8142 ", value: ["
8143 << ref_expected_value << "]"
8144 " to GLSL type ["
8145 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8146 ", retrieved value: ["
8147 << result_value << "]"
8148 ", expected value: ["
8149 << (unsigned int)expected_value << "]"
8150 ", shader used:\n"
8151 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8152
8153 result = false;
8154 }
8155
8156 break;
8157 } /* VARIABLE_TYPE_UINT case */
8158
8159 default:
8160 {
8161 TCU_FAIL("Unrecognized variable type");
8162 }
8163 } /* switch (test_case.dst_type) */
8164 } /* for (all result components) */
8165 } /* for (all base values) */
8166
8167 return result;
8168 }
8169
8170 /** Constructor
8171 *
8172 * @param context Rendering context.
8173 */
GPUShaderFP64Test6(deqp::Context & context)8174 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8175 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8176 "during compilation time.")
8177 , m_cs_id(0)
8178 , m_fs_id(0)
8179 , m_gs_id(0)
8180 , m_tc_id(0)
8181 , m_te_id(0)
8182 , m_vs_id(0)
8183 , m_has_test_passed(true)
8184 {
8185 }
8186
8187 /** Deinitializes all buffers and GL objects that may have been generated
8188 * during test execution.
8189 **/
deinit()8190 void GPUShaderFP64Test6::deinit()
8191 {
8192 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8193
8194 if (m_cs_id != 0)
8195 {
8196 gl.deleteShader(m_cs_id);
8197
8198 m_cs_id = 0;
8199 }
8200
8201 if (m_fs_id != 0)
8202 {
8203 gl.deleteShader(m_fs_id);
8204
8205 m_fs_id = 0;
8206 }
8207
8208 if (m_gs_id != 0)
8209 {
8210 gl.deleteShader(m_gs_id);
8211
8212 m_gs_id = 0;
8213 }
8214
8215 if (m_tc_id != 0)
8216 {
8217 gl.deleteShader(m_tc_id);
8218
8219 m_tc_id = 0;
8220 }
8221
8222 if (m_te_id != 0)
8223 {
8224 gl.deleteShader(m_te_id);
8225
8226 m_te_id = 0;
8227 }
8228
8229 if (m_vs_id != 0)
8230 {
8231 gl.deleteShader(m_vs_id);
8232
8233 m_vs_id = 0;
8234 }
8235 }
8236
8237 /** Executes a single test case.
8238 *
8239 * This function can throw TestError exceptions if GL implementation reports
8240 * an error.
8241 *
8242 * @param test_case Test case descriptor.
8243 *
8244 * @return true if test case passed, false otherwise.
8245 **/
executeIteration(const _test_case & test_case)8246 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8247 {
8248 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8249 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8250 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8251 bool result = true;
8252 const char* stage_body = NULL;
8253 const char* stage_name = NULL;
8254
8255 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8256 {
8257 const glw::GLuint so_id = so_ids[n_so_id];
8258
8259 /* Skip compute shader if it is not supported */
8260 if (0 == so_id)
8261 {
8262 continue;
8263 }
8264
8265 /* Compile the shader */
8266 gl.compileShader(so_id);
8267 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8268
8269 /* Has the compilation failed as expected? */
8270 glw::GLint compile_status = GL_TRUE;
8271
8272 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8273 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8274
8275 if (compile_status == GL_TRUE)
8276 {
8277 /* What is the current stage's name? */
8278 if (so_id == m_cs_id)
8279 {
8280 stage_body = test_case.cs_shader_body.c_str();
8281 stage_name = "Compute shader";
8282 }
8283 else if (so_id == m_fs_id)
8284 {
8285 stage_body = test_case.fs_shader_body.c_str();
8286 stage_name = "Fragment shader";
8287 }
8288 else if (so_id == m_gs_id)
8289 {
8290 stage_body = test_case.gs_shader_body.c_str();
8291 stage_name = "Geometry shader";
8292 }
8293 else if (so_id == m_tc_id)
8294 {
8295 stage_body = test_case.tc_shader_body.c_str();
8296 stage_name = "Tessellation control shader";
8297 }
8298 else if (so_id == m_te_id)
8299 {
8300 stage_body = test_case.te_shader_body.c_str();
8301 stage_name = "Tessellation evaluation shader";
8302 }
8303 else if (so_id == m_vs_id)
8304 {
8305 stage_body = test_case.vs_shader_body.c_str();
8306 stage_name = "Vertex shader";
8307 }
8308 else
8309 {
8310 /* Doesn't make much sense to throw exceptions here so.. */
8311 stage_body = "";
8312 stage_name = "[?]";
8313 }
8314
8315 /* This shader should have never compiled successfully! */
8316 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8317 << " has been compiled successfully, even though the shader was malformed."
8318 " Following is shader body:\n"
8319 << stage_body << tcu::TestLog::EndMessage;
8320
8321 result = false;
8322 }
8323 } /* for (all shader objects) */
8324
8325 return result;
8326 }
8327
8328 /** Retrieves body of a compute shader that should be used for the purpose of
8329 * user-specified test case.
8330 *
8331 * @param test_case Test case descriptor to use.
8332 *
8333 * @return Requested string.
8334 **/
getComputeShaderBody(const _test_case & test_case)8335 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8336 {
8337 std::stringstream result_sstream;
8338
8339 /* Add pre-amble */
8340 result_sstream << "#version 420\n"
8341 "#extension GL_ARB_compute_shader : require\n"
8342 "\n"
8343 "layout(local_size_x = 6) in;\n"
8344 "\n"
8345 "void main()\n"
8346 "{\n";
8347
8348 /* Add local variable declarations */
8349 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8350
8351 if (test_case.src_array_size > 1)
8352 {
8353 result_sstream << "[" << test_case.src_array_size << "]";
8354 }
8355
8356 result_sstream << ";\n";
8357
8358 if (test_case.wrap_dst_type_in_structure)
8359 {
8360 result_sstream << "struct\n"
8361 "{\n"
8362 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8363 }
8364 else
8365 {
8366 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8367 }
8368
8369 result_sstream << ";\n";
8370
8371 if (test_case.wrap_dst_type_in_structure)
8372 {
8373 result_sstream << "\n} dst;\n";
8374 }
8375
8376 /* Add actual body */
8377 result_sstream << "dst = src;\n"
8378 "}\n";
8379
8380 /* Return the body */
8381 return result_sstream.str();
8382 }
8383
8384 /** Retrieves body of a fragment shader that should be used for the purpose of
8385 * user-specified test case.
8386 *
8387 * @param test_case Test case descriptor to use.
8388 *
8389 * @return Requested string.
8390 **/
getFragmentShaderBody(const _test_case & test_case)8391 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8392 {
8393 std::stringstream result_sstream;
8394
8395 /* Add pre-amble */
8396 result_sstream << "#version 420\n"
8397 "\n"
8398 "void main()\n"
8399 "{\n";
8400
8401 /* Add local variable declarations */
8402 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8403
8404 if (test_case.src_array_size > 1)
8405 {
8406 result_sstream << "[" << test_case.src_array_size << "]";
8407 }
8408
8409 result_sstream << ";\n";
8410
8411 if (test_case.wrap_dst_type_in_structure)
8412 {
8413 result_sstream << "struct\n"
8414 "{\n"
8415 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8416 }
8417 else
8418 {
8419 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8420 }
8421
8422 result_sstream << ";\n";
8423
8424 if (test_case.wrap_dst_type_in_structure)
8425 {
8426 result_sstream << "\n} dst;\n";
8427 }
8428
8429 /* Add actual body */
8430 result_sstream << "dst = src;\n"
8431 "}\n";
8432
8433 /* Return the body */
8434 return result_sstream.str();
8435 }
8436
8437 /** Retrieves body of a geometry shader that should be used for the purpose of
8438 * user-specified test case.
8439 *
8440 * @param test_case Test case descriptor to use.
8441 *
8442 * @return Requested string.
8443 **/
getGeometryShaderBody(const _test_case & test_case)8444 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8445 {
8446 std::stringstream result_sstream;
8447
8448 /* Add preamble */
8449 result_sstream << "#version 420\n"
8450 "\n"
8451 "layout(points) in;\n"
8452 "layout(max_vertices=1, points) out;\n"
8453 "\n"
8454 "void main()\n"
8455 "{\n";
8456
8457 /* Add local variable declarations */
8458 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8459
8460 if (test_case.src_array_size > 1)
8461 {
8462 result_sstream << "[" << test_case.src_array_size << "]";
8463 }
8464
8465 result_sstream << ";\n";
8466
8467 if (test_case.wrap_dst_type_in_structure)
8468 {
8469 result_sstream << "struct\n"
8470 "{\n"
8471 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8472 }
8473 else
8474 {
8475 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8476 }
8477
8478 result_sstream << ";\n"
8479 "\n";
8480
8481 if (test_case.wrap_dst_type_in_structure)
8482 {
8483 result_sstream << "} dst;\n";
8484 }
8485
8486 /* Add actual body */
8487 result_sstream << "dst = src;\n"
8488 "}\n";
8489
8490 /* We're done! */
8491 return result_sstream.str();
8492 }
8493
8494 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8495 * user-specified test case.
8496 *
8497 * @param test_case Test case descriptor to use.
8498 *
8499 * @return Requested string.
8500 **/
getTessellationControlShaderBody(const _test_case & test_case)8501 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8502 {
8503 std::stringstream result_sstream;
8504
8505 /* Add preamble */
8506 result_sstream << "#version 420\n"
8507 "\n"
8508 "layout(vertices=4) out;\n"
8509 "\n"
8510 "void main()\n"
8511 "{\n";
8512
8513 /* Add local variable declarations. */
8514 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8515
8516 if (test_case.src_array_size > 1)
8517 {
8518 result_sstream << "[" << test_case.src_array_size << "]";
8519 }
8520
8521 result_sstream << ";\n";
8522
8523 if (test_case.wrap_dst_type_in_structure)
8524 {
8525 result_sstream << "struct\n"
8526 "{\n"
8527 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8528 }
8529 else
8530 {
8531 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8532 }
8533
8534 if (test_case.wrap_dst_type_in_structure)
8535 {
8536 result_sstream << ";\n"
8537 "} dst;\n";
8538 }
8539 else
8540 {
8541 result_sstream << ";\n";
8542 }
8543
8544 /* Continue with the actual body. */
8545 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8546 "gl_TessLevelOuter[1] = 1.0;\n"
8547 "dst = src;\n"
8548 "}\n";
8549
8550 /* Return the body */
8551 return result_sstream.str();
8552 }
8553
8554 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8555 * user-specified test case.
8556 *
8557 * @param test_case Test case descriptor to use.
8558 *
8559 * @return Requested string.
8560 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8561 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8562 {
8563 std::stringstream result_sstream;
8564
8565 /* Add preamble */
8566 result_sstream << "#version 420\n"
8567 "\n"
8568 "layout(isolines) in;\n"
8569 "\n"
8570 "void main()\n"
8571 "{\n";
8572
8573 /* Add local variable declarations */
8574 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8575
8576 if (test_case.src_array_size > 1)
8577 {
8578 result_sstream << "[" << test_case.src_array_size << "]";
8579 }
8580
8581 result_sstream << ";\n";
8582
8583 if (test_case.wrap_dst_type_in_structure)
8584 {
8585 result_sstream << "struct\n"
8586 "{\n"
8587 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8588 }
8589 else
8590 {
8591 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8592 }
8593
8594 if (test_case.wrap_dst_type_in_structure)
8595 {
8596 result_sstream << ";\n"
8597 "} dst;\n";
8598 }
8599 else
8600 {
8601 result_sstream << ";\n";
8602 }
8603
8604 /* Continue with the actual body. */
8605 result_sstream << "dst = src;\n";
8606
8607 /* Complete the body */
8608 result_sstream << "}\n";
8609
8610 /* Return the body */
8611 return result_sstream.str();
8612 }
8613
8614 /** Retrieves body of a vertex shader that should be used for the purpose of
8615 * user-specified test case.
8616 *
8617 * @param test_case Test case descriptor to use.
8618 *
8619 * @return Requested string.
8620 **/
getVertexShaderBody(const _test_case & test_case)8621 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8622 {
8623 std::stringstream result_sstream;
8624
8625 /* Add preamble */
8626 result_sstream << "#version 420\n"
8627 "\n"
8628 "void main()\n"
8629 "{\n";
8630
8631 /* Add local variables */
8632 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8633
8634 if (test_case.src_array_size > 1)
8635 {
8636 result_sstream << "[" << test_case.src_array_size << "]";
8637 }
8638
8639 result_sstream << ";\n";
8640
8641 if (test_case.wrap_dst_type_in_structure)
8642 {
8643 result_sstream << "struct\n"
8644 "{\n"
8645 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8646 }
8647 else
8648 {
8649 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8650 }
8651
8652 if (test_case.wrap_dst_type_in_structure)
8653 {
8654 result_sstream << ";\n"
8655 "} dst;\n";
8656 }
8657 else
8658 {
8659 result_sstream << ";\n";
8660 }
8661
8662 /* Start actual body */
8663 result_sstream << "dst = src;\n"
8664 "gl_Position = vec4(1.0);\n"
8665 "}";
8666
8667 return result_sstream.str();
8668 }
8669
8670 /** Initializes shader objects required to run the test. */
initTest()8671 void GPUShaderFP64Test6::initTest()
8672 {
8673 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8674
8675 /* Generate shader objects */
8676
8677 /* Compute shader support and GL 4.2 required */
8678 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8679 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8680 {
8681 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8682 }
8683
8684 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8685 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8686 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8687 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8688 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8689
8690 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8691 }
8692
8693 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8694 *
8695 * @param test_case Test case descriptor to generate the shader bodies for.
8696 **/
initIteration(_test_case & test_case)8697 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8698 {
8699 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8700
8701 test_case.cs_shader_body = getComputeShaderBody(test_case);
8702 test_case.fs_shader_body = getFragmentShaderBody(test_case);
8703 test_case.gs_shader_body = getGeometryShaderBody(test_case);
8704 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8705 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8706 test_case.vs_shader_body = getVertexShaderBody(test_case);
8707
8708 /* Assign the bodies to relevant shaders */
8709 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8710 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8711 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8712 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8713 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8714 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8715
8716 /* m_cs_id is initialized only if compute_shader is supported */
8717 if (0 != m_cs_id)
8718 {
8719 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8720 }
8721
8722 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8723 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8724 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8725 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8726 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8727 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8728 }
8729
8730 /** Executes test iteration.
8731 *
8732 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8733 */
iterate()8734 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8735 {
8736 /* Do not execute the test if GL_ARB_texture_view is not supported */
8737 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8738 {
8739 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8740 }
8741
8742 /* Initialize GL objects needed to run the tests */
8743 initTest();
8744
8745 /* Build iteration array to run the tests in an automated manner */
8746 _test_case test_cases[] = {
8747 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8748 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8749 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8750 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8751 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8752 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8753 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8754 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8755 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8756 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8757 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8758 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8759 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8760 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8761 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8762 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8763 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8764 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8765 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8766 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8767 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8768 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8769 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8770 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8771 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8772 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8773 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8774 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8775 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8776 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8777 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8778 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8779 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8780 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8781 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8782 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8783 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8784 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8785 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8786 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8787 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8788 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8789 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8790 };
8791 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8792
8793 /* Execute all iterations */
8794 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8795 {
8796 _test_case& test_case = test_cases[n_test_case];
8797
8798 /* Initialize a program object we will use to perform the casting */
8799 initIteration(test_case);
8800
8801 /* Use the program object to XFB the results */
8802 m_has_test_passed &= executeIteration(test_case);
8803
8804 } /* for (all test cases) */
8805
8806 /* We're done */
8807 if (m_has_test_passed)
8808 {
8809 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8810 }
8811 else
8812 {
8813 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8814 }
8815
8816 return STOP;
8817 }
8818
8819 /** Constructor
8820 *
8821 * @param context Rendering context.
8822 */
GPUShaderFP64Test7(deqp::Context & context)8823 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8824 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8825 "in all shader stages.")
8826 , m_are_double_inputs_supported(false)
8827 , m_fbo_id(0)
8828 , m_fs_id(0)
8829 , m_gs_id(0)
8830 , m_has_test_passed(true)
8831 , m_n_max_components_per_stage(0)
8832 , m_n_xfb_varyings(0)
8833 , m_po_id(0)
8834 , m_tc_id(0)
8835 , m_te_id(0)
8836 , m_to_id(0)
8837 , m_to_data(NULL)
8838 , m_to_height(4)
8839 , m_to_width(4)
8840 , m_xfb_bo_id(0)
8841 , m_xfb_varyings(NULL)
8842 , m_vao_id(0)
8843 , m_vs_id(0)
8844 {
8845 }
8846
8847 /** Compiles all shaders attached to test program object and links it.
8848 *
8849 * @param variables
8850 *
8851 * @return true if the process was executed successfully, false otherwise.
8852 */
buildTestProgram(_variables & variables)8853 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8854 {
8855 std::string fs_body = getFragmentShaderBody(variables);
8856 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8857 std::string gs_body = getGeometryShaderBody(variables);
8858 std::string tc_body = getTessellationControlShaderBody(variables);
8859 std::string te_body = getTessellationEvaluationShaderBody(variables);
8860 std::string vs_body = getVertexShaderBody(variables);
8861 bool result = false;
8862
8863 /* Try to link the program object */
8864 glw::GLint link_status = GL_FALSE;
8865
8866 /* Compile the shaders */
8867 if (!compileShader(m_fs_id, fs_body))
8868 {
8869 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8870
8871 goto end;
8872 }
8873
8874 if (!compileShader(m_gs_id, gs_body))
8875 {
8876 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8877
8878 goto end;
8879 }
8880
8881 if (!compileShader(m_tc_id, tc_body))
8882 {
8883 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8884 << tcu::TestLog::EndMessage;
8885
8886 goto end;
8887 }
8888
8889 if (!compileShader(m_te_id, te_body))
8890 {
8891 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8892 << tcu::TestLog::EndMessage;
8893
8894 goto end;
8895 }
8896
8897 if (!compileShader(m_vs_id, vs_body))
8898 {
8899 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8900
8901 goto end;
8902 }
8903
8904 /* Configure XFB */
8905 releaseXFBVaryingNames();
8906 generateXFBVaryingNames(variables);
8907
8908 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8909
8910 gl.linkProgram(m_po_id);
8911
8912 /* Have we succeeded? */
8913 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8914
8915 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8916 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8917
8918 if (link_status != GL_TRUE)
8919 {
8920 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8921 << tcu::TestLog::EndMessage;
8922
8923 goto end;
8924 }
8925
8926 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8927 if (m_are_double_inputs_supported)
8928 {
8929 const size_t n_variables = variables.size();
8930
8931 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8932 {
8933 _variable& current_variable = variables[n_variable];
8934 std::stringstream attribute_name_sstream;
8935
8936 attribute_name_sstream << "in_vs_variable" << n_variable;
8937
8938 if (current_variable.array_size > 1)
8939 {
8940 attribute_name_sstream << "[0]";
8941 }
8942
8943 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8944
8945 if (current_variable.attribute_location == -1)
8946 {
8947 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8948 << attribute_name_sstream.str().c_str()
8949 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8950
8951 m_has_test_passed = false;
8952 goto end;
8953 }
8954 } /* for (all test variables) */
8955 } /* if (m_are_double_inputs_supported) */
8956
8957 m_current_fs_body = fs_body;
8958 m_current_gs_body = gs_body;
8959 m_current_tc_body = tc_body;
8960 m_current_te_body = te_body;
8961 m_current_vs_body = vs_body;
8962
8963 result = true;
8964
8965 end:
8966 return result;
8967 }
8968
8969 /** Updates shader object's body and then compiles the shader.
8970 *
8971 * @param body Body to use for the shader.
8972 *
8973 * @return true if the shader compiled successfully, false otherwise.
8974 **/
compileShader(glw::GLint shader_id,const std::string & body)8975 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8976 {
8977 const char* body_raw_ptr = body.c_str();
8978 glw::GLint compile_status = GL_FALSE;
8979 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8980
8981 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8982 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8983
8984 gl.compileShader(shader_id);
8985 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8986
8987 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8988 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8989
8990 return (compile_status == GL_TRUE);
8991 }
8992
8993 /** Configure storage of a buffer object used for capturing XFB data.
8994 *
8995 * @param variables Holds descriptor for all variables used for the iteration the
8996 * BO is being configured for. Storage size will be directly related
8997 * to the number of the variables and their type.
8998 */
configureXFBBuffer(const _variables & variables)8999 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9000 {
9001 DE_ASSERT(m_n_xfb_varyings != 0);
9002
9003 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9004 * The test only draws a single patch, and triangles are caught by transform feed-back.
9005 * Let's initialize the storage, according to the list of variables that will be used
9006 * for the test run.
9007 */
9008 unsigned int bo_size = 0;
9009
9010 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9011 variables_iterator++)
9012 {
9013 const _variable& variable = *variables_iterator;
9014 unsigned int n_bytes_needed = static_cast<unsigned int>(
9015 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9016
9017 bo_size += n_bytes_needed;
9018 } /* for (all variables) */
9019
9020 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9021
9022 /* Set up the BO storage */
9023 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9024
9025 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9026 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9027 }
9028
9029 /** Deinitializes all buffers and GL objects that may have been generated
9030 * during test execution.
9031 **/
deinit()9032 void GPUShaderFP64Test7::deinit()
9033 {
9034 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9035
9036 if (m_fbo_id != 0)
9037 {
9038 gl.deleteFramebuffers(1, &m_fbo_id);
9039
9040 m_fbo_id = 0;
9041 }
9042
9043 if (m_fs_id != 0)
9044 {
9045 gl.deleteShader(m_fs_id);
9046
9047 m_fs_id = 0;
9048 }
9049
9050 if (m_gs_id != 0)
9051 {
9052 gl.deleteShader(m_gs_id);
9053
9054 m_gs_id = 0;
9055 }
9056
9057 if (m_po_id != 0)
9058 {
9059 gl.deleteProgram(m_po_id);
9060
9061 m_po_id = 0;
9062 }
9063
9064 if (m_tc_id != 0)
9065 {
9066 gl.deleteShader(m_tc_id);
9067
9068 m_tc_id = 0;
9069 }
9070
9071 if (m_te_id != 0)
9072 {
9073 gl.deleteShader(m_te_id);
9074
9075 m_te_id = 0;
9076 }
9077
9078 if (m_to_data != NULL)
9079 {
9080 delete[] m_to_data;
9081
9082 m_to_data = NULL;
9083 }
9084
9085 if (m_to_id != 0)
9086 {
9087 gl.deleteTextures(1, &m_to_id);
9088
9089 m_to_id = 0;
9090 }
9091
9092 if (m_xfb_bo_id != 0)
9093 {
9094 gl.deleteBuffers(1, &m_xfb_bo_id);
9095
9096 m_xfb_bo_id = 0;
9097 }
9098
9099 if (m_xfb_varyings != DE_NULL)
9100 {
9101 releaseXFBVaryingNames();
9102 }
9103
9104 if (m_vao_id != 0)
9105 {
9106 gl.deleteVertexArrays(1, &m_vao_id);
9107
9108 m_vao_id = 0;
9109 }
9110
9111 if (m_vs_id != 0)
9112 {
9113 gl.deleteShader(m_vs_id);
9114
9115 m_vs_id = 0;
9116 }
9117 }
9118
9119 /** Executes the functional part of the test (case a) from the test spec)
9120 *
9121 * @param variables Vector of variable descriptors defining properties of
9122 * variables that should be used for the iteration.
9123 *
9124 * @return true if the test passed, false otherwise.
9125 **/
executeFunctionalTest(_variables & variables)9126 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9127 {
9128 bool result = true;
9129
9130 /* Build the test program */
9131 if (!buildTestProgram(variables))
9132 {
9133 return false;
9134 }
9135
9136 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9137 if (m_are_double_inputs_supported)
9138 {
9139 setInputAttributeValues(variables);
9140 }
9141
9142 /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9143 * only, if a data mismatch is detected.
9144 */
9145 configureXFBBuffer(variables);
9146
9147 /* Issue a draw call using the test program */
9148 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9149
9150 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9151 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9152
9153 gl.clear(GL_COLOR_BUFFER_BIT);
9154 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9155
9156 gl.useProgram(m_po_id);
9157 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9158
9159 gl.viewport(0, /* x */
9160 0, /* y */
9161 m_to_width, m_to_height);
9162 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9163
9164 gl.beginTransformFeedback(GL_TRIANGLES);
9165 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9166 {
9167 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9168 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9169 }
9170 gl.endTransformFeedback();
9171 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9172
9173 /* Verify color attachment contents */
9174 const float epsilon = 1.0f / 255.0f;
9175
9176 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9177 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9178
9179 for (unsigned int y = 0; y < m_to_height; ++y)
9180 {
9181 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9182
9183 for (unsigned int x = 0; x < m_to_width; ++x)
9184 {
9185 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9186
9187 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9188 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9189 {
9190 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9191 << ")"
9192 "; expected:(0, 255, 0, 0), found: ("
9193 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9194 << ", " << (int)pixel_ptr[3]
9195 << "), with the following variable types used as varyings:"
9196 << tcu::TestLog::EndMessage;
9197
9198 /* List the variable types that failed the test */
9199 const size_t n_variables = variables.size();
9200
9201 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9202 {
9203 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9204 << Utils::getVariableTypeString(variables[n_variable].type)
9205 << " (array size:" << variables[n_variable].array_size << ")"
9206 << tcu::TestLog::EndMessage;
9207 } /* for (all variable types) */
9208
9209 /* Log the variable contents */
9210 logVariableContents(variables);
9211
9212 /* Log shaders used for the iteration */
9213 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9214 "\n"
9215 "(VS):\n"
9216 << m_current_vs_body.c_str() << "\n"
9217 << "(TC):\n"
9218 "\n"
9219 << m_current_tc_body.c_str() << "\n"
9220 "(TE):\n"
9221 "\n"
9222 << m_current_te_body.c_str() << "\n"
9223 "(GS):\n"
9224 << m_current_gs_body.c_str() << "\n"
9225 "(FS):\n"
9226 "\n"
9227 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9228
9229 result = false;
9230
9231 goto end;
9232 }
9233 } /* for (all columns) */
9234 } /* for (all rows) */
9235
9236 /* All done! */
9237 end:
9238 return result;
9239 }
9240
9241 /** Takes user-input vector of test variables and allocates & fills an array of strings
9242 * holding names of geometry shader stage varyings that should be captured during
9243 * transform feedback operation. The array will be stored in m_xfb_varyings.
9244 *
9245 * @param variables Holds all test variable descriptors to be used for the iteration.
9246 */
generateXFBVaryingNames(const _variables & variables)9247 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9248 {
9249 unsigned int n_variable = 0;
9250 unsigned int n_varying = 0;
9251 unsigned int n_varyings = 0;
9252
9253 if (m_xfb_varyings != NULL)
9254 {
9255 releaseXFBVaryingNames();
9256 }
9257
9258 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9259 ++variables_iterator)
9260 {
9261 const _variable& variable = *variables_iterator;
9262
9263 n_varyings += variable.array_size;
9264 }
9265
9266 m_xfb_varyings = new glw::GLchar*[n_varyings];
9267
9268 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9269 ++variables_iterator, ++n_variable)
9270 {
9271 const _variable& variable = *variables_iterator;
9272
9273 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9274 {
9275 std::stringstream varying_sstream;
9276 size_t varying_length;
9277
9278 varying_sstream << "gs_variable" << n_variable;
9279
9280 if (variable.array_size > 1)
9281 {
9282 varying_sstream << "[" << array_index << "]";
9283 }
9284
9285 /* Store the varying name */
9286 varying_length = varying_sstream.str().length();
9287 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9288
9289 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9290 m_xfb_varyings[n_varying][varying_length] = 0;
9291 } /* for (all array indices) */
9292 } /* for (all varyings) */
9293
9294 m_n_xfb_varyings = n_varyings;
9295 }
9296
9297 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9298 * without using the "flat" keyword. (case c) )
9299 *
9300 * @param input_variable_type Variable type to use for input variable declaration.
9301 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9302 * of the arrayed variable.
9303 *
9304 * @return Requested string.
9305 **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9306 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9307 Utils::_variable_type input_variable_type, unsigned int array_size)
9308 {
9309 std::stringstream result_sstream;
9310 std::stringstream array_index_stringstream;
9311 std::stringstream array_size_stringstream;
9312
9313 if (array_size > 1)
9314 {
9315 array_index_stringstream << "[0]";
9316 array_size_stringstream << "[" << array_size << "]";
9317 }
9318
9319 if (Utils::isMatrixVariableType(input_variable_type))
9320 {
9321 array_index_stringstream << "[0].x";
9322 }
9323 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9324 {
9325 array_index_stringstream << "[0]";
9326 }
9327
9328 result_sstream << "#version 400\n"
9329 "\n"
9330 "in "
9331 << Utils::getVariableTypeString(input_variable_type) << " test_input"
9332 << array_size_stringstream.str() << ";\n"
9333 "\n"
9334 "out float test_output;\n"
9335 "\n"
9336 "void main()\n"
9337 "{\n"
9338 " if (test_input"
9339 << array_index_stringstream.str() << " > 2.0)\n"
9340 " {\n"
9341 " test_output = 1.0;\n"
9342 " }\n"
9343 " else\n"
9344 " {\n"
9345 " test_output = 3.0;\n"
9346 " }\n"
9347 "}\n";
9348
9349 return result_sstream.str();
9350 }
9351
9352 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9353 *
9354 * @param input_variable_type Variable type to use for input variable declaration.
9355 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9356 * of the arrayed variable.
9357 *
9358 * @return Requested string.
9359 **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9360 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9361 Utils::_variable_type output_variable_type, unsigned int array_size)
9362 {
9363 std::stringstream array_index_sstream;
9364 std::stringstream array_size_sstream;
9365 std::stringstream result_sstream;
9366 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9367
9368 if (array_size > 1)
9369 {
9370 array_index_sstream << "[0]";
9371 array_size_sstream << "[" << array_size << "]";
9372 }
9373
9374 result_sstream << "#version 400\n"
9375 "\n"
9376 "out "
9377 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9378 "\n"
9379 "void main()\n"
9380 "{\n"
9381 " test_output"
9382 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9383 "}\n";
9384
9385 return result_sstream.str();
9386 }
9387
9388 /** Retrieves body of a fragment shader that uses user-specified set of variables
9389 * to declare contents of input & output block.
9390 *
9391 * @param variables As per description.
9392 *
9393 * @return Requested string.
9394 **/
getFragmentShaderBody(const _variables & variables)9395 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9396 {
9397 std::stringstream result_sstream;
9398
9399 /* Form the pre-amble */
9400 result_sstream << "#version 400\n"
9401 "\n"
9402
9403 /* Add input block */
9404 << "in GS_DATA\n"
9405 "{\n"
9406 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9407 "\n"
9408
9409 /* Add output variable */
9410 << "out vec4 result;\n"
9411 "\n"
9412
9413 /* Add main() definition */
9414 "void main()\n"
9415 "{\n"
9416 "const double epsilon = 1e-5;\n"
9417 "\n"
9418 "result = vec4(1, 0, 0, 0);\n"
9419 "\n";
9420
9421 /* Determine expected values first */
9422 unsigned int base_counter = 1;
9423 const size_t n_variables = variables.size();
9424
9425 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9426 {
9427 unsigned int variable_array_size = variables[n_variable].array_size;
9428 Utils::_variable_type variable_type = variables[n_variable].type;
9429 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9430 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9431
9432 std::stringstream array_size_sstream;
9433
9434 if (variable_array_size > 1)
9435 {
9436 array_size_sstream << "[" << variable_array_size << "]";
9437 }
9438
9439 /* Local variable declaration */
9440 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9441 << ";\n"
9442 "\n";
9443
9444 /* Set expected values */
9445 for (unsigned int index = 0; index < variable_array_size; ++index)
9446 {
9447 std::stringstream array_index_sstream;
9448
9449 if (variable_array_size > 1)
9450 {
9451 array_index_sstream << "[" << index << "]";
9452 }
9453
9454 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9455 << variable_type_string << "(";
9456
9457 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9458 {
9459 unsigned int expected_value =
9460 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9461
9462 if (m_are_double_inputs_supported)
9463 {
9464 /* VS input attributes */
9465 //expected_value += (base_counter + 6);
9466 expected_value -= 1;
9467 }
9468
9469 result_sstream << expected_value;
9470
9471 if (n_component != (n_variable_type_components - 1))
9472 {
9473 result_sstream << ", ";
9474 }
9475
9476 ++base_counter;
9477 } /* for (all components) */
9478
9479 result_sstream << ");\n";
9480 } /* for (all array indices) */
9481
9482 result_sstream << "\n";
9483 } /* for (all variable types) */
9484
9485 /* Now that we know the expected values, do a huge conditional check to verify if all
9486 * input variables carry correct information.
9487 */
9488 result_sstream << "if (";
9489
9490 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9491 {
9492 unsigned int variable_array_size = variables[n_variable].array_size;
9493 Utils::_variable_type variable_type = variables[n_variable].type;
9494 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type);
9495 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9496 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9497
9498 for (unsigned int index = 0; index < variable_array_size; ++index)
9499 {
9500 std::stringstream array_index_sstream;
9501
9502 if (variable_array_size > 1)
9503 {
9504 array_index_sstream << "[" << index << "]";
9505 }
9506
9507 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9508 {
9509 std::stringstream component_index_sstream;
9510
9511 if (n_variable_type_components > 1)
9512 {
9513 component_index_sstream << "[" << n_component << "]";
9514 }
9515
9516 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9517
9518 if (is_variable_type_matrix)
9519 {
9520 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9521 const unsigned int column = n_component % n_columns;
9522 const unsigned int row = n_component / n_columns;
9523
9524 result_sstream << "[" << column << "]"
9525 "."
9526 << Utils::getComponentAtIndex(row);
9527 }
9528 else
9529 {
9530 result_sstream << component_index_sstream.str();
9531 }
9532
9533 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9534
9535 if (is_variable_type_matrix)
9536 {
9537 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9538 const unsigned int column = n_component % n_columns;
9539 const unsigned int row = n_component / n_columns;
9540
9541 result_sstream << "[" << column << "]"
9542 "."
9543 << Utils::getComponentAtIndex(row);
9544 }
9545 else
9546 {
9547 result_sstream << component_index_sstream.str();
9548 }
9549
9550 result_sstream << ") <= epsilon &&";
9551 } /* for (all components) */
9552 } /* for (all array indices) */
9553 } /* for (all variable types) */
9554
9555 result_sstream << "true)\n"
9556 "{\n"
9557 " result = vec4(0, 1, 0, 0);\n"
9558 "}\n"
9559 "}\n";
9560
9561 /* All done */
9562 return result_sstream.str();
9563 }
9564
9565 /** Retrieves body of a geometry shader that uses user-specified set of variables
9566 * to declare contents of input & output block.
9567 *
9568 * @param variables As per description.
9569 *
9570 * @return Requested string.
9571 **/
getGeometryShaderBody(const _variables & variables)9572 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9573 {
9574 std::stringstream result_sstream;
9575
9576 /* Form the pre-amble */
9577 result_sstream << "#version 400\n"
9578 "\n"
9579 "layout(triangles) in;\n"
9580 "layout(triangle_strip, max_vertices=4) out;\n"
9581 "\n"
9582
9583 /* Add the input block */
9584 "in TE_DATA\n"
9585 "{\n"
9586 << getVariableDeclarations("te", variables) << "} in_data[];\n"
9587 "\n"
9588
9589 /* Add the output block */
9590 "out GS_DATA\n"
9591 "{\n"
9592 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9593 "\n"
9594
9595 /* Declare main() function */
9596 "void main()\n"
9597 "{\n";
9598
9599 /* Take input variables, add a predefined value and forward them to output variables */
9600 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9601 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
9602 const unsigned int n_quad_vertices =
9603 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9604 const size_t n_variables = variables.size();
9605
9606 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9607 {
9608 unsigned int counter = 4;
9609 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9610
9611 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9612 {
9613 unsigned int variable_array_size = variables[n_variable].array_size;
9614 Utils::_variable_type variable_type = variables[n_variable].type;
9615 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9616 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9617
9618 for (unsigned int index = 0; index < variable_array_size; ++index)
9619 {
9620 std::stringstream array_index_sstream;
9621
9622 if (variable_array_size > 1)
9623 {
9624 array_index_sstream << "[" << index << "]";
9625 }
9626
9627 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9628 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9629 << variable_type_string << "(";
9630
9631 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9632 {
9633 result_sstream << (counter++);
9634
9635 if (n_component != (n_variable_type_components - 1))
9636 {
9637 result_sstream << ", ";
9638 }
9639 } /* for (all components) */
9640
9641 result_sstream << ");\n";
9642 } /* for (all array indices) */
9643 } /* for (all variable types) */
9644
9645 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9646 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9647 "EmitVertex();\n";
9648 } /* for (all emitted quad vertices) */
9649
9650 result_sstream << "EndPrimitive();\n"
9651 "}\n";
9652
9653 /* All done */
9654 return result_sstream.str();
9655 }
9656
9657 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9658 * to declare contents of input & output block.
9659 *
9660 * @param variables As per description.
9661 *
9662 * @return Requested string.
9663 **/
getTessellationControlShaderBody(const _variables & variables)9664 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9665 {
9666 std::stringstream result_sstream;
9667
9668 /* Form the pre-amble */
9669 result_sstream << "#version 400\n"
9670 "\n"
9671 "layout (vertices=4) out;\n"
9672
9673 /* Declare input block */
9674 "in VS_DATA\n"
9675 "{\n"
9676 << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9677
9678 /* Declare output block */
9679 "out TC_DATA\n"
9680 "{\n"
9681 << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9682 "\n"
9683
9684 /* Define main() */
9685 "void main()\n"
9686 "{\n"
9687 " gl_TessLevelInner[0] = 1;\n"
9688 " gl_TessLevelInner[1] = 1;\n"
9689 " gl_TessLevelOuter[0] = 1;\n"
9690 " gl_TessLevelOuter[1] = 1;\n"
9691 " gl_TessLevelOuter[2] = 1;\n"
9692 " gl_TessLevelOuter[3] = 1;\n"
9693 "\n";
9694
9695 /* Take input variables, add a predefined value and forward them to output variables */
9696 const size_t n_variables = variables.size();
9697 unsigned int counter = 2;
9698
9699 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9700 {
9701 unsigned int variable_array_size = variables[n_variable].array_size;
9702 Utils::_variable_type variable_type = variables[n_variable].type;
9703 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9704 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9705
9706 for (unsigned int index = 0; index < variable_array_size; ++index)
9707 {
9708 std::stringstream array_index_sstream;
9709
9710 if (variable_array_size > 1)
9711 {
9712 array_index_sstream << "[" << index << "]";
9713 }
9714
9715 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9716 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9717 << variable_type_string << "(";
9718
9719 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9720 {
9721 result_sstream << (counter++);
9722
9723 if (n_component != (n_variable_type_components - 1))
9724 {
9725 result_sstream << ", ";
9726 }
9727 }
9728
9729 result_sstream << ");\n";
9730 } /* for (all array indices) */
9731 } /* for (all variable types) */
9732
9733 result_sstream << "}\n";
9734
9735 /* We're done */
9736 return result_sstream.str();
9737 }
9738
9739 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9740 * to declare contents of input & output block.
9741 *
9742 * @param variables As per description.
9743 *
9744 * @return Requested string.
9745 **/
getTessellationEvaluationShaderBody(const _variables & variables)9746 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9747 {
9748 std::stringstream result_sstream;
9749
9750 /* Form the pre-amble */
9751 result_sstream << "#version 400\n"
9752 "\n"
9753 "layout(quads) in;\n"
9754 "\n"
9755
9756 /* Define input block */
9757 "in TC_DATA\n"
9758 "{\n"
9759 << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9760 "\n"
9761
9762 /* Define output block */
9763 "out TE_DATA\n"
9764 "{\n"
9765 << getVariableDeclarations("te", variables) << "};\n"
9766 "\n"
9767
9768 /* Define main() */
9769 "void main()\n"
9770 "{\n";
9771
9772 /* Take input variables, add a predefined value and forward them to output variables */
9773 const size_t n_variables = variables.size();
9774 unsigned int counter = 3;
9775
9776 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9777 {
9778 unsigned int variable_array_size = variables[n_variable].array_size;
9779 Utils::_variable_type variable_type = variables[n_variable].type;
9780 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9781 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9782
9783 for (unsigned int index = 0; index < variable_array_size; ++index)
9784 {
9785 std::stringstream array_index_sstream;
9786
9787 if (variable_array_size > 1)
9788 {
9789 array_index_sstream << "[" << index << "]";
9790 }
9791
9792 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9793 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9794
9795 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9796 {
9797 result_sstream << (counter++);
9798
9799 if (n_component != (n_variable_type_components - 1))
9800 {
9801 result_sstream << ", ";
9802 }
9803 } /* for (all components) */
9804
9805 result_sstream << ");\n";
9806 } /* for (all array indices) */
9807 } /* for (all variable types) */
9808
9809 result_sstream << "}\n";
9810
9811 /* All done */
9812 return result_sstream.str();
9813 }
9814
9815 /** Returns a string containing declarations of user-specified set of variables.
9816 * Each declaration can optionally use a layot qualifier requested by the caller.
9817 *
9818 * @param prefix Prefix to use for variable names.
9819 * @param variables List of variables to declare in the result string.
9820 * @param explicit_locations true if each declaration should explicitly define location
9821 * of the variable ( eg. (layout location=X) )
9822 * @param layout_qualifier Optional qualifier to use for the declaration. Must not
9823 * be NULL.
9824 *
9825 * @return Requested string.
9826 **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9827 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9828 const char* layout_qualifier)
9829 {
9830 std::stringstream result_sstream;
9831
9832 /* Define output variables */
9833 const size_t n_variables = variables.size();
9834
9835 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9836 {
9837 unsigned int variable_array_size = variables[n_variable].array_size;
9838 Utils::_variable_type variable_type = variables[n_variable].type;
9839 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9840
9841 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9842
9843 if (variable_array_size > 1)
9844 {
9845 result_sstream << "[" << variable_array_size << "]";
9846 }
9847
9848 result_sstream << ";\n";
9849 } /* for (all user-specified variable types) */
9850
9851 return result_sstream.str();
9852 }
9853
9854 /** Retrieves body of a vertex shader that uses user-specified set of variables
9855 * to declare contents of input & output block.
9856 *
9857 * @param variables As per description.
9858 *
9859 * @return Requested string.
9860 **/
getVertexShaderBody(const _variables & variables)9861 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9862 {
9863 std::stringstream result_sstream;
9864
9865 /* Form pre-amble */
9866 result_sstream << "#version 400\n"
9867 "\n";
9868
9869 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9870 if (m_are_double_inputs_supported)
9871 {
9872 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9873 << getVariableDeclarations("in_vs", variables, "in");
9874 }
9875
9876 /* Define output variables */
9877 result_sstream << "out VS_DATA\n"
9878 "{\n"
9879 << getVariableDeclarations("vs", variables);
9880
9881 /* Define main() */
9882 result_sstream << "};\n"
9883 "\n"
9884 "void main()\n"
9885 "{\n";
9886
9887 /* Set output variable values */
9888 unsigned int counter = 1;
9889 const size_t n_variables = variables.size();
9890
9891 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9892 {
9893 unsigned int variable_array_size = variables[n_variable].array_size;
9894 Utils::_variable_type variable_type = variables[n_variable].type;
9895 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9896 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9897
9898 for (unsigned int index = 0; index < variable_array_size; ++index)
9899 {
9900 if (variable_array_size == 1)
9901 {
9902 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9903 }
9904 else
9905 {
9906 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9907 << " = " << variable_type_string << "(";
9908 }
9909
9910 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9911 {
9912 result_sstream << (double)(counter++);
9913
9914 /* Use input attributes, if available */
9915 if (m_are_double_inputs_supported)
9916 {
9917 result_sstream << " + in_vs_variable" << n_variable;
9918
9919 if (variable_array_size > 1)
9920 {
9921 result_sstream << "[" << index << "]";
9922 }
9923
9924 if (Utils::isMatrixVariableType(variables[n_variable].type))
9925 {
9926 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9927 const unsigned int column = n_component % n_columns;
9928 const unsigned int row = n_component / n_columns;
9929
9930 result_sstream << "[" << (column) << "]"
9931 "."
9932 << Utils::getComponentAtIndex(row);
9933 }
9934 else if (n_variable_type_components > 1)
9935 {
9936 result_sstream << "[" << n_component << "]";
9937 }
9938 }
9939
9940 if (n_component != (n_variable_type_components - 1))
9941 {
9942 result_sstream << ", ";
9943 }
9944 } /* for (all components) */
9945
9946 result_sstream << ");\n";
9947 }
9948 } /* for (all variable types) */
9949
9950 /* We will be using geometry shader to lay out the actual vertices so
9951 * the only thing we need to make sure is that the vertex never gets
9952 * culled.
9953 */
9954 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9955 "}\n";
9956
9957 /* That's it */
9958 return result_sstream.str();
9959 }
9960
9961 /** Initializes shader objects required to run the test. */
initTest()9962 void GPUShaderFP64Test7::initTest()
9963 {
9964 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9965
9966 /* Are double-precision input variables supported? */
9967 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9968
9969 /* Create a vertex array object */
9970 gl.genVertexArrays(1, &m_vao_id);
9971 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9972
9973 gl.bindVertexArray(m_vao_id);
9974 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9975
9976 /* Create a texture object we will use as FBO's color attachment */
9977 gl.genTextures(1, &m_to_id);
9978 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9979
9980 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9981 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9982
9983 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9984 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9985
9986 /* Allocate temporary buffer to hold the texture data we will be reading
9987 * from color attachment. */
9988 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9989
9990 /* Create and set up a framebuffer object */
9991 gl.genFramebuffers(1, &m_fbo_id);
9992 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9993
9994 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9995 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
9996
9997 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
9998 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
9999
10000 /* Create all shader objects */
10001 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10002 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10003 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10004 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10005 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10006 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10007
10008 /* Create test program object */
10009 m_po_id = gl.createProgram();
10010 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10011
10012 /* Attach the shaders to the program object */
10013 gl.attachShader(m_po_id, m_fs_id);
10014 gl.attachShader(m_po_id, m_gs_id);
10015 gl.attachShader(m_po_id, m_tc_id);
10016 gl.attachShader(m_po_id, m_te_id);
10017 gl.attachShader(m_po_id, m_vs_id);
10018 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10019
10020 /* The test passes double-precision values through the whole rendering pipeline.
10021 * This translates to a notable amount of components that we would need to transfer
10022 * all values in one fell swoop. The number is large enough to exceed minimum
10023 * capabilities as described for OpenGL 4.0 implementations.
10024 * For that reason, the test executes in turns. Each turn is allocated as many
10025 * double-precision scalar/matrix values as supported by the tested GL implementation.
10026 */
10027 glw::GLint gl_max_fragment_input_components_value = 0;
10028 glw::GLint gl_max_geometry_input_components_value = 0;
10029 glw::GLint gl_max_geometry_output_components_value = 0;
10030 glw::GLint gl_max_tess_control_input_components_value = 0;
10031 glw::GLint gl_max_tess_control_output_components_value = 0;
10032 glw::GLint gl_max_tess_evaluation_input_components_value = 0;
10033 glw::GLint gl_max_tess_evaluation_output_components_value = 0;
10034 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10035 glw::GLint gl_max_vertex_output_components_value = 0;
10036
10037 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10038 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10039 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10040 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10041 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10042 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10043 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10044 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10045 &gl_max_transform_feedback_interleaved_components_value);
10046 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10047 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10048
10049 m_n_max_components_per_stage =
10050 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10051 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10052 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10053 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10054 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10055 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10056 m_n_max_components_per_stage =
10057 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10058 m_n_max_components_per_stage =
10059 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10060
10061 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10062 * the input patch */
10063 gl.patchParameteri(GL_PATCH_VERTICES, 1);
10064
10065 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10066
10067 /* Initialize a BO we will use to hold XFB data */
10068 gl.genBuffers(1, &m_xfb_bo_id);
10069 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10070
10071 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10072 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10073
10074 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10075 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10076 }
10077
10078 /** Executes test iteration.
10079 *
10080 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10081 */
iterate()10082 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10083 {
10084 /* Do not execute the test if GL_ARB_texture_view is not supported */
10085 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10086 {
10087 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10088 }
10089
10090 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10091 {
10092 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10093 }
10094
10095 /* Initialize GL objects required to run the test */
10096 initTest();
10097
10098 /* Check the negative cases first */
10099 const Utils::_variable_type double_variable_types[] = {
10100 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10101 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10102 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10103 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10104 Utils::VARIABLE_TYPE_DMAT4X3,
10105 };
10106 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10107
10108 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10109 ++n_double_variable_type)
10110 {
10111 for (unsigned int array_size = 1; array_size < 3; ++array_size)
10112 {
10113 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10114
10115 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10116 {
10117 m_testCtx.getLog() << tcu::TestLog::Message
10118 << "A fragment shader with double-precision output variable compiled successfully."
10119 << tcu::TestLog::EndMessage;
10120
10121 m_has_test_passed = false;
10122 }
10123
10124 if (compileShader(m_fs_id,
10125 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10126 {
10127 m_testCtx.getLog()
10128 << tcu::TestLog::Message
10129 << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10130 " compiled successfully."
10131 << tcu::TestLog::EndMessage;
10132
10133 m_has_test_passed = false;
10134 }
10135 }
10136 } /* for (all variable types) */
10137
10138 /* Execute functional test. Split the run into as many iterations as necessary
10139 * so that we do not exceed GL implementation's capabilities. */
10140 unsigned int n_tested_variables = 0;
10141 _variables variables_to_test;
10142
10143 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10144 {
10145 glw::GLint total_n_used_components = 0;
10146
10147 /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10148 * of varying components that can be used for all shadr stages.
10149 */
10150 while (total_n_used_components < m_n_max_components_per_stage &&
10151 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10152 {
10153 _variable new_variable;
10154 unsigned int n_type_components = 0;
10155 glw::GLint n_used_components = 0;
10156
10157 new_variable.array_size =
10158 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10159 new_variable.type = double_variable_types[n_tested_variables / 2];
10160
10161 /* Double-precision varyings can use twice as many components as single-precision FPs */
10162 n_type_components = 4 /* components per location */ *
10163 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10164 n_used_components = n_type_components * new_variable.array_size * 2;
10165
10166 /* Do we have enough space? */
10167 if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10168 {
10169 if (n_used_components > m_n_max_components_per_stage)
10170 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10171 n_tested_variables++;
10172 }
10173 break;
10174 }
10175
10176 /* We can safely test the type in current iteration */
10177 total_n_used_components += n_used_components;
10178 n_tested_variables++;
10179
10180 variables_to_test.push_back(new_variable);
10181 }
10182
10183 if (variables_to_test.size() > 0)
10184 {
10185 m_has_test_passed &= executeFunctionalTest(variables_to_test);
10186
10187 variables_to_test.clear();
10188 }
10189 }
10190
10191 /* We're done */
10192 if (m_has_test_passed)
10193 {
10194 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10195 }
10196 else
10197 {
10198 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10199 }
10200
10201 return STOP;
10202 }
10203
10204 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10205 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10206 {
10207 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10208 std::stringstream log_sstream;
10209
10210 log_sstream << "Test variable values as retrieved from geometry shader:\n";
10211
10212 /* Map the XFB BO contents into process space */
10213 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10214
10215 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10216
10217 /* Read the variable contents. We only care about the set of varyings emitted
10218 * for first vertex in the geometry shader */
10219 unsigned int n_varying = 0;
10220 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10221
10222 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10223 ++variables_iterator, ++n_varying)
10224 {
10225 const _variable& variable = *variables_iterator;
10226 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10227 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10228
10229 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10230 {
10231 log_sstream << "gs_variable" << n_varying;
10232
10233 if (variable.array_size > 1)
10234 {
10235 log_sstream << "[" << array_index << "]";
10236 }
10237
10238 log_sstream << ": (";
10239
10240 for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10241 {
10242 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10243
10244 if (n_component != (n_components - 1))
10245 {
10246 log_sstream << ", ";
10247 }
10248
10249 traveller_ptr += sizeof(double);
10250 }
10251
10252 log_sstream << ")\n";
10253 } /* for (all array indices) */
10254 } /* for (all variables) */
10255
10256 /* Unmap the BO */
10257 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10258 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10259
10260 /* Pass the logged stream into the framework */
10261 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10262 }
10263
10264 /** De-allocates an arary holding strings representing names of varyings that
10265 * should be used for transform feed-back.
10266 **/
releaseXFBVaryingNames()10267 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10268 {
10269 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10270 {
10271 delete[] m_xfb_varyings[n_varying];
10272 }
10273
10274 delete[] m_xfb_varyings;
10275 m_xfb_varyings = DE_NULL;
10276
10277 m_n_xfb_varyings = 0;
10278 }
10279
10280 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10281 * Takes a list of test variables used for current iteration and assigns increasing values
10282 * to subsequent input attributes of the test program.
10283 *
10284 * @param variables Test variables of the current iteration.
10285 */
setInputAttributeValues(const _variables & variables)10286 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10287 {
10288 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10289
10290 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10291 variable_iterator++)
10292 {
10293 const _variable& variable = *variable_iterator;
10294 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type);
10295 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10296 unsigned int n_components = 0;
10297 unsigned int n_columns = 1;
10298
10299 if (is_matrix_type)
10300 {
10301 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type);
10302 n_components = n_total_components / n_columns;
10303
10304 DE_ASSERT(n_total_components % n_columns == 0);
10305 }
10306 else
10307 {
10308 n_components = n_total_components;
10309 }
10310
10311 DE_ASSERT(n_components >= 1 && n_components <= 4);
10312
10313 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10314 {
10315 const double data[] = { -1, -1, -1, -1 };
10316
10317 switch (n_components)
10318 {
10319 case 1:
10320 {
10321 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10322 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10323
10324 break;
10325 }
10326
10327 case 2:
10328 {
10329 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10330 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10331
10332 break;
10333 }
10334
10335 case 3:
10336 {
10337 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10338 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10339
10340 break;
10341 }
10342
10343 case 4:
10344 {
10345 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10346 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10347
10348 break;
10349 }
10350
10351 default:
10352 {
10353 TCU_FAIL("Unrecognized number of components");
10354 }
10355 } /* switch (n_components) */
10356
10357 /* Make sure VAAs are disabled */
10358 gl.disableVertexAttribArray(variable.attribute_location + index);
10359 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10360 } /* for (all array indices) */
10361 } /* for (all variables) */
10362 }
10363
10364 /** Constructor
10365 *
10366 * @param context Rendering context.
10367 */
GPUShaderFP64Test8(deqp::Context & context)10368 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10369 : TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10370 "are accepted during compilation stage")
10371 , m_cs_id(0)
10372 , m_fs_id(0)
10373 , m_gs_id(0)
10374 , m_tc_id(0)
10375 , m_te_id(0)
10376 , m_vs_id(0)
10377 , m_has_test_passed(true)
10378 {
10379 }
10380
10381 /** Deinitializes all buffers and GL objects that may have been generated
10382 * during test execution.
10383 **/
deinit()10384 void GPUShaderFP64Test8::deinit()
10385 {
10386 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10387
10388 if (m_cs_id != 0)
10389 {
10390 gl.deleteShader(m_cs_id);
10391
10392 m_cs_id = 0;
10393 }
10394
10395 if (m_fs_id != 0)
10396 {
10397 gl.deleteShader(m_fs_id);
10398
10399 m_fs_id = 0;
10400 }
10401
10402 if (m_gs_id != 0)
10403 {
10404 gl.deleteShader(m_gs_id);
10405
10406 m_gs_id = 0;
10407 }
10408
10409 if (m_tc_id != 0)
10410 {
10411 gl.deleteShader(m_tc_id);
10412
10413 m_tc_id = 0;
10414 }
10415
10416 if (m_te_id != 0)
10417 {
10418 gl.deleteShader(m_te_id);
10419
10420 m_te_id = 0;
10421 }
10422
10423 if (m_vs_id != 0)
10424 {
10425 gl.deleteShader(m_vs_id);
10426
10427 m_vs_id = 0;
10428 }
10429 }
10430
10431 /** Executes a single test case.
10432 *
10433 * This function can throw TestError exceptions if GL implementation reports
10434 * an error.
10435 *
10436 * @param test_case Test case descriptor.
10437 *
10438 * @return true if test case passed, false otherwise.
10439 **/
executeIteration(const _test_case & test_case)10440 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10441 {
10442 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10443 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10444 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
10445 bool result = true;
10446 const char* stage_body = NULL;
10447 const char* stage_name = NULL;
10448
10449 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10450 {
10451 const glw::GLuint so_id = so_ids[n_so_id];
10452
10453 /* Skip compute shader if it is not supported */
10454 if (0 == so_id)
10455 {
10456 continue;
10457 }
10458
10459 /* Compile the shader */
10460 gl.compileShader(so_id);
10461 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10462
10463 /* Has the compilation succeeded as expected? */
10464 glw::GLint compile_status = GL_FALSE;
10465
10466 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10467 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10468
10469 if (compile_status == GL_FALSE)
10470 {
10471 /* What is the current stage's name? */
10472 if (so_id == m_cs_id)
10473 {
10474 stage_body = test_case.cs_shader_body.c_str();
10475 stage_name = "Compute shader";
10476 }
10477 else if (so_id == m_fs_id)
10478 {
10479 stage_body = test_case.fs_shader_body.c_str();
10480 stage_name = "Fragment shader";
10481 }
10482 else if (so_id == m_gs_id)
10483 {
10484 stage_body = test_case.gs_shader_body.c_str();
10485 stage_name = "Geometry shader";
10486 }
10487 else if (so_id == m_tc_id)
10488 {
10489 stage_body = test_case.tc_shader_body.c_str();
10490 stage_name = "Tessellation control shader";
10491 }
10492 else if (so_id == m_te_id)
10493 {
10494 stage_body = test_case.te_shader_body.c_str();
10495 stage_name = "Tessellation evaluation shader";
10496 }
10497 else if (so_id == m_vs_id)
10498 {
10499 stage_body = test_case.vs_shader_body.c_str();
10500 stage_name = "Vertex shader";
10501 }
10502 else
10503 {
10504 /* Doesn't make much sense to throw exceptions here so.. */
10505 stage_body = "";
10506 stage_name = "[?]";
10507 }
10508
10509 /* This shader should have never failed to compile! */
10510 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10511 << " has not compiled successfully, even though the shader is valid."
10512 " Following is shader's body:\n"
10513 << stage_body << tcu::TestLog::EndMessage;
10514
10515 result = false;
10516 }
10517 } /* for (all shader objects) */
10518
10519 return result;
10520 }
10521
10522 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10523 * type.
10524 *
10525 * @param variable_type Variable type to return valid argument lists for.
10526 **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10527 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10528 const Utils::_variable_type& variable_type)
10529 {
10530 const Utils::_variable_type matrix_types[] = {
10531 Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10532 Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10533 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10534 };
10535 const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10536 Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10537 const unsigned int n_matrix_types = sizeof(matrix_types) / sizeof(matrix_types[0]);
10538 const unsigned int n_scalar_types = sizeof(scalar_types) / sizeof(scalar_types[0]);
10539 const int n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10540
10541 /* Construct the argument list tree root. Each node carries a counter that tells how many components
10542 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10543 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10544 * used to define a subsequent argument, and its counter is increased by the amount of components
10545 * described by the type.
10546 */
10547 _argument_list_tree_node root;
10548
10549 root.n_components_used = 0;
10550 root.parent = NULL;
10551 root.type = variable_type;
10552
10553 /* Fill till all leaves use up all available components */
10554 _argument_list_tree_node_queue nodes_queue;
10555
10556 nodes_queue.push(&root);
10557
10558 do
10559 {
10560 /* Pop the first item in the queue */
10561 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10562 nodes_queue.pop();
10563
10564 /* Matrix variable types can be defined by a combination of non-matrix variable types OR
10565 * a single matrix variable type.
10566 *
10567 * Let's handle the latter case first.
10568 */
10569 const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10570
10571 if (Utils::isMatrixVariableType(current_node_ptr->type))
10572 {
10573 /* Iterate through all known matrix types. All the types can be used
10574 * as a constructor, assuming only one value is used to define new matrix's
10575 * contents. */
10576 for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10577 {
10578 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10579
10580 /* Construct a new child node. Since GLSL spec clearly states we must not use more
10581 * than one constructor argument if the only argument is a matrix type, mark the node
10582 * as if it defined all available components.
10583 */
10584 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10585
10586 new_subnode->n_components_used = n_total_components;
10587 new_subnode->parent = current_node_ptr;
10588 new_subnode->type = new_argument_type;
10589
10590 /* Add the descriptor to node list but do not add it to the queue. This would be
10591 * a redundant operation, since no new children nodes would have been assigned to
10592 * this node anyway.
10593 */
10594 current_node_ptr->children.push_back(new_subnode);
10595 } /* for (all matrix types) */
10596 } /* if (current node's type is a matrix) */
10597
10598 /* Now for a combination of non-matrix variable types.. */
10599 if (!Utils::isMatrixVariableType(current_node_ptr->type))
10600 {
10601 /* Iterate through all known scalar types */
10602 for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10603 {
10604 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10605 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10606
10607 /* Only use the scalar type if we don't exceed the amount of components we can define
10608 * for requested type.
10609 */
10610 if (n_new_argument_components <= n_components_remaining)
10611 {
10612 /* Form new node descriptor */
10613 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10614
10615 new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10616 new_subnode->parent = current_node_ptr;
10617 new_subnode->type = new_argument_type;
10618
10619 current_node_ptr->children.push_back(new_subnode);
10620 nodes_queue.push(new_subnode);
10621 }
10622 } /* for (all scalar types) */
10623 } /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10624 } while (nodes_queue.size() > 0);
10625
10626 /* To construct the argument lists, traverse the tree. Each path from root to child
10627 * gives us a single argument list.
10628 *
10629 * First, identify leaf nodes.
10630 */
10631 _argument_list_tree_nodes leaf_nodes;
10632
10633 nodes_queue.push(&root);
10634
10635 do
10636 {
10637 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10638 nodes_queue.pop();
10639
10640 if (current_node_ptr->children.size() == 0)
10641 {
10642 /* This is a leaf node !*/
10643 leaf_nodes.push_back(current_node_ptr);
10644 }
10645 else
10646 {
10647 /* Throw all children nodes to the queue */
10648 const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10649
10650 for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10651 {
10652 nodes_queue.push(current_node_ptr->children[n_children_node]);
10653 } /* for (all children nodes) */
10654 }
10655 } while (nodes_queue.size() > 0);
10656
10657 /* For all leaf nodes, move up the tree and construct the argument lists. */
10658 const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10659 _argument_lists result;
10660
10661 for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10662 {
10663 _argument_list argument_list;
10664 _argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10665
10666 do
10667 {
10668 if (current_node_ptr != &root)
10669 {
10670 if (argument_list.size() == 0)
10671 {
10672 argument_list.push_back(current_node_ptr->type);
10673 }
10674 else
10675 {
10676 argument_list.insert(argument_list.begin(), current_node_ptr->type);
10677 }
10678 }
10679
10680 current_node_ptr = current_node_ptr->parent;
10681 } while (current_node_ptr != NULL);
10682
10683 result.push_back(argument_list);
10684 } /* for (all leaf nodes) */
10685
10686 return result;
10687 }
10688
10689 /** Retrieves body of a compute shader that should be used for the purpose of
10690 * user-specified test case.
10691 *
10692 * @param test_case Test case descriptor to use.
10693 *
10694 * @return Requested string.
10695 **/
getComputeShaderBody(const _test_case & test_case)10696 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10697 {
10698 std::stringstream result_sstream;
10699
10700 /* Form the body */
10701 result_sstream << "#version 420\n"
10702 "#extension GL_ARB_compute_shader : require\n"
10703 "\n"
10704 "layout(local_size_x = 1) in;\n"
10705 "\n"
10706 "void main()\n"
10707 "{\n"
10708 << getGeneralBody(test_case) << "}\n";
10709
10710 /* Return the body */
10711 return result_sstream.str();
10712 }
10713
10714 /** Retrieves body of a fragment shader that should be used for the purpose of
10715 * user-specified test case.
10716 *
10717 * @param test_case Test case descriptor to use.
10718 *
10719 * @return Requested string.
10720 **/
getFragmentShaderBody(const _test_case & test_case)10721 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10722 {
10723 std::stringstream result_sstream;
10724
10725 /* Form the body */
10726 result_sstream << "#version 420\n"
10727 "\n"
10728 "void main()\n"
10729 "{\n"
10730 << getGeneralBody(test_case) << "}\n"
10731 "\n";
10732
10733 /* Return the body */
10734 return result_sstream.str();
10735 }
10736
10737 /** Returns a GLSL line that defines and initializes a variable as described by
10738 * user-specified test case descriptor.
10739 *
10740 * @param test_case Test case descriptor to use for the query.
10741 *
10742 * @return As per description
10743 **/
getGeneralBody(const _test_case & test_case)10744 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10745 {
10746 std::stringstream result_sstream;
10747
10748 /* Form the body */
10749 std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10750
10751 result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10752
10753 for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10754 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10755 {
10756 const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10757 std::string argument_variable_type_string = Utils::getVariableTypeString(argument_variable_type);
10758 const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10759
10760 if (argument_list_iterator != test_case.argument_list.begin())
10761 {
10762 result_sstream << ", ";
10763 }
10764
10765 result_sstream << argument_variable_type_string << "(";
10766
10767 for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10768 {
10769 result_sstream << (double)(n_component + 1);
10770
10771 if (n_component != (argument_n_components - 1))
10772 {
10773 result_sstream << ", ";
10774 }
10775 } /* for (all argument components) */
10776
10777 result_sstream << ")";
10778 } /* for (all arguments) */
10779
10780 result_sstream << ");\n";
10781
10782 return result_sstream.str();
10783 }
10784
10785 /** Retrieves body of a geometry shader that should be used for the purpose of
10786 * user-specified test case.
10787 *
10788 * @param test_case Test case descriptor to use.
10789 *
10790 * @return Requested string.
10791 **/
getGeometryShaderBody(const _test_case & test_case)10792 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10793 {
10794 std::stringstream result_sstream;
10795
10796 /* Form the body */
10797 result_sstream << "#version 420\n"
10798 "\n"
10799 "layout(points) in;\n"
10800 "layout(max_vertices=1, points) out;\n"
10801 "\n"
10802 "void main()\n"
10803 "{\n"
10804 << getGeneralBody(test_case) << "}\n"
10805 "\n";
10806
10807 /* We're done! */
10808 return result_sstream.str();
10809 }
10810
10811 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10812 * user-specified test case.
10813 *
10814 * @param test_case Test case descriptor to use.
10815 *
10816 * @return Requested string.
10817 **/
getTessellationControlShaderBody(const _test_case & test_case)10818 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10819 {
10820 std::stringstream result_sstream;
10821
10822 /* Form the body */
10823 result_sstream << "#version 420\n"
10824 "\n"
10825 "layout(vertices=4) out;\n"
10826 "\n"
10827 "void main()\n"
10828 "{\n"
10829 << getGeneralBody(test_case) << "}\n"
10830 "\n";
10831
10832 /* Return the body */
10833 return result_sstream.str();
10834 }
10835
10836 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10837 * user-specified test case.
10838 *
10839 * @param test_case Test case descriptor to use.
10840 *
10841 * @return Requested string.
10842 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10843 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10844 {
10845 std::stringstream result_sstream;
10846
10847 /* Form the body */
10848 result_sstream << "#version 420\n"
10849 "\n"
10850 "layout(isolines) in;\n"
10851 "\n"
10852 "void main()\n"
10853 "{\n"
10854 << getGeneralBody(test_case) << "}\n"
10855 "\n";
10856
10857 /* Return the body */
10858 return result_sstream.str();
10859 }
10860
10861 /** Retrieves body of a vertex shader that should be used for the purpose of
10862 * user-specified test case.
10863 *
10864 * @param test_case Test case descriptor to use.
10865 *
10866 * @return Requested string.
10867 **/
getVertexShaderBody(const _test_case & test_case)10868 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10869 {
10870 std::stringstream result_sstream;
10871
10872 /* Form the body */
10873 result_sstream << "#version 420\n"
10874 "\n"
10875 "void main()\n"
10876 "{\n"
10877 << getGeneralBody(test_case) << "}\n"
10878 "\n";
10879
10880 return result_sstream.str();
10881 }
10882
10883 /** Initializes shader objects required to run the test. */
initTest()10884 void GPUShaderFP64Test8::initTest()
10885 {
10886 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10887
10888 /* Generate shader objects */
10889
10890 /* Compute shader support and GL 4.2 required */
10891 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10892 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10893 {
10894 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10895 }
10896
10897 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10898 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10899 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10900 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10901 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10902
10903 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10904 }
10905
10906 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10907 *
10908 * @param test_case Test case descriptor to generate the shader bodies for.
10909 **/
initIteration(_test_case & test_case)10910 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10911 {
10912 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10913
10914 test_case.cs_shader_body = getComputeShaderBody(test_case);
10915 test_case.fs_shader_body = getFragmentShaderBody(test_case);
10916 test_case.gs_shader_body = getGeometryShaderBody(test_case);
10917 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10918 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10919 test_case.vs_shader_body = getVertexShaderBody(test_case);
10920
10921 /* Assign the bodies to relevant shaders */
10922 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10923 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10924 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10925 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10926 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10927 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10928
10929 /* m_cs_id is initialized only if compute_shader is supported */
10930 if (0 != m_cs_id)
10931 {
10932 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10933 }
10934
10935 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10936 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10937 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10938 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10939 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10940 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10941 }
10942
10943 /** Executes test iteration.
10944 *
10945 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10946 */
iterate()10947 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10948 {
10949 /* Do not execute the test if GL_ARB_texture_view is not supported */
10950 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10951 {
10952 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10953 }
10954
10955 /* Initialize GL objects needed to run the tests */
10956 initTest();
10957
10958 /* Build iteration array to run the tests in an automated manner */
10959 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10960 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10961 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10962 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10963 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10964 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10965 Utils::VARIABLE_TYPE_DVEC4 };
10966 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10967
10968 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10969 {
10970 const Utils::_variable_type variable_type = variable_types[n_variable_type];
10971
10972 /* Construct a set of argument lists valid for the variable type considered */
10973 _argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10974
10975 for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10976 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10977 {
10978 /* Constructor thwe test case descriptor */
10979 _test_case test_case;
10980
10981 test_case.argument_list = *argument_list_iterator;
10982 test_case.type = variable_type;
10983
10984 /* Initialize a program object we will use to perform the casting */
10985 initIteration(test_case);
10986
10987 /* See if the shader compiles. */
10988 m_has_test_passed &= executeIteration(test_case);
10989 } /* for (all argument lists) */
10990 } /* for (all variable types) */
10991
10992 /* We're done */
10993 if (m_has_test_passed)
10994 {
10995 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10996 }
10997 else
10998 {
10999 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11000 }
11001
11002 return STOP;
11003 }
11004
11005 /** Constructor.
11006 *
11007 * @param context Rendering context.
11008 *
11009 **/
GPUShaderFP64Test9(deqp::Context & context)11010 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11011 : TestCase(context, "operators", "Verifies that general and relational operators work "
11012 "correctly when used against double-precision floating-"
11013 "point types.")
11014 , m_has_test_passed(true)
11015 , m_po_id(0)
11016 , m_xfb_bo_id(0)
11017 , m_vao_id(0)
11018 , m_vs_id(0)
11019 {
11020 /* Left blank intentionally */
11021 }
11022
11023 /** Deinitializes all ES objects that may have been created during
11024 * test execution.
11025 **/
deinit()11026 void GPUShaderFP64Test9::deinit()
11027 {
11028 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11029
11030 if (m_po_id != 0)
11031 {
11032 gl.deleteProgram(m_po_id);
11033
11034 m_po_id = 0;
11035 }
11036
11037 if (m_xfb_bo_id != 0)
11038 {
11039 gl.deleteBuffers(1, &m_xfb_bo_id);
11040
11041 m_xfb_bo_id = 0;
11042 }
11043
11044 if (m_vao_id != 0)
11045 {
11046 gl.deleteVertexArrays(1, &m_vao_id);
11047
11048 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11049 }
11050
11051 if (m_vs_id != 0)
11052 {
11053 gl.deleteShader(m_vs_id);
11054
11055 m_vs_id = 0;
11056 }
11057 }
11058
11059 /** Executes a single test iteration using user-specified test case properties.
11060 *
11061 * @param test_case Test case descriptor.
11062 *
11063 * @return true if the pass was successful, false if the test should fail.
11064 **/
executeTestIteration(const _test_case & test_case)11065 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11066 {
11067 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11068 bool result = true;
11069
11070 /* Activate the test program object */
11071 gl.useProgram(m_po_id);
11072 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11073
11074 /* Draw a single point with XFB enabled */
11075 gl.beginTransformFeedback(GL_POINTS);
11076 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11077 {
11078 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11079 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11080 }
11081 gl.endTransformFeedback();
11082 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11083
11084 /* Map the XFB BO into process space */
11085 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11086
11087 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11088
11089 result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11090
11091 /* Unmap the BO */
11092 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11093 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11094
11095 return result;
11096 }
11097
11098 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11099 * under user-specified location.
11100 *
11101 * @param matrix_a_type Type of the l-side matrix.
11102 * @param matrix_a_data Row-ordered data of l-side matrix.
11103 * @param matrix_b_type Type of the r-side matrix.
11104 * @param matrix_b_data Row-ordered data of r-side matrix.
11105 * @param out_result_ptr Deref to be used to store the multiplication result.
11106 **/
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)11107 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11108 const std::vector<double>& matrix_a_data,
11109 const Utils::_variable_type& matrix_b_type,
11110 const std::vector<double>& matrix_b_data, double* out_result_ptr)
11111 {
11112 (void)matrix_b_type;
11113 using namespace tcu;
11114 /* To keep the code maintainable, we only consider cases relevant for this test */
11115 switch (matrix_a_type)
11116 {
11117 case Utils::VARIABLE_TYPE_DMAT2:
11118 {
11119 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11120
11121 tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11122 tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11123 tcu::Matrix2d result;
11124
11125 matrix_a = transpose(matrix_a);
11126 matrix_b = transpose(matrix_b);
11127 result = matrix_a * matrix_b;
11128
11129 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11130 break;
11131 }
11132
11133 case Utils::VARIABLE_TYPE_DMAT2X3:
11134 {
11135 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11136
11137 tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11138 tcu::Matrix<double, 3, 2> matrix_a_transposed;
11139 tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11140 tcu::Matrix<double, 2, 3> matrix_b_transposed;
11141 tcu::Matrix<double, 3, 3> result;
11142
11143 matrix_a_transposed = transpose(matrix_a);
11144 matrix_b_transposed = transpose(matrix_b);
11145 result = matrix_a_transposed * matrix_b_transposed;
11146
11147 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11148 break;
11149 }
11150
11151 case Utils::VARIABLE_TYPE_DMAT2X4:
11152 {
11153 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11154
11155 tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11156 tcu::Matrix<double, 4, 2> matrix_a_transposed;
11157 tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11158 tcu::Matrix<double, 2, 4> matrix_b_transposed;
11159 tcu::Matrix<double, 4, 4> result;
11160
11161 matrix_a_transposed = transpose(matrix_a);
11162 matrix_b_transposed = transpose(matrix_b);
11163 result = matrix_a_transposed * matrix_b_transposed;
11164
11165 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11166 break;
11167 }
11168
11169 case Utils::VARIABLE_TYPE_DMAT3:
11170 {
11171 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11172
11173 tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11174 tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11175 tcu::Matrix<double, 3, 3> result;
11176
11177 matrix_a = transpose(matrix_a);
11178 matrix_b = transpose(matrix_b);
11179 result = matrix_a * matrix_b;
11180
11181 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11182 break;
11183 }
11184
11185 case Utils::VARIABLE_TYPE_DMAT3X2:
11186 {
11187 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11188
11189 tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11190 tcu::Matrix<double, 2, 3> matrix_a_transposed;
11191 tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11192 tcu::Matrix<double, 3, 2> matrix_b_transposed;
11193 tcu::Matrix<double, 2, 2> result;
11194
11195 matrix_a_transposed = transpose(matrix_a);
11196 matrix_b_transposed = transpose(matrix_b);
11197 result = matrix_a_transposed * matrix_b_transposed;
11198
11199 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11200 break;
11201 }
11202
11203 case Utils::VARIABLE_TYPE_DMAT3X4:
11204 {
11205 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11206
11207 tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11208 tcu::Matrix<double, 4, 3> matrix_a_transposed;
11209 tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11210 tcu::Matrix<double, 3, 4> matrix_b_transposed;
11211 tcu::Matrix<double, 4, 4> result;
11212
11213 matrix_a_transposed = transpose(matrix_a);
11214 matrix_b_transposed = transpose(matrix_b);
11215 result = matrix_a_transposed * matrix_b_transposed;
11216
11217 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11218 break;
11219 }
11220
11221 case Utils::VARIABLE_TYPE_DMAT4:
11222 {
11223 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11224
11225 tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11226 tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11227 tcu::Matrix<double, 4, 4> result;
11228
11229 matrix_a = transpose(matrix_a);
11230 matrix_b = transpose(matrix_b);
11231 result = matrix_a * matrix_b;
11232
11233 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11234 break;
11235 }
11236
11237 case Utils::VARIABLE_TYPE_DMAT4X2:
11238 {
11239 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11240
11241 tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11242 tcu::Matrix<double, 2, 4> matrix_a_transposed;
11243 tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11244 tcu::Matrix<double, 4, 2> matrix_b_transposed;
11245 tcu::Matrix<double, 2, 2> result;
11246
11247 matrix_a_transposed = transpose(matrix_a);
11248 matrix_b_transposed = transpose(matrix_b);
11249 result = matrix_a_transposed * matrix_b_transposed;
11250
11251 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11252 break;
11253 }
11254
11255 case Utils::VARIABLE_TYPE_DMAT4X3:
11256 {
11257 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11258
11259 tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11260 tcu::Matrix<double, 3, 4> matrix_a_transposed;
11261 tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11262 tcu::Matrix<double, 4, 3> matrix_b_transposed;
11263 tcu::Matrix<double, 3, 3> result;
11264
11265 matrix_a_transposed = transpose(matrix_a);
11266 matrix_b_transposed = transpose(matrix_b);
11267 result = matrix_a_transposed * matrix_b_transposed;
11268
11269 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11270 break;
11271 }
11272
11273 default:
11274 {
11275 TCU_FAIL("Unrecognized matrix A type");
11276 }
11277 } /* switch (matrix_a_type) */
11278 }
11279
11280 /** Returns GLSL operator representation of the user-specified operation.
11281 *
11282 * @param operation_type Internal operation type to retrieve the operator for.
11283 *
11284 * @return As per description.
11285 **/
getOperatorForOperationType(const _operation_type & operation_type)11286 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11287 {
11288 const char* result = NULL;
11289
11290 switch (operation_type)
11291 {
11292 case OPERATION_TYPE_ADDITION:
11293 result = "+";
11294 break;
11295 case OPERATION_TYPE_DIVISION:
11296 result = "/";
11297 break;
11298 case OPERATION_TYPE_MULTIPLICATION:
11299 result = "*";
11300 break;
11301 case OPERATION_TYPE_SUBTRACTION:
11302 result = "-";
11303 break;
11304
11305 case OPERATION_TYPE_PRE_DECREMENTATION:
11306 case OPERATION_TYPE_POST_DECREMENTATION:
11307 {
11308 result = "--";
11309
11310 break;
11311 }
11312
11313 case OPERATION_TYPE_PRE_INCREMENTATION:
11314 case OPERATION_TYPE_POST_INCREMENTATION:
11315 {
11316 result = "++";
11317
11318 break;
11319 }
11320
11321 default:
11322 {
11323 TCU_FAIL("Unrecognized operation type");
11324 }
11325 } /* switch(operation_type) */
11326
11327 return result;
11328 }
11329
11330 /** Returns a string representing user-specified operation type.
11331 *
11332 * @param operation_type Operation type to return the literal for.
11333 *
11334 * @return Requested string.
11335 **/
getOperationTypeString(const _operation_type & operation_type)11336 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11337 {
11338 std::string result = "[?]";
11339
11340 switch (operation_type)
11341 {
11342 case OPERATION_TYPE_ADDITION:
11343 result = "addition";
11344 break;
11345 case OPERATION_TYPE_DIVISION:
11346 result = "division";
11347 break;
11348 case OPERATION_TYPE_MULTIPLICATION:
11349 result = "multiplication";
11350 break;
11351 case OPERATION_TYPE_SUBTRACTION:
11352 result = "subtraction";
11353 break;
11354 case OPERATION_TYPE_PRE_DECREMENTATION:
11355 result = "pre-decrementation";
11356 break;
11357 case OPERATION_TYPE_PRE_INCREMENTATION:
11358 result = "pre-incrementation";
11359 break;
11360 case OPERATION_TYPE_POST_DECREMENTATION:
11361 result = "post-decrementation";
11362 break;
11363 case OPERATION_TYPE_POST_INCREMENTATION:
11364 result = "post-incrementation";
11365 break;
11366
11367 default:
11368 {
11369 TCU_FAIL("Unrecognized operation type");
11370 }
11371 }
11372
11373 return result;
11374 }
11375
11376 /** Returns body of a vertex shader that should be used for user-specified test case
11377 * descriptor.
11378 *
11379 * @param test_case Test case descriptor.
11380 *
11381 * @return Requested GLSL shader body.
11382 **/
getVertexShaderBody(_test_case & test_case)11383 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11384 {
11385 std::stringstream result_sstream;
11386 std::string result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11387 std::string variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11388 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11389 const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11390
11391 /* If we are to multiply matrices, we will need to use a different type
11392 * for the result variable if either of the matrices is not square.
11393 */
11394 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11395 Utils::isMatrixVariableType(test_case.variable_type))
11396 {
11397 Utils::_variable_type result_variable_type;
11398 Utils::_variable_type transposed_matrix_variable_type =
11399 Utils::getTransposedMatrixVariableType(test_case.variable_type);
11400
11401 result_variable_type =
11402 Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11403 result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11404
11405 test_case.result_variable_type = result_variable_type;
11406 }
11407
11408 /* Form the pre-amble */
11409 result_sstream << "#version 400\n"
11410 "\n"
11411
11412 /* Add output variables */
11413 "out "
11414 << result_variable_type_string << " result;\n"
11415 "out ivec2 result_lt;\n"
11416 "out ivec2 result_lte;\n"
11417 "out ivec2 result_gt;\n"
11418 "out ivec2 result_gte;\n"
11419 "void main()\n"
11420 "{\n";
11421
11422 /* Form reference values */
11423 result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11424
11425 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11426 {
11427 result_sstream << (n_variable_component + 1);
11428
11429 if (n_variable_component != (n_variable_components - 1))
11430 {
11431 result_sstream << ", ";
11432 }
11433 } /* for (all variable components) */
11434
11435 result_sstream << ");\n";
11436
11437 for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11438 ++n_ref2_case)
11439 {
11440 Utils::_variable_type compatible_variable_type = test_case.variable_type;
11441
11442 if (Utils::isMatrixVariableType(compatible_variable_type) &&
11443 test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11444 {
11445 compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11446 }
11447
11448 std::string ref2_variable_type_fp_string =
11449 Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11450 std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11451 std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11452 std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11453
11454 result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11455
11456 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11457 ++n_variable_component)
11458 {
11459 result_sstream << (n_variable_components - (n_variable_component + 1));
11460
11461 if (n_variable_component != (n_variable_components - 1))
11462 {
11463 result_sstream << ", ";
11464 }
11465 } /* for (all variable components) */
11466
11467 result_sstream << ");\n";
11468 } /* for (both reference2 declarations) */
11469
11470 /* Add actual body */
11471 result_sstream << "\n"
11472 "result = ";
11473
11474 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11475 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11476 {
11477 result_sstream << getOperatorForOperationType(test_case.operation_type);
11478 }
11479
11480 result_sstream << "reference1 ";
11481
11482 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11483 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11484 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11485 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11486 {
11487 if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11488 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11489 {
11490 result_sstream << getOperatorForOperationType(test_case.operation_type);
11491 }
11492 }
11493 else
11494 {
11495 result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11496 }
11497
11498 result_sstream << ";\n";
11499
11500 if (Utils::isScalarVariableType(test_case.variable_type))
11501 {
11502 result_sstream << "result_lt [0] = (reference1 < reference2) ? 1 : 0;\n"
11503 "result_lt [1] = (reference1 < reference2f) ? 1 : 0;\n"
11504 "result_lte[0] = (reference1 <= reference2) ? 1 : 0;\n"
11505 "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11506 "result_gt [0] = (reference1 > reference2) ? 1 : 0;\n"
11507 "result_gt [1] = (reference1 > reference2f) ? 1 : 0;\n"
11508 "result_gte[0] = (reference1 >= reference2) ? 1 : 0;\n"
11509 "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11510 }
11511 else
11512 {
11513 result_sstream << "result_lt [0] = 1;\n"
11514 "result_lt [1] = 1;\n"
11515 "result_lte[0] = 1;\n"
11516 "result_lte[1] = 1;\n"
11517 "result_gt [0] = 1;\n"
11518 "result_gt [1] = 1;\n"
11519 "result_gte[0] = 1;\n"
11520 "result_gte[1] = 1;\n";
11521 }
11522
11523 result_sstream << "}\n";
11524
11525 /* All done */
11526 return result_sstream.str();
11527 }
11528
11529 /** Initializes all GL objects required to run the test.
11530 *
11531 * This function can throw a TestError exception if the implementation misbehaves.
11532 */
initTest()11533 void GPUShaderFP64Test9::initTest()
11534 {
11535 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11536
11537 /* Create program & vertex shader objects */
11538 m_po_id = gl.createProgram();
11539 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11540
11541 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11542
11543 /* Attach the shader to the program */
11544 gl.attachShader(m_po_id, m_vs_id);
11545 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11546
11547 /* Set up a buffer object */
11548 gl.genBuffers(1, &m_xfb_bo_id);
11549 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11550
11551 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11552 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11553
11554 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11555 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11556
11557 /* Set up a vertex array object */
11558 gl.genVertexArrays(1, &m_vao_id);
11559 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11560
11561 gl.bindVertexArray(m_vao_id);
11562 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11563 }
11564
11565 /** Initializes all GL objects required to run an iteration described by
11566 * user-specified test case descriptor.
11567 *
11568 * @param test_case Test case descriptor to use for the initialization.
11569 **/
initTestIteration(_test_case & test_case)11570 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11571 {
11572 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11573 std::string vs_body = getVertexShaderBody(test_case);
11574 const char* vs_body_raw_ptr = vs_body.c_str();
11575
11576 /* Store the shader's body */
11577 test_case.vs_body = vs_body;
11578
11579 /* Try to compile the shader */
11580 glw::GLint compile_status = GL_FALSE;
11581
11582 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11583 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11584
11585 gl.compileShader(m_vs_id);
11586 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11587
11588 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11589 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11590
11591 if (compile_status != GL_TRUE)
11592 {
11593 TCU_FAIL("Test shader compilation failed.");
11594 }
11595
11596 /* Configure XFB */
11597 const char* xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11598 const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11599
11600 gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11601 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11602
11603 /* Try to link the program */
11604 glw::GLint link_status = GL_FALSE;
11605
11606 gl.linkProgram(m_po_id);
11607 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11608
11609 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11610 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11611
11612 if (link_status != GL_TRUE)
11613 {
11614 TCU_FAIL("Test program linking failure");
11615 }
11616
11617 /* Set up XFB BO data storage */
11618 const unsigned int result_variable_size = static_cast<unsigned int>(
11619 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11620 const unsigned int xfb_bo_size = static_cast<unsigned int>(
11621 result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11622
11623 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11624 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11625 }
11626
11627 /** Executes test iteration.
11628 *
11629 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11630 */
iterate()11631 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11632 {
11633 /* Do not execute the test if GL_ARB_texture_view is not supported */
11634 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11635 {
11636 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11637 }
11638
11639 /* Initialize all ES objects required to run all the checks */
11640 initTest();
11641
11642 /* Iterate through all variable types we want to test */
11643 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
11644 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11645 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11646 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
11647 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11648 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
11649 Utils::VARIABLE_TYPE_DVEC4 };
11650 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11651
11652 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11653 {
11654 /* Iterate through all operation types we want to check */
11655 for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11656 {
11657 _operation_type operation_type = (_operation_type)n_operation_type;
11658 const Utils::_variable_type& variable_type = variable_types[n_variable_type];
11659
11660 /* Construct test case descriptor */
11661 _test_case test_case;
11662
11663 test_case.operation_type = operation_type;
11664 test_case.result_variable_type = variable_type;
11665 test_case.variable_type = variable_type;
11666
11667 /* Run the iteration */
11668 initTestIteration(test_case);
11669
11670 m_has_test_passed &= executeTestIteration(test_case);
11671 } /* for (all operation types) */
11672 } /* for (all variable types) */
11673
11674 /* All done. */
11675 if (m_has_test_passed)
11676 {
11677 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11678 }
11679 else
11680 {
11681 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11682 }
11683
11684 return STOP;
11685 }
11686
11687 /** Verifies data XFBed out by the draw call for user-specified test case
11688 * descriptor.
11689 *
11690 * @param test_case Test case descriptor
11691 * @param xfb_data Buffer holding the data XFBed out during the draw call.
11692 * Must not be NULL.
11693 *
11694 * @return true if the data was found to be correct, false otherwise.
11695 **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11696 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11697 {
11698 const double epsilon = 1e-5;
11699 const unsigned int n_result_components =
11700 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11701 bool result = true;
11702 const double* xfb_data_result = (const double*)xfb_data;
11703 const int* xfb_data_result_lt = (const int*)(xfb_data_result + n_result_components);
11704 const int* xfb_data_result_lte = (const int*)xfb_data_result_lt + 2; /* cast/non-cast cases */
11705 const int* xfb_data_result_gt = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11706 const int* xfb_data_result_gte = (const int*)xfb_data_result_gt + 2; /* cast/non-cast cases */
11707
11708 /* Prepare reference values */
11709 int modifier;
11710 std::vector<double> reference1;
11711 std::vector<double> reference2;
11712
11713 if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11714 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11715 {
11716 modifier = 1;
11717 }
11718 else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11719 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11720 {
11721 modifier = -1;
11722 }
11723 else
11724 {
11725 modifier = 0;
11726 }
11727
11728 if (Utils::isMatrixVariableType(test_case.variable_type))
11729 {
11730 /* Matrices may be of different sizes so we need to compute the
11731 * reference values separately for each matrix
11732 */
11733 const Utils::_variable_type matrix_a_type = test_case.variable_type;
11734 const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11735 const unsigned int n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11736 const unsigned int n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11737
11738 for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11739 {
11740 reference1.push_back(modifier + n_component + 1);
11741 }
11742
11743 for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11744 {
11745 reference2.push_back(n_matrix_b_components - (n_component + 1));
11746 }
11747 } /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11748 else
11749 {
11750 /* Generate as many components as will be expected for the result variable */
11751 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11752 {
11753 reference1.push_back(modifier + n_result_component + 1);
11754 reference2.push_back(n_result_components - (n_result_component + 1));
11755 }
11756 }
11757
11758 /* Verify the result value(s) */
11759 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11760 Utils::isMatrixVariableType(test_case.variable_type))
11761 {
11762 /* Matrix multiplication */
11763 double expected_result_data[4 * 4];
11764 Utils::_variable_type matrix_a_type = test_case.variable_type;
11765 Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11766
11767 getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11768
11769 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11770 {
11771 if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11772 {
11773 std::stringstream log_sstream;
11774
11775 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11776 << Utils::getVariableTypeString(matrix_b_type)
11777 << " matrix multiplication was incorrect; expected:(";
11778
11779 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11780 ++n_logged_component)
11781 {
11782 log_sstream << expected_result_data[n_logged_component];
11783
11784 if (n_logged_component != (n_result_components - 1))
11785 {
11786 log_sstream << ", ";
11787 }
11788 } /* for (all components to be logged) */
11789
11790 log_sstream << "), retrieved:(";
11791
11792 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11793 ++n_logged_component)
11794 {
11795 log_sstream << xfb_data_result[n_logged_component];
11796
11797 if (n_logged_component != (n_result_components - 1))
11798 {
11799 log_sstream << ", ";
11800 }
11801 } /* for (all components to be logged) */
11802
11803 log_sstream << ")";
11804
11805 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11806
11807 result = false;
11808 break;
11809 }
11810 } /* for (all result components) */
11811 } /* if (dealing with matrix multiplication) */
11812 else
11813 {
11814 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11815 {
11816 double expected_value = reference1[n_component];
11817
11818 switch (test_case.operation_type)
11819 {
11820 case OPERATION_TYPE_ADDITION:
11821 expected_value += reference2[n_component];
11822 break;
11823 case OPERATION_TYPE_DIVISION:
11824 expected_value /= reference2[n_component];
11825 break;
11826 case OPERATION_TYPE_MULTIPLICATION:
11827 expected_value *= reference2[n_component];
11828 break;
11829 case OPERATION_TYPE_SUBTRACTION:
11830 expected_value -= reference2[n_component];
11831 break;
11832
11833 case OPERATION_TYPE_PRE_DECREMENTATION:
11834 case OPERATION_TYPE_PRE_INCREMENTATION:
11835 {
11836 /* Modifier already applied */
11837 break;
11838 }
11839
11840 case OPERATION_TYPE_POST_DECREMENTATION:
11841 case OPERATION_TYPE_POST_INCREMENTATION:
11842 {
11843 /* Need to reverse the modification for the purpose of the following check */
11844 expected_value -= modifier;
11845
11846 break;
11847 }
11848
11849 default:
11850 {
11851 TCU_FAIL("Unrecognized operation type");
11852 }
11853 } /* switch (test_case.operation_type) */
11854
11855 if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11856 {
11857 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11858 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11859
11860 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11861 << variable_type_string << "]"
11862 " and operation type ["
11863 << operation_type_string << "]"
11864 " were found invalid."
11865 << tcu::TestLog::EndMessage;
11866
11867 result = false;
11868 break;
11869 } /* if (test case failed) */
11870 } /* for (all components) */
11871 }
11872
11873 /* Verify the comparison operation results */
11874 if (Utils::isScalarVariableType(test_case.variable_type))
11875 {
11876 DE_ASSERT(n_result_components == 1);
11877
11878 const bool expected_result_lt[2] = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11879 const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11880 const bool expected_result_gt[2] = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11881 const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11882
11883 if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11884 (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11885 {
11886 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11887 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11888
11889 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11890 "variable type ["
11891 << variable_type_string << "]"
11892 "and operation type ["
11893 << operation_type_string << "]"
11894 "was found invalid; expected:("
11895 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11896 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11897 << tcu::TestLog::EndMessage;
11898
11899 result = false;
11900 }
11901
11902 if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11903 (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11904 {
11905 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11906 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11907
11908 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11909 "variable type ["
11910 << variable_type_string << "]"
11911 "and operation type ["
11912 << operation_type_string << "]"
11913 "was found invalid; expected:("
11914 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11915 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11916 << tcu::TestLog::EndMessage;
11917
11918 result = false;
11919 }
11920
11921 if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11922 (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11923 {
11924 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11925 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11926
11927 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11928 "variable type ["
11929 << variable_type_string << "]"
11930 "and operation type ["
11931 << operation_type_string << "]"
11932 "was found invalid; expected:("
11933 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11934 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11935 << tcu::TestLog::EndMessage;
11936
11937 result = false;
11938 }
11939
11940 if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11941 (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11942 {
11943 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11944 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11945
11946 m_testCtx.getLog() << tcu::TestLog::Message
11947 << "Values reported for greater-than-or-equal operator used for "
11948 "variable type ["
11949 << variable_type_string << "]"
11950 "and operation type ["
11951 << operation_type_string << "]"
11952 "was found invalid; expected:("
11953 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11954 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11955 << tcu::TestLog::EndMessage;
11956
11957 result = false;
11958 }
11959 } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11960 else
11961 {
11962 if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11963 xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11964 xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11965 {
11966 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11967 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11968
11969 m_testCtx.getLog() << tcu::TestLog::Message
11970 << "Invalid value was reported for matrix variable type, for which "
11971 " operator checks are not executed; variable type ["
11972 << variable_type_string << "]"
11973 "and operation type ["
11974 << operation_type_string << "]" << tcu::TestLog::EndMessage;
11975
11976 result = false;
11977 }
11978 }
11979
11980 return result;
11981 }
11982
11983 namespace TypeHelpers
11984 {
11985 /** Get base type for reference types
11986 *
11987 * @tparam T type
11988 **/
11989 template <typename T>
11990 class referenceToType
11991 {
11992 public:
11993 typedef T result;
11994 };
11995
11996 template <typename T>
11997 class referenceToType<const T&>
11998 {
11999 public:
12000 typedef T result;
12001 };
12002
12003 /** Maps variable type with enumeration Utils::_variable_type
12004 *
12005 * @tparam T type
12006 **/
12007 template <typename T>
12008 class typeInfo;
12009
12010 template <>
12011 class typeInfo<glw::GLboolean>
12012 {
12013 public:
12014 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12015 };
12016
12017 template <>
12018 class typeInfo<glw::GLdouble>
12019 {
12020 public:
12021 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12022 };
12023
12024 template <>
12025 class typeInfo<tcu::UVec2>
12026 {
12027 public:
12028 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12029 };
12030
12031 template <>
12032 class typeInfo<tcu::UVec3>
12033 {
12034 public:
12035 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12036 };
12037
12038 template <>
12039 class typeInfo<tcu::UVec4>
12040 {
12041 public:
12042 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12043 };
12044
12045 template <>
12046 class typeInfo<tcu::DVec2>
12047 {
12048 public:
12049 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12050 };
12051
12052 template <>
12053 class typeInfo<tcu::DVec3>
12054 {
12055 public:
12056 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12057 };
12058
12059 template <>
12060 class typeInfo<tcu::DVec4>
12061 {
12062 public:
12063 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12064 };
12065
12066 template <>
12067 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12068 {
12069 public:
12070 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12071 };
12072
12073 template <>
12074 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12075 {
12076 public:
12077 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12078 };
12079
12080 template <>
12081 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12082 {
12083 public:
12084 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12085 };
12086
12087 template <>
12088 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12089 {
12090 public:
12091 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12092 };
12093
12094 template <>
12095 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12096 {
12097 public:
12098 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12099 };
12100
12101 template <>
12102 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12103 {
12104 public:
12105 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12106 };
12107
12108 template <>
12109 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12110 {
12111 public:
12112 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12113 };
12114
12115 template <>
12116 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12117 {
12118 public:
12119 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12120 };
12121
12122 template <>
12123 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12124 {
12125 public:
12126 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12127 };
12128 } /* TypeHelpers */
12129
12130 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12131 *
12132 **/
12133 namespace Math
12134 {
12135 template <typename T>
12136 static T clamp(T x, T minVal, T maxVal);
12137
12138 template <int Size>
12139 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12140
12141 template <int Size>
12142 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12143
12144 template <typename T>
12145 static T determinant(T val);
12146
12147 template <typename T>
12148 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12149
12150 template <typename T>
12151 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12152
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12155
12156 template <int Size>
12157 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12158 glw::GLuint column, glw::GLuint row);
12159
12160 template <int Size>
12161 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12162 const tcu::Vector<glw::GLdouble, Size>& right);
12163
12164 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12165
12166 static glw::GLdouble fract(glw::GLdouble val);
12167
12168 template <typename T>
12169 static T frexp(T val, glw::GLint& exp);
12170
12171 template <int Size>
12172 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12173 const tcu::Vector<glw::GLdouble, Size>& right);
12174
12175 template <int Size>
12176 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12177 const tcu::Vector<glw::GLdouble, Size>& right);
12178
12179 template <int Size>
12180 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12181
12182 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12183
12184 static glw::GLuint isinf_impl(glw::GLdouble val);
12185
12186 static glw::GLuint isnan_impl(glw::GLdouble val);
12187
12188 template <typename T>
12189 static T ldexp(T val, glw::GLint exp);
12190
12191 template <int Size>
12192 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12193 const tcu::Vector<glw::GLdouble, Size>& right);
12194
12195 template <int Size>
12196 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12197 const tcu::Vector<glw::GLdouble, Size>& right);
12198
12199 template <typename T>
12200 static T max(T left, T right);
12201
12202 template <typename T>
12203 static T min(T left, T right);
12204
12205 template <int Size>
12206 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12207 glw::GLuint row);
12208
12209 template <typename T>
12210 static T mix(T left, T right, T weight);
12211
12212 template <typename T>
12213 static T mod(T left, T right);
12214
12215 template <typename T>
12216 static T modf(T val, T& integer);
12217
12218 template <typename T>
12219 static T multiply(T left, T right);
12220
12221 template <int Size>
12222 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12223 const tcu::Vector<glw::GLdouble, Size>& right);
12224
12225 template <int Cols, int Rows>
12226 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12227 const tcu::Vector<glw::GLdouble, Cols>& right);
12228
12229 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12230
12231 template <typename T>
12232 static T round(T t);
12233
12234 template <typename T>
12235 static T roundEven(T t);
12236
12237 template <typename T>
12238 static T sign(T t);
12239
12240 template <typename T>
12241 static T smoothStep(T e0, T e1, T val);
12242
12243 template <typename T>
12244 static T step(T edge, T val);
12245
12246 template <typename T, int Rows, int Cols>
12247 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12248
12249 template <typename T>
12250 static T trunc(T t);
12251
12252 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12253
12254 template <typename T>
clamp(T x,T minVal,T maxVal)12255 static T clamp(T x, T minVal, T maxVal)
12256 {
12257 return min(max(x, minVal), maxVal);
12258 }
12259
12260 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12261 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12262 {
12263 tcu::Matrix<glw::GLdouble, Size, Size> result;
12264
12265 for (glw::GLuint c = 0; c < Size; ++c)
12266 {
12267 for (glw::GLuint r = 0; r < Size; ++r)
12268 {
12269 const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12270
12271 result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12272 }
12273 }
12274
12275 return result;
12276 }
12277
12278 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12279 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12280 {
12281 tcu::Vector<glw::GLuint, Size> result;
12282
12283 for (glw::GLint i = 0; i < Size; ++i)
12284 {
12285 if (GL_FALSE != src[i])
12286 {
12287 result[i] = 1;
12288 }
12289 else
12290 {
12291 result[i] = 0;
12292 }
12293 }
12294
12295 return result;
12296 }
12297
12298 template <typename T>
det2(T _00,T _10,T _01,T _11)12299 static T det2(T _00, T _10, T _01, T _11)
12300 {
12301 return _00 * _11 - _01 * _10;
12302 }
12303
12304 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12305 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12306 {
12307 return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12308 }
12309
12310 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)12311 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,
12312 T _33)
12313 {
12314 return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12315 _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12316 _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12317 _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12318 }
12319
12320 template <typename T>
determinant(T val)12321 static T determinant(T val)
12322 {
12323 return val;
12324 }
12325
12326 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12327 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12328 {
12329 return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12330 }
12331
12332 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12333 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12334 {
12335 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));
12336 }
12337
12338 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12339 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12340 {
12341 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),
12342 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12343 }
12344
12345 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12346 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12347 glw::GLuint column, glw::GLuint row)
12348 {
12349 // GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12350 #if (DE_COMPILER == DE_COMPILER_GCC)
12351 # pragma GCC diagnostic push
12352 # pragma GCC diagnostic ignored "-Warray-bounds"
12353 #endif
12354
12355 const glw::GLint eCol = static_cast<glw::GLint>(column);
12356 const glw::GLint eRow = static_cast<glw::GLint>(row);
12357
12358 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12359
12360 for (glw::GLint c = 0; c < Size; ++c)
12361 {
12362 /* Skip eliminated column */
12363 if (eCol == c)
12364 {
12365 continue;
12366 }
12367
12368 for (glw::GLint r = 0; r < Size; ++r)
12369 {
12370 /* Skip eliminated row */
12371 if (eRow == r)
12372 {
12373 continue;
12374 }
12375
12376 const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12377 const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12378
12379 result(r + r_offset, c + c_offset) = matrix(r, c);
12380 }
12381 }
12382
12383 return result;
12384
12385 #if (DE_COMPILER == DE_COMPILER_GCC)
12386 # pragma GCC diagnostic pop
12387 #endif
12388 }
12389
12390 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12391 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12392 const tcu::Vector<glw::GLdouble, Size>& right)
12393 {
12394 return convertBvecToUvec(tcu::equal(left, right));
12395 }
12396
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12397 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12398 {
12399 return a * b + c;
12400 }
12401
fract(glw::GLdouble val)12402 static glw::GLdouble fract(glw::GLdouble val)
12403 {
12404 return val - floor(val);
12405 }
12406
12407 template <typename T>
frexp(T val,glw::GLint & exp)12408 static T frexp(T val, glw::GLint& exp)
12409 {
12410 return ::frexp(val, &exp);
12411 }
12412
12413 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12414 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12415 const tcu::Vector<glw::GLdouble, Size>& right)
12416 {
12417 return convertBvecToUvec(tcu::greaterThan(left, right));
12418 }
12419
12420 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12421 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12422 const tcu::Vector<glw::GLdouble, Size>& right)
12423 {
12424 return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12425 }
12426
12427 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12428 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12429 {
12430 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix);
12431 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12432 const glw::GLdouble det = determinant(matrix);
12433 const glw::GLdouble inv_det = 1.0 / det;
12434
12435 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12436
12437 return result;
12438 }
12439
inverseSqrt(glw::GLdouble val)12440 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12441 {
12442 const glw::GLdouble root = sqrt(val);
12443
12444 return (1.0 / root);
12445 }
12446
isinf_impl(glw::GLdouble val)12447 static glw::GLuint isinf_impl(glw::GLdouble val)
12448 {
12449 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12450
12451 return ((infinity == val) || (-infinity == val));
12452 }
12453
isnan_impl(glw::GLdouble val)12454 static glw::GLuint isnan_impl(glw::GLdouble val)
12455 {
12456 return val != val;
12457 }
12458
12459 template <typename T>
ldexp(T val,glw::GLint exp)12460 static T ldexp(T val, glw::GLint exp)
12461 {
12462 return ::ldexp(val, exp);
12463 }
12464
12465 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12466 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12467 const tcu::Vector<glw::GLdouble, Size>& right)
12468 {
12469 return convertBvecToUvec(tcu::lessThan(left, right));
12470 }
12471
12472 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12473 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12474 const tcu::Vector<glw::GLdouble, Size>& right)
12475 {
12476 return convertBvecToUvec(tcu::lessThanEqual(left, right));
12477 }
12478
12479 template <typename T>
max(T left,T right)12480 static T max(T left, T right)
12481 {
12482 return (left >= right) ? left : right;
12483 }
12484
12485 template <typename T>
min(T left,T right)12486 static T min(T left, T right)
12487 {
12488 return (left <= right) ? left : right;
12489 }
12490
12491 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12492 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12493 glw::GLuint row)
12494 {
12495 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12496
12497 return determinant(eliminated);
12498 }
12499
12500 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12501 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12502 {
12503 const glw::GLuint r = (0 == row) ? 1 : 0;
12504 const glw::GLuint c = (0 == column) ? 1 : 0;
12505
12506 return matrix(r, c);
12507 }
12508
12509 template <typename T>
mix(T left,T right,T weight)12510 static T mix(T left, T right, T weight)
12511 {
12512 return left * (1 - weight) + right * (weight);
12513 }
12514
12515 template <typename T>
mod(T left,T right)12516 static T mod(T left, T right)
12517 {
12518 const T div_res = left / right;
12519 const T floored = floor(div_res);
12520
12521 return left - right * floored;
12522 }
12523
12524 template <typename T>
modf(T val,T & integer)12525 static T modf(T val, T& integer)
12526 {
12527 return ::modf(val, &integer);
12528 }
12529
12530 template <typename T>
multiply(T left,T right)12531 static T multiply(T left, T right)
12532 {
12533 T result = left * right;
12534
12535 return result;
12536 }
12537
12538 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12539 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12540 const tcu::Vector<glw::GLdouble, Size>& right)
12541 {
12542 return convertBvecToUvec(tcu::notEqual(left, right));
12543 }
12544
12545 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12546 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12547 const tcu::Vector<glw::GLdouble, Cols>& right)
12548 {
12549 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12550 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12551 tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12552
12553 for (glw::GLuint i = 0; i < Rows; ++i)
12554 {
12555 left_mat(i, 0) = left[i];
12556 }
12557
12558 for (glw::GLuint i = 0; i < Cols; ++i)
12559 {
12560 right_mat(0, i) = right[i];
12561 }
12562
12563 result = left_mat * right_mat;
12564
12565 return result;
12566 }
12567
packDouble2x32(const tcu::UVec2 & in)12568 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12569 {
12570 const glw::GLuint buffer[2] = { in[0], in[1] };
12571 glw::GLdouble result;
12572 memcpy(&result, buffer, sizeof(result));
12573 return result;
12574 }
12575
12576 template <typename T>
round(T t)12577 static T round(T t)
12578 {
12579 T frac = fract(t);
12580 T res = t - frac;
12581
12582 if (((T)0.5) < frac)
12583 {
12584 res += ((T)1.0);
12585 }
12586
12587 return res;
12588 }
12589
12590 template <typename T>
roundEven(T t)12591 static T roundEven(T t)
12592 {
12593 T frac = fract(t);
12594 T res = t - frac;
12595
12596 if (((T)0.5) < frac)
12597 {
12598 res += ((T)1.0);
12599 }
12600 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12601 {
12602 res += ((T)1.0);
12603 }
12604
12605 return res;
12606 }
12607
12608 template <typename T>
sign(T t)12609 static T sign(T t)
12610 {
12611 if (0 > t)
12612 {
12613 return -1;
12614 }
12615 else if (0 == t)
12616 {
12617 return 0;
12618 }
12619 else
12620 {
12621 return 1;
12622 }
12623 }
12624
12625 template <typename T>
smoothStep(T e0,T e1,T val)12626 static T smoothStep(T e0, T e1, T val)
12627 {
12628 if (e0 >= val)
12629 {
12630 return 0;
12631 }
12632
12633 if (e1 <= val)
12634 {
12635 return 1;
12636 }
12637
12638 T temp = (val - e0) / (e1 - e0);
12639
12640 T result = temp * temp * (3 - 2 * temp);
12641
12642 return result;
12643 }
12644
12645 template <typename T>
step(T edge,T val)12646 static T step(T edge, T val)
12647 {
12648 if (edge > val)
12649 {
12650 return 0;
12651 }
12652 else
12653 {
12654 return 1;
12655 }
12656 }
12657
12658 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12659 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12660 {
12661 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12662
12663 return result;
12664 }
12665
12666 template <typename T>
trunc(T t)12667 static T trunc(T t)
12668 {
12669 const T abs_value = de::abs(t);
12670 const T result_value = floor(abs_value);
12671
12672 const T result = sign(t) * result_value;
12673
12674 return result;
12675 }
12676
unpackDouble2x32(const glw::GLdouble & val)12677 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12678 {
12679 glw::GLuint* ptr = (glw::GLuint*)&val;
12680 tcu::UVec2 result(ptr[0], ptr[1]);
12681
12682 return result;
12683 }
12684 } /* Math */
12685
12686 /** Enumeration of tested functions
12687 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12688 * For example "max" can be called for (dvec3, double).
12689 **/
12690 enum FunctionEnum
12691 {
12692 FUNCTION_ABS = 0,
12693 FUNCTION_CEIL,
12694 FUNCTION_CLAMP,
12695 FUNCTION_CLAMP_AGAINST_SCALAR,
12696 FUNCTION_CROSS,
12697 FUNCTION_DETERMINANT,
12698 FUNCTION_DISTANCE,
12699 FUNCTION_DOT,
12700 FUNCTION_EQUAL,
12701 FUNCTION_FACEFORWARD,
12702 FUNCTION_FLOOR,
12703 FUNCTION_FMA,
12704 FUNCTION_FRACT,
12705 FUNCTION_FREXP,
12706 FUNCTION_GREATERTHAN,
12707 FUNCTION_GREATERTHANEQUAL,
12708 FUNCTION_INVERSE,
12709 FUNCTION_INVERSESQRT,
12710 FUNCTION_LDEXP,
12711 FUNCTION_LESSTHAN,
12712 FUNCTION_LESSTHANEQUAL,
12713 FUNCTION_LENGTH,
12714 FUNCTION_MATRIXCOMPMULT,
12715 FUNCTION_MAX,
12716 FUNCTION_MAX_AGAINST_SCALAR,
12717 FUNCTION_MIN,
12718 FUNCTION_MIN_AGAINST_SCALAR,
12719 FUNCTION_MIX,
12720 FUNCTION_MOD,
12721 FUNCTION_MOD_AGAINST_SCALAR,
12722 FUNCTION_MODF,
12723 FUNCTION_NORMALIZE,
12724 FUNCTION_NOTEQUAL,
12725 FUNCTION_OUTERPRODUCT,
12726 FUNCTION_PACKDOUBLE2X32,
12727 FUNCTION_REFLECT,
12728 FUNCTION_REFRACT,
12729 FUNCTION_ROUND,
12730 FUNCTION_ROUNDEVEN,
12731 FUNCTION_SIGN,
12732 FUNCTION_SMOOTHSTEP,
12733 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12734 FUNCTION_SQRT,
12735 FUNCTION_STEP,
12736 FUNCTION_STEP_AGAINST_SCALAR,
12737 FUNCTION_TRANSPOSE,
12738 FUNCTION_TRUNC,
12739 FUNCTION_UNPACKDOUBLE2X32,
12740 FUNCTION_ISNAN,
12741 FUNCTION_ISINF,
12742 };
12743
12744 struct TypeDefinition
12745 {
12746 std::string name;
12747 glw::GLuint n_columns;
12748 glw::GLuint n_rows;
12749 };
12750
12751 /** Implementation of BuiltinFunctionTest test, description follows:
12752 *
12753 * Verify double-precision support in common functions works correctly.
12754 * All double-precision types that apply for particular cases should
12755 * be tested for the following functions:
12756 *
12757 * - abs();
12758 * - ceil();
12759 * - clamp();
12760 * - cross();
12761 * - determinant();
12762 * - distance();
12763 * - dot();
12764 * - equal();
12765 * - faceforward();
12766 * - floor();
12767 * - fma();
12768 * - fract();
12769 * - frexp();
12770 * - greaterThan();
12771 * - greaterThanEqual();
12772 * - inverse();
12773 * - inversesqrt();
12774 * - ldexp();
12775 * - lessThan();
12776 * - lessThanEqual();
12777 * - length();
12778 * - matrixCompMult();
12779 * - max();
12780 * - min();
12781 * - mix();
12782 * - mod();
12783 * - modf();
12784 * - normalize();
12785 * - notEqual();
12786 * - outerProduct();
12787 * - packDouble2x32();
12788 * - reflect();
12789 * - refract();
12790 * - round();
12791 * - roundEven();
12792 * - sign();
12793 * - smoothstep();
12794 * - sqrt();
12795 * - step();
12796 * - transpose();
12797 * - trunc();
12798 * - unpackDouble2x32();
12799 * - isnan();
12800 * - isinf();
12801 *
12802 * The test should work by creating a program object (for each case
12803 * considered), to which a vertex shader should be attached. The
12804 * shader should define input variables that should be used as
12805 * arguments for the function in question. The result of the
12806 * operation should then be XFBed back to the test, where the
12807 * value should be verified.
12808 *
12809 * Reference function implementation from pre-DEQP CTS framework
12810 * should be ported to C for verification purposes where available.
12811 *
12812 * The test should use 1024 different scalar/vector/matrix argument
12813 * combinations. It should pass if all functions are determined
12814 * to work correctly for all argument combinations used.
12815 **/
12816 class BuiltinFunctionTest : public deqp::TestCase
12817 {
12818 public:
12819 /* Public methods */
12820 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12821 TypeDefinition typeDefinition);
12822
12823 virtual void deinit();
12824 virtual tcu::TestNode::IterateResult iterate();
12825
12826 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12827 *
12828 **/
12829 class functionObject
12830 {
12831 public:
12832 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12833 Utils::_variable_type result_type);
12834
~functionObject()12835 virtual ~functionObject()
12836 {
12837 }
12838
12839 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12840
12841 virtual glw::GLuint getArgumentCount() const = 0;
12842 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12843 glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12844 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12845 glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12846 glw::GLuint getArgumentStride() const;
12847 glw::GLuint getArgumentStride(glw::GLuint argument) const;
12848 FunctionEnum getFunctionEnum() const;
12849 const glw::GLchar* getName() const;
12850 glw::GLuint getResultComponents(glw::GLuint result) const;
12851 virtual glw::GLuint getResultCount() const;
12852 glw::GLuint getResultOffset(glw::GLuint result) const;
12853 virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12854 glw::GLuint getResultStride(glw::GLuint result) const;
12855 glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12856 glw::GLuint getResultStride() const;
12857
12858 protected:
12859 const FunctionEnum m_function_enum;
12860 const glw::GLchar* m_function_name;
12861 const glw::GLvoid* m_p_function;
12862 const Utils::_variable_type m_res_type;
12863 };
12864
12865 private:
12866 /* Private types */
12867 /** General type enumeration
12868 *
12869 **/
12870 enum generalType
12871 {
12872 SCALAR = 0,
12873 VECTOR,
12874 MATRIX,
12875 };
12876
12877 /** Details of variable type
12878 *
12879 **/
12880 struct typeDetails
12881 {
12882 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12883
12884 generalType m_general_type;
12885 glw::GLuint m_n_columns;
12886 glw::GLuint m_n_rows;
12887 glw::GLenum m_type;
12888 std::string m_type_name;
12889 };
12890
12891 /* Typedefs for gl.uniform* function pointers */
12892 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12893 const glw::GLdouble*);
12894 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12895 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12896 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12897
12898 /* Private methods */
12899 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12900
12901 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12902
12903 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
12904 const functionObject& function_object) const;
12905
12906 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
12907 const functionObject& function_object) const;
12908
12909 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
12910 const functionObject& function_object) const;
12911
12912 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
12913 const functionObject& function_object) const;
12914
12915 const glw::GLchar* getUniformName(glw::GLuint argument) const;
12916 const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12917
12918 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12919
12920 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12921
12922 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12923
12924 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12925 glw::GLubyte* buffer);
12926
12927 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12928
12929 void prepareTestData(const functionObject& function_object);
12930 void prepareVertexShaderCode(const functionObject& function_object);
12931
12932 bool test(FunctionEnum function, const typeDetails& type);
12933
12934 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12935
12936 void testInit();
12937
12938 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12939 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12940 const glw::GLvoid* result_src);
12941
12942 bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12943
12944 /* Private constants */
12945 static const glw::GLdouble m_epsilon;
12946 static const glw::GLuint m_n_veritces;
12947
12948 /* Private fields */
12949 glw::GLuint m_transform_feedback_buffer_id;
12950 glw::GLuint m_vertex_array_object_id;
12951
12952 std::vector<glw::GLubyte> m_expected_results_data;
12953 FunctionEnum m_function;
12954 TypeDefinition m_typeDefinition;
12955 std::vector<glw::GLubyte> m_argument_data;
12956 std::string m_vertex_shader_code;
12957 };
12958
12959 /* Constants used by BuiltinFunctionTest */
12960 /** Khronos Bug #14010
12961 * Using an epsilon value for comparing floating points is error prone.
12962 * Rather than writing a new floating point comparison function, I am
12963 * increasing the epsilon value to allow greater orders of magnitude
12964 * of floating point values.
12965 **/
12966 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002;
12967 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
12968
12969 /** Implementations of function objects required by "BuiltinFunctionTest"
12970 *
12971 **/
12972 namespace FunctionObject
12973 {
12974 /** Maps variable type with enumeration Utils::_variable_type
12975 *
12976 * @tparam T type
12977 **/
12978 template <typename T>
12979 class typeInfo
12980 {
12981 public:
12982 static const Utils::_variable_type variable_type =
12983 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12984 };
12985
12986 /** Place data from <in> into <buffer>
12987 *
12988 * @param buffer Buffer
12989 * @param in Input data
12990 **/
12991 template <typename T>
12992 class pack
12993 {
12994 public:
set(glw::GLvoid * buffer,const T & in)12995 static void set(glw::GLvoid* buffer, const T& in)
12996 {
12997 *(T*)buffer = in;
12998 }
12999 };
13000
13001 /** Place tcu::Matrix data from <in> into <buffer>
13002 *
13003 * @param buffer Buffer
13004 * @param in Input data
13005 **/
13006 template <int Cols, int Rows>
13007 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13008 {
13009 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13010 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13011 {
13012 glw::GLdouble* data = (glw::GLdouble*)buffer;
13013
13014 for (glw::GLint column = 0; column < Cols; ++column)
13015 {
13016 for (glw::GLint row = 0; row < Rows; ++row)
13017 {
13018 glw::GLint index = column * Rows + row;
13019
13020 data[index] = in(row, column);
13021 }
13022 }
13023 }
13024 };
13025
13026 /** Get data of <out> from <buffer>
13027 *
13028 * @param buffer Buffer
13029 * @param out Output data
13030 **/
13031 template <typename T>
13032 class unpack
13033 {
13034 public:
get(const glw::GLvoid * buffer,T & out)13035 static void get(const glw::GLvoid* buffer, T& out)
13036 {
13037 out = *(T*)buffer;
13038 }
13039 };
13040
13041 /** Get tcu::Matrix data from <buffer>
13042 *
13043 * @param buffer Buffer
13044 * @param out Output data
13045 **/
13046 template <int Cols, int Rows>
13047 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13048 {
13049 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13050 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13051 {
13052 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13053
13054 for (glw::GLint column = 0; column < Cols; ++column)
13055 {
13056 for (glw::GLint row = 0; row < Rows; ++row)
13057 {
13058 glw::GLint index = column * Rows + row;
13059
13060 out(row, column) = data[index];
13061 }
13062 }
13063 }
13064 };
13065
13066 /** Base of unary function classes
13067 *
13068 **/
13069 class unaryBase : public BuiltinFunctionTest::functionObject
13070 {
13071 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)13072 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13073 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13074 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13075 {
13076 }
13077
getArgumentCount() const13078 virtual glw::GLuint getArgumentCount() const
13079 {
13080 return 1;
13081 }
13082
getArgumentType(glw::GLuint) const13083 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13084 {
13085 return m_arg_type;
13086 }
13087
13088 protected:
13089 const Utils::_variable_type m_arg_type;
13090 };
13091
13092 /** Unary function class. It treats input argument as one variable.
13093 *
13094 * @tparam ResT Type of result
13095 * @tparam ArgT Type of argument
13096 **/
13097 template <typename ResT, typename ArgT>
13098 class unary : public unaryBase
13099 {
13100 public:
13101 typedef ResT (*functionPointer)(const ArgT&);
13102
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13103 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13104 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13105 typeInfo<ArgT>::variable_type)
13106 {
13107 }
13108
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13109 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13110 {
13111 ResT result;
13112 ArgT arg;
13113
13114 unpack<ArgT>::get(argument_src, arg);
13115
13116 functionPointer p_function = (functionPointer)m_p_function;
13117
13118 result = p_function(arg);
13119
13120 pack<ResT>::set(result_dst, result);
13121 }
13122 };
13123
13124 /** Unary function class. It treats input argument as separate components.
13125 *
13126 * @tparam ResT Type of result
13127 **/
13128 template <typename ResT>
13129 class unaryByComponent : public unaryBase
13130 {
13131 public:
13132 typedef ResT (*functionPointer)(glw::GLdouble);
13133
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13134 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13135 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13136 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13137 {
13138 }
13139
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13140 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13141 {
13142 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13143 ResT* p_result = (ResT*)result_dst;
13144 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src;
13145
13146 functionPointer p_function = (functionPointer)m_p_function;
13147
13148 for (glw::GLuint component = 0; component < n_components; ++component)
13149 {
13150 p_result[component] = p_function(p_arg[component]);
13151 }
13152 }
13153 };
13154
13155 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13156 *
13157 * @tparam ResT Type of result
13158 * @tparam ArgT Type of argument
13159 * @tparam OutT Type of output parameter
13160 **/
13161 template <typename ResT, typename ArgT, typename OutT>
13162 class unaryWithOutputByComponent : public unaryBase
13163 {
13164 public:
13165 typedef ResT (*functionPointer)(ArgT, OutT&);
13166
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)13167 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13168 functionPointer function_pointer, const Utils::_variable_type res_type,
13169 const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13170 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13171 , m_out_type(out_type)
13172 {
13173 }
13174
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13175 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13176 {
13177 ResT* p_result = (ResT*)result_dst;
13178 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13179 ArgT* p_arg = (ArgT*)argument_src;
13180
13181 const glw::GLuint n_components_0 = getArgumentComponents(0);
13182 const glw::GLuint n_components_1 = getResultComponents(1);
13183 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13184
13185 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13186 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13187
13188 functionPointer p_function = (functionPointer)m_p_function;
13189
13190 for (glw::GLuint component = 0; component < n_components; ++component)
13191 {
13192 const ArgT first_arg = p_arg[component * component_step_0];
13193 OutT& second_arg = p_out[component * component_step_1];
13194
13195 p_result[component] = p_function(first_arg, second_arg);
13196 }
13197 }
13198
getResultCount() const13199 glw::GLuint getResultCount() const
13200 {
13201 return 2;
13202 }
13203
getResultType(glw::GLuint result) const13204 Utils::_variable_type getResultType(glw::GLuint result) const
13205 {
13206 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13207
13208 switch (result)
13209 {
13210 case 0:
13211 type = m_res_type;
13212 break;
13213 case 1:
13214 type = m_out_type;
13215 break;
13216 default:
13217 TCU_FAIL("Not implemented");
13218 break;
13219 }
13220
13221 return type;
13222 }
13223
13224 protected:
13225 const Utils::_variable_type m_out_type;
13226 };
13227
13228 /** Base of binary function classes.
13229 *
13230 **/
13231 class binaryBase : public BuiltinFunctionTest::functionObject
13232 {
13233 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)13234 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13235 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13236 const Utils::_variable_type arg_2_type)
13237 : functionObject(function_enum, function_name, function_pointer, res_type)
13238 , m_arg_1_type(arg_1_type)
13239 , m_arg_2_type(arg_2_type)
13240 {
13241 }
13242
getArgumentCount() const13243 virtual glw::GLuint getArgumentCount() const
13244 {
13245 return 2;
13246 }
13247
getArgumentType(glw::GLuint argument) const13248 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13249 {
13250 switch (argument)
13251 {
13252 case 0:
13253 return m_arg_1_type;
13254 case 1:
13255 return m_arg_2_type;
13256 default:
13257 return Utils::VARIABLE_TYPE_UNKNOWN;
13258 }
13259 }
13260
13261 protected:
13262 const Utils::_variable_type m_arg_1_type;
13263 const Utils::_variable_type m_arg_2_type;
13264 };
13265
13266 /** Binary function class. It treats input arguments as two variables.
13267 *
13268 * @param ResT Type of result
13269 * @param Arg1T Type of first argument
13270 * @param Arg2T Type of second argument
13271 **/
13272 template <typename ResT, typename Arg1T, typename Arg2T>
13273 class binary : public binaryBase
13274 {
13275 public:
13276 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13277
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13278 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13279 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13280 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13281 {
13282 }
13283
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13284 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13285 {
13286 const glw::GLuint argument_1_stride = getArgumentStride(0);
13287
13288 functionPointer p_function = (functionPointer)m_p_function;
13289
13290 Arg1T arg_1;
13291 Arg2T arg_2;
13292 ResT result;
13293
13294 unpack<Arg1T>::get(argument_src, arg_1);
13295 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13296
13297 result = p_function(arg_1, arg_2);
13298
13299 pack<ResT>::set(result_dst, result);
13300 }
13301 };
13302
13303 /** Binary function class. It treats input arguments as separate components.
13304 *
13305 * @param ResT Type of result
13306 * @param Arg1T Type of first argument
13307 * @param Arg2T Type of second argument
13308 **/
13309 template <typename ResT, typename Arg1T, typename Arg2T>
13310 class binaryByComponent : public binaryBase
13311 {
13312 public:
13313 typedef ResT (*functionPointer)(Arg1T, Arg2T);
13314
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)13315 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13316 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13317 const Utils::_variable_type arg_2_type)
13318 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13319 {
13320 }
13321
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13322 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13323 {
13324 ResT* p_result = (ResT*)result_dst;
13325 Arg1T* p_arg_1 = (Arg1T*)argument_src;
13326 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13327
13328 const glw::GLuint n_components_0 = getArgumentComponents(0);
13329 const glw::GLuint n_components_1 = getArgumentComponents(1);
13330 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13331
13332 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13333 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13334
13335 functionPointer p_function = (functionPointer)m_p_function;
13336
13337 for (glw::GLuint component = 0; component < n_components; ++component)
13338 {
13339 const Arg1T first_arg = p_arg_1[component * component_step_0];
13340 const Arg2T second_arg = p_arg_2[component * component_step_1];
13341
13342 p_result[component] = p_function(first_arg, second_arg);
13343 }
13344 }
13345 };
13346
13347 /** Base of tenary function classes.
13348 *
13349 **/
13350 class tenaryBase : public BuiltinFunctionTest::functionObject
13351 {
13352 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)13353 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13354 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13355 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13356 : functionObject(function_enum, function_name, function_pointer, res_type)
13357 , m_arg_1_type(arg_1_type)
13358 , m_arg_2_type(arg_2_type)
13359 , m_arg_3_type(arg_3_type)
13360 {
13361 }
13362
getArgumentCount() const13363 virtual glw::GLuint getArgumentCount() const
13364 {
13365 return 3;
13366 }
13367
getArgumentType(glw::GLuint argument) const13368 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13369 {
13370 switch (argument)
13371 {
13372 case 0:
13373 return m_arg_1_type;
13374 case 1:
13375 return m_arg_2_type;
13376 case 2:
13377 return m_arg_3_type;
13378 default:
13379 return Utils::VARIABLE_TYPE_UNKNOWN;
13380 }
13381 }
13382
13383 protected:
13384 const Utils::_variable_type m_arg_1_type;
13385 const Utils::_variable_type m_arg_2_type;
13386 const Utils::_variable_type m_arg_3_type;
13387 };
13388
13389 /** Tenary function class. It treats input arguments as three variables.
13390 *
13391 * @param ResT Type of result
13392 * @param Arg1T Type of first argument
13393 * @param Arg2T Type of second argument
13394 * @param Arg3T Type of third argument
13395 **/
13396 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13397 class tenary : public tenaryBase
13398 {
13399 public:
13400 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13401 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13402 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13403 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13404
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13405 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13406 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13407 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13408 {
13409 }
13410
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13411 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13412 {
13413 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13414 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13415
13416 functionPointer p_function = (functionPointer)m_p_function;
13417
13418 arg1T arg_1;
13419 arg2T arg_2;
13420 arg3T arg_3;
13421 ResT result;
13422
13423 unpack<arg1T>::get(argument_src, arg_1);
13424 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13425 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13426
13427 result = p_function(arg_1, arg_2, arg_3);
13428
13429 pack<ResT>::set(result_dst, result);
13430 }
13431 };
13432
13433 /** Tenary function class. It treats input arguments as separate components.
13434 *
13435
13436 **/
13437 class tenaryByComponent : public tenaryBase
13438 {
13439 public:
13440 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13441
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)13442 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13443 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13444 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13445 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13446 arg_3_type)
13447 {
13448 }
13449
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13450 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13451 {
13452 glw::GLdouble* p_result = (glw::GLdouble*)result_dst;
13453 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src;
13454
13455 const glw::GLuint n_components_0 = getArgumentComponents(0);
13456 const glw::GLuint n_components_1 = getArgumentComponents(1);
13457 const glw::GLuint n_components_2 = getArgumentComponents(2);
13458 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2);
13459
13460 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13461 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13462 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13463
13464 functionPointer p_function = (functionPointer)m_p_function;
13465
13466 for (glw::GLuint component = 0; component < n_components; ++component)
13467 {
13468 const glw::GLdouble first_arg = p_arg[component * component_step_0];
13469 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13470 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13471
13472 p_result[component] = p_function(first_arg, second_arg, third_arg);
13473 }
13474 }
13475 };
13476 } /* FunctionObject */
13477
13478 /** Constructor.
13479 *
13480 * @param context Rendering context.
13481 **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13482 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13483 TypeDefinition typeDefinition)
13484 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13485 , m_transform_feedback_buffer_id(0)
13486 , m_vertex_array_object_id(0)
13487 , m_function(function)
13488 , m_typeDefinition(typeDefinition)
13489 {
13490 /* Nothing to be done here */
13491 }
13492
13493 /** Deinitializes all GL objects that may have been created during test execution.
13494 *
13495 **/
deinit()13496 void BuiltinFunctionTest::deinit()
13497 {
13498 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13499
13500 /* Clean buffers */
13501 if (0 != m_transform_feedback_buffer_id)
13502 {
13503 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13504 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13505 m_transform_feedback_buffer_id = 0;
13506 }
13507
13508 /* Clean VAO */
13509 if (0 != m_vertex_array_object_id)
13510 {
13511 gl.bindVertexArray(0);
13512 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13513 m_vertex_array_object_id = 0;
13514 }
13515 }
13516
13517 /** Execute test
13518 *
13519 * @return tcu::TestNode::STOP
13520 **/
iterate()13521 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13522 {
13523 /* Check if extension is supported */
13524 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13525 {
13526 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13527 }
13528
13529 testInit();
13530
13531 /* Verify result */
13532 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13533 if (test(m_function, type))
13534 {
13535 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13536 }
13537 else
13538 {
13539 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13540 }
13541
13542 /* Done */
13543 return tcu::TestNode::STOP;
13544 }
13545
13546 /** Constructor
13547 *
13548 * @param function_enum Function enumeration
13549 * @param function_name Function name
13550 * @param function_pointer Pointer to routine that wiil be executed
13551 * @param result_type Type of result
13552 **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13553 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13554 glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13555 : m_function_enum(function_enum)
13556 , m_function_name(function_name)
13557 , m_p_function(function_pointer)
13558 , m_res_type(result_type)
13559 {
13560 /* Nothing to be done here */
13561 }
13562
13563 /** Get number of components for <argument>
13564 *
13565 * @param argument Argument ordinal, starts with 0
13566 *
13567 * @return Number of components
13568 **/
getArgumentComponents(glw::GLuint argument) const13569 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13570 {
13571 const Utils::_variable_type type = getArgumentType(argument);
13572 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13573
13574 return n_components;
13575 }
13576
13577 /** Get size in bytes of single component of <argument>
13578 *
13579 * @param argument Argument ordinal, starts with 0
13580 *
13581 * @return Size of component
13582 **/
getArgumentComponentSize(glw::GLuint argument) const13583 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13584 {
13585 const Utils::_variable_type type = getArgumentType(argument);
13586 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13587 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13588
13589 return base_type_size;
13590 }
13591
13592 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13593 *
13594 * @param argument Argument ordinal, starts with 0
13595 *
13596 * @return Offset of arguemnt's data
13597 **/
getArgumentOffset(glw::GLuint argument) const13598 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13599 {
13600 glw::GLuint result = 0;
13601
13602 for (glw::GLuint i = 0; i < argument; ++i)
13603 {
13604 result += getArgumentStride(i);
13605 }
13606
13607 return result;
13608 }
13609
13610 /** Get stride in bytes of all arguments
13611 *
13612 * @return Stride of all arguments
13613 **/
getArgumentStride() const13614 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13615 {
13616 const glw::GLuint n_args = getArgumentCount();
13617 glw::GLuint result = 0;
13618
13619 for (glw::GLuint i = 0; i < n_args; ++i)
13620 {
13621 result += getArgumentStride(i);
13622 }
13623
13624 return result;
13625 }
13626
13627 /** Get stride in bytes of <argument>
13628 *
13629 * @param argument Argument ordinal, starts with 0
13630 *
13631 * @return Stride of argument
13632 **/
getArgumentStride(glw::GLuint argument) const13633 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13634 {
13635 const glw::GLuint component_size = getArgumentComponentSize(argument);
13636 const glw::GLuint n_components = getArgumentComponents(argument);
13637
13638 return n_components * component_size;
13639 }
13640
13641 /** Get function enumeration
13642 *
13643 * @return Function enumeration
13644 **/
getFunctionEnum() const13645 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13646 {
13647 return m_function_enum;
13648 }
13649
13650 /** Get function name
13651 *
13652 * @return Function name
13653 **/
getName() const13654 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13655 {
13656 return m_function_name;
13657 }
13658
13659 /** Get number of components for <result>
13660 *
13661 * @param result Result ordinal, starts with 0
13662 *
13663 * @return Number of components
13664 **/
getResultComponents(glw::GLuint result) const13665 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13666 {
13667 const Utils::_variable_type type = getResultType(result);
13668 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13669
13670 return n_components;
13671 }
13672
13673 /** Get number of results
13674 *
13675 * @return Number of results
13676 **/
getResultCount() const13677 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13678 {
13679 return 1;
13680 }
13681
13682 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13683 *
13684 * @param result Result ordinal, starts with 0
13685 *
13686 * @return Offset
13687 **/
getResultOffset(glw::GLuint result) const13688 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13689 {
13690 glw::GLuint offset = 0;
13691
13692 for (glw::GLuint i = 0; i < result; ++i)
13693 {
13694 offset += getResultStride(i);
13695 offset = deAlign32(offset, getBaseTypeSize(i));
13696 }
13697
13698 return offset;
13699 }
13700
13701 /** Get stride in bytes of <result>.
13702 *
13703 * @param result Result ordinal, starts with 0
13704 *
13705 * @return Stride
13706 **/
getResultStride(glw::GLuint result) const13707 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13708 {
13709 const Utils::_variable_type type = getResultType(result);
13710 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13711
13712 return n_components * getBaseTypeSize(result);
13713 }
13714
13715 /** Get size in bytes of <result> base component.
13716 *
13717 * @param result Result ordinal, starts with 0
13718 *
13719 * @return Alignment
13720 **/
getBaseTypeSize(glw::GLuint result) const13721 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13722 {
13723 const Utils::_variable_type type = getResultType(result);
13724 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13725 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13726
13727 return base_type_size;
13728 }
13729
13730 /** Get stride in bytes of all results.
13731 *
13732 * @return Stride
13733 **/
getResultStride() const13734 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13735 {
13736 const glw::GLuint n_results = getResultCount();
13737 glw::GLuint stride = 0;
13738 glw::GLuint maxAlignment = 0;
13739
13740 for (glw::GLuint i = 0; i < n_results; ++i)
13741 {
13742 const glw::GLuint alignment = getBaseTypeSize(i);
13743 stride += getResultStride(i);
13744 stride = deAlign32(stride, alignment);
13745 maxAlignment = deMaxu32(maxAlignment, alignment);
13746 }
13747
13748 // The stride of all results must also be aligned,
13749 // so results for next vertex are aligned.
13750 return deAlign32(stride, maxAlignment);
13751 }
13752
13753 /** Get type of <result>.
13754 *
13755 * @param result Result ordinal, starts with 0
13756 *
13757 * @return Type
13758 **/
getResultType(glw::GLuint) const13759 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13760 {
13761 return m_res_type;
13762 }
13763
13764 /** Constructor
13765 *
13766 * @param n_columns Number of columns
13767 * @param n_rows Number of rows
13768 **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13769 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13770 : m_n_columns(n_columns), m_n_rows(n_rows)
13771 {
13772 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13773 m_type = Utils::getGLDataTypeOfVariableType(type);
13774 m_type_name = Utils::getVariableTypeString(type);
13775
13776 if (1 == m_n_columns)
13777 {
13778 if (1 == m_n_rows)
13779 {
13780 m_general_type = SCALAR;
13781 }
13782 else
13783 {
13784 m_general_type = VECTOR;
13785 }
13786 }
13787 else
13788 {
13789 m_general_type = MATRIX;
13790 }
13791 }
13792
13793 /** Compare two values
13794 *
13795 * @param type Type of values
13796 * @param left Pointer to left value
13797 * @param right Pointer to right value
13798 *
13799 * @return true if values are equal, false otherwise
13800 **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13801 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13802 {
13803 bool result = true;
13804
13805 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13806 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13807
13808 switch (base_type)
13809 {
13810 case Utils::VARIABLE_TYPE_DOUBLE:
13811
13812 {
13813 const glw::GLdouble* left_values = (glw::GLdouble*)left;
13814 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13815
13816 for (glw::GLuint component = 0; component < n_components; ++component)
13817 {
13818 const glw::GLdouble left_value = left_values[component];
13819 const glw::GLdouble right_value = right_values[component];
13820
13821 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13822 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13823 {
13824 result = false;
13825 break;
13826 }
13827 }
13828 }
13829
13830 break;
13831
13832 case Utils::VARIABLE_TYPE_INT:
13833
13834 {
13835 const glw::GLint* left_values = (glw::GLint*)left;
13836 const glw::GLint* right_values = (glw::GLint*)right;
13837
13838 for (glw::GLuint component = 0; component < n_components; ++component)
13839 {
13840 const glw::GLint left_value = left_values[component];
13841 const glw::GLint right_value = right_values[component];
13842
13843 if (left_value != right_value)
13844 {
13845 result = false;
13846 break;
13847 }
13848 }
13849 }
13850
13851 break;
13852
13853 case Utils::VARIABLE_TYPE_UINT:
13854
13855 {
13856 const glw::GLuint* left_values = (glw::GLuint*)left;
13857 const glw::GLuint* right_values = (glw::GLuint*)right;
13858
13859 for (glw::GLuint component = 0; component < n_components; ++component)
13860 {
13861 const glw::GLuint left_value = left_values[component];
13862 const glw::GLuint right_value = right_values[component];
13863
13864 if (left_value != right_value)
13865 {
13866 result = false;
13867 break;
13868 }
13869 }
13870 }
13871
13872 break;
13873
13874 default:
13875
13876 TCU_FAIL("Not implemented");
13877 }
13878
13879 return result;
13880 }
13881
13882 /** Create instance of function object for given function enumeration and type
13883 *
13884 * @param function Function enumeration
13885 * @param type Type details
13886 *
13887 * @return Create object
13888 **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13889 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
13890 const typeDetails& type)
13891 {
13892 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13893 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13894 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13895 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13896 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13897 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13898 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13899 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13900 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13901
13902 const glw::GLuint n_columns = type.m_n_columns;
13903 const glw::GLuint n_rows = type.m_n_rows;
13904 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1);
13905 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13906 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows);
13907 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows);
13908
13909 switch (function)
13910 {
13911 case FUNCTION_ABS:
13912
13913 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13914 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13915
13916 case FUNCTION_CEIL:
13917
13918 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13919 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13920
13921 case FUNCTION_CLAMP:
13922
13923 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13924 variable_type /* arg1_type */, variable_type /* arg2_type */,
13925 variable_type /* arg3_type */);
13926
13927 case FUNCTION_CLAMP_AGAINST_SCALAR:
13928
13929 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13930 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13931 scalar_type /* arg3_type */);
13932
13933 case FUNCTION_CROSS:
13934
13935 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13936 function, "cross", tcu::cross);
13937
13938 case FUNCTION_DETERMINANT:
13939
13940 switch (variable_type)
13941 {
13942 case Utils::VARIABLE_TYPE_DMAT2:
13943 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13944 Math::determinant);
13945 case Utils::VARIABLE_TYPE_DMAT3:
13946 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13947 Math::determinant);
13948 case Utils::VARIABLE_TYPE_DMAT4:
13949 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13950 Math::determinant);
13951 default:
13952 TCU_FAIL("Not implemented");
13953 }
13954
13955 case FUNCTION_DISTANCE:
13956
13957 switch (variable_type)
13958 {
13959 case Utils::VARIABLE_TYPE_DVEC2:
13960 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13961 function, "distance", tcu::distance);
13962 case Utils::VARIABLE_TYPE_DVEC3:
13963 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13964 function, "distance", tcu::distance);
13965 case Utils::VARIABLE_TYPE_DVEC4:
13966 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13967 function, "distance", tcu::distance);
13968 default:
13969 break;
13970 }
13971
13972 break;
13973
13974 case FUNCTION_DOT:
13975
13976 switch (variable_type)
13977 {
13978 case Utils::VARIABLE_TYPE_DVEC2:
13979 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13980 function, "dot", tcu::dot);
13981 case Utils::VARIABLE_TYPE_DVEC3:
13982 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13983 function, "dot", tcu::dot);
13984 case Utils::VARIABLE_TYPE_DVEC4:
13985 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13986 function, "dot", tcu::dot);
13987 default:
13988 break;
13989 }
13990
13991 break;
13992
13993 case FUNCTION_EQUAL:
13994
13995 switch (variable_type)
13996 {
13997 case Utils::VARIABLE_TYPE_DVEC2:
13998 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13999 function, "equal", Math::equal);
14000 case Utils::VARIABLE_TYPE_DVEC3:
14001 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14002 function, "equal", Math::equal);
14003 case Utils::VARIABLE_TYPE_DVEC4:
14004 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14005 function, "equal", Math::equal);
14006 default:
14007 break;
14008 }
14009
14010 break;
14011
14012 case FUNCTION_FACEFORWARD:
14013
14014 switch (variable_type)
14015 {
14016 case Utils::VARIABLE_TYPE_DVEC2:
14017 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14018 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14019 function, "faceforward", tcu::faceForward);
14020 case Utils::VARIABLE_TYPE_DVEC3:
14021 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14022 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14023 function, "faceforward", tcu::faceForward);
14024 case Utils::VARIABLE_TYPE_DVEC4:
14025 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14026 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14027 function, "faceforward", tcu::faceForward);
14028 default:
14029 break;
14030 }
14031
14032 break;
14033
14034 case FUNCTION_FLOOR:
14035
14036 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14037 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14038
14039 case FUNCTION_FMA:
14040
14041 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */,
14042 variable_type /* arg1_type */, variable_type /* arg2_type */,
14043 variable_type /* arg3_type */);
14044
14045 case FUNCTION_FRACT:
14046
14047 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14048 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14049
14050 case FUNCTION_FREXP:
14051
14052 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14053 glw::GLint /* OutT */>(
14054 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14055 int_type /* out_type */);
14056
14057 case FUNCTION_GREATERTHAN:
14058
14059 switch (variable_type)
14060 {
14061 case Utils::VARIABLE_TYPE_DVEC2:
14062 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14063 function, "greaterThan", Math::greaterThan);
14064 case Utils::VARIABLE_TYPE_DVEC3:
14065 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14066 function, "greaterThan", Math::greaterThan);
14067 case Utils::VARIABLE_TYPE_DVEC4:
14068 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14069 function, "greaterThan", Math::greaterThan);
14070 default:
14071 break;
14072 }
14073
14074 break;
14075
14076 case FUNCTION_GREATERTHANEQUAL:
14077
14078 switch (variable_type)
14079 {
14080 case Utils::VARIABLE_TYPE_DVEC2:
14081 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14082 function, "greaterThanEqual", Math::greaterThanEqual);
14083 case Utils::VARIABLE_TYPE_DVEC3:
14084 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14085 function, "greaterThanEqual", Math::greaterThanEqual);
14086 case Utils::VARIABLE_TYPE_DVEC4:
14087 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14088 function, "greaterThanEqual", Math::greaterThanEqual);
14089 default:
14090 break;
14091 }
14092
14093 break;
14094
14095 case FUNCTION_INVERSE:
14096
14097 switch (variable_type)
14098 {
14099 case Utils::VARIABLE_TYPE_DMAT2:
14100 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14101 case Utils::VARIABLE_TYPE_DMAT3:
14102 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14103 case Utils::VARIABLE_TYPE_DMAT4:
14104 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14105 default:
14106 break;
14107 }
14108
14109 break;
14110
14111 case FUNCTION_INVERSESQRT:
14112
14113 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14114 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14115
14116 case FUNCTION_LDEXP:
14117
14118 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14119 glw::GLint /* Arg2T */>(
14120 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */,
14121 int_type /* arg2_type */);
14122
14123 case FUNCTION_LESSTHAN:
14124
14125 switch (variable_type)
14126 {
14127 case Utils::VARIABLE_TYPE_DVEC2:
14128 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14129 function, "lessThan", Math::lessThan);
14130 case Utils::VARIABLE_TYPE_DVEC3:
14131 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14132 function, "lessThan", Math::lessThan);
14133 case Utils::VARIABLE_TYPE_DVEC4:
14134 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14135 function, "lessThan", Math::lessThan);
14136 default:
14137 break;
14138 }
14139
14140 break;
14141
14142 case FUNCTION_LESSTHANEQUAL:
14143
14144 switch (variable_type)
14145 {
14146 case Utils::VARIABLE_TYPE_DVEC2:
14147 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14148 function, "lessThanEqual", Math::lessThanEqual);
14149 case Utils::VARIABLE_TYPE_DVEC3:
14150 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14151 function, "lessThanEqual", Math::lessThanEqual);
14152 case Utils::VARIABLE_TYPE_DVEC4:
14153 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14154 function, "lessThanEqual", Math::lessThanEqual);
14155 default:
14156 break;
14157 }
14158
14159 break;
14160
14161 case FUNCTION_LENGTH:
14162
14163 switch (variable_type)
14164 {
14165 case Utils::VARIABLE_TYPE_DVEC2:
14166 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14167 tcu::length);
14168 case Utils::VARIABLE_TYPE_DVEC3:
14169 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14170 tcu::length);
14171 case Utils::VARIABLE_TYPE_DVEC4:
14172 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14173 tcu::length);
14174 default:
14175 break;
14176 }
14177
14178 break;
14179
14180 case FUNCTION_MATRIXCOMPMULT:
14181
14182 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14183 glw::GLdouble /* Arg2T */>(
14184 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */,
14185 variable_type /* arg2_type */);
14186
14187 case FUNCTION_MAX:
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 variable_type /* arg2_type */);
14193
14194 case FUNCTION_MAX_AGAINST_SCALAR:
14195
14196 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14197 glw::GLdouble /* Arg2T */>(
14198 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14199 scalar_type /* arg2_type */);
14200
14201 case FUNCTION_MIN:
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 variable_type /* arg2_type */);
14207
14208 case FUNCTION_MIN_AGAINST_SCALAR:
14209
14210 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14211 glw::GLdouble /* Arg2T */>(
14212 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14213 scalar_type /* arg2_type */);
14214
14215 case FUNCTION_MIX:
14216
14217 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */,
14218 variable_type /* arg1_type */, variable_type /* arg2_type */,
14219 variable_type /* arg3_type */);
14220
14221 case FUNCTION_MOD:
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 variable_type /* arg2_type */);
14227
14228 case FUNCTION_MOD_AGAINST_SCALAR:
14229
14230 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14231 glw::GLdouble /* Arg2T */>(
14232 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14233 scalar_type /* arg2_type */);
14234
14235 case FUNCTION_MODF:
14236
14237 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14238 glw::GLdouble /* OutT */>(
14239 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14240 variable_type /* out_type */);
14241
14242 case FUNCTION_NORMALIZE:
14243
14244 switch (variable_type)
14245 {
14246 case Utils::VARIABLE_TYPE_DVEC2:
14247 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14248 tcu::normalize);
14249 case Utils::VARIABLE_TYPE_DVEC3:
14250 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14251 tcu::normalize);
14252 case Utils::VARIABLE_TYPE_DVEC4:
14253 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14254 tcu::normalize);
14255 default:
14256 break;
14257 }
14258
14259 break;
14260
14261 case FUNCTION_NOTEQUAL:
14262
14263 switch (variable_type)
14264 {
14265 case Utils::VARIABLE_TYPE_DVEC2:
14266 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14267 function, "notEqual", Math::notEqual);
14268 case Utils::VARIABLE_TYPE_DVEC3:
14269 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14270 function, "notEqual", Math::notEqual);
14271 case Utils::VARIABLE_TYPE_DVEC4:
14272 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14273 function, "notEqual", Math::notEqual);
14274 default:
14275 break;
14276 }
14277
14278 break;
14279
14280 case FUNCTION_OUTERPRODUCT:
14281
14282 switch (variable_type)
14283 {
14284 case Utils::VARIABLE_TYPE_DMAT2:
14285 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14286 function, "outerProduct", Math::outerProduct);
14287 case Utils::VARIABLE_TYPE_DMAT2X3:
14288 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14289 function, "outerProduct", Math::outerProduct);
14290 case Utils::VARIABLE_TYPE_DMAT2X4:
14291 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 function, "outerProduct", Math::outerProduct);
14293 case Utils::VARIABLE_TYPE_DMAT3:
14294 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14295 function, "outerProduct", Math::outerProduct);
14296 case Utils::VARIABLE_TYPE_DMAT3X2:
14297 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14298 function, "outerProduct", Math::outerProduct);
14299 case Utils::VARIABLE_TYPE_DMAT3X4:
14300 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 function, "outerProduct", Math::outerProduct);
14302 case Utils::VARIABLE_TYPE_DMAT4:
14303 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14304 function, "outerProduct", Math::outerProduct);
14305 case Utils::VARIABLE_TYPE_DMAT4X2:
14306 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14307 function, "outerProduct", Math::outerProduct);
14308 case Utils::VARIABLE_TYPE_DMAT4X3:
14309 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 function, "outerProduct", Math::outerProduct);
14311 default:
14312 break;
14313 }
14314
14315 break;
14316
14317 case FUNCTION_PACKDOUBLE2X32:
14318
14319 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14320 Math::packDouble2x32);
14321
14322 case FUNCTION_REFLECT:
14323
14324 switch (variable_type)
14325 {
14326 case Utils::VARIABLE_TYPE_DVEC2:
14327 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14328 function, "reflect", tcu::reflect);
14329 case Utils::VARIABLE_TYPE_DVEC3:
14330 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14331 function, "reflect", tcu::reflect);
14332 case Utils::VARIABLE_TYPE_DVEC4:
14333 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14334 function, "reflect", tcu::reflect);
14335 default:
14336 break;
14337 }
14338
14339 break;
14340
14341 case FUNCTION_REFRACT:
14342
14343 switch (variable_type)
14344 {
14345 case Utils::VARIABLE_TYPE_DVEC2:
14346 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14347 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14348 function, "refract", tcu::refract);
14349 case Utils::VARIABLE_TYPE_DVEC3:
14350 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14351 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14352 function, "refract", tcu::refract);
14353 case Utils::VARIABLE_TYPE_DVEC4:
14354 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14355 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14356 function, "refract", tcu::refract);
14357 default:
14358 break;
14359 }
14360
14361 break;
14362
14363 case FUNCTION_ROUND:
14364
14365 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14366 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14367
14368 case FUNCTION_ROUNDEVEN:
14369
14370 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14371 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14372
14373 case FUNCTION_SIGN:
14374
14375 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14376 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14377
14378 case FUNCTION_SMOOTHSTEP:
14379
14380 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14381 variable_type /* res_type */, variable_type /* arg1_type */,
14382 variable_type /* arg2_type */, variable_type /* arg3_type */);
14383
14384 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14385
14386 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14387 variable_type /* res_type */, scalar_type /* arg1_type */,
14388 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14389
14390 case FUNCTION_SQRT:
14391
14392 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14393 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14394
14395 case FUNCTION_STEP:
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 */, variable_type /* arg1_type */,
14400 variable_type /* arg2_type */);
14401
14402 case FUNCTION_STEP_AGAINST_SCALAR:
14403
14404 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14405 glw::GLdouble /* Arg2T */>(
14406 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */,
14407 variable_type /* arg2_type */);
14408
14409 case FUNCTION_TRANSPOSE:
14410
14411 switch (variable_type)
14412 {
14413 case Utils::VARIABLE_TYPE_DMAT2:
14414 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14415 Math::transpose);
14416 case Utils::VARIABLE_TYPE_DMAT2X3:
14417 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14418 Math::transpose);
14419 case Utils::VARIABLE_TYPE_DMAT2X4:
14420 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14421 Math::transpose);
14422 case Utils::VARIABLE_TYPE_DMAT3:
14423 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14424 Math::transpose);
14425 case Utils::VARIABLE_TYPE_DMAT3X2:
14426 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14427 Math::transpose);
14428 case Utils::VARIABLE_TYPE_DMAT3X4:
14429 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14430 Math::transpose);
14431 case Utils::VARIABLE_TYPE_DMAT4:
14432 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14433 Math::transpose);
14434 case Utils::VARIABLE_TYPE_DMAT4X2:
14435 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14436 Math::transpose);
14437 case Utils::VARIABLE_TYPE_DMAT4X3:
14438 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14439 Math::transpose);
14440 default:
14441 break;
14442 }
14443
14444 break;
14445
14446 case FUNCTION_TRUNC:
14447
14448 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14449 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14450
14451 case FUNCTION_UNPACKDOUBLE2X32:
14452
14453 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14454 Math::unpackDouble2x32);
14455
14456 case FUNCTION_ISNAN:
14457
14458 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14459 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14460
14461 case FUNCTION_ISINF:
14462
14463 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14464 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14465
14466 default:
14467 TCU_FAIL("Not implemented");
14468 return 0;
14469 }
14470
14471 TCU_FAIL("Not implemented");
14472 return 0;
14473 }
14474
14475 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14476 *
14477 * @param argument Argument index
14478 * @param function_object Function object
14479 *
14480 * @return Function pointer
14481 **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14482 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14483 glw::GLuint argument, const functionObject& function_object) const
14484 {
14485 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14486 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14487
14488 switch (argument_type)
14489 {
14490 case Utils::VARIABLE_TYPE_DMAT2:
14491 return gl.uniformMatrix2dv;
14492 case Utils::VARIABLE_TYPE_DMAT2X3:
14493 return gl.uniformMatrix2x3dv;
14494 case Utils::VARIABLE_TYPE_DMAT2X4:
14495 return gl.uniformMatrix2x4dv;
14496 case Utils::VARIABLE_TYPE_DMAT3:
14497 return gl.uniformMatrix3dv;
14498 case Utils::VARIABLE_TYPE_DMAT3X2:
14499 return gl.uniformMatrix3x2dv;
14500 case Utils::VARIABLE_TYPE_DMAT3X4:
14501 return gl.uniformMatrix3x4dv;
14502 case Utils::VARIABLE_TYPE_DMAT4:
14503 return gl.uniformMatrix4dv;
14504 case Utils::VARIABLE_TYPE_DMAT4X2:
14505 return gl.uniformMatrix4x2dv;
14506 case Utils::VARIABLE_TYPE_DMAT4X3:
14507 return gl.uniformMatrix4x3dv;
14508 default:
14509 break;
14510 }
14511
14512 TCU_FAIL("Not implemented");
14513 return 0;
14514 }
14515
14516 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14517 *
14518 * @param argument Argument index
14519 * @param function_object Function object
14520 *
14521 * @return Function pointer
14522 **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14523 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14524 glw::GLuint argument, const functionObject& function_object) const
14525 {
14526 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14527 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14528
14529 switch (argument_type)
14530 {
14531 case Utils::VARIABLE_TYPE_DOUBLE:
14532 return gl.uniform1dv;
14533 case Utils::VARIABLE_TYPE_DVEC2:
14534 return gl.uniform2dv;
14535 case Utils::VARIABLE_TYPE_DVEC3:
14536 return gl.uniform3dv;
14537 case Utils::VARIABLE_TYPE_DVEC4:
14538 return gl.uniform4dv;
14539 default:
14540 TCU_FAIL("Not implemented");
14541 }
14542
14543 return 0;
14544 }
14545
14546 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14547 *
14548 * @param argument Argument index
14549 * @param function_object Function object
14550 *
14551 * @return Function pointer
14552 **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14553 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14554 glw::GLuint argument, const functionObject& function_object) const
14555 {
14556 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14557 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14558
14559 switch (argument_type)
14560 {
14561 case Utils::VARIABLE_TYPE_INT:
14562 return gl.uniform1iv;
14563 case Utils::VARIABLE_TYPE_IVEC2:
14564 return gl.uniform2iv;
14565 case Utils::VARIABLE_TYPE_IVEC3:
14566 return gl.uniform3iv;
14567 case Utils::VARIABLE_TYPE_IVEC4:
14568 return gl.uniform4iv;
14569 default:
14570 TCU_FAIL("Not implemented");
14571 }
14572
14573 return 0;
14574 }
14575
14576 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14577 *
14578 * @param argument Argument index
14579 * @param function_object Function object
14580 *
14581 * @return Function pointer
14582 **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14583 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14584 glw::GLuint argument, const functionObject& function_object) const
14585 {
14586 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14587 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14588
14589 switch (argument_type)
14590 {
14591 case Utils::VARIABLE_TYPE_UVEC2:
14592 return gl.uniform2uiv;
14593 default:
14594 TCU_FAIL("Not implemented");
14595 }
14596
14597 return 0;
14598 }
14599
14600 /** Get name of uniform that will be used as <argument>.
14601 *
14602 * @param argument Argument index
14603 *
14604 * @return Name of uniform
14605 **/
getUniformName(glw::GLuint argument) const14606 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14607 {
14608 switch (argument)
14609 {
14610 case 0:
14611 return "uniform_0";
14612 case 1:
14613 return "uniform_1";
14614 case 2:
14615 return "uniform_2";
14616 default:
14617 TCU_FAIL("Not implemented");
14618 return 0;
14619 }
14620 }
14621
14622 /** Get name of varying that will be used as <result>.
14623 *
14624 * @param result Result index
14625 *
14626 * @return Name of varying
14627 **/
getVaryingName(glw::GLuint result) const14628 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14629 {
14630 switch (result)
14631 {
14632 case 0:
14633 return "result_0";
14634 case 1:
14635 return "result_1";
14636 case 2:
14637 return "result_2";
14638 default:
14639 TCU_FAIL("Not implemented");
14640 return 0;
14641 }
14642 }
14643
14644 /** Check if given combination of function and type is implemented
14645 *
14646 * @param function Function enumeration
14647 * @param type Type details
14648 *
14649 * @return true if function is available for given type, false otherwise
14650 **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14651 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14652 {
14653 static const bool look_up_table[][3] = {
14654 /* SCALAR, VECTOR, MATRIX */
14655 /* FUNCTION_ABS: */ { true, true, false },
14656 /* FUNCTION_CEIL: */ { true, true, false },
14657 /* FUNCTION_CLAMP: */ { true, true, false },
14658 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false },
14659 /* FUNCTION_CROSS: */ { false, true, false },
14660 /* FUNCTION_DETERMINANT: */ { false, false, true },
14661 /* FUNCTION_DISTANCE: */ { false, true, false },
14662 /* FUNCTION_DOT: */ { false, true, false },
14663 /* FUNCTION_EQUAL: */ { false, true, false },
14664 /* FUNCTION_FACEFORWARD: */ { false, true, false },
14665 /* FUNCTION_FLOOR: */ { true, true, false },
14666 /* FUNCTION_FMA: */ { true, true, false },
14667 /* FUNCTION_FRACT: */ { true, true, false },
14668 /* FUNCTION_FREXP: */ { true, true, false },
14669 /* FUNCTION_GREATERTHAN: */ { false, true, false },
14670 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false },
14671 /* FUNCTION_INVERSE: */ { false, false, true },
14672 /* FUNCTION_INVERSESQRT: */ { true, true, false },
14673 /* FUNCTION_LDEXP: */ { true, true, false },
14674 /* FUNCTION_LESSTHAN: */ { false, true, false },
14675 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false },
14676 /* FUNCTION_LENGTH: */ { false, true, false },
14677 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true },
14678 /* FUNCTION_MAX: */ { true, true, false },
14679 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false },
14680 /* FUNCTION_MIN: */ { true, true, false },
14681 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false },
14682 /* FUNCTION_MIX: */ { true, true, false },
14683 /* FUNCTION_MOD: */ { true, true, false },
14684 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false },
14685 /* FUNCTION_MODF: */ { true, true, false },
14686 /* FUNCTION_NORMALIZE: */ { false, true, false },
14687 /* FUNCTION_NOTEQUAL: */ { false, true, false },
14688 /* FUNCTION_OUTERPRODUCT: */ { false, false, true },
14689 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false },
14690 /* FUNCTION_REFLECT: */ { false, true, false },
14691 /* FUNCTION_REFRACT: */ { false, true, false },
14692 /* FUNCTION_ROUND: */ { true, true, false },
14693 /* FUNCTION_ROUNDEVEN: */ { true, true, false },
14694 /* FUNCTION_SIGN: */ { true, false, false },
14695 /* FUNCTION_SMOOTHSTEP: */ { true, true, false },
14696 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14697 /* FUNCTION_SQRT: */ { true, true, false },
14698 /* FUNCTION_STEP: */ { true, true, false },
14699 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false },
14700 /* FUNCTION_TRANSPOSE: */ { false, false, false },
14701 /* FUNCTION_TRUNC: */ { true, true, false },
14702 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false },
14703 /* FUNCTION_ISNAN: */ { true, true, false },
14704 /* FUNCTION_ISINF: */ { true, true, false },
14705 };
14706
14707 bool result = look_up_table[function][type.m_general_type];
14708
14709 if (true == result)
14710 {
14711 switch (function)
14712 {
14713 case FUNCTION_CROSS: /* Only 3 element vectors */
14714 result = (3 == type.m_n_rows);
14715 break;
14716 case FUNCTION_DETERMINANT: /* Only square matrices */
14717 case FUNCTION_INVERSE:
14718 result = (type.m_n_columns == type.m_n_rows);
14719 break;
14720 default:
14721 break;
14722 }
14723 }
14724
14725 return result;
14726 }
14727
14728 /** Logs variable of given type: name (type) [values]
14729 *
14730 * @param buffer Source of data
14731 * @param name Name of variable
14732 * @param type Type of variable
14733 **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14734 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14735 Utils::_variable_type type) const
14736 {
14737 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14738 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
14739 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14740
14741 message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14742
14743 for (glw::GLuint component = 0; component < n_components; ++component)
14744 {
14745 if (0 != component)
14746 {
14747 message << ", ";
14748 }
14749
14750 switch (base_type)
14751 {
14752 case Utils::VARIABLE_TYPE_DOUBLE:
14753 message << ((glw::GLdouble*)buffer)[component];
14754 break;
14755 case Utils::VARIABLE_TYPE_INT:
14756 message << ((glw::GLint*)buffer)[component];
14757 break;
14758 case Utils::VARIABLE_TYPE_UINT:
14759 message << ((glw::GLuint*)buffer)[component];
14760 break;
14761 default:
14762 TCU_FAIL("Not implemented");
14763 }
14764 }
14765
14766 message << "]" << tcu::TestLog::EndMessage;
14767 }
14768
14769 /** Prepare input arguments, data are stored in <buffer>
14770 *
14771 * @param function_object Function object
14772 * @param vertex Vertex index
14773 * @param buffer Buffer pointer
14774 **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14775 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14776 glw::GLubyte* buffer)
14777 {
14778 const glw::GLuint n_arguments = function_object.getArgumentCount();
14779
14780 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14781 {
14782 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14783
14784 prepareComponents(function_object, vertex, argument, buffer + offset);
14785 }
14786 }
14787
14788 /** Prepare components for given <function_object>, <vertex> and <argument>
14789 *
14790 * @param function_object Function object
14791 * @param vertex Vertex index
14792 * @param argument Argument index
14793 * @param buffer Buffer pointer
14794 **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14795 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14796 glw::GLuint argument, glw::GLubyte* buffer)
14797 {
14798 glw::GLuint argument_index[3] = { 0 };
14799 glw::GLuint argument_reset[3] = { 0 };
14800 glw::GLuint argument_step[3] = { 0 };
14801 glw::GLdouble double_argument_start[3] = { 0.0 };
14802 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14803 glw::GLuint int_argument_start = -4;
14804 const glw::GLuint n_arguments = function_object.getArgumentCount();
14805 const glw::GLuint n_components = function_object.getArgumentComponents(argument);
14806 glw::GLuint uint_argument_start = 0;
14807
14808 switch (n_arguments)
14809 {
14810 case 1:
14811 argument_step[0] = 1;
14812 argument_reset[0] = 1024;
14813 double_argument_start[0] = -511.5;
14814 break;
14815 case 2:
14816 argument_step[0] = 32;
14817 argument_step[1] = 1;
14818 argument_reset[0] = 32;
14819 argument_reset[1] = 32;
14820 double_argument_start[0] = -15.5;
14821 double_argument_start[1] = -15.5;
14822 break;
14823 case 3:
14824 argument_step[0] = 64;
14825 argument_step[1] = 8;
14826 argument_step[2] = 1;
14827 argument_reset[0] = 16;
14828 argument_reset[1] = 8;
14829 argument_reset[2] = 8;
14830 double_argument_start[0] = -7.5;
14831 double_argument_start[1] = -3.5;
14832 double_argument_start[2] = -3.5;
14833 break;
14834 default:
14835 TCU_FAIL("Not implemented");
14836 return;
14837 }
14838
14839 switch (function_object.getFunctionEnum())
14840 {
14841 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14842 case FUNCTION_CLAMP_AGAINST_SCALAR:
14843 double_argument_start[2] = 4.5;
14844 break;
14845 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14846 double_argument_start[0] = 16.5;
14847 break;
14848 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14849 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14850 argument_step[0] = 1;
14851 argument_step[1] = 8;
14852 argument_step[2] = 64;
14853 argument_reset[0] = 8;
14854 argument_reset[1] = 8;
14855 argument_reset[2] = 16;
14856 double_argument_start[0] = -3.5;
14857 double_argument_start[1] = 4.5;
14858 double_argument_start[2] = -7.5;
14859 break;
14860 default:
14861 break;
14862 }
14863
14864 for (glw::GLuint i = 0; i < n_arguments; ++i)
14865 {
14866 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14867 }
14868
14869 switch (base_arg_type)
14870 {
14871 case Utils::VARIABLE_TYPE_DOUBLE:
14872 {
14873 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14874
14875 double_argument_start[argument] += argument_index[argument];
14876
14877 for (glw::GLuint component = 0; component < n_components; ++component)
14878 {
14879 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14880
14881 switch (function_object.getFunctionEnum())
14882 {
14883 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14884 if (0.5 == Math::fract(value))
14885 {
14886 value += 0.01;
14887 }
14888 break;
14889 default:
14890 break;
14891 }
14892
14893 argument_dst[component] = value;
14894 }
14895 }
14896 break;
14897 case Utils::VARIABLE_TYPE_INT:
14898 {
14899 glw::GLint* argument_dst = (glw::GLint*)buffer;
14900
14901 uint_argument_start += argument_index[argument];
14902
14903 for (glw::GLuint component = 0; component < n_components; ++component)
14904 {
14905 const glw::GLint value = int_argument_start + component;
14906
14907 argument_dst[component] = value;
14908 }
14909 }
14910 break;
14911 case Utils::VARIABLE_TYPE_UINT:
14912 {
14913 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14914
14915 uint_argument_start += argument_index[argument];
14916
14917 for (glw::GLuint component = 0; component < n_components; ++component)
14918 {
14919 const glw::GLuint value = uint_argument_start + component;
14920
14921 argument_dst[component] = value;
14922 }
14923 }
14924 break;
14925 default:
14926 TCU_FAIL("Not implemented");
14927 return;
14928 }
14929 }
14930
14931 /** Prepare programInfo for given functionObject
14932 *
14933 * @param function_object Function object
14934 * @param out_program_info Program info
14935 **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14936 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14937 {
14938 const glw::GLuint n_varying_names = function_object.getResultCount();
14939 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14940
14941 prepareVertexShaderCode(function_object);
14942
14943 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14944 varying_names, n_varying_names);
14945 }
14946
14947 /** Prepare input data and expected results for given function object
14948 *
14949 * @param function_object Function object
14950 **/
prepareTestData(const functionObject & function_object)14951 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14952 {
14953 const glw::GLuint result_stride = function_object.getResultStride();
14954 const glw::GLuint result_buffer_size = result_stride * m_n_veritces;
14955 const glw::GLuint argument_stride = function_object.getArgumentStride();
14956 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14957
14958 m_argument_data.clear();
14959 m_expected_results_data.clear();
14960
14961 m_argument_data.resize(argument_buffer_size);
14962 m_expected_results_data.resize(result_buffer_size);
14963
14964 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14965 {
14966 const glw::GLuint result_offset = vertex * result_stride;
14967 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset];
14968 const glw::GLuint argument_offset = vertex * argument_stride;
14969 glw::GLubyte* argument_dst = &m_argument_data[argument_offset];
14970
14971 prepareArgument(function_object, vertex, argument_dst);
14972 function_object.call(result_dst, argument_dst);
14973 }
14974 }
14975
14976 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14977 *
14978 * @param function_object Function object
14979 **/
prepareVertexShaderCode(const functionObject & function_object)14980 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14981 {
14982 static const glw::GLchar* shader_template_code = "#version 400 core\n"
14983 "\n"
14984 "precision highp float;\n"
14985 "\n"
14986 "ARGUMENT_DEFINITION"
14987 "\n"
14988 "RESULT_DEFINITION"
14989 "\n"
14990 "void main()\n"
14991 "{\n"
14992 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14993 "}\n"
14994 "\n";
14995
14996 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
14997 static const glw::GLchar* argument_token = "ARGUMENT";
14998 static const glw::GLchar* function_name_token = "FUNCTION_NAME";
14999 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION";
15000 static const glw::GLchar* result_name_token = "RESULT_NAME";
15001 static const glw::GLchar* result_type_token = "RESULT_TYPE";
15002 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME";
15003 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE";
15004
15005 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15006 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT";
15007 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT";
15008 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15009
15010 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15011 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument);
15012 const glw::GLuint n_arguments = function_object.getArgumentCount();
15013 const glw::GLuint n_results = function_object.getResultCount();
15014 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition);
15015 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0));
15016
15017 size_t search_position = 0;
15018 std::string string = shader_template_code;
15019
15020 /* Replace ARGUMENT_DEFINITION with definitions */
15021 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15022 {
15023 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15024 const glw::GLchar* uniform_name = getUniformName(argument);
15025 std::string uniform_type = Utils::getVariableTypeString(argument_type);
15026
15027 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15028
15029 search_position -= argument_definition_length;
15030
15031 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15032 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15033 }
15034
15035 /* Remove ARGUMENT_DEFINITION */
15036 Utils::replaceToken(argument_definition_token, search_position, "", string);
15037
15038 /* Replace RESULT_DEFINITION with definitions */
15039 for (glw::GLuint result = 0; result < n_results; ++result)
15040 {
15041 Utils::_variable_type variable_type = function_object.getResultType(result);
15042 const glw::GLchar* varying_name = getVaryingName(result);
15043 std::string varying_type = Utils::getVariableTypeString(variable_type);
15044
15045 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15046
15047 search_position -= result_definition_length;
15048
15049 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15050 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15051 }
15052
15053 /* Remove RESULT_DEFINITION */
15054 Utils::replaceToken(result_definition_token, search_position, "", string);
15055
15056 /* Replace RESULT_NAME */
15057 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15058
15059 /* Replace RESULT_TYPE */
15060 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15061
15062 /* Replace FUNCTION_NAME */
15063 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15064
15065 /* Replace ARGUMENT with list of arguments */
15066 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15067 {
15068 const glw::GLchar* uniform_name = getUniformName(argument);
15069
15070 if (0 == argument)
15071 {
15072 Utils::replaceToken(argument_token, search_position, first_argument, string);
15073 }
15074 else
15075 {
15076 Utils::replaceToken(argument_token, search_position, argument_str, string);
15077 }
15078
15079 search_position -= first_argument_length;
15080
15081 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15082 }
15083
15084 for (glw::GLuint result = 1; result < n_results; ++result)
15085 {
15086 const glw::GLchar* varying_name = getVaryingName(result);
15087
15088 Utils::replaceToken(argument_token, search_position, argument_str, string);
15089
15090 search_position -= first_argument_length;
15091
15092 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15093 }
15094
15095 /* Remove ARGUMENT */
15096 Utils::replaceToken(argument_token, search_position, "", string);
15097
15098 m_vertex_shader_code = string;
15099 }
15100
15101 /** Test single function with one type
15102 *
15103 * param function Function enumeration
15104 * param type Type details
15105 *
15106 * @return true if test pass (or function is not available for <type>), false otherwise
15107 **/
test(FunctionEnum function,const typeDetails & type)15108 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15109 {
15110 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15111
15112 /* Skip if function is not implemented for type */
15113 if (false == isFunctionImplemented(function, type))
15114 {
15115 return true;
15116 }
15117
15118 Utils::programInfo program(m_context);
15119 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15120
15121 prepareProgram(*function_object, program);
15122 prepareTestData(*function_object);
15123
15124 /* Set up program */
15125 gl.useProgram(program.m_program_object_id);
15126 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15127
15128 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15129 {
15130 testBegin(*function_object, program.m_program_object_id, vertex);
15131
15132 gl.beginTransformFeedback(GL_POINTS);
15133 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15134
15135 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15136 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15137
15138 gl.endTransformFeedback();
15139 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15140
15141 if (false == verifyResults(*function_object, vertex))
15142 {
15143 return false;
15144 }
15145 }
15146
15147 return true;
15148 }
15149
15150 /** Update transform feedback buffer and uniforms
15151 *
15152 * @param function_object Function object
15153 * @param program_id Program object id
15154 * @param vertex Vertex index
15155 **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15156 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15157 {
15158 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15159 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15160 const glw::GLuint n_arguments = function_object.getArgumentCount();
15161 const glw::GLuint result_buffer_size = function_object.getResultStride();
15162 const glw::GLuint vertex_offset = arguments_stride * vertex;
15163
15164 /* Update transform feedback buffer */
15165 std::vector<glw::GLubyte> transform_feedback_buffer_data;
15166 transform_feedback_buffer_data.resize(result_buffer_size);
15167
15168 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15169 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15170
15171 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15172 GL_DYNAMIC_COPY);
15173 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15174
15175 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15176 result_buffer_size);
15177 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15178
15179 /* Update VAO */
15180 gl.bindVertexArray(m_vertex_array_object_id);
15181 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15182
15183 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15184 {
15185 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15186 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15187 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type);
15188 const glw::GLchar* uniform_name = getUniformName(argument);
15189 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name);
15190 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15191
15192 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15193
15194 if (-1 == uniform_location)
15195 {
15196 TCU_FAIL("Inactive uniform");
15197 }
15198
15199 if (1 == n_columns)
15200 {
15201 switch (Utils::getBaseVariableType(argument_type))
15202 {
15203 case Utils::VARIABLE_TYPE_DOUBLE:
15204 {
15205 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15206
15207 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15208 }
15209 break;
15210 case Utils::VARIABLE_TYPE_UINT:
15211 {
15212 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15213
15214 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15215 }
15216 break;
15217 case Utils::VARIABLE_TYPE_INT:
15218 {
15219 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15220
15221 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15222 }
15223 break;
15224 default:
15225 TCU_FAIL("Not implemented");
15226 }
15227 }
15228 else
15229 {
15230 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15231
15232 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15233 }
15234 }
15235 }
15236
15237 /** Init GL obejcts
15238 *
15239 **/
testInit()15240 void BuiltinFunctionTest::testInit()
15241 {
15242 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15243
15244 gl.genBuffers(1, &m_transform_feedback_buffer_id);
15245 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15246
15247 gl.genVertexArrays(1, &m_vertex_array_object_id);
15248 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15249
15250 gl.enable(GL_RASTERIZER_DISCARD);
15251 }
15252
15253 /** Checks if function result is an acceptable edge case
15254 *
15255 * @param function_object Function object
15256 * @param vertex Vertex index
15257 *
15258 * @return true if all results are as expected, false otherwise
15259 **/
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)15260 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15261 const Utils::_variable_type result_type,
15262 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15263 {
15264 FunctionEnum function_type = function_object.getFunctionEnum();
15265 switch (function_type)
15266 {
15267 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15268 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15269 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15270 case FUNCTION_MOD:
15271 case FUNCTION_MOD_AGAINST_SCALAR:
15272 {
15273 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15274 const glw::GLuint vertex_offset = arguments_stride * vertex;
15275 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0);
15276 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1);
15277 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset;
15278 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset;
15279 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index];
15280 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index];
15281 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15282 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15283 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15284 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src);
15285 bool edge_case_present = false;
15286 bool recheck = false;
15287
15288 // verify if there is a mod(a, a) case and prepare new expected result
15289 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15290 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15291 for (glw::GLuint component = 0; component < n_components; ++component)
15292 {
15293 glw::GLdouble expected_result_component = expected_result[component];
15294 glw::GLdouble actual_result_component = actual_result[component];
15295 glw::GLdouble argument_1_component = argument_1[component];
15296 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15297
15298 // if coresponding components of arguments are equal and if component of first argument
15299 // and component of result are equal then expected result must be corrected
15300 bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15301 round(argument_1_component / argument_2_component));
15302 edge_case_present = possible_edge_case &&
15303 (m_epsilon > de::abs(argument_2_component - actual_result_component));
15304 recheck |= edge_case_present;
15305 corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15306 }
15307
15308 // recheck test result with corrected expected result
15309 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15310 }
15311 default:
15312 return false;
15313 }
15314 }
15315
15316 /** Compare contents of transform feedback buffer with expected results
15317 *
15318 * @param function_object Function object
15319 * @param vertex Vertex index
15320 *
15321 * @return true if all results are as expected, false otherwise
15322 **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15323 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15324 {
15325 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15326 bool test_result = true;
15327 const glw::GLuint n_results = function_object.getResultCount();
15328 const glw::GLuint results_stride = function_object.getResultStride();
15329 const glw::GLuint results_offset = vertex * results_stride;
15330 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset];
15331
15332 /* Get transform feedback data */
15333 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15334 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15335
15336 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15337 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15338
15339 for (glw::GLuint result = 0; result < n_results; ++result)
15340 {
15341 const Utils::_variable_type result_type = function_object.getResultType(result);
15342 const glw::GLuint result_offset = function_object.getResultOffset(result);
15343
15344 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15345 const glw::GLvoid* result_src = feedback_data + result_offset;
15346
15347 if (compare(result_type, expected_result_src, result_src))
15348 continue;
15349
15350 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15351 {
15352 test_result = false;
15353 break;
15354 }
15355 }
15356
15357 /* Unmap transform feedback buffer */
15358 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15359 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15360
15361 if (false == test_result)
15362 {
15363 const glw::GLuint argument_stride = function_object.getArgumentStride();
15364 const glw::GLuint arguments_offset = vertex * argument_stride;
15365
15366 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15367 << tcu::TestLog::EndMessage;
15368
15369 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15370 << tcu::TestLog::EndMessage;
15371
15372 for (glw::GLuint result = 0; result < n_results; ++result)
15373 {
15374 const Utils::_variable_type result_type = function_object.getResultType(result);
15375 const glw::GLuint result_offset = function_object.getResultOffset(result);
15376
15377 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15378 const glw::GLvoid* result_src = feedback_data + result_offset;
15379
15380 logVariableType(result_src, "Result", result_type);
15381 logVariableType(expected_result_src, "Expected result", result_type);
15382 }
15383
15384 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15385 {
15386 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15387 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset];
15388
15389 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15390 }
15391
15392 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15393 << m_vertex_shader_code << tcu::TestLog::EndMessage;
15394 }
15395
15396 return test_result;
15397 }
15398
15399 /** Constructor.
15400 *
15401 * @param context Rendering context.
15402 **/
GPUShaderFP64Tests(deqp::Context & context)15403 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15404 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15405 {
15406 /* Left blank on purpose */
15407 }
15408
15409 /** Initializes a texture_storage_multisample test group.
15410 *
15411 **/
init(void)15412 void GPUShaderFP64Tests::init(void)
15413 {
15414 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15415 fp64->addChild(new GPUShaderFP64Test1(m_context));
15416 fp64->addChild(new GPUShaderFP64Test2(m_context));
15417 fp64->addChild(new GPUShaderFP64Test3(m_context));
15418 fp64->addChild(new GPUShaderFP64Test4(m_context));
15419 fp64->addChild(new GPUShaderFP64Test5(m_context));
15420 fp64->addChild(new GPUShaderFP64Test6(m_context));
15421 fp64->addChild(new GPUShaderFP64Test7(m_context));
15422 fp64->addChild(new GPUShaderFP64Test8(m_context));
15423 fp64->addChild(new GPUShaderFP64Test9(m_context));
15424 addChild(fp64);
15425
15426 TypeDefinition typeDefinition[] =
15427 {
15428 { "double", 1, 1 },
15429 { "dvec2", 1, 2 },
15430 { "dvec3", 1, 3 },
15431 { "dvec4", 1, 4 },
15432 { "dmat2", 2, 2 },
15433 { "dmat2x3", 2, 3 },
15434 { "dmat2x4", 2, 4 },
15435 { "dmat3x2", 3, 2 },
15436 { "dmat3", 3, 3 },
15437 { "dmat3x4", 3, 4 },
15438 { "dmat4x2", 4, 2 },
15439 { "dmat4x3", 4, 3 },
15440 { "dmat4", 4, 4 }
15441 };
15442
15443 struct BuiltinFunctions
15444 {
15445 std::string name;
15446 FunctionEnum function;
15447 } builtinFunctions[] = {
15448 { "abs", FUNCTION_ABS },
15449 { "ceil", FUNCTION_CEIL },
15450 { "clamp", FUNCTION_CLAMP },
15451 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR },
15452 { "cross", FUNCTION_CROSS },
15453 { "determinant", FUNCTION_DETERMINANT },
15454 { "distance", FUNCTION_DISTANCE },
15455 { "dot", FUNCTION_DOT },
15456 { "equal", FUNCTION_EQUAL },
15457 { "faceforward", FUNCTION_FACEFORWARD },
15458 { "floor", FUNCTION_FLOOR },
15459 { "fma", FUNCTION_FMA },
15460 { "fract", FUNCTION_FRACT },
15461 { "frexp", FUNCTION_FREXP },
15462 { "greaterthan", FUNCTION_GREATERTHAN },
15463 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL },
15464 { "inverse", FUNCTION_INVERSE },
15465 { "inversesqrt", FUNCTION_INVERSESQRT },
15466 { "ldexp", FUNCTION_LDEXP },
15467 { "lessthan", FUNCTION_LESSTHAN },
15468 { "lessthanequal", FUNCTION_LESSTHANEQUAL },
15469 { "length", FUNCTION_LENGTH },
15470 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT },
15471 { "max", FUNCTION_MAX },
15472 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR },
15473 { "min", FUNCTION_MIN },
15474 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR },
15475 { "mix", FUNCTION_MIX },
15476 { "mod", FUNCTION_MOD },
15477 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR },
15478 { "modf", FUNCTION_MODF },
15479 { "normalize", FUNCTION_NORMALIZE },
15480 { "notequal", FUNCTION_NOTEQUAL },
15481 { "outerproduct", FUNCTION_OUTERPRODUCT },
15482 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 },
15483 { "reflect", FUNCTION_REFLECT },
15484 { "refract", FUNCTION_REFRACT },
15485 { "round", FUNCTION_ROUND },
15486 { "roundeven", FUNCTION_ROUNDEVEN },
15487 { "sign", FUNCTION_SIGN },
15488 { "smoothstep", FUNCTION_SMOOTHSTEP },
15489 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15490 { "sqrt", FUNCTION_SQRT },
15491 { "step", FUNCTION_STEP },
15492 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR },
15493 { "transpose", FUNCTION_TRANSPOSE },
15494 { "trunc", FUNCTION_TRUNC },
15495 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 },
15496 { "isnan", FUNCTION_ISNAN },
15497 { "isinf", FUNCTION_ISINF }
15498 };
15499
15500 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15501 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15502 {
15503 const BuiltinFunctions& bf = builtinFunctions[i];
15504 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15505 {
15506 std::string caseName = bf.name + "_" + typeDefinition[j].name;
15507 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15508 }
15509 }
15510 addChild(builin);
15511 }
15512
15513 } /* glcts namespace */
15514