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 /* Set up rounding for the tests */
6937 deSetRoundingMode(DE_ROUNDINGMODE_TO_NEAREST_EVEN);
6938
6939 for (unsigned int n_program = 0; n_program < n_programs; ++n_program)
6940 {
6941 glw::GLuint po_id = programs[n_program];
6942 unsigned int n_stages = 0;
6943 _stage_data** stage_data = DE_NULL;
6944
6945 if (po_id == m_po_cs_id)
6946 {
6947 n_stages = n_cs_stages;
6948 stage_data = cs_stages;
6949 }
6950 else
6951 {
6952 n_stages = n_noncs_stages;
6953 stage_data = noncs_stages;
6954 }
6955
6956 /* Skip compute shader program if not supported */
6957 if (0 == po_id)
6958 {
6959 continue;
6960 }
6961
6962 for (unsigned int n_stage = 0; n_stage < n_stages; ++n_stage)
6963 {
6964 /* Iterate through all uniforms */
6965 _stage_data* stage_ptr = stage_data[n_stage];
6966
6967 /* Set up arrays that we will guide the automated testing */
6968 const uniform_value_pair double_uniforms[] = {
6969 uniform_value_pair(stage_ptr->uniforms.uniform_location_double, &stage_ptr->uniforms.uniform_double),
6970 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[0],
6971 stage_ptr->uniforms.uniform_double_arr + 0),
6972 uniform_value_pair(stage_ptr->uniforms.uniform_location_double_arr[1],
6973 stage_ptr->uniforms.uniform_double_arr + 1),
6974 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_double,
6975 &stage_ptr->uniform_structure_arrays[0].uniform_double),
6976 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_double,
6977 &stage_ptr->uniform_structure_arrays[1].uniform_double)
6978 };
6979 const uniform_value_pair dvec2_uniforms[] = {
6980 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2, stage_ptr->uniforms.uniform_dvec2),
6981 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[0],
6982 stage_ptr->uniforms.uniform_dvec2_arr + 0),
6983 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec2_arr[1],
6984 stage_ptr->uniforms.uniform_dvec2_arr + 2),
6985 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec2,
6986 stage_ptr->uniform_structure_arrays[0].uniform_dvec2),
6987 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec2,
6988 stage_ptr->uniform_structure_arrays[1].uniform_dvec2)
6989 };
6990 const uniform_value_pair dvec3_uniforms[] = {
6991 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3, stage_ptr->uniforms.uniform_dvec3),
6992 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[0],
6993 stage_ptr->uniforms.uniform_dvec3_arr + 0),
6994 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec3_arr[1],
6995 stage_ptr->uniforms.uniform_dvec3_arr + 3),
6996 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec3,
6997 stage_ptr->uniform_structure_arrays[0].uniform_dvec3),
6998 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec3,
6999 stage_ptr->uniform_structure_arrays[1].uniform_dvec3)
7000 };
7001 const uniform_value_pair dvec4_uniforms[] = {
7002 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4, stage_ptr->uniforms.uniform_dvec4),
7003 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[0],
7004 stage_ptr->uniforms.uniform_dvec4_arr + 0),
7005 uniform_value_pair(stage_ptr->uniforms.uniform_location_dvec4_arr[1],
7006 stage_ptr->uniforms.uniform_dvec4_arr + 4),
7007 uniform_value_pair(stage_ptr->uniform_structure_arrays[0].uniform_location_dvec4,
7008 stage_ptr->uniform_structure_arrays[0].uniform_dvec4),
7009 uniform_value_pair(stage_ptr->uniform_structure_arrays[1].uniform_location_dvec4,
7010 stage_ptr->uniform_structure_arrays[1].uniform_dvec4)
7011 };
7012
7013 /* Iterate over all uniforms and verify the values reported by the API */
7014 double returned_double_data[4];
7015 float returned_float_data[4];
7016 int returned_int_data[4];
7017 unsigned int returned_uint_data[4];
7018
7019 for (unsigned int n_type = 0; n_type < 4 /* double/dvec2/dvec3/dvec4 */; ++n_type)
7020 {
7021 const uniform_value_pair* current_uv_pairs = NULL;
7022 const unsigned int n_components_used = n_type + 1; /* n_type=0: double, n_type=1: dvec2, etc.. */
7023 unsigned int n_pairs = 0;
7024
7025 switch (n_type)
7026 {
7027 case 0: /* double */
7028 {
7029 current_uv_pairs = double_uniforms;
7030 n_pairs = sizeof(double_uniforms) / sizeof(double_uniforms[0]);
7031
7032 break;
7033 }
7034
7035 case 1: /* dvec2 */
7036 {
7037 current_uv_pairs = dvec2_uniforms;
7038 n_pairs = sizeof(dvec2_uniforms) / sizeof(dvec2_uniforms[0]);
7039
7040 break;
7041 }
7042
7043 case 2: /* dvec3 */
7044 {
7045 current_uv_pairs = dvec3_uniforms;
7046 n_pairs = sizeof(dvec3_uniforms) / sizeof(dvec3_uniforms[0]);
7047
7048 break;
7049 }
7050
7051 case 3: /* dvec4 */
7052 {
7053 current_uv_pairs = dvec4_uniforms;
7054 n_pairs = sizeof(dvec4_uniforms) / sizeof(dvec4_uniforms[0]);
7055
7056 break;
7057 }
7058
7059 default:
7060 {
7061 TCU_FAIL("Invalid type index requested");
7062 }
7063 } /* switch (n_type) */
7064
7065 for (unsigned int n_pair = 0; n_pair < n_pairs; ++n_pair)
7066 {
7067 const uniform_value_pair& current_uv_pair = current_uv_pairs[n_pair];
7068 glw::GLint uniform_location = current_uv_pair.first;
7069 const double* uniform_value = current_uv_pair.second;
7070
7071 /* Retrieve the values from the GL implementation*/
7072 gl.getUniformdv(po_id, uniform_location, returned_double_data);
7073 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformdv() call failed.");
7074
7075 gl.getUniformfv(po_id, uniform_location, returned_float_data);
7076 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformfv() call failed.");
7077
7078 gl.getUniformiv(po_id, uniform_location, returned_int_data);
7079 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformiv() call failed.");
7080
7081 gl.getUniformuiv(po_id, uniform_location, returned_uint_data);
7082 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformuiv() call failed.");
7083
7084 /* Make sure the values reported match the reference values */
7085 bool can_continue = true;
7086 const float epsilon = 1e-5f;
7087
7088 for (unsigned int n_component = 0; n_component < n_components_used && can_continue; ++n_component)
7089 {
7090 if (de::abs(returned_double_data[n_component] - uniform_value[n_component]) > epsilon)
7091 {
7092 m_testCtx.getLog()
7093 << tcu::TestLog::Message
7094 << "Invalid uniform value reported by glGetUniformdv() for uniform location ["
7095 << uniform_location << "]"
7096 " and component ["
7097 << n_component << "]"
7098 ": retrieved:["
7099 << returned_double_data[n_component] << "]"
7100 ", expected:["
7101 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7102
7103 result = false;
7104 }
7105
7106 if (de::abs(returned_float_data[n_component] - uniform_value[n_component]) > epsilon)
7107 {
7108 m_testCtx.getLog()
7109 << tcu::TestLog::Message
7110 << "Invalid uniform value reported by glGetUniformfv() for uniform location ["
7111 << uniform_location << "]"
7112 " and component ["
7113 << n_component << "]"
7114 ": retrieved:["
7115 << returned_float_data[n_component] << "]"
7116 ", expected:["
7117 << uniform_value[n_component] << "]" << tcu::TestLog::EndMessage;
7118
7119 result = false;
7120 }
7121
7122 /* ints */
7123 int rounded_uniform_value_sint = (int)(deFloatRound((float)uniform_value[n_component]));
7124 unsigned int rounded_uniform_value_uint =
7125 (unsigned int)(uniform_value[n_component] > 0.0) ?
7126 ((unsigned int)deFloatRound((float)uniform_value[n_component])) :
7127 0;
7128
7129 if (returned_int_data[n_component] != rounded_uniform_value_sint)
7130 {
7131 m_testCtx.getLog()
7132 << tcu::TestLog::Message
7133 << "Invalid uniform value reported by glGetUniformiv() for uniform location ["
7134 << uniform_location << "]"
7135 " and component ["
7136 << n_component << "]"
7137 ": retrieved:["
7138 << returned_int_data[n_component] << "]"
7139 ", expected:["
7140 << rounded_uniform_value_sint << "]" << tcu::TestLog::EndMessage;
7141
7142 result = false;
7143 }
7144
7145 if (returned_uint_data[n_component] != rounded_uniform_value_uint)
7146 {
7147 m_testCtx.getLog()
7148 << tcu::TestLog::Message
7149 << "Invalid uniform value reported by glGetUniformuiv() for uniform location ["
7150 << uniform_location << "]"
7151 " and component ["
7152 << n_component << "]"
7153 ": retrieved:["
7154 << returned_uint_data[n_component] << "]"
7155 ", expected:["
7156 << rounded_uniform_value_uint << "]" << tcu::TestLog::EndMessage;
7157
7158 result = false;
7159 }
7160 } /* for (all components) */
7161 } /* for (all uniform+value pairs) */
7162 } /* for (all 4 uniform types) */
7163 } /* for (all shader stages) */
7164 } /* for (both program objects) */
7165
7166 /* All done! */
7167 return result;
7168 }
7169
7170 /** Constructor
7171 *
7172 * @param context Rendering context.
7173 */
GPUShaderFP64Test5(deqp::Context & context)7174 GPUShaderFP64Test5::GPUShaderFP64Test5(deqp::Context& context)
7175 : TestCase(context, "conversions", "Verifies explicit and implicit casts involving double-precision"
7176 " floating-point variables work correctly")
7177 , m_base_value_bo_data(DE_NULL)
7178 , m_base_value_bo_id(0)
7179 , m_has_test_passed(true)
7180 , m_po_base_value_attribute_location(-1)
7181 , m_po_id(0)
7182 , m_vao_id(0)
7183 , m_vs_id(0)
7184 , m_xfb_bo_id(0)
7185 , m_xfb_bo_size(0)
7186 {
7187 /* Set up base value array (as per test spec) */
7188 m_base_values[0] = -25.12065f;
7189 m_base_values[1] = 0.0f;
7190 m_base_values[2] = 0.001f;
7191 m_base_values[3] = 1.0f;
7192 m_base_values[4] = 256.78901f;
7193
7194 /* Set up swizzle matrix */
7195 m_swizzle_matrix[0][0] = SWIZZLE_TYPE_NONE;
7196 m_swizzle_matrix[0][1] = SWIZZLE_TYPE_Y;
7197 m_swizzle_matrix[0][2] = SWIZZLE_TYPE_Z;
7198 m_swizzle_matrix[0][3] = SWIZZLE_TYPE_W;
7199 m_swizzle_matrix[1][0] = SWIZZLE_TYPE_NONE;
7200 m_swizzle_matrix[1][1] = SWIZZLE_TYPE_YX;
7201 m_swizzle_matrix[1][2] = SWIZZLE_TYPE_ZY;
7202 m_swizzle_matrix[1][3] = SWIZZLE_TYPE_WX;
7203 m_swizzle_matrix[2][0] = SWIZZLE_TYPE_NONE;
7204 m_swizzle_matrix[2][1] = SWIZZLE_TYPE_YXX;
7205 m_swizzle_matrix[2][2] = SWIZZLE_TYPE_XZY;
7206 m_swizzle_matrix[2][3] = SWIZZLE_TYPE_XWZY;
7207 m_swizzle_matrix[3][0] = SWIZZLE_TYPE_NONE;
7208 m_swizzle_matrix[3][1] = SWIZZLE_TYPE_YXXY;
7209 m_swizzle_matrix[3][2] = SWIZZLE_TYPE_XZXY;
7210 m_swizzle_matrix[3][3] = SWIZZLE_TYPE_XZYW;
7211 }
7212
deinit()7213 void GPUShaderFP64Test5::deinit()
7214 {
7215 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7216
7217 if (m_base_value_bo_data != DE_NULL)
7218 {
7219 delete[] m_base_value_bo_data;
7220
7221 m_base_value_bo_data = DE_NULL;
7222 }
7223
7224 if (m_base_value_bo_id != 0)
7225 {
7226 gl.deleteBuffers(1, &m_base_value_bo_id);
7227
7228 m_base_value_bo_id = 0;
7229 }
7230
7231 if (m_vao_id != 0)
7232 {
7233 gl.deleteVertexArrays(1, &m_vao_id);
7234
7235 m_vao_id = 0;
7236 }
7237
7238 if (m_xfb_bo_id != 0)
7239 {
7240 gl.deleteBuffers(1, &m_xfb_bo_id);
7241
7242 m_xfb_bo_id = 0;
7243 }
7244
7245 /* TCU_FAIL will skip the per sub test iteration de-initialization, we need to
7246 * take care of it here
7247 */
7248 deinitInteration();
7249 }
7250
7251 /** Deinitializes all buffers and GL objects that may have been generated
7252 * during test execution.
7253 **/
deinitInteration()7254 void GPUShaderFP64Test5::deinitInteration()
7255 {
7256 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7257
7258 if (m_po_id != 0)
7259 {
7260 gl.deleteProgram(m_po_id);
7261
7262 m_po_id = 0;
7263 }
7264
7265 if (m_vs_id != 0)
7266 {
7267 gl.deleteShader(m_vs_id);
7268
7269 m_vs_id = 0;
7270 }
7271 }
7272
7273 /** Executes a single test case iteration using user-provided test case descriptor.
7274 *
7275 * This function may throw a TestError exception if GL implementation misbehaves.
7276 *
7277 * @param test_case Test case descriptor to use.
7278 *
7279 * @return true if the values returned by GL implementation were found to be valid,
7280 * false otherwise.
7281 **/
executeIteration(const _test_case & test_case)7282 bool GPUShaderFP64Test5::executeIteration(const _test_case& test_case)
7283 {
7284 bool result = true;
7285
7286 /* Convert the base values array to the type of input attribute we'll be using
7287 * for the iteration.
7288 */
7289 Utils::_variable_type base_value_type = Utils::getBaseVariableType(test_case.src_type);
7290
7291 if (base_value_type == Utils::VARIABLE_TYPE_BOOL)
7292 {
7293 /* bools are actually represented by ints, since bool varyings are not allowed */
7294 base_value_type = Utils::VARIABLE_TYPE_INT;
7295 }
7296
7297 const unsigned int base_value_component_size = Utils::getBaseVariableTypeComponentSize(base_value_type);
7298 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7299
7300 m_base_value_bo_data = new unsigned char[base_value_component_size * n_base_values];
7301
7302 unsigned char* base_value_traveller_ptr = m_base_value_bo_data;
7303
7304 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7305 {
7306 switch (base_value_type)
7307 {
7308 case Utils::VARIABLE_TYPE_DOUBLE:
7309 *((double*)base_value_traveller_ptr) = (double)m_base_values[n_base_value];
7310 break;
7311 case Utils::VARIABLE_TYPE_FLOAT:
7312 *((float*)base_value_traveller_ptr) = (float)m_base_values[n_base_value];
7313 break;
7314 case Utils::VARIABLE_TYPE_INT:
7315 *((int*)base_value_traveller_ptr) = (int)m_base_values[n_base_value];
7316 break;
7317 case Utils::VARIABLE_TYPE_UINT:
7318 *((unsigned int*)base_value_traveller_ptr) = (unsigned int)m_base_values[n_base_value];
7319 break;
7320
7321 default:
7322 {
7323 TCU_FAIL("Unrecognized base value type");
7324 }
7325 }
7326
7327 base_value_traveller_ptr += base_value_component_size;
7328 } /* for (all base values) */
7329
7330 /* Update buffer object storage with the data we've just finished preparing. */
7331 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7332
7333 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7334 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7335
7336 gl.bufferSubData(GL_ARRAY_BUFFER, 0 /* offset */, base_value_component_size * n_base_values, m_base_value_bo_data);
7337 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
7338
7339 /* Configure vertex attribute array corresponding to 'base_value' attribute, so that the
7340 * new data is interpreted correctly.
7341 */
7342 if (base_value_type == Utils::VARIABLE_TYPE_FLOAT)
7343 {
7344 gl.vertexAttribPointer(m_po_base_value_attribute_location, 1, /* size */
7345 Utils::getGLDataTypeOfBaseVariableType(base_value_type), GL_FALSE, /* normalized */
7346 0, /* stride */
7347 DE_NULL); /* pointer */
7348 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer() call failed.");
7349 }
7350 else if (base_value_type == Utils::VARIABLE_TYPE_INT || base_value_type == Utils::VARIABLE_TYPE_UINT)
7351 {
7352 gl.vertexAttribIPointer(m_po_base_value_attribute_location, 1, /* size */
7353 Utils::getGLDataTypeOfBaseVariableType(base_value_type), 0, /* stride */
7354 DE_NULL); /* pointer */
7355 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribIPointer() call failed.");
7356 }
7357 else
7358 {
7359 DE_ASSERT(base_value_type == Utils::VARIABLE_TYPE_DOUBLE);
7360
7361 gl.vertexAttribLPointer(m_po_base_value_attribute_location, 1, /* size */
7362 GL_DOUBLE, 0, /* stride */
7363 DE_NULL); /* pointer */
7364 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertxAttribLPointer() call failed.");
7365 }
7366
7367 gl.enableVertexAttribArray(m_po_base_value_attribute_location);
7368 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray() call failed.");
7369
7370 /* Execute the draw call */
7371 gl.useProgram(m_po_id);
7372 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
7373
7374 gl.beginTransformFeedback(GL_POINTS);
7375 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
7376 {
7377 gl.drawArrays(GL_POINTS, 0 /* first */, n_base_values);
7378 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
7379 }
7380 gl.endTransformFeedback();
7381 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
7382
7383 /* Map the XFB buffer object into process space */
7384 void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
7385
7386 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
7387 DE_ASSERT(xfb_data_ptr != NULL);
7388
7389 /* Verify the data */
7390 result &= verifyXFBData((const unsigned char*)xfb_data_ptr, test_case);
7391
7392 /* Unmap the XFB BO */
7393 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
7394 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
7395
7396 /** Good to release the data buffer at this point */
7397 if (m_base_value_bo_data != DE_NULL)
7398 {
7399 delete[] m_base_value_bo_data;
7400
7401 m_base_value_bo_data = DE_NULL;
7402 }
7403
7404 /* All done */
7405 return result;
7406 }
7407
7408 /** Returns properties of a swizzle operator described by @param type swizzle type.
7409 *
7410 * @param out_swizzle_string Deref will be used to store a GLSL literal
7411 * corresponding to the specific swizzle operator.
7412 * Must not be NULL.
7413 * @param out_n_components Deref will be used to store the amount of components
7414 * used by the operator. Must not be NULL.
7415 * @param out_component_order Deref will be used to store up to 4 integer values,
7416 * corresponding to component indices described by the
7417 * operator for a particular position. Must not be NULL.
7418 **/
getSwizzleTypeProperties(_swizzle_type type,std::string * out_swizzle_string,unsigned int * out_n_components,unsigned int * out_component_order)7419 void GPUShaderFP64Test5::getSwizzleTypeProperties(_swizzle_type type, std::string* out_swizzle_string,
7420 unsigned int* out_n_components, unsigned int* out_component_order)
7421 {
7422 unsigned int result_component_order[4] = { 0 };
7423 unsigned int result_n_components = 0;
7424 std::string result_swizzle_string;
7425
7426 switch (type)
7427 {
7428 case SWIZZLE_TYPE_NONE:
7429 {
7430 result_swizzle_string = "";
7431 result_n_components = 0;
7432
7433 break;
7434 }
7435
7436 case SWIZZLE_TYPE_XWZY:
7437 {
7438 result_swizzle_string = "xwzy";
7439 result_n_components = 4;
7440 result_component_order[0] = 0;
7441 result_component_order[1] = 3;
7442 result_component_order[2] = 2;
7443 result_component_order[3] = 1;
7444
7445 break;
7446 }
7447
7448 case SWIZZLE_TYPE_XZXY:
7449 {
7450 result_swizzle_string = "xzxy";
7451 result_n_components = 4;
7452 result_component_order[0] = 0;
7453 result_component_order[1] = 2;
7454 result_component_order[2] = 0;
7455 result_component_order[3] = 1;
7456
7457 break;
7458 }
7459
7460 case SWIZZLE_TYPE_XZY:
7461 {
7462 result_swizzle_string = "xzy";
7463 result_n_components = 3;
7464 result_component_order[0] = 0;
7465 result_component_order[1] = 2;
7466 result_component_order[2] = 1;
7467
7468 break;
7469 }
7470
7471 case SWIZZLE_TYPE_XZYW:
7472 {
7473 result_swizzle_string = "xzyw";
7474 result_n_components = 4;
7475 result_component_order[0] = 0;
7476 result_component_order[1] = 2;
7477 result_component_order[2] = 1;
7478 result_component_order[3] = 3;
7479
7480 break;
7481 }
7482
7483 case SWIZZLE_TYPE_Y:
7484 {
7485 result_swizzle_string = "y";
7486 result_n_components = 1;
7487 result_component_order[0] = 1;
7488
7489 break;
7490 }
7491
7492 case SWIZZLE_TYPE_YX:
7493 {
7494 result_swizzle_string = "yx";
7495 result_n_components = 2;
7496 result_component_order[0] = 1;
7497 result_component_order[1] = 0;
7498
7499 break;
7500 }
7501
7502 case SWIZZLE_TYPE_YXX:
7503 {
7504 result_swizzle_string = "yxx";
7505 result_n_components = 3;
7506 result_component_order[0] = 1;
7507 result_component_order[1] = 0;
7508 result_component_order[2] = 0;
7509
7510 break;
7511 }
7512
7513 case SWIZZLE_TYPE_YXXY:
7514 {
7515 result_swizzle_string = "yxxy";
7516 result_n_components = 4;
7517 result_component_order[0] = 1;
7518 result_component_order[1] = 0;
7519 result_component_order[2] = 0;
7520 result_component_order[3] = 1;
7521
7522 break;
7523 }
7524
7525 case SWIZZLE_TYPE_Z:
7526 {
7527 result_swizzle_string = "z";
7528 result_n_components = 1;
7529 result_component_order[0] = 2;
7530
7531 break;
7532 }
7533
7534 case SWIZZLE_TYPE_ZY:
7535 {
7536 result_swizzle_string = "zy";
7537 result_n_components = 2;
7538 result_component_order[0] = 2;
7539 result_component_order[1] = 1;
7540
7541 break;
7542 }
7543
7544 case SWIZZLE_TYPE_W:
7545 {
7546 result_swizzle_string = "w";
7547 result_n_components = 1;
7548 result_component_order[0] = 3;
7549
7550 break;
7551 }
7552
7553 case SWIZZLE_TYPE_WX:
7554 {
7555 result_swizzle_string = "wx";
7556 result_n_components = 2;
7557 result_component_order[0] = 3;
7558 result_component_order[1] = 0;
7559
7560 break;
7561 }
7562
7563 default:
7564 {
7565 TCU_FAIL("Unrecognized swizzle type");
7566 }
7567 } /* switch (type) */
7568
7569 if (out_swizzle_string != DE_NULL)
7570 {
7571 *out_swizzle_string = result_swizzle_string;
7572 }
7573
7574 if (out_n_components != DE_NULL)
7575 {
7576 *out_n_components = result_n_components;
7577 }
7578
7579 if (out_component_order != DE_NULL)
7580 {
7581 memcpy(out_component_order, result_component_order, sizeof(unsigned int) * result_n_components);
7582 }
7583 }
7584
7585 /** Returns body of a vertex shader that should be used for particular test case,
7586 * given user-specified test case descriptor.
7587 *
7588 * @param test_case Descriptor to use for the query.
7589 *
7590 * @return Requested data.
7591 **/
getVertexShaderBody(const _test_case & test_case)7592 std::string GPUShaderFP64Test5::getVertexShaderBody(const _test_case& test_case)
7593 {
7594 std::stringstream result;
7595 const std::string base_type_string = Utils::getVariableTypeString(Utils::getBaseVariableType(test_case.src_type));
7596 const std::string dst_type_string = Utils::getVariableTypeString(test_case.dst_type);
7597 const unsigned int n_dst_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7598 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7599 const std::string src_type_string = Utils::getVariableTypeString(test_case.src_type);
7600
7601 /* Add version preamble */
7602 result << "#version 420\n"
7603 "\n";
7604
7605 /* Declare output variables. Note that boolean output variables are not supported, so we need
7606 * to handle that special case correctly */
7607 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7608 {
7609 result << "out int result;\n";
7610 }
7611 else
7612 {
7613 result << "out " << dst_type_string << " result;\n";
7614 }
7615
7616 /* Declare input variables. Handle the bool case exclusively. */
7617 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7618 {
7619 /* Use ints for bools. We will cast them to bool in the code later. */
7620 result << "in int base_value;\n";
7621 }
7622 else
7623 {
7624 result << "in " << base_type_string << " base_value;\n";
7625 }
7626
7627 /* Declare main() and construct the value we will be casting from.
7628 *
7629 * Note: Addition operations on bool values cause an implicit conversion to int
7630 * which is not allowed. Hence, we skip these operations for this special
7631 * case.
7632 */
7633 result << "void main()\n"
7634 "{\n"
7635 << src_type_string << " lside_value = ";
7636
7637 if (test_case.src_type == Utils::VARIABLE_TYPE_BOOL)
7638 {
7639 result << src_type_string << "(0 != ";
7640 }
7641 else
7642 {
7643 result << src_type_string << "(";
7644 }
7645
7646 if (test_case.src_type != Utils::VARIABLE_TYPE_BOOL)
7647 {
7648 for (unsigned int n_component = 0; n_component < n_src_components; ++n_component)
7649 {
7650 result << "base_value + " << n_component;
7651
7652 if (n_component != (n_src_components - 1))
7653 {
7654 result << ", ";
7655 }
7656 } /* for (all components) */
7657 }
7658 else
7659 {
7660 DE_ASSERT(n_src_components == 1);
7661
7662 result << "base_value";
7663 }
7664
7665 result << ");\n";
7666
7667 /* Perform the casting operation. Add swizzle operator if possible. */
7668 if (test_case.dst_type == Utils::VARIABLE_TYPE_BOOL)
7669 {
7670 /* Handle the bool case exclusively */
7671 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7672 {
7673 result << "result = (bool(lside_value) == false) ? 0 : 1";
7674 }
7675 else
7676 {
7677 result << "result = (lside_value == false) ? 0 : 1";
7678 }
7679 }
7680 else
7681 {
7682 if (test_case.type == TEST_CASE_TYPE_EXPLICIT)
7683 {
7684 result << "result = " << dst_type_string << "(lside_value)";
7685 }
7686 else
7687 {
7688 result << "result = lside_value";
7689 }
7690 }
7691
7692 if (n_src_components > 1 && !Utils::isMatrixVariableType(test_case.src_type))
7693 {
7694 /* Add a swizzle operator */
7695 DE_ASSERT(n_dst_components > 0 && n_dst_components <= 4);
7696 DE_ASSERT(n_src_components > 0 && n_src_components <= 4);
7697
7698 unsigned int swizzle_component_order[4] = { 0 };
7699 unsigned int swizzle_n_components = 0;
7700 _swizzle_type swizzle_operator = m_swizzle_matrix[n_dst_components - 1][n_src_components - 1];
7701 std::string swizzle_string;
7702
7703 getSwizzleTypeProperties(swizzle_operator, &swizzle_string, &swizzle_n_components, swizzle_component_order);
7704
7705 if (swizzle_n_components > 0)
7706 {
7707 result << "." << swizzle_string;
7708 }
7709 }
7710
7711 /* Close the shader implementation. */
7712 result << ";\n"
7713 "}\n";
7714
7715 return result.str();
7716 }
7717
7718 /** Initializes program & shader objects needed to run the iteration, given
7719 * user-specified test case descriptor.
7720 *
7721 * This function can throw a TestError exception if a GL error is detected
7722 * during execution.
7723 *
7724 * @param test_case Descriptor to use for the iteration.
7725 **/
initIteration(_test_case & test_case)7726 void GPUShaderFP64Test5::initIteration(_test_case& test_case)
7727 {
7728 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7729
7730 /* Create program & shader objects */
7731 m_po_id = gl.createProgram();
7732 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
7733
7734 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
7735 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
7736
7737 /* Configure shader body */
7738 std::string body = getVertexShaderBody(test_case);
7739 const char* body_raw_ptr = body.c_str();
7740
7741 gl.shaderSource(m_vs_id, 1 /* count */, &body_raw_ptr, DE_NULL /* length */);
7742 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
7743
7744 /* Store it in the test case descriptor for logging purposes */
7745 test_case.shader_body = body;
7746
7747 /* Compile the shader */
7748 glw::GLint compile_status = GL_FALSE;
7749
7750 gl.compileShader(m_vs_id);
7751 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
7752
7753 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
7754 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
7755
7756 if (compile_status != GL_TRUE)
7757 {
7758 TCU_FAIL("Shader compilation failed");
7759 }
7760
7761 /* Attach the shader to the program obejct */
7762 gl.attachShader(m_po_id, m_vs_id);
7763 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
7764
7765 /* Configure XFB for the program object */
7766 const char* xfb_varying_name = "result";
7767
7768 gl.transformFeedbackVaryings(m_po_id, 1 /* count */, &xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
7769 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
7770
7771 /* Link the program object */
7772 glw::GLint link_status = GL_FALSE;
7773
7774 gl.linkProgram(m_po_id);
7775 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
7776
7777 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
7778 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
7779
7780 if (link_status != GL_TRUE)
7781 {
7782 TCU_FAIL("Program linking failed");
7783 }
7784
7785 /* Retrieve attribute locations */
7786 m_po_base_value_attribute_location = gl.getAttribLocation(m_po_id, "base_value");
7787 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation() call failed.");
7788
7789 if (m_po_base_value_attribute_location == -1)
7790 {
7791 TCU_FAIL("'base_value' is considered an inactive attribute which is invalid.");
7792 }
7793 }
7794
7795 /** Initializes GL objects used by all test cases.
7796 *
7797 * This function may throw a TestError exception if GL implementation reports
7798 * an error at any point.
7799 **/
initTest()7800 void GPUShaderFP64Test5::initTest()
7801 {
7802 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
7803
7804 /* Generate buffer object IDs */
7805 gl.genBuffers(1, &m_base_value_bo_id);
7806 gl.genBuffers(1, &m_xfb_bo_id);
7807 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
7808
7809 /* Allocate buffer object storage for 'base_value' input attribute data. All iterations
7810 * will never eat up more than 1 double (as per test spec) and we will be drawing
7811 * as many points in a single draw call as there are defined in m_base_values array.
7812 */
7813 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7814
7815 gl.bindBuffer(GL_ARRAY_BUFFER, m_base_value_bo_id);
7816 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7817
7818 gl.bufferData(GL_ARRAY_BUFFER, sizeof(double) * n_base_values, DE_NULL /* data */, GL_STATIC_DRAW);
7819 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7820
7821 /* Allocate buffer object storage for XFB data. For each iteratiom we will be using
7822 * five base values. Each XFBed value can take up to 16 components (eg. mat4) and be
7823 * of double type (eg. dmat4), so make sure a sufficient amount of space is requested.
7824 */
7825 const unsigned int xfb_bo_size = sizeof(double) * 16 /* components */ * n_base_values;
7826
7827 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
7828 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
7829
7830 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
7831 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
7832
7833 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
7834 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
7835
7836 /* Allocate a client-side buffer to hold the data we will be mapping from XFB BO */
7837 m_xfb_bo_size = xfb_bo_size;
7838
7839 /* Generate a vertex array object we will need to use for the draw calls */
7840 gl.genVertexArrays(1, &m_vao_id);
7841 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
7842
7843 gl.bindVertexArray(m_vao_id);
7844 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
7845 }
7846
7847 /** Executes test iteration.
7848 *
7849 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
7850 */
iterate()7851 tcu::TestNode::IterateResult GPUShaderFP64Test5::iterate()
7852 {
7853 /* Do not execute the test if GL_ARB_texture_view is not supported */
7854 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
7855 {
7856 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
7857 }
7858
7859 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
7860 {
7861 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
7862 }
7863
7864 /* Initialize GL objects needed to run the tests */
7865 initTest();
7866
7867 /* Build iteration array to run the tests in an automated manner */
7868 _test_case test_cases[] = {
7869 /* test case type */ /* source type */ /* destination type */
7870 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7871 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7872 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7873 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7874 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7875 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7876 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7877 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7878 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7879 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, "" },
7880 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, "" },
7881 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, "" },
7882 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, "" },
7883 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, "" },
7884 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, "" },
7885 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, "" },
7886 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, "" },
7887 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, "" },
7888 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, "" },
7889 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, "" },
7890 { TEST_CASE_TYPE_IMPLICIT, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, "" },
7891
7892 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7893 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7894 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, "" },
7895 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_INT, "" },
7896 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_UINT, "" },
7897 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_FLOAT, "" },
7898 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_BOOL, "" },
7899 { TEST_CASE_TYPE_EXPLICIT, Utils::VARIABLE_TYPE_BOOL, Utils::VARIABLE_TYPE_DOUBLE, "" }
7900 };
7901 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
7902
7903 /* Execute all iterations */
7904 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
7905 {
7906 _test_case& test_case = test_cases[n_test_case];
7907
7908 /* Initialize a program object we will use to perform the casting */
7909 initIteration(test_case);
7910
7911 /* Use the program object to XFB the results */
7912 m_has_test_passed &= executeIteration(test_case);
7913
7914 /* Release the GL Resource for this sub test */
7915 deinitInteration();
7916
7917 } /* for (all test cases) */
7918 /* We're done */
7919 if (m_has_test_passed)
7920 {
7921 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
7922 }
7923 else
7924 {
7925 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7926 }
7927
7928 return STOP;
7929 }
7930
7931 /** Verifies if data XFBed out by the vertex shader are valid, given test case descriptor,
7932 * for which the data have been generated.
7933 *
7934 * @param data_ptr Buffer holding the data XFBed out by the shader.
7935 * @param test_case Descriptor of the test case, for which the vertex shader was
7936 * generated.
7937 *
7938 * @return true if the data were found to be valid, false otherwise.
7939 **/
verifyXFBData(const unsigned char * data_ptr,const _test_case & test_case)7940 bool GPUShaderFP64Test5::verifyXFBData(const unsigned char* data_ptr, const _test_case& test_case)
7941 {
7942 const Utils::_variable_type base_dst_type = Utils::getBaseVariableType(test_case.dst_type);
7943 const Utils::_variable_type base_src_type = Utils::getBaseVariableType(test_case.src_type);
7944 const float epsilon = 1e-5f;
7945 const unsigned int n_base_values = sizeof(m_base_values) / sizeof(m_base_values[0]);
7946 const unsigned int n_result_components = Utils::getNumberOfComponentsForVariableType(test_case.dst_type);
7947 const unsigned int n_src_components = Utils::getNumberOfComponentsForVariableType(test_case.src_type);
7948 bool result = true;
7949 _swizzle_type swizzle_operator = SWIZZLE_TYPE_NONE;
7950 unsigned int swizzle_order[4] = { 0 };
7951 const unsigned char* traveller_ptr = data_ptr;
7952
7953 if (!Utils::isMatrixVariableType(test_case.src_type))
7954 {
7955 DE_ASSERT(n_result_components >= 1 && n_result_components <= 4);
7956 DE_ASSERT(n_src_components >= 1 && n_src_components <= 4);
7957
7958 swizzle_operator = m_swizzle_matrix[n_result_components - 1][n_src_components - 1];
7959
7960 getSwizzleTypeProperties(swizzle_operator, DE_NULL, /* out_swizzle_string */
7961 DE_NULL, /* out_n_components */
7962 swizzle_order);
7963 }
7964
7965 for (unsigned int n_base_value = 0; n_base_value < n_base_values; ++n_base_value)
7966 {
7967 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
7968 {
7969 unsigned int n_swizzled_component = n_result_component;
7970
7971 if (swizzle_operator != SWIZZLE_TYPE_NONE)
7972 {
7973 n_swizzled_component =
7974 (n_result_component / n_result_components) * n_result_component + swizzle_order[n_result_component];
7975 }
7976
7977 switch (base_dst_type)
7978 {
7979 case Utils::VARIABLE_TYPE_BOOL:
7980 case Utils::VARIABLE_TYPE_INT:
7981 {
7982 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
7983 double expected_value = ref_expected_value;
7984 int result_value = *((int*)traveller_ptr);
7985
7986 if (base_dst_type == Utils::VARIABLE_TYPE_BOOL)
7987 {
7988 if (expected_value != 0.0)
7989 {
7990 expected_value = 1.0;
7991 }
7992 }
7993
7994 if (result_value != (int)expected_value)
7995 {
7996 m_testCtx.getLog() << tcu::TestLog::Message
7997 << "Invalid boolean/integer value obtained when doing an "
7998 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
7999 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8000 << "]"
8001 ", component index: ["
8002 << n_swizzled_component << "]"
8003 ", value: ["
8004 << ref_expected_value << "]"
8005 " to GLSL type ["
8006 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8007 ", retrieved value: ["
8008 << result_value << "]"
8009 ", expected value: ["
8010 << (int)expected_value << "]"
8011 ", shader used:\n"
8012 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8013
8014 result = false;
8015 }
8016
8017 traveller_ptr += sizeof(int);
8018 break;
8019 } /* VARIABLE_TYPE_BOOL or VARIABLE_TYPE_INT cases */
8020
8021 case Utils::VARIABLE_TYPE_DOUBLE:
8022 {
8023 double ref_expected_value = m_base_values[n_base_value] + (double)n_swizzled_component;
8024 double expected_value = ref_expected_value;
8025 double result_value = *((double*)traveller_ptr);
8026
8027 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8028 {
8029 expected_value = ((int)expected_value != 0.0) ? 1.0 : 0.0;
8030 }
8031 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8032 {
8033 expected_value = (int)expected_value;
8034 }
8035 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8036 {
8037 // Negative values in base values array when converted to unsigned int will be ZERO
8038 // Addition operations done inside the shader in such cases will operate on ZERO rather
8039 // than the negative value being passed.
8040 // Replicate the sequence of conversion and addition operations done on the
8041 // shader input, to calculate the expected values in XFB data in the
8042 // problematic cases.
8043 if (expected_value < 0)
8044 {
8045 expected_value = (unsigned int)m_base_values[n_base_value] + n_swizzled_component;
8046 }
8047 expected_value = (unsigned int)expected_value;
8048 }
8049
8050 traveller_ptr += sizeof(double);
8051 if (de::abs(result_value - expected_value) > epsilon)
8052 {
8053 m_testCtx.getLog() << tcu::TestLog::Message
8054 << "Invalid double-precision floating-point value obtained when doing an "
8055 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8056 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8057 << "]"
8058 ", component index: ["
8059 << n_swizzled_component << "]"
8060 ", value: ["
8061 << ref_expected_value << "]"
8062 " to GLSL type ["
8063 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8064 ", retrieved value: ["
8065 << std::setprecision(16) << result_value << "]"
8066 ", expected value: ["
8067 << std::setprecision(16) << expected_value << "]"
8068 ", shader used:\n"
8069 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8070
8071 result = false;
8072 }
8073
8074 break;
8075 } /* VARIABLE_TYPE_DOUBLE case */
8076
8077 case Utils::VARIABLE_TYPE_FLOAT:
8078 {
8079 float ref_expected_value = (float)m_base_values[n_base_value] + (float)n_swizzled_component;
8080 float expected_value = ref_expected_value;
8081 float result_value = *((float*)traveller_ptr);
8082
8083 if (base_src_type == Utils::VARIABLE_TYPE_BOOL)
8084 {
8085 expected_value = (expected_value != 0.0f) ? 1.0f : 0.0f;
8086 }
8087 else if (base_src_type == Utils::VARIABLE_TYPE_INT)
8088 {
8089 expected_value = (float)((int)expected_value);
8090 }
8091 else if (base_src_type == Utils::VARIABLE_TYPE_UINT)
8092 {
8093 expected_value = (float)((unsigned int)expected_value);
8094 }
8095
8096 traveller_ptr += sizeof(float);
8097 if (de::abs(result_value - expected_value) > epsilon)
8098 {
8099 m_testCtx.getLog() << tcu::TestLog::Message
8100 << "Invalid single-precision floating-point value obtained when doing an "
8101 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8102 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8103 << "]"
8104 ", component index: ["
8105 << n_swizzled_component << "]"
8106 ", value: ["
8107 << ref_expected_value << "]"
8108 " to GLSL type ["
8109 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8110 ", retrieved value: ["
8111 << std::setprecision(16) << result_value << "]"
8112 ", expected value: ["
8113 << std::setprecision(16) << expected_value << "]"
8114 ", shader used:\n"
8115 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8116
8117 result = false;
8118 }
8119
8120 break;
8121 } /* VARIABLE_TYPE_FLOAT case */
8122
8123 case Utils::VARIABLE_TYPE_UINT:
8124 {
8125 double ref_expected_value = (m_base_values[n_base_value]) + static_cast<float>(n_swizzled_component);
8126 double expected_value = ref_expected_value;
8127 unsigned int result_value = *((unsigned int*)traveller_ptr);
8128
8129 traveller_ptr += sizeof(unsigned int);
8130 if (result_value != (unsigned int)expected_value)
8131 {
8132 if (expected_value < 0.0)
8133 {
8134 // It is undefined to convert a negative floating-point value to an uint.
8135 break;
8136 }
8137
8138 m_testCtx.getLog() << tcu::TestLog::Message
8139 << "Invalid unsigned integer value obtained when doing an "
8140 << ((test_case.type == TEST_CASE_TYPE_EXPLICIT) ? "explicit" : "implicit")
8141 << " cast from GLSL type [" << Utils::getVariableTypeString(test_case.src_type)
8142 << "]"
8143 ", component index: ["
8144 << n_swizzled_component << "]"
8145 ", value: ["
8146 << ref_expected_value << "]"
8147 " to GLSL type ["
8148 << Utils::getVariableTypeString(test_case.dst_type) << "]"
8149 ", retrieved value: ["
8150 << result_value << "]"
8151 ", expected value: ["
8152 << (unsigned int)expected_value << "]"
8153 ", shader used:\n"
8154 << test_case.shader_body.c_str() << tcu::TestLog::EndMessage;
8155
8156 result = false;
8157 }
8158
8159 break;
8160 } /* VARIABLE_TYPE_UINT case */
8161
8162 default:
8163 {
8164 TCU_FAIL("Unrecognized variable type");
8165 }
8166 } /* switch (test_case.dst_type) */
8167 } /* for (all result components) */
8168 } /* for (all base values) */
8169
8170 return result;
8171 }
8172
8173 /** Constructor
8174 *
8175 * @param context Rendering context.
8176 */
GPUShaderFP64Test6(deqp::Context & context)8177 GPUShaderFP64Test6::GPUShaderFP64Test6(deqp::Context& context)
8178 : TestCase(context, "illegal_conversions", "Verifies that invalid casts to double-precision variables are detected "
8179 "during compilation time.")
8180 , m_cs_id(0)
8181 , m_fs_id(0)
8182 , m_gs_id(0)
8183 , m_tc_id(0)
8184 , m_te_id(0)
8185 , m_vs_id(0)
8186 , m_has_test_passed(true)
8187 {
8188 }
8189
8190 /** Deinitializes all buffers and GL objects that may have been generated
8191 * during test execution.
8192 **/
deinit()8193 void GPUShaderFP64Test6::deinit()
8194 {
8195 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8196
8197 if (m_cs_id != 0)
8198 {
8199 gl.deleteShader(m_cs_id);
8200
8201 m_cs_id = 0;
8202 }
8203
8204 if (m_fs_id != 0)
8205 {
8206 gl.deleteShader(m_fs_id);
8207
8208 m_fs_id = 0;
8209 }
8210
8211 if (m_gs_id != 0)
8212 {
8213 gl.deleteShader(m_gs_id);
8214
8215 m_gs_id = 0;
8216 }
8217
8218 if (m_tc_id != 0)
8219 {
8220 gl.deleteShader(m_tc_id);
8221
8222 m_tc_id = 0;
8223 }
8224
8225 if (m_te_id != 0)
8226 {
8227 gl.deleteShader(m_te_id);
8228
8229 m_te_id = 0;
8230 }
8231
8232 if (m_vs_id != 0)
8233 {
8234 gl.deleteShader(m_vs_id);
8235
8236 m_vs_id = 0;
8237 }
8238 }
8239
8240 /** Executes a single test case.
8241 *
8242 * This function can throw TestError exceptions if GL implementation reports
8243 * an error.
8244 *
8245 * @param test_case Test case descriptor.
8246 *
8247 * @return true if test case passed, false otherwise.
8248 **/
executeIteration(const _test_case & test_case)8249 bool GPUShaderFP64Test6::executeIteration(const _test_case& test_case)
8250 {
8251 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8252 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
8253 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
8254 bool result = true;
8255 const char* stage_body = NULL;
8256 const char* stage_name = NULL;
8257
8258 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
8259 {
8260 const glw::GLuint so_id = so_ids[n_so_id];
8261
8262 /* Skip compute shader if it is not supported */
8263 if (0 == so_id)
8264 {
8265 continue;
8266 }
8267
8268 /* Compile the shader */
8269 gl.compileShader(so_id);
8270 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8271
8272 /* Has the compilation failed as expected? */
8273 glw::GLint compile_status = GL_TRUE;
8274
8275 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
8276 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8277
8278 if (compile_status == GL_TRUE)
8279 {
8280 /* What is the current stage's name? */
8281 if (so_id == m_cs_id)
8282 {
8283 stage_body = test_case.cs_shader_body.c_str();
8284 stage_name = "Compute shader";
8285 }
8286 else if (so_id == m_fs_id)
8287 {
8288 stage_body = test_case.fs_shader_body.c_str();
8289 stage_name = "Fragment shader";
8290 }
8291 else if (so_id == m_gs_id)
8292 {
8293 stage_body = test_case.gs_shader_body.c_str();
8294 stage_name = "Geometry shader";
8295 }
8296 else if (so_id == m_tc_id)
8297 {
8298 stage_body = test_case.tc_shader_body.c_str();
8299 stage_name = "Tessellation control shader";
8300 }
8301 else if (so_id == m_te_id)
8302 {
8303 stage_body = test_case.te_shader_body.c_str();
8304 stage_name = "Tessellation evaluation shader";
8305 }
8306 else if (so_id == m_vs_id)
8307 {
8308 stage_body = test_case.vs_shader_body.c_str();
8309 stage_name = "Vertex shader";
8310 }
8311 else
8312 {
8313 /* Doesn't make much sense to throw exceptions here so.. */
8314 stage_body = "";
8315 stage_name = "[?]";
8316 }
8317
8318 /* This shader should have never compiled successfully! */
8319 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
8320 << " has been compiled successfully, even though the shader was malformed."
8321 " Following is shader body:\n"
8322 << stage_body << tcu::TestLog::EndMessage;
8323
8324 result = false;
8325 }
8326 } /* for (all shader objects) */
8327
8328 return result;
8329 }
8330
8331 /** Retrieves body of a compute shader that should be used for the purpose of
8332 * user-specified test case.
8333 *
8334 * @param test_case Test case descriptor to use.
8335 *
8336 * @return Requested string.
8337 **/
getComputeShaderBody(const _test_case & test_case)8338 std::string GPUShaderFP64Test6::getComputeShaderBody(const _test_case& test_case)
8339 {
8340 std::stringstream result_sstream;
8341
8342 /* Add pre-amble */
8343 result_sstream << "#version 420\n"
8344 "#extension GL_ARB_compute_shader : require\n"
8345 "\n"
8346 "layout(local_size_x = 6) in;\n"
8347 "\n"
8348 "void main()\n"
8349 "{\n";
8350
8351 /* Add local variable declarations */
8352 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8353
8354 if (test_case.src_array_size > 1)
8355 {
8356 result_sstream << "[" << test_case.src_array_size << "]";
8357 }
8358
8359 result_sstream << ";\n";
8360
8361 if (test_case.wrap_dst_type_in_structure)
8362 {
8363 result_sstream << "struct\n"
8364 "{\n"
8365 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8366 }
8367 else
8368 {
8369 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8370 }
8371
8372 result_sstream << ";\n";
8373
8374 if (test_case.wrap_dst_type_in_structure)
8375 {
8376 result_sstream << "\n} dst;\n";
8377 }
8378
8379 /* Add actual body */
8380 result_sstream << "dst = src;\n"
8381 "}\n";
8382
8383 /* Return the body */
8384 return result_sstream.str();
8385 }
8386
8387 /** Retrieves body of a fragment shader that should be used for the purpose of
8388 * user-specified test case.
8389 *
8390 * @param test_case Test case descriptor to use.
8391 *
8392 * @return Requested string.
8393 **/
getFragmentShaderBody(const _test_case & test_case)8394 std::string GPUShaderFP64Test6::getFragmentShaderBody(const _test_case& test_case)
8395 {
8396 std::stringstream result_sstream;
8397
8398 /* Add pre-amble */
8399 result_sstream << "#version 420\n"
8400 "\n"
8401 "void main()\n"
8402 "{\n";
8403
8404 /* Add local variable declarations */
8405 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8406
8407 if (test_case.src_array_size > 1)
8408 {
8409 result_sstream << "[" << test_case.src_array_size << "]";
8410 }
8411
8412 result_sstream << ";\n";
8413
8414 if (test_case.wrap_dst_type_in_structure)
8415 {
8416 result_sstream << "struct\n"
8417 "{\n"
8418 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8419 }
8420 else
8421 {
8422 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8423 }
8424
8425 result_sstream << ";\n";
8426
8427 if (test_case.wrap_dst_type_in_structure)
8428 {
8429 result_sstream << "\n} dst;\n";
8430 }
8431
8432 /* Add actual body */
8433 result_sstream << "dst = src;\n"
8434 "}\n";
8435
8436 /* Return the body */
8437 return result_sstream.str();
8438 }
8439
8440 /** Retrieves body of a geometry shader that should be used for the purpose of
8441 * user-specified test case.
8442 *
8443 * @param test_case Test case descriptor to use.
8444 *
8445 * @return Requested string.
8446 **/
getGeometryShaderBody(const _test_case & test_case)8447 std::string GPUShaderFP64Test6::getGeometryShaderBody(const _test_case& test_case)
8448 {
8449 std::stringstream result_sstream;
8450
8451 /* Add preamble */
8452 result_sstream << "#version 420\n"
8453 "\n"
8454 "layout(points) in;\n"
8455 "layout(max_vertices=1, points) out;\n"
8456 "\n"
8457 "void main()\n"
8458 "{\n";
8459
8460 /* Add local variable declarations */
8461 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8462
8463 if (test_case.src_array_size > 1)
8464 {
8465 result_sstream << "[" << test_case.src_array_size << "]";
8466 }
8467
8468 result_sstream << ";\n";
8469
8470 if (test_case.wrap_dst_type_in_structure)
8471 {
8472 result_sstream << "struct\n"
8473 "{\n"
8474 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8475 }
8476 else
8477 {
8478 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8479 }
8480
8481 result_sstream << ";\n"
8482 "\n";
8483
8484 if (test_case.wrap_dst_type_in_structure)
8485 {
8486 result_sstream << "} dst;\n";
8487 }
8488
8489 /* Add actual body */
8490 result_sstream << "dst = src;\n"
8491 "}\n";
8492
8493 /* We're done! */
8494 return result_sstream.str();
8495 }
8496
8497 /** Retrieves body of a tesellation control shader that should be used for the purpose of
8498 * user-specified test case.
8499 *
8500 * @param test_case Test case descriptor to use.
8501 *
8502 * @return Requested string.
8503 **/
getTessellationControlShaderBody(const _test_case & test_case)8504 std::string GPUShaderFP64Test6::getTessellationControlShaderBody(const _test_case& test_case)
8505 {
8506 std::stringstream result_sstream;
8507
8508 /* Add preamble */
8509 result_sstream << "#version 420\n"
8510 "\n"
8511 "layout(vertices=4) out;\n"
8512 "\n"
8513 "void main()\n"
8514 "{\n";
8515
8516 /* Add local variable declarations. */
8517 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8518
8519 if (test_case.src_array_size > 1)
8520 {
8521 result_sstream << "[" << test_case.src_array_size << "]";
8522 }
8523
8524 result_sstream << ";\n";
8525
8526 if (test_case.wrap_dst_type_in_structure)
8527 {
8528 result_sstream << "struct\n"
8529 "{\n"
8530 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8531 }
8532 else
8533 {
8534 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8535 }
8536
8537 if (test_case.wrap_dst_type_in_structure)
8538 {
8539 result_sstream << ";\n"
8540 "} dst;\n";
8541 }
8542 else
8543 {
8544 result_sstream << ";\n";
8545 }
8546
8547 /* Continue with the actual body. */
8548 result_sstream << "gl_TessLevelOuter[0] = 1.0;\n"
8549 "gl_TessLevelOuter[1] = 1.0;\n"
8550 "dst = src;\n"
8551 "}\n";
8552
8553 /* Return the body */
8554 return result_sstream.str();
8555 }
8556
8557 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
8558 * user-specified test case.
8559 *
8560 * @param test_case Test case descriptor to use.
8561 *
8562 * @return Requested string.
8563 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)8564 std::string GPUShaderFP64Test6::getTessellationEvaluationShaderBody(const _test_case& test_case)
8565 {
8566 std::stringstream result_sstream;
8567
8568 /* Add preamble */
8569 result_sstream << "#version 420\n"
8570 "\n"
8571 "layout(isolines) in;\n"
8572 "\n"
8573 "void main()\n"
8574 "{\n";
8575
8576 /* Add local variable declarations */
8577 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8578
8579 if (test_case.src_array_size > 1)
8580 {
8581 result_sstream << "[" << test_case.src_array_size << "]";
8582 }
8583
8584 result_sstream << ";\n";
8585
8586 if (test_case.wrap_dst_type_in_structure)
8587 {
8588 result_sstream << "struct\n"
8589 "{\n"
8590 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8591 }
8592 else
8593 {
8594 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8595 }
8596
8597 if (test_case.wrap_dst_type_in_structure)
8598 {
8599 result_sstream << ";\n"
8600 "} dst;\n";
8601 }
8602 else
8603 {
8604 result_sstream << ";\n";
8605 }
8606
8607 /* Continue with the actual body. */
8608 result_sstream << "dst = src;\n";
8609
8610 /* Complete the body */
8611 result_sstream << "}\n";
8612
8613 /* Return the body */
8614 return result_sstream.str();
8615 }
8616
8617 /** Retrieves body of a vertex shader that should be used for the purpose of
8618 * user-specified test case.
8619 *
8620 * @param test_case Test case descriptor to use.
8621 *
8622 * @return Requested string.
8623 **/
getVertexShaderBody(const _test_case & test_case)8624 std::string GPUShaderFP64Test6::getVertexShaderBody(const _test_case& test_case)
8625 {
8626 std::stringstream result_sstream;
8627
8628 /* Add preamble */
8629 result_sstream << "#version 420\n"
8630 "\n"
8631 "void main()\n"
8632 "{\n";
8633
8634 /* Add local variables */
8635 result_sstream << Utils::getVariableTypeString(test_case.src_type) << " src";
8636
8637 if (test_case.src_array_size > 1)
8638 {
8639 result_sstream << "[" << test_case.src_array_size << "]";
8640 }
8641
8642 result_sstream << ";\n";
8643
8644 if (test_case.wrap_dst_type_in_structure)
8645 {
8646 result_sstream << "struct\n"
8647 "{\n"
8648 << Utils::getVariableTypeString(test_case.dst_type) << " member";
8649 }
8650 else
8651 {
8652 result_sstream << Utils::getVariableTypeString(test_case.dst_type) << " dst";
8653 }
8654
8655 if (test_case.wrap_dst_type_in_structure)
8656 {
8657 result_sstream << ";\n"
8658 "} dst;\n";
8659 }
8660 else
8661 {
8662 result_sstream << ";\n";
8663 }
8664
8665 /* Start actual body */
8666 result_sstream << "dst = src;\n"
8667 "gl_Position = vec4(1.0);\n"
8668 "}";
8669
8670 return result_sstream.str();
8671 }
8672
8673 /** Initializes shader objects required to run the test. */
initTest()8674 void GPUShaderFP64Test6::initTest()
8675 {
8676 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8677
8678 /* Generate shader objects */
8679
8680 /* Compute shader support and GL 4.2 required */
8681 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
8682 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
8683 {
8684 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
8685 }
8686
8687 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
8688 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
8689 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
8690 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
8691 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
8692
8693 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
8694 }
8695
8696 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
8697 *
8698 * @param test_case Test case descriptor to generate the shader bodies for.
8699 **/
initIteration(_test_case & test_case)8700 void GPUShaderFP64Test6::initIteration(_test_case& test_case)
8701 {
8702 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8703
8704 test_case.cs_shader_body = getComputeShaderBody(test_case);
8705 test_case.fs_shader_body = getFragmentShaderBody(test_case);
8706 test_case.gs_shader_body = getGeometryShaderBody(test_case);
8707 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
8708 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
8709 test_case.vs_shader_body = getVertexShaderBody(test_case);
8710
8711 /* Assign the bodies to relevant shaders */
8712 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
8713 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
8714 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
8715 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
8716 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
8717 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
8718
8719 /* m_cs_id is initialized only if compute_shader is supported */
8720 if (0 != m_cs_id)
8721 {
8722 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
8723 }
8724
8725 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
8726 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
8727 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
8728 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
8729 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
8730 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
8731 }
8732
8733 /** Executes test iteration.
8734 *
8735 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
8736 */
iterate()8737 tcu::TestNode::IterateResult GPUShaderFP64Test6::iterate()
8738 {
8739 /* Do not execute the test if GL_ARB_texture_view is not supported */
8740 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
8741 {
8742 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
8743 }
8744
8745 /* Initialize GL objects needed to run the tests */
8746 initTest();
8747
8748 /* Build iteration array to run the tests in an automated manner */
8749 _test_case test_cases[] = {
8750 /* Src array size */ /* Src type */ /* Dst type */ /* wrap_dst_type_in_structure */
8751 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8752 { 2, Utils::VARIABLE_TYPE_INT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8753 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8754 { 2, Utils::VARIABLE_TYPE_IVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8755 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8756 { 2, Utils::VARIABLE_TYPE_IVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8757 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8758 { 2, Utils::VARIABLE_TYPE_IVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8759 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8760 { 2, Utils::VARIABLE_TYPE_UINT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8761 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8762 { 2, Utils::VARIABLE_TYPE_UVEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8763 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8764 { 2, Utils::VARIABLE_TYPE_UVEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8765 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8766 { 2, Utils::VARIABLE_TYPE_UVEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8767 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, false, "", "", "", "", "", "" },
8768 { 2, Utils::VARIABLE_TYPE_FLOAT, Utils::VARIABLE_TYPE_DOUBLE, true, "", "", "", "", "", "" },
8769 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, false, "", "", "", "", "", "" },
8770 { 2, Utils::VARIABLE_TYPE_VEC2, Utils::VARIABLE_TYPE_DVEC2, true, "", "", "", "", "", "" },
8771 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, false, "", "", "", "", "", "" },
8772 { 2, Utils::VARIABLE_TYPE_VEC3, Utils::VARIABLE_TYPE_DVEC3, true, "", "", "", "", "", "" },
8773 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, false, "", "", "", "", "", "" },
8774 { 2, Utils::VARIABLE_TYPE_VEC4, Utils::VARIABLE_TYPE_DVEC4, true, "", "", "", "", "", "" },
8775 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, false, "", "", "", "", "", "" },
8776 { 2, Utils::VARIABLE_TYPE_MAT2, Utils::VARIABLE_TYPE_DMAT2, true, "", "", "", "", "", "" },
8777 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, false, "", "", "", "", "", "" },
8778 { 2, Utils::VARIABLE_TYPE_MAT3, Utils::VARIABLE_TYPE_DMAT3, true, "", "", "", "", "", "" },
8779 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, false, "", "", "", "", "", "" },
8780 { 2, Utils::VARIABLE_TYPE_MAT4, Utils::VARIABLE_TYPE_DMAT4, true, "", "", "", "", "", "" },
8781 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, false, "", "", "", "", "", "" },
8782 { 2, Utils::VARIABLE_TYPE_MAT2X3, Utils::VARIABLE_TYPE_DMAT2X3, true, "", "", "", "", "", "" },
8783 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, false, "", "", "", "", "", "" },
8784 { 2, Utils::VARIABLE_TYPE_MAT2X4, Utils::VARIABLE_TYPE_DMAT2X4, true, "", "", "", "", "", "" },
8785 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, false, "", "", "", "", "", "" },
8786 { 2, Utils::VARIABLE_TYPE_MAT3X2, Utils::VARIABLE_TYPE_DMAT3X2, true, "", "", "", "", "", "" },
8787 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, false, "", "", "", "", "", "" },
8788 { 2, Utils::VARIABLE_TYPE_MAT3X4, Utils::VARIABLE_TYPE_DMAT3X4, true, "", "", "", "", "", "" },
8789 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, false, "", "", "", "", "", "" },
8790 { 2, Utils::VARIABLE_TYPE_MAT4X2, Utils::VARIABLE_TYPE_DMAT4X2, true, "", "", "", "", "", "" },
8791 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, false, "", "", "", "", "", "" },
8792 { 2, Utils::VARIABLE_TYPE_MAT4X3, Utils::VARIABLE_TYPE_DMAT4X3, true, "", "", "", "", "", "" }
8793 };
8794 const unsigned int n_test_cases = sizeof(test_cases) / sizeof(test_cases[0]);
8795
8796 /* Execute all iterations */
8797 for (unsigned int n_test_case = 0; n_test_case < n_test_cases; ++n_test_case)
8798 {
8799 _test_case& test_case = test_cases[n_test_case];
8800
8801 /* Initialize a program object we will use to perform the casting */
8802 initIteration(test_case);
8803
8804 /* Use the program object to XFB the results */
8805 m_has_test_passed &= executeIteration(test_case);
8806
8807 } /* for (all test cases) */
8808
8809 /* We're done */
8810 if (m_has_test_passed)
8811 {
8812 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
8813 }
8814 else
8815 {
8816 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8817 }
8818
8819 return STOP;
8820 }
8821
8822 /** Constructor
8823 *
8824 * @param context Rendering context.
8825 */
GPUShaderFP64Test7(deqp::Context & context)8826 GPUShaderFP64Test7::GPUShaderFP64Test7(deqp::Context& context)
8827 : TestCase(context, "varyings", "Verifies double-precision floating-point varyings work correctly "
8828 "in all shader stages.")
8829 , m_are_double_inputs_supported(false)
8830 , m_fbo_id(0)
8831 , m_fs_id(0)
8832 , m_gs_id(0)
8833 , m_has_test_passed(true)
8834 , m_n_max_components_per_stage(0)
8835 , m_n_xfb_varyings(0)
8836 , m_po_id(0)
8837 , m_tc_id(0)
8838 , m_te_id(0)
8839 , m_to_id(0)
8840 , m_to_data(NULL)
8841 , m_to_height(4)
8842 , m_to_width(4)
8843 , m_xfb_bo_id(0)
8844 , m_xfb_varyings(NULL)
8845 , m_vao_id(0)
8846 , m_vs_id(0)
8847 {
8848 }
8849
8850 /** Compiles all shaders attached to test program object and links it.
8851 *
8852 * @param variables
8853 *
8854 * @return true if the process was executed successfully, false otherwise.
8855 */
buildTestProgram(_variables & variables)8856 bool GPUShaderFP64Test7::buildTestProgram(_variables& variables)
8857 {
8858 std::string fs_body = getFragmentShaderBody(variables);
8859 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8860 std::string gs_body = getGeometryShaderBody(variables);
8861 std::string tc_body = getTessellationControlShaderBody(variables);
8862 std::string te_body = getTessellationEvaluationShaderBody(variables);
8863 std::string vs_body = getVertexShaderBody(variables);
8864 bool result = false;
8865
8866 /* Try to link the program object */
8867 glw::GLint link_status = GL_FALSE;
8868
8869 /* Compile the shaders */
8870 if (!compileShader(m_fs_id, fs_body))
8871 {
8872 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader failed to compile." << tcu::TestLog::EndMessage;
8873
8874 goto end;
8875 }
8876
8877 if (!compileShader(m_gs_id, gs_body))
8878 {
8879 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry shader failed to compile." << tcu::TestLog::EndMessage;
8880
8881 goto end;
8882 }
8883
8884 if (!compileShader(m_tc_id, tc_body))
8885 {
8886 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation control shader failed to compile."
8887 << tcu::TestLog::EndMessage;
8888
8889 goto end;
8890 }
8891
8892 if (!compileShader(m_te_id, te_body))
8893 {
8894 m_testCtx.getLog() << tcu::TestLog::Message << "Tessellation evaluation shader failed to compile."
8895 << tcu::TestLog::EndMessage;
8896
8897 goto end;
8898 }
8899
8900 if (!compileShader(m_vs_id, vs_body))
8901 {
8902 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader failed to compile." << tcu::TestLog::EndMessage;
8903
8904 goto end;
8905 }
8906
8907 /* Configure XFB */
8908 releaseXFBVaryingNames();
8909 generateXFBVaryingNames(variables);
8910
8911 gl.transformFeedbackVaryings(m_po_id, m_n_xfb_varyings, m_xfb_varyings, GL_INTERLEAVED_ATTRIBS);
8912
8913 gl.linkProgram(m_po_id);
8914
8915 /* Have we succeeded? */
8916 GLU_EXPECT_NO_ERROR(gl.getError(), "Either glTransformFeedbackVaryings() or glLinkProgram() call failed.");
8917
8918 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
8919 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
8920
8921 if (link_status != GL_TRUE)
8922 {
8923 m_testCtx.getLog() << tcu::TestLog::Message << "A valid program object failed to link."
8924 << tcu::TestLog::EndMessage;
8925
8926 goto end;
8927 }
8928
8929 /* Retrieve attribute locations *if* GL_ARB_vertex_attrib_64bit is supported */
8930 if (m_are_double_inputs_supported)
8931 {
8932 const size_t n_variables = variables.size();
8933
8934 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
8935 {
8936 _variable& current_variable = variables[n_variable];
8937 std::stringstream attribute_name_sstream;
8938
8939 attribute_name_sstream << "in_vs_variable" << n_variable;
8940
8941 if (current_variable.array_size > 1)
8942 {
8943 attribute_name_sstream << "[0]";
8944 }
8945
8946 current_variable.attribute_location = gl.getAttribLocation(m_po_id, attribute_name_sstream.str().c_str());
8947
8948 if (current_variable.attribute_location == -1)
8949 {
8950 m_testCtx.getLog() << tcu::TestLog::Message << "Input double-precision attribute named ["
8951 << attribute_name_sstream.str().c_str()
8952 << "] is considered inactive which is invalid." << tcu::TestLog::EndMessage;
8953
8954 m_has_test_passed = false;
8955 goto end;
8956 }
8957 } /* for (all test variables) */
8958 } /* if (m_are_double_inputs_supported) */
8959
8960 m_current_fs_body = fs_body;
8961 m_current_gs_body = gs_body;
8962 m_current_tc_body = tc_body;
8963 m_current_te_body = te_body;
8964 m_current_vs_body = vs_body;
8965
8966 result = true;
8967
8968 end:
8969 return result;
8970 }
8971
8972 /** Updates shader object's body and then compiles the shader.
8973 *
8974 * @param body Body to use for the shader.
8975 *
8976 * @return true if the shader compiled successfully, false otherwise.
8977 **/
compileShader(glw::GLint shader_id,const std::string & body)8978 bool GPUShaderFP64Test7::compileShader(glw::GLint shader_id, const std::string& body)
8979 {
8980 const char* body_raw_ptr = body.c_str();
8981 glw::GLint compile_status = GL_FALSE;
8982 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
8983
8984 gl.shaderSource(shader_id, 1 /* count */, &body_raw_ptr, NULL /* length */);
8985 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
8986
8987 gl.compileShader(shader_id);
8988 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
8989
8990 gl.getShaderiv(shader_id, GL_COMPILE_STATUS, &compile_status);
8991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
8992
8993 return (compile_status == GL_TRUE);
8994 }
8995
8996 /** Configure storage of a buffer object used for capturing XFB data.
8997 *
8998 * @param variables Holds descriptor for all variables used for the iteration the
8999 * BO is being configured for. Storage size will be directly related
9000 * to the number of the variables and their type.
9001 */
configureXFBBuffer(const _variables & variables)9002 void GPUShaderFP64Test7::configureXFBBuffer(const _variables& variables)
9003 {
9004 DE_ASSERT(m_n_xfb_varyings != 0);
9005
9006 /* Geometry shaders outputs 4 vertices making up a triangle strip per draw call.
9007 * The test only draws a single patch, and triangles are caught by transform feed-back.
9008 * Let's initialize the storage, according to the list of variables that will be used
9009 * for the test run.
9010 */
9011 unsigned int bo_size = 0;
9012
9013 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9014 variables_iterator++)
9015 {
9016 const _variable& variable = *variables_iterator;
9017 unsigned int n_bytes_needed = static_cast<unsigned int>(
9018 Utils::getNumberOfComponentsForVariableType(variable.type) * variable.array_size * sizeof(double));
9019
9020 bo_size += n_bytes_needed;
9021 } /* for (all variables) */
9022
9023 bo_size *= 3 /* vertices per triangle */ * 2; /* triangles emitted by geometry shader */
9024
9025 /* Set up the BO storage */
9026 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9027
9028 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
9029 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
9030 }
9031
9032 /** Deinitializes all buffers and GL objects that may have been generated
9033 * during test execution.
9034 **/
deinit()9035 void GPUShaderFP64Test7::deinit()
9036 {
9037 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9038
9039 if (m_fbo_id != 0)
9040 {
9041 gl.deleteFramebuffers(1, &m_fbo_id);
9042
9043 m_fbo_id = 0;
9044 }
9045
9046 if (m_fs_id != 0)
9047 {
9048 gl.deleteShader(m_fs_id);
9049
9050 m_fs_id = 0;
9051 }
9052
9053 if (m_gs_id != 0)
9054 {
9055 gl.deleteShader(m_gs_id);
9056
9057 m_gs_id = 0;
9058 }
9059
9060 if (m_po_id != 0)
9061 {
9062 gl.deleteProgram(m_po_id);
9063
9064 m_po_id = 0;
9065 }
9066
9067 if (m_tc_id != 0)
9068 {
9069 gl.deleteShader(m_tc_id);
9070
9071 m_tc_id = 0;
9072 }
9073
9074 if (m_te_id != 0)
9075 {
9076 gl.deleteShader(m_te_id);
9077
9078 m_te_id = 0;
9079 }
9080
9081 if (m_to_data != NULL)
9082 {
9083 delete[] m_to_data;
9084
9085 m_to_data = NULL;
9086 }
9087
9088 if (m_to_id != 0)
9089 {
9090 gl.deleteTextures(1, &m_to_id);
9091
9092 m_to_id = 0;
9093 }
9094
9095 if (m_xfb_bo_id != 0)
9096 {
9097 gl.deleteBuffers(1, &m_xfb_bo_id);
9098
9099 m_xfb_bo_id = 0;
9100 }
9101
9102 if (m_xfb_varyings != DE_NULL)
9103 {
9104 releaseXFBVaryingNames();
9105 }
9106
9107 if (m_vao_id != 0)
9108 {
9109 gl.deleteVertexArrays(1, &m_vao_id);
9110
9111 m_vao_id = 0;
9112 }
9113
9114 if (m_vs_id != 0)
9115 {
9116 gl.deleteShader(m_vs_id);
9117
9118 m_vs_id = 0;
9119 }
9120 }
9121
9122 /** Executes the functional part of the test (case a) from the test spec)
9123 *
9124 * @param variables Vector of variable descriptors defining properties of
9125 * variables that should be used for the iteration.
9126 *
9127 * @return true if the test passed, false otherwise.
9128 **/
executeFunctionalTest(_variables & variables)9129 bool GPUShaderFP64Test7::executeFunctionalTest(_variables& variables)
9130 {
9131 bool result = true;
9132
9133 /* Build the test program */
9134 if (!buildTestProgram(variables))
9135 {
9136 return false;
9137 }
9138
9139 /* Set up input attributes if GL_ARB_vertex_attrib_64bit extension is supported */
9140 if (m_are_double_inputs_supported)
9141 {
9142 setInputAttributeValues(variables);
9143 }
9144
9145 /* Set up buffer object to hold XFB data. The data will be used for logging purposes
9146 * only, if a data mismatch is detected.
9147 */
9148 configureXFBBuffer(variables);
9149
9150 /* Issue a draw call using the test program */
9151 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9152
9153 gl.clearColor(1.0f, 1.0f, 1.0f, 1.0f);
9154 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
9155
9156 gl.clear(GL_COLOR_BUFFER_BIT);
9157 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
9158
9159 gl.useProgram(m_po_id);
9160 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
9161
9162 gl.viewport(0, /* x */
9163 0, /* y */
9164 m_to_width, m_to_height);
9165 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
9166
9167 gl.beginTransformFeedback(GL_TRIANGLES);
9168 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
9169 {
9170 gl.drawArrays(GL_PATCHES, 0 /* first */, 4 /* count */);
9171 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
9172 }
9173 gl.endTransformFeedback();
9174 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
9175
9176 /* Verify color attachment contents */
9177 const float epsilon = 1.0f / 255.0f;
9178
9179 gl.readPixels(0 /* x */, 0 /* y */, m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, m_to_data);
9180 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
9181
9182 for (unsigned int y = 0; y < m_to_height; ++y)
9183 {
9184 const unsigned char* row_ptr = m_to_data + 4 /* rgba */ * m_to_width * y;
9185
9186 for (unsigned int x = 0; x < m_to_width; ++x)
9187 {
9188 const unsigned char* pixel_ptr = row_ptr + 4 /* rgba */ * x;
9189
9190 if (de::abs(pixel_ptr[0]) > epsilon || de::abs(pixel_ptr[1] - 255) > epsilon ||
9191 de::abs(pixel_ptr[2]) > epsilon || de::abs(pixel_ptr[3]) > epsilon)
9192 {
9193 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel found at (" << x << ", " << y
9194 << ")"
9195 "; expected:(0, 255, 0, 0), found: ("
9196 << (int)pixel_ptr[0] << ", " << (int)pixel_ptr[1] << ", " << (int)pixel_ptr[2]
9197 << ", " << (int)pixel_ptr[3]
9198 << "), with the following variable types used as varyings:"
9199 << tcu::TestLog::EndMessage;
9200
9201 /* List the variable types that failed the test */
9202 const size_t n_variables = variables.size();
9203
9204 for (size_t n_variable = 0; n_variable < n_variables; ++n_variable)
9205 {
9206 m_testCtx.getLog() << tcu::TestLog::Message << "gs_variable" << n_variable << ": "
9207 << Utils::getVariableTypeString(variables[n_variable].type)
9208 << " (array size:" << variables[n_variable].array_size << ")"
9209 << tcu::TestLog::EndMessage;
9210 } /* for (all variable types) */
9211
9212 /* Log the variable contents */
9213 logVariableContents(variables);
9214
9215 /* Log shaders used for the iteration */
9216 m_testCtx.getLog() << tcu::TestLog::Message << "Shaders used:\n"
9217 "\n"
9218 "(VS):\n"
9219 << m_current_vs_body.c_str() << "\n"
9220 << "(TC):\n"
9221 "\n"
9222 << m_current_tc_body.c_str() << "\n"
9223 "(TE):\n"
9224 "\n"
9225 << m_current_te_body.c_str() << "\n"
9226 "(GS):\n"
9227 << m_current_gs_body.c_str() << "\n"
9228 "(FS):\n"
9229 "\n"
9230 << m_current_fs_body.c_str() << tcu::TestLog::EndMessage;
9231
9232 result = false;
9233
9234 goto end;
9235 }
9236 } /* for (all columns) */
9237 } /* for (all rows) */
9238
9239 /* All done! */
9240 end:
9241 return result;
9242 }
9243
9244 /** Takes user-input vector of test variables and allocates & fills an array of strings
9245 * holding names of geometry shader stage varyings that should be captured during
9246 * transform feedback operation. The array will be stored in m_xfb_varyings.
9247 *
9248 * @param variables Holds all test variable descriptors to be used for the iteration.
9249 */
generateXFBVaryingNames(const _variables & variables)9250 void GPUShaderFP64Test7::generateXFBVaryingNames(const _variables& variables)
9251 {
9252 unsigned int n_variable = 0;
9253 unsigned int n_varying = 0;
9254 unsigned int n_varyings = 0;
9255
9256 if (m_xfb_varyings != NULL)
9257 {
9258 releaseXFBVaryingNames();
9259 }
9260
9261 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9262 ++variables_iterator)
9263 {
9264 const _variable& variable = *variables_iterator;
9265
9266 n_varyings += variable.array_size;
9267 }
9268
9269 m_xfb_varyings = new glw::GLchar*[n_varyings];
9270
9271 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
9272 ++variables_iterator, ++n_variable)
9273 {
9274 const _variable& variable = *variables_iterator;
9275
9276 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index, ++n_varying)
9277 {
9278 std::stringstream varying_sstream;
9279 size_t varying_length;
9280
9281 varying_sstream << "gs_variable" << n_variable;
9282
9283 if (variable.array_size > 1)
9284 {
9285 varying_sstream << "[" << array_index << "]";
9286 }
9287
9288 /* Store the varying name */
9289 varying_length = varying_sstream.str().length();
9290 m_xfb_varyings[n_varying] = new glw::GLchar[varying_length + 1 /* terminator */];
9291
9292 memcpy(m_xfb_varyings[n_varying], varying_sstream.str().c_str(), varying_length);
9293 m_xfb_varyings[n_varying][varying_length] = 0;
9294 } /* for (all array indices) */
9295 } /* for (all varyings) */
9296
9297 m_n_xfb_varyings = n_varyings;
9298 }
9299
9300 /** Retrieves body of a shader that defines input variable of user-specified type & array size
9301 * without using the "flat" keyword. (case c) )
9302 *
9303 * @param input_variable_type Variable type to use for input variable declaration.
9304 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9305 * of the arrayed variable.
9306 *
9307 * @return Requested string.
9308 **/
getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(Utils::_variable_type input_variable_type,unsigned int array_size)9309 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(
9310 Utils::_variable_type input_variable_type, unsigned int array_size)
9311 {
9312 std::stringstream result_sstream;
9313 std::stringstream array_index_stringstream;
9314 std::stringstream array_size_stringstream;
9315
9316 if (array_size > 1)
9317 {
9318 array_index_stringstream << "[0]";
9319 array_size_stringstream << "[" << array_size << "]";
9320 }
9321
9322 if (Utils::isMatrixVariableType(input_variable_type))
9323 {
9324 array_index_stringstream << "[0].x";
9325 }
9326 else if (Utils::getNumberOfComponentsForVariableType(input_variable_type) > 1)
9327 {
9328 array_index_stringstream << "[0]";
9329 }
9330
9331 result_sstream << "#version 400\n"
9332 "\n"
9333 "in "
9334 << Utils::getVariableTypeString(input_variable_type) << " test_input"
9335 << array_size_stringstream.str() << ";\n"
9336 "\n"
9337 "out float test_output;\n"
9338 "\n"
9339 "void main()\n"
9340 "{\n"
9341 " if (test_input"
9342 << array_index_stringstream.str() << " > 2.0)\n"
9343 " {\n"
9344 " test_output = 1.0;\n"
9345 " }\n"
9346 " else\n"
9347 " {\n"
9348 " test_output = 3.0;\n"
9349 " }\n"
9350 "}\n";
9351
9352 return result_sstream.str();
9353 }
9354
9355 /** Retrieves body of a shader that defines double-precision floating-point output variable. (case b) ).
9356 *
9357 * @param input_variable_type Variable type to use for input variable declaration.
9358 * @param array_size 1 if the variable should not be arrayed; otherwise defines size
9359 * of the arrayed variable.
9360 *
9361 * @return Requested string.
9362 **/
getCodeOfFragmentShaderWithDoublePrecisionOutput(Utils::_variable_type output_variable_type,unsigned int array_size)9363 std::string GPUShaderFP64Test7::getCodeOfFragmentShaderWithDoublePrecisionOutput(
9364 Utils::_variable_type output_variable_type, unsigned int array_size)
9365 {
9366 std::stringstream array_index_sstream;
9367 std::stringstream array_size_sstream;
9368 std::stringstream result_sstream;
9369 std::string output_variable_type_string = Utils::getVariableTypeString(output_variable_type);
9370
9371 if (array_size > 1)
9372 {
9373 array_index_sstream << "[0]";
9374 array_size_sstream << "[" << array_size << "]";
9375 }
9376
9377 result_sstream << "#version 400\n"
9378 "\n"
9379 "out "
9380 << output_variable_type_string << " test_output" << array_size_sstream.str() << ";\n"
9381 "\n"
9382 "void main()\n"
9383 "{\n"
9384 " test_output"
9385 << array_index_sstream.str() << " = " << output_variable_type_string << "(2.0);\n"
9386 "}\n";
9387
9388 return result_sstream.str();
9389 }
9390
9391 /** Retrieves body of a fragment shader that uses user-specified set of variables
9392 * to declare contents of input & output block.
9393 *
9394 * @param variables As per description.
9395 *
9396 * @return Requested string.
9397 **/
getFragmentShaderBody(const _variables & variables)9398 std::string GPUShaderFP64Test7::getFragmentShaderBody(const _variables& variables)
9399 {
9400 std::stringstream result_sstream;
9401
9402 /* Form the pre-amble */
9403 result_sstream << "#version 400\n"
9404 "\n"
9405
9406 /* Add input block */
9407 << "in GS_DATA\n"
9408 "{\n"
9409 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9410 "\n"
9411
9412 /* Add output variable */
9413 << "out vec4 result;\n"
9414 "\n"
9415
9416 /* Add main() definition */
9417 "void main()\n"
9418 "{\n"
9419 "const double epsilon = 1e-5;\n"
9420 "\n"
9421 "result = vec4(1, 0, 0, 0);\n"
9422 "\n";
9423
9424 /* Determine expected values first */
9425 unsigned int base_counter = 1;
9426 const size_t n_variables = variables.size();
9427
9428 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9429 {
9430 unsigned int variable_array_size = variables[n_variable].array_size;
9431 Utils::_variable_type variable_type = variables[n_variable].type;
9432 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9433 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9434
9435 std::stringstream array_size_sstream;
9436
9437 if (variable_array_size > 1)
9438 {
9439 array_size_sstream << "[" << variable_array_size << "]";
9440 }
9441
9442 /* Local variable declaration */
9443 result_sstream << variable_type_string << " expected_variable" << n_variable << array_size_sstream.str()
9444 << ";\n"
9445 "\n";
9446
9447 /* Set expected values */
9448 for (unsigned int index = 0; index < variable_array_size; ++index)
9449 {
9450 std::stringstream array_index_sstream;
9451
9452 if (variable_array_size > 1)
9453 {
9454 array_index_sstream << "[" << index << "]";
9455 }
9456
9457 result_sstream << "expected_variable" << n_variable << array_index_sstream.str() << " = "
9458 << variable_type_string << "(";
9459
9460 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9461 {
9462 unsigned int expected_value =
9463 (base_counter + 0) + (base_counter + 1) + (base_counter + 2) + (base_counter + 3);
9464
9465 if (m_are_double_inputs_supported)
9466 {
9467 /* VS input attributes */
9468 //expected_value += (base_counter + 6);
9469 expected_value -= 1;
9470 }
9471
9472 result_sstream << expected_value;
9473
9474 if (n_component != (n_variable_type_components - 1))
9475 {
9476 result_sstream << ", ";
9477 }
9478
9479 ++base_counter;
9480 } /* for (all components) */
9481
9482 result_sstream << ");\n";
9483 } /* for (all array indices) */
9484
9485 result_sstream << "\n";
9486 } /* for (all variable types) */
9487
9488 /* Now that we know the expected values, do a huge conditional check to verify if all
9489 * input variables carry correct information.
9490 */
9491 result_sstream << "if (";
9492
9493 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9494 {
9495 unsigned int variable_array_size = variables[n_variable].array_size;
9496 Utils::_variable_type variable_type = variables[n_variable].type;
9497 bool is_variable_type_matrix = Utils::isMatrixVariableType(variable_type);
9498 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9499 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9500
9501 for (unsigned int index = 0; index < variable_array_size; ++index)
9502 {
9503 std::stringstream array_index_sstream;
9504
9505 if (variable_array_size > 1)
9506 {
9507 array_index_sstream << "[" << index << "]";
9508 }
9509
9510 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9511 {
9512 std::stringstream component_index_sstream;
9513
9514 if (n_variable_type_components > 1)
9515 {
9516 component_index_sstream << "[" << n_component << "]";
9517 }
9518
9519 result_sstream << "abs(expected_variable" << n_variable << array_index_sstream.str();
9520
9521 if (is_variable_type_matrix)
9522 {
9523 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9524 const unsigned int column = n_component % n_columns;
9525 const unsigned int row = n_component / n_columns;
9526
9527 result_sstream << "[" << column << "]"
9528 "."
9529 << Utils::getComponentAtIndex(row);
9530 }
9531 else
9532 {
9533 result_sstream << component_index_sstream.str();
9534 }
9535
9536 result_sstream << " - gs_variable" << n_variable << array_index_sstream.str();
9537
9538 if (is_variable_type_matrix)
9539 {
9540 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9541 const unsigned int column = n_component % n_columns;
9542 const unsigned int row = n_component / n_columns;
9543
9544 result_sstream << "[" << column << "]"
9545 "."
9546 << Utils::getComponentAtIndex(row);
9547 }
9548 else
9549 {
9550 result_sstream << component_index_sstream.str();
9551 }
9552
9553 result_sstream << ") <= epsilon &&";
9554 } /* for (all components) */
9555 } /* for (all array indices) */
9556 } /* for (all variable types) */
9557
9558 result_sstream << "true)\n"
9559 "{\n"
9560 " result = vec4(0, 1, 0, 0);\n"
9561 "}\n"
9562 "}\n";
9563
9564 /* All done */
9565 return result_sstream.str();
9566 }
9567
9568 /** Retrieves body of a geometry shader that uses user-specified set of variables
9569 * to declare contents of input & output block.
9570 *
9571 * @param variables As per description.
9572 *
9573 * @return Requested string.
9574 **/
getGeometryShaderBody(const _variables & variables)9575 std::string GPUShaderFP64Test7::getGeometryShaderBody(const _variables& variables)
9576 {
9577 std::stringstream result_sstream;
9578
9579 /* Form the pre-amble */
9580 result_sstream << "#version 400\n"
9581 "\n"
9582 "layout(triangles) in;\n"
9583 "layout(triangle_strip, max_vertices=4) out;\n"
9584 "\n"
9585
9586 /* Add the input block */
9587 "in TE_DATA\n"
9588 "{\n"
9589 << getVariableDeclarations("te", variables) << "} in_data[];\n"
9590 "\n"
9591
9592 /* Add the output block */
9593 "out GS_DATA\n"
9594 "{\n"
9595 << getVariableDeclarations("gs", variables, "flat") << "};\n"
9596 "\n"
9597
9598 /* Declare main() function */
9599 "void main()\n"
9600 "{\n";
9601
9602 /* Take input variables, add a predefined value and forward them to output variables */
9603 const float quad_vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
9604 1.0f, -1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f };
9605 const unsigned int n_quad_vertices =
9606 sizeof(quad_vertices) / sizeof(quad_vertices[0]) / 4 /* components per vertex */;
9607 const size_t n_variables = variables.size();
9608
9609 for (unsigned int n_quad_vertex = 0; n_quad_vertex < n_quad_vertices; ++n_quad_vertex)
9610 {
9611 unsigned int counter = 4;
9612 const float* current_quad_vertex = quad_vertices + n_quad_vertex * 4 /* components per vertex */;
9613
9614 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9615 {
9616 unsigned int variable_array_size = variables[n_variable].array_size;
9617 Utils::_variable_type variable_type = variables[n_variable].type;
9618 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9619 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9620
9621 for (unsigned int index = 0; index < variable_array_size; ++index)
9622 {
9623 std::stringstream array_index_sstream;
9624
9625 if (variable_array_size > 1)
9626 {
9627 array_index_sstream << "[" << index << "]";
9628 }
9629
9630 result_sstream << "gs_variable" << n_variable << array_index_sstream.str()
9631 << " = in_data[0].te_variable" << n_variable << array_index_sstream.str() << " + "
9632 << variable_type_string << "(";
9633
9634 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9635 {
9636 result_sstream << (counter++);
9637
9638 if (n_component != (n_variable_type_components - 1))
9639 {
9640 result_sstream << ", ";
9641 }
9642 } /* for (all components) */
9643
9644 result_sstream << ");\n";
9645 } /* for (all array indices) */
9646 } /* for (all variable types) */
9647
9648 result_sstream << "gl_Position = vec4(" << current_quad_vertex[0] << ", " << current_quad_vertex[1] << ", "
9649 << current_quad_vertex[2] << ", " << current_quad_vertex[3] << ");\n"
9650 "EmitVertex();\n";
9651 } /* for (all emitted quad vertices) */
9652
9653 result_sstream << "EndPrimitive();\n"
9654 "}\n";
9655
9656 /* All done */
9657 return result_sstream.str();
9658 }
9659
9660 /** Retrieves body of a tessellation control shader that uses user-specified set of variables
9661 * to declare contents of input & output block.
9662 *
9663 * @param variables As per description.
9664 *
9665 * @return Requested string.
9666 **/
getTessellationControlShaderBody(const _variables & variables)9667 std::string GPUShaderFP64Test7::getTessellationControlShaderBody(const _variables& variables)
9668 {
9669 std::stringstream result_sstream;
9670
9671 /* Form the pre-amble */
9672 result_sstream << "#version 400\n"
9673 "\n"
9674 "layout (vertices=4) out;\n"
9675
9676 /* Declare input block */
9677 "in VS_DATA\n"
9678 "{\n"
9679 << getVariableDeclarations("vs", variables) << "} in_data[];\n"
9680
9681 /* Declare output block */
9682 "out TC_DATA\n"
9683 "{\n"
9684 << getVariableDeclarations("tc", variables) << "} out_data[];\n"
9685 "\n"
9686
9687 /* Define main() */
9688 "void main()\n"
9689 "{\n"
9690 " gl_TessLevelInner[0] = 1;\n"
9691 " gl_TessLevelInner[1] = 1;\n"
9692 " gl_TessLevelOuter[0] = 1;\n"
9693 " gl_TessLevelOuter[1] = 1;\n"
9694 " gl_TessLevelOuter[2] = 1;\n"
9695 " gl_TessLevelOuter[3] = 1;\n"
9696 "\n";
9697
9698 /* Take input variables, add a predefined value and forward them to output variables */
9699 const size_t n_variables = variables.size();
9700 unsigned int counter = 2;
9701
9702 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9703 {
9704 unsigned int variable_array_size = variables[n_variable].array_size;
9705 Utils::_variable_type variable_type = variables[n_variable].type;
9706 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9707 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9708
9709 for (unsigned int index = 0; index < variable_array_size; ++index)
9710 {
9711 std::stringstream array_index_sstream;
9712
9713 if (variable_array_size > 1)
9714 {
9715 array_index_sstream << "[" << index << "]";
9716 }
9717
9718 result_sstream << "out_data[gl_InvocationID].tc_variable" << n_variable << array_index_sstream.str()
9719 << " = in_data[0].vs_variable" << n_variable << array_index_sstream.str() << " + "
9720 << variable_type_string << "(";
9721
9722 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9723 {
9724 result_sstream << (counter++);
9725
9726 if (n_component != (n_variable_type_components - 1))
9727 {
9728 result_sstream << ", ";
9729 }
9730 }
9731
9732 result_sstream << ");\n";
9733 } /* for (all array indices) */
9734 } /* for (all variable types) */
9735
9736 result_sstream << "}\n";
9737
9738 /* We're done */
9739 return result_sstream.str();
9740 }
9741
9742 /** Retrieves body of a tessellation evaluation shader that uses user-specified set of variables
9743 * to declare contents of input & output block.
9744 *
9745 * @param variables As per description.
9746 *
9747 * @return Requested string.
9748 **/
getTessellationEvaluationShaderBody(const _variables & variables)9749 std::string GPUShaderFP64Test7::getTessellationEvaluationShaderBody(const _variables& variables)
9750 {
9751 std::stringstream result_sstream;
9752
9753 /* Form the pre-amble */
9754 result_sstream << "#version 400\n"
9755 "\n"
9756 "layout(quads) in;\n"
9757 "\n"
9758
9759 /* Define input block */
9760 "in TC_DATA\n"
9761 "{\n"
9762 << getVariableDeclarations("tc", variables) << "} in_data[];\n"
9763 "\n"
9764
9765 /* Define output block */
9766 "out TE_DATA\n"
9767 "{\n"
9768 << getVariableDeclarations("te", variables) << "};\n"
9769 "\n"
9770
9771 /* Define main() */
9772 "void main()\n"
9773 "{\n";
9774
9775 /* Take input variables, add a predefined value and forward them to output variables */
9776 const size_t n_variables = variables.size();
9777 unsigned int counter = 3;
9778
9779 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9780 {
9781 unsigned int variable_array_size = variables[n_variable].array_size;
9782 Utils::_variable_type variable_type = variables[n_variable].type;
9783 unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9784 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9785
9786 for (unsigned int index = 0; index < variable_array_size; ++index)
9787 {
9788 std::stringstream array_index_sstream;
9789
9790 if (variable_array_size > 1)
9791 {
9792 array_index_sstream << "[" << index << "]";
9793 }
9794
9795 result_sstream << "te_variable" << n_variable << array_index_sstream.str() << " = in_data[0].tc_variable"
9796 << n_variable << array_index_sstream.str() << " + " << variable_type_string << "(";
9797
9798 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9799 {
9800 result_sstream << (counter++);
9801
9802 if (n_component != (n_variable_type_components - 1))
9803 {
9804 result_sstream << ", ";
9805 }
9806 } /* for (all components) */
9807
9808 result_sstream << ");\n";
9809 } /* for (all array indices) */
9810 } /* for (all variable types) */
9811
9812 result_sstream << "}\n";
9813
9814 /* All done */
9815 return result_sstream.str();
9816 }
9817
9818 /** Returns a string containing declarations of user-specified set of variables.
9819 * Each declaration can optionally use a layot qualifier requested by the caller.
9820 *
9821 * @param prefix Prefix to use for variable names.
9822 * @param variables List of variables to declare in the result string.
9823 * @param explicit_locations true if each declaration should explicitly define location
9824 * of the variable ( eg. (layout location=X) )
9825 * @param layout_qualifier Optional qualifier to use for the declaration. Must not
9826 * be NULL.
9827 *
9828 * @return Requested string.
9829 **/
getVariableDeclarations(const char * prefix,const _variables & variables,const char * layout_qualifier)9830 std::string GPUShaderFP64Test7::getVariableDeclarations(const char* prefix, const _variables& variables,
9831 const char* layout_qualifier)
9832 {
9833 std::stringstream result_sstream;
9834
9835 /* Define output variables */
9836 const size_t n_variables = variables.size();
9837
9838 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9839 {
9840 unsigned int variable_array_size = variables[n_variable].array_size;
9841 Utils::_variable_type variable_type = variables[n_variable].type;
9842 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9843
9844 result_sstream << layout_qualifier << " " << variable_type_string << " " << prefix << "_variable" << n_variable;
9845
9846 if (variable_array_size > 1)
9847 {
9848 result_sstream << "[" << variable_array_size << "]";
9849 }
9850
9851 result_sstream << ";\n";
9852 } /* for (all user-specified variable types) */
9853
9854 return result_sstream.str();
9855 }
9856
9857 /** Retrieves body of a vertex shader that uses user-specified set of variables
9858 * to declare contents of input & output block.
9859 *
9860 * @param variables As per description.
9861 *
9862 * @return Requested string.
9863 **/
getVertexShaderBody(const _variables & variables)9864 std::string GPUShaderFP64Test7::getVertexShaderBody(const _variables& variables)
9865 {
9866 std::stringstream result_sstream;
9867
9868 /* Form pre-amble */
9869 result_sstream << "#version 400\n"
9870 "\n";
9871
9872 /* Define input variables if GL_ARB_vertex_attrib_64bit is supported */
9873 if (m_are_double_inputs_supported)
9874 {
9875 result_sstream << "#extension GL_ARB_vertex_attrib_64bit : require\n"
9876 << getVariableDeclarations("in_vs", variables, "in");
9877 }
9878
9879 /* Define output variables */
9880 result_sstream << "out VS_DATA\n"
9881 "{\n"
9882 << getVariableDeclarations("vs", variables);
9883
9884 /* Define main() */
9885 result_sstream << "};\n"
9886 "\n"
9887 "void main()\n"
9888 "{\n";
9889
9890 /* Set output variable values */
9891 unsigned int counter = 1;
9892 const size_t n_variables = variables.size();
9893
9894 for (unsigned int n_variable = 0; n_variable < n_variables; ++n_variable)
9895 {
9896 unsigned int variable_array_size = variables[n_variable].array_size;
9897 Utils::_variable_type variable_type = variables[n_variable].type;
9898 const unsigned int n_variable_type_components = Utils::getNumberOfComponentsForVariableType(variable_type);
9899 std::string variable_type_string = Utils::getVariableTypeString(variable_type);
9900
9901 for (unsigned int index = 0; index < variable_array_size; ++index)
9902 {
9903 if (variable_array_size == 1)
9904 {
9905 result_sstream << "vs_variable" << n_variable << " = " << variable_type_string << "(";
9906 }
9907 else
9908 {
9909 result_sstream << "vs_variable" << n_variable << "[" << index << "]"
9910 << " = " << variable_type_string << "(";
9911 }
9912
9913 for (unsigned int n_component = 0; n_component < n_variable_type_components; ++n_component)
9914 {
9915 result_sstream << (double)(counter++);
9916
9917 /* Use input attributes, if available */
9918 if (m_are_double_inputs_supported)
9919 {
9920 result_sstream << " + in_vs_variable" << n_variable;
9921
9922 if (variable_array_size > 1)
9923 {
9924 result_sstream << "[" << index << "]";
9925 }
9926
9927 if (Utils::isMatrixVariableType(variables[n_variable].type))
9928 {
9929 const unsigned int n_columns = Utils::getNumberOfColumnsForVariableType(variable_type);
9930 const unsigned int column = n_component % n_columns;
9931 const unsigned int row = n_component / n_columns;
9932
9933 result_sstream << "[" << (column) << "]"
9934 "."
9935 << Utils::getComponentAtIndex(row);
9936 }
9937 else if (n_variable_type_components > 1)
9938 {
9939 result_sstream << "[" << n_component << "]";
9940 }
9941 }
9942
9943 if (n_component != (n_variable_type_components - 1))
9944 {
9945 result_sstream << ", ";
9946 }
9947 } /* for (all components) */
9948
9949 result_sstream << ");\n";
9950 }
9951 } /* for (all variable types) */
9952
9953 /* We will be using geometry shader to lay out the actual vertices so
9954 * the only thing we need to make sure is that the vertex never gets
9955 * culled.
9956 */
9957 result_sstream << "gl_Position = vec4(0, 0, 0, 1);\n"
9958 "}\n";
9959
9960 /* That's it */
9961 return result_sstream.str();
9962 }
9963
9964 /** Initializes shader objects required to run the test. */
initTest()9965 void GPUShaderFP64Test7::initTest()
9966 {
9967 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
9968
9969 /* Are double-precision input variables supported? */
9970 m_are_double_inputs_supported = m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit");
9971
9972 /* Create a vertex array object */
9973 gl.genVertexArrays(1, &m_vao_id);
9974 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
9975
9976 gl.bindVertexArray(m_vao_id);
9977 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
9978
9979 /* Create a texture object we will use as FBO's color attachment */
9980 gl.genTextures(1, &m_to_id);
9981 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed");
9982
9983 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
9984 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
9985
9986 gl.texStorage2D(GL_TEXTURE_2D, 1 /* levels */, GL_RGBA8, m_to_width, m_to_height);
9987 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
9988
9989 /* Allocate temporary buffer to hold the texture data we will be reading
9990 * from color attachment. */
9991 m_to_data = new unsigned char[m_to_width * m_to_height * 4 /* RGBA */];
9992
9993 /* Create and set up a framebuffer object */
9994 gl.genFramebuffers(1, &m_fbo_id);
9995 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
9996
9997 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
9998 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindframebuffer() call failed.");
9999
10000 gl.framebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0 /* level */);
10001 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
10002
10003 /* Create all shader objects */
10004 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10005 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10006 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10007 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10008 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10009 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10010
10011 /* Create test program object */
10012 m_po_id = gl.createProgram();
10013 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
10014
10015 /* Attach the shaders to the program object */
10016 gl.attachShader(m_po_id, m_fs_id);
10017 gl.attachShader(m_po_id, m_gs_id);
10018 gl.attachShader(m_po_id, m_tc_id);
10019 gl.attachShader(m_po_id, m_te_id);
10020 gl.attachShader(m_po_id, m_vs_id);
10021 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
10022
10023 /* The test passes double-precision values through the whole rendering pipeline.
10024 * This translates to a notable amount of components that we would need to transfer
10025 * all values in one fell swoop. The number is large enough to exceed minimum
10026 * capabilities as described for OpenGL 4.0 implementations.
10027 * For that reason, the test executes in turns. Each turn is allocated as many
10028 * double-precision scalar/matrix values as supported by the tested GL implementation.
10029 */
10030 glw::GLint gl_max_fragment_input_components_value = 0;
10031 glw::GLint gl_max_geometry_input_components_value = 0;
10032 glw::GLint gl_max_geometry_output_components_value = 0;
10033 glw::GLint gl_max_tess_control_input_components_value = 0;
10034 glw::GLint gl_max_tess_control_output_components_value = 0;
10035 glw::GLint gl_max_tess_evaluation_input_components_value = 0;
10036 glw::GLint gl_max_tess_evaluation_output_components_value = 0;
10037 glw::GLint gl_max_transform_feedback_interleaved_components_value = 0;
10038 glw::GLint gl_max_vertex_output_components_value = 0;
10039
10040 gl.getIntegerv(GL_MAX_FRAGMENT_INPUT_COMPONENTS, &gl_max_fragment_input_components_value);
10041 gl.getIntegerv(GL_MAX_GEOMETRY_INPUT_COMPONENTS, &gl_max_geometry_input_components_value);
10042 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &gl_max_geometry_output_components_value);
10043 gl.getIntegerv(GL_MAX_TESS_CONTROL_INPUT_COMPONENTS, &gl_max_tess_control_input_components_value);
10044 gl.getIntegerv(GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS, &gl_max_tess_control_output_components_value);
10045 gl.getIntegerv(GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS, &gl_max_tess_evaluation_input_components_value);
10046 gl.getIntegerv(GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS, &gl_max_tess_evaluation_output_components_value);
10047 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS,
10048 &gl_max_transform_feedback_interleaved_components_value);
10049 gl.getIntegerv(GL_MAX_VERTEX_OUTPUT_COMPONENTS, &gl_max_vertex_output_components_value);
10050 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetintegerv() call(s) failed.");
10051
10052 m_n_max_components_per_stage =
10053 de::min(gl_max_vertex_output_components_value, gl_max_tess_control_input_components_value);
10054 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_fragment_input_components_value);
10055 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_input_components_value);
10056 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_geometry_output_components_value);
10057 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_control_output_components_value);
10058 m_n_max_components_per_stage = de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_input_components_value);
10059 m_n_max_components_per_stage =
10060 de::min(m_n_max_components_per_stage, gl_max_tess_evaluation_output_components_value);
10061 m_n_max_components_per_stage =
10062 de::min(m_n_max_components_per_stage, gl_max_transform_feedback_interleaved_components_value);
10063
10064 /* Update GL_PATCH_VERTICES setting so that we only use a single vertex to build
10065 * the input patch */
10066 gl.patchParameteri(GL_PATCH_VERTICES, 1);
10067
10068 GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteri() call failed.");
10069
10070 /* Initialize a BO we will use to hold XFB data */
10071 gl.genBuffers(1, &m_xfb_bo_id);
10072 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
10073
10074 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
10075 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
10076
10077 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
10078 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
10079 }
10080
10081 /** Executes test iteration.
10082 *
10083 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10084 */
iterate()10085 tcu::TestNode::IterateResult GPUShaderFP64Test7::iterate()
10086 {
10087 /* Do not execute the test if GL_ARB_texture_view is not supported */
10088 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10089 {
10090 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10091 }
10092
10093 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_vertex_attrib_64bit"))
10094 {
10095 throw tcu::NotSupportedError("GL_ARB_vertex_attrib_64bit is not supported.");
10096 }
10097
10098 /* Initialize GL objects required to run the test */
10099 initTest();
10100
10101 /* Check the negative cases first */
10102 const Utils::_variable_type double_variable_types[] = {
10103 Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10104 Utils::VARIABLE_TYPE_DVEC4, Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10105 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2,
10106 Utils::VARIABLE_TYPE_DMAT3X4, Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10107 Utils::VARIABLE_TYPE_DMAT4X3,
10108 };
10109 const unsigned int n_double_variable_types = sizeof(double_variable_types) / sizeof(double_variable_types[0]);
10110
10111 for (unsigned int n_double_variable_type = 0; n_double_variable_type < n_double_variable_types;
10112 ++n_double_variable_type)
10113 {
10114 for (unsigned int array_size = 1; array_size < 3; ++array_size)
10115 {
10116 Utils::_variable_type variable_type = double_variable_types[n_double_variable_type];
10117
10118 if (compileShader(m_fs_id, getCodeOfFragmentShaderWithDoublePrecisionOutput(variable_type, array_size)))
10119 {
10120 m_testCtx.getLog() << tcu::TestLog::Message
10121 << "A fragment shader with double-precision output variable compiled successfully."
10122 << tcu::TestLog::EndMessage;
10123
10124 m_has_test_passed = false;
10125 }
10126
10127 if (compileShader(m_fs_id,
10128 getCodeOfFragmentShaderWithNonFlatDoublePrecisionInput(variable_type, array_size)))
10129 {
10130 m_testCtx.getLog()
10131 << tcu::TestLog::Message
10132 << "A fragment shader with double-precision input variables lacking flat layout qualifier"
10133 " compiled successfully."
10134 << tcu::TestLog::EndMessage;
10135
10136 m_has_test_passed = false;
10137 }
10138 }
10139 } /* for (all variable types) */
10140
10141 /* Execute functional test. Split the run into as many iterations as necessary
10142 * so that we do not exceed GL implementation's capabilities. */
10143 unsigned int n_tested_variables = 0;
10144 _variables variables_to_test;
10145
10146 while (n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10147 {
10148 glw::GLint total_n_used_components = 0;
10149
10150 /* Use as many variables as possible for the iterations. Do not exceed maximum amount
10151 * of varying components that can be used for all shadr stages.
10152 */
10153 while (total_n_used_components < m_n_max_components_per_stage &&
10154 n_tested_variables != n_double_variable_types * 2 /* arrayed & non-arrayed */)
10155 {
10156 _variable new_variable;
10157 unsigned int n_type_components = 0;
10158 glw::GLint n_used_components = 0;
10159
10160 new_variable.array_size =
10161 ((n_tested_variables % 2) == 0) ? 1 /* non-arrayed variable */ : 2; /* arrayed variable */
10162 new_variable.type = double_variable_types[n_tested_variables / 2];
10163
10164 /* Double-precision varyings can use twice as many components as single-precision FPs */
10165 n_type_components = 4 /* components per location */ *
10166 Utils::getNumberOfLocationsUsedByDoublePrecisionVariableType(new_variable.type);
10167 n_used_components = n_type_components * new_variable.array_size * 2;
10168
10169 /* Do we have enough space? */
10170 if (total_n_used_components + n_used_components > m_n_max_components_per_stage)
10171 {
10172 if (n_used_components > m_n_max_components_per_stage)
10173 { //if the number of components for this variable is larger than the max_components_per_stage, then skip it.
10174 n_tested_variables++;
10175 }
10176 break;
10177 }
10178
10179 /* We can safely test the type in current iteration */
10180 total_n_used_components += n_used_components;
10181 n_tested_variables++;
10182
10183 variables_to_test.push_back(new_variable);
10184 }
10185
10186 if (variables_to_test.size() > 0)
10187 {
10188 m_has_test_passed &= executeFunctionalTest(variables_to_test);
10189
10190 variables_to_test.clear();
10191 }
10192 }
10193
10194 /* We're done */
10195 if (m_has_test_passed)
10196 {
10197 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10198 }
10199 else
10200 {
10201 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
10202 }
10203
10204 return STOP;
10205 }
10206
10207 /** Logs contents of test variables, as XFBed out by already executed test iteration. */
logVariableContents(const _variables & variables)10208 void GPUShaderFP64Test7::logVariableContents(const _variables& variables)
10209 {
10210 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10211 std::stringstream log_sstream;
10212
10213 log_sstream << "Test variable values as retrieved from geometry shader:\n";
10214
10215 /* Map the XFB BO contents into process space */
10216 const void* xfb_bo_data = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
10217
10218 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
10219
10220 /* Read the variable contents. We only care about the set of varyings emitted
10221 * for first vertex in the geometry shader */
10222 unsigned int n_varying = 0;
10223 const unsigned char* traveller_ptr = (const unsigned char*)xfb_bo_data;
10224
10225 for (_variables_const_iterator variables_iterator = variables.begin(); variables_iterator != variables.end();
10226 ++variables_iterator, ++n_varying)
10227 {
10228 const _variable& variable = *variables_iterator;
10229 const Utils::_variable_type& base_variable_type = Utils::getBaseVariableType(variable.type);
10230 const unsigned int n_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10231
10232 for (unsigned int array_index = 0; array_index < variable.array_size; ++array_index)
10233 {
10234 log_sstream << "gs_variable" << n_varying;
10235
10236 if (variable.array_size > 1)
10237 {
10238 log_sstream << "[" << array_index << "]";
10239 }
10240
10241 log_sstream << ": (";
10242
10243 for (unsigned int n_component = 0; n_component < n_components; ++n_component)
10244 {
10245 log_sstream << Utils::getStringForVariableTypeValue(base_variable_type, traveller_ptr);
10246
10247 if (n_component != (n_components - 1))
10248 {
10249 log_sstream << ", ";
10250 }
10251
10252 traveller_ptr += sizeof(double);
10253 }
10254
10255 log_sstream << ")\n";
10256 } /* for (all array indices) */
10257 } /* for (all variables) */
10258
10259 /* Unmap the BO */
10260 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
10261 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
10262
10263 /* Pass the logged stream into the framework */
10264 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
10265 }
10266
10267 /** De-allocates an arary holding strings representing names of varyings that
10268 * should be used for transform feed-back.
10269 **/
releaseXFBVaryingNames()10270 void GPUShaderFP64Test7::releaseXFBVaryingNames()
10271 {
10272 for (unsigned int n_varying = 0; n_varying < m_n_xfb_varyings; ++n_varying)
10273 {
10274 delete[] m_xfb_varyings[n_varying];
10275 }
10276
10277 delete[] m_xfb_varyings;
10278 m_xfb_varyings = DE_NULL;
10279
10280 m_n_xfb_varyings = 0;
10281 }
10282
10283 /** This function should only be called if GL_ARB_vertex_attrib_64bit extension is supported.
10284 * Takes a list of test variables used for current iteration and assigns increasing values
10285 * to subsequent input attributes of the test program.
10286 *
10287 * @param variables Test variables of the current iteration.
10288 */
setInputAttributeValues(const _variables & variables)10289 void GPUShaderFP64Test7::setInputAttributeValues(const _variables& variables)
10290 {
10291 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10292
10293 for (_variables_const_iterator variable_iterator = variables.begin(); variable_iterator != variables.end();
10294 variable_iterator++)
10295 {
10296 const _variable& variable = *variable_iterator;
10297 const bool is_matrix_type = Utils::isMatrixVariableType(variable.type);
10298 const unsigned int n_total_components = Utils::getNumberOfComponentsForVariableType(variable.type);
10299 unsigned int n_components = 0;
10300 unsigned int n_columns = 1;
10301
10302 if (is_matrix_type)
10303 {
10304 n_columns = Utils::getNumberOfColumnsForVariableType(variable.type);
10305 n_components = n_total_components / n_columns;
10306
10307 DE_ASSERT(n_total_components % n_columns == 0);
10308 }
10309 else
10310 {
10311 n_components = n_total_components;
10312 }
10313
10314 DE_ASSERT(n_components >= 1 && n_components <= 4);
10315
10316 for (unsigned int index = 0; index < n_columns * variable.array_size; ++index)
10317 {
10318 const double data[] = { -1, -1, -1, -1 };
10319
10320 switch (n_components)
10321 {
10322 case 1:
10323 {
10324 gl.vertexAttribL1dv(variable.attribute_location + index, data);
10325 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib1dv() call failed.");
10326
10327 break;
10328 }
10329
10330 case 2:
10331 {
10332 gl.vertexAttribL2dv(variable.attribute_location + index, data);
10333 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib2dv() call failed.");
10334
10335 break;
10336 }
10337
10338 case 3:
10339 {
10340 gl.vertexAttribL3dv(variable.attribute_location + index, data);
10341 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib3dv() call failed.");
10342
10343 break;
10344 }
10345
10346 case 4:
10347 {
10348 gl.vertexAttribL4dv(variable.attribute_location + index, data);
10349 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttrib4dv() call failed.");
10350
10351 break;
10352 }
10353
10354 default:
10355 {
10356 TCU_FAIL("Unrecognized number of components");
10357 }
10358 } /* switch (n_components) */
10359
10360 /* Make sure VAAs are disabled */
10361 gl.disableVertexAttribArray(variable.attribute_location + index);
10362 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray() call failed.");
10363 } /* for (all array indices) */
10364 } /* for (all variables) */
10365 }
10366
10367 /** Constructor
10368 *
10369 * @param context Rendering context.
10370 */
GPUShaderFP64Test8(deqp::Context & context)10371 GPUShaderFP64Test8::GPUShaderFP64Test8(deqp::Context& context)
10372 : TestCase(context, "valid_constructors", "Verifies that valid double-precision floating-point constructors "
10373 "are accepted during compilation stage")
10374 , m_cs_id(0)
10375 , m_fs_id(0)
10376 , m_gs_id(0)
10377 , m_tc_id(0)
10378 , m_te_id(0)
10379 , m_vs_id(0)
10380 , m_has_test_passed(true)
10381 {
10382 }
10383
10384 /** Deinitializes all buffers and GL objects that may have been generated
10385 * during test execution.
10386 **/
deinit()10387 void GPUShaderFP64Test8::deinit()
10388 {
10389 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10390
10391 if (m_cs_id != 0)
10392 {
10393 gl.deleteShader(m_cs_id);
10394
10395 m_cs_id = 0;
10396 }
10397
10398 if (m_fs_id != 0)
10399 {
10400 gl.deleteShader(m_fs_id);
10401
10402 m_fs_id = 0;
10403 }
10404
10405 if (m_gs_id != 0)
10406 {
10407 gl.deleteShader(m_gs_id);
10408
10409 m_gs_id = 0;
10410 }
10411
10412 if (m_tc_id != 0)
10413 {
10414 gl.deleteShader(m_tc_id);
10415
10416 m_tc_id = 0;
10417 }
10418
10419 if (m_te_id != 0)
10420 {
10421 gl.deleteShader(m_te_id);
10422
10423 m_te_id = 0;
10424 }
10425
10426 if (m_vs_id != 0)
10427 {
10428 gl.deleteShader(m_vs_id);
10429
10430 m_vs_id = 0;
10431 }
10432 }
10433
10434 /** Executes a single test case.
10435 *
10436 * This function can throw TestError exceptions if GL implementation reports
10437 * an error.
10438 *
10439 * @param test_case Test case descriptor.
10440 *
10441 * @return true if test case passed, false otherwise.
10442 **/
executeIteration(const _test_case & test_case)10443 bool GPUShaderFP64Test8::executeIteration(const _test_case& test_case)
10444 {
10445 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10446 const glw::GLuint so_ids[] = { m_cs_id, m_fs_id, m_gs_id, m_tc_id, m_te_id, m_vs_id };
10447 const unsigned int n_so_ids = sizeof(so_ids) / sizeof(so_ids[0]);
10448 bool result = true;
10449 const char* stage_body = NULL;
10450 const char* stage_name = NULL;
10451
10452 for (unsigned int n_so_id = 0; n_so_id < n_so_ids; ++n_so_id)
10453 {
10454 const glw::GLuint so_id = so_ids[n_so_id];
10455
10456 /* Skip compute shader if it is not supported */
10457 if (0 == so_id)
10458 {
10459 continue;
10460 }
10461
10462 /* Compile the shader */
10463 gl.compileShader(so_id);
10464 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
10465
10466 /* Has the compilation succeeded as expected? */
10467 glw::GLint compile_status = GL_FALSE;
10468
10469 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
10470 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
10471
10472 if (compile_status == GL_FALSE)
10473 {
10474 /* What is the current stage's name? */
10475 if (so_id == m_cs_id)
10476 {
10477 stage_body = test_case.cs_shader_body.c_str();
10478 stage_name = "Compute shader";
10479 }
10480 else if (so_id == m_fs_id)
10481 {
10482 stage_body = test_case.fs_shader_body.c_str();
10483 stage_name = "Fragment shader";
10484 }
10485 else if (so_id == m_gs_id)
10486 {
10487 stage_body = test_case.gs_shader_body.c_str();
10488 stage_name = "Geometry shader";
10489 }
10490 else if (so_id == m_tc_id)
10491 {
10492 stage_body = test_case.tc_shader_body.c_str();
10493 stage_name = "Tessellation control shader";
10494 }
10495 else if (so_id == m_te_id)
10496 {
10497 stage_body = test_case.te_shader_body.c_str();
10498 stage_name = "Tessellation evaluation shader";
10499 }
10500 else if (so_id == m_vs_id)
10501 {
10502 stage_body = test_case.vs_shader_body.c_str();
10503 stage_name = "Vertex shader";
10504 }
10505 else
10506 {
10507 /* Doesn't make much sense to throw exceptions here so.. */
10508 stage_body = "";
10509 stage_name = "[?]";
10510 }
10511
10512 /* This shader should have never failed to compile! */
10513 m_testCtx.getLog() << tcu::TestLog::Message << stage_name
10514 << " has not compiled successfully, even though the shader is valid."
10515 " Following is shader's body:\n"
10516 << stage_body << tcu::TestLog::EndMessage;
10517
10518 result = false;
10519 }
10520 } /* for (all shader objects) */
10521
10522 return result;
10523 }
10524
10525 /** Retrieves all argument lists that can be used to initialize a variable of user-specified
10526 * type.
10527 *
10528 * @param variable_type Variable type to return valid argument lists for.
10529 **/
getArgumentListsForVariableType(const Utils::_variable_type & variable_type)10530 GPUShaderFP64Test8::_argument_lists GPUShaderFP64Test8::getArgumentListsForVariableType(
10531 const Utils::_variable_type& variable_type)
10532 {
10533 const Utils::_variable_type matrix_types[] = {
10534 Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3, Utils::VARIABLE_TYPE_DMAT2X4,
10535 Utils::VARIABLE_TYPE_DMAT3, Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10536 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2, Utils::VARIABLE_TYPE_DMAT4X3,
10537 };
10538 const Utils::_variable_type scalar_types[] = { Utils::VARIABLE_TYPE_DOUBLE, Utils::VARIABLE_TYPE_DVEC2,
10539 Utils::VARIABLE_TYPE_DVEC3, Utils::VARIABLE_TYPE_DVEC4 };
10540 const unsigned int n_matrix_types = sizeof(matrix_types) / sizeof(matrix_types[0]);
10541 const unsigned int n_scalar_types = sizeof(scalar_types) / sizeof(scalar_types[0]);
10542 const int n_total_components = (int)Utils::getNumberOfComponentsForVariableType(variable_type);
10543
10544 /* Construct the argument list tree root. Each node carries a counter that tells how many components
10545 * have already been assigned. Nodes that eat up all components are considered leaves and do not have
10546 * any children. Otherwise, each node is assigned as many children, as there are types that could be
10547 * used to define a subsequent argument, and its counter is increased by the amount of components
10548 * described by the type.
10549 */
10550 _argument_list_tree_node root;
10551
10552 root.n_components_used = 0;
10553 root.parent = NULL;
10554 root.type = variable_type;
10555
10556 /* Fill till all leaves use up all available components */
10557 _argument_list_tree_node_queue nodes_queue;
10558
10559 nodes_queue.push(&root);
10560
10561 do
10562 {
10563 /* Pop the first item in the queue */
10564 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10565 nodes_queue.pop();
10566
10567 /* Matrix variable types can be defined by a combination of non-matrix variable types OR
10568 * a single matrix variable type.
10569 *
10570 * Let's handle the latter case first.
10571 */
10572 const int n_components_remaining = n_total_components - current_node_ptr->n_components_used;
10573
10574 if (Utils::isMatrixVariableType(current_node_ptr->type))
10575 {
10576 /* Iterate through all known matrix types. All the types can be used
10577 * as a constructor, assuming only one value is used to define new matrix's
10578 * contents. */
10579 for (unsigned int n_matrix_type = 0; n_matrix_type < n_matrix_types; ++n_matrix_type)
10580 {
10581 Utils::_variable_type new_argument_type = matrix_types[n_matrix_type];
10582
10583 /* Construct a new child node. Since GLSL spec clearly states we must not use more
10584 * than one constructor argument if the only argument is a matrix type, mark the node
10585 * as if it defined all available components.
10586 */
10587 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10588
10589 new_subnode->n_components_used = n_total_components;
10590 new_subnode->parent = current_node_ptr;
10591 new_subnode->type = new_argument_type;
10592
10593 /* Add the descriptor to node list but do not add it to the queue. This would be
10594 * a redundant operation, since no new children nodes would have been assigned to
10595 * this node anyway.
10596 */
10597 current_node_ptr->children.push_back(new_subnode);
10598 } /* for (all matrix types) */
10599 } /* if (current node's type is a matrix) */
10600
10601 /* Now for a combination of non-matrix variable types.. */
10602 if (!Utils::isMatrixVariableType(current_node_ptr->type))
10603 {
10604 /* Iterate through all known scalar types */
10605 for (unsigned int n_scalar_type = 0; n_scalar_type < n_scalar_types; ++n_scalar_type)
10606 {
10607 Utils::_variable_type new_argument_type = scalar_types[n_scalar_type];
10608 const int n_new_argument_components = Utils::getNumberOfComponentsForVariableType(new_argument_type);
10609
10610 /* Only use the scalar type if we don't exceed the amount of components we can define
10611 * for requested type.
10612 */
10613 if (n_new_argument_components <= n_components_remaining)
10614 {
10615 /* Form new node descriptor */
10616 _argument_list_tree_node* new_subnode = new _argument_list_tree_node;
10617
10618 new_subnode->n_components_used = n_new_argument_components + current_node_ptr->n_components_used;
10619 new_subnode->parent = current_node_ptr;
10620 new_subnode->type = new_argument_type;
10621
10622 current_node_ptr->children.push_back(new_subnode);
10623 nodes_queue.push(new_subnode);
10624 }
10625 } /* for (all scalar types) */
10626 } /* if (!Utils::isMatrixVariableType(current_node_ptr->type) ) */
10627 } while (nodes_queue.size() > 0);
10628
10629 /* To construct the argument lists, traverse the tree. Each path from root to child
10630 * gives us a single argument list.
10631 *
10632 * First, identify leaf nodes.
10633 */
10634 _argument_list_tree_nodes leaf_nodes;
10635
10636 nodes_queue.push(&root);
10637
10638 do
10639 {
10640 _argument_list_tree_node* current_node_ptr = nodes_queue.front();
10641 nodes_queue.pop();
10642
10643 if (current_node_ptr->children.size() == 0)
10644 {
10645 /* This is a leaf node !*/
10646 leaf_nodes.push_back(current_node_ptr);
10647 }
10648 else
10649 {
10650 /* Throw all children nodes to the queue */
10651 const unsigned int n_children_nodes = (unsigned int)current_node_ptr->children.size();
10652
10653 for (unsigned int n_children_node = 0; n_children_node < n_children_nodes; ++n_children_node)
10654 {
10655 nodes_queue.push(current_node_ptr->children[n_children_node]);
10656 } /* for (all children nodes) */
10657 }
10658 } while (nodes_queue.size() > 0);
10659
10660 /* For all leaf nodes, move up the tree and construct the argument lists. */
10661 const unsigned int n_leaf_nodes = (unsigned int)leaf_nodes.size();
10662 _argument_lists result;
10663
10664 for (unsigned int n_leaf_node = 0; n_leaf_node < n_leaf_nodes; ++n_leaf_node)
10665 {
10666 _argument_list argument_list;
10667 _argument_list_tree_node* current_node_ptr = leaf_nodes[n_leaf_node];
10668
10669 do
10670 {
10671 if (current_node_ptr != &root)
10672 {
10673 if (argument_list.size() == 0)
10674 {
10675 argument_list.push_back(current_node_ptr->type);
10676 }
10677 else
10678 {
10679 argument_list.insert(argument_list.begin(), current_node_ptr->type);
10680 }
10681 }
10682
10683 current_node_ptr = current_node_ptr->parent;
10684 } while (current_node_ptr != NULL);
10685
10686 result.push_back(argument_list);
10687 } /* for (all leaf nodes) */
10688
10689 return result;
10690 }
10691
10692 /** Retrieves body of a compute shader that should be used for the purpose of
10693 * user-specified test case.
10694 *
10695 * @param test_case Test case descriptor to use.
10696 *
10697 * @return Requested string.
10698 **/
getComputeShaderBody(const _test_case & test_case)10699 std::string GPUShaderFP64Test8::getComputeShaderBody(const _test_case& test_case)
10700 {
10701 std::stringstream result_sstream;
10702
10703 /* Form the body */
10704 result_sstream << "#version 420\n"
10705 "#extension GL_ARB_compute_shader : require\n"
10706 "\n"
10707 "layout(local_size_x = 1) in;\n"
10708 "\n"
10709 "void main()\n"
10710 "{\n"
10711 << getGeneralBody(test_case) << "}\n";
10712
10713 /* Return the body */
10714 return result_sstream.str();
10715 }
10716
10717 /** Retrieves body of a fragment shader that should be used for the purpose of
10718 * user-specified test case.
10719 *
10720 * @param test_case Test case descriptor to use.
10721 *
10722 * @return Requested string.
10723 **/
getFragmentShaderBody(const _test_case & test_case)10724 std::string GPUShaderFP64Test8::getFragmentShaderBody(const _test_case& test_case)
10725 {
10726 std::stringstream result_sstream;
10727
10728 /* Form the body */
10729 result_sstream << "#version 420\n"
10730 "\n"
10731 "void main()\n"
10732 "{\n"
10733 << getGeneralBody(test_case) << "}\n"
10734 "\n";
10735
10736 /* Return the body */
10737 return result_sstream.str();
10738 }
10739
10740 /** Returns a GLSL line that defines and initializes a variable as described by
10741 * user-specified test case descriptor.
10742 *
10743 * @param test_case Test case descriptor to use for the query.
10744 *
10745 * @return As per description
10746 **/
getGeneralBody(const _test_case & test_case)10747 std::string GPUShaderFP64Test8::getGeneralBody(const _test_case& test_case)
10748 {
10749 std::stringstream result_sstream;
10750
10751 /* Form the body */
10752 std::string variable_type_string = Utils::getVariableTypeString(test_case.type);
10753
10754 result_sstream << variable_type_string << " src = " << variable_type_string << "(";
10755
10756 for (_argument_list_const_iterator argument_list_iterator = test_case.argument_list.begin();
10757 argument_list_iterator != test_case.argument_list.end(); argument_list_iterator++)
10758 {
10759 const Utils::_variable_type argument_variable_type = *argument_list_iterator;
10760 std::string argument_variable_type_string = Utils::getVariableTypeString(argument_variable_type);
10761 const unsigned int argument_n_components = Utils::getNumberOfComponentsForVariableType(argument_variable_type);
10762
10763 if (argument_list_iterator != test_case.argument_list.begin())
10764 {
10765 result_sstream << ", ";
10766 }
10767
10768 result_sstream << argument_variable_type_string << "(";
10769
10770 for (unsigned int n_component = 0; n_component < argument_n_components; ++n_component)
10771 {
10772 result_sstream << (double)(n_component + 1);
10773
10774 if (n_component != (argument_n_components - 1))
10775 {
10776 result_sstream << ", ";
10777 }
10778 } /* for (all argument components) */
10779
10780 result_sstream << ")";
10781 } /* for (all arguments) */
10782
10783 result_sstream << ");\n";
10784
10785 return result_sstream.str();
10786 }
10787
10788 /** Retrieves body of a geometry shader that should be used for the purpose of
10789 * user-specified test case.
10790 *
10791 * @param test_case Test case descriptor to use.
10792 *
10793 * @return Requested string.
10794 **/
getGeometryShaderBody(const _test_case & test_case)10795 std::string GPUShaderFP64Test8::getGeometryShaderBody(const _test_case& test_case)
10796 {
10797 std::stringstream result_sstream;
10798
10799 /* Form the body */
10800 result_sstream << "#version 420\n"
10801 "\n"
10802 "layout(points) in;\n"
10803 "layout(max_vertices=1, points) out;\n"
10804 "\n"
10805 "void main()\n"
10806 "{\n"
10807 << getGeneralBody(test_case) << "}\n"
10808 "\n";
10809
10810 /* We're done! */
10811 return result_sstream.str();
10812 }
10813
10814 /** Retrieves body of a tesellation control shader that should be used for the purpose of
10815 * user-specified test case.
10816 *
10817 * @param test_case Test case descriptor to use.
10818 *
10819 * @return Requested string.
10820 **/
getTessellationControlShaderBody(const _test_case & test_case)10821 std::string GPUShaderFP64Test8::getTessellationControlShaderBody(const _test_case& test_case)
10822 {
10823 std::stringstream result_sstream;
10824
10825 /* Form the body */
10826 result_sstream << "#version 420\n"
10827 "\n"
10828 "layout(vertices=4) out;\n"
10829 "\n"
10830 "void main()\n"
10831 "{\n"
10832 << getGeneralBody(test_case) << "}\n"
10833 "\n";
10834
10835 /* Return the body */
10836 return result_sstream.str();
10837 }
10838
10839 /** Retrieves body of a tessellation evaluation shader that should be used for the purpose of
10840 * user-specified test case.
10841 *
10842 * @param test_case Test case descriptor to use.
10843 *
10844 * @return Requested string.
10845 **/
getTessellationEvaluationShaderBody(const _test_case & test_case)10846 std::string GPUShaderFP64Test8::getTessellationEvaluationShaderBody(const _test_case& test_case)
10847 {
10848 std::stringstream result_sstream;
10849
10850 /* Form the body */
10851 result_sstream << "#version 420\n"
10852 "\n"
10853 "layout(isolines) in;\n"
10854 "\n"
10855 "void main()\n"
10856 "{\n"
10857 << getGeneralBody(test_case) << "}\n"
10858 "\n";
10859
10860 /* Return the body */
10861 return result_sstream.str();
10862 }
10863
10864 /** Retrieves body of a vertex shader that should be used for the purpose of
10865 * user-specified test case.
10866 *
10867 * @param test_case Test case descriptor to use.
10868 *
10869 * @return Requested string.
10870 **/
getVertexShaderBody(const _test_case & test_case)10871 std::string GPUShaderFP64Test8::getVertexShaderBody(const _test_case& test_case)
10872 {
10873 std::stringstream result_sstream;
10874
10875 /* Form the body */
10876 result_sstream << "#version 420\n"
10877 "\n"
10878 "void main()\n"
10879 "{\n"
10880 << getGeneralBody(test_case) << "}\n"
10881 "\n";
10882
10883 return result_sstream.str();
10884 }
10885
10886 /** Initializes shader objects required to run the test. */
initTest()10887 void GPUShaderFP64Test8::initTest()
10888 {
10889 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10890
10891 /* Generate shader objects */
10892
10893 /* Compute shader support and GL 4.2 required */
10894 if ((true == m_context.getContextInfo().isExtensionSupported("GL_ARB_compute_shader")) &&
10895 (true == Utils::isGLVersionAtLeast(gl, 4 /* major */, 2 /* minor */)))
10896 {
10897 m_cs_id = gl.createShader(GL_COMPUTE_SHADER);
10898 }
10899
10900 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
10901 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
10902 m_tc_id = gl.createShader(GL_TESS_CONTROL_SHADER);
10903 m_te_id = gl.createShader(GL_TESS_EVALUATION_SHADER);
10904 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
10905
10906 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
10907 }
10908
10909 /** Assigns shader bodies to all shader objects that will be used for a single iteration.
10910 *
10911 * @param test_case Test case descriptor to generate the shader bodies for.
10912 **/
initIteration(_test_case & test_case)10913 void GPUShaderFP64Test8::initIteration(_test_case& test_case)
10914 {
10915 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
10916
10917 test_case.cs_shader_body = getComputeShaderBody(test_case);
10918 test_case.fs_shader_body = getFragmentShaderBody(test_case);
10919 test_case.gs_shader_body = getGeometryShaderBody(test_case);
10920 test_case.tc_shader_body = getTessellationControlShaderBody(test_case);
10921 test_case.te_shader_body = getTessellationEvaluationShaderBody(test_case);
10922 test_case.vs_shader_body = getVertexShaderBody(test_case);
10923
10924 /* Assign the bodies to relevant shaders */
10925 const char* cs_body_raw_ptr = test_case.cs_shader_body.c_str();
10926 const char* fs_body_raw_ptr = test_case.fs_shader_body.c_str();
10927 const char* gs_body_raw_ptr = test_case.gs_shader_body.c_str();
10928 const char* tc_body_raw_ptr = test_case.tc_shader_body.c_str();
10929 const char* te_body_raw_ptr = test_case.te_shader_body.c_str();
10930 const char* vs_body_raw_ptr = test_case.vs_shader_body.c_str();
10931
10932 /* m_cs_id is initialized only if compute_shader is supported */
10933 if (0 != m_cs_id)
10934 {
10935 gl.shaderSource(m_cs_id, 1 /* count */, &cs_body_raw_ptr, DE_NULL /* length */);
10936 }
10937
10938 gl.shaderSource(m_fs_id, 1 /* count */, &fs_body_raw_ptr, DE_NULL /* length */);
10939 gl.shaderSource(m_gs_id, 1 /* count */, &gs_body_raw_ptr, DE_NULL /* length */);
10940 gl.shaderSource(m_tc_id, 1 /* count */, &tc_body_raw_ptr, DE_NULL /* length */);
10941 gl.shaderSource(m_te_id, 1 /* count */, &te_body_raw_ptr, DE_NULL /* length */);
10942 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
10943 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call(s) failed.");
10944 }
10945
10946 /** Executes test iteration.
10947 *
10948 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
10949 */
iterate()10950 tcu::TestNode::IterateResult GPUShaderFP64Test8::iterate()
10951 {
10952 /* Do not execute the test if GL_ARB_texture_view is not supported */
10953 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
10954 {
10955 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
10956 }
10957
10958 /* Initialize GL objects needed to run the tests */
10959 initTest();
10960
10961 /* Build iteration array to run the tests in an automated manner */
10962 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
10963 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
10964 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
10965 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
10966 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
10967 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
10968 Utils::VARIABLE_TYPE_DVEC4 };
10969 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
10970
10971 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
10972 {
10973 const Utils::_variable_type variable_type = variable_types[n_variable_type];
10974
10975 /* Construct a set of argument lists valid for the variable type considered */
10976 _argument_lists argument_lists = getArgumentListsForVariableType(variable_type);
10977
10978 for (_argument_lists_const_iterator argument_list_iterator = argument_lists.begin();
10979 argument_list_iterator != argument_lists.end(); argument_list_iterator++)
10980 {
10981 /* Constructor thwe test case descriptor */
10982 _test_case test_case;
10983
10984 test_case.argument_list = *argument_list_iterator;
10985 test_case.type = variable_type;
10986
10987 /* Initialize a program object we will use to perform the casting */
10988 initIteration(test_case);
10989
10990 /* See if the shader compiles. */
10991 m_has_test_passed &= executeIteration(test_case);
10992 } /* for (all argument lists) */
10993 } /* for (all variable types) */
10994
10995 /* We're done */
10996 if (m_has_test_passed)
10997 {
10998 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
10999 }
11000 else
11001 {
11002 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11003 }
11004
11005 return STOP;
11006 }
11007
11008 /** Constructor.
11009 *
11010 * @param context Rendering context.
11011 *
11012 **/
GPUShaderFP64Test9(deqp::Context & context)11013 GPUShaderFP64Test9::GPUShaderFP64Test9(deqp::Context& context)
11014 : TestCase(context, "operators", "Verifies that general and relational operators work "
11015 "correctly when used against double-precision floating-"
11016 "point types.")
11017 , m_has_test_passed(true)
11018 , m_po_id(0)
11019 , m_xfb_bo_id(0)
11020 , m_vao_id(0)
11021 , m_vs_id(0)
11022 {
11023 /* Left blank intentionally */
11024 }
11025
11026 /** Deinitializes all ES objects that may have been created during
11027 * test execution.
11028 **/
deinit()11029 void GPUShaderFP64Test9::deinit()
11030 {
11031 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11032
11033 if (m_po_id != 0)
11034 {
11035 gl.deleteProgram(m_po_id);
11036
11037 m_po_id = 0;
11038 }
11039
11040 if (m_xfb_bo_id != 0)
11041 {
11042 gl.deleteBuffers(1, &m_xfb_bo_id);
11043
11044 m_xfb_bo_id = 0;
11045 }
11046
11047 if (m_vao_id != 0)
11048 {
11049 gl.deleteVertexArrays(1, &m_vao_id);
11050
11051 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays() call failed.");
11052 }
11053
11054 if (m_vs_id != 0)
11055 {
11056 gl.deleteShader(m_vs_id);
11057
11058 m_vs_id = 0;
11059 }
11060 }
11061
11062 /** Executes a single test iteration using user-specified test case properties.
11063 *
11064 * @param test_case Test case descriptor.
11065 *
11066 * @return true if the pass was successful, false if the test should fail.
11067 **/
executeTestIteration(const _test_case & test_case)11068 bool GPUShaderFP64Test9::executeTestIteration(const _test_case& test_case)
11069 {
11070 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11071 bool result = true;
11072
11073 /* Activate the test program object */
11074 gl.useProgram(m_po_id);
11075 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
11076
11077 /* Draw a single point with XFB enabled */
11078 gl.beginTransformFeedback(GL_POINTS);
11079 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
11080 {
11081 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
11082 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
11083 }
11084 gl.endTransformFeedback();
11085 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
11086
11087 /* Map the XFB BO into process space */
11088 const void* xfb_data_ptr = gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
11089
11090 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer() call failed.");
11091
11092 result = verifyXFBData(test_case, (const unsigned char*)xfb_data_ptr);
11093
11094 /* Unmap the BO */
11095 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
11096 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
11097
11098 return result;
11099 }
11100
11101 /** Performs a matrix multiplication, given types of l-side and r-side matrices and stores the result
11102 * under user-specified location.
11103 *
11104 * @param matrix_a_type Type of the l-side matrix.
11105 * @param matrix_a_data Row-ordered data of l-side matrix.
11106 * @param matrix_b_type Type of the r-side matrix.
11107 * @param matrix_b_data Row-ordered data of r-side matrix.
11108 * @param out_result_ptr Deref to be used to store the multiplication result.
11109 **/
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)11110 void GPUShaderFP64Test9::getMatrixMultiplicationResult(const Utils::_variable_type& matrix_a_type,
11111 const std::vector<double>& matrix_a_data,
11112 const Utils::_variable_type& matrix_b_type,
11113 const std::vector<double>& matrix_b_data, double* out_result_ptr)
11114 {
11115 (void)matrix_b_type;
11116 using namespace tcu;
11117 /* To keep the code maintainable, we only consider cases relevant for this test */
11118 switch (matrix_a_type)
11119 {
11120 case Utils::VARIABLE_TYPE_DMAT2:
11121 {
11122 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2);
11123
11124 tcu::Matrix2d matrix_a(&matrix_a_data[0]);
11125 tcu::Matrix2d matrix_b(&matrix_b_data[0]);
11126 tcu::Matrix2d result;
11127
11128 matrix_a = transpose(matrix_a);
11129 matrix_b = transpose(matrix_b);
11130 result = matrix_a * matrix_b;
11131
11132 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11133 break;
11134 }
11135
11136 case Utils::VARIABLE_TYPE_DMAT2X3:
11137 {
11138 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X2);
11139
11140 tcu::Matrix<double, 2, 3> matrix_a(&matrix_a_data[0]);
11141 tcu::Matrix<double, 3, 2> matrix_a_transposed;
11142 tcu::Matrix<double, 3, 2> matrix_b(&matrix_b_data[0]);
11143 tcu::Matrix<double, 2, 3> matrix_b_transposed;
11144 tcu::Matrix<double, 3, 3> result;
11145
11146 matrix_a_transposed = transpose(matrix_a);
11147 matrix_b_transposed = transpose(matrix_b);
11148 result = matrix_a_transposed * matrix_b_transposed;
11149
11150 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11151 break;
11152 }
11153
11154 case Utils::VARIABLE_TYPE_DMAT2X4:
11155 {
11156 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X2);
11157
11158 tcu::Matrix<double, 2, 4> matrix_a(&matrix_a_data[0]);
11159 tcu::Matrix<double, 4, 2> matrix_a_transposed;
11160 tcu::Matrix<double, 4, 2> matrix_b(&matrix_b_data[0]);
11161 tcu::Matrix<double, 2, 4> matrix_b_transposed;
11162 tcu::Matrix<double, 4, 4> result;
11163
11164 matrix_a_transposed = transpose(matrix_a);
11165 matrix_b_transposed = transpose(matrix_b);
11166 result = matrix_a_transposed * matrix_b_transposed;
11167
11168 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11169 break;
11170 }
11171
11172 case Utils::VARIABLE_TYPE_DMAT3:
11173 {
11174 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3);
11175
11176 tcu::Matrix<double, 3, 3> matrix_a(&matrix_a_data[0]);
11177 tcu::Matrix<double, 3, 3> matrix_b(&matrix_b_data[0]);
11178 tcu::Matrix<double, 3, 3> result;
11179
11180 matrix_a = transpose(matrix_a);
11181 matrix_b = transpose(matrix_b);
11182 result = matrix_a * matrix_b;
11183
11184 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11185 break;
11186 }
11187
11188 case Utils::VARIABLE_TYPE_DMAT3X2:
11189 {
11190 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X3);
11191
11192 tcu::Matrix<double, 3, 2> matrix_a(&matrix_a_data[0]);
11193 tcu::Matrix<double, 2, 3> matrix_a_transposed;
11194 tcu::Matrix<double, 2, 3> matrix_b(&matrix_b_data[0]);
11195 tcu::Matrix<double, 3, 2> matrix_b_transposed;
11196 tcu::Matrix<double, 2, 2> result;
11197
11198 matrix_a_transposed = transpose(matrix_a);
11199 matrix_b_transposed = transpose(matrix_b);
11200 result = matrix_a_transposed * matrix_b_transposed;
11201
11202 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11203 break;
11204 }
11205
11206 case Utils::VARIABLE_TYPE_DMAT3X4:
11207 {
11208 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4X3);
11209
11210 tcu::Matrix<double, 3, 4> matrix_a(&matrix_a_data[0]);
11211 tcu::Matrix<double, 4, 3> matrix_a_transposed;
11212 tcu::Matrix<double, 4, 3> matrix_b(&matrix_b_data[0]);
11213 tcu::Matrix<double, 3, 4> matrix_b_transposed;
11214 tcu::Matrix<double, 4, 4> result;
11215
11216 matrix_a_transposed = transpose(matrix_a);
11217 matrix_b_transposed = transpose(matrix_b);
11218 result = matrix_a_transposed * matrix_b_transposed;
11219
11220 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11221 break;
11222 }
11223
11224 case Utils::VARIABLE_TYPE_DMAT4:
11225 {
11226 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT4);
11227
11228 tcu::Matrix<double, 4, 4> matrix_a(&matrix_a_data[0]);
11229 tcu::Matrix<double, 4, 4> matrix_b(&matrix_b_data[0]);
11230 tcu::Matrix<double, 4, 4> result;
11231
11232 matrix_a = transpose(matrix_a);
11233 matrix_b = transpose(matrix_b);
11234 result = matrix_a * matrix_b;
11235
11236 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 4 * 4);
11237 break;
11238 }
11239
11240 case Utils::VARIABLE_TYPE_DMAT4X2:
11241 {
11242 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT2X4);
11243
11244 tcu::Matrix<double, 4, 2> matrix_a(&matrix_a_data[0]);
11245 tcu::Matrix<double, 2, 4> matrix_a_transposed;
11246 tcu::Matrix<double, 2, 4> matrix_b(&matrix_b_data[0]);
11247 tcu::Matrix<double, 4, 2> matrix_b_transposed;
11248 tcu::Matrix<double, 2, 2> result;
11249
11250 matrix_a_transposed = transpose(matrix_a);
11251 matrix_b_transposed = transpose(matrix_b);
11252 result = matrix_a_transposed * matrix_b_transposed;
11253
11254 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 2 * 2);
11255 break;
11256 }
11257
11258 case Utils::VARIABLE_TYPE_DMAT4X3:
11259 {
11260 DE_ASSERT(matrix_b_type == Utils::VARIABLE_TYPE_DMAT3X4);
11261
11262 tcu::Matrix<double, 4, 3> matrix_a(&matrix_a_data[0]);
11263 tcu::Matrix<double, 3, 4> matrix_a_transposed;
11264 tcu::Matrix<double, 3, 4> matrix_b(&matrix_b_data[0]);
11265 tcu::Matrix<double, 4, 3> matrix_b_transposed;
11266 tcu::Matrix<double, 3, 3> result;
11267
11268 matrix_a_transposed = transpose(matrix_a);
11269 matrix_b_transposed = transpose(matrix_b);
11270 result = matrix_a_transposed * matrix_b_transposed;
11271
11272 memcpy(out_result_ptr, result.getColumnMajorData().getPtr(), sizeof(double) * 3 * 3);
11273 break;
11274 }
11275
11276 default:
11277 {
11278 TCU_FAIL("Unrecognized matrix A type");
11279 }
11280 } /* switch (matrix_a_type) */
11281 }
11282
11283 /** Returns GLSL operator representation of the user-specified operation.
11284 *
11285 * @param operation_type Internal operation type to retrieve the operator for.
11286 *
11287 * @return As per description.
11288 **/
getOperatorForOperationType(const _operation_type & operation_type)11289 const char* GPUShaderFP64Test9::getOperatorForOperationType(const _operation_type& operation_type)
11290 {
11291 const char* result = NULL;
11292
11293 switch (operation_type)
11294 {
11295 case OPERATION_TYPE_ADDITION:
11296 result = "+";
11297 break;
11298 case OPERATION_TYPE_DIVISION:
11299 result = "/";
11300 break;
11301 case OPERATION_TYPE_MULTIPLICATION:
11302 result = "*";
11303 break;
11304 case OPERATION_TYPE_SUBTRACTION:
11305 result = "-";
11306 break;
11307
11308 case OPERATION_TYPE_PRE_DECREMENTATION:
11309 case OPERATION_TYPE_POST_DECREMENTATION:
11310 {
11311 result = "--";
11312
11313 break;
11314 }
11315
11316 case OPERATION_TYPE_PRE_INCREMENTATION:
11317 case OPERATION_TYPE_POST_INCREMENTATION:
11318 {
11319 result = "++";
11320
11321 break;
11322 }
11323
11324 default:
11325 {
11326 TCU_FAIL("Unrecognized operation type");
11327 }
11328 } /* switch(operation_type) */
11329
11330 return result;
11331 }
11332
11333 /** Returns a string representing user-specified operation type.
11334 *
11335 * @param operation_type Operation type to return the literal for.
11336 *
11337 * @return Requested string.
11338 **/
getOperationTypeString(const _operation_type & operation_type)11339 std::string GPUShaderFP64Test9::getOperationTypeString(const _operation_type& operation_type)
11340 {
11341 std::string result = "[?]";
11342
11343 switch (operation_type)
11344 {
11345 case OPERATION_TYPE_ADDITION:
11346 result = "addition";
11347 break;
11348 case OPERATION_TYPE_DIVISION:
11349 result = "division";
11350 break;
11351 case OPERATION_TYPE_MULTIPLICATION:
11352 result = "multiplication";
11353 break;
11354 case OPERATION_TYPE_SUBTRACTION:
11355 result = "subtraction";
11356 break;
11357 case OPERATION_TYPE_PRE_DECREMENTATION:
11358 result = "pre-decrementation";
11359 break;
11360 case OPERATION_TYPE_PRE_INCREMENTATION:
11361 result = "pre-incrementation";
11362 break;
11363 case OPERATION_TYPE_POST_DECREMENTATION:
11364 result = "post-decrementation";
11365 break;
11366 case OPERATION_TYPE_POST_INCREMENTATION:
11367 result = "post-incrementation";
11368 break;
11369
11370 default:
11371 {
11372 TCU_FAIL("Unrecognized operation type");
11373 }
11374 }
11375
11376 return result;
11377 }
11378
11379 /** Returns body of a vertex shader that should be used for user-specified test case
11380 * descriptor.
11381 *
11382 * @param test_case Test case descriptor.
11383 *
11384 * @return Requested GLSL shader body.
11385 **/
getVertexShaderBody(_test_case & test_case)11386 std::string GPUShaderFP64Test9::getVertexShaderBody(_test_case& test_case)
11387 {
11388 std::stringstream result_sstream;
11389 std::string result_variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11390 std::string variable_type_fp_string = Utils::getFPVariableTypeStringForVariableType(test_case.variable_type);
11391 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11392 const unsigned int n_variable_components = Utils::getNumberOfComponentsForVariableType(test_case.variable_type);
11393
11394 /* If we are to multiply matrices, we will need to use a different type
11395 * for the result variable if either of the matrices is not square.
11396 */
11397 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11398 Utils::isMatrixVariableType(test_case.variable_type))
11399 {
11400 Utils::_variable_type result_variable_type;
11401 Utils::_variable_type transposed_matrix_variable_type =
11402 Utils::getTransposedMatrixVariableType(test_case.variable_type);
11403
11404 result_variable_type =
11405 Utils::getPostMatrixMultiplicationVariableType(test_case.variable_type, transposed_matrix_variable_type);
11406 result_variable_type_string = Utils::getVariableTypeString(result_variable_type);
11407
11408 test_case.result_variable_type = result_variable_type;
11409 }
11410
11411 /* Form the pre-amble */
11412 result_sstream << "#version 400\n"
11413 "\n"
11414
11415 /* Add output variables */
11416 "out "
11417 << result_variable_type_string << " result;\n"
11418 "out ivec2 result_lt;\n"
11419 "out ivec2 result_lte;\n"
11420 "out ivec2 result_gt;\n"
11421 "out ivec2 result_gte;\n"
11422 "void main()\n"
11423 "{\n";
11424
11425 /* Form reference values */
11426 result_sstream << variable_type_string << " reference1 = " << variable_type_string << "(";
11427
11428 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components; ++n_variable_component)
11429 {
11430 result_sstream << (n_variable_component + 1);
11431
11432 if (n_variable_component != (n_variable_components - 1))
11433 {
11434 result_sstream << ", ";
11435 }
11436 } /* for (all variable components) */
11437
11438 result_sstream << ");\n";
11439
11440 for (unsigned int n_ref2_case = 0; n_ref2_case < 2; /* single- and double-precision cases */
11441 ++n_ref2_case)
11442 {
11443 Utils::_variable_type compatible_variable_type = test_case.variable_type;
11444
11445 if (Utils::isMatrixVariableType(compatible_variable_type) &&
11446 test_case.operation_type == OPERATION_TYPE_MULTIPLICATION)
11447 {
11448 compatible_variable_type = Utils::getTransposedMatrixVariableType(compatible_variable_type);
11449 }
11450
11451 std::string ref2_variable_type_fp_string =
11452 Utils::getFPVariableTypeStringForVariableType(compatible_variable_type);
11453 std::string ref2_variable_type_string = Utils::getVariableTypeString(compatible_variable_type);
11454 std::string ref2_variable_type = (n_ref2_case == 0) ? ref2_variable_type_fp_string : ref2_variable_type_string;
11455 std::string ref2_variable_name = (n_ref2_case == 0) ? "reference2f" : "reference2";
11456
11457 result_sstream << ref2_variable_type << " " << ref2_variable_name << " = " << ref2_variable_type << "(";
11458
11459 for (unsigned int n_variable_component = 0; n_variable_component < n_variable_components;
11460 ++n_variable_component)
11461 {
11462 result_sstream << (n_variable_components - (n_variable_component + 1));
11463
11464 if (n_variable_component != (n_variable_components - 1))
11465 {
11466 result_sstream << ", ";
11467 }
11468 } /* for (all variable components) */
11469
11470 result_sstream << ");\n";
11471 } /* for (both reference2 declarations) */
11472
11473 /* Add actual body */
11474 result_sstream << "\n"
11475 "result = ";
11476
11477 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11478 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION)
11479 {
11480 result_sstream << getOperatorForOperationType(test_case.operation_type);
11481 }
11482
11483 result_sstream << "reference1 ";
11484
11485 if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11486 test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11487 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11488 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11489 {
11490 if (test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION ||
11491 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11492 {
11493 result_sstream << getOperatorForOperationType(test_case.operation_type);
11494 }
11495 }
11496 else
11497 {
11498 result_sstream << getOperatorForOperationType(test_case.operation_type) << " reference2";
11499 }
11500
11501 result_sstream << ";\n";
11502
11503 if (Utils::isScalarVariableType(test_case.variable_type))
11504 {
11505 result_sstream << "result_lt [0] = (reference1 < reference2) ? 1 : 0;\n"
11506 "result_lt [1] = (reference1 < reference2f) ? 1 : 0;\n"
11507 "result_lte[0] = (reference1 <= reference2) ? 1 : 0;\n"
11508 "result_lte[1] = (reference1 <= reference2f) ? 1 : 0;\n"
11509 "result_gt [0] = (reference1 > reference2) ? 1 : 0;\n"
11510 "result_gt [1] = (reference1 > reference2f) ? 1 : 0;\n"
11511 "result_gte[0] = (reference1 >= reference2) ? 1 : 0;\n"
11512 "result_gte[1] = (reference1 >= reference2f) ? 1 : 0;\n";
11513 }
11514 else
11515 {
11516 result_sstream << "result_lt [0] = 1;\n"
11517 "result_lt [1] = 1;\n"
11518 "result_lte[0] = 1;\n"
11519 "result_lte[1] = 1;\n"
11520 "result_gt [0] = 1;\n"
11521 "result_gt [1] = 1;\n"
11522 "result_gte[0] = 1;\n"
11523 "result_gte[1] = 1;\n";
11524 }
11525
11526 result_sstream << "}\n";
11527
11528 /* All done */
11529 return result_sstream.str();
11530 }
11531
11532 /** Initializes all GL objects required to run the test.
11533 *
11534 * This function can throw a TestError exception if the implementation misbehaves.
11535 */
initTest()11536 void GPUShaderFP64Test9::initTest()
11537 {
11538 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11539
11540 /* Create program & vertex shader objects */
11541 m_po_id = gl.createProgram();
11542 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
11543
11544 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() or glCreateShader() call failed.");
11545
11546 /* Attach the shader to the program */
11547 gl.attachShader(m_po_id, m_vs_id);
11548 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call failed.");
11549
11550 /* Set up a buffer object */
11551 gl.genBuffers(1, &m_xfb_bo_id);
11552 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
11553
11554 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_xfb_bo_id);
11555 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
11556
11557 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_xfb_bo_id);
11558 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
11559
11560 /* Set up a vertex array object */
11561 gl.genVertexArrays(1, &m_vao_id);
11562 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
11563
11564 gl.bindVertexArray(m_vao_id);
11565 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
11566 }
11567
11568 /** Initializes all GL objects required to run an iteration described by
11569 * user-specified test case descriptor.
11570 *
11571 * @param test_case Test case descriptor to use for the initialization.
11572 **/
initTestIteration(_test_case & test_case)11573 void GPUShaderFP64Test9::initTestIteration(_test_case& test_case)
11574 {
11575 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
11576 std::string vs_body = getVertexShaderBody(test_case);
11577 const char* vs_body_raw_ptr = vs_body.c_str();
11578
11579 /* Store the shader's body */
11580 test_case.vs_body = vs_body;
11581
11582 /* Try to compile the shader */
11583 glw::GLint compile_status = GL_FALSE;
11584
11585 gl.shaderSource(m_vs_id, 1 /* count */, &vs_body_raw_ptr, DE_NULL /* length */);
11586 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
11587
11588 gl.compileShader(m_vs_id);
11589 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
11590
11591 gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &compile_status);
11592 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
11593
11594 if (compile_status != GL_TRUE)
11595 {
11596 TCU_FAIL("Test shader compilation failed.");
11597 }
11598
11599 /* Configure XFB */
11600 const char* xfb_names[] = { "result", "result_lt", "result_lte", "result_gt", "result_gte" };
11601 const unsigned int n_xfb_names = sizeof(xfb_names) / sizeof(xfb_names[0]);
11602
11603 gl.transformFeedbackVaryings(m_po_id, n_xfb_names, xfb_names, GL_INTERLEAVED_ATTRIBS);
11604 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
11605
11606 /* Try to link the program */
11607 glw::GLint link_status = GL_FALSE;
11608
11609 gl.linkProgram(m_po_id);
11610 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
11611
11612 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
11613 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
11614
11615 if (link_status != GL_TRUE)
11616 {
11617 TCU_FAIL("Test program linking failure");
11618 }
11619
11620 /* Set up XFB BO data storage */
11621 const unsigned int result_variable_size = static_cast<unsigned int>(
11622 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type) * sizeof(double));
11623 const unsigned int xfb_bo_size = static_cast<unsigned int>(
11624 result_variable_size + sizeof(int) * 2 /* ivec2s */ * 4); /* result_ output variables */
11625
11626 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, xfb_bo_size, DE_NULL /* data */, GL_STATIC_DRAW);
11627 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
11628 }
11629
11630 /** Executes test iteration.
11631 *
11632 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
11633 */
iterate()11634 tcu::TestNode::IterateResult GPUShaderFP64Test9::iterate()
11635 {
11636 /* Do not execute the test if GL_ARB_texture_view is not supported */
11637 if (!m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
11638 {
11639 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported.");
11640 }
11641
11642 /* Initialize all ES objects required to run all the checks */
11643 initTest();
11644
11645 /* Iterate through all variable types we want to test */
11646 const Utils::_variable_type variable_types[] = { Utils::VARIABLE_TYPE_DMAT2, Utils::VARIABLE_TYPE_DMAT2X3,
11647 Utils::VARIABLE_TYPE_DMAT2X4, Utils::VARIABLE_TYPE_DMAT3,
11648 Utils::VARIABLE_TYPE_DMAT3X2, Utils::VARIABLE_TYPE_DMAT3X4,
11649 Utils::VARIABLE_TYPE_DMAT4, Utils::VARIABLE_TYPE_DMAT4X2,
11650 Utils::VARIABLE_TYPE_DMAT4X3, Utils::VARIABLE_TYPE_DOUBLE,
11651 Utils::VARIABLE_TYPE_DVEC2, Utils::VARIABLE_TYPE_DVEC3,
11652 Utils::VARIABLE_TYPE_DVEC4 };
11653 const unsigned int n_variable_types = sizeof(variable_types) / sizeof(variable_types[0]);
11654
11655 for (unsigned int n_variable_type = 0; n_variable_type < n_variable_types; ++n_variable_type)
11656 {
11657 /* Iterate through all operation types we want to check */
11658 for (unsigned int n_operation_type = 0; n_operation_type < OPERATION_TYPE_COUNT; ++n_operation_type)
11659 {
11660 _operation_type operation_type = (_operation_type)n_operation_type;
11661 const Utils::_variable_type& variable_type = variable_types[n_variable_type];
11662
11663 /* Construct test case descriptor */
11664 _test_case test_case;
11665
11666 test_case.operation_type = operation_type;
11667 test_case.result_variable_type = variable_type;
11668 test_case.variable_type = variable_type;
11669
11670 /* Run the iteration */
11671 initTestIteration(test_case);
11672
11673 m_has_test_passed &= executeTestIteration(test_case);
11674 } /* for (all operation types) */
11675 } /* for (all variable types) */
11676
11677 /* All done. */
11678 if (m_has_test_passed)
11679 {
11680 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
11681 }
11682 else
11683 {
11684 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
11685 }
11686
11687 return STOP;
11688 }
11689
11690 /** Verifies data XFBed out by the draw call for user-specified test case
11691 * descriptor.
11692 *
11693 * @param test_case Test case descriptor
11694 * @param xfb_data Buffer holding the data XFBed out during the draw call.
11695 * Must not be NULL.
11696 *
11697 * @return true if the data was found to be correct, false otherwise.
11698 **/
verifyXFBData(const _test_case & test_case,const unsigned char * xfb_data)11699 bool GPUShaderFP64Test9::verifyXFBData(const _test_case& test_case, const unsigned char* xfb_data)
11700 {
11701 const double epsilon = 1e-5;
11702 const unsigned int n_result_components =
11703 Utils::getNumberOfComponentsForVariableType(test_case.result_variable_type);
11704 bool result = true;
11705 const double* xfb_data_result = (const double*)xfb_data;
11706 const int* xfb_data_result_lt = (const int*)(xfb_data_result + n_result_components);
11707 const int* xfb_data_result_lte = (const int*)xfb_data_result_lt + 2; /* cast/non-cast cases */
11708 const int* xfb_data_result_gt = (const int*)xfb_data_result_lte + 2; /* cast/non-cast cases */
11709 const int* xfb_data_result_gte = (const int*)xfb_data_result_gt + 2; /* cast/non-cast cases */
11710
11711 /* Prepare reference values */
11712 int modifier;
11713 std::vector<double> reference1;
11714 std::vector<double> reference2;
11715
11716 if (test_case.operation_type == OPERATION_TYPE_PRE_INCREMENTATION ||
11717 test_case.operation_type == OPERATION_TYPE_POST_INCREMENTATION)
11718 {
11719 modifier = 1;
11720 }
11721 else if (test_case.operation_type == OPERATION_TYPE_PRE_DECREMENTATION ||
11722 test_case.operation_type == OPERATION_TYPE_POST_DECREMENTATION)
11723 {
11724 modifier = -1;
11725 }
11726 else
11727 {
11728 modifier = 0;
11729 }
11730
11731 if (Utils::isMatrixVariableType(test_case.variable_type))
11732 {
11733 /* Matrices may be of different sizes so we need to compute the
11734 * reference values separately for each matrix
11735 */
11736 const Utils::_variable_type matrix_a_type = test_case.variable_type;
11737 const Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11738 const unsigned int n_matrix_a_components = Utils::getNumberOfComponentsForVariableType(matrix_a_type);
11739 const unsigned int n_matrix_b_components = Utils::getNumberOfComponentsForVariableType(matrix_b_type);
11740
11741 for (unsigned int n_component = 0; n_component < n_matrix_a_components; ++n_component)
11742 {
11743 reference1.push_back(modifier + n_component + 1);
11744 }
11745
11746 for (unsigned int n_component = 0; n_component < n_matrix_b_components; ++n_component)
11747 {
11748 reference2.push_back(n_matrix_b_components - (n_component + 1));
11749 }
11750 } /* if (Utils::isMatrixVariableType(test_case.variable_type) */
11751 else
11752 {
11753 /* Generate as many components as will be expected for the result variable */
11754 for (unsigned int n_result_component = 0; n_result_component < n_result_components; ++n_result_component)
11755 {
11756 reference1.push_back(modifier + n_result_component + 1);
11757 reference2.push_back(n_result_components - (n_result_component + 1));
11758 }
11759 }
11760
11761 /* Verify the result value(s) */
11762 if (test_case.operation_type == OPERATION_TYPE_MULTIPLICATION &&
11763 Utils::isMatrixVariableType(test_case.variable_type))
11764 {
11765 /* Matrix multiplication */
11766 double expected_result_data[4 * 4];
11767 Utils::_variable_type matrix_a_type = test_case.variable_type;
11768 Utils::_variable_type matrix_b_type = Utils::getTransposedMatrixVariableType(test_case.variable_type);
11769
11770 getMatrixMultiplicationResult(matrix_a_type, reference1, matrix_b_type, reference2, expected_result_data);
11771
11772 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11773 {
11774 if (de::abs(xfb_data_result[n_component] - expected_result_data[n_component]) > epsilon)
11775 {
11776 std::stringstream log_sstream;
11777
11778 log_sstream << "Data returned for " << Utils::getVariableTypeString(matrix_a_type) << " * "
11779 << Utils::getVariableTypeString(matrix_b_type)
11780 << " matrix multiplication was incorrect; expected:(";
11781
11782 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11783 ++n_logged_component)
11784 {
11785 log_sstream << expected_result_data[n_logged_component];
11786
11787 if (n_logged_component != (n_result_components - 1))
11788 {
11789 log_sstream << ", ";
11790 }
11791 } /* for (all components to be logged) */
11792
11793 log_sstream << "), retrieved:(";
11794
11795 for (unsigned int n_logged_component = 0; n_logged_component < n_result_components;
11796 ++n_logged_component)
11797 {
11798 log_sstream << xfb_data_result[n_logged_component];
11799
11800 if (n_logged_component != (n_result_components - 1))
11801 {
11802 log_sstream << ", ";
11803 }
11804 } /* for (all components to be logged) */
11805
11806 log_sstream << ")";
11807
11808 m_testCtx.getLog() << tcu::TestLog::Message << log_sstream.str().c_str() << tcu::TestLog::EndMessage;
11809
11810 result = false;
11811 break;
11812 }
11813 } /* for (all result components) */
11814 } /* if (dealing with matrix multiplication) */
11815 else
11816 {
11817 for (unsigned int n_component = 0; n_component < n_result_components; ++n_component)
11818 {
11819 double expected_value = reference1[n_component];
11820
11821 switch (test_case.operation_type)
11822 {
11823 case OPERATION_TYPE_ADDITION:
11824 expected_value += reference2[n_component];
11825 break;
11826 case OPERATION_TYPE_DIVISION:
11827 expected_value /= reference2[n_component];
11828 break;
11829 case OPERATION_TYPE_MULTIPLICATION:
11830 expected_value *= reference2[n_component];
11831 break;
11832 case OPERATION_TYPE_SUBTRACTION:
11833 expected_value -= reference2[n_component];
11834 break;
11835
11836 case OPERATION_TYPE_PRE_DECREMENTATION:
11837 case OPERATION_TYPE_PRE_INCREMENTATION:
11838 {
11839 /* Modifier already applied */
11840 break;
11841 }
11842
11843 case OPERATION_TYPE_POST_DECREMENTATION:
11844 case OPERATION_TYPE_POST_INCREMENTATION:
11845 {
11846 /* Need to reverse the modification for the purpose of the following check */
11847 expected_value -= modifier;
11848
11849 break;
11850 }
11851
11852 default:
11853 {
11854 TCU_FAIL("Unrecognized operation type");
11855 }
11856 } /* switch (test_case.operation_type) */
11857
11858 if (de::abs(xfb_data_result[n_component] - expected_value) > epsilon)
11859 {
11860 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11861 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11862
11863 m_testCtx.getLog() << tcu::TestLog::Message << "Value(s) generated for variable type ["
11864 << variable_type_string << "]"
11865 " and operation type ["
11866 << operation_type_string << "]"
11867 " were found invalid."
11868 << tcu::TestLog::EndMessage;
11869
11870 result = false;
11871 break;
11872 } /* if (test case failed) */
11873 } /* for (all components) */
11874 }
11875
11876 /* Verify the comparison operation results */
11877 if (Utils::isScalarVariableType(test_case.variable_type))
11878 {
11879 DE_ASSERT(n_result_components == 1);
11880
11881 const bool expected_result_lt[2] = { reference1[0] < reference2[0], reference1[0] < (float)reference2[0] };
11882 const bool expected_result_lte[2] = { reference1[0] <= reference2[0], reference1[0] <= (float)reference2[0] };
11883 const bool expected_result_gt[2] = { reference1[0] > reference2[0], reference1[0] > (float)reference2[0] };
11884 const bool expected_result_gte[2] = { reference1[0] >= reference2[0], reference1[0] >= (float)reference2[0] };
11885
11886 if ((xfb_data_result_lt[0] ? 1 : 0) != expected_result_lt[0] ||
11887 (xfb_data_result_lt[1] ? 1 : 0) != expected_result_lt[1])
11888 {
11889 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11890 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11891
11892 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than operator used for "
11893 "variable type ["
11894 << variable_type_string << "]"
11895 "and operation type ["
11896 << operation_type_string << "]"
11897 "was found invalid; expected:("
11898 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11899 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11900 << tcu::TestLog::EndMessage;
11901
11902 result = false;
11903 }
11904
11905 if ((xfb_data_result_lte[0] ? 1 : 0) != expected_result_lte[0] ||
11906 (xfb_data_result_lte[1] ? 1 : 0) != expected_result_lte[1])
11907 {
11908 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11909 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11910
11911 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for lower-than-or-equal operator used for "
11912 "variable type ["
11913 << variable_type_string << "]"
11914 "and operation type ["
11915 << operation_type_string << "]"
11916 "was found invalid; expected:("
11917 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11918 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11919 << tcu::TestLog::EndMessage;
11920
11921 result = false;
11922 }
11923
11924 if ((xfb_data_result_gt[0] ? 1 : 0) != expected_result_gt[0] ||
11925 (xfb_data_result_gt[1] ? 1 : 0) != expected_result_gt[1])
11926 {
11927 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11928 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11929
11930 m_testCtx.getLog() << tcu::TestLog::Message << "Values reported for greater-than operator used for "
11931 "variable type ["
11932 << variable_type_string << "]"
11933 "and operation type ["
11934 << operation_type_string << "]"
11935 "was found invalid; expected:("
11936 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11937 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11938 << tcu::TestLog::EndMessage;
11939
11940 result = false;
11941 }
11942
11943 if ((xfb_data_result_gte[0] ? 1 : 0) != expected_result_gte[0] ||
11944 (xfb_data_result_gte[1] ? 1 : 0) != expected_result_gte[1])
11945 {
11946 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11947 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11948
11949 m_testCtx.getLog() << tcu::TestLog::Message
11950 << "Values reported for greater-than-or-equal operator used for "
11951 "variable type ["
11952 << variable_type_string << "]"
11953 "and operation type ["
11954 << operation_type_string << "]"
11955 "was found invalid; expected:("
11956 << expected_result_lt[0] << ", " << expected_result_lt[1] << "); found:("
11957 << xfb_data_result_lt[0] << ", " << xfb_data_result_lt[1] << ")."
11958 << tcu::TestLog::EndMessage;
11959
11960 result = false;
11961 }
11962 } /* if (Utils::isScalarVariableType(test_case.variable_type) ) */
11963 else
11964 {
11965 if (xfb_data_result_lt[0] != 1 || xfb_data_result_lt[1] != 1 || xfb_data_result_lte[0] != 1 ||
11966 xfb_data_result_lte[1] != 1 || xfb_data_result_gt[0] != 1 || xfb_data_result_gt[1] != 1 ||
11967 xfb_data_result_gte[0] != 1 || xfb_data_result_gte[1] != 1)
11968 {
11969 std::string operation_type_string = getOperationTypeString(test_case.operation_type);
11970 std::string variable_type_string = Utils::getVariableTypeString(test_case.variable_type);
11971
11972 m_testCtx.getLog() << tcu::TestLog::Message
11973 << "Invalid value was reported for matrix variable type, for which "
11974 " operator checks are not executed; variable type ["
11975 << variable_type_string << "]"
11976 "and operation type ["
11977 << operation_type_string << "]" << tcu::TestLog::EndMessage;
11978
11979 result = false;
11980 }
11981 }
11982
11983 return result;
11984 }
11985
11986 namespace TypeHelpers
11987 {
11988 /** Get base type for reference types
11989 *
11990 * @tparam T type
11991 **/
11992 template <typename T>
11993 class referenceToType
11994 {
11995 public:
11996 typedef T result;
11997 };
11998
11999 template <typename T>
12000 class referenceToType<const T&>
12001 {
12002 public:
12003 typedef T result;
12004 };
12005
12006 /** Maps variable type with enumeration Utils::_variable_type
12007 *
12008 * @tparam T type
12009 **/
12010 template <typename T>
12011 class typeInfo;
12012
12013 template <>
12014 class typeInfo<glw::GLboolean>
12015 {
12016 public:
12017 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_BOOL;
12018 };
12019
12020 template <>
12021 class typeInfo<glw::GLdouble>
12022 {
12023 public:
12024 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DOUBLE;
12025 };
12026
12027 template <>
12028 class typeInfo<tcu::UVec2>
12029 {
12030 public:
12031 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC2;
12032 };
12033
12034 template <>
12035 class typeInfo<tcu::UVec3>
12036 {
12037 public:
12038 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC3;
12039 };
12040
12041 template <>
12042 class typeInfo<tcu::UVec4>
12043 {
12044 public:
12045 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_UVEC4;
12046 };
12047
12048 template <>
12049 class typeInfo<tcu::DVec2>
12050 {
12051 public:
12052 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC2;
12053 };
12054
12055 template <>
12056 class typeInfo<tcu::DVec3>
12057 {
12058 public:
12059 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC3;
12060 };
12061
12062 template <>
12063 class typeInfo<tcu::DVec4>
12064 {
12065 public:
12066 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DVEC4;
12067 };
12068
12069 template <>
12070 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 2> >
12071 {
12072 public:
12073 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2;
12074 };
12075
12076 template <>
12077 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 2> >
12078 {
12079 public:
12080 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X3;
12081 };
12082
12083 template <>
12084 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 2> >
12085 {
12086 public:
12087 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT2X4;
12088 };
12089
12090 template <>
12091 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 3> >
12092 {
12093 public:
12094 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3;
12095 };
12096
12097 template <>
12098 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 3> >
12099 {
12100 public:
12101 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X2;
12102 };
12103
12104 template <>
12105 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 3> >
12106 {
12107 public:
12108 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT3X4;
12109 };
12110
12111 template <>
12112 class typeInfo<tcu::Matrix<glw::GLdouble, 4, 4> >
12113 {
12114 public:
12115 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4;
12116 };
12117
12118 template <>
12119 class typeInfo<tcu::Matrix<glw::GLdouble, 2, 4> >
12120 {
12121 public:
12122 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X2;
12123 };
12124
12125 template <>
12126 class typeInfo<tcu::Matrix<glw::GLdouble, 3, 4> >
12127 {
12128 public:
12129 static const Utils::_variable_type variable_type = Utils::VARIABLE_TYPE_DMAT4X3;
12130 };
12131 } /* TypeHelpers */
12132
12133 /** Implementations of "math" functions required by "GPUShaderFP64Test10"
12134 *
12135 **/
12136 namespace Math
12137 {
12138 template <typename T>
12139 static T clamp(T x, T minVal, T maxVal);
12140
12141 template <int Size>
12142 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12143
12144 template <int Size>
12145 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src);
12146
12147 template <typename T>
12148 static T determinant(T val);
12149
12150 template <typename T>
12151 static T determinant(const tcu::Matrix<T, 2, 2>& mat);
12152
12153 template <typename T>
12154 static T determinant(const tcu::Matrix<T, 3, 3>& mat);
12155
12156 template <typename T>
12157 static T determinant(const tcu::Matrix<T, 4, 4>& mat);
12158
12159 template <int Size>
12160 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12161 glw::GLuint column, glw::GLuint row);
12162
12163 template <int Size>
12164 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12165 const tcu::Vector<glw::GLdouble, Size>& right);
12166
12167 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c);
12168
12169 static glw::GLdouble fract(glw::GLdouble val);
12170
12171 template <typename T>
12172 static T frexp(T val, glw::GLint& exp);
12173
12174 template <int Size>
12175 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12176 const tcu::Vector<glw::GLdouble, Size>& right);
12177
12178 template <int Size>
12179 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12180 const tcu::Vector<glw::GLdouble, Size>& right);
12181
12182 template <int Size>
12183 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix);
12184
12185 static glw::GLdouble inverseSqrt(glw::GLdouble val);
12186
12187 static glw::GLuint isinf_impl(glw::GLdouble val);
12188
12189 static glw::GLuint isnan_impl(glw::GLdouble val);
12190
12191 template <typename T>
12192 static T ldexp(T val, glw::GLint exp);
12193
12194 template <int Size>
12195 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12196 const tcu::Vector<glw::GLdouble, Size>& right);
12197
12198 template <int Size>
12199 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12200 const tcu::Vector<glw::GLdouble, Size>& right);
12201
12202 template <typename T>
12203 static T max(T left, T right);
12204
12205 template <typename T>
12206 static T min(T left, T right);
12207
12208 template <int Size>
12209 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12210 glw::GLuint row);
12211
12212 template <typename T>
12213 static T mix(T left, T right, T weight);
12214
12215 template <typename T>
12216 static T mod(T left, T right);
12217
12218 template <typename T>
12219 static T modf(T val, T& integer);
12220
12221 template <typename T>
12222 static T multiply(T left, T right);
12223
12224 template <int Size>
12225 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12226 const tcu::Vector<glw::GLdouble, Size>& right);
12227
12228 template <int Cols, int Rows>
12229 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12230 const tcu::Vector<glw::GLdouble, Cols>& right);
12231
12232 static glw::GLdouble packDouble2x32(const tcu::UVec2& in);
12233
12234 template <typename T>
12235 static T round(T t);
12236
12237 template <typename T>
12238 static T roundEven(T t);
12239
12240 template <typename T>
12241 static T sign(T t);
12242
12243 template <typename T>
12244 static T smoothStep(T e0, T e1, T val);
12245
12246 template <typename T>
12247 static T step(T edge, T val);
12248
12249 template <typename T, int Rows, int Cols>
12250 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix);
12251
12252 template <typename T>
12253 static T trunc(T t);
12254
12255 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val);
12256
12257 template <typename T>
clamp(T x,T minVal,T maxVal)12258 static T clamp(T x, T minVal, T maxVal)
12259 {
12260 return min(max(x, minVal), maxVal);
12261 }
12262
12263 template <int Size>
cofactors(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12264 static tcu::Matrix<glw::GLdouble, Size, Size> cofactors(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12265 {
12266 tcu::Matrix<glw::GLdouble, Size, Size> result;
12267
12268 for (glw::GLuint c = 0; c < Size; ++c)
12269 {
12270 for (glw::GLuint r = 0; r < Size; ++r)
12271 {
12272 const glw::GLdouble minor_value = minor_impl(matrix, c, r);
12273
12274 result(r, c) = (1 == (c + r) % 2) ? -minor_value : minor_value;
12275 }
12276 }
12277
12278 return result;
12279 }
12280
12281 template <int Size>
convertBvecToUvec(const tcu::Vector<bool,Size> & src)12282 static tcu::Vector<glw::GLuint, Size> convertBvecToUvec(const tcu::Vector<bool, Size>& src)
12283 {
12284 tcu::Vector<glw::GLuint, Size> result;
12285
12286 for (glw::GLint i = 0; i < Size; ++i)
12287 {
12288 if (GL_FALSE != src[i])
12289 {
12290 result[i] = 1;
12291 }
12292 else
12293 {
12294 result[i] = 0;
12295 }
12296 }
12297
12298 return result;
12299 }
12300
12301 template <typename T>
det2(T _00,T _10,T _01,T _11)12302 static T det2(T _00, T _10, T _01, T _11)
12303 {
12304 return _00 * _11 - _01 * _10;
12305 }
12306
12307 template <typename T>
det3(T _00,T _10,T _20,T _01,T _11,T _21,T _02,T _12,T _22)12308 static T det3(T _00, T _10, T _20, T _01, T _11, T _21, T _02, T _12, T _22)
12309 {
12310 return _00 * det2(_11, _21, _12, _22) - _10 * det2(_01, _21, _02, _22) + _20 * det2(_01, _11, _02, _12);
12311 }
12312
12313 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)12314 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,
12315 T _33)
12316 {
12317 return _00 * det3(_11, _21, _31, _12, _22, _32, _13, _23, _33) -
12318 _10 * det3(_01, _21, _31, _02, _22, _32, _03, _23, _33) +
12319 _20 * det3(_01, _11, _31, _02, _12, _32, _03, _13, _33) -
12320 _30 * det3(_01, _11, _21, _02, _12, _22, _03, _13, _23);
12321 }
12322
12323 template <typename T>
determinant(T val)12324 static T determinant(T val)
12325 {
12326 return val;
12327 }
12328
12329 template <typename T>
determinant(const tcu::Matrix<T,2,2> & mat)12330 static T determinant(const tcu::Matrix<T, 2, 2>& mat)
12331 {
12332 return det2(mat(0, 0), mat(0, 1), mat(1, 0), mat(1, 1));
12333 }
12334
12335 template <typename T>
determinant(const tcu::Matrix<T,3,3> & mat)12336 static T determinant(const tcu::Matrix<T, 3, 3>& mat)
12337 {
12338 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));
12339 }
12340
12341 template <typename T>
determinant(const tcu::Matrix<T,4,4> & mat)12342 static T determinant(const tcu::Matrix<T, 4, 4>& mat)
12343 {
12344 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),
12345 mat(2, 1), mat(2, 2), mat(2, 3), mat(3, 0), mat(3, 1), mat(3, 2), mat(3, 3));
12346 }
12347
12348 template <int Size>
eliminate(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12349 static tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminate(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix,
12350 glw::GLuint column, glw::GLuint row)
12351 {
12352 // GCC sometimes diagnoses an incorrect out of bounds write here. The code has been verified to be correct.
12353 #if (DE_COMPILER == DE_COMPILER_GCC)
12354 # pragma GCC diagnostic push
12355 # pragma GCC diagnostic ignored "-Warray-bounds"
12356 #endif
12357
12358 const glw::GLint eCol = static_cast<glw::GLint>(column);
12359 const glw::GLint eRow = static_cast<glw::GLint>(row);
12360
12361 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> result;
12362
12363 for (glw::GLint c = 0; c < Size; ++c)
12364 {
12365 /* Skip eliminated column */
12366 if (eCol == c)
12367 {
12368 continue;
12369 }
12370
12371 for (glw::GLint r = 0; r < Size; ++r)
12372 {
12373 /* Skip eliminated row */
12374 if (eRow == r)
12375 {
12376 continue;
12377 }
12378
12379 const glw::GLint r_offset = (r > eRow) ? -1 : 0;
12380 const glw::GLint c_offset = (c > eCol) ? -1 : 0;
12381
12382 result(r + r_offset, c + c_offset) = matrix(r, c);
12383 }
12384 }
12385
12386 return result;
12387
12388 #if (DE_COMPILER == DE_COMPILER_GCC)
12389 # pragma GCC diagnostic pop
12390 #endif
12391 }
12392
12393 template <int Size>
equal(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12394 static tcu::Vector<glw::GLuint, Size> equal(const tcu::Vector<glw::GLdouble, Size>& left,
12395 const tcu::Vector<glw::GLdouble, Size>& right)
12396 {
12397 return convertBvecToUvec(tcu::equal(left, right));
12398 }
12399
fma(glw::GLdouble a,glw::GLdouble b,glw::GLdouble c)12400 static glw::GLdouble fma(glw::GLdouble a, glw::GLdouble b, glw::GLdouble c)
12401 {
12402 return a * b + c;
12403 }
12404
fract(glw::GLdouble val)12405 static glw::GLdouble fract(glw::GLdouble val)
12406 {
12407 return val - floor(val);
12408 }
12409
12410 template <typename T>
frexp(T val,glw::GLint & exp)12411 static T frexp(T val, glw::GLint& exp)
12412 {
12413 return ::frexp(val, &exp);
12414 }
12415
12416 template <int Size>
greaterThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12417 static tcu::Vector<glw::GLuint, Size> greaterThan(const tcu::Vector<glw::GLdouble, Size>& left,
12418 const tcu::Vector<glw::GLdouble, Size>& right)
12419 {
12420 return convertBvecToUvec(tcu::greaterThan(left, right));
12421 }
12422
12423 template <int Size>
greaterThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12424 static tcu::Vector<glw::GLuint, Size> greaterThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12425 const tcu::Vector<glw::GLdouble, Size>& right)
12426 {
12427 return convertBvecToUvec(tcu::greaterThanEqual(left, right));
12428 }
12429
12430 template <int Size>
inverse(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix)12431 static tcu::Matrix<glw::GLdouble, Size, Size> inverse(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix)
12432 {
12433 const tcu::Matrix<glw::GLdouble, Size, Size> cof = cofactors(matrix);
12434 const tcu::Matrix<glw::GLdouble, Size, Size> adjugate = tcu::transpose(cof);
12435 const glw::GLdouble det = determinant(matrix);
12436 const glw::GLdouble inv_det = 1.0 / det;
12437
12438 tcu::Matrix<glw::GLdouble, Size, Size> result = adjugate * inv_det;
12439
12440 return result;
12441 }
12442
inverseSqrt(glw::GLdouble val)12443 static glw::GLdouble inverseSqrt(glw::GLdouble val)
12444 {
12445 const glw::GLdouble root = sqrt(val);
12446
12447 return (1.0 / root);
12448 }
12449
isinf_impl(glw::GLdouble val)12450 static glw::GLuint isinf_impl(glw::GLdouble val)
12451 {
12452 const glw::GLdouble infinity = std::numeric_limits<glw::GLdouble>::infinity();
12453
12454 return ((infinity == val) || (-infinity == val));
12455 }
12456
isnan_impl(glw::GLdouble val)12457 static glw::GLuint isnan_impl(glw::GLdouble val)
12458 {
12459 return val != val;
12460 }
12461
12462 template <typename T>
ldexp(T val,glw::GLint exp)12463 static T ldexp(T val, glw::GLint exp)
12464 {
12465 return ::ldexp(val, exp);
12466 }
12467
12468 template <int Size>
lessThan(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12469 static tcu::Vector<glw::GLuint, Size> lessThan(const tcu::Vector<glw::GLdouble, Size>& left,
12470 const tcu::Vector<glw::GLdouble, Size>& right)
12471 {
12472 return convertBvecToUvec(tcu::lessThan(left, right));
12473 }
12474
12475 template <int Size>
lessThanEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12476 static tcu::Vector<glw::GLuint, Size> lessThanEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12477 const tcu::Vector<glw::GLdouble, Size>& right)
12478 {
12479 return convertBvecToUvec(tcu::lessThanEqual(left, right));
12480 }
12481
12482 template <typename T>
max(T left,T right)12483 static T max(T left, T right)
12484 {
12485 return (left >= right) ? left : right;
12486 }
12487
12488 template <typename T>
min(T left,T right)12489 static T min(T left, T right)
12490 {
12491 return (left <= right) ? left : right;
12492 }
12493
12494 template <int Size>
minor_impl(const tcu::Matrix<glw::GLdouble,Size,Size> & matrix,glw::GLuint column,glw::GLuint row)12495 static glw::GLdouble minor_impl(const tcu::Matrix<glw::GLdouble, Size, Size>& matrix, glw::GLuint column,
12496 glw::GLuint row)
12497 {
12498 tcu::Matrix<glw::GLdouble, Size - 1, Size - 1> eliminated = eliminate(matrix, column, row);
12499
12500 return determinant(eliminated);
12501 }
12502
12503 template <>
minor_impl(const tcu::Matrix<glw::GLdouble,2,2> & matrix,glw::GLuint column,glw::GLuint row)12504 glw::GLdouble minor_impl<2>(const tcu::Matrix<glw::GLdouble, 2, 2>& matrix, glw::GLuint column, glw::GLuint row)
12505 {
12506 const glw::GLuint r = (0 == row) ? 1 : 0;
12507 const glw::GLuint c = (0 == column) ? 1 : 0;
12508
12509 return matrix(r, c);
12510 }
12511
12512 template <typename T>
mix(T left,T right,T weight)12513 static T mix(T left, T right, T weight)
12514 {
12515 return left * (1 - weight) + right * (weight);
12516 }
12517
12518 template <typename T>
mod(T left,T right)12519 static T mod(T left, T right)
12520 {
12521 const T div_res = left / right;
12522 const T floored = floor(div_res);
12523
12524 return left - right * floored;
12525 }
12526
12527 template <typename T>
modf(T val,T & integer)12528 static T modf(T val, T& integer)
12529 {
12530 return ::modf(val, &integer);
12531 }
12532
12533 template <typename T>
multiply(T left,T right)12534 static T multiply(T left, T right)
12535 {
12536 T result = left * right;
12537
12538 return result;
12539 }
12540
12541 template <int Size>
notEqual(const tcu::Vector<glw::GLdouble,Size> & left,const tcu::Vector<glw::GLdouble,Size> & right)12542 static tcu::Vector<glw::GLuint, Size> notEqual(const tcu::Vector<glw::GLdouble, Size>& left,
12543 const tcu::Vector<glw::GLdouble, Size>& right)
12544 {
12545 return convertBvecToUvec(tcu::notEqual(left, right));
12546 }
12547
12548 template <int Cols, int Rows>
outerProduct(const tcu::Vector<glw::GLdouble,Rows> & left,const tcu::Vector<glw::GLdouble,Cols> & right)12549 static tcu::Matrix<glw::GLdouble, Rows, Cols> outerProduct(const tcu::Vector<glw::GLdouble, Rows>& left,
12550 const tcu::Vector<glw::GLdouble, Cols>& right)
12551 {
12552 tcu::Matrix<glw::GLdouble, Rows, 1> left_mat;
12553 tcu::Matrix<glw::GLdouble, 1, Cols> right_mat;
12554 tcu::Matrix<glw::GLdouble, Rows, Cols> result;
12555
12556 for (glw::GLuint i = 0; i < Rows; ++i)
12557 {
12558 left_mat(i, 0) = left[i];
12559 }
12560
12561 for (glw::GLuint i = 0; i < Cols; ++i)
12562 {
12563 right_mat(0, i) = right[i];
12564 }
12565
12566 result = left_mat * right_mat;
12567
12568 return result;
12569 }
12570
packDouble2x32(const tcu::UVec2 & in)12571 static glw::GLdouble packDouble2x32(const tcu::UVec2& in)
12572 {
12573 const glw::GLuint buffer[2] = { in[0], in[1] };
12574 glw::GLdouble result;
12575 memcpy(&result, buffer, sizeof(result));
12576 return result;
12577 }
12578
12579 template <typename T>
round(T t)12580 static T round(T t)
12581 {
12582 T frac = fract(t);
12583 T res = t - frac;
12584
12585 if (((T)0.5) < frac)
12586 {
12587 res += ((T)1.0);
12588 }
12589
12590 return res;
12591 }
12592
12593 template <typename T>
roundEven(T t)12594 static T roundEven(T t)
12595 {
12596 T frac = fract(t);
12597 T res = t - frac;
12598
12599 if (((T)0.5) < frac)
12600 {
12601 res += ((T)1.0);
12602 }
12603 else if ((((T)0.5) == frac) && (0 != ((int)res) % 2))
12604 {
12605 res += ((T)1.0);
12606 }
12607
12608 return res;
12609 }
12610
12611 template <typename T>
sign(T t)12612 static T sign(T t)
12613 {
12614 if (0 > t)
12615 {
12616 return -1;
12617 }
12618 else if (0 == t)
12619 {
12620 return 0;
12621 }
12622 else
12623 {
12624 return 1;
12625 }
12626 }
12627
12628 template <typename T>
smoothStep(T e0,T e1,T val)12629 static T smoothStep(T e0, T e1, T val)
12630 {
12631 if (e0 >= val)
12632 {
12633 return 0;
12634 }
12635
12636 if (e1 <= val)
12637 {
12638 return 1;
12639 }
12640
12641 T temp = (val - e0) / (e1 - e0);
12642
12643 T result = temp * temp * (3 - 2 * temp);
12644
12645 return result;
12646 }
12647
12648 template <typename T>
step(T edge,T val)12649 static T step(T edge, T val)
12650 {
12651 if (edge > val)
12652 {
12653 return 0;
12654 }
12655 else
12656 {
12657 return 1;
12658 }
12659 }
12660
12661 template <typename T, int Rows, int Cols>
transpose(const tcu::Matrix<T,Rows,Cols> & matrix)12662 static tcu::Matrix<T, Cols, Rows> transpose(const tcu::Matrix<T, Rows, Cols>& matrix)
12663 {
12664 tcu::Matrix<T, Cols, Rows> result = tcu::transpose(matrix);
12665
12666 return result;
12667 }
12668
12669 template <typename T>
trunc(T t)12670 static T trunc(T t)
12671 {
12672 const T abs_value = de::abs(t);
12673 const T result_value = floor(abs_value);
12674
12675 const T result = sign(t) * result_value;
12676
12677 return result;
12678 }
12679
unpackDouble2x32(const glw::GLdouble & val)12680 static tcu::UVec2 unpackDouble2x32(const glw::GLdouble& val)
12681 {
12682 glw::GLuint* ptr = (glw::GLuint*)&val;
12683 tcu::UVec2 result(ptr[0], ptr[1]);
12684
12685 return result;
12686 }
12687 } /* Math */
12688
12689 /** Enumeration of tested functions
12690 * *_AGAINT_SCALAR enums are used to call glsl function with mixed scalar and genDType arguments.
12691 * For example "max" can be called for (dvec3, double).
12692 **/
12693 enum FunctionEnum
12694 {
12695 FUNCTION_ABS = 0,
12696 FUNCTION_CEIL,
12697 FUNCTION_CLAMP,
12698 FUNCTION_CLAMP_AGAINST_SCALAR,
12699 FUNCTION_CROSS,
12700 FUNCTION_DETERMINANT,
12701 FUNCTION_DISTANCE,
12702 FUNCTION_DOT,
12703 FUNCTION_EQUAL,
12704 FUNCTION_FACEFORWARD,
12705 FUNCTION_FLOOR,
12706 FUNCTION_FMA,
12707 FUNCTION_FRACT,
12708 FUNCTION_FREXP,
12709 FUNCTION_GREATERTHAN,
12710 FUNCTION_GREATERTHANEQUAL,
12711 FUNCTION_INVERSE,
12712 FUNCTION_INVERSESQRT,
12713 FUNCTION_LDEXP,
12714 FUNCTION_LESSTHAN,
12715 FUNCTION_LESSTHANEQUAL,
12716 FUNCTION_LENGTH,
12717 FUNCTION_MATRIXCOMPMULT,
12718 FUNCTION_MAX,
12719 FUNCTION_MAX_AGAINST_SCALAR,
12720 FUNCTION_MIN,
12721 FUNCTION_MIN_AGAINST_SCALAR,
12722 FUNCTION_MIX,
12723 FUNCTION_MOD,
12724 FUNCTION_MOD_AGAINST_SCALAR,
12725 FUNCTION_MODF,
12726 FUNCTION_NORMALIZE,
12727 FUNCTION_NOTEQUAL,
12728 FUNCTION_OUTERPRODUCT,
12729 FUNCTION_PACKDOUBLE2X32,
12730 FUNCTION_REFLECT,
12731 FUNCTION_REFRACT,
12732 FUNCTION_ROUND,
12733 FUNCTION_ROUNDEVEN,
12734 FUNCTION_SIGN,
12735 FUNCTION_SMOOTHSTEP,
12736 FUNCTION_SMOOTHSTEP_AGAINST_SCALAR,
12737 FUNCTION_SQRT,
12738 FUNCTION_STEP,
12739 FUNCTION_STEP_AGAINST_SCALAR,
12740 FUNCTION_TRANSPOSE,
12741 FUNCTION_TRUNC,
12742 FUNCTION_UNPACKDOUBLE2X32,
12743 FUNCTION_ISNAN,
12744 FUNCTION_ISINF,
12745 };
12746
12747 struct TypeDefinition
12748 {
12749 std::string name;
12750 glw::GLuint n_columns;
12751 glw::GLuint n_rows;
12752 };
12753
12754 /** Implementation of BuiltinFunctionTest test, description follows:
12755 *
12756 * Verify double-precision support in common functions works correctly.
12757 * All double-precision types that apply for particular cases should
12758 * be tested for the following functions:
12759 *
12760 * - abs();
12761 * - ceil();
12762 * - clamp();
12763 * - cross();
12764 * - determinant();
12765 * - distance();
12766 * - dot();
12767 * - equal();
12768 * - faceforward();
12769 * - floor();
12770 * - fma();
12771 * - fract();
12772 * - frexp();
12773 * - greaterThan();
12774 * - greaterThanEqual();
12775 * - inverse();
12776 * - inversesqrt();
12777 * - ldexp();
12778 * - lessThan();
12779 * - lessThanEqual();
12780 * - length();
12781 * - matrixCompMult();
12782 * - max();
12783 * - min();
12784 * - mix();
12785 * - mod();
12786 * - modf();
12787 * - normalize();
12788 * - notEqual();
12789 * - outerProduct();
12790 * - packDouble2x32();
12791 * - reflect();
12792 * - refract();
12793 * - round();
12794 * - roundEven();
12795 * - sign();
12796 * - smoothstep();
12797 * - sqrt();
12798 * - step();
12799 * - transpose();
12800 * - trunc();
12801 * - unpackDouble2x32();
12802 * - isnan();
12803 * - isinf();
12804 *
12805 * The test should work by creating a program object (for each case
12806 * considered), to which a vertex shader should be attached. The
12807 * shader should define input variables that should be used as
12808 * arguments for the function in question. The result of the
12809 * operation should then be XFBed back to the test, where the
12810 * value should be verified.
12811 *
12812 * Reference function implementation from pre-DEQP CTS framework
12813 * should be ported to C for verification purposes where available.
12814 *
12815 * The test should use 1024 different scalar/vector/matrix argument
12816 * combinations. It should pass if all functions are determined
12817 * to work correctly for all argument combinations used.
12818 **/
12819 class BuiltinFunctionTest : public deqp::TestCase
12820 {
12821 public:
12822 /* Public methods */
12823 BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
12824 TypeDefinition typeDefinition);
12825
12826 virtual void deinit();
12827 virtual tcu::TestNode::IterateResult iterate();
12828
12829 /** Base class of functionObject. Main goal of it is to keep function details toghether and hide calling code.
12830 *
12831 **/
12832 class functionObject
12833 {
12834 public:
12835 functionObject(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
12836 Utils::_variable_type result_type);
12837
~functionObject()12838 virtual ~functionObject()
12839 {
12840 }
12841
12842 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const = 0;
12843
12844 virtual glw::GLuint getArgumentCount() const = 0;
12845 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const = 0;
12846 glw::GLuint getArgumentComponents(glw::GLuint argument) const;
12847 glw::GLuint getArgumentComponentSize(glw::GLuint argument) const;
12848 glw::GLuint getArgumentOffset(glw::GLuint argument) const;
12849 glw::GLuint getArgumentStride() const;
12850 glw::GLuint getArgumentStride(glw::GLuint argument) const;
12851 FunctionEnum getFunctionEnum() const;
12852 const glw::GLchar* getName() const;
12853 glw::GLuint getResultComponents(glw::GLuint result) const;
12854 virtual glw::GLuint getResultCount() const;
12855 glw::GLuint getResultOffset(glw::GLuint result) const;
12856 virtual Utils::_variable_type getResultType(glw::GLuint result) const;
12857 glw::GLuint getResultStride(glw::GLuint result) const;
12858 glw::GLuint getBaseTypeSize(glw::GLuint result) const;
12859 glw::GLuint getResultStride() const;
12860
12861 protected:
12862 const FunctionEnum m_function_enum;
12863 const glw::GLchar* m_function_name;
12864 const glw::GLvoid* m_p_function;
12865 const Utils::_variable_type m_res_type;
12866 };
12867
12868 private:
12869 /* Private types */
12870 /** General type enumeration
12871 *
12872 **/
12873 enum generalType
12874 {
12875 SCALAR = 0,
12876 VECTOR,
12877 MATRIX,
12878 };
12879
12880 /** Details of variable type
12881 *
12882 **/
12883 struct typeDetails
12884 {
12885 typeDetails(glw::GLuint n_columns, glw::GLuint n_rows);
12886
12887 generalType m_general_type;
12888 glw::GLuint m_n_columns;
12889 glw::GLuint m_n_rows;
12890 glw::GLenum m_type;
12891 std::string m_type_name;
12892 };
12893
12894 /* Typedefs for gl.uniform* function pointers */
12895 typedef GLW_APICALL void(GLW_APIENTRY* uniformDMatFunctionPointer)(glw::GLint, glw::GLsizei, glw::GLboolean,
12896 const glw::GLdouble*);
12897 typedef GLW_APICALL void(GLW_APIENTRY* uniformDVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLdouble*);
12898 typedef GLW_APICALL void(GLW_APIENTRY* uniformIVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLint*);
12899 typedef GLW_APICALL void(GLW_APIENTRY* uniformUVecFunctionPointer)(glw::GLint, glw::GLsizei, const glw::GLuint*);
12900
12901 /* Private methods */
12902 bool compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right);
12903
12904 functionObject* getFunctionObject(FunctionEnum function, const typeDetails& type);
12905
12906 uniformDMatFunctionPointer getUniformFunctionForDMat(glw::GLuint argument,
12907 const functionObject& function_object) const;
12908
12909 uniformDVecFunctionPointer getUniformFunctionForDVec(glw::GLuint argument,
12910 const functionObject& function_object) const;
12911
12912 uniformIVecFunctionPointer getUniformFunctionForIVec(glw::GLuint argument,
12913 const functionObject& function_object) const;
12914
12915 uniformUVecFunctionPointer getUniformFunctionForUVec(glw::GLuint argument,
12916 const functionObject& function_object) const;
12917
12918 const glw::GLchar* getUniformName(glw::GLuint argument) const;
12919 const glw::GLchar* getVaryingName(glw::GLuint argument) const;
12920
12921 bool isFunctionImplemented(FunctionEnum function, const typeDetails& type) const;
12922
12923 void logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name, Utils::_variable_type type) const;
12924
12925 void prepareArgument(const functionObject& function_object, glw::GLuint vertex, glw::GLubyte* buffer);
12926
12927 void prepareComponents(const functionObject& function_object, glw::GLuint vertex, glw::GLuint argument,
12928 glw::GLubyte* buffer);
12929
12930 void prepareProgram(const functionObject& function_object, Utils::programInfo& program_info);
12931
12932 void prepareTestData(const functionObject& function_object);
12933 void prepareVertexShaderCode(const functionObject& function_object);
12934
12935 bool test(FunctionEnum function, const typeDetails& type);
12936
12937 void testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex);
12938
12939 void testInit();
12940
12941 bool isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
12942 const Utils::_variable_type result_type, const glw::GLvoid* expected_result_src,
12943 const glw::GLvoid* result_src);
12944
12945 bool verifyResults(const functionObject& function_object, glw::GLuint vertex);
12946
12947 /* Private constants */
12948 static const glw::GLdouble m_epsilon;
12949 static const glw::GLuint m_n_veritces;
12950
12951 /* Private fields */
12952 glw::GLuint m_transform_feedback_buffer_id;
12953 glw::GLuint m_vertex_array_object_id;
12954
12955 std::vector<glw::GLubyte> m_expected_results_data;
12956 FunctionEnum m_function;
12957 TypeDefinition m_typeDefinition;
12958 std::vector<glw::GLubyte> m_argument_data;
12959 std::string m_vertex_shader_code;
12960 };
12961
12962 /* Constants used by BuiltinFunctionTest */
12963 /** Khronos Bug #14010
12964 * Using an epsilon value for comparing floating points is error prone.
12965 * Rather than writing a new floating point comparison function, I am
12966 * increasing the epsilon value to allow greater orders of magnitude
12967 * of floating point values.
12968 **/
12969 const glw::GLdouble BuiltinFunctionTest::m_epsilon = 0.00002;
12970 const glw::GLuint BuiltinFunctionTest::m_n_veritces = 1024;
12971
12972 /** Implementations of function objects required by "BuiltinFunctionTest"
12973 *
12974 **/
12975 namespace FunctionObject
12976 {
12977 /** Maps variable type with enumeration Utils::_variable_type
12978 *
12979 * @tparam T type
12980 **/
12981 template <typename T>
12982 class typeInfo
12983 {
12984 public:
12985 static const Utils::_variable_type variable_type =
12986 TypeHelpers::typeInfo<typename TypeHelpers::referenceToType<T>::result>::variable_type;
12987 };
12988
12989 /** Place data from <in> into <buffer>
12990 *
12991 * @param buffer Buffer
12992 * @param in Input data
12993 **/
12994 template <typename T>
12995 class pack
12996 {
12997 public:
set(glw::GLvoid * buffer,const T & in)12998 static void set(glw::GLvoid* buffer, const T& in)
12999 {
13000 *(T*)buffer = in;
13001 }
13002 };
13003
13004 /** Place tcu::Matrix data from <in> into <buffer>
13005 *
13006 * @param buffer Buffer
13007 * @param in Input data
13008 **/
13009 template <int Cols, int Rows>
13010 class pack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13011 {
13012 public:
set(glw::GLvoid * buffer,const tcu::Matrix<glw::GLdouble,Rows,Cols> & in)13013 static void set(glw::GLvoid* buffer, const tcu::Matrix<glw::GLdouble, Rows, Cols>& in)
13014 {
13015 glw::GLdouble* data = (glw::GLdouble*)buffer;
13016
13017 for (glw::GLint column = 0; column < Cols; ++column)
13018 {
13019 for (glw::GLint row = 0; row < Rows; ++row)
13020 {
13021 glw::GLint index = column * Rows + row;
13022
13023 data[index] = in(row, column);
13024 }
13025 }
13026 }
13027 };
13028
13029 /** Get data of <out> from <buffer>
13030 *
13031 * @param buffer Buffer
13032 * @param out Output data
13033 **/
13034 template <typename T>
13035 class unpack
13036 {
13037 public:
get(const glw::GLvoid * buffer,T & out)13038 static void get(const glw::GLvoid* buffer, T& out)
13039 {
13040 out = *(T*)buffer;
13041 }
13042 };
13043
13044 /** Get tcu::Matrix data from <buffer>
13045 *
13046 * @param buffer Buffer
13047 * @param out Output data
13048 **/
13049 template <int Cols, int Rows>
13050 class unpack<tcu::Matrix<glw::GLdouble, Rows, Cols> >
13051 {
13052 public:
get(const glw::GLvoid * buffer,tcu::Matrix<glw::GLdouble,Rows,Cols> & out)13053 static void get(const glw::GLvoid* buffer, tcu::Matrix<glw::GLdouble, Rows, Cols>& out)
13054 {
13055 const glw::GLdouble* data = (glw::GLdouble*)buffer;
13056
13057 for (glw::GLint column = 0; column < Cols; ++column)
13058 {
13059 for (glw::GLint row = 0; row < Rows; ++row)
13060 {
13061 glw::GLint index = column * Rows + row;
13062
13063 out(row, column) = data[index];
13064 }
13065 }
13066 }
13067 };
13068
13069 /** Base of unary function classes
13070 *
13071 **/
13072 class unaryBase : public BuiltinFunctionTest::functionObject
13073 {
13074 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)13075 unaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13076 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13077 : functionObject(function_enum, function_name, function_pointer, res_type), m_arg_type(arg_type)
13078 {
13079 }
13080
getArgumentCount() const13081 virtual glw::GLuint getArgumentCount() const
13082 {
13083 return 1;
13084 }
13085
getArgumentType(glw::GLuint) const13086 virtual Utils::_variable_type getArgumentType(glw::GLuint /* argument */) const
13087 {
13088 return m_arg_type;
13089 }
13090
13091 protected:
13092 const Utils::_variable_type m_arg_type;
13093 };
13094
13095 /** Unary function class. It treats input argument as one variable.
13096 *
13097 * @tparam ResT Type of result
13098 * @tparam ArgT Type of argument
13099 **/
13100 template <typename ResT, typename ArgT>
13101 class unary : public unaryBase
13102 {
13103 public:
13104 typedef ResT (*functionPointer)(const ArgT&);
13105
unary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13106 unary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13107 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13108 typeInfo<ArgT>::variable_type)
13109 {
13110 }
13111
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13112 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13113 {
13114 ResT result;
13115 ArgT arg;
13116
13117 unpack<ArgT>::get(argument_src, arg);
13118
13119 functionPointer p_function = (functionPointer)m_p_function;
13120
13121 result = p_function(arg);
13122
13123 pack<ResT>::set(result_dst, result);
13124 }
13125 };
13126
13127 /** Unary function class. It treats input argument as separate components.
13128 *
13129 * @tparam ResT Type of result
13130 **/
13131 template <typename ResT>
13132 class unaryByComponent : public unaryBase
13133 {
13134 public:
13135 typedef ResT (*functionPointer)(glw::GLdouble);
13136
unaryByComponent(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer,const Utils::_variable_type res_type,const Utils::_variable_type arg_type)13137 unaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13138 const Utils::_variable_type res_type, const Utils::_variable_type arg_type)
13139 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13140 {
13141 }
13142
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13143 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13144 {
13145 glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(m_arg_type);
13146 ResT* p_result = (ResT*)result_dst;
13147 glw::GLdouble* p_arg = (glw::GLdouble*)argument_src;
13148
13149 functionPointer p_function = (functionPointer)m_p_function;
13150
13151 for (glw::GLuint component = 0; component < n_components; ++component)
13152 {
13153 p_result[component] = p_function(p_arg[component]);
13154 }
13155 }
13156 };
13157
13158 /** Class of functions with one input and one output parameter. It treats arguments as separate components.
13159 *
13160 * @tparam ResT Type of result
13161 * @tparam ArgT Type of argument
13162 * @tparam OutT Type of output parameter
13163 **/
13164 template <typename ResT, typename ArgT, typename OutT>
13165 class unaryWithOutputByComponent : public unaryBase
13166 {
13167 public:
13168 typedef ResT (*functionPointer)(ArgT, OutT&);
13169
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)13170 unaryWithOutputByComponent(FunctionEnum function_enum, const glw::GLchar* function_name,
13171 functionPointer function_pointer, const Utils::_variable_type res_type,
13172 const Utils::_variable_type arg_type, const Utils::_variable_type out_type)
13173 : unaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_type)
13174 , m_out_type(out_type)
13175 {
13176 }
13177
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13178 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13179 {
13180 ResT* p_result = (ResT*)result_dst;
13181 OutT* p_out = (OutT*)((glw::GLubyte*)result_dst + getResultOffset(1));
13182 ArgT* p_arg = (ArgT*)argument_src;
13183
13184 const glw::GLuint n_components_0 = getArgumentComponents(0);
13185 const glw::GLuint n_components_1 = getResultComponents(1);
13186 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13187
13188 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13189 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13190
13191 functionPointer p_function = (functionPointer)m_p_function;
13192
13193 for (glw::GLuint component = 0; component < n_components; ++component)
13194 {
13195 const ArgT first_arg = p_arg[component * component_step_0];
13196 OutT& second_arg = p_out[component * component_step_1];
13197
13198 p_result[component] = p_function(first_arg, second_arg);
13199 }
13200 }
13201
getResultCount() const13202 glw::GLuint getResultCount() const
13203 {
13204 return 2;
13205 }
13206
getResultType(glw::GLuint result) const13207 Utils::_variable_type getResultType(glw::GLuint result) const
13208 {
13209 Utils::_variable_type type = Utils::VARIABLE_TYPE_UNKNOWN;
13210
13211 switch (result)
13212 {
13213 case 0:
13214 type = m_res_type;
13215 break;
13216 case 1:
13217 type = m_out_type;
13218 break;
13219 default:
13220 TCU_FAIL("Not implemented");
13221 break;
13222 }
13223
13224 return type;
13225 }
13226
13227 protected:
13228 const Utils::_variable_type m_out_type;
13229 };
13230
13231 /** Base of binary function classes.
13232 *
13233 **/
13234 class binaryBase : public BuiltinFunctionTest::functionObject
13235 {
13236 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)13237 binaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13238 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13239 const Utils::_variable_type arg_2_type)
13240 : functionObject(function_enum, function_name, function_pointer, res_type)
13241 , m_arg_1_type(arg_1_type)
13242 , m_arg_2_type(arg_2_type)
13243 {
13244 }
13245
getArgumentCount() const13246 virtual glw::GLuint getArgumentCount() const
13247 {
13248 return 2;
13249 }
13250
getArgumentType(glw::GLuint argument) const13251 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13252 {
13253 switch (argument)
13254 {
13255 case 0:
13256 return m_arg_1_type;
13257 case 1:
13258 return m_arg_2_type;
13259 default:
13260 return Utils::VARIABLE_TYPE_UNKNOWN;
13261 }
13262 }
13263
13264 protected:
13265 const Utils::_variable_type m_arg_1_type;
13266 const Utils::_variable_type m_arg_2_type;
13267 };
13268
13269 /** Binary function class. It treats input arguments as two variables.
13270 *
13271 * @param ResT Type of result
13272 * @param Arg1T Type of first argument
13273 * @param Arg2T Type of second argument
13274 **/
13275 template <typename ResT, typename Arg1T, typename Arg2T>
13276 class binary : public binaryBase
13277 {
13278 public:
13279 typedef ResT (*functionPointer)(const Arg1T&, const Arg2T&);
13280
binary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13281 binary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13282 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13283 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type)
13284 {
13285 }
13286
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13287 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13288 {
13289 const glw::GLuint argument_1_stride = getArgumentStride(0);
13290
13291 functionPointer p_function = (functionPointer)m_p_function;
13292
13293 Arg1T arg_1;
13294 Arg2T arg_2;
13295 ResT result;
13296
13297 unpack<Arg1T>::get(argument_src, arg_1);
13298 unpack<Arg2T>::get((glw::GLubyte*)argument_src + argument_1_stride, arg_2);
13299
13300 result = p_function(arg_1, arg_2);
13301
13302 pack<ResT>::set(result_dst, result);
13303 }
13304 };
13305
13306 /** Binary function class. It treats input arguments as separate components.
13307 *
13308 * @param ResT Type of result
13309 * @param Arg1T Type of first argument
13310 * @param Arg2T Type of second argument
13311 **/
13312 template <typename ResT, typename Arg1T, typename Arg2T>
13313 class binaryByComponent : public binaryBase
13314 {
13315 public:
13316 typedef ResT (*functionPointer)(Arg1T, Arg2T);
13317
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)13318 binaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13319 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13320 const Utils::_variable_type arg_2_type)
13321 : binaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type)
13322 {
13323 }
13324
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13325 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13326 {
13327 ResT* p_result = (ResT*)result_dst;
13328 Arg1T* p_arg_1 = (Arg1T*)argument_src;
13329 Arg2T* p_arg_2 = (Arg2T*)((glw::GLubyte*)argument_src + getArgumentOffset(1));
13330
13331 const glw::GLuint n_components_0 = getArgumentComponents(0);
13332 const glw::GLuint n_components_1 = getArgumentComponents(1);
13333 const glw::GLuint n_components = de::max(n_components_0, n_components_1);
13334
13335 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13336 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13337
13338 functionPointer p_function = (functionPointer)m_p_function;
13339
13340 for (glw::GLuint component = 0; component < n_components; ++component)
13341 {
13342 const Arg1T first_arg = p_arg_1[component * component_step_0];
13343 const Arg2T second_arg = p_arg_2[component * component_step_1];
13344
13345 p_result[component] = p_function(first_arg, second_arg);
13346 }
13347 }
13348 };
13349
13350 /** Base of tenary function classes.
13351 *
13352 **/
13353 class tenaryBase : public BuiltinFunctionTest::functionObject
13354 {
13355 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)13356 tenaryBase(FunctionEnum function_enum, const glw::GLchar* function_name, glw::GLvoid* function_pointer,
13357 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13358 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13359 : functionObject(function_enum, function_name, function_pointer, res_type)
13360 , m_arg_1_type(arg_1_type)
13361 , m_arg_2_type(arg_2_type)
13362 , m_arg_3_type(arg_3_type)
13363 {
13364 }
13365
getArgumentCount() const13366 virtual glw::GLuint getArgumentCount() const
13367 {
13368 return 3;
13369 }
13370
getArgumentType(glw::GLuint argument) const13371 virtual Utils::_variable_type getArgumentType(glw::GLuint argument) const
13372 {
13373 switch (argument)
13374 {
13375 case 0:
13376 return m_arg_1_type;
13377 case 1:
13378 return m_arg_2_type;
13379 case 2:
13380 return m_arg_3_type;
13381 default:
13382 return Utils::VARIABLE_TYPE_UNKNOWN;
13383 }
13384 }
13385
13386 protected:
13387 const Utils::_variable_type m_arg_1_type;
13388 const Utils::_variable_type m_arg_2_type;
13389 const Utils::_variable_type m_arg_3_type;
13390 };
13391
13392 /** Tenary function class. It treats input arguments as three variables.
13393 *
13394 * @param ResT Type of result
13395 * @param Arg1T Type of first argument
13396 * @param Arg2T Type of second argument
13397 * @param Arg3T Type of third argument
13398 **/
13399 template <typename ResT, typename Arg1T, typename Arg2T, typename Arg3T>
13400 class tenary : public tenaryBase
13401 {
13402 public:
13403 typedef ResT (*functionPointer)(Arg1T, Arg2T, Arg3T);
13404 typedef typename TypeHelpers::referenceToType<Arg1T>::result arg1T;
13405 typedef typename TypeHelpers::referenceToType<Arg2T>::result arg2T;
13406 typedef typename TypeHelpers::referenceToType<Arg3T>::result arg3T;
13407
tenary(FunctionEnum function_enum,const glw::GLchar * function_name,functionPointer function_pointer)13408 tenary(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer)
13409 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, typeInfo<ResT>::variable_type,
13410 typeInfo<Arg1T>::variable_type, typeInfo<Arg2T>::variable_type, typeInfo<Arg3T>::variable_type)
13411 {
13412 }
13413
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13414 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13415 {
13416 const glw::GLuint argument_2_offset = getArgumentOffset(1);
13417 const glw::GLuint argument_3_offset = getArgumentOffset(2);
13418
13419 functionPointer p_function = (functionPointer)m_p_function;
13420
13421 arg1T arg_1;
13422 arg2T arg_2;
13423 arg3T arg_3;
13424 ResT result;
13425
13426 unpack<arg1T>::get(argument_src, arg_1);
13427 unpack<arg2T>::get((glw::GLubyte*)argument_src + argument_2_offset, arg_2);
13428 unpack<arg3T>::get((glw::GLubyte*)argument_src + argument_3_offset, arg_3);
13429
13430 result = p_function(arg_1, arg_2, arg_3);
13431
13432 pack<ResT>::set(result_dst, result);
13433 }
13434 };
13435
13436 /** Tenary function class. It treats input arguments as separate components.
13437 *
13438
13439 **/
13440 class tenaryByComponent : public tenaryBase
13441 {
13442 public:
13443 typedef glw::GLdouble (*functionPointer)(glw::GLdouble, glw::GLdouble, glw::GLdouble);
13444
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)13445 tenaryByComponent(FunctionEnum function_enum, const glw::GLchar* function_name, functionPointer function_pointer,
13446 const Utils::_variable_type res_type, const Utils::_variable_type arg_1_type,
13447 const Utils::_variable_type arg_2_type, const Utils::_variable_type arg_3_type)
13448 : tenaryBase(function_enum, function_name, (glw::GLvoid*)function_pointer, res_type, arg_1_type, arg_2_type,
13449 arg_3_type)
13450 {
13451 }
13452
call(glw::GLvoid * result_dst,const glw::GLvoid * argument_src) const13453 virtual void call(glw::GLvoid* result_dst, const glw::GLvoid* argument_src) const
13454 {
13455 glw::GLdouble* p_result = (glw::GLdouble*)result_dst;
13456 const glw::GLdouble* p_arg = (const glw::GLdouble*)argument_src;
13457
13458 const glw::GLuint n_components_0 = getArgumentComponents(0);
13459 const glw::GLuint n_components_1 = getArgumentComponents(1);
13460 const glw::GLuint n_components_2 = getArgumentComponents(2);
13461 const glw::GLuint n_components = de::max(de::max(n_components_0, n_components_1), n_components_2);
13462
13463 const glw::GLuint component_step_0 = (1 == n_components_0) ? 0 : 1;
13464 const glw::GLuint component_step_1 = (1 == n_components_1) ? 0 : 1;
13465 const glw::GLuint component_step_2 = (1 == n_components_2) ? 0 : 1;
13466
13467 functionPointer p_function = (functionPointer)m_p_function;
13468
13469 for (glw::GLuint component = 0; component < n_components; ++component)
13470 {
13471 const glw::GLdouble first_arg = p_arg[component * component_step_0];
13472 const glw::GLdouble second_arg = p_arg[component * component_step_1 + n_components_0];
13473 const glw::GLdouble third_arg = p_arg[component * component_step_2 + n_components_0 + n_components_1];
13474
13475 p_result[component] = p_function(first_arg, second_arg, third_arg);
13476 }
13477 }
13478 };
13479 } /* FunctionObject */
13480
13481 /** Constructor.
13482 *
13483 * @param context Rendering context.
13484 **/
BuiltinFunctionTest(deqp::Context & context,std::string caseName,FunctionEnum function,TypeDefinition typeDefinition)13485 BuiltinFunctionTest::BuiltinFunctionTest(deqp::Context& context, std::string caseName, FunctionEnum function,
13486 TypeDefinition typeDefinition)
13487 : TestCase(context, caseName.c_str(), "Verify that built-in functions support double-precision types")
13488 , m_transform_feedback_buffer_id(0)
13489 , m_vertex_array_object_id(0)
13490 , m_function(function)
13491 , m_typeDefinition(typeDefinition)
13492 {
13493 /* Nothing to be done here */
13494 }
13495
13496 /** Deinitializes all GL objects that may have been created during test execution.
13497 *
13498 **/
deinit()13499 void BuiltinFunctionTest::deinit()
13500 {
13501 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
13502
13503 /* Clean buffers */
13504 if (0 != m_transform_feedback_buffer_id)
13505 {
13506 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
13507 gl.deleteBuffers(1, &m_transform_feedback_buffer_id);
13508 m_transform_feedback_buffer_id = 0;
13509 }
13510
13511 /* Clean VAO */
13512 if (0 != m_vertex_array_object_id)
13513 {
13514 gl.bindVertexArray(0);
13515 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
13516 m_vertex_array_object_id = 0;
13517 }
13518 }
13519
13520 /** Execute test
13521 *
13522 * @return tcu::TestNode::STOP
13523 **/
iterate()13524 tcu::TestNode::IterateResult BuiltinFunctionTest::iterate()
13525 {
13526 /* Check if extension is supported */
13527 if (false == m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader_fp64"))
13528 {
13529 throw tcu::NotSupportedError("GL_ARB_gpu_shader_fp64 is not supported");
13530 }
13531
13532 testInit();
13533
13534 /* Verify result */
13535 typeDetails type(m_typeDefinition.n_columns, m_typeDefinition.n_rows);
13536 if (test(m_function, type))
13537 {
13538 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
13539 }
13540 else
13541 {
13542 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
13543 }
13544
13545 /* Done */
13546 return tcu::TestNode::STOP;
13547 }
13548
13549 /** Constructor
13550 *
13551 * @param function_enum Function enumeration
13552 * @param function_name Function name
13553 * @param function_pointer Pointer to routine that wiil be executed
13554 * @param result_type Type of result
13555 **/
functionObject(FunctionEnum function_enum,const glw::GLchar * function_name,glw::GLvoid * function_pointer,Utils::_variable_type result_type)13556 BuiltinFunctionTest::functionObject::functionObject(FunctionEnum function_enum, const glw::GLchar* function_name,
13557 glw::GLvoid* function_pointer, Utils::_variable_type result_type)
13558 : m_function_enum(function_enum)
13559 , m_function_name(function_name)
13560 , m_p_function(function_pointer)
13561 , m_res_type(result_type)
13562 {
13563 /* Nothing to be done here */
13564 }
13565
13566 /** Get number of components for <argument>
13567 *
13568 * @param argument Argument ordinal, starts with 0
13569 *
13570 * @return Number of components
13571 **/
getArgumentComponents(glw::GLuint argument) const13572 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponents(glw::GLuint argument) const
13573 {
13574 const Utils::_variable_type type = getArgumentType(argument);
13575 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13576
13577 return n_components;
13578 }
13579
13580 /** Get size in bytes of single component of <argument>
13581 *
13582 * @param argument Argument ordinal, starts with 0
13583 *
13584 * @return Size of component
13585 **/
getArgumentComponentSize(glw::GLuint argument) const13586 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentComponentSize(glw::GLuint argument) const
13587 {
13588 const Utils::_variable_type type = getArgumentType(argument);
13589 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13590 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13591
13592 return base_type_size;
13593 }
13594
13595 /** Get offset in bytes of <argument>. 0 is offset of first argument. Assumes tight packing.
13596 *
13597 * @param argument Argument ordinal, starts with 0
13598 *
13599 * @return Offset of arguemnt's data
13600 **/
getArgumentOffset(glw::GLuint argument) const13601 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentOffset(glw::GLuint argument) const
13602 {
13603 glw::GLuint result = 0;
13604
13605 for (glw::GLuint i = 0; i < argument; ++i)
13606 {
13607 result += getArgumentStride(i);
13608 }
13609
13610 return result;
13611 }
13612
13613 /** Get stride in bytes of all arguments
13614 *
13615 * @return Stride of all arguments
13616 **/
getArgumentStride() const13617 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride() const
13618 {
13619 const glw::GLuint n_args = getArgumentCount();
13620 glw::GLuint result = 0;
13621
13622 for (glw::GLuint i = 0; i < n_args; ++i)
13623 {
13624 result += getArgumentStride(i);
13625 }
13626
13627 return result;
13628 }
13629
13630 /** Get stride in bytes of <argument>
13631 *
13632 * @param argument Argument ordinal, starts with 0
13633 *
13634 * @return Stride of argument
13635 **/
getArgumentStride(glw::GLuint argument) const13636 glw::GLuint BuiltinFunctionTest::functionObject::getArgumentStride(glw::GLuint argument) const
13637 {
13638 const glw::GLuint component_size = getArgumentComponentSize(argument);
13639 const glw::GLuint n_components = getArgumentComponents(argument);
13640
13641 return n_components * component_size;
13642 }
13643
13644 /** Get function enumeration
13645 *
13646 * @return Function enumeration
13647 **/
getFunctionEnum() const13648 FunctionEnum BuiltinFunctionTest::functionObject::getFunctionEnum() const
13649 {
13650 return m_function_enum;
13651 }
13652
13653 /** Get function name
13654 *
13655 * @return Function name
13656 **/
getName() const13657 const glw::GLchar* BuiltinFunctionTest::functionObject::getName() const
13658 {
13659 return m_function_name;
13660 }
13661
13662 /** Get number of components for <result>
13663 *
13664 * @param result Result ordinal, starts with 0
13665 *
13666 * @return Number of components
13667 **/
getResultComponents(glw::GLuint result) const13668 glw::GLuint BuiltinFunctionTest::functionObject::getResultComponents(glw::GLuint result) const
13669 {
13670 const Utils::_variable_type type = getResultType(result);
13671 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13672
13673 return n_components;
13674 }
13675
13676 /** Get number of results
13677 *
13678 * @return Number of results
13679 **/
getResultCount() const13680 glw::GLuint BuiltinFunctionTest::functionObject::getResultCount() const
13681 {
13682 return 1;
13683 }
13684
13685 /** Get offset in bytes of <result>. First result offset is 0. Assume tight packing.
13686 *
13687 * @param result Result ordinal, starts with 0
13688 *
13689 * @return Offset
13690 **/
getResultOffset(glw::GLuint result) const13691 glw::GLuint BuiltinFunctionTest::functionObject::getResultOffset(glw::GLuint result) const
13692 {
13693 glw::GLuint offset = 0;
13694
13695 for (glw::GLuint i = 0; i < result; ++i)
13696 {
13697 offset += getResultStride(i);
13698 offset = deAlign32(offset, getBaseTypeSize(i));
13699 }
13700
13701 return offset;
13702 }
13703
13704 /** Get stride in bytes of <result>.
13705 *
13706 * @param result Result ordinal, starts with 0
13707 *
13708 * @return Stride
13709 **/
getResultStride(glw::GLuint result) const13710 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride(glw::GLuint result) const
13711 {
13712 const Utils::_variable_type type = getResultType(result);
13713 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13714
13715 return n_components * getBaseTypeSize(result);
13716 }
13717
13718 /** Get size in bytes of <result> base component.
13719 *
13720 * @param result Result ordinal, starts with 0
13721 *
13722 * @return Alignment
13723 **/
getBaseTypeSize(glw::GLuint result) const13724 glw::GLuint BuiltinFunctionTest::functionObject::getBaseTypeSize(glw::GLuint result) const
13725 {
13726 const Utils::_variable_type type = getResultType(result);
13727 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13728 const glw::GLuint base_type_size = Utils::getBaseVariableTypeComponentSize(base_type);
13729
13730 return base_type_size;
13731 }
13732
13733 /** Get stride in bytes of all results.
13734 *
13735 * @return Stride
13736 **/
getResultStride() const13737 glw::GLuint BuiltinFunctionTest::functionObject::getResultStride() const
13738 {
13739 const glw::GLuint n_results = getResultCount();
13740 glw::GLuint stride = 0;
13741 glw::GLuint maxAlignment = 0;
13742
13743 for (glw::GLuint i = 0; i < n_results; ++i)
13744 {
13745 const glw::GLuint alignment = getBaseTypeSize(i);
13746 stride += getResultStride(i);
13747 stride = deAlign32(stride, alignment);
13748 maxAlignment = deMaxu32(maxAlignment, alignment);
13749 }
13750
13751 // The stride of all results must also be aligned,
13752 // so results for next vertex are aligned.
13753 return deAlign32(stride, maxAlignment);
13754 }
13755
13756 /** Get type of <result>.
13757 *
13758 * @param result Result ordinal, starts with 0
13759 *
13760 * @return Type
13761 **/
getResultType(glw::GLuint) const13762 Utils::_variable_type BuiltinFunctionTest::functionObject::getResultType(glw::GLuint /* result */) const
13763 {
13764 return m_res_type;
13765 }
13766
13767 /** Constructor
13768 *
13769 * @param n_columns Number of columns
13770 * @param n_rows Number of rows
13771 **/
typeDetails(glw::GLuint n_columns,glw::GLuint n_rows)13772 BuiltinFunctionTest::typeDetails::typeDetails(glw::GLuint n_columns, glw::GLuint n_rows)
13773 : m_n_columns(n_columns), m_n_rows(n_rows)
13774 {
13775 Utils::_variable_type type = Utils::getDoubleVariableType(n_columns, n_rows);
13776 m_type = Utils::getGLDataTypeOfVariableType(type);
13777 m_type_name = Utils::getVariableTypeString(type);
13778
13779 if (1 == m_n_columns)
13780 {
13781 if (1 == m_n_rows)
13782 {
13783 m_general_type = SCALAR;
13784 }
13785 else
13786 {
13787 m_general_type = VECTOR;
13788 }
13789 }
13790 else
13791 {
13792 m_general_type = MATRIX;
13793 }
13794 }
13795
13796 /** Compare two values
13797 *
13798 * @param type Type of values
13799 * @param left Pointer to left value
13800 * @param right Pointer to right value
13801 *
13802 * @return true if values are equal, false otherwise
13803 **/
compare(Utils::_variable_type type,const glw::GLvoid * left,const glw::GLvoid * right)13804 bool BuiltinFunctionTest::compare(Utils::_variable_type type, const glw::GLvoid* left, const glw::GLvoid* right)
13805 {
13806 bool result = true;
13807
13808 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
13809 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
13810
13811 switch (base_type)
13812 {
13813 case Utils::VARIABLE_TYPE_DOUBLE:
13814
13815 {
13816 const glw::GLdouble* left_values = (glw::GLdouble*)left;
13817 const glw::GLdouble* right_values = (glw::GLdouble*)right;
13818
13819 for (glw::GLuint component = 0; component < n_components; ++component)
13820 {
13821 const glw::GLdouble left_value = left_values[component];
13822 const glw::GLdouble right_value = right_values[component];
13823
13824 if ((left_value != right_value) && (m_epsilon < de::abs(left_value - right_value)) &&
13825 (0 == Math::isnan_impl(left_value)) && (0 == Math::isnan_impl(right_value)))
13826 {
13827 result = false;
13828 break;
13829 }
13830 }
13831 }
13832
13833 break;
13834
13835 case Utils::VARIABLE_TYPE_INT:
13836
13837 {
13838 const glw::GLint* left_values = (glw::GLint*)left;
13839 const glw::GLint* right_values = (glw::GLint*)right;
13840
13841 for (glw::GLuint component = 0; component < n_components; ++component)
13842 {
13843 const glw::GLint left_value = left_values[component];
13844 const glw::GLint right_value = right_values[component];
13845
13846 if (left_value != right_value)
13847 {
13848 result = false;
13849 break;
13850 }
13851 }
13852 }
13853
13854 break;
13855
13856 case Utils::VARIABLE_TYPE_UINT:
13857
13858 {
13859 const glw::GLuint* left_values = (glw::GLuint*)left;
13860 const glw::GLuint* right_values = (glw::GLuint*)right;
13861
13862 for (glw::GLuint component = 0; component < n_components; ++component)
13863 {
13864 const glw::GLuint left_value = left_values[component];
13865 const glw::GLuint right_value = right_values[component];
13866
13867 if (left_value != right_value)
13868 {
13869 result = false;
13870 break;
13871 }
13872 }
13873 }
13874
13875 break;
13876
13877 default:
13878
13879 TCU_FAIL("Not implemented");
13880 }
13881
13882 return result;
13883 }
13884
13885 /** Create instance of function object for given function enumeration and type
13886 *
13887 * @param function Function enumeration
13888 * @param type Type details
13889 *
13890 * @return Create object
13891 **/
getFunctionObject(FunctionEnum function,const typeDetails & type)13892 BuiltinFunctionTest::functionObject* BuiltinFunctionTest::getFunctionObject(FunctionEnum function,
13893 const typeDetails& type)
13894 {
13895 typedef tcu::Matrix<glw::GLdouble, 2, 2> DMat2;
13896 typedef tcu::Matrix<glw::GLdouble, 3, 2> DMat2x3;
13897 typedef tcu::Matrix<glw::GLdouble, 4, 2> DMat2x4;
13898 typedef tcu::Matrix<glw::GLdouble, 2, 3> DMat3x2;
13899 typedef tcu::Matrix<glw::GLdouble, 3, 3> DMat3;
13900 typedef tcu::Matrix<glw::GLdouble, 4, 3> DMat3x4;
13901 typedef tcu::Matrix<glw::GLdouble, 2, 4> DMat4x2;
13902 typedef tcu::Matrix<glw::GLdouble, 3, 4> DMat4x3;
13903 typedef tcu::Matrix<glw::GLdouble, 4, 4> DMat4;
13904
13905 const glw::GLuint n_columns = type.m_n_columns;
13906 const glw::GLuint n_rows = type.m_n_rows;
13907 const Utils::_variable_type scalar_type = Utils::getDoubleVariableType(1, 1);
13908 const Utils::_variable_type variable_type = Utils::getDoubleVariableType(n_columns, n_rows);
13909 const Utils::_variable_type uint_type = Utils::getUintVariableType(1, n_rows);
13910 const Utils::_variable_type int_type = Utils::getIntVariableType(1, n_rows);
13911
13912 switch (function)
13913 {
13914 case FUNCTION_ABS:
13915
13916 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13917 function, "abs", de::abs, variable_type /* res_type */, variable_type /* arg_type */);
13918
13919 case FUNCTION_CEIL:
13920
13921 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
13922 function, "ceil", ceil, variable_type /* res_type */, variable_type /* arg_type */);
13923
13924 case FUNCTION_CLAMP:
13925
13926 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13927 variable_type /* arg1_type */, variable_type /* arg2_type */,
13928 variable_type /* arg3_type */);
13929
13930 case FUNCTION_CLAMP_AGAINST_SCALAR:
13931
13932 return new FunctionObject::tenaryByComponent(function, "clamp", Math::clamp, variable_type /* res_type */,
13933 variable_type /* arg1_type */, scalar_type /* arg2_type */,
13934 scalar_type /* arg3_type */);
13935
13936 case FUNCTION_CROSS:
13937
13938 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13939 function, "cross", tcu::cross);
13940
13941 case FUNCTION_DETERMINANT:
13942
13943 switch (variable_type)
13944 {
13945 case Utils::VARIABLE_TYPE_DMAT2:
13946 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat2 /* ArgT */>(function, "determinant",
13947 Math::determinant);
13948 case Utils::VARIABLE_TYPE_DMAT3:
13949 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat3 /* ArgT */>(function, "determinant",
13950 Math::determinant);
13951 case Utils::VARIABLE_TYPE_DMAT4:
13952 return new FunctionObject::unary<glw::GLdouble /* ResT */, DMat4 /* ArgT */>(function, "determinant",
13953 Math::determinant);
13954 default:
13955 TCU_FAIL("Not implemented");
13956 }
13957
13958 case FUNCTION_DISTANCE:
13959
13960 switch (variable_type)
13961 {
13962 case Utils::VARIABLE_TYPE_DVEC2:
13963 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13964 function, "distance", tcu::distance);
13965 case Utils::VARIABLE_TYPE_DVEC3:
13966 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13967 function, "distance", tcu::distance);
13968 case Utils::VARIABLE_TYPE_DVEC4:
13969 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13970 function, "distance", tcu::distance);
13971 default:
13972 break;
13973 }
13974
13975 break;
13976
13977 case FUNCTION_DOT:
13978
13979 switch (variable_type)
13980 {
13981 case Utils::VARIABLE_TYPE_DVEC2:
13982 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
13983 function, "dot", tcu::dot);
13984 case Utils::VARIABLE_TYPE_DVEC3:
13985 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
13986 function, "dot", tcu::dot);
13987 case Utils::VARIABLE_TYPE_DVEC4:
13988 return new FunctionObject::binary<glw::GLdouble /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
13989 function, "dot", tcu::dot);
13990 default:
13991 break;
13992 }
13993
13994 break;
13995
13996 case FUNCTION_EQUAL:
13997
13998 switch (variable_type)
13999 {
14000 case Utils::VARIABLE_TYPE_DVEC2:
14001 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14002 function, "equal", Math::equal);
14003 case Utils::VARIABLE_TYPE_DVEC3:
14004 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14005 function, "equal", Math::equal);
14006 case Utils::VARIABLE_TYPE_DVEC4:
14007 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14008 function, "equal", Math::equal);
14009 default:
14010 break;
14011 }
14012
14013 break;
14014
14015 case FUNCTION_FACEFORWARD:
14016
14017 switch (variable_type)
14018 {
14019 case Utils::VARIABLE_TYPE_DVEC2:
14020 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14021 const tcu::DVec2& /* Arg2T */, const tcu::DVec2& /* Arg3T */>(
14022 function, "faceforward", tcu::faceForward);
14023 case Utils::VARIABLE_TYPE_DVEC3:
14024 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14025 const tcu::DVec3& /* Arg2T */, const tcu::DVec3& /* Arg3T */>(
14026 function, "faceforward", tcu::faceForward);
14027 case Utils::VARIABLE_TYPE_DVEC4:
14028 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14029 const tcu::DVec4& /* Arg2T */, const tcu::DVec4& /* Arg3T */>(
14030 function, "faceforward", tcu::faceForward);
14031 default:
14032 break;
14033 }
14034
14035 break;
14036
14037 case FUNCTION_FLOOR:
14038
14039 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14040 function, "floor", floor, variable_type /* res_type */, variable_type /* arg_type */);
14041
14042 case FUNCTION_FMA:
14043
14044 return new FunctionObject::tenaryByComponent(function, "fma", Math::fma, variable_type /* res_type */,
14045 variable_type /* arg1_type */, variable_type /* arg2_type */,
14046 variable_type /* arg3_type */);
14047
14048 case FUNCTION_FRACT:
14049
14050 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14051 function, "fract", Math::fract, variable_type /* res_type */, variable_type /* arg_type */);
14052
14053 case FUNCTION_FREXP:
14054
14055 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14056 glw::GLint /* OutT */>(
14057 function, "frexp", Math::frexp, variable_type /* res_type */, variable_type /* arg_type */,
14058 int_type /* out_type */);
14059
14060 case FUNCTION_GREATERTHAN:
14061
14062 switch (variable_type)
14063 {
14064 case Utils::VARIABLE_TYPE_DVEC2:
14065 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14066 function, "greaterThan", Math::greaterThan);
14067 case Utils::VARIABLE_TYPE_DVEC3:
14068 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14069 function, "greaterThan", Math::greaterThan);
14070 case Utils::VARIABLE_TYPE_DVEC4:
14071 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14072 function, "greaterThan", Math::greaterThan);
14073 default:
14074 break;
14075 }
14076
14077 break;
14078
14079 case FUNCTION_GREATERTHANEQUAL:
14080
14081 switch (variable_type)
14082 {
14083 case Utils::VARIABLE_TYPE_DVEC2:
14084 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14085 function, "greaterThanEqual", Math::greaterThanEqual);
14086 case Utils::VARIABLE_TYPE_DVEC3:
14087 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14088 function, "greaterThanEqual", Math::greaterThanEqual);
14089 case Utils::VARIABLE_TYPE_DVEC4:
14090 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14091 function, "greaterThanEqual", Math::greaterThanEqual);
14092 default:
14093 break;
14094 }
14095
14096 break;
14097
14098 case FUNCTION_INVERSE:
14099
14100 switch (variable_type)
14101 {
14102 case Utils::VARIABLE_TYPE_DMAT2:
14103 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "inverse", Math::inverse);
14104 case Utils::VARIABLE_TYPE_DMAT3:
14105 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "inverse", Math::inverse);
14106 case Utils::VARIABLE_TYPE_DMAT4:
14107 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "inverse", Math::inverse);
14108 default:
14109 break;
14110 }
14111
14112 break;
14113
14114 case FUNCTION_INVERSESQRT:
14115
14116 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14117 function, "inversesqrt", Math::inverseSqrt, variable_type /* res_type */, variable_type /* arg_type */);
14118
14119 case FUNCTION_LDEXP:
14120
14121 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14122 glw::GLint /* Arg2T */>(
14123 function, "ldexp", ::ldexp, variable_type /* res_type */, variable_type /* arg1_type */,
14124 int_type /* arg2_type */);
14125
14126 case FUNCTION_LESSTHAN:
14127
14128 switch (variable_type)
14129 {
14130 case Utils::VARIABLE_TYPE_DVEC2:
14131 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14132 function, "lessThan", Math::lessThan);
14133 case Utils::VARIABLE_TYPE_DVEC3:
14134 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14135 function, "lessThan", Math::lessThan);
14136 case Utils::VARIABLE_TYPE_DVEC4:
14137 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14138 function, "lessThan", Math::lessThan);
14139 default:
14140 break;
14141 }
14142
14143 break;
14144
14145 case FUNCTION_LESSTHANEQUAL:
14146
14147 switch (variable_type)
14148 {
14149 case Utils::VARIABLE_TYPE_DVEC2:
14150 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14151 function, "lessThanEqual", Math::lessThanEqual);
14152 case Utils::VARIABLE_TYPE_DVEC3:
14153 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14154 function, "lessThanEqual", Math::lessThanEqual);
14155 case Utils::VARIABLE_TYPE_DVEC4:
14156 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14157 function, "lessThanEqual", Math::lessThanEqual);
14158 default:
14159 break;
14160 }
14161
14162 break;
14163
14164 case FUNCTION_LENGTH:
14165
14166 switch (variable_type)
14167 {
14168 case Utils::VARIABLE_TYPE_DVEC2:
14169 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec2 /* ArgT */>(function, "length",
14170 tcu::length);
14171 case Utils::VARIABLE_TYPE_DVEC3:
14172 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec3 /* ArgT */>(function, "length",
14173 tcu::length);
14174 case Utils::VARIABLE_TYPE_DVEC4:
14175 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::DVec4 /* ArgT */>(function, "length",
14176 tcu::length);
14177 default:
14178 break;
14179 }
14180
14181 break;
14182
14183 case FUNCTION_MATRIXCOMPMULT:
14184
14185 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14186 glw::GLdouble /* Arg2T */>(
14187 function, "matrixCompMult", Math::multiply, variable_type /* res_type */, variable_type /* arg1_type */,
14188 variable_type /* arg2_type */);
14189
14190 case FUNCTION_MAX:
14191
14192 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14193 glw::GLdouble /* Arg2T */>(
14194 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14195 variable_type /* arg2_type */);
14196
14197 case FUNCTION_MAX_AGAINST_SCALAR:
14198
14199 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14200 glw::GLdouble /* Arg2T */>(
14201 function, "max", Math::max, variable_type /* res_type */, variable_type /* arg1_type */,
14202 scalar_type /* arg2_type */);
14203
14204 case FUNCTION_MIN:
14205
14206 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14207 glw::GLdouble /* Arg2T */>(
14208 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14209 variable_type /* arg2_type */);
14210
14211 case FUNCTION_MIN_AGAINST_SCALAR:
14212
14213 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14214 glw::GLdouble /* Arg2T */>(
14215 function, "min", Math::min, variable_type /* res_type */, variable_type /* arg1_type */,
14216 scalar_type /* arg2_type */);
14217
14218 case FUNCTION_MIX:
14219
14220 return new FunctionObject::tenaryByComponent(function, "mix", Math::mix, variable_type /* res_type */,
14221 variable_type /* arg1_type */, variable_type /* arg2_type */,
14222 variable_type /* arg3_type */);
14223
14224 case FUNCTION_MOD:
14225
14226 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14227 glw::GLdouble /* Arg2T */>(
14228 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14229 variable_type /* arg2_type */);
14230
14231 case FUNCTION_MOD_AGAINST_SCALAR:
14232
14233 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14234 glw::GLdouble /* Arg2T */>(
14235 function, "mod", Math::mod, variable_type /* res_type */, variable_type /* arg1_type */,
14236 scalar_type /* arg2_type */);
14237
14238 case FUNCTION_MODF:
14239
14240 return new FunctionObject::unaryWithOutputByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* ArgT */,
14241 glw::GLdouble /* OutT */>(
14242 function, "modf", Math::modf, variable_type /* res_type */, variable_type /* arg_type */,
14243 variable_type /* out_type */);
14244
14245 case FUNCTION_NORMALIZE:
14246
14247 switch (variable_type)
14248 {
14249 case Utils::VARIABLE_TYPE_DVEC2:
14250 return new FunctionObject::unary<tcu::DVec2 /* ResT */, tcu::DVec2 /* ArgT */>(function, "normalize",
14251 tcu::normalize);
14252 case Utils::VARIABLE_TYPE_DVEC3:
14253 return new FunctionObject::unary<tcu::DVec3 /* ResT */, tcu::DVec3 /* ArgT */>(function, "normalize",
14254 tcu::normalize);
14255 case Utils::VARIABLE_TYPE_DVEC4:
14256 return new FunctionObject::unary<tcu::DVec4 /* ResT */, tcu::DVec4 /* ArgT */>(function, "normalize",
14257 tcu::normalize);
14258 default:
14259 break;
14260 }
14261
14262 break;
14263
14264 case FUNCTION_NOTEQUAL:
14265
14266 switch (variable_type)
14267 {
14268 case Utils::VARIABLE_TYPE_DVEC2:
14269 return new FunctionObject::binary<tcu::UVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14270 function, "notEqual", Math::notEqual);
14271 case Utils::VARIABLE_TYPE_DVEC3:
14272 return new FunctionObject::binary<tcu::UVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14273 function, "notEqual", Math::notEqual);
14274 case Utils::VARIABLE_TYPE_DVEC4:
14275 return new FunctionObject::binary<tcu::UVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14276 function, "notEqual", Math::notEqual);
14277 default:
14278 break;
14279 }
14280
14281 break;
14282
14283 case FUNCTION_OUTERPRODUCT:
14284
14285 switch (variable_type)
14286 {
14287 case Utils::VARIABLE_TYPE_DMAT2:
14288 return new FunctionObject::binary<DMat2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14289 function, "outerProduct", Math::outerProduct);
14290 case Utils::VARIABLE_TYPE_DMAT2X3:
14291 return new FunctionObject::binary<DMat2x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14292 function, "outerProduct", Math::outerProduct);
14293 case Utils::VARIABLE_TYPE_DMAT2X4:
14294 return new FunctionObject::binary<DMat2x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14295 function, "outerProduct", Math::outerProduct);
14296 case Utils::VARIABLE_TYPE_DMAT3:
14297 return new FunctionObject::binary<DMat3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14298 function, "outerProduct", Math::outerProduct);
14299 case Utils::VARIABLE_TYPE_DMAT3X2:
14300 return new FunctionObject::binary<DMat3x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14301 function, "outerProduct", Math::outerProduct);
14302 case Utils::VARIABLE_TYPE_DMAT3X4:
14303 return new FunctionObject::binary<DMat3x4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14304 function, "outerProduct", Math::outerProduct);
14305 case Utils::VARIABLE_TYPE_DMAT4:
14306 return new FunctionObject::binary<DMat4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14307 function, "outerProduct", Math::outerProduct);
14308 case Utils::VARIABLE_TYPE_DMAT4X2:
14309 return new FunctionObject::binary<DMat4x2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14310 function, "outerProduct", Math::outerProduct);
14311 case Utils::VARIABLE_TYPE_DMAT4X3:
14312 return new FunctionObject::binary<DMat4x3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14313 function, "outerProduct", Math::outerProduct);
14314 default:
14315 break;
14316 }
14317
14318 break;
14319
14320 case FUNCTION_PACKDOUBLE2X32:
14321
14322 return new FunctionObject::unary<glw::GLdouble /* ResT */, tcu::UVec2 /* ArgT */>(function, "packDouble2x32",
14323 Math::packDouble2x32);
14324
14325 case FUNCTION_REFLECT:
14326
14327 switch (variable_type)
14328 {
14329 case Utils::VARIABLE_TYPE_DVEC2:
14330 return new FunctionObject::binary<tcu::DVec2 /* ResT */, tcu::DVec2 /* Arg1T */, tcu::DVec2 /* Arg2T */>(
14331 function, "reflect", tcu::reflect);
14332 case Utils::VARIABLE_TYPE_DVEC3:
14333 return new FunctionObject::binary<tcu::DVec3 /* ResT */, tcu::DVec3 /* Arg1T */, tcu::DVec3 /* Arg2T */>(
14334 function, "reflect", tcu::reflect);
14335 case Utils::VARIABLE_TYPE_DVEC4:
14336 return new FunctionObject::binary<tcu::DVec4 /* ResT */, tcu::DVec4 /* Arg1T */, tcu::DVec4 /* Arg2T */>(
14337 function, "reflect", tcu::reflect);
14338 default:
14339 break;
14340 }
14341
14342 break;
14343
14344 case FUNCTION_REFRACT:
14345
14346 switch (variable_type)
14347 {
14348 case Utils::VARIABLE_TYPE_DVEC2:
14349 return new FunctionObject::tenary<tcu::DVec2 /* ResT */, const tcu::DVec2& /* Arg1T */,
14350 const tcu::DVec2& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14351 function, "refract", tcu::refract);
14352 case Utils::VARIABLE_TYPE_DVEC3:
14353 return new FunctionObject::tenary<tcu::DVec3 /* ResT */, const tcu::DVec3& /* Arg1T */,
14354 const tcu::DVec3& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14355 function, "refract", tcu::refract);
14356 case Utils::VARIABLE_TYPE_DVEC4:
14357 return new FunctionObject::tenary<tcu::DVec4 /* ResT */, const tcu::DVec4& /* Arg1T */,
14358 const tcu::DVec4& /* Arg2T */, glw::GLdouble /* Arg3T */>(
14359 function, "refract", tcu::refract);
14360 default:
14361 break;
14362 }
14363
14364 break;
14365
14366 case FUNCTION_ROUND:
14367
14368 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14369 function, "round", Math::round, variable_type /* res_type */, variable_type /* arg_type */);
14370
14371 case FUNCTION_ROUNDEVEN:
14372
14373 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14374 function, "roundEven", Math::roundEven, variable_type /* res_type */, variable_type /* arg_type */);
14375
14376 case FUNCTION_SIGN:
14377
14378 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14379 function, "sign", Math::sign, variable_type /* res_type */, variable_type /* arg_type */);
14380
14381 case FUNCTION_SMOOTHSTEP:
14382
14383 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14384 variable_type /* res_type */, variable_type /* arg1_type */,
14385 variable_type /* arg2_type */, variable_type /* arg3_type */);
14386
14387 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14388
14389 return new FunctionObject::tenaryByComponent(function, "smoothstep", Math::smoothStep,
14390 variable_type /* res_type */, scalar_type /* arg1_type */,
14391 scalar_type /* arg2_type */, variable_type /* arg3_type */);
14392
14393 case FUNCTION_SQRT:
14394
14395 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14396 function, "sqrt", sqrt, variable_type /* res_type */, variable_type /* arg_type */);
14397
14398 case FUNCTION_STEP:
14399
14400 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14401 glw::GLdouble /* Arg2T */>(
14402 function, "step", Math::step, variable_type /* res_type */, variable_type /* arg1_type */,
14403 variable_type /* arg2_type */);
14404
14405 case FUNCTION_STEP_AGAINST_SCALAR:
14406
14407 return new FunctionObject::binaryByComponent<glw::GLdouble /* ResT */, glw::GLdouble /* Arg1T */,
14408 glw::GLdouble /* Arg2T */>(
14409 function, "step", Math::step, variable_type /* res_type */, scalar_type /* arg1_type */,
14410 variable_type /* arg2_type */);
14411
14412 case FUNCTION_TRANSPOSE:
14413
14414 switch (variable_type)
14415 {
14416 case Utils::VARIABLE_TYPE_DMAT2:
14417 return new FunctionObject::unary<DMat2 /* ResT */, DMat2 /* ArgT */>(function, "transpose",
14418 Math::transpose);
14419 case Utils::VARIABLE_TYPE_DMAT2X3:
14420 return new FunctionObject::unary<DMat2x3 /* ResT */, DMat3x2 /* ArgT */>(function, "transpose",
14421 Math::transpose);
14422 case Utils::VARIABLE_TYPE_DMAT2X4:
14423 return new FunctionObject::unary<DMat2x4 /* ResT */, DMat4x2 /* ArgT */>(function, "transpose",
14424 Math::transpose);
14425 case Utils::VARIABLE_TYPE_DMAT3:
14426 return new FunctionObject::unary<DMat3 /* ResT */, DMat3 /* ArgT */>(function, "transpose",
14427 Math::transpose);
14428 case Utils::VARIABLE_TYPE_DMAT3X2:
14429 return new FunctionObject::unary<DMat3x2 /* ResT */, DMat2x3 /* ArgT */>(function, "transpose",
14430 Math::transpose);
14431 case Utils::VARIABLE_TYPE_DMAT3X4:
14432 return new FunctionObject::unary<DMat3x4 /* ResT */, DMat4x3 /* ArgT */>(function, "transpose",
14433 Math::transpose);
14434 case Utils::VARIABLE_TYPE_DMAT4:
14435 return new FunctionObject::unary<DMat4 /* ResT */, DMat4 /* ArgT */>(function, "transpose",
14436 Math::transpose);
14437 case Utils::VARIABLE_TYPE_DMAT4X2:
14438 return new FunctionObject::unary<DMat4x2 /* ResT */, DMat2x4 /* ArgT */>(function, "transpose",
14439 Math::transpose);
14440 case Utils::VARIABLE_TYPE_DMAT4X3:
14441 return new FunctionObject::unary<DMat4x3 /* ResT */, DMat3x4 /* ArgT */>(function, "transpose",
14442 Math::transpose);
14443 default:
14444 break;
14445 }
14446
14447 break;
14448
14449 case FUNCTION_TRUNC:
14450
14451 return new FunctionObject::unaryByComponent<glw::GLdouble /* ResT */>(
14452 function, "trunc", Math::trunc, variable_type /* res_type */, variable_type /* arg_type */);
14453
14454 case FUNCTION_UNPACKDOUBLE2X32:
14455
14456 return new FunctionObject::unary<tcu::UVec2 /* ResT */, glw::GLdouble /* ArgT */>(function, "unpackDouble2x32",
14457 Math::unpackDouble2x32);
14458
14459 case FUNCTION_ISNAN:
14460
14461 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14462 function, "isnan", Math::isnan_impl, uint_type /* res_type */, variable_type /* arg_type */);
14463
14464 case FUNCTION_ISINF:
14465
14466 return new FunctionObject::unaryByComponent<glw::GLuint /* ResT */>(
14467 function, "isinf", Math::isinf_impl, uint_type /* res_type */, variable_type /* arg_type */);
14468
14469 default:
14470 TCU_FAIL("Not implemented");
14471 return 0;
14472 }
14473
14474 TCU_FAIL("Not implemented");
14475 return 0;
14476 }
14477
14478 /** Get gl.uniform* that match type of argument. Assumes that type is matrix of double.
14479 *
14480 * @param argument Argument index
14481 * @param function_object Function object
14482 *
14483 * @return Function pointer
14484 **/
getUniformFunctionForDMat(glw::GLuint argument,const functionObject & function_object) const14485 BuiltinFunctionTest::uniformDMatFunctionPointer BuiltinFunctionTest::getUniformFunctionForDMat(
14486 glw::GLuint argument, const functionObject& function_object) const
14487 {
14488 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14489 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14490
14491 switch (argument_type)
14492 {
14493 case Utils::VARIABLE_TYPE_DMAT2:
14494 return gl.uniformMatrix2dv;
14495 case Utils::VARIABLE_TYPE_DMAT2X3:
14496 return gl.uniformMatrix2x3dv;
14497 case Utils::VARIABLE_TYPE_DMAT2X4:
14498 return gl.uniformMatrix2x4dv;
14499 case Utils::VARIABLE_TYPE_DMAT3:
14500 return gl.uniformMatrix3dv;
14501 case Utils::VARIABLE_TYPE_DMAT3X2:
14502 return gl.uniformMatrix3x2dv;
14503 case Utils::VARIABLE_TYPE_DMAT3X4:
14504 return gl.uniformMatrix3x4dv;
14505 case Utils::VARIABLE_TYPE_DMAT4:
14506 return gl.uniformMatrix4dv;
14507 case Utils::VARIABLE_TYPE_DMAT4X2:
14508 return gl.uniformMatrix4x2dv;
14509 case Utils::VARIABLE_TYPE_DMAT4X3:
14510 return gl.uniformMatrix4x3dv;
14511 default:
14512 break;
14513 }
14514
14515 TCU_FAIL("Not implemented");
14516 return 0;
14517 }
14518
14519 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of double.
14520 *
14521 * @param argument Argument index
14522 * @param function_object Function object
14523 *
14524 * @return Function pointer
14525 **/
getUniformFunctionForDVec(glw::GLuint argument,const functionObject & function_object) const14526 BuiltinFunctionTest::uniformDVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForDVec(
14527 glw::GLuint argument, const functionObject& function_object) const
14528 {
14529 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14530 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14531
14532 switch (argument_type)
14533 {
14534 case Utils::VARIABLE_TYPE_DOUBLE:
14535 return gl.uniform1dv;
14536 case Utils::VARIABLE_TYPE_DVEC2:
14537 return gl.uniform2dv;
14538 case Utils::VARIABLE_TYPE_DVEC3:
14539 return gl.uniform3dv;
14540 case Utils::VARIABLE_TYPE_DVEC4:
14541 return gl.uniform4dv;
14542 default:
14543 TCU_FAIL("Not implemented");
14544 }
14545
14546 return 0;
14547 }
14548
14549 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of signed integer.
14550 *
14551 * @param argument Argument index
14552 * @param function_object Function object
14553 *
14554 * @return Function pointer
14555 **/
getUniformFunctionForIVec(glw::GLuint argument,const functionObject & function_object) const14556 BuiltinFunctionTest::uniformIVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForIVec(
14557 glw::GLuint argument, const functionObject& function_object) const
14558 {
14559 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14560 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14561
14562 switch (argument_type)
14563 {
14564 case Utils::VARIABLE_TYPE_INT:
14565 return gl.uniform1iv;
14566 case Utils::VARIABLE_TYPE_IVEC2:
14567 return gl.uniform2iv;
14568 case Utils::VARIABLE_TYPE_IVEC3:
14569 return gl.uniform3iv;
14570 case Utils::VARIABLE_TYPE_IVEC4:
14571 return gl.uniform4iv;
14572 default:
14573 TCU_FAIL("Not implemented");
14574 }
14575
14576 return 0;
14577 }
14578
14579 /** Get gl.uniform* that match type of argument. Assumes that type is scalar or vector of unsigned integer.
14580 *
14581 * @param argument Argument index
14582 * @param function_object Function object
14583 *
14584 * @return Function pointer
14585 **/
getUniformFunctionForUVec(glw::GLuint argument,const functionObject & function_object) const14586 BuiltinFunctionTest::uniformUVecFunctionPointer BuiltinFunctionTest::getUniformFunctionForUVec(
14587 glw::GLuint argument, const functionObject& function_object) const
14588 {
14589 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
14590 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
14591
14592 switch (argument_type)
14593 {
14594 case Utils::VARIABLE_TYPE_UVEC2:
14595 return gl.uniform2uiv;
14596 default:
14597 TCU_FAIL("Not implemented");
14598 }
14599
14600 return 0;
14601 }
14602
14603 /** Get name of uniform that will be used as <argument>.
14604 *
14605 * @param argument Argument index
14606 *
14607 * @return Name of uniform
14608 **/
getUniformName(glw::GLuint argument) const14609 const glw::GLchar* BuiltinFunctionTest::getUniformName(glw::GLuint argument) const
14610 {
14611 switch (argument)
14612 {
14613 case 0:
14614 return "uniform_0";
14615 case 1:
14616 return "uniform_1";
14617 case 2:
14618 return "uniform_2";
14619 default:
14620 TCU_FAIL("Not implemented");
14621 return 0;
14622 }
14623 }
14624
14625 /** Get name of varying that will be used as <result>.
14626 *
14627 * @param result Result index
14628 *
14629 * @return Name of varying
14630 **/
getVaryingName(glw::GLuint result) const14631 const glw::GLchar* BuiltinFunctionTest::getVaryingName(glw::GLuint result) const
14632 {
14633 switch (result)
14634 {
14635 case 0:
14636 return "result_0";
14637 case 1:
14638 return "result_1";
14639 case 2:
14640 return "result_2";
14641 default:
14642 TCU_FAIL("Not implemented");
14643 return 0;
14644 }
14645 }
14646
14647 /** Check if given combination of function and type is implemented
14648 *
14649 * @param function Function enumeration
14650 * @param type Type details
14651 *
14652 * @return true if function is available for given type, false otherwise
14653 **/
isFunctionImplemented(FunctionEnum function,const typeDetails & type) const14654 bool BuiltinFunctionTest::isFunctionImplemented(FunctionEnum function, const typeDetails& type) const
14655 {
14656 static const bool look_up_table[][3] = {
14657 /* SCALAR, VECTOR, MATRIX */
14658 /* FUNCTION_ABS: */ { true, true, false },
14659 /* FUNCTION_CEIL: */ { true, true, false },
14660 /* FUNCTION_CLAMP: */ { true, true, false },
14661 /* FUNCTION_CLAMP_AGAINST_SCALAR: */ { false, true, false },
14662 /* FUNCTION_CROSS: */ { false, true, false },
14663 /* FUNCTION_DETERMINANT: */ { false, false, true },
14664 /* FUNCTION_DISTANCE: */ { false, true, false },
14665 /* FUNCTION_DOT: */ { false, true, false },
14666 /* FUNCTION_EQUAL: */ { false, true, false },
14667 /* FUNCTION_FACEFORWARD: */ { false, true, false },
14668 /* FUNCTION_FLOOR: */ { true, true, false },
14669 /* FUNCTION_FMA: */ { true, true, false },
14670 /* FUNCTION_FRACT: */ { true, true, false },
14671 /* FUNCTION_FREXP: */ { true, true, false },
14672 /* FUNCTION_GREATERTHAN: */ { false, true, false },
14673 /* FUNCTION_GREATERTHANEQUAL: */ { false, true, false },
14674 /* FUNCTION_INVERSE: */ { false, false, true },
14675 /* FUNCTION_INVERSESQRT: */ { true, true, false },
14676 /* FUNCTION_LDEXP: */ { true, true, false },
14677 /* FUNCTION_LESSTHAN: */ { false, true, false },
14678 /* FUNCTION_LESSTHANEQUAL: */ { false, true, false },
14679 /* FUNCTION_LENGTH: */ { false, true, false },
14680 /* FUNCTION_MATRIXCOMPMULT: */ { false, false, true },
14681 /* FUNCTION_MAX: */ { true, true, false },
14682 /* FUNCTION_MAX_AGAINST_SCALAR: */ { false, true, false },
14683 /* FUNCTION_MIN: */ { true, true, false },
14684 /* FUNCTION_MIN_AGAINST_SCALAR: */ { false, true, false },
14685 /* FUNCTION_MIX: */ { true, true, false },
14686 /* FUNCTION_MOD: */ { true, true, false },
14687 /* FUNCTION_MOD_AGAINST_SCALAR: */ { false, true, false },
14688 /* FUNCTION_MODF: */ { true, true, false },
14689 /* FUNCTION_NORMALIZE: */ { false, true, false },
14690 /* FUNCTION_NOTEQUAL: */ { false, true, false },
14691 /* FUNCTION_OUTERPRODUCT: */ { false, false, true },
14692 /* FUNCTION_PACKDOUBLE2X32: */ { true, false, false },
14693 /* FUNCTION_REFLECT: */ { false, true, false },
14694 /* FUNCTION_REFRACT: */ { false, true, false },
14695 /* FUNCTION_ROUND: */ { true, true, false },
14696 /* FUNCTION_ROUNDEVEN: */ { true, true, false },
14697 /* FUNCTION_SIGN: */ { true, false, false },
14698 /* FUNCTION_SMOOTHSTEP: */ { true, true, false },
14699 /* FUNCTION_SMOOTHSTEP_AGAINST_SCALAR: */ { false, true, false },
14700 /* FUNCTION_SQRT: */ { true, true, false },
14701 /* FUNCTION_STEP: */ { true, true, false },
14702 /* FUNCTION_STEP_AGAINST_SCALAR: */ { false, true, false },
14703 /* FUNCTION_TRANSPOSE: */ { false, false, false },
14704 /* FUNCTION_TRUNC: */ { true, true, false },
14705 /* FUNCTION_UNPACKDOUBLE2X32: */ { true, false, false },
14706 /* FUNCTION_ISNAN: */ { true, true, false },
14707 /* FUNCTION_ISINF: */ { true, true, false },
14708 };
14709
14710 bool result = look_up_table[function][type.m_general_type];
14711
14712 if (true == result)
14713 {
14714 switch (function)
14715 {
14716 case FUNCTION_CROSS: /* Only 3 element vectors */
14717 result = (3 == type.m_n_rows);
14718 break;
14719 case FUNCTION_DETERMINANT: /* Only square matrices */
14720 case FUNCTION_INVERSE:
14721 result = (type.m_n_columns == type.m_n_rows);
14722 break;
14723 default:
14724 break;
14725 }
14726 }
14727
14728 return result;
14729 }
14730
14731 /** Logs variable of given type: name (type) [values]
14732 *
14733 * @param buffer Source of data
14734 * @param name Name of variable
14735 * @param type Type of variable
14736 **/
logVariableType(const glw::GLvoid * buffer,const glw::GLchar * name,Utils::_variable_type type) const14737 void BuiltinFunctionTest::logVariableType(const glw::GLvoid* buffer, const glw::GLchar* name,
14738 Utils::_variable_type type) const
14739 {
14740 const Utils::_variable_type base_type = Utils::getBaseVariableType(type);
14741 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(type);
14742 tcu::MessageBuilder message = m_context.getTestContext().getLog() << tcu::TestLog::Message;
14743
14744 message << name << " (" << Utils::getVariableTypeString(type) << ") [";
14745
14746 for (glw::GLuint component = 0; component < n_components; ++component)
14747 {
14748 if (0 != component)
14749 {
14750 message << ", ";
14751 }
14752
14753 switch (base_type)
14754 {
14755 case Utils::VARIABLE_TYPE_DOUBLE:
14756 message << ((glw::GLdouble*)buffer)[component];
14757 break;
14758 case Utils::VARIABLE_TYPE_INT:
14759 message << ((glw::GLint*)buffer)[component];
14760 break;
14761 case Utils::VARIABLE_TYPE_UINT:
14762 message << ((glw::GLuint*)buffer)[component];
14763 break;
14764 default:
14765 TCU_FAIL("Not implemented");
14766 }
14767 }
14768
14769 message << "]" << tcu::TestLog::EndMessage;
14770 }
14771
14772 /** Prepare input arguments, data are stored in <buffer>
14773 *
14774 * @param function_object Function object
14775 * @param vertex Vertex index
14776 * @param buffer Buffer pointer
14777 **/
prepareArgument(const functionObject & function_object,glw::GLuint vertex,glw::GLubyte * buffer)14778 void BuiltinFunctionTest::prepareArgument(const functionObject& function_object, glw::GLuint vertex,
14779 glw::GLubyte* buffer)
14780 {
14781 const glw::GLuint n_arguments = function_object.getArgumentCount();
14782
14783 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
14784 {
14785 const glw::GLuint offset = function_object.getArgumentOffset(argument);
14786
14787 prepareComponents(function_object, vertex, argument, buffer + offset);
14788 }
14789 }
14790
14791 /** Prepare components for given <function_object>, <vertex> and <argument>
14792 *
14793 * @param function_object Function object
14794 * @param vertex Vertex index
14795 * @param argument Argument index
14796 * @param buffer Buffer pointer
14797 **/
prepareComponents(const functionObject & function_object,glw::GLuint vertex,glw::GLuint argument,glw::GLubyte * buffer)14798 void BuiltinFunctionTest::prepareComponents(const functionObject& function_object, glw::GLuint vertex,
14799 glw::GLuint argument, glw::GLubyte* buffer)
14800 {
14801 glw::GLuint argument_index[3] = { 0 };
14802 glw::GLuint argument_reset[3] = { 0 };
14803 glw::GLuint argument_step[3] = { 0 };
14804 glw::GLdouble double_argument_start[3] = { 0.0 };
14805 const Utils::_variable_type base_arg_type = Utils::getBaseVariableType(function_object.getArgumentType(argument));
14806 glw::GLuint int_argument_start = -4;
14807 const glw::GLuint n_arguments = function_object.getArgumentCount();
14808 const glw::GLuint n_components = function_object.getArgumentComponents(argument);
14809 glw::GLuint uint_argument_start = 0;
14810
14811 switch (n_arguments)
14812 {
14813 case 1:
14814 argument_step[0] = 1;
14815 argument_reset[0] = 1024;
14816 double_argument_start[0] = -511.5;
14817 break;
14818 case 2:
14819 argument_step[0] = 32;
14820 argument_step[1] = 1;
14821 argument_reset[0] = 32;
14822 argument_reset[1] = 32;
14823 double_argument_start[0] = -15.5;
14824 double_argument_start[1] = -15.5;
14825 break;
14826 case 3:
14827 argument_step[0] = 64;
14828 argument_step[1] = 8;
14829 argument_step[2] = 1;
14830 argument_reset[0] = 16;
14831 argument_reset[1] = 8;
14832 argument_reset[2] = 8;
14833 double_argument_start[0] = -7.5;
14834 double_argument_start[1] = -3.5;
14835 double_argument_start[2] = -3.5;
14836 break;
14837 default:
14838 TCU_FAIL("Not implemented");
14839 return;
14840 }
14841
14842 switch (function_object.getFunctionEnum())
14843 {
14844 case FUNCTION_CLAMP: /* arg_2 must be less than arg_3 */
14845 case FUNCTION_CLAMP_AGAINST_SCALAR:
14846 double_argument_start[2] = 4.5;
14847 break;
14848 case FUNCTION_INVERSESQRT: /* inversesqrt is undefined for argument <= 0 */
14849 double_argument_start[0] = 16.5;
14850 break;
14851 case FUNCTION_SMOOTHSTEP: /* arg_1 must be less than arg_2 */
14852 case FUNCTION_SMOOTHSTEP_AGAINST_SCALAR:
14853 argument_step[0] = 1;
14854 argument_step[1] = 8;
14855 argument_step[2] = 64;
14856 argument_reset[0] = 8;
14857 argument_reset[1] = 8;
14858 argument_reset[2] = 16;
14859 double_argument_start[0] = -3.5;
14860 double_argument_start[1] = 4.5;
14861 double_argument_start[2] = -7.5;
14862 break;
14863 default:
14864 break;
14865 }
14866
14867 for (glw::GLuint i = 0; i < n_arguments; ++i)
14868 {
14869 argument_index[i] = (vertex / argument_step[i]) % argument_reset[i];
14870 }
14871
14872 switch (base_arg_type)
14873 {
14874 case Utils::VARIABLE_TYPE_DOUBLE:
14875 {
14876 glw::GLdouble* argument_dst = (glw::GLdouble*)buffer;
14877
14878 double_argument_start[argument] += argument_index[argument];
14879
14880 for (glw::GLuint component = 0; component < n_components; ++component)
14881 {
14882 glw::GLdouble value = double_argument_start[argument] + ((glw::GLdouble)component) / 8.0;
14883
14884 switch (function_object.getFunctionEnum())
14885 {
14886 case FUNCTION_ROUND: /* Result for 0.5 depends on implementation */
14887 if (0.5 == Math::fract(value))
14888 {
14889 value += 0.01;
14890 }
14891 break;
14892 default:
14893 break;
14894 }
14895
14896 argument_dst[component] = value;
14897 }
14898 }
14899 break;
14900 case Utils::VARIABLE_TYPE_INT:
14901 {
14902 glw::GLint* argument_dst = (glw::GLint*)buffer;
14903
14904 uint_argument_start += argument_index[argument];
14905
14906 for (glw::GLuint component = 0; component < n_components; ++component)
14907 {
14908 const glw::GLint value = int_argument_start + component;
14909
14910 argument_dst[component] = value;
14911 }
14912 }
14913 break;
14914 case Utils::VARIABLE_TYPE_UINT:
14915 {
14916 glw::GLuint* argument_dst = (glw::GLuint*)buffer;
14917
14918 uint_argument_start += argument_index[argument];
14919
14920 for (glw::GLuint component = 0; component < n_components; ++component)
14921 {
14922 const glw::GLuint value = uint_argument_start + component;
14923
14924 argument_dst[component] = value;
14925 }
14926 }
14927 break;
14928 default:
14929 TCU_FAIL("Not implemented");
14930 return;
14931 }
14932 }
14933
14934 /** Prepare programInfo for given functionObject
14935 *
14936 * @param function_object Function object
14937 * @param out_program_info Program info
14938 **/
prepareProgram(const functionObject & function_object,Utils::programInfo & out_program_info)14939 void BuiltinFunctionTest::prepareProgram(const functionObject& function_object, Utils::programInfo& out_program_info)
14940 {
14941 const glw::GLuint n_varying_names = function_object.getResultCount();
14942 static const glw::GLchar* varying_names[3] = { getVaryingName(0), getVaryingName(1), getVaryingName(2) };
14943
14944 prepareVertexShaderCode(function_object);
14945
14946 out_program_info.build(0 /* cs */, 0 /* fs */, 0 /* gs */, 0 /* tcs */, 0 /* tes */, m_vertex_shader_code.c_str(),
14947 varying_names, n_varying_names);
14948 }
14949
14950 /** Prepare input data and expected results for given function object
14951 *
14952 * @param function_object Function object
14953 **/
prepareTestData(const functionObject & function_object)14954 void BuiltinFunctionTest::prepareTestData(const functionObject& function_object)
14955 {
14956 const glw::GLuint result_stride = function_object.getResultStride();
14957 const glw::GLuint result_buffer_size = result_stride * m_n_veritces;
14958 const glw::GLuint argument_stride = function_object.getArgumentStride();
14959 const glw::GLuint argument_buffer_size = m_n_veritces * argument_stride;
14960
14961 m_argument_data.clear();
14962 m_expected_results_data.clear();
14963
14964 m_argument_data.resize(argument_buffer_size);
14965 m_expected_results_data.resize(result_buffer_size);
14966
14967 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
14968 {
14969 const glw::GLuint result_offset = vertex * result_stride;
14970 glw::GLdouble* result_dst = (glw::GLdouble*)&m_expected_results_data[result_offset];
14971 const glw::GLuint argument_offset = vertex * argument_stride;
14972 glw::GLubyte* argument_dst = &m_argument_data[argument_offset];
14973
14974 prepareArgument(function_object, vertex, argument_dst);
14975 function_object.call(result_dst, argument_dst);
14976 }
14977 }
14978
14979 /** Prepare source code of vertex shader for given function object. Result is stored in m_vertex_shader_code.
14980 *
14981 * @param function_object Function object
14982 **/
prepareVertexShaderCode(const functionObject & function_object)14983 void BuiltinFunctionTest::prepareVertexShaderCode(const functionObject& function_object)
14984 {
14985 static const glw::GLchar* shader_template_code = "#version 400 core\n"
14986 "\n"
14987 "precision highp float;\n"
14988 "\n"
14989 "ARGUMENT_DEFINITION"
14990 "\n"
14991 "RESULT_DEFINITION"
14992 "\n"
14993 "void main()\n"
14994 "{\n"
14995 " RESULT_NAME = RESULT_TYPE(FUNCTION_NAME(ARGUMENT));\n"
14996 "}\n"
14997 "\n";
14998
14999 static const glw::GLchar* argument_definition_token = "ARGUMENT_DEFINITION";
15000 static const glw::GLchar* argument_token = "ARGUMENT";
15001 static const glw::GLchar* function_name_token = "FUNCTION_NAME";
15002 static const glw::GLchar* result_definition_token = "RESULT_DEFINITION";
15003 static const glw::GLchar* result_name_token = "RESULT_NAME";
15004 static const glw::GLchar* result_type_token = "RESULT_TYPE";
15005 static const glw::GLchar* uniform_name_token = "UNIFORM_NAME";
15006 static const glw::GLchar* uniform_type_token = "UNIFORM_TYPE";
15007
15008 static const glw::GLchar* argument_definition = "uniform UNIFORM_TYPE UNIFORM_NAME;\nARGUMENT_DEFINITION";
15009 static const glw::GLchar* argument_str = ", UNIFORM_NAMEARGUMENT";
15010 static const glw::GLchar* first_argument = "UNIFORM_NAMEARGUMENT";
15011 static const glw::GLchar* result_definition = "flat out RESULT_TYPE RESULT_NAME;\nRESULT_DEFINITION";
15012
15013 const glw::GLuint argument_definition_length = (glw::GLuint)strlen(argument_definition);
15014 const glw::GLuint first_argument_length = (glw::GLuint)strlen(first_argument);
15015 const glw::GLuint n_arguments = function_object.getArgumentCount();
15016 const glw::GLuint n_results = function_object.getResultCount();
15017 const glw::GLuint result_definition_length = (glw::GLuint)strlen(result_definition);
15018 std::string result_type = Utils::getVariableTypeString(function_object.getResultType(0));
15019
15020 size_t search_position = 0;
15021 std::string string = shader_template_code;
15022
15023 /* Replace ARGUMENT_DEFINITION with definitions */
15024 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15025 {
15026 Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15027 const glw::GLchar* uniform_name = getUniformName(argument);
15028 std::string uniform_type = Utils::getVariableTypeString(argument_type);
15029
15030 Utils::replaceToken(argument_definition_token, search_position, argument_definition, string);
15031
15032 search_position -= argument_definition_length;
15033
15034 Utils::replaceToken(uniform_type_token, search_position, uniform_type.c_str(), string);
15035 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15036 }
15037
15038 /* Remove ARGUMENT_DEFINITION */
15039 Utils::replaceToken(argument_definition_token, search_position, "", string);
15040
15041 /* Replace RESULT_DEFINITION with definitions */
15042 for (glw::GLuint result = 0; result < n_results; ++result)
15043 {
15044 Utils::_variable_type variable_type = function_object.getResultType(result);
15045 const glw::GLchar* varying_name = getVaryingName(result);
15046 std::string varying_type = Utils::getVariableTypeString(variable_type);
15047
15048 Utils::replaceToken(result_definition_token, search_position, result_definition, string);
15049
15050 search_position -= result_definition_length;
15051
15052 Utils::replaceToken(result_type_token, search_position, varying_type.c_str(), string);
15053 Utils::replaceToken(result_name_token, search_position, varying_name, string);
15054 }
15055
15056 /* Remove RESULT_DEFINITION */
15057 Utils::replaceToken(result_definition_token, search_position, "", string);
15058
15059 /* Replace RESULT_NAME */
15060 Utils::replaceToken(result_name_token, search_position, getVaryingName(0), string);
15061
15062 /* Replace RESULT_TYPE */
15063 Utils::replaceToken(result_type_token, search_position, result_type.c_str(), string);
15064
15065 /* Replace FUNCTION_NAME */
15066 Utils::replaceToken(function_name_token, search_position, function_object.getName(), string);
15067
15068 /* Replace ARGUMENT with list of arguments */
15069 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15070 {
15071 const glw::GLchar* uniform_name = getUniformName(argument);
15072
15073 if (0 == argument)
15074 {
15075 Utils::replaceToken(argument_token, search_position, first_argument, string);
15076 }
15077 else
15078 {
15079 Utils::replaceToken(argument_token, search_position, argument_str, string);
15080 }
15081
15082 search_position -= first_argument_length;
15083
15084 Utils::replaceToken(uniform_name_token, search_position, uniform_name, string);
15085 }
15086
15087 for (glw::GLuint result = 1; result < n_results; ++result)
15088 {
15089 const glw::GLchar* varying_name = getVaryingName(result);
15090
15091 Utils::replaceToken(argument_token, search_position, argument_str, string);
15092
15093 search_position -= first_argument_length;
15094
15095 Utils::replaceToken(uniform_name_token, search_position, varying_name, string);
15096 }
15097
15098 /* Remove ARGUMENT */
15099 Utils::replaceToken(argument_token, search_position, "", string);
15100
15101 m_vertex_shader_code = string;
15102 }
15103
15104 /** Test single function with one type
15105 *
15106 * param function Function enumeration
15107 * param type Type details
15108 *
15109 * @return true if test pass (or function is not available for <type>), false otherwise
15110 **/
test(FunctionEnum function,const typeDetails & type)15111 bool BuiltinFunctionTest::test(FunctionEnum function, const typeDetails& type)
15112 {
15113 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15114
15115 /* Skip if function is not implemented for type */
15116 if (false == isFunctionImplemented(function, type))
15117 {
15118 return true;
15119 }
15120
15121 Utils::programInfo program(m_context);
15122 de::UniquePtr<functionObject> function_object(getFunctionObject(function, type));
15123
15124 prepareProgram(*function_object, program);
15125 prepareTestData(*function_object);
15126
15127 /* Set up program */
15128 gl.useProgram(program.m_program_object_id);
15129 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
15130
15131 for (glw::GLuint vertex = 0; vertex < m_n_veritces; ++vertex)
15132 {
15133 testBegin(*function_object, program.m_program_object_id, vertex);
15134
15135 gl.beginTransformFeedback(GL_POINTS);
15136 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
15137
15138 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
15139 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
15140
15141 gl.endTransformFeedback();
15142 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
15143
15144 if (false == verifyResults(*function_object, vertex))
15145 {
15146 return false;
15147 }
15148 }
15149
15150 return true;
15151 }
15152
15153 /** Update transform feedback buffer and uniforms
15154 *
15155 * @param function_object Function object
15156 * @param program_id Program object id
15157 * @param vertex Vertex index
15158 **/
testBegin(const functionObject & function_object,glw::GLuint program_id,glw::GLuint vertex)15159 void BuiltinFunctionTest::testBegin(const functionObject& function_object, glw::GLuint program_id, glw::GLuint vertex)
15160 {
15161 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15162 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15163 const glw::GLuint n_arguments = function_object.getArgumentCount();
15164 const glw::GLuint result_buffer_size = function_object.getResultStride();
15165 const glw::GLuint vertex_offset = arguments_stride * vertex;
15166
15167 /* Update transform feedback buffer */
15168 std::vector<glw::GLubyte> transform_feedback_buffer_data;
15169 transform_feedback_buffer_data.resize(result_buffer_size);
15170
15171 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15172 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15173
15174 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, result_buffer_size, &transform_feedback_buffer_data[0],
15175 GL_DYNAMIC_COPY);
15176 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
15177
15178 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_transform_feedback_buffer_id, 0 /* offset */,
15179 result_buffer_size);
15180 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
15181
15182 /* Update VAO */
15183 gl.bindVertexArray(m_vertex_array_object_id);
15184 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
15185
15186 for (glw::GLuint argument = 0; argument < n_arguments; ++argument)
15187 {
15188 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15189 const Utils::_variable_type argument_type = function_object.getArgumentType(argument);
15190 const glw::GLuint n_columns = Utils::getNumberOfColumnsForVariableType(argument_type);
15191 const glw::GLchar* uniform_name = getUniformName(argument);
15192 const glw::GLint uniform_location = gl.getUniformLocation(program_id, uniform_name);
15193 const glw::GLdouble* uniform_src = (glw::GLdouble*)&m_argument_data[vertex_offset + argument_offset];
15194
15195 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
15196
15197 if (-1 == uniform_location)
15198 {
15199 TCU_FAIL("Inactive uniform");
15200 }
15201
15202 if (1 == n_columns)
15203 {
15204 switch (Utils::getBaseVariableType(argument_type))
15205 {
15206 case Utils::VARIABLE_TYPE_DOUBLE:
15207 {
15208 uniformDVecFunctionPointer p_uniform_function = getUniformFunctionForDVec(argument, function_object);
15209
15210 p_uniform_function(uniform_location, 1 /* count */, uniform_src);
15211 }
15212 break;
15213 case Utils::VARIABLE_TYPE_UINT:
15214 {
15215 uniformUVecFunctionPointer p_uniform_function = getUniformFunctionForUVec(argument, function_object);
15216
15217 p_uniform_function(uniform_location, 1 /* count */, (glw::GLuint*)uniform_src);
15218 }
15219 break;
15220 case Utils::VARIABLE_TYPE_INT:
15221 {
15222 uniformIVecFunctionPointer p_uniform_function = getUniformFunctionForIVec(argument, function_object);
15223
15224 p_uniform_function(uniform_location, 1 /* count */, (glw::GLint*)uniform_src);
15225 }
15226 break;
15227 default:
15228 TCU_FAIL("Not implemented");
15229 }
15230 }
15231 else
15232 {
15233 uniformDMatFunctionPointer p_uniform_function = getUniformFunctionForDMat(argument, function_object);
15234
15235 p_uniform_function(uniform_location, 1 /* count */, GL_FALSE /* transpose */, uniform_src);
15236 }
15237 }
15238 }
15239
15240 /** Init GL obejcts
15241 *
15242 **/
testInit()15243 void BuiltinFunctionTest::testInit()
15244 {
15245 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15246
15247 gl.genBuffers(1, &m_transform_feedback_buffer_id);
15248 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
15249
15250 gl.genVertexArrays(1, &m_vertex_array_object_id);
15251 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
15252
15253 gl.enable(GL_RASTERIZER_DISCARD);
15254 }
15255
15256 /** Checks if function result is an acceptable edge case
15257 *
15258 * @param function_object Function object
15259 * @param vertex Vertex index
15260 *
15261 * @return true if all results are as expected, false otherwise
15262 **/
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)15263 bool BuiltinFunctionTest::isResultEdgeCase(const functionObject& function_object, glw::GLuint vertex,
15264 const Utils::_variable_type result_type,
15265 const glw::GLvoid* expected_result_src, const glw::GLvoid* result_src)
15266 {
15267 FunctionEnum function_type = function_object.getFunctionEnum();
15268 switch (function_type)
15269 {
15270 // mod(a, b) is defined as a - b * floor(a/b) and mod(a,a) should be 0. However OpenGL
15271 // allows for some error in division, so a/a could actually end up being 1.0 - 1ULP.
15272 // In such a case, floor(a/a) would end up as 0, with mod(a,a) becoming a.
15273 case FUNCTION_MOD:
15274 case FUNCTION_MOD_AGAINST_SCALAR:
15275 {
15276 const glw::GLuint arguments_stride = function_object.getArgumentStride();
15277 const glw::GLuint vertex_offset = arguments_stride * vertex;
15278 const glw::GLuint argument_1_offset = function_object.getArgumentOffset(0);
15279 const glw::GLuint argument_2_offset = function_object.getArgumentOffset(1);
15280 const glw::GLuint argument_1_index = argument_1_offset + vertex_offset;
15281 const glw::GLuint argument_2_index = argument_2_offset + vertex_offset;
15282 const glw::GLubyte* argument_1_bytes = &m_argument_data[argument_1_index];
15283 const glw::GLubyte* argument_2_bytes = &m_argument_data[argument_2_index];
15284 const glw::GLdouble* argument_1 = reinterpret_cast<const glw::GLdouble*>(argument_1_bytes);
15285 const glw::GLdouble* argument_2 = reinterpret_cast<const glw::GLdouble*>(argument_2_bytes);
15286 const glw::GLdouble* expected_result = reinterpret_cast<const glw::GLdouble*>(expected_result_src);
15287 const glw::GLdouble* actual_result = reinterpret_cast<const glw::GLdouble*>(result_src);
15288 bool edge_case_present = false;
15289 bool recheck = false;
15290
15291 // verify if there is a mod(a, a) case and prepare new expected result
15292 const glw::GLuint n_components = Utils::getNumberOfComponentsForVariableType(result_type);
15293 std::vector<glw::GLdouble> corrected_expected_result(n_components, 0.0);
15294 for (glw::GLuint component = 0; component < n_components; ++component)
15295 {
15296 glw::GLdouble expected_result_component = expected_result[component];
15297 glw::GLdouble actual_result_component = actual_result[component];
15298 glw::GLdouble argument_1_component = argument_1[component];
15299 glw::GLdouble argument_2_component = argument_2[(function_type == FUNCTION_MOD) ? component : 0];
15300
15301 // if coresponding components of arguments are equal and if component of first argument
15302 // and component of result are equal then expected result must be corrected
15303 bool possible_edge_case = m_epsilon > de::abs((argument_1_component / argument_2_component) -
15304 round(argument_1_component / argument_2_component));
15305 edge_case_present = possible_edge_case &&
15306 (m_epsilon > de::abs(argument_2_component - actual_result_component));
15307 recheck |= edge_case_present;
15308 corrected_expected_result[component] = edge_case_present ? argument_2_component : expected_result_component;
15309 }
15310
15311 // recheck test result with corrected expected result
15312 return (recheck && compare(result_type, &(corrected_expected_result[0]), result_src));
15313 }
15314 default:
15315 return false;
15316 }
15317 }
15318
15319 /** Compare contents of transform feedback buffer with expected results
15320 *
15321 * @param function_object Function object
15322 * @param vertex Vertex index
15323 *
15324 * @return true if all results are as expected, false otherwise
15325 **/
verifyResults(const functionObject & function_object,glw::GLuint vertex)15326 bool BuiltinFunctionTest::verifyResults(const functionObject& function_object, glw::GLuint vertex)
15327 {
15328 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
15329 bool test_result = true;
15330 const glw::GLuint n_results = function_object.getResultCount();
15331 const glw::GLuint results_stride = function_object.getResultStride();
15332 const glw::GLuint results_offset = vertex * results_stride;
15333 const glw::GLubyte* expected_results = &m_expected_results_data[results_offset];
15334
15335 /* Get transform feedback data */
15336 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_transform_feedback_buffer_id);
15337 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
15338
15339 glw::GLubyte* feedback_data = (glw::GLubyte*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
15340 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
15341
15342 for (glw::GLuint result = 0; result < n_results; ++result)
15343 {
15344 const Utils::_variable_type result_type = function_object.getResultType(result);
15345 const glw::GLuint result_offset = function_object.getResultOffset(result);
15346
15347 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15348 const glw::GLvoid* result_src = feedback_data + result_offset;
15349
15350 if (compare(result_type, expected_result_src, result_src))
15351 continue;
15352
15353 if (!isResultEdgeCase(function_object, vertex, result_type, expected_result_src, result_src))
15354 {
15355 test_result = false;
15356 break;
15357 }
15358 }
15359
15360 /* Unmap transform feedback buffer */
15361 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
15362 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
15363
15364 if (false == test_result)
15365 {
15366 const glw::GLuint argument_stride = function_object.getArgumentStride();
15367 const glw::GLuint arguments_offset = vertex * argument_stride;
15368
15369 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Error. Invalid result."
15370 << tcu::TestLog::EndMessage;
15371
15372 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Function: " << function_object.getName()
15373 << tcu::TestLog::EndMessage;
15374
15375 for (glw::GLuint result = 0; result < n_results; ++result)
15376 {
15377 const Utils::_variable_type result_type = function_object.getResultType(result);
15378 const glw::GLuint result_offset = function_object.getResultOffset(result);
15379
15380 const glw::GLvoid* expected_result_src = expected_results + result_offset;
15381 const glw::GLvoid* result_src = feedback_data + result_offset;
15382
15383 logVariableType(result_src, "Result", result_type);
15384 logVariableType(expected_result_src, "Expected result", result_type);
15385 }
15386
15387 for (glw::GLuint argument = 0; argument < function_object.getArgumentCount(); ++argument)
15388 {
15389 const glw::GLuint argument_offset = function_object.getArgumentOffset(argument);
15390 const glw::GLubyte* argument_src = &m_argument_data[arguments_offset + argument_offset];
15391
15392 logVariableType(argument_src, "Argument", function_object.getArgumentType(argument));
15393 }
15394
15395 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Shader:\n"
15396 << m_vertex_shader_code << tcu::TestLog::EndMessage;
15397 }
15398
15399 return test_result;
15400 }
15401
15402 /** Constructor.
15403 *
15404 * @param context Rendering context.
15405 **/
GPUShaderFP64Tests(deqp::Context & context)15406 GPUShaderFP64Tests::GPUShaderFP64Tests(deqp::Context& context)
15407 : TestCaseGroup(context, "gpu_shader_fp64", "Verifies \"gpu_shader_fp64\" functionality")
15408 {
15409 /* Left blank on purpose */
15410 }
15411
15412 /** Initializes a texture_storage_multisample test group.
15413 *
15414 **/
init(void)15415 void GPUShaderFP64Tests::init(void)
15416 {
15417 TestCaseGroup* fp64 = new TestCaseGroup(m_context, "fp64", "");
15418 fp64->addChild(new GPUShaderFP64Test1(m_context));
15419 fp64->addChild(new GPUShaderFP64Test2(m_context));
15420 fp64->addChild(new GPUShaderFP64Test3(m_context));
15421 fp64->addChild(new GPUShaderFP64Test4(m_context));
15422 fp64->addChild(new GPUShaderFP64Test5(m_context));
15423 fp64->addChild(new GPUShaderFP64Test6(m_context));
15424 fp64->addChild(new GPUShaderFP64Test7(m_context));
15425 fp64->addChild(new GPUShaderFP64Test8(m_context));
15426 fp64->addChild(new GPUShaderFP64Test9(m_context));
15427 addChild(fp64);
15428
15429 TypeDefinition typeDefinition[] =
15430 {
15431 { "double", 1, 1 },
15432 { "dvec2", 1, 2 },
15433 { "dvec3", 1, 3 },
15434 { "dvec4", 1, 4 },
15435 { "dmat2", 2, 2 },
15436 { "dmat2x3", 2, 3 },
15437 { "dmat2x4", 2, 4 },
15438 { "dmat3x2", 3, 2 },
15439 { "dmat3", 3, 3 },
15440 { "dmat3x4", 3, 4 },
15441 { "dmat4x2", 4, 2 },
15442 { "dmat4x3", 4, 3 },
15443 { "dmat4", 4, 4 }
15444 };
15445
15446 struct BuiltinFunctions
15447 {
15448 std::string name;
15449 FunctionEnum function;
15450 } builtinFunctions[] = {
15451 { "abs", FUNCTION_ABS },
15452 { "ceil", FUNCTION_CEIL },
15453 { "clamp", FUNCTION_CLAMP },
15454 { "clamp_against_scalar", FUNCTION_CLAMP_AGAINST_SCALAR },
15455 { "cross", FUNCTION_CROSS },
15456 { "determinant", FUNCTION_DETERMINANT },
15457 { "distance", FUNCTION_DISTANCE },
15458 { "dot", FUNCTION_DOT },
15459 { "equal", FUNCTION_EQUAL },
15460 { "faceforward", FUNCTION_FACEFORWARD },
15461 { "floor", FUNCTION_FLOOR },
15462 { "fma", FUNCTION_FMA },
15463 { "fract", FUNCTION_FRACT },
15464 { "frexp", FUNCTION_FREXP },
15465 { "greaterthan", FUNCTION_GREATERTHAN },
15466 { "greaterthanequal", FUNCTION_GREATERTHANEQUAL },
15467 { "inverse", FUNCTION_INVERSE },
15468 { "inversesqrt", FUNCTION_INVERSESQRT },
15469 { "ldexp", FUNCTION_LDEXP },
15470 { "lessthan", FUNCTION_LESSTHAN },
15471 { "lessthanequal", FUNCTION_LESSTHANEQUAL },
15472 { "length", FUNCTION_LENGTH },
15473 { "matrixcompmult", FUNCTION_MATRIXCOMPMULT },
15474 { "max", FUNCTION_MAX },
15475 { "max_against_scalar", FUNCTION_MAX_AGAINST_SCALAR },
15476 { "min", FUNCTION_MIN },
15477 { "min_against_scalar", FUNCTION_MIN_AGAINST_SCALAR },
15478 { "mix", FUNCTION_MIX },
15479 { "mod", FUNCTION_MOD },
15480 { "mod_against_scalar", FUNCTION_MOD_AGAINST_SCALAR },
15481 { "modf", FUNCTION_MODF },
15482 { "normalize", FUNCTION_NORMALIZE },
15483 { "notequal", FUNCTION_NOTEQUAL },
15484 { "outerproduct", FUNCTION_OUTERPRODUCT },
15485 { "packdouble2x32", FUNCTION_PACKDOUBLE2X32 },
15486 { "reflect", FUNCTION_REFLECT },
15487 { "refract", FUNCTION_REFRACT },
15488 { "round", FUNCTION_ROUND },
15489 { "roundeven", FUNCTION_ROUNDEVEN },
15490 { "sign", FUNCTION_SIGN },
15491 { "smoothstep", FUNCTION_SMOOTHSTEP },
15492 { "smoothstep_against_scalar", FUNCTION_SMOOTHSTEP_AGAINST_SCALAR },
15493 { "sqrt", FUNCTION_SQRT },
15494 { "step", FUNCTION_STEP },
15495 { "step_against_scalar", FUNCTION_STEP_AGAINST_SCALAR },
15496 { "transpose", FUNCTION_TRANSPOSE },
15497 { "trunc", FUNCTION_TRUNC },
15498 { "unpackdouble2x32", FUNCTION_UNPACKDOUBLE2X32 },
15499 { "isnan", FUNCTION_ISNAN },
15500 { "isinf", FUNCTION_ISINF }
15501 };
15502
15503 TestCaseGroup* builin = new TestCaseGroup(m_context, "builtin", "");
15504 for (int i = 0; i < DE_LENGTH_OF_ARRAY(builtinFunctions); ++i)
15505 {
15506 const BuiltinFunctions& bf = builtinFunctions[i];
15507 for (int j = 0; j < DE_LENGTH_OF_ARRAY(typeDefinition); ++j)
15508 {
15509 std::string caseName = bf.name + "_" + typeDefinition[j].name;
15510 builin->addChild(new BuiltinFunctionTest(m_context, caseName, bf.function, typeDefinition[j]));
15511 }
15512 }
15513 addChild(builin);
15514 }
15515
15516 } /* glcts namespace */
15517