1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-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 gl4cEnhancedLayoutsTests.cpp
26 * \brief Implements conformance tests for "Enhanced Layouts" functionality.
27 */ /*-------------------------------------------------------------------*/
28
29 #include "gl4cEnhancedLayoutsTests.hpp"
30
31 #include "gluContextInfo.hpp"
32 #include "gluDefs.hpp"
33 #include "gluStrUtil.hpp"
34 #include "glwEnums.hpp"
35 #include "glwFunctions.hpp"
36 #include "tcuTestLog.hpp"
37
38 #include <algorithm>
39 #include <iomanip>
40 #include <string>
41 #include <vector>
42
43 /* DEBUG */
44 #define USE_NSIGHT 0
45 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0
46 #define DEBUG_NEG_LOG_ERROR 0
47 #define DEBUG_REPLACE_TOKEN 0
48 #define DEBUG_REPEAT_TEST_CASE 0
49 #define DEBUG_REPEATED_TEST_CASE 0
50
51 /* Texture test base */
52 #define DEBUG_TTB_VERIFICATION_SNIPPET_STAGE 0
53 #define DEBUG_TTB_VERIFICATION_SNIPPET_VARIABLE 0
54
55 /* Tests */
56 #define DEBUG_VERTEX_ATTRIB_LOCATIONS_TEST_VARIABLE 0
57
58 /* WORKAROUNDS */
59 #define WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST 0
60 #define WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST 0
61 #define WRKARD_UNIFORMBLOCKALIGNMENT 0
62 #define WRKARD_VARYINGLOCATIONSTEST 0
63
64 using namespace glw;
65
66 namespace gl4cts
67 {
68 namespace EnhancedLayouts
69 {
70 namespace Utils
71 {
72 /** Constants used by "random" generators **/
73 static const GLuint s_rand_start = 3;
74 static const GLuint s_rand_max = 16;
75 static const GLuint s_rand_max_half = s_rand_max / 2;
76
77 /** Seed used by "random" generators **/
78 static GLuint s_rand = s_rand_start;
79
80 /** Get "random" unsigned int value
81 *
82 * @return Value
83 **/
GetRandUint()84 static GLuint GetRandUint()
85 {
86 const GLuint rand = s_rand++;
87
88 if (s_rand_max <= s_rand)
89 {
90 s_rand = s_rand_start;
91 }
92
93 return rand;
94 }
95
96 /** Get "random" int value
97 *
98 * @return Value
99 **/
GetRandInt()100 GLint GetRandInt()
101 {
102 const GLint rand = GetRandUint() - s_rand_max_half;
103
104 return rand;
105 }
106
107 /** Get "random" double value
108 *
109 * @return Value
110 **/
GetRandDouble()111 GLdouble GetRandDouble()
112 {
113 const GLint rand = GetRandInt();
114
115 GLdouble result = (GLfloat)rand / (GLdouble)s_rand_max_half;
116
117 return result;
118 }
119
120 /** Get "random" float value
121 *
122 * @return Value
123 **/
GetRandFloat()124 GLfloat GetRandFloat()
125 {
126 const GLint rand = GetRandInt();
127
128 GLfloat result = (GLfloat)rand / (GLfloat)s_rand_max_half;
129
130 return result;
131 }
132
133 /** String used by list routines **/
134 static const GLchar* const g_list = "LIST";
135
136 /** Type constants **/
137 const Type Type::_double = Type::GetType(Type::Double, 1, 1);
138 const Type Type::dmat2 = Type::GetType(Type::Double, 2, 2);
139 const Type Type::dmat2x3 = Type::GetType(Type::Double, 2, 3);
140 const Type Type::dmat2x4 = Type::GetType(Type::Double, 2, 4);
141 const Type Type::dmat3x2 = Type::GetType(Type::Double, 3, 2);
142 const Type Type::dmat3 = Type::GetType(Type::Double, 3, 3);
143 const Type Type::dmat3x4 = Type::GetType(Type::Double, 3, 4);
144 const Type Type::dmat4x2 = Type::GetType(Type::Double, 4, 2);
145 const Type Type::dmat4x3 = Type::GetType(Type::Double, 4, 3);
146 const Type Type::dmat4 = Type::GetType(Type::Double, 4, 4);
147 const Type Type::dvec2 = Type::GetType(Type::Double, 1, 2);
148 const Type Type::dvec3 = Type::GetType(Type::Double, 1, 3);
149 const Type Type::dvec4 = Type::GetType(Type::Double, 1, 4);
150 const Type Type::_int = Type::GetType(Type::Int, 1, 1);
151 const Type Type::ivec2 = Type::GetType(Type::Int, 1, 2);
152 const Type Type::ivec3 = Type::GetType(Type::Int, 1, 3);
153 const Type Type::ivec4 = Type::GetType(Type::Int, 1, 4);
154 const Type Type::_float = Type::GetType(Type::Float, 1, 1);
155 const Type Type::mat2 = Type::GetType(Type::Float, 2, 2);
156 const Type Type::mat2x3 = Type::GetType(Type::Float, 2, 3);
157 const Type Type::mat2x4 = Type::GetType(Type::Float, 2, 4);
158 const Type Type::mat3x2 = Type::GetType(Type::Float, 3, 2);
159 const Type Type::mat3 = Type::GetType(Type::Float, 3, 3);
160 const Type Type::mat3x4 = Type::GetType(Type::Float, 3, 4);
161 const Type Type::mat4x2 = Type::GetType(Type::Float, 4, 2);
162 const Type Type::mat4x3 = Type::GetType(Type::Float, 4, 3);
163 const Type Type::mat4 = Type::GetType(Type::Float, 4, 4);
164 const Type Type::vec2 = Type::GetType(Type::Float, 1, 2);
165 const Type Type::vec3 = Type::GetType(Type::Float, 1, 3);
166 const Type Type::vec4 = Type::GetType(Type::Float, 1, 4);
167 const Type Type::uint = Type::GetType(Type::Uint, 1, 1);
168 const Type Type::uvec2 = Type::GetType(Type::Uint, 1, 2);
169 const Type Type::uvec3 = Type::GetType(Type::Uint, 1, 3);
170 const Type Type::uvec4 = Type::GetType(Type::Uint, 1, 4);
171
172 /** Generate data for type. This routine follows STD140 rules
173 *
174 * @return Vector of bytes filled with data
175 **/
GenerateData() const176 std::vector<GLubyte> Type::GenerateData() const
177 {
178 const GLuint alignment = GetActualAlignment(0, false);
179
180 std::vector<GLubyte> data;
181 data.resize(alignment * m_n_columns);
182
183 for (GLuint column = 0; column < m_n_columns; ++column)
184 {
185 GLvoid* ptr = (GLvoid*)&data[column * alignment];
186
187 switch (m_basic_type)
188 {
189 case Double:
190 {
191 GLdouble* d_ptr = (GLdouble*)ptr;
192
193 for (GLuint i = 0; i < m_n_rows; ++i)
194 {
195 d_ptr[i] = GetRandDouble();
196 }
197 }
198 break;
199 case Float:
200 {
201 GLfloat* f_ptr = (GLfloat*)ptr;
202
203 for (GLuint i = 0; i < m_n_rows; ++i)
204 {
205 f_ptr[i] = GetRandFloat();
206 }
207 }
208 break;
209 case Int:
210 {
211 GLint* i_ptr = (GLint*)ptr;
212
213 for (GLuint i = 0; i < m_n_rows; ++i)
214 {
215 i_ptr[i] = GetRandInt();
216 }
217 }
218 break;
219 case Uint:
220 {
221 GLuint* ui_ptr = (GLuint*)ptr;
222
223 for (GLuint i = 0; i < m_n_rows; ++i)
224 {
225 ui_ptr[i] = GetRandUint();
226 }
227 }
228 break;
229 }
230 }
231
232 return data;
233 }
234
235 /** Generate data for type. This routine packs data tightly.
236 *
237 * @return Vector of bytes filled with data
238 **/
GenerateDataPacked() const239 std::vector<GLubyte> Type::GenerateDataPacked() const
240 {
241 const GLuint basic_size = GetTypeSize(m_basic_type);
242 const GLuint n_elements = m_n_columns * m_n_rows;
243 const GLuint size = basic_size * n_elements;
244
245 std::vector<GLubyte> data;
246 data.resize(size);
247
248 GLvoid* ptr = (GLvoid*)&data[0];
249
250 switch (m_basic_type)
251 {
252 case Double:
253 {
254 GLdouble* d_ptr = (GLdouble*)ptr;
255
256 for (GLuint i = 0; i < n_elements; ++i)
257 {
258 d_ptr[i] = GetRandDouble();
259 }
260 }
261 break;
262 case Float:
263 {
264 GLfloat* f_ptr = (GLfloat*)ptr;
265
266 for (GLuint i = 0; i < n_elements; ++i)
267 {
268 f_ptr[i] = GetRandFloat();
269 }
270 }
271 break;
272 case Int:
273 {
274 GLint* i_ptr = (GLint*)ptr;
275
276 for (GLuint i = 0; i < n_elements; ++i)
277 {
278 i_ptr[i] = GetRandInt();
279 }
280 }
281 break;
282 case Uint:
283 {
284 GLuint* ui_ptr = (GLuint*)ptr;
285
286 for (GLuint i = 0; i < n_elements; ++i)
287 {
288 ui_ptr[i] = GetRandUint();
289 }
290 }
291 break;
292 }
293
294 return data;
295 }
296
297 /** Calculate "actual alignment". It work under assumption that align value is valid
298 *
299 * @param align Requested alignment, eg with "align" qualifier
300 * @param is_array Selects if an array of type or single instance should be considered
301 *
302 * @return Calculated value
303 **/
GetActualAlignment(GLuint align,bool is_array) const304 GLuint Type::GetActualAlignment(GLuint align, bool is_array) const
305 {
306 const GLuint base_alignment = GetBaseAlignment(is_array);
307
308 return std::max(align, base_alignment);
309 }
310
311 /** Align given ofset with specified alignment
312 *
313 * @param offset Offset
314 * @param alignment Alignment
315 *
316 * @return Calculated value
317 **/
align(GLuint offset,GLuint alignment)318 GLuint align(GLuint offset, GLuint alignment)
319 {
320 const GLuint rest = offset % alignment;
321
322 if (0 != rest)
323 {
324 GLuint missing = alignment - rest;
325 offset += missing;
326 }
327
328 return offset;
329 }
330
331 /** Calculate "actual offset"
332 *
333 * @param start_offset Requested offset
334 * @param actual_alignment Actual alignemnt
335 *
336 * @return Calculated value
337 **/
GetActualOffset(GLuint start_offset,GLuint actual_alignment)338 GLuint Type::GetActualOffset(GLuint start_offset, GLuint actual_alignment)
339 {
340 GLuint offset = align(start_offset, actual_alignment);
341
342 return offset;
343 }
344
345 /** Calculate "base alignment" for given type
346 *
347 * @param is_array Select if array or single instance should be considered
348 *
349 * @return Calculated value
350 **/
GetBaseAlignment(bool is_array) const351 GLuint Type::GetBaseAlignment(bool is_array) const
352 {
353 GLuint elements = 1;
354
355 switch (m_n_rows)
356 {
357 case 2:
358 elements = 2;
359 break;
360 case 3:
361 case 4:
362 elements = 4;
363 break;
364 default:
365 break;
366 }
367
368 GLuint N = GetTypeSize(m_basic_type);
369 GLuint alignment = N * elements;
370
371 if ((true == is_array) || (1 != m_n_columns))
372 {
373 alignment = align(alignment, 16 /* vec4 alignment */);
374 }
375
376 return alignment;
377 }
378
379 /** Returns string representing GLSL constructor of type with arguments provided in data
380 *
381 * @param data Array of values that will be used as construcotr arguments.
382 * It is interpreted as tightly packed array of type matching this type.
383 *
384 * @return String in form "Type(args)"
385 **/
GetGLSLConstructor(const GLvoid * data) const386 std::string Type::GetGLSLConstructor(const GLvoid* data) const
387 {
388 const GLchar* type = GetGLSLTypeName();
389
390 std::stringstream stream;
391
392 stream << type << "(";
393
394 /* Scalar or vector */
395 if (1 == m_n_columns)
396 {
397 for (GLuint row = 0; row < m_n_rows; ++row)
398 {
399 switch (m_basic_type)
400 {
401 case Double:
402 stream << ((GLdouble*)data)[row];
403 break;
404 case Float:
405 stream << ((GLfloat*)data)[row];
406 break;
407 case Int:
408 stream << ((GLint*)data)[row];
409 break;
410 case Uint:
411 stream << ((GLuint*)data)[row];
412 break;
413 }
414
415 if (row + 1 != m_n_rows)
416 {
417 stream << ", ";
418 }
419 }
420 }
421 else /* Matrix: mat(vec(), vec() .. ) */
422 {
423 const GLuint basic_size = GetTypeSize(m_basic_type);
424 // Very indescoverable defect, the column stride should be calculated by rows, such as mat2x3, which is 2, columns 3 rows, its column stride should be 3 * sizeof(float)
425 const GLuint column_stride = m_n_rows * basic_size;
426 const Type column_type = GetType(m_basic_type, 1, m_n_rows);
427
428 for (GLuint column = 0; column < m_n_columns; ++column)
429 {
430 const GLuint column_offset = column * column_stride;
431 const GLvoid* column_data = (GLubyte*)data + column_offset;
432
433 stream << column_type.GetGLSLConstructor(column_data);
434
435 if (column + 1 != m_n_columns)
436 {
437 stream << ", ";
438 }
439 }
440 }
441
442 stream << ")";
443
444 return stream.str();
445 }
446
447 /** Get glsl name of the type
448 *
449 * @return Name of glsl type
450 **/
GetGLSLTypeName() const451 const glw::GLchar* Type::GetGLSLTypeName() const
452 {
453 static const GLchar* float_lut[4][4] = {
454 { "float", "vec2", "vec3", "vec4" },
455 { 0, "mat2", "mat2x3", "mat2x4" },
456 { 0, "mat3x2", "mat3", "mat3x4" },
457 { 0, "mat4x2", "mat4x3", "mat4" },
458 };
459
460 static const GLchar* double_lut[4][4] = {
461 { "double", "dvec2", "dvec3", "dvec4" },
462 { 0, "dmat2", "dmat2x3", "dmat2x4" },
463 { 0, "dmat3x2", "dmat3", "dmat3x4" },
464 { 0, "dmat4x2", "dmat4x3", "dmat4" },
465 };
466
467 static const GLchar* int_lut[4] = { "int", "ivec2", "ivec3", "ivec4" };
468
469 static const GLchar* uint_lut[4] = { "uint", "uvec2", "uvec3", "uvec4" };
470
471 const GLchar* result = 0;
472
473 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
474 {
475 return 0;
476 }
477
478 switch (m_basic_type)
479 {
480 case Float:
481 result = float_lut[m_n_columns - 1][m_n_rows - 1];
482 break;
483 case Double:
484 result = double_lut[m_n_columns - 1][m_n_rows - 1];
485 break;
486 case Int:
487 result = int_lut[m_n_rows - 1];
488 break;
489 case Uint:
490 result = uint_lut[m_n_rows - 1];
491 break;
492 default:
493 TCU_FAIL("Invliad enum");
494 }
495
496 return result;
497 }
498
499 /** Get number of locations required for the type
500 *
501 * @return Number of columns times:
502 * - 2 when type is double with 3 or 4 rows,
503 * - 1 otherwise or if it's a vertex shader input.
504 **/
GetLocations(bool is_vs_input) const505 GLuint Type::GetLocations(bool is_vs_input) const
506 {
507 GLuint n_loc_per_column;
508
509 /* 1 or 2 doubles any for rest */
510 if ((2 >= m_n_rows) || (Double != m_basic_type) || is_vs_input)
511 {
512 n_loc_per_column = 1;
513 }
514 else
515 {
516 /* 3 and 4 doubles */
517 n_loc_per_column = 2;
518 }
519
520 return n_loc_per_column * m_n_columns;
521 }
522
523 /** Get size of the type in bytes.
524 * Note that this routine doesn't consider arrays and assumes
525 * column_major matrices.
526 *
527 * @return Formula:
528 * - If std140 packaging and matrix; number of columns * base alignment
529 * - Otherwise; number of elements * sizeof(base_type)
530 **/
GetSize(const bool is_std140) const531 GLuint Type::GetSize(const bool is_std140) const
532 {
533 const GLuint basic_type_size = GetTypeSize(m_basic_type);
534 const GLuint n_elements = m_n_columns * m_n_rows;
535
536 if (is_std140 && m_n_columns > 1)
537 {
538 return m_n_columns * GetBaseAlignment(false);
539 }
540
541 return basic_type_size * n_elements;
542 }
543
544 /** Get GLenum representing the type
545 *
546 * @return GLenum
547 **/
GetTypeGLenum() const548 GLenum Type::GetTypeGLenum() const
549 {
550 static const GLenum float_lut[4][4] = {
551 { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 },
552 { 0, GL_FLOAT_MAT2, GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4 },
553 { 0, GL_FLOAT_MAT3x2, GL_FLOAT_MAT3, GL_FLOAT_MAT3x4 },
554 { 0, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3, GL_FLOAT_MAT4 },
555 };
556
557 static const GLenum double_lut[4][4] = {
558 { GL_DOUBLE, GL_DOUBLE_VEC2, GL_DOUBLE_VEC3, GL_DOUBLE_VEC4 },
559 { 0, GL_DOUBLE_MAT2, GL_DOUBLE_MAT2x3, GL_DOUBLE_MAT2x4 },
560 { 0, GL_DOUBLE_MAT3x2, GL_DOUBLE_MAT3, GL_DOUBLE_MAT3x4 },
561 { 0, GL_DOUBLE_MAT4x2, GL_DOUBLE_MAT4x3, GL_DOUBLE_MAT4 },
562 };
563
564 static const GLenum int_lut[4] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 };
565
566 static const GLenum uint_lut[4] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3,
567 GL_UNSIGNED_INT_VEC4 };
568
569 GLenum result = 0;
570
571 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
572 {
573 return 0;
574 }
575
576 switch (m_basic_type)
577 {
578 case Float:
579 result = float_lut[m_n_columns - 1][m_n_rows - 1];
580 break;
581 case Double:
582 result = double_lut[m_n_columns - 1][m_n_rows - 1];
583 break;
584 case Int:
585 result = int_lut[m_n_rows - 1];
586 break;
587 case Uint:
588 result = uint_lut[m_n_rows - 1];
589 break;
590 default:
591 TCU_FAIL("Invliad enum");
592 }
593
594 return result;
595 }
596
597 /** Calculate the numbe of components consumed by a type
598 * according to 11.1.2.1 Output Variables
599 *
600 * @return Calculated number of components for the type
601 **/
GetNumComponents() const602 GLuint Type::GetNumComponents() const
603 {
604 // Rule 3 of Section 7.6.2.2
605 // If the member is a three-component vector with components consuming N
606 // basic machine units, the base alignment is 4N.
607 GLuint num_components = (m_n_rows == 3 ? 4 : m_n_rows) * m_n_columns;
608
609 if (m_basic_type == Double)
610 {
611 num_components *= 2;
612 }
613
614 return num_components;
615 }
616
617 /** Calculate stride for the type according to std140 rules
618 *
619 * @param alignment Alignment of type
620 * @param n_columns Number of columns
621 * @param n_array_elements Number of elements in array
622 *
623 * @return Calculated value
624 **/
CalculateStd140Stride(GLuint alignment,GLuint n_columns,GLuint n_array_elements)625 GLuint Type::CalculateStd140Stride(GLuint alignment, GLuint n_columns, GLuint n_array_elements)
626 {
627 GLuint stride = alignment * n_columns;
628 if (0 != n_array_elements)
629 {
630 stride *= n_array_elements;
631 }
632
633 return stride;
634 }
635
636 /** Check if glsl support matrices for specific basic type
637 *
638 * @param type Basic type
639 *
640 * @return true if matrices of <type> are supported, false otherwise
641 **/
DoesTypeSupportMatrix(TYPES type)642 bool Type::DoesTypeSupportMatrix(TYPES type)
643 {
644 bool result = false;
645
646 switch (type)
647 {
648 case Float:
649 case Double:
650 result = true;
651 break;
652 case Int:
653 case Uint:
654 result = false;
655 break;
656 default:
657 TCU_FAIL("Invliad enum");
658 }
659
660 return result;
661 }
662
663 /** Creates instance of Type
664 *
665 * @param basic_type Select basic type of instance
666 * @param n_columns Number of columns
667 * @param n_rows Number of rows
668 *
669 * @return Type instance
670 **/
GetType(TYPES basic_type,glw::GLuint n_columns,glw::GLuint n_rows)671 Type Type::GetType(TYPES basic_type, glw::GLuint n_columns, glw::GLuint n_rows)
672 {
673 Type type = { basic_type, n_columns, n_rows };
674
675 return type;
676 }
677
678 /** Get Size of given type in bytes
679 *
680 * @param type
681 *
682 * @return Size of type
683 **/
GetTypeSize(TYPES type)684 GLuint Type::GetTypeSize(TYPES type)
685 {
686 GLuint result = 0;
687
688 switch (type)
689 {
690 case Float:
691 result = sizeof(GLfloat);
692 break;
693 case Double:
694 result = sizeof(GLdouble);
695 break;
696 case Int:
697 result = sizeof(GLint);
698 break;
699 case Uint:
700 result = sizeof(GLuint);
701 break;
702 default:
703 TCU_FAIL("Invalid enum");
704 }
705
706 return result;
707 }
708
709 /** Get GLenum representing given type
710 *
711 * @param type
712 *
713 * @return GLenum value
714 **/
GetTypeGLenum(TYPES type)715 GLenum Type::GetTypeGLenum(TYPES type)
716 {
717 GLenum result = 0;
718
719 switch (type)
720 {
721 case Float:
722 result = GL_FLOAT;
723 break;
724 case Double:
725 result = GL_DOUBLE;
726 break;
727 case Int:
728 result = GL_INT;
729 break;
730 case Uint:
731 result = GL_UNSIGNED_INT;
732 break;
733 default:
734 TCU_FAIL("Invalid enum");
735 }
736
737 return result;
738 }
739
740 /** Get proper glUniformNdv routine for vectors with specified number of rows
741 *
742 * @param gl GL functions
743 * @param n_rows Number of rows
744 *
745 * @return Function address
746 **/
getUniformNdv(const glw::Functions & gl,glw::GLuint n_rows)747 uniformNdv getUniformNdv(const glw::Functions& gl, glw::GLuint n_rows)
748 {
749 uniformNdv result = 0;
750
751 switch (n_rows)
752 {
753 case 1:
754 result = gl.uniform1dv;
755 break;
756 case 2:
757 result = gl.uniform2dv;
758 break;
759 case 3:
760 result = gl.uniform3dv;
761 break;
762 case 4:
763 result = gl.uniform4dv;
764 break;
765 default:
766 TCU_FAIL("Invalid number of rows");
767 }
768
769 return result;
770 }
771
772 /** Get proper glUniformNfv routine for vectors with specified number of rows
773 *
774 * @param gl GL functions
775 * @param n_rows Number of rows
776 *
777 * @return Function address
778 **/
getUniformNfv(const glw::Functions & gl,glw::GLuint n_rows)779 uniformNfv getUniformNfv(const glw::Functions& gl, glw::GLuint n_rows)
780 {
781 uniformNfv result = 0;
782
783 switch (n_rows)
784 {
785 case 1:
786 result = gl.uniform1fv;
787 break;
788 case 2:
789 result = gl.uniform2fv;
790 break;
791 case 3:
792 result = gl.uniform3fv;
793 break;
794 case 4:
795 result = gl.uniform4fv;
796 break;
797 default:
798 TCU_FAIL("Invalid number of rows");
799 }
800
801 return result;
802 }
803
804 /** Get proper glUniformNiv routine for vectors with specified number of rows
805 *
806 * @param gl GL functions
807 * @param n_rows Number of rows
808 *
809 * @return Function address
810 **/
getUniformNiv(const glw::Functions & gl,glw::GLuint n_rows)811 uniformNiv getUniformNiv(const glw::Functions& gl, glw::GLuint n_rows)
812 {
813 uniformNiv result = 0;
814
815 switch (n_rows)
816 {
817 case 1:
818 result = gl.uniform1iv;
819 break;
820 case 2:
821 result = gl.uniform2iv;
822 break;
823 case 3:
824 result = gl.uniform3iv;
825 break;
826 case 4:
827 result = gl.uniform4iv;
828 break;
829 default:
830 TCU_FAIL("Invalid number of rows");
831 }
832
833 return result;
834 }
835
836 /** Get proper glUniformNuiv routine for vectors with specified number of rows
837 *
838 * @param gl GL functions
839 * @param n_rows Number of rows
840 *
841 * @return Function address
842 **/
getUniformNuiv(const glw::Functions & gl,glw::GLuint n_rows)843 uniformNuiv getUniformNuiv(const glw::Functions& gl, glw::GLuint n_rows)
844 {
845 uniformNuiv result = 0;
846
847 switch (n_rows)
848 {
849 case 1:
850 result = gl.uniform1uiv;
851 break;
852 case 2:
853 result = gl.uniform2uiv;
854 break;
855 case 3:
856 result = gl.uniform3uiv;
857 break;
858 case 4:
859 result = gl.uniform4uiv;
860 break;
861 default:
862 TCU_FAIL("Invalid number of rows");
863 }
864
865 return result;
866 }
867
868 /** Get proper glUniformMatrixNdv routine for matrix with specified number of columns and rows
869 *
870 * @param gl GL functions
871 * @param n_rows Number of rows
872 *
873 * @return Function address
874 **/
getUniformMatrixNdv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)875 uniformMatrixNdv getUniformMatrixNdv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
876 {
877 uniformMatrixNdv result = 0;
878
879 switch (n_columns)
880 {
881 case 2:
882 switch (n_rows)
883 {
884 case 2:
885 result = gl.uniformMatrix2dv;
886 break;
887 case 3:
888 result = gl.uniformMatrix2x3dv;
889 break;
890 case 4:
891 result = gl.uniformMatrix2x4dv;
892 break;
893 default:
894 TCU_FAIL("Invalid number of rows");
895 }
896 break;
897 case 3:
898 switch (n_rows)
899 {
900 case 2:
901 result = gl.uniformMatrix3x2dv;
902 break;
903 case 3:
904 result = gl.uniformMatrix3dv;
905 break;
906 case 4:
907 result = gl.uniformMatrix3x4dv;
908 break;
909 default:
910 TCU_FAIL("Invalid number of rows");
911 }
912 break;
913 case 4:
914 switch (n_rows)
915 {
916 case 2:
917 result = gl.uniformMatrix4x2dv;
918 break;
919 case 3:
920 result = gl.uniformMatrix4x3dv;
921 break;
922 case 4:
923 result = gl.uniformMatrix4dv;
924 break;
925 default:
926 TCU_FAIL("Invalid number of rows");
927 }
928 break;
929 default:
930 TCU_FAIL("Invalid number of columns");
931 }
932
933 return result;
934 }
935
936 /** Get proper glUniformMatrixNfv routine for vectors with specified number of columns and rows
937 *
938 * @param gl GL functions
939 * @param n_rows Number of rows
940 *
941 * @return Function address
942 **/
getUniformMatrixNfv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)943 uniformMatrixNfv getUniformMatrixNfv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
944 {
945 uniformMatrixNfv result = 0;
946
947 switch (n_columns)
948 {
949 case 2:
950 switch (n_rows)
951 {
952 case 2:
953 result = gl.uniformMatrix2fv;
954 break;
955 case 3:
956 result = gl.uniformMatrix2x3fv;
957 break;
958 case 4:
959 result = gl.uniformMatrix2x4fv;
960 break;
961 default:
962 TCU_FAIL("Invalid number of rows");
963 }
964 break;
965 case 3:
966 switch (n_rows)
967 {
968 case 2:
969 result = gl.uniformMatrix3x2fv;
970 break;
971 case 3:
972 result = gl.uniformMatrix3fv;
973 break;
974 case 4:
975 result = gl.uniformMatrix3x4fv;
976 break;
977 default:
978 TCU_FAIL("Invalid number of rows");
979 }
980 break;
981 case 4:
982 switch (n_rows)
983 {
984 case 2:
985 result = gl.uniformMatrix4x2fv;
986 break;
987 case 3:
988 result = gl.uniformMatrix4x3fv;
989 break;
990 case 4:
991 result = gl.uniformMatrix4fv;
992 break;
993 default:
994 TCU_FAIL("Invalid number of rows");
995 }
996 break;
997 default:
998 TCU_FAIL("Invalid number of columns");
999 }
1000
1001 return result;
1002 }
1003
verifyVarying(Program & program,const std::string & parent_name,const Variable::Descriptor & desc,std::stringstream & stream,bool is_input)1004 bool verifyVarying(Program& program, const std::string& parent_name, const Variable::Descriptor& desc,
1005 std::stringstream& stream, bool is_input)
1006 {
1007 GLint component = 0;
1008 GLuint index = 0;
1009 GLenum interface = GL_PROGRAM_INPUT;
1010 GLint location = 0;
1011
1012 if (false == is_input)
1013 {
1014 interface = GL_PROGRAM_OUTPUT;
1015 }
1016
1017 const std::string& name = Utils::Variable::GetReference(parent_name, desc, Utils::Variable::BASIC, 0);
1018
1019 try
1020 {
1021 index = program.GetResourceIndex(name, interface);
1022
1023 program.GetResource(interface, index, GL_LOCATION, 1 /* size */, &location);
1024 program.GetResource(interface, index, GL_LOCATION_COMPONENT, 1 /* size */, &component);
1025 }
1026 catch (std::exception& exc)
1027 {
1028 stream << "Failed to query program for varying: " << desc.m_name << ". Reason: " << exc.what() << "\n";
1029
1030 return false;
1031 }
1032
1033 bool result = true;
1034
1035 if (location != desc.m_expected_location)
1036 {
1037 stream << "Attribute: " << desc.m_name << " - invalid location: " << location
1038 << " expected: " << desc.m_expected_location << std::endl;
1039 result = false;
1040 }
1041 if (component != desc.m_expected_component)
1042 {
1043 stream << "Attribute: " << desc.m_name << " - invalid component: " << component
1044 << " expected: " << desc.m_expected_component << std::endl;
1045 result = false;
1046 }
1047
1048 return result;
1049 }
1050
1051 /** Query program resource for given variable and verify that everything is as expected
1052 *
1053 * @param program Program object
1054 * @param variable Variable object
1055 * @param stream Stream that will be used to log any error
1056 * @param is_input Selects if varying is input or output
1057 *
1058 * @return true if verification is positive, false otherwise
1059 **/
checkVarying(Program & program,Shader::STAGES stage,const Variable & variable,std::stringstream & stream,bool is_input)1060 bool checkVarying(Program& program, Shader::STAGES stage, const Variable& variable, std::stringstream& stream, bool is_input)
1061 {
1062 bool result = true;
1063
1064 if (variable.IsBlock())
1065 {
1066 Utils::Interface* interface = variable.m_descriptor.m_interface;
1067 const size_t n_members = interface->m_members.size();
1068
1069 for (size_t i = 0; i < n_members; ++i)
1070 {
1071 const Variable::Descriptor& member = interface->m_members[i];
1072 bool member_result = verifyVarying(program, interface->m_name, member, stream, is_input);
1073
1074 if (false == member_result)
1075 {
1076 result = false;
1077 }
1078 }
1079 }
1080 /*
1081 To query the the location of struct member by glGetProgramResource, we need pass the variable name "gs_fs_output[0].single",
1082 but in original implementation, the test pass the name "Data.single", which can't get any valid result.
1083 struct Data {
1084 dmat2 single;
1085 dmat2 array[1];
1086 };
1087 layout (location = 0) in Data gs_fs_output[1];
1088 */
1089 else if (variable.IsStruct())
1090 {
1091 Utils::Interface* interface = variable.m_descriptor.m_interface;
1092 const size_t n_members = interface->m_members.size();
1093 std::string structVariable = variable.m_descriptor.m_name;
1094
1095 switch (Variable::GetFlavour(stage, is_input ? Variable::INPUT : Variable::OUTPUT))
1096 {
1097 case Variable::ARRAY:
1098 case Variable::INDEXED_BY_INVOCATION_ID:
1099 structVariable.append("[0]");
1100 break;
1101 default:
1102 break;
1103 }
1104
1105 // If struct variable is an array
1106 if (0 != variable.m_descriptor.m_n_array_elements)
1107 {
1108 for (GLuint i = 0; i < variable.m_descriptor.m_n_array_elements; i++)
1109 {
1110 GLchar buffer[16];
1111 sprintf(buffer, "%d", i);
1112 structVariable.append("[");
1113 structVariable.append(buffer);
1114 structVariable.append("]");
1115 for (size_t j = 0; j < n_members; ++j)
1116 {
1117 const Variable::Descriptor& member = interface->m_members[j];
1118 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1119
1120 if (false == member_result)
1121 {
1122 result = false;
1123 }
1124 }
1125 }
1126 }
1127 else
1128 {
1129 for (GLuint i = 0; i < n_members; ++i)
1130 {
1131 const Variable::Descriptor& member = interface->m_members[i];
1132 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1133
1134 if (false == member_result)
1135 {
1136 result = false;
1137 }
1138 }
1139 }
1140 }
1141 else
1142 {
1143 result = verifyVarying(program, "", variable.m_descriptor, stream, is_input);
1144 }
1145 return result;
1146 }
1147
1148 /** Query program resource for given variable and verify that everything is as expected
1149 *
1150 * @param program Program object
1151 * @param variable Variable object
1152 * @param stream Stream that will be used to log any error
1153 *
1154 * @return true if verification is positive, false otherwise
1155 **/
checkUniform(Program & program,const Utils::Variable & variable,std::stringstream & stream)1156 bool checkUniform(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1157 {
1158 bool result = true;
1159
1160 if (false == variable.IsBlock())
1161 {
1162 TCU_FAIL("Not implemented");
1163 }
1164 else
1165 {
1166 Utils::Interface* interface = variable.m_descriptor.m_interface;
1167
1168 size_t size = interface->m_members.size();
1169
1170 std::vector<GLuint> indices;
1171 std::vector<const char*> names;
1172 std::vector<std::string> names_str;
1173 std::vector<GLint> offsets;
1174
1175 indices.resize(size);
1176 names.resize(size);
1177 names_str.resize(size);
1178 offsets.resize(size);
1179
1180 for (size_t i = 0; i < size; ++i)
1181 {
1182 indices[i] = 0;
1183 offsets[i] = 0;
1184
1185 const std::string& name =
1186 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1187
1188 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1189 {
1190 const std::string& member_name = Utils::Variable::GetReference(
1191 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1192
1193 names_str[i] = member_name;
1194 }
1195 else
1196 {
1197 names_str[i] = name;
1198 }
1199
1200 names[i] = names_str[i].c_str();
1201 }
1202
1203 try
1204 {
1205 program.GetUniformIndices(static_cast<glw::GLsizei>(size), &names[0], &indices[0]);
1206 program.GetActiveUniformsiv(static_cast<glw::GLsizei>(size), &indices[0], GL_UNIFORM_OFFSET, &offsets[0]);
1207 }
1208 catch (std::exception& exc)
1209 {
1210 stream << "Failed to query program for uniforms in block: " << variable.m_descriptor.m_name
1211 << ". Reason: " << exc.what() << "\n";
1212
1213 return false;
1214 }
1215
1216 for (size_t i = 0; i < size; ++i)
1217 {
1218 Utils::Variable::Descriptor& desc = interface->m_members[i];
1219
1220 if (offsets[i] != (GLint)desc.m_offset)
1221 {
1222 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offsets[i]
1223 << " expected: " << desc.m_offset << std::endl;
1224 result = false;
1225 }
1226 }
1227 }
1228
1229 return result;
1230 }
1231
1232 /** Query program resource for given variable and verify that everything is as expected
1233 *
1234 * @param program Program object
1235 * @param variable Variable object
1236 * @param stream Stream that will be used to log any error
1237 *
1238 * @return true if verification is positive, false otherwise
1239 **/
checkSSB(Program & program,const Utils::Variable & variable,std::stringstream & stream)1240 bool checkSSB(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1241 {
1242 bool result = true;
1243
1244 if (false == variable.IsBlock())
1245 {
1246 TCU_FAIL("Not implemented");
1247 }
1248 else
1249 {
1250 Utils::Interface* interface = variable.m_descriptor.m_interface;
1251
1252 size_t size = interface->m_members.size();
1253
1254 for (size_t i = 0; i < size; ++i)
1255 {
1256 GLuint index = 0;
1257 std::string name_str = "";
1258 GLint offset = 0;
1259
1260 const std::string& name =
1261 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1262
1263 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1264 {
1265 const std::string& member_name = Utils::Variable::GetReference(
1266 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1267
1268 name_str = member_name;
1269 }
1270 else
1271 {
1272 name_str = name;
1273 }
1274
1275 try
1276 {
1277 index = program.GetResourceIndex(name_str, GL_BUFFER_VARIABLE);
1278
1279 program.GetResource(GL_BUFFER_VARIABLE, index, GL_OFFSET, 1, &offset);
1280 }
1281 catch (std::exception& exc)
1282 {
1283 stream << "Failed to query program for buffer variable: " << variable.m_descriptor.m_name
1284 << ". Reason: " << exc.what() << "\n";
1285
1286 return false;
1287 }
1288
1289 Utils::Variable::Descriptor& desc = interface->m_members[i];
1290
1291 if (offset != (GLint)desc.m_offset)
1292 {
1293 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offset
1294 << " expected: " << desc.m_offset << std::endl;
1295 result = false;
1296 }
1297 }
1298 }
1299
1300 return result;
1301 }
1302
1303 /** Query program resources at given stage and verifies results
1304 *
1305 * @param program Program object
1306 * @param program_interface Definition of program interface
1307 * @param stage Stage to be verified
1308 * @param check_inputs Select if inputs should be verified
1309 * @param check_outputs Select if output should be verified
1310 * @param check_uniforms Select if uniforms should be verified
1311 * @param check_ssbs Select if buffers should be verified
1312 * @param stream Stream that will be used to log any error
1313 *
1314 * @return true if verification is positive, false otherwise
1315 **/
checkProgramStage(Program & program,const ProgramInterface & program_interface,Utils::Shader::STAGES stage,bool check_inputs,bool check_outputs,bool check_uniforms,bool check_ssbs,std::stringstream & stream)1316 bool checkProgramStage(Program& program, const ProgramInterface& program_interface, Utils::Shader::STAGES stage,
1317 bool check_inputs, bool check_outputs, bool check_uniforms, bool check_ssbs,
1318 std::stringstream& stream)
1319 {
1320 typedef Variable::PtrVector::const_iterator const_iterator;
1321
1322 const ShaderInterface& interface = program_interface.GetShaderInterface(stage);
1323
1324 bool result = true;
1325
1326 /* Inputs */
1327 if (true == check_inputs)
1328 {
1329 const Variable::PtrVector& inputs = interface.m_inputs;
1330
1331 for (const_iterator it = inputs.begin(); it != inputs.end(); ++it)
1332 {
1333 if (false == checkVarying(program, stage, **it, stream, true))
1334 {
1335 result = false;
1336 }
1337 }
1338 }
1339
1340 /* Outputs */
1341 if (true == check_outputs)
1342 {
1343 const Variable::PtrVector& outputs = interface.m_outputs;
1344
1345 for (const_iterator it = outputs.begin(); it != outputs.end(); ++it)
1346 {
1347 if (false == checkVarying(program, stage, **it, stream, false))
1348 {
1349 result = false;
1350 }
1351 }
1352 }
1353
1354 /* Uniforms */
1355 if (true == check_uniforms)
1356 {
1357 const Variable::PtrVector& uniforms = interface.m_uniforms;
1358
1359 for (const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
1360 {
1361 if (false == checkUniform(program, **it, stream))
1362 {
1363 result = false;
1364 }
1365 }
1366 }
1367
1368 /* SSBs */
1369 if (true == check_ssbs)
1370 {
1371 const Variable::PtrVector& ssbs = interface.m_ssb_blocks;
1372
1373 for (const_iterator it = ssbs.begin(); it != ssbs.end(); ++it)
1374 {
1375 if (false == checkSSB(program, **it, stream))
1376 {
1377 result = false;
1378 }
1379 }
1380 }
1381
1382 return result;
1383 }
1384
1385 /** Query resources of monolithic compute program and verifies results
1386 *
1387 * @param program Program object
1388 * @param program_interface Definition of program interface
1389 * @param stream Stream that will be used to log any error
1390 *
1391 * @return true if verification is positive, false otherwise
1392 **/
checkMonolithicComputeProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1393 bool checkMonolithicComputeProgramInterface(Program& program, const ProgramInterface& program_interface,
1394 std::stringstream& stream)
1395 {
1396 bool result = true;
1397
1398 if (false == checkProgramStage(program, program_interface, Shader::COMPUTE, false, false, true, true, stream))
1399 {
1400 result = false;
1401 }
1402
1403 /* Done */
1404 return result;
1405 }
1406
1407 /** Query resources of monolithic draw program and verifies results
1408 *
1409 * @param program Program object
1410 * @param program_interface Definition of program interface
1411 * @param stream Stream that will be used to log any error
1412 *
1413 * @return true if verification is positive, false otherwise
1414 **/
checkMonolithicDrawProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1415 bool checkMonolithicDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1416 std::stringstream& stream)
1417 {
1418 bool result = true;
1419
1420 if (false == checkProgramStage(program, program_interface, Shader::VERTEX, true, false, true, true, stream))
1421 {
1422 result = false;
1423 }
1424
1425 /* Done */
1426 return result;
1427 }
1428
1429 /** Query resources of separable draw program and verifies results
1430 *
1431 * @param program Program object
1432 * @param program_interface Definition of program interface
1433 * @param stream Stream that will be used to log any error
1434 *
1435 * @return true if verification is positive, false otherwise
1436 **/
checkSeparableDrawProgramInterface(Program & program,const ProgramInterface & program_interface,Utils::Shader::STAGES stage,std::stringstream & stream)1437 bool checkSeparableDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1438 Utils::Shader::STAGES stage, std::stringstream& stream)
1439 {
1440 bool result = true;
1441
1442 if (false == checkProgramStage(program, program_interface, stage, true, true, true, true, stream))
1443 {
1444 result = false;
1445 }
1446
1447 /* Done */
1448 return result;
1449 }
1450
1451 /** Check if extension is supported
1452 *
1453 * @param context Test context
1454 * @param extension_name Name of extension
1455 *
1456 * @return true if extension is supported, false otherwise
1457 **/
isExtensionSupported(deqp::Context & context,const GLchar * extension_name)1458 bool isExtensionSupported(deqp::Context& context, const GLchar* extension_name)
1459 {
1460 const std::vector<std::string>& extensions = context.getContextInfo().getExtensions();
1461
1462 if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
1463 {
1464 return false;
1465 }
1466
1467 return true;
1468 }
1469
1470 /** Check if GL context meets version requirements
1471 *
1472 * @param gl Functions
1473 * @param required_major Minimum required MAJOR_VERSION
1474 * @param required_minor Minimum required MINOR_VERSION
1475 *
1476 * @return true if GL context version is at least as requested, false otherwise
1477 **/
isGLVersionAtLeast(const Functions & gl,GLint required_major,GLint required_minor)1478 bool isGLVersionAtLeast(const Functions& gl, GLint required_major, GLint required_minor)
1479 {
1480 glw::GLint major = 0;
1481 glw::GLint minor = 0;
1482
1483 gl.getIntegerv(GL_MAJOR_VERSION, &major);
1484 gl.getIntegerv(GL_MINOR_VERSION, &minor);
1485
1486 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1487
1488 if (major > required_major)
1489 {
1490 /* Major is higher than required one */
1491 return true;
1492 }
1493 else if (major == required_major)
1494 {
1495 if (minor >= required_minor)
1496 {
1497 /* Major is equal to required one */
1498 /* Minor is higher than or equal to required one */
1499 return true;
1500 }
1501 else
1502 {
1503 /* Major is equal to required one */
1504 /* Minor is lower than required one */
1505 return false;
1506 }
1507 }
1508 else
1509 {
1510 /* Major is lower than required one */
1511 return false;
1512 }
1513 }
1514
1515 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1516 *
1517 * @param token Token string
1518 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1519 * @param text String that will be used as replacement for <token>
1520 * @param string String to work on
1521 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1522 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1523 {
1524 const size_t text_length = strlen(text);
1525 const size_t token_length = strlen(token);
1526 const size_t token_position = string.find(token, search_position);
1527
1528 #if DEBUG_REPLACE_TOKEN
1529 if (std::string::npos == token_position)
1530 {
1531 string.append("\n\nInvalid token: ");
1532 string.append(token);
1533
1534 TCU_FAIL(string.c_str());
1535 }
1536 #endif /* DEBUG_REPLACE_TOKEN */
1537
1538 string.replace(token_position, token_length, text, text_length);
1539
1540 search_position = token_position + text_length;
1541 }
1542
1543 /** Replace all occurances of <token> with <text> in <string>
1544 *
1545 * @param token Token string
1546 * @param text String that will be used as replacement for <token>
1547 * @param string String to work on
1548 **/
replaceAllTokens(const GLchar * token,const GLchar * text,std::string & string)1549 void replaceAllTokens(const GLchar* token, const GLchar* text, std::string& string)
1550 {
1551 const size_t text_length = strlen(text);
1552 const size_t token_length = strlen(token);
1553
1554 size_t search_position = 0;
1555
1556 while (1)
1557 {
1558 const size_t token_position = string.find(token, search_position);
1559
1560 if (std::string::npos == token_position)
1561 {
1562 break;
1563 }
1564
1565 search_position = token_position + text_length;
1566
1567 string.replace(token_position, token_length, text, text_length);
1568 }
1569 }
1570
1571 /** Rounds up the value to the next power of 2.
1572 * This routine does not work for 0, see the url for explanations.
1573 *
1574 * @param value Starting point
1575 *
1576 * @return Calculated value
1577 **/
roundUpToPowerOf2(glw::GLuint value)1578 glw::GLuint roundUpToPowerOf2(glw::GLuint value)
1579 {
1580 /* Taken from: graphics.stanford.edu/~seander/bithacks.html */
1581 --value;
1582
1583 value |= value >> 1;
1584 value |= value >> 2;
1585 value |= value >> 4;
1586 value |= value >> 8;
1587 value |= value >> 16;
1588
1589 ++value;
1590
1591 return value;
1592 }
1593
1594 /** Insert elements of list into string.
1595 * List in string is represented either by token "LIST" or "SEPARATORLIST".
1596 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>.
1597 * LIST is replaced with <element>SEPARATORLIST
1598 *
1599 * @param element Element to be inserted
1600 * @param separator Separator inserted between elements
1601 * @param search_position Position in string, where search for list should start
1602 * @param string String
1603 **/
insertElementOfList(const GLchar * element,const GLchar * separator,size_t & search_position,std::string & string)1604 void insertElementOfList(const GLchar* element, const GLchar* separator, size_t& search_position, std::string& string)
1605 {
1606 static const char* list = g_list;
1607 static const char* sep_list = "SEPARATORLIST";
1608
1609 /* Try to get "list" positions */
1610 const size_t list_position = string.find(list, search_position);
1611 const size_t sep_list_position = string.find(sep_list, search_position);
1612
1613 /* There is no list in string */
1614 if (std::string::npos == list_position)
1615 {
1616 return;
1617 }
1618
1619 if (9 /* strlen(SEPARATOR) */ == list_position - sep_list_position)
1620 {
1621 replaceToken("SEPARATOR", search_position, separator, string);
1622 }
1623
1624 /* Save search_position */
1625 const size_t start_position = search_position;
1626
1627 /* Prepare new element */
1628 replaceToken("LIST", search_position, "ELEMENTSEPARATORLIST", string);
1629
1630 /* Restore search_position */
1631 search_position = start_position;
1632
1633 /* Replace element and separator */
1634 replaceToken("ELEMENT", search_position, element, string);
1635 }
1636
1637 /** Close list in string.
1638 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>
1639 * LIST is replaced with ""
1640 *
1641 * @param separator Separator inserted between elements
1642 * @param search_position Position in string, where search for list should start
1643 * @param string String
1644 **/
endList(const glw::GLchar * separator,size_t & search_position,std::string & string)1645 void endList(const glw::GLchar* separator, size_t& search_position, std::string& string)
1646 {
1647 const size_t sep_position = string.find("SEPARATOR", search_position);
1648 if (std::string::npos != sep_position)
1649 {
1650 replaceToken("SEPARATOR", search_position, separator, string);
1651 }
1652
1653 replaceToken("LIST", search_position, "", string);
1654 }
1655
1656 /* Buffer constants */
1657 const GLuint Buffer::m_invalid_id = -1;
1658
1659 /** Constructor.
1660 *
1661 * @param context CTS context.
1662 **/
Buffer(deqp::Context & context)1663 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_buffer(Array), m_context(context)
1664 {
1665 }
1666
1667 /** Destructor
1668 *
1669 **/
~Buffer()1670 Buffer::~Buffer()
1671 {
1672 Release();
1673 }
1674
1675 /** Initialize buffer instance
1676 *
1677 * @param buffer Buffer type
1678 * @param usage Buffer usage enum
1679 * @param size <size> parameter
1680 * @param data <data> parameter
1681 **/
Init(BUFFERS buffer,USAGE usage,GLsizeiptr size,GLvoid * data)1682 void Buffer::Init(BUFFERS buffer, USAGE usage, GLsizeiptr size, GLvoid* data)
1683 {
1684 /* Delete previous buffer instance */
1685 Release();
1686
1687 m_buffer = buffer;
1688
1689 const Functions& gl = m_context.getRenderContext().getFunctions();
1690
1691 Generate(gl, m_id);
1692 Bind(gl, m_id, m_buffer);
1693 Data(gl, m_buffer, usage, size, data);
1694 }
1695
1696 /** Release buffer instance
1697 *
1698 **/
Release()1699 void Buffer::Release()
1700 {
1701 if (m_invalid_id != m_id)
1702 {
1703 const Functions& gl = m_context.getRenderContext().getFunctions();
1704
1705 gl.deleteBuffers(1, &m_id);
1706 m_id = m_invalid_id;
1707 }
1708 }
1709
1710 /** Binds buffer to its target
1711 *
1712 **/
Bind() const1713 void Buffer::Bind() const
1714 {
1715 const Functions& gl = m_context.getRenderContext().getFunctions();
1716
1717 Bind(gl, m_id, m_buffer);
1718 }
1719
1720 /** Binds indexed buffer
1721 *
1722 * @param index <index> parameter
1723 **/
BindBase(GLuint index) const1724 void Buffer::BindBase(GLuint index) const
1725 {
1726 const Functions& gl = m_context.getRenderContext().getFunctions();
1727
1728 BindBase(gl, m_id, m_buffer, index);
1729 }
1730
1731 /** Binds range of buffer
1732 *
1733 * @param index <index> parameter
1734 * @param offset <offset> parameter
1735 * @param size <size> parameter
1736 **/
BindRange(GLuint index,GLintptr offset,GLsizeiptr size) const1737 void Buffer::BindRange(GLuint index, GLintptr offset, GLsizeiptr size) const
1738 {
1739 const Functions& gl = m_context.getRenderContext().getFunctions();
1740
1741 BindRange(gl, m_id, m_buffer, index, offset, size);
1742 }
1743
1744 /** Allocate memory for buffer and sends initial content
1745 *
1746 * @param usage Buffer usage enum
1747 * @param size <size> parameter
1748 * @param data <data> parameter
1749 **/
Data(USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1750 void Buffer::Data(USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1751 {
1752 const Functions& gl = m_context.getRenderContext().getFunctions();
1753
1754 Data(gl, m_buffer, usage, size, data);
1755 }
1756
1757 /** Maps contents of buffer into CPU space
1758 *
1759 * @param access Requested access
1760 *
1761 * @return Pointer to memory region available for CPU
1762 **/
Map(ACCESS access)1763 GLvoid* Buffer::Map(ACCESS access)
1764 {
1765 const Functions& gl = m_context.getRenderContext().getFunctions();
1766
1767 return Map(gl, m_buffer, access);
1768 }
1769
1770 /** Allocate memory for buffer and sends initial content
1771 *
1772 * @param offset Offset in buffer
1773 * @param size <size> parameter
1774 * @param data <data> parameter
1775 **/
SubData(glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1776 void Buffer::SubData(glw::GLintptr offset, glw::GLsizeiptr size, glw::GLvoid* data)
1777 {
1778 const Functions& gl = m_context.getRenderContext().getFunctions();
1779
1780 SubData(gl, m_buffer, offset, size, data);
1781 }
1782
1783 /** Maps contents of buffer into CPU space
1784 **/
UnMap()1785 void Buffer::UnMap()
1786 {
1787 const Functions& gl = m_context.getRenderContext().getFunctions();
1788
1789 return UnMap(gl, m_buffer);
1790 }
1791
1792 /** Bind buffer to given target
1793 *
1794 * @param gl GL functions
1795 * @param id Id of buffer
1796 * @param buffer Buffer enum
1797 **/
Bind(const Functions & gl,GLuint id,BUFFERS buffer)1798 void Buffer::Bind(const Functions& gl, GLuint id, BUFFERS buffer)
1799 {
1800 GLenum target = GetBufferGLenum(buffer);
1801
1802 gl.bindBuffer(target, id);
1803 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
1804 }
1805
1806 /** Binds indexed buffer
1807 *
1808 * @param gl GL functions
1809 * @param id Id of buffer
1810 * @param buffer Buffer enum
1811 * @param index <index> parameter
1812 **/
BindBase(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index)1813 void Buffer::BindBase(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index)
1814 {
1815 GLenum target = GetBufferGLenum(buffer);
1816
1817 gl.bindBufferBase(target, index, id);
1818 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
1819 }
1820
1821 /** Binds buffer range
1822 *
1823 * @param gl GL functions
1824 * @param id Id of buffer
1825 * @param buffer Buffer enum
1826 * @param index <index> parameter
1827 * @param offset <offset> parameter
1828 * @param size <size> parameter
1829 **/
BindRange(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index,GLintptr offset,GLsizeiptr size)1830 void Buffer::BindRange(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index, GLintptr offset, GLsizeiptr size)
1831 {
1832 GLenum target = GetBufferGLenum(buffer);
1833
1834 gl.bindBufferRange(target, index, id, offset, size);
1835 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
1836 }
1837
1838 /** Allocate memory for buffer and sends initial content
1839 *
1840 * @param gl GL functions
1841 * @param buffer Buffer enum
1842 * @param usage Buffer usage enum
1843 * @param size <size> parameter
1844 * @param data <data> parameter
1845 **/
Data(const glw::Functions & gl,BUFFERS buffer,USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1846 void Buffer::Data(const glw::Functions& gl, BUFFERS buffer, USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1847 {
1848 GLenum target = GetBufferGLenum(buffer);
1849 GLenum gl_usage = GetUsageGLenum(usage);
1850
1851 gl.bufferData(target, size, data, gl_usage);
1852 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
1853 }
1854
1855 /** Allocate memory for buffer and sends initial content
1856 *
1857 * @param gl GL functions
1858 * @param buffer Buffer enum
1859 * @param offset Offset in buffer
1860 * @param size <size> parameter
1861 * @param data <data> parameter
1862 **/
SubData(const glw::Functions & gl,BUFFERS buffer,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1863 void Buffer::SubData(const glw::Functions& gl, BUFFERS buffer, glw::GLintptr offset, glw::GLsizeiptr size,
1864 glw::GLvoid* data)
1865 {
1866 GLenum target = GetBufferGLenum(buffer);
1867
1868 gl.bufferSubData(target, offset, size, data);
1869 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
1870 }
1871
1872 /** Generate buffer
1873 *
1874 * @param gl GL functions
1875 * @param out_id Id of buffer
1876 **/
Generate(const Functions & gl,GLuint & out_id)1877 void Buffer::Generate(const Functions& gl, GLuint& out_id)
1878 {
1879 GLuint id = m_invalid_id;
1880
1881 gl.genBuffers(1, &id);
1882 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
1883
1884 if (m_invalid_id == id)
1885 {
1886 TCU_FAIL("Got invalid id");
1887 }
1888
1889 out_id = id;
1890 }
1891
1892 /** Maps buffer content
1893 *
1894 * @param gl GL functions
1895 * @param buffer Buffer enum
1896 * @param access Access rights for mapped region
1897 *
1898 * @return Mapped memory
1899 **/
Map(const Functions & gl,BUFFERS buffer,ACCESS access)1900 void* Buffer::Map(const Functions& gl, BUFFERS buffer, ACCESS access)
1901 {
1902 GLenum target = GetBufferGLenum(buffer);
1903 GLenum gl_access = GetAccessGLenum(access);
1904
1905 void* result = gl.mapBuffer(target, gl_access);
1906 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
1907
1908 return result;
1909 }
1910
1911 /** Unmaps buffer
1912 *
1913 **/
UnMap(const Functions & gl,BUFFERS buffer)1914 void Buffer::UnMap(const Functions& gl, BUFFERS buffer)
1915 {
1916 GLenum target = GetBufferGLenum(buffer);
1917
1918 gl.unmapBuffer(target);
1919 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
1920 }
1921
1922 /** Return GLenum representation of requested access
1923 *
1924 * @param access Requested access
1925 *
1926 * @return GLenum value
1927 **/
GetAccessGLenum(ACCESS access)1928 GLenum Buffer::GetAccessGLenum(ACCESS access)
1929 {
1930 GLenum result = 0;
1931
1932 switch (access)
1933 {
1934 case ReadOnly:
1935 result = GL_READ_ONLY;
1936 break;
1937 case WriteOnly:
1938 result = GL_WRITE_ONLY;
1939 break;
1940 case ReadWrite:
1941 result = GL_READ_WRITE;
1942 break;
1943 default:
1944 TCU_FAIL("Invalid enum");
1945 }
1946
1947 return result;
1948 }
1949
1950 /** Return GLenum representation of requested buffer type
1951 *
1952 * @param buffer Requested buffer type
1953 *
1954 * @return GLenum value
1955 **/
GetBufferGLenum(BUFFERS buffer)1956 GLenum Buffer::GetBufferGLenum(BUFFERS buffer)
1957 {
1958 GLenum result = 0;
1959
1960 switch (buffer)
1961 {
1962 case Array:
1963 result = GL_ARRAY_BUFFER;
1964 break;
1965 case Element:
1966 result = GL_ELEMENT_ARRAY_BUFFER;
1967 break;
1968 case Shader_Storage:
1969 result = GL_SHADER_STORAGE_BUFFER;
1970 break;
1971 case Texture:
1972 result = GL_TEXTURE_BUFFER;
1973 break;
1974 case Transform_feedback:
1975 result = GL_TRANSFORM_FEEDBACK_BUFFER;
1976 break;
1977 case Uniform:
1978 result = GL_UNIFORM_BUFFER;
1979 break;
1980 default:
1981 TCU_FAIL("Invalid enum");
1982 }
1983
1984 return result;
1985 }
1986
1987 /** Return GLenum representation of requested usage
1988 *
1989 * @param usage Requested usage
1990 *
1991 * @return GLenum value
1992 **/
GetUsageGLenum(USAGE usage)1993 GLenum Buffer::GetUsageGLenum(USAGE usage)
1994 {
1995 GLenum result = 0;
1996
1997 switch (usage)
1998 {
1999 case DynamicCopy:
2000 result = GL_DYNAMIC_COPY;
2001 break;
2002 case DynamicDraw:
2003 result = GL_DYNAMIC_DRAW;
2004 break;
2005 case DynamicRead:
2006 result = GL_DYNAMIC_READ;
2007 break;
2008 case StaticCopy:
2009 result = GL_STATIC_COPY;
2010 break;
2011 case StaticDraw:
2012 result = GL_STATIC_DRAW;
2013 break;
2014 case StaticRead:
2015 result = GL_STATIC_READ;
2016 break;
2017 case StreamCopy:
2018 result = GL_STREAM_COPY;
2019 break;
2020 case StreamDraw:
2021 result = GL_STREAM_DRAW;
2022 break;
2023 case StreamRead:
2024 result = GL_STREAM_READ;
2025 break;
2026 default:
2027 TCU_FAIL("Invalid enum");
2028 }
2029
2030 return result;
2031 }
2032
2033 /** Returns name of buffer target
2034 *
2035 * @param buffer Target enum
2036 *
2037 * @return Name of target
2038 **/
GetBufferName(BUFFERS buffer)2039 const GLchar* Buffer::GetBufferName(BUFFERS buffer)
2040 {
2041 const GLchar* name = 0;
2042
2043 switch (buffer)
2044 {
2045 case Array:
2046 name = "Array";
2047 break;
2048 case Element:
2049 name = "Element";
2050 break;
2051 case Shader_Storage:
2052 name = "Shader_Storage";
2053 break;
2054 case Texture:
2055 name = "Texture";
2056 break;
2057 case Transform_feedback:
2058 name = "Transform_feedback";
2059 break;
2060 case Uniform:
2061 name = "Uniform";
2062 break;
2063 default:
2064 TCU_FAIL("Invalid enum");
2065 }
2066
2067 return name;
2068 }
2069
2070 /* Framebuffer constants */
2071 const GLuint Framebuffer::m_invalid_id = -1;
2072
2073 /** Constructor
2074 *
2075 * @param context CTS context
2076 **/
Framebuffer(deqp::Context & context)2077 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2078 {
2079 /* Nothing to be done here */
2080 }
2081
2082 /** Destructor
2083 *
2084 **/
~Framebuffer()2085 Framebuffer::~Framebuffer()
2086 {
2087 Release();
2088 }
2089
2090 /** Initialize framebuffer instance
2091 *
2092 **/
Init()2093 void Framebuffer::Init()
2094 {
2095 /* Delete previous instance */
2096 Release();
2097
2098 const Functions& gl = m_context.getRenderContext().getFunctions();
2099
2100 Generate(gl, m_id);
2101 }
2102
2103 /** Release framebuffer instance
2104 *
2105 **/
Release()2106 void Framebuffer::Release()
2107 {
2108 if (m_invalid_id != m_id)
2109 {
2110 const Functions& gl = m_context.getRenderContext().getFunctions();
2111
2112 gl.deleteFramebuffers(1, &m_id);
2113 m_id = m_invalid_id;
2114 }
2115 }
2116
2117 /** Attach texture to specified attachment
2118 *
2119 * @param attachment Attachment
2120 * @param texture_id Texture id
2121 * @param width Texture width
2122 * @param height Texture height
2123 **/
AttachTexture(GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2124 void Framebuffer::AttachTexture(GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2125 {
2126 const Functions& gl = m_context.getRenderContext().getFunctions();
2127
2128 AttachTexture(gl, attachment, texture_id, width, height);
2129 }
2130
2131 /** Binds framebuffer to DRAW_FRAMEBUFFER
2132 *
2133 **/
Bind()2134 void Framebuffer::Bind()
2135 {
2136 const Functions& gl = m_context.getRenderContext().getFunctions();
2137
2138 Bind(gl, m_id);
2139 }
2140
2141 /** Clear framebuffer
2142 *
2143 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2144 **/
Clear(GLenum mask)2145 void Framebuffer::Clear(GLenum mask)
2146 {
2147 const Functions& gl = m_context.getRenderContext().getFunctions();
2148
2149 Clear(gl, mask);
2150 }
2151
2152 /** Specifies clear color
2153 *
2154 * @param red Red channel
2155 * @param green Green channel
2156 * @param blue Blue channel
2157 * @param alpha Alpha channel
2158 **/
ClearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2159 void Framebuffer::ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2160 {
2161 const Functions& gl = m_context.getRenderContext().getFunctions();
2162
2163 ClearColor(gl, red, green, blue, alpha);
2164 }
2165
2166 /** Attach texture to specified attachment
2167 *
2168 * @param gl GL functions
2169 * @param attachment Attachment
2170 * @param texture_id Texture id
2171 * @param width Texture width
2172 * @param height Texture height
2173 **/
AttachTexture(const Functions & gl,GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2174 void Framebuffer::AttachTexture(const Functions& gl, GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2175 {
2176 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
2177 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
2178
2179 gl.viewport(0 /* x */, 0 /* y */, width, height);
2180 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
2181 }
2182
2183 /** Binds framebuffer to DRAW_FRAMEBUFFER
2184 *
2185 * @param gl GL functions
2186 * @param id ID of framebuffer
2187 **/
Bind(const Functions & gl,GLuint id)2188 void Framebuffer::Bind(const Functions& gl, GLuint id)
2189 {
2190 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
2191 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
2192 }
2193
2194 /** Clear framebuffer
2195 *
2196 * @param gl GL functions
2197 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2198 **/
Clear(const Functions & gl,GLenum mask)2199 void Framebuffer::Clear(const Functions& gl, GLenum mask)
2200 {
2201 gl.clear(mask);
2202 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2203 }
2204
2205 /** Specifies clear color
2206 *
2207 * @param gl GL functions
2208 * @param red Red channel
2209 * @param green Green channel
2210 * @param blue Blue channel
2211 * @param alpha Alpha channel
2212 **/
ClearColor(const Functions & gl,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2213 void Framebuffer::ClearColor(const Functions& gl, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2214 {
2215 gl.clearColor(red, green, blue, alpha);
2216 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2217 }
2218
2219 /** Generate framebuffer
2220 *
2221 **/
Generate(const Functions & gl,GLuint & out_id)2222 void Framebuffer::Generate(const Functions& gl, GLuint& out_id)
2223 {
2224 GLuint id = m_invalid_id;
2225
2226 gl.genFramebuffers(1, &id);
2227 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
2228
2229 if (m_invalid_id == id)
2230 {
2231 TCU_FAIL("Invalid id");
2232 }
2233
2234 out_id = id;
2235 }
2236
2237 /* Shader's constants */
2238 const GLuint Shader::m_invalid_id = 0;
2239
2240 /** Constructor.
2241 *
2242 * @param context CTS context.
2243 **/
Shader(deqp::Context & context)2244 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2245 {
2246 /* Nothing to be done here */
2247 }
2248
2249 /** Destructor
2250 *
2251 **/
~Shader()2252 Shader::~Shader()
2253 {
2254 Release();
2255 }
2256
2257 /** Initialize shader instance
2258 *
2259 * @param stage Shader stage
2260 * @param source Source code
2261 **/
Init(STAGES stage,const std::string & source)2262 void Shader::Init(STAGES stage, const std::string& source)
2263 {
2264 if (true == source.empty())
2265 {
2266 /* No source == no shader */
2267 return;
2268 }
2269
2270 /* Delete any previous shader */
2271 Release();
2272
2273 /* Create, set source and compile */
2274 const Functions& gl = m_context.getRenderContext().getFunctions();
2275
2276 Create(gl, stage, m_id);
2277 Source(gl, m_id, source);
2278
2279 try
2280 {
2281 Compile(gl, m_id);
2282 }
2283 catch (const CompilationException& exc)
2284 {
2285 throw InvalidSourceException(exc.what(), source, stage);
2286 }
2287 }
2288
2289 /** Release shader instance
2290 *
2291 **/
Release()2292 void Shader::Release()
2293 {
2294 if (m_invalid_id != m_id)
2295 {
2296 const Functions& gl = m_context.getRenderContext().getFunctions();
2297
2298 gl.deleteShader(m_id);
2299 m_id = m_invalid_id;
2300 }
2301 }
2302
2303 /** Compile shader
2304 *
2305 * @param gl GL functions
2306 * @param id Shader id
2307 **/
Compile(const Functions & gl,GLuint id)2308 void Shader::Compile(const Functions& gl, GLuint id)
2309 {
2310 GLint status = GL_FALSE;
2311
2312 /* Compile */
2313 gl.compileShader(id);
2314 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
2315
2316 /* Get compilation status */
2317 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
2318 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2319
2320 /* Log compilation error */
2321 if (GL_TRUE != status)
2322 {
2323 glw::GLint length = 0;
2324 std::string message;
2325
2326 /* Error log length */
2327 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
2328 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2329
2330 /* Prepare storage */
2331 message.resize(length, 0);
2332
2333 /* Get error log */
2334 gl.getShaderInfoLog(id, length, 0, &message[0]);
2335 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
2336
2337 throw CompilationException(message.c_str());
2338 }
2339 }
2340
2341 /** Create shader
2342 *
2343 * @param gl GL functions
2344 * @param stage Shader stage
2345 * @param out_id Shader id
2346 **/
Create(const Functions & gl,STAGES stage,GLuint & out_id)2347 void Shader::Create(const Functions& gl, STAGES stage, GLuint& out_id)
2348 {
2349 const GLenum shaderType = GetShaderStageGLenum(stage);
2350 const GLuint id = gl.createShader(shaderType);
2351 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
2352
2353 if (m_invalid_id == id)
2354 {
2355 TCU_FAIL("Failed to create shader");
2356 }
2357
2358 out_id = id;
2359 }
2360
2361 /** Set shader's source code
2362 *
2363 * @param gl GL functions
2364 * @param id Shader id
2365 * @param source Shader source code
2366 **/
Source(const Functions & gl,GLuint id,const std::string & source)2367 void Shader::Source(const Functions& gl, GLuint id, const std::string& source)
2368 {
2369 const GLchar* code = source.c_str();
2370
2371 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
2372 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
2373 }
2374
2375 /** Get GLenum repesenting shader stage
2376 *
2377 * @param stage Shader stage
2378 *
2379 * @return GLenum
2380 **/
GetShaderStageGLenum(STAGES stage)2381 GLenum Shader::GetShaderStageGLenum(STAGES stage)
2382 {
2383 GLenum result = 0;
2384
2385 switch (stage)
2386 {
2387 case COMPUTE:
2388 result = GL_COMPUTE_SHADER;
2389 break;
2390 case FRAGMENT:
2391 result = GL_FRAGMENT_SHADER;
2392 break;
2393 case GEOMETRY:
2394 result = GL_GEOMETRY_SHADER;
2395 break;
2396 case TESS_CTRL:
2397 result = GL_TESS_CONTROL_SHADER;
2398 break;
2399 case TESS_EVAL:
2400 result = GL_TESS_EVALUATION_SHADER;
2401 break;
2402 case VERTEX:
2403 result = GL_VERTEX_SHADER;
2404 break;
2405 default:
2406 TCU_FAIL("Invalid enum");
2407 }
2408
2409 return result;
2410 }
2411
2412 /** Get string representing name of shader stage
2413 *
2414 * @param stage Shader stage
2415 *
2416 * @return String with name of shader stage
2417 **/
GetStageName(STAGES stage)2418 const glw::GLchar* Shader::GetStageName(STAGES stage)
2419 {
2420 const GLchar* result = 0;
2421
2422 switch (stage)
2423 {
2424 case COMPUTE:
2425 result = "compute";
2426 break;
2427 case VERTEX:
2428 result = "vertex";
2429 break;
2430 case TESS_CTRL:
2431 result = "tessellation control";
2432 break;
2433 case TESS_EVAL:
2434 result = "tessellation evaluation";
2435 break;
2436 case GEOMETRY:
2437 result = "geometry";
2438 break;
2439 case FRAGMENT:
2440 result = "fragment";
2441 break;
2442 default:
2443 TCU_FAIL("Invalid enum");
2444 }
2445
2446 return result;
2447 }
2448
2449 /** Logs shader source
2450 *
2451 * @param context CTS context
2452 * @param source Source of shader
2453 * @param stage Shader stage
2454 **/
LogSource(deqp::Context & context,const std::string & source,STAGES stage)2455 void Shader::LogSource(deqp::Context& context, const std::string& source, STAGES stage)
2456 {
2457 /* Skip empty shaders */
2458 if (true == source.empty())
2459 {
2460 return;
2461 }
2462
2463 context.getTestContext().getLog() << tcu::TestLog::Message
2464 << "Shader source. Stage: " << Shader::GetStageName(stage)
2465 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(source);
2466 }
2467
2468 /** Constructor
2469 *
2470 * @param message Compilation error message
2471 **/
CompilationException(const GLchar * message)2472 Shader::CompilationException::CompilationException(const GLchar* message)
2473 {
2474 m_message = message;
2475 }
2476
2477 /** Returns error messages
2478 *
2479 * @return Compilation error message
2480 **/
what() const2481 const char* Shader::CompilationException::what() const throw()
2482 {
2483 return m_message.c_str();
2484 }
2485
2486 /** Constructor
2487 *
2488 * @param message Compilation error message
2489 **/
InvalidSourceException(const GLchar * error_message,const std::string & source,STAGES stage)2490 Shader::InvalidSourceException::InvalidSourceException(const GLchar* error_message, const std::string& source,
2491 STAGES stage)
2492 : m_message(error_message), m_source(source), m_stage(stage)
2493 {
2494 }
2495
2496 /** Returns error messages
2497 *
2498 * @return Compilation error message
2499 **/
what() const2500 const char* Shader::InvalidSourceException::what() const throw()
2501 {
2502 return "Compilation error";
2503 }
2504
2505 /** Logs error message and shader sources **/
log(deqp::Context & context) const2506 void Shader::InvalidSourceException::log(deqp::Context& context) const
2507 {
2508 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader: " << m_message.c_str()
2509 << tcu::TestLog::EndMessage;
2510
2511 LogSource(context, m_source, m_stage);
2512 }
2513
2514 /* Program constants */
2515 const GLuint Pipeline::m_invalid_id = 0;
2516
2517 /** Constructor.
2518 *
2519 * @param context CTS context.
2520 **/
Pipeline(deqp::Context & context)2521 Pipeline::Pipeline(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2522 {
2523 /* Nothing to be done here */
2524 }
2525
2526 /** Destructor
2527 *
2528 **/
~Pipeline()2529 Pipeline::~Pipeline()
2530 {
2531 Release();
2532 }
2533
2534 /** Initialize pipline object
2535 *
2536 **/
Init()2537 void Pipeline::Init()
2538 {
2539 Release();
2540
2541 const Functions& gl = m_context.getRenderContext().getFunctions();
2542
2543 /* Generate */
2544 gl.genProgramPipelines(1, &m_id);
2545 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
2546 }
2547
2548 /** Release pipeline object
2549 *
2550 **/
Release()2551 void Pipeline::Release()
2552 {
2553 if (m_invalid_id != m_id)
2554 {
2555 const Functions& gl = m_context.getRenderContext().getFunctions();
2556
2557 /* Generate */
2558 gl.deleteProgramPipelines(1, &m_id);
2559 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines");
2560
2561 m_id = m_invalid_id;
2562 }
2563 }
2564
2565 /** Bind pipeline
2566 *
2567 **/
Bind()2568 void Pipeline::Bind()
2569 {
2570 const Functions& gl = m_context.getRenderContext().getFunctions();
2571
2572 Bind(gl, m_id);
2573 }
2574
2575 /** Set which stages should be active
2576 *
2577 * @param program_id Id of program
2578 * @param stages Logical combination of enums representing stages
2579 **/
UseProgramStages(GLuint program_id,GLenum stages)2580 void Pipeline::UseProgramStages(GLuint program_id, GLenum stages)
2581 {
2582 const Functions& gl = m_context.getRenderContext().getFunctions();
2583
2584 UseProgramStages(gl, m_id, program_id, stages);
2585 }
2586
2587 /** Bind pipeline
2588 *
2589 * @param gl Functiions
2590 * @param id Pipeline id
2591 **/
Bind(const Functions & gl,GLuint id)2592 void Pipeline::Bind(const Functions& gl, GLuint id)
2593 {
2594 gl.bindProgramPipeline(id);
2595 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
2596 }
2597
2598 /** Set which stages should be active
2599 *
2600 * @param gl Functiions
2601 * @param id Pipeline id
2602 * @param program_id Id of program
2603 * @param stages Logical combination of enums representing stages
2604 **/
UseProgramStages(const Functions & gl,GLuint id,GLuint program_id,GLenum stages)2605 void Pipeline::UseProgramStages(const Functions& gl, GLuint id, GLuint program_id, GLenum stages)
2606 {
2607 gl.useProgramStages(id, stages, program_id);
2608 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
2609 }
2610
2611 /* Program constants */
2612 const GLuint Program::m_invalid_id = 0;
2613
2614 /** Constructor.
2615 *
2616 * @param context CTS context.
2617 **/
Program(deqp::Context & context)2618 Program::Program(deqp::Context& context)
2619 : m_id(m_invalid_id)
2620 , m_compute(context)
2621 , m_fragment(context)
2622 , m_geometry(context)
2623 , m_tess_ctrl(context)
2624 , m_tess_eval(context)
2625 , m_vertex(context)
2626 , m_context(context)
2627 {
2628 /* Nothing to be done here */
2629 }
2630
2631 /** Destructor
2632 *
2633 **/
~Program()2634 Program::~Program()
2635 {
2636 Release();
2637 }
2638
2639 /** Initialize program instance
2640 *
2641 * @param compute_shader Compute shader source code
2642 * @param fragment_shader Fragment shader source code
2643 * @param geometry_shader Geometry shader source code
2644 * @param tessellation_control_shader Tessellation control shader source code
2645 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2646 * @param vertex_shader Vertex shader source code
2647 * @param captured_varyings Vector of variables to be captured with transfrom feedback
2648 * @param capture_interleaved Select mode of transform feedback (separate or interleaved)
2649 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2650 **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tessellation_control_shader,const std::string & tessellation_evaluation_shader,const std::string & vertex_shader,const NameVector & captured_varyings,bool capture_interleaved,bool is_separable)2651 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2652 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2653 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2654 const NameVector& captured_varyings, bool capture_interleaved, bool is_separable)
2655 {
2656 /* Delete previous program */
2657 Release();
2658
2659 /* GL entry points */
2660 const Functions& gl = m_context.getRenderContext().getFunctions();
2661
2662 /* Initialize shaders */
2663 m_compute.Init(Shader::COMPUTE, compute_shader);
2664 m_fragment.Init(Shader::FRAGMENT, fragment_shader);
2665 m_geometry.Init(Shader::GEOMETRY, geometry_shader);
2666 m_tess_ctrl.Init(Shader::TESS_CTRL, tessellation_control_shader);
2667 m_tess_eval.Init(Shader::TESS_EVAL, tessellation_evaluation_shader);
2668 m_vertex.Init(Shader::VERTEX, vertex_shader);
2669
2670 /* Create program, set up transform feedback and attach shaders */
2671 Create(gl, m_id);
2672 Capture(gl, m_id, captured_varyings, capture_interleaved);
2673 Attach(gl, m_id, m_compute.m_id);
2674 Attach(gl, m_id, m_fragment.m_id);
2675 Attach(gl, m_id, m_geometry.m_id);
2676 Attach(gl, m_id, m_tess_ctrl.m_id);
2677 Attach(gl, m_id, m_tess_eval.m_id);
2678 Attach(gl, m_id, m_vertex.m_id);
2679
2680 /* Set separable parameter */
2681 if (true == is_separable)
2682 {
2683 gl.programParameteri(m_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2684 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
2685 }
2686
2687 try
2688 {
2689 /* Link program */
2690 Link(gl, m_id);
2691 }
2692 catch (const LinkageException& exc)
2693 {
2694 throw BuildException(exc.what(), compute_shader, fragment_shader, geometry_shader, tessellation_control_shader,
2695 tessellation_evaluation_shader, vertex_shader);
2696 }
2697 }
2698
2699 /** Initialize program instance
2700 *
2701 * @param compute_shader Compute shader source code
2702 * @param fragment_shader Fragment shader source code
2703 * @param geometry_shader Geometry shader source code
2704 * @param tessellation_control_shader Tessellation control shader source code
2705 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2706 * @param vertex_shader Vertex shader source code
2707 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2708 **/
Init(const std::string & compute_shader,const std::string & fragment_shader,const std::string & geometry_shader,const std::string & tessellation_control_shader,const std::string & tessellation_evaluation_shader,const std::string & vertex_shader,bool is_separable)2709 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2710 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2711 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2712 bool is_separable)
2713 {
2714 NameVector captured_varying;
2715
2716 Init(compute_shader, fragment_shader, geometry_shader, tessellation_control_shader, tessellation_evaluation_shader,
2717 vertex_shader, captured_varying, true, is_separable);
2718 }
2719
2720 /** Release program instance
2721 *
2722 **/
Release()2723 void Program::Release()
2724 {
2725 const Functions& gl = m_context.getRenderContext().getFunctions();
2726
2727 if (m_invalid_id != m_id)
2728 {
2729 Use(gl, m_invalid_id);
2730
2731 gl.deleteProgram(m_id);
2732 m_id = m_invalid_id;
2733 }
2734
2735 m_compute.Release();
2736 m_fragment.Release();
2737 m_geometry.Release();
2738 m_tess_ctrl.Release();
2739 m_tess_eval.Release();
2740 m_vertex.Release();
2741 }
2742
2743 /** Get <pname> for a set of active uniforms
2744 *
2745 * @param count Number of indices
2746 * @param indices Indices of uniforms
2747 * @param pname Queired pname
2748 * @param params Array that will be filled with values of parameters
2749 **/
GetActiveUniformsiv(GLsizei count,const GLuint * indices,GLenum pname,GLint * params) const2750 void Program::GetActiveUniformsiv(GLsizei count, const GLuint* indices, GLenum pname, GLint* params) const
2751 {
2752 const Functions& gl = m_context.getRenderContext().getFunctions();
2753
2754 GetActiveUniformsiv(gl, m_id, count, indices, pname, params);
2755 }
2756
2757 /** Get location of attribute
2758 *
2759 * @param name Name of attribute
2760 *
2761 * @return Result of query
2762 **/
GetAttribLocation(const std::string & name) const2763 glw::GLint Program::GetAttribLocation(const std::string& name) const
2764 {
2765 const Functions& gl = m_context.getRenderContext().getFunctions();
2766
2767 return GetAttribLocation(gl, m_id, name);
2768 }
2769
2770 /** Query resource
2771 *
2772 * @param interface Interface to be queried
2773 * @param index Index of resource
2774 * @param property Property to be queried
2775 * @param buf_size Size of <params> buffer
2776 * @param params Results of query
2777 **/
GetResource(GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params) const2778 void Program::GetResource(GLenum interface, GLuint index, GLenum property, GLsizei buf_size, GLint* params) const
2779 {
2780 const Functions& gl = m_context.getRenderContext().getFunctions();
2781
2782 GetResource(gl, m_id, interface, index, property, buf_size, params);
2783 }
2784
2785 /** Query for index of resource
2786 *
2787 * @param name Name of resource
2788 * @param interface Interface to be queried
2789 *
2790 * @return Result of query
2791 **/
GetResourceIndex(const std::string & name,GLenum interface) const2792 glw::GLuint Program::GetResourceIndex(const std::string& name, GLenum interface) const
2793 {
2794 const Functions& gl = m_context.getRenderContext().getFunctions();
2795
2796 return GetResourceIndex(gl, m_id, name, interface);
2797 }
2798
2799 /** Get indices for a set of uniforms
2800 *
2801 * @param count Count number of uniforms
2802 * @param names Names of uniforms
2803 * @param indices Buffer that will be filled with indices
2804 **/
GetUniformIndices(GLsizei count,const GLchar ** names,GLuint * indices) const2805 void Program::GetUniformIndices(GLsizei count, const GLchar** names, GLuint* indices) const
2806 {
2807 const Functions& gl = m_context.getRenderContext().getFunctions();
2808
2809 GetUniformIndices(gl, m_id, count, names, indices);
2810 }
2811
2812 /** Get uniform location
2813 *
2814 * @param name Name of uniform
2815 *
2816 * @return Results of query
2817 **/
GetUniformLocation(const std::string & name) const2818 glw::GLint Program::GetUniformLocation(const std::string& name) const
2819 {
2820 const Functions& gl = m_context.getRenderContext().getFunctions();
2821
2822 return GetUniformLocation(gl, m_id, name);
2823 }
2824
2825 /** Set program as active
2826 *
2827 **/
Use() const2828 void Program::Use() const
2829 {
2830 const Functions& gl = m_context.getRenderContext().getFunctions();
2831
2832 Use(gl, m_id);
2833 }
2834
2835 /** Attach shader to program
2836 *
2837 * @param gl GL functions
2838 * @param program_id Id of program
2839 * @param shader_id Id of shader
2840 **/
Attach(const Functions & gl,GLuint program_id,GLuint shader_id)2841 void Program::Attach(const Functions& gl, GLuint program_id, GLuint shader_id)
2842 {
2843 /* Sanity checks */
2844 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
2845 {
2846 return;
2847 }
2848
2849 gl.attachShader(program_id, shader_id);
2850 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
2851 }
2852
2853 /** Set up captured varyings
2854 *
2855 * @param gl GL functions
2856 * @param id Id of program
2857 * @param captured_varyings Vector of varyings
2858 * @param capture_interleaved Selects if interleaved or separate mode should be used
2859 **/
Capture(const Functions & gl,GLuint id,const NameVector & captured_varyings,bool capture_interleaved)2860 void Program::Capture(const Functions& gl, GLuint id, const NameVector& captured_varyings, bool capture_interleaved)
2861 {
2862 const size_t n_varyings = captured_varyings.size();
2863
2864 if (0 == n_varyings)
2865 {
2866 /* empty list, skip */
2867 return;
2868 }
2869
2870 std::vector<const GLchar*> varying_names;
2871 varying_names.resize(n_varyings);
2872
2873 for (size_t i = 0; i < n_varyings; ++i)
2874 {
2875 varying_names[i] = captured_varyings[i].c_str();
2876 }
2877
2878 GLenum mode = 0;
2879 if (true == capture_interleaved)
2880 {
2881 mode = GL_INTERLEAVED_ATTRIBS;
2882 }
2883 else
2884 {
2885 mode = GL_SEPARATE_ATTRIBS;
2886 }
2887
2888 gl.transformFeedbackVaryings(id, static_cast<GLsizei>(n_varyings), &varying_names[0], mode);
2889 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
2890 }
2891
2892 /** Create program instance
2893 *
2894 * @param gl GL functions
2895 * @param out_id Id of program
2896 **/
Create(const Functions & gl,GLuint & out_id)2897 void Program::Create(const Functions& gl, GLuint& out_id)
2898 {
2899 const GLuint id = gl.createProgram();
2900 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
2901
2902 if (m_invalid_id == id)
2903 {
2904 TCU_FAIL("Failed to create program");
2905 }
2906
2907 out_id = id;
2908 }
2909
2910 /** Get <pname> for a set of active uniforms
2911 *
2912 * @param gl Functions
2913 * @param program_id Id of program
2914 * @param count Number of indices
2915 * @param indices Indices of uniforms
2916 * @param pname Queired pname
2917 * @param params Array that will be filled with values of parameters
2918 **/
GetActiveUniformsiv(const Functions & gl,GLuint program_id,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)2919 void Program::GetActiveUniformsiv(const Functions& gl, GLuint program_id, GLsizei count, const GLuint* indices,
2920 GLenum pname, GLint* params)
2921 {
2922 gl.getActiveUniformsiv(program_id, count, indices, pname, params);
2923 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
2924 }
2925
2926 /** Get indices for a set of uniforms
2927 *
2928 * @param gl Functions
2929 * @param program_id Id of program
2930 * @param count Count number of uniforms
2931 * @param names Names of uniforms
2932 * @param indices Buffer that will be filled with indices
2933 **/
GetUniformIndices(const Functions & gl,GLuint program_id,GLsizei count,const GLchar ** names,GLuint * indices)2934 void Program::GetUniformIndices(const Functions& gl, GLuint program_id, GLsizei count, const GLchar** names,
2935 GLuint* indices)
2936 {
2937 gl.getUniformIndices(program_id, count, names, indices);
2938 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
2939 }
2940
2941 /** Link program
2942 *
2943 * @param gl GL functions
2944 * @param id Id of program
2945 **/
Link(const Functions & gl,GLuint id)2946 void Program::Link(const Functions& gl, GLuint id)
2947 {
2948 GLint status = GL_FALSE;
2949
2950 gl.linkProgram(id);
2951 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
2952
2953 /* Get link status */
2954 gl.getProgramiv(id, GL_LINK_STATUS, &status);
2955 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
2956
2957 /* Log link error */
2958 if (GL_TRUE != status)
2959 {
2960 glw::GLint length = 0;
2961 std::string message;
2962
2963 /* Get error log length */
2964 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
2965 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
2966
2967 message.resize(length, 0);
2968
2969 /* Get error log */
2970 gl.getProgramInfoLog(id, length, 0, &message[0]);
2971 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
2972
2973 throw LinkageException(message.c_str());
2974 }
2975 }
2976
2977 /** Set generic uniform
2978 *
2979 * @param gl Functions
2980 * @param type Type of uniform
2981 * @param count Length of array
2982 * @param location Location of uniform
2983 * @param data Data that will be used
2984 **/
Uniform(const Functions & gl,const Type & type,GLsizei count,GLint location,const GLvoid * data)2985 void Program::Uniform(const Functions& gl, const Type& type, GLsizei count, GLint location, const GLvoid* data)
2986 {
2987 if (-1 == location)
2988 {
2989 TCU_FAIL("Uniform is inactive");
2990 }
2991
2992 switch (type.m_basic_type)
2993 {
2994 case Type::Double:
2995 if (1 == type.m_n_columns)
2996 {
2997 getUniformNdv(gl, type.m_n_rows)(location, count, (const GLdouble*)data);
2998 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNdv");
2999 }
3000 else
3001 {
3002 getUniformMatrixNdv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLdouble*)data);
3003 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNdv");
3004 }
3005 break;
3006 case Type::Float:
3007 if (1 == type.m_n_columns)
3008 {
3009 getUniformNfv(gl, type.m_n_rows)(location, count, (const GLfloat*)data);
3010 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNfv");
3011 }
3012 else
3013 {
3014 getUniformMatrixNfv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLfloat*)data);
3015 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNfv");
3016 }
3017 break;
3018 case Type::Int:
3019 getUniformNiv(gl, type.m_n_rows)(location, count, (const GLint*)data);
3020 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNiv");
3021 break;
3022 case Type::Uint:
3023 getUniformNuiv(gl, type.m_n_rows)(location, count, (const GLuint*)data);
3024 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNuiv");
3025 break;
3026 default:
3027 TCU_FAIL("Invalid enum");
3028 }
3029 }
3030
3031 /** Use program
3032 *
3033 * @param gl GL functions
3034 * @param id Id of program
3035 **/
Use(const Functions & gl,GLuint id)3036 void Program::Use(const Functions& gl, GLuint id)
3037 {
3038 gl.useProgram(id);
3039 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
3040 }
3041
3042 /** Get location of attribute
3043 *
3044 * @param gl GL functions
3045 * @param id Id of program
3046 * @param name Name of attribute
3047 *
3048 * @return Location of attribute
3049 **/
GetAttribLocation(const Functions & gl,GLuint id,const std::string & name)3050 GLint Program::GetAttribLocation(const Functions& gl, GLuint id, const std::string& name)
3051 {
3052 GLint location = gl.getAttribLocation(id, name.c_str());
3053 GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
3054
3055 return location;
3056 }
3057
3058 /** Query resource
3059 *
3060 * @param gl GL functions
3061 * @param id Id of program
3062 * @param interface Interface to be queried
3063 * @param index Index of resource
3064 * @param property Property to be queried
3065 * @param buf_size Size of <params> buffer
3066 * @param params Results of query
3067 **/
GetResource(const Functions & gl,GLuint id,GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params)3068 void Program::GetResource(const Functions& gl, GLuint id, GLenum interface, GLuint index, GLenum property,
3069 GLsizei buf_size, GLint* params)
3070 {
3071 gl.getProgramResourceiv(id, interface, index, 1 /* propCount */, &property, buf_size /* bufSize */, 0 /* length */,
3072 params);
3073 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3074 }
3075
3076 /** Get index of resource
3077 *
3078 * @param gl GL functions
3079 * @param id Id of program
3080 * @param name Name of resource
3081 * @param interface Program interface to queried
3082 *
3083 * @return Location of attribute
3084 **/
GetResourceIndex(const Functions & gl,GLuint id,const std::string & name,GLenum interface)3085 GLuint Program::GetResourceIndex(const Functions& gl, GLuint id, const std::string& name, GLenum interface)
3086 {
3087 GLuint index = gl.getProgramResourceIndex(id, interface, name.c_str());
3088 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3089
3090 return index;
3091 }
3092
3093 /** Get location of attribute
3094 *
3095 * @param gl GL functions
3096 * @param id Id of program
3097 * @param name Name of attribute
3098 *
3099 * @return Location of uniform
3100 **/
GetUniformLocation(const Functions & gl,GLuint id,const std::string & name)3101 GLint Program::GetUniformLocation(const Functions& gl, GLuint id, const std::string& name)
3102 {
3103 GLint location = gl.getUniformLocation(id, name.c_str());
3104 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3105
3106 return location;
3107 }
3108
3109 /** Constructor
3110 *
3111 * @param error_message Error message
3112 * @param compute_shader Source code for compute stage
3113 * @param fragment_shader Source code for fragment stage
3114 * @param geometry_shader Source code for geometry stage
3115 * @param tess_ctrl_shader Source code for tessellation control stage
3116 * @param tess_eval_shader Source code for tessellation evaluation stage
3117 * @param vertex_shader Source code for vertex stage
3118 **/
BuildException(const glw::GLchar * error_message,const std::string compute_shader,const std::string fragment_shader,const std::string geometry_shader,const std::string tess_ctrl_shader,const std::string tess_eval_shader,const std::string vertex_shader)3119 Program::BuildException::BuildException(const glw::GLchar* error_message, const std::string compute_shader,
3120 const std::string fragment_shader, const std::string geometry_shader,
3121 const std::string tess_ctrl_shader, const std::string tess_eval_shader,
3122 const std::string vertex_shader)
3123 : m_error_message(error_message)
3124 , m_compute_shader(compute_shader)
3125 , m_fragment_shader(fragment_shader)
3126 , m_geometry_shader(geometry_shader)
3127 , m_tess_ctrl_shader(tess_ctrl_shader)
3128 , m_tess_eval_shader(tess_eval_shader)
3129 , m_vertex_shader(vertex_shader)
3130 {
3131 }
3132
3133 /** Overwrites std::exception::what method
3134 *
3135 * @return Message compossed from error message and shader sources
3136 **/
what() const3137 const char* Program::BuildException::what() const throw()
3138 {
3139 return "Failed to link program";
3140 }
3141
3142 /** Logs error message and shader sources **/
log(deqp::Context & context) const3143 void Program::BuildException::log(deqp::Context& context) const
3144 {
3145 context.getTestContext().getLog() << tcu::TestLog::Message << "Link failure: " << m_error_message
3146 << tcu::TestLog::EndMessage;
3147
3148 Shader::LogSource(context, m_vertex_shader, Shader::VERTEX);
3149 Shader::LogSource(context, m_tess_ctrl_shader, Shader::TESS_CTRL);
3150 Shader::LogSource(context, m_tess_eval_shader, Shader::TESS_EVAL);
3151 Shader::LogSource(context, m_geometry_shader, Shader::GEOMETRY);
3152 Shader::LogSource(context, m_fragment_shader, Shader::FRAGMENT);
3153 Shader::LogSource(context, m_compute_shader, Shader::COMPUTE);
3154 }
3155
3156 /** Constructor
3157 *
3158 * @param message Linking error message
3159 **/
LinkageException(const glw::GLchar * message)3160 Program::LinkageException::LinkageException(const glw::GLchar* message) : m_error_message(message)
3161 {
3162 /* Nothing to be done */
3163 }
3164
3165 /** Returns error messages
3166 *
3167 * @return Linking error message
3168 **/
what() const3169 const char* Program::LinkageException::what() const throw()
3170 {
3171 return m_error_message.c_str();
3172 }
3173
3174 /* Texture constants */
3175 const GLuint Texture::m_invalid_id = -1;
3176
3177 /** Constructor.
3178 *
3179 * @param context CTS context.
3180 **/
Texture(deqp::Context & context)3181 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_type(TEX_2D)
3182 {
3183 /* Nothing to done here */
3184 }
3185
3186 /** Destructor
3187 *
3188 **/
~Texture()3189 Texture::~Texture()
3190 {
3191 Release();
3192 }
3193
3194 /** Initialize texture instance
3195 *
3196 * @param tex_type Type of texture
3197 * @param width Width of texture
3198 * @param height Height of texture
3199 * @param depth Depth of texture
3200 * @param internal_format Internal format of texture
3201 * @param format Format of texture data
3202 * @param type Type of texture data
3203 * @param data Texture data
3204 **/
Init(TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format,GLenum format,GLenum type,GLvoid * data)3205 void Texture::Init(TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum internal_format, GLenum format,
3206 GLenum type, GLvoid* data)
3207 {
3208 const Functions& gl = m_context.getRenderContext().getFunctions();
3209
3210 /* Delete previous texture */
3211 Release();
3212
3213 m_type = tex_type;
3214
3215 /* Generate, bind, allocate storage and upload data */
3216 Generate(gl, m_id);
3217 Bind(gl, m_id, tex_type);
3218 Storage(gl, tex_type, width, height, depth, internal_format);
3219 Update(gl, tex_type, width, height, depth, format, type, data);
3220 }
3221
3222 /** Initialize buffer texture
3223 *
3224 * @param internal_format Internal format of texture
3225 * @param buffer_id Id of buffer that will be used as data source
3226 **/
Init(GLenum internal_format,GLuint buffer_id)3227 void Texture::Init(GLenum internal_format, GLuint buffer_id)
3228 {
3229 const Functions& gl = m_context.getRenderContext().getFunctions();
3230
3231 /* Delete previous texture */
3232 Release();
3233
3234 m_type = TEX_BUFFER;
3235
3236 /* Generate, bind and attach buffer */
3237 Generate(gl, m_id);
3238 Bind(gl, m_id, TEX_BUFFER);
3239 TexBuffer(gl, buffer_id, internal_format);
3240 }
3241
3242 /** Release texture instance
3243 *
3244 **/
Release()3245 void Texture::Release()
3246 {
3247 if (m_invalid_id != m_id)
3248 {
3249 const Functions& gl = m_context.getRenderContext().getFunctions();
3250
3251 gl.deleteTextures(1, &m_id);
3252 m_id = m_invalid_id;
3253 }
3254 }
3255
3256 /** Bind texture to its target
3257 *
3258 **/
Bind() const3259 void Texture::Bind() const
3260 {
3261 const Functions& gl = m_context.getRenderContext().getFunctions();
3262
3263 Bind(gl, m_id, m_type);
3264 }
3265
3266 /** Get texture data
3267 *
3268 * @param format Format of data
3269 * @param type Type of data
3270 * @param out_data Buffer for data
3271 **/
Get(GLenum format,GLenum type,GLvoid * out_data) const3272 void Texture::Get(GLenum format, GLenum type, GLvoid* out_data) const
3273 {
3274 const Functions& gl = m_context.getRenderContext().getFunctions();
3275
3276 Bind(gl, m_id, m_type);
3277 Get(gl, m_type, format, type, out_data);
3278 }
3279
3280 /** Bind texture to target
3281 *
3282 * @param gl GL functions
3283 * @param id Id of texture
3284 * @param tex_type Type of texture
3285 **/
Bind(const Functions & gl,GLuint id,TYPES tex_type)3286 void Texture::Bind(const Functions& gl, GLuint id, TYPES tex_type)
3287 {
3288 GLenum target = GetTargetGLenum(tex_type);
3289
3290 gl.bindTexture(target, id);
3291 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3292 }
3293
3294 /** Generate texture instance
3295 *
3296 * @param gl GL functions
3297 * @param out_id Id of texture
3298 **/
Generate(const Functions & gl,GLuint & out_id)3299 void Texture::Generate(const Functions& gl, GLuint& out_id)
3300 {
3301 GLuint id = m_invalid_id;
3302
3303 gl.genTextures(1, &id);
3304 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
3305
3306 if (m_invalid_id == id)
3307 {
3308 TCU_FAIL("Invalid id");
3309 }
3310
3311 out_id = id;
3312 }
3313
3314 /** Get texture data
3315 *
3316 * @param gl GL functions
3317 * @param format Format of data
3318 * @param type Type of data
3319 * @param out_data Buffer for data
3320 **/
Get(const Functions & gl,TYPES tex_type,GLenum format,GLenum type,GLvoid * out_data)3321 void Texture::Get(const Functions& gl, TYPES tex_type, GLenum format, GLenum type, GLvoid* out_data)
3322 {
3323 GLenum target = GetTargetGLenum(tex_type);
3324
3325 if (TEX_CUBE != tex_type)
3326 {
3327 gl.getTexImage(target, 0 /* level */, format, type, out_data);
3328 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3329 }
3330 else
3331 {
3332 GLint width;
3333 GLint height;
3334
3335 if ((GL_RGBA != format) && (GL_UNSIGNED_BYTE != type))
3336 {
3337 TCU_FAIL("Not implemented");
3338 }
3339
3340 GLuint texel_size = 4;
3341
3342 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_WIDTH, &width);
3343 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3344
3345 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_HEIGHT, &height);
3346 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3347
3348 const GLuint image_size = width * height * texel_size;
3349
3350 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, format, type,
3351 (GLvoid*)((GLchar*)out_data + (image_size * 0)));
3352 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, format, type,
3353 (GLvoid*)((GLchar*)out_data + (image_size * 1)));
3354 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, format, type,
3355 (GLvoid*)((GLchar*)out_data + (image_size * 2)));
3356 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, format, type,
3357 (GLvoid*)((GLchar*)out_data + (image_size * 3)));
3358 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, format, type,
3359 (GLvoid*)((GLchar*)out_data + (image_size * 4)));
3360 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, format, type,
3361 (GLvoid*)((GLchar*)out_data + (image_size * 5)));
3362 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3363 }
3364 }
3365
3366 /** Allocate storage for texture
3367 *
3368 * @param gl GL functions
3369 * @param tex_type Type of texture
3370 * @param width Width of texture
3371 * @param height Height of texture
3372 * @param depth Depth of texture
3373 * @param internal_format Internal format of texture
3374 **/
Storage(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format)3375 void Texture::Storage(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth,
3376 GLenum internal_format)
3377 {
3378 static const GLuint levels = 1;
3379
3380 GLenum target = GetTargetGLenum(tex_type);
3381
3382 switch (tex_type)
3383 {
3384 case TEX_1D:
3385 gl.texStorage1D(target, levels, internal_format, width);
3386 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3387 break;
3388 case TEX_2D:
3389 case TEX_1D_ARRAY:
3390 case TEX_2D_RECT:
3391 case TEX_CUBE:
3392 gl.texStorage2D(target, levels, internal_format, width, height);
3393 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3394 break;
3395 case TEX_3D:
3396 case TEX_2D_ARRAY:
3397 gl.texStorage3D(target, levels, internal_format, width, height, depth);
3398 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3399 break;
3400 default:
3401 TCU_FAIL("Invliad enum");
3402 break;
3403 }
3404 }
3405
3406 /** Attach buffer as source of texture buffer data
3407 *
3408 * @param gl GL functions
3409 * @param internal_format Internal format of texture
3410 * @param buffer_id Id of buffer that will be used as data source
3411 **/
TexBuffer(const Functions & gl,GLenum internal_format,GLuint & buffer_id)3412 void Texture::TexBuffer(const Functions& gl, GLenum internal_format, GLuint& buffer_id)
3413 {
3414 gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id);
3415 GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
3416 }
3417
3418 /** Update contents of texture
3419 *
3420 * @param gl GL functions
3421 * @param tex_type Type of texture
3422 * @param width Width of texture
3423 * @param height Height of texture
3424 * @param format Format of data
3425 * @param type Type of data
3426 * @param data Buffer with image data
3427 **/
Update(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum format,GLenum type,GLvoid * data)3428 void Texture::Update(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum format,
3429 GLenum type, GLvoid* data)
3430 {
3431 static const GLuint level = 0;
3432
3433 GLenum target = GetTargetGLenum(tex_type);
3434
3435 switch (tex_type)
3436 {
3437 case TEX_1D:
3438 gl.texSubImage1D(target, level, 0 /* x */, width, format, type, data);
3439 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3440 break;
3441 case TEX_2D:
3442 case TEX_1D_ARRAY:
3443 case TEX_2D_RECT:
3444 gl.texSubImage2D(target, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
3445 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3446 break;
3447 case TEX_CUBE:
3448 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3449 data);
3450 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3451 data);
3452 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3453 data);
3454 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3455 data);
3456 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3457 data);
3458 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3459 data);
3460 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3461 break;
3462 case TEX_3D:
3463 case TEX_2D_ARRAY:
3464 gl.texSubImage3D(target, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format, type, data);
3465 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3466 break;
3467 default:
3468 TCU_FAIL("Invliad enum");
3469 break;
3470 }
3471 }
3472
3473 /** Get target for given texture type
3474 *
3475 * @param type Type of texture
3476 *
3477 * @return Target
3478 **/
GetTargetGLenum(TYPES type)3479 GLenum Texture::GetTargetGLenum(TYPES type)
3480 {
3481 GLenum result = 0;
3482
3483 switch (type)
3484 {
3485 case TEX_BUFFER:
3486 result = GL_TEXTURE_BUFFER;
3487 break;
3488 case TEX_2D:
3489 result = GL_TEXTURE_2D;
3490 break;
3491 case TEX_2D_RECT:
3492 result = GL_TEXTURE_RECTANGLE;
3493 break;
3494 case TEX_2D_ARRAY:
3495 result = GL_TEXTURE_2D_ARRAY;
3496 break;
3497 case TEX_3D:
3498 result = GL_TEXTURE_3D;
3499 break;
3500 case TEX_CUBE:
3501 result = GL_TEXTURE_CUBE_MAP;
3502 break;
3503 case TEX_1D:
3504 result = GL_TEXTURE_1D;
3505 break;
3506 case TEX_1D_ARRAY:
3507 result = GL_TEXTURE_1D_ARRAY;
3508 break;
3509 }
3510
3511 return result;
3512 }
3513
3514 /* VertexArray constants */
3515 const GLuint VertexArray::m_invalid_id = -1;
3516
3517 /** Constructor.
3518 *
3519 * @param context CTS context.
3520 **/
VertexArray(deqp::Context & context)3521 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
3522 {
3523 }
3524
3525 /** Destructor
3526 *
3527 **/
~VertexArray()3528 VertexArray::~VertexArray()
3529 {
3530 Release();
3531 }
3532
3533 /** Initialize vertex array instance
3534 *
3535 **/
Init()3536 void VertexArray::Init()
3537 {
3538 /* Delete previous instance */
3539 Release();
3540
3541 const Functions& gl = m_context.getRenderContext().getFunctions();
3542
3543 Generate(gl, m_id);
3544 }
3545
3546 /** Release vertex array object instance
3547 *
3548 **/
Release()3549 void VertexArray::Release()
3550 {
3551 if (m_invalid_id != m_id)
3552 {
3553 const Functions& gl = m_context.getRenderContext().getFunctions();
3554
3555 gl.deleteVertexArrays(1, &m_id);
3556
3557 m_id = m_invalid_id;
3558 }
3559 }
3560
3561 /** Set attribute in VAO
3562 *
3563 * @param index Index of attribute
3564 * @param type Type of attribute
3565 * @param n_array_elements Arary length
3566 * @param normalized Selectis if values should be normalized
3567 * @param stride Stride
3568 * @param pointer Pointer to data, or offset in buffer
3569 **/
Attribute(GLuint index,const Type & type,GLuint n_array_elements,GLboolean normalized,GLsizei stride,const GLvoid * pointer)3570 void VertexArray::Attribute(GLuint index, const Type& type, GLuint n_array_elements, GLboolean normalized,
3571 GLsizei stride, const GLvoid* pointer)
3572 {
3573 const Functions& gl = m_context.getRenderContext().getFunctions();
3574
3575 AttribPointer(gl, index, type, n_array_elements, normalized, stride, pointer);
3576 Enable(gl, index, type, n_array_elements);
3577 }
3578
3579 /** Binds Vertex array object
3580 *
3581 **/
Bind()3582 void VertexArray::Bind()
3583 {
3584 const Functions& gl = m_context.getRenderContext().getFunctions();
3585
3586 Bind(gl, m_id);
3587 }
3588
3589 /** Set attribute in VAO
3590 *
3591 * @param gl Functions
3592 * @param index Index of attribute
3593 * @param type Type of attribute
3594 * @param n_array_elements Arary length
3595 * @param normalized Selectis if values should be normalized
3596 * @param stride Stride
3597 * @param pointer Pointer to data, or offset in buffer
3598 **/
AttribPointer(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements,GLboolean normalized,GLsizei stride,const GLvoid * pointer)3599 void VertexArray::AttribPointer(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements,
3600 GLboolean normalized, GLsizei stride, const GLvoid* pointer)
3601 {
3602 const GLuint basic_type_size = Type::GetTypeSize(type.m_basic_type);
3603 const GLint size = (GLint)type.m_n_rows;
3604 const GLuint column_size = (GLuint)size * basic_type_size;
3605 const GLenum gl_type = Type::GetTypeGLenum(type.m_basic_type);
3606
3607 GLuint offset = 0;
3608
3609 /* If attribute is not an array */
3610 if (0 == n_array_elements)
3611 {
3612 n_array_elements = 1;
3613 }
3614
3615 /* For each element in array */
3616 for (GLuint element = 0; element < n_array_elements; ++element)
3617 {
3618 /* For each column in matrix */
3619 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3620 {
3621 /* Calculate offset */
3622 const GLvoid* ptr = (GLubyte*)pointer + offset;
3623
3624 /* Set up attribute */
3625 switch (type.m_basic_type)
3626 {
3627 case Type::Float:
3628 gl.vertexAttribPointer(index, size, gl_type, normalized, stride, ptr);
3629 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer");
3630 break;
3631 case Type::Int:
3632 case Type::Uint:
3633 gl.vertexAttribIPointer(index, size, gl_type, stride, ptr);
3634 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribIPointer");
3635 break;
3636 case Type::Double:
3637 gl.vertexAttribLPointer(index, size, gl_type, stride, ptr);
3638 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribLPointer");
3639 break;
3640 default:
3641 TCU_FAIL("Invalid enum");
3642 }
3643
3644 /* Next location */
3645 offset += column_size;
3646 index += 1;
3647 }
3648 }
3649 }
3650
3651 /** Binds Vertex array object
3652 *
3653 * @param gl GL functions
3654 * @param id ID of vertex array object
3655 **/
Bind(const glw::Functions & gl,glw::GLuint id)3656 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
3657 {
3658 gl.bindVertexArray(id);
3659 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
3660 }
3661
3662 /** Disable attribute in VAO
3663 *
3664 * @param gl Functions
3665 * @param index Index of attribute
3666 * @param type Type of attribute
3667 * @param n_array_elements Arary length
3668 **/
Disable(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements)3669 void VertexArray::Disable(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements)
3670 {
3671 /* If attribute is not an array */
3672 if (0 == n_array_elements)
3673 {
3674 n_array_elements = 1;
3675 }
3676
3677 /* For each element in array */
3678 for (GLuint element = 0; element < n_array_elements; ++element)
3679 {
3680 /* For each column in matrix */
3681 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3682 {
3683 /* Enable attribute array */
3684 gl.disableVertexAttribArray(index);
3685 GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
3686
3687 /* Next location */
3688 index += 1;
3689 }
3690 }
3691 }
3692
3693 /** Set divisor for attribute
3694 *
3695 * @param gl Functions
3696 * @param index Index of attribute
3697 * @param divisor New divisor value
3698 **/
Divisor(const Functions & gl,GLuint index,GLuint divisor)3699 void VertexArray::Divisor(const Functions& gl, GLuint index, GLuint divisor)
3700 {
3701 gl.vertexAttribDivisor(index, divisor);
3702 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribDivisor");
3703 }
3704
3705 /** Enables attribute in VAO
3706 *
3707 * @param gl Functions
3708 * @param index Index of attribute
3709 * @param type Type of attribute
3710 * @param n_array_elements Arary length
3711 **/
Enable(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements)3712 void VertexArray::Enable(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements)
3713 {
3714 /* If attribute is not an array */
3715 if (0 == n_array_elements)
3716 {
3717 n_array_elements = 1;
3718 }
3719
3720 /* For each element in array */
3721 for (GLuint element = 0; element < n_array_elements; ++element)
3722 {
3723 /* For each column in matrix */
3724 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3725 {
3726 /* Enable attribute array */
3727 gl.enableVertexAttribArray(index);
3728 GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
3729
3730 /* Next location */
3731 index += 1;
3732 }
3733 }
3734 }
3735
3736 /** Generates Vertex array object
3737 *
3738 * @param gl GL functions
3739 * @param out_id ID of vertex array object
3740 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)3741 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
3742 {
3743 GLuint id = m_invalid_id;
3744
3745 gl.genVertexArrays(1, &id);
3746 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3747
3748 if (m_invalid_id == id)
3749 {
3750 TCU_FAIL("Invalid id");
3751 }
3752
3753 out_id = id;
3754 }
3755
3756 /* Constatns used by Variable */
3757 const GLint Variable::m_automatic_location = -1;
3758
3759 /** Copy constructor
3760 *
3761 **/
Variable(const Variable & var)3762 Variable::Variable(const Variable& var)
3763 : m_data(var.m_data)
3764 , m_data_size(var.m_data_size)
3765 , m_descriptor(var.m_descriptor.m_name.c_str(), var.m_descriptor.m_qualifiers.c_str(),
3766 var.m_descriptor.m_expected_component, var.m_descriptor.m_expected_location,
3767 var.m_descriptor.m_builtin, var.m_descriptor.m_normalized, var.m_descriptor.m_n_array_elements,
3768 var.m_descriptor.m_expected_stride_of_element, var.m_descriptor.m_offset)
3769 , m_storage(var.m_storage)
3770 {
3771 m_descriptor.m_type = var.m_descriptor.m_type;
3772
3773 if (BUILTIN != var.m_descriptor.m_type)
3774 {
3775 m_descriptor.m_interface = var.m_descriptor.m_interface;
3776 }
3777 }
3778
3779 /** Get code that defines variable
3780 *
3781 * @param flavour Provides info if variable is array or not
3782 *
3783 * @return String with code
3784 **/
GetDefinition(FLAVOUR flavour) const3785 std::string Variable::GetDefinition(FLAVOUR flavour) const
3786 {
3787 return m_descriptor.GetDefinition(flavour, m_storage);
3788 }
3789
3790 /** Calcualtes stride of variable
3791 *
3792 * @return Calculated value
3793 **/
GetStride() const3794 GLuint Variable::GetStride() const
3795 {
3796 GLint variable_stride = 0;
3797
3798 if (0 == m_descriptor.m_n_array_elements)
3799 {
3800 variable_stride = m_descriptor.m_expected_stride_of_element;
3801 }
3802 else
3803 {
3804 variable_stride = m_descriptor.m_expected_stride_of_element * m_descriptor.m_n_array_elements;
3805 }
3806
3807 return variable_stride;
3808 }
3809
3810 /** Check if variable is block
3811 *
3812 * @return true if variable type is block, false otherwise
3813 **/
IsBlock() const3814 bool Variable::IsBlock() const
3815 {
3816 if (BUILTIN == m_descriptor.m_type)
3817 {
3818 return false;
3819 }
3820
3821 const Interface* interface = m_descriptor.m_interface;
3822 if (0 == interface)
3823 {
3824 TCU_FAIL("Nullptr");
3825 }
3826
3827 return (Interface::BLOCK == interface->m_type);
3828 }
3829
3830 /** Check if variable is struct
3831 *
3832 * @return true if variable type is struct, false otherwise
3833 **/
IsStruct() const3834 bool Variable::IsStruct() const
3835 {
3836 if (BUILTIN == m_descriptor.m_type)
3837 {
3838 return false;
3839 }
3840
3841 const Interface* interface = m_descriptor.m_interface;
3842 if (0 == interface)
3843 {
3844 TCU_FAIL("Nullptr");
3845 }
3846
3847 return (Interface::STRUCT == interface->m_type);
3848 }
3849 /** Get code that reference variable
3850 *
3851 * @param parent_name Name of parent
3852 * @param variable Descriptor of variable
3853 * @param flavour Provides info about how variable should be referenced
3854 * @param array_index Index of array, ignored when variable is not array
3855 *
3856 * @return String with code
3857 **/
GetReference(const std::string & parent_name,const Descriptor & variable,FLAVOUR flavour,GLuint array_index)3858 std::string Variable::GetReference(const std::string& parent_name, const Descriptor& variable, FLAVOUR flavour,
3859 GLuint array_index)
3860 {
3861 std::string name;
3862
3863 /* Prepare name */
3864 if (false == parent_name.empty())
3865 {
3866 name = parent_name;
3867 name.append(".");
3868 name.append(variable.m_name);
3869 }
3870 else
3871 {
3872 name = variable.m_name;
3873 }
3874
3875 /* */
3876 switch (flavour)
3877 {
3878 case Utils::Variable::BASIC:
3879 break;
3880
3881 case Utils::Variable::ARRAY:
3882 name.append("[0]");
3883 break;
3884
3885 case Utils::Variable::INDEXED_BY_INVOCATION_ID:
3886 name.append("[gl_InvocationID]");
3887 break;
3888 }
3889
3890 /* Assumption that both variables have same lengths */
3891 if (0 != variable.m_n_array_elements)
3892 {
3893 GLchar buffer[16];
3894 sprintf(buffer, "%d", array_index);
3895 name.append("[");
3896 name.append(buffer);
3897 name.append("]");
3898 }
3899
3900 return name;
3901 }
3902
3903 /** Get "flavour" of varying
3904 *
3905 * @param stage Stage of shader
3906 * @param direction Selects if varying is in or out
3907 *
3908 * @return Flavour
3909 **/
GetFlavour(Shader::STAGES stage,VARYING_DIRECTION direction)3910 Variable::FLAVOUR Variable::GetFlavour(Shader::STAGES stage, VARYING_DIRECTION direction)
3911 {
3912 FLAVOUR result = BASIC;
3913
3914 switch (stage)
3915 {
3916 case Shader::GEOMETRY:
3917 case Shader::TESS_EVAL:
3918 if (INPUT == direction)
3919 {
3920 result = ARRAY;
3921 }
3922 break;
3923 case Shader::TESS_CTRL:
3924 result = INDEXED_BY_INVOCATION_ID;
3925 break;
3926 default:
3927 break;
3928 }
3929
3930 return result;
3931 }
3932
3933 /** Constructor, for built-in types
3934 *
3935 * @param name Name
3936 * @param qualifiers Qualifiers
3937 * @param expected_component Expected component of variable
3938 * @param expected_location Expected location
3939 * @param type Type
3940 * @param normalized Selects if data should be normalized
3941 * @param n_array_elements Length of array
3942 * @param expected_stride_of_element Expected stride of element
3943 * @param offset Offset
3944 **/
Descriptor(const GLchar * name,const GLchar * qualifiers,GLint expected_component,GLint expected_location,const Type & type,GLboolean normalized,GLuint n_array_elements,GLint expected_stride_of_element,GLuint offset)3945 Variable::Descriptor::Descriptor(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
3946 GLint expected_location, const Type& type, GLboolean normalized,
3947 GLuint n_array_elements, GLint expected_stride_of_element, GLuint offset)
3948 : m_expected_component(expected_component)
3949 , m_expected_location(expected_location)
3950 , m_expected_stride_of_element(expected_stride_of_element)
3951 , m_n_array_elements(n_array_elements)
3952 , m_name(name)
3953 , m_normalized(normalized)
3954 , m_offset(offset)
3955 , m_qualifiers(qualifiers)
3956 , m_type(BUILTIN)
3957 , m_builtin(type)
3958 {
3959 }
3960
3961 /** Constructor, for interface types
3962 *
3963 * @param name Name
3964 * @param qualifiers Qualifiers
3965 * @param expected_component Expected component of variable
3966 * @param expected_location Expected location
3967 * @param interface Interface of variable
3968 * @param n_array_elements Length of array
3969 * @param expected_stride_of_element Expected stride of element
3970 * @param offset Offset
3971 **/
Descriptor(const GLchar * name,const GLchar * qualifiers,GLint expected_componenet,GLint expected_location,Interface * interface,GLuint n_array_elements,GLint expected_stride_of_element,GLuint offset)3972 Variable::Descriptor::Descriptor(const GLchar* name, const GLchar* qualifiers, GLint expected_componenet,
3973 GLint expected_location, Interface* interface, GLuint n_array_elements,
3974 GLint expected_stride_of_element, GLuint offset)
3975 : m_expected_component(expected_componenet)
3976 , m_expected_location(expected_location)
3977 , m_expected_stride_of_element(expected_stride_of_element)
3978 , m_n_array_elements(n_array_elements)
3979 , m_name(name)
3980 , m_normalized(GL_FALSE)
3981 , m_offset(offset)
3982 , m_qualifiers(qualifiers)
3983 , m_type(INTERFACE)
3984 , m_interface(interface)
3985 {
3986 }
3987
3988 /** Get definition of variable
3989 *
3990 * @param flavour Flavour of variable
3991 * @param storage Storage used for variable
3992 *
3993 * @return code with defintion
3994 **/
GetDefinition(FLAVOUR flavour,STORAGE storage) const3995 std::string Variable::Descriptor::GetDefinition(FLAVOUR flavour, STORAGE storage) const
3996 {
3997 static const GLchar* basic_template = "QUALIFIERS STORAGETYPE NAMEARRAY;";
3998 static const GLchar* array_template = "QUALIFIERS STORAGETYPE NAME[]ARRAY;";
3999 const GLchar* storage_str = 0;
4000
4001 std::string definition;
4002 size_t position = 0;
4003
4004 /* Select definition template */
4005 switch (flavour)
4006 {
4007 case BASIC:
4008 definition = basic_template;
4009 break;
4010 case ARRAY:
4011 case INDEXED_BY_INVOCATION_ID:
4012 definition = array_template;
4013 break;
4014 default:
4015 TCU_FAIL("Invliad enum");
4016 break;
4017 }
4018
4019 if (BUILTIN != m_type)
4020 {
4021 if (0 == m_interface)
4022 {
4023 TCU_FAIL("Nullptr");
4024 }
4025 }
4026
4027 /* Qualifiers */
4028 if (true == m_qualifiers.empty())
4029 {
4030 replaceToken("QUALIFIERS ", position, "", definition);
4031 }
4032 else
4033 {
4034 replaceToken("QUALIFIERS", position, m_qualifiers.c_str(), definition);
4035 }
4036
4037 // According to spec: int, uint, and double type must always be declared with flat qualifier
4038 bool flat_qualifier = false;
4039 if (m_type != BUILTIN && m_interface != NULL)
4040 {
4041 if (m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Int ||
4042 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Uint ||
4043 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Double)
4044 {
4045 flat_qualifier = true;
4046 }
4047 }
4048 /* Storage */
4049 switch (storage)
4050 {
4051 case VARYING_INPUT:
4052 storage_str = flat_qualifier ? "flat in " : "in ";
4053 break;
4054 case VARYING_OUTPUT:
4055 storage_str = "out ";
4056 break;
4057 case UNIFORM:
4058 storage_str = "uniform ";
4059 break;
4060 case SSB:
4061 storage_str = "buffer ";
4062 break;
4063 case MEMBER:
4064 storage_str = "";
4065 break;
4066 default:
4067 TCU_FAIL("Invalid enum");
4068 break;
4069 }
4070
4071 replaceToken("STORAGE", position, storage_str, definition);
4072
4073 /* Type */
4074 if (BUILTIN == m_type)
4075 {
4076 replaceToken("TYPE", position, m_builtin.GetGLSLTypeName(), definition);
4077 }
4078 else
4079 {
4080 if (Interface::STRUCT == m_interface->m_type)
4081 {
4082 replaceToken("TYPE", position, m_interface->m_name.c_str(), definition);
4083 }
4084 else
4085 {
4086 const std::string& block_definition = m_interface->GetDefinition();
4087
4088 replaceToken("TYPE", position, block_definition.c_str(), definition);
4089 }
4090 }
4091
4092 /* Name */
4093 replaceToken("NAME", position, m_name.c_str(), definition);
4094
4095 /* Array size */
4096 if (0 == m_n_array_elements)
4097 {
4098 replaceToken("ARRAY", position, "", definition);
4099 }
4100 else
4101 {
4102 char buffer[16];
4103 sprintf(buffer, "[%d]", m_n_array_elements);
4104
4105 replaceToken("ARRAY", position, buffer, definition);
4106 }
4107
4108 /* Done */
4109 return definition;
4110 }
4111
4112 /** Get definitions for variables collected in vector
4113 *
4114 * @param vector Collection of variables
4115 * @param flavour Flavour of variables
4116 *
4117 * @return Code with definitions
4118 **/
GetDefinitions(const Variable::PtrVector & vector,Variable::FLAVOUR flavour)4119 std::string GetDefinitions(const Variable::PtrVector& vector, Variable::FLAVOUR flavour)
4120 {
4121 std::string list = Utils::g_list;
4122 size_t position = 0;
4123
4124 for (GLuint i = 0; i < vector.size(); ++i)
4125 {
4126 Utils::insertElementOfList(vector[i]->GetDefinition(flavour).c_str(), "\n", position, list);
4127 }
4128
4129 Utils::endList("", position, list);
4130
4131 return list;
4132 }
4133
4134 /** Get definitions for interfaces collected in vector
4135 *
4136 * @param vector Collection of interfaces
4137 *
4138 * @return Code with definitions
4139 **/
GetDefinitions(const Interface::PtrVector & vector)4140 std::string GetDefinitions(const Interface::PtrVector& vector)
4141 {
4142 std::string list = Utils::g_list;
4143 size_t position = 0;
4144
4145 for (GLuint i = 0; i < vector.size(); ++i)
4146 {
4147 Utils::insertElementOfList(vector[i]->GetDefinition().c_str(), "\n", position, list);
4148 }
4149
4150 Utils::endList("", position, list);
4151
4152 return list;
4153 }
4154
4155 /** Constructor
4156 *
4157 * @param name Name
4158 * @param type Type of interface
4159 **/
Interface(const GLchar * name,Interface::TYPE type)4160 Interface::Interface(const GLchar* name, Interface::TYPE type) : m_name(name), m_type(type)
4161 {
4162 }
4163
4164 /** Adds member to interface
4165 *
4166 * @param member Descriptor of new member
4167 *
4168 * @return Pointer to just created member
4169 **/
AddMember(const Variable::Descriptor & member)4170 Variable::Descriptor* Interface::AddMember(const Variable::Descriptor& member)
4171 {
4172 m_members.push_back(member);
4173
4174 return &m_members.back();
4175 }
4176
4177 /** Get definition of interface
4178 *
4179 * @param Code with definition
4180 **/
GetDefinition() const4181 std::string Interface::GetDefinition() const
4182 {
4183 std::string definition;
4184 size_t position = 0;
4185
4186 const GLchar* member_list = " MEMBER_DEFINITION\nMEMBER_LIST";
4187
4188 if (STRUCT == m_type)
4189 {
4190 definition = "struct NAME {\nMEMBER_LIST};";
4191 }
4192 else
4193 {
4194 definition = "NAME {\nMEMBER_LIST}";
4195 }
4196
4197 /* Name */
4198 replaceToken("NAME", position, m_name.c_str(), definition);
4199
4200 /* Member list */
4201 for (GLuint i = 0; i < m_members.size(); ++i)
4202 {
4203 const size_t start_position = position;
4204 const std::string& member_definition = m_members[i].GetDefinition(Variable::BASIC, Variable::MEMBER);
4205
4206 /* Member list */
4207 replaceToken("MEMBER_LIST", position, member_list, definition);
4208
4209 /* Move back position */
4210 position = start_position;
4211
4212 /* Member definition */
4213 replaceToken("MEMBER_DEFINITION", position, member_definition.c_str(), definition);
4214 }
4215
4216 /* Remove last member list */
4217 replaceToken("MEMBER_LIST", position, "", definition);
4218
4219 /* Done */
4220 return definition;
4221 }
4222
4223 /** Adds member of built-in type to interface
4224 *
4225 * @param name Name
4226 * @param qualifiers Qualifiers
4227 * @param expected_component Expected component of variable
4228 * @param expected_location Expected location
4229 * @param type Type
4230 * @param normalized Selects if data should be normalized
4231 * @param n_array_elements Length of array
4232 * @param expected_stride_of_element Expected stride of element
4233 * @param offset Offset
4234 *
4235 * @return Pointer to just created member
4236 **/
Member(const GLchar * name,const GLchar * qualifiers,GLint expected_component,GLint expected_location,const Type & type,GLboolean normalized,GLuint n_array_elements,GLint expected_stride_of_element,GLuint offset)4237 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4238 GLint expected_location, const Type& type, GLboolean normalized,
4239 GLuint n_array_elements, GLint expected_stride_of_element, GLuint offset)
4240 {
4241 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, type, normalized,
4242 n_array_elements, expected_stride_of_element, offset));
4243 }
4244
4245 /** Adds member of interface type to interface
4246 *
4247 * @param name Name
4248 * @param qualifiers Qualifiers
4249 * @param expected_component Expected component of variable
4250 * @param expected_location Expected location
4251 * @param type Type
4252 * @param normalized Selects if data should be normalized
4253 * @param n_array_elements Length of array
4254 * @param expected_stride_of_element Expected stride of element
4255 * @param offset Offset
4256 *
4257 * @return Pointer to just created member
4258 **/
Member(const GLchar * name,const GLchar * qualifiers,GLint expected_component,GLint expected_location,Interface * nterface,GLuint n_array_elements,GLint expected_stride_of_element,GLuint offset)4259 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4260 GLint expected_location, Interface* nterface, GLuint n_array_elements,
4261 GLint expected_stride_of_element, GLuint offset)
4262 {
4263 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, nterface,
4264 n_array_elements, expected_stride_of_element, offset));
4265 }
4266
4267 /** Clears contents of vector of pointers
4268 *
4269 * @tparam T Type of elements
4270 *
4271 * @param vector Collection to be cleared
4272 **/
4273 template <typename T>
clearPtrVector(std::vector<T * > & vector)4274 void clearPtrVector(std::vector<T*>& vector)
4275 {
4276 for (size_t i = 0; i < vector.size(); ++i)
4277 {
4278 T* t = vector[i];
4279
4280 vector[i] = 0;
4281
4282 if (0 != t)
4283 {
4284 delete t;
4285 }
4286 }
4287
4288 vector.clear();
4289 }
4290
4291 /** Constructor
4292 *
4293 * @param stage Stage described by that interface
4294 **/
ShaderInterface(Shader::STAGES stage)4295 ShaderInterface::ShaderInterface(Shader::STAGES stage) : m_stage(stage)
4296 {
4297 /* Nothing to be done */
4298 }
4299
4300 /** Get definitions of globals
4301 *
4302 * @return Code with definitions
4303 **/
GetDefinitionsGlobals() const4304 std::string ShaderInterface::GetDefinitionsGlobals() const
4305 {
4306 return m_globals;
4307 }
4308
4309 /** Get definitions of inputs
4310 *
4311 * @return Code with definitions
4312 **/
GetDefinitionsInputs() const4313 std::string ShaderInterface::GetDefinitionsInputs() const
4314 {
4315 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::INPUT);
4316
4317 return GetDefinitions(m_inputs, flavour);
4318 }
4319
4320 /** Get definitions of outputs
4321 *
4322 * @return Code with definitions
4323 **/
GetDefinitionsOutputs() const4324 std::string ShaderInterface::GetDefinitionsOutputs() const
4325 {
4326 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::OUTPUT);
4327
4328 return GetDefinitions(m_outputs, flavour);
4329 }
4330
4331 /** Get definitions of buffers
4332 *
4333 * @return Code with definitions
4334 **/
GetDefinitionsSSBs() const4335 std::string ShaderInterface::GetDefinitionsSSBs() const
4336 {
4337 return GetDefinitions(m_ssb_blocks, Variable::BASIC);
4338 }
4339
4340 /** Get definitions of uniforms
4341 *
4342 * @return Code with definitions
4343 **/
GetDefinitionsUniforms() const4344 std::string ShaderInterface::GetDefinitionsUniforms() const
4345 {
4346 return GetDefinitions(m_uniforms, Variable::BASIC);
4347 }
4348
4349 /** Constructor
4350 *
4351 * @param in Input variable
4352 * @param out Output variable
4353 **/
VaryingConnection(Variable * in,Variable * out)4354 VaryingConnection::VaryingConnection(Variable* in, Variable* out) : m_in(in), m_out(out)
4355 {
4356 /* NBothing to be done here */
4357 }
4358
4359 /** Adds new varying connection to given stage
4360 *
4361 * @param stage Shader stage
4362 * @param in In varying
4363 * @param out Out varying
4364 **/
Add(Shader::STAGES stage,Variable * in,Variable * out)4365 void VaryingPassthrough::Add(Shader::STAGES stage, Variable* in, Variable* out)
4366 {
4367 VaryingConnection::Vector& vector = Get(stage);
4368
4369 vector.push_back(VaryingConnection(in, out));
4370 }
4371
4372 /** Get all passthrough connections for given stage
4373 *
4374 * @param stage Shader stage
4375 *
4376 * @return Vector of connections
4377 **/
Get(Shader::STAGES stage)4378 VaryingConnection::Vector& VaryingPassthrough::Get(Shader::STAGES stage)
4379 {
4380 VaryingConnection::Vector* result = 0;
4381
4382 switch (stage)
4383 {
4384 case Shader::FRAGMENT:
4385 result = &m_fragment;
4386 break;
4387 case Shader::GEOMETRY:
4388 result = &m_geometry;
4389 break;
4390 case Shader::TESS_CTRL:
4391 result = &m_tess_ctrl;
4392 break;
4393 case Shader::TESS_EVAL:
4394 result = &m_tess_eval;
4395 break;
4396 case Shader::VERTEX:
4397 result = &m_vertex;
4398 break;
4399 default:
4400 TCU_FAIL("Invalid enum");
4401 }
4402
4403 return *result;
4404 }
4405
4406 /** Constructor
4407 *
4408 **/
ProgramInterface()4409 ProgramInterface::ProgramInterface()
4410 : m_compute(Shader::COMPUTE)
4411 , m_vertex(Shader::VERTEX)
4412 , m_tess_ctrl(Shader::TESS_CTRL)
4413 , m_tess_eval(Shader::TESS_EVAL)
4414 , m_geometry(Shader::GEOMETRY)
4415 , m_fragment(Shader::FRAGMENT)
4416 {
4417 }
4418
4419 /** Destructor
4420 *
4421 **/
~ProgramInterface()4422 ProgramInterface::~ProgramInterface()
4423 {
4424 clearPtrVector(m_blocks);
4425 clearPtrVector(m_structures);
4426 }
4427
4428 /** Adds new interface
4429 *
4430 * @param name
4431 * @param type
4432 *
4433 * @return Pointer to created interface
4434 **/
AddInterface(const GLchar * name,Interface::TYPE type)4435 Interface* ProgramInterface::AddInterface(const GLchar* name, Interface::TYPE type)
4436 {
4437 Interface* interface = 0;
4438
4439 if (Interface::STRUCT == type)
4440 {
4441 interface = new Interface(name, type);
4442
4443 m_structures.push_back(interface);
4444 }
4445 else
4446 {
4447 interface = new Interface(name, type);
4448
4449 m_blocks.push_back(interface);
4450 }
4451
4452 return interface;
4453 }
4454
4455 /** Adds new block interface
4456 *
4457 * @param name
4458 *
4459 * @return Pointer to created interface
4460 **/
Block(const GLchar * name)4461 Interface* ProgramInterface::Block(const GLchar* name)
4462 {
4463 return AddInterface(name, Interface::BLOCK);
4464 }
4465
4466 /** Get interface of given shader stage
4467 *
4468 * @param stage Shader stage
4469 *
4470 * @return Reference to stage interface
4471 **/
GetShaderInterface(Shader::STAGES stage)4472 ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage)
4473 {
4474 ShaderInterface* interface = 0;
4475
4476 switch (stage)
4477 {
4478 case Shader::COMPUTE:
4479 interface = &m_compute;
4480 break;
4481 case Shader::FRAGMENT:
4482 interface = &m_fragment;
4483 break;
4484 case Shader::GEOMETRY:
4485 interface = &m_geometry;
4486 break;
4487 case Shader::TESS_CTRL:
4488 interface = &m_tess_ctrl;
4489 break;
4490 case Shader::TESS_EVAL:
4491 interface = &m_tess_eval;
4492 break;
4493 case Shader::VERTEX:
4494 interface = &m_vertex;
4495 break;
4496 default:
4497 TCU_FAIL("Invalid enum");
4498 }
4499
4500 return *interface;
4501 }
4502
4503 /** Get interface of given shader stage
4504 *
4505 * @param stage Shader stage
4506 *
4507 * @return Reference to stage interface
4508 **/
GetShaderInterface(Shader::STAGES stage) const4509 const ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage) const
4510 {
4511 const ShaderInterface* interface = 0;
4512
4513 switch (stage)
4514 {
4515 case Shader::COMPUTE:
4516 interface = &m_compute;
4517 break;
4518 case Shader::FRAGMENT:
4519 interface = &m_fragment;
4520 break;
4521 case Shader::GEOMETRY:
4522 interface = &m_geometry;
4523 break;
4524 case Shader::TESS_CTRL:
4525 interface = &m_tess_ctrl;
4526 break;
4527 case Shader::TESS_EVAL:
4528 interface = &m_tess_eval;
4529 break;
4530 case Shader::VERTEX:
4531 interface = &m_vertex;
4532 break;
4533 default:
4534 TCU_FAIL("Invalid enum");
4535 }
4536
4537 return *interface;
4538 }
4539
4540 /** Clone interface of Vertex shader stage to other stages
4541 * It creates matching inputs, outputs, uniforms and buffers in other stages.
4542 * There are no additional outputs for FRAGMENT shader generated.
4543 *
4544 * @param varying_passthrough Collection of varyings connections
4545 **/
CloneVertexInterface(VaryingPassthrough & varying_passthrough)4546 void ProgramInterface::CloneVertexInterface(VaryingPassthrough& varying_passthrough)
4547 {
4548 /* VS outputs >> TCS inputs >> TCS outputs >> .. >> FS inputs */
4549 for (size_t i = 0; i < m_vertex.m_outputs.size(); ++i)
4550 {
4551 const Variable& vs_var = *m_vertex.m_outputs[i];
4552 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4553
4554 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4555 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4556 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4557 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4558 }
4559
4560 /* Copy uniforms from VS to other stages */
4561 for (size_t i = 0; i < m_vertex.m_uniforms.size(); ++i)
4562 {
4563 Variable& vs_var = *m_vertex.m_uniforms[i];
4564 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4565
4566 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4567 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4568 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4569 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4570 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4571
4572 /* Uniform blocks needs unique binding */
4573 if (true == vs_var.IsBlock())
4574 {
4575 replaceBinding(vs_var, Shader::VERTEX);
4576 }
4577 }
4578
4579 /* Copy SSBs from VS to other stages */
4580 for (size_t i = 0; i < m_vertex.m_ssb_blocks.size(); ++i)
4581 {
4582 Variable& vs_var = *m_vertex.m_ssb_blocks[i];
4583 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4584
4585 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4586 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4587 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4588 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4589 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4590
4591 /* SSBs blocks needs unique binding */
4592 if (true == vs_var.IsBlock())
4593 {
4594 replaceBinding(vs_var, Shader::VERTEX);
4595 }
4596 }
4597
4598 m_compute.m_globals = m_vertex.m_globals;
4599 m_fragment.m_globals = m_vertex.m_globals;
4600 m_geometry.m_globals = m_vertex.m_globals;
4601 m_tess_ctrl.m_globals = m_vertex.m_globals;
4602 m_tess_eval.m_globals = m_vertex.m_globals;
4603 }
4604
4605 /** Clone variable for specific stage
4606 *
4607 * @param variable Variable
4608 * @param stage Requested stage
4609 * @param prefix Prefix used in variable name that is specific for original stage
4610 * @param varying_passthrough Collection of varyings connections
4611 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,const GLchar * prefix,VaryingPassthrough & varying_passthrough)4612 void ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage, const GLchar* prefix,
4613 VaryingPassthrough& varying_passthrough)
4614 {
4615 switch (variable.m_storage)
4616 {
4617 case Variable::VARYING_OUTPUT:
4618 {
4619 Variable* in = cloneVariableForStage(variable, stage, Variable::VARYING_INPUT, prefix);
4620
4621 if (Shader::FRAGMENT != stage)
4622 {
4623 Variable* out = cloneVariableForStage(variable, stage, Variable::VARYING_OUTPUT, prefix);
4624 varying_passthrough.Add(stage, in, out);
4625 }
4626 }
4627 break;
4628 case Variable::UNIFORM:
4629 case Variable::SSB:
4630 cloneVariableForStage(variable, stage, variable.m_storage, prefix);
4631 break;
4632 default:
4633 TCU_FAIL("Invalid enum");
4634 break;
4635 }
4636 }
4637
4638 /** Clone variable for specific stage
4639 *
4640 * @param variable Variable
4641 * @param stage Requested stage
4642 * @param storage Storage used by variable
4643 * @param prefix Prefix used in variable name that is specific for original stage
4644 *
4645 * @return New variable
4646 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4647 Variable* ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage,
4648 Variable::STORAGE storage, const GLchar* prefix)
4649 {
4650 /* Initialize with original variable */
4651 Variable* var = new Variable(variable);
4652 if (0 == var)
4653 {
4654 TCU_FAIL("Memory allocation");
4655 }
4656
4657 /* Set up storage */
4658 var->m_storage = storage;
4659
4660 /* Get name */
4661 std::string name = variable.m_descriptor.m_name;
4662
4663 /* Prefix name with stage ID, empty means default block */
4664 if (false == name.empty())
4665 {
4666 size_t position = 0;
4667 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4668 Utils::replaceToken(prefix, position, stage_prefix, name);
4669 }
4670 var->m_descriptor.m_name = name;
4671
4672 /* Clone block */
4673 const bool is_block = variable.IsBlock();
4674 if (true == is_block)
4675 {
4676 const Interface* interface = variable.m_descriptor.m_interface;
4677
4678 Interface* block = CloneBlockForStage(*interface, stage, storage, prefix);
4679
4680 var->m_descriptor.m_interface = block;
4681 }
4682
4683 /* Store variable */
4684 ShaderInterface& si = GetShaderInterface(stage);
4685 Variable* result = 0;
4686
4687 switch (storage)
4688 {
4689 case Variable::VARYING_INPUT:
4690 si.m_inputs.push_back(var);
4691 result = si.m_inputs.back();
4692 break;
4693 case Variable::VARYING_OUTPUT:
4694 si.m_outputs.push_back(var);
4695 result = si.m_outputs.back();
4696 break;
4697 case Variable::UNIFORM:
4698 /* Uniform blocks needs unique binding */
4699 if (true == is_block)
4700 {
4701 replaceBinding(*var, stage);
4702 }
4703
4704 si.m_uniforms.push_back(var);
4705 result = si.m_uniforms.back();
4706 break;
4707 case Variable::SSB:
4708 /* SSBs needs unique binding */
4709 if (true == is_block)
4710 {
4711 replaceBinding(*var, stage);
4712 }
4713
4714 si.m_ssb_blocks.push_back(var);
4715 result = si.m_ssb_blocks.back();
4716 break;
4717 default:
4718 TCU_FAIL("Invalid enum");
4719 break;
4720 }
4721
4722 return result;
4723 }
4724
4725 /** clone block to specific stage
4726 *
4727 * @param block Block to be copied
4728 * @param stage Specific stage
4729 * @param storage Storage used by block
4730 * @param prefix Prefix used in block name
4731 *
4732 * @return New interface
4733 **/
CloneBlockForStage(const Interface & block,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4734 Interface* ProgramInterface::CloneBlockForStage(const Interface& block, Shader::STAGES stage, Variable::STORAGE storage,
4735 const GLchar* prefix)
4736 {
4737 /* Get name */
4738 std::string name = block.m_name;
4739
4740 /* Prefix name with stage ID */
4741 size_t position = 0;
4742 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4743 Utils::replaceToken(prefix, position, stage_prefix, name);
4744
4745 Interface* ptr = GetBlock(name.c_str());
4746
4747 if (0 == ptr)
4748 {
4749 ptr = AddInterface(name.c_str(), Interface::BLOCK);
4750 }
4751
4752 ptr->m_members = block.m_members;
4753
4754 return ptr;
4755 }
4756
4757 /** Get stage specific prefix used in names
4758 *
4759 * @param stage Stage
4760 * @param storage Storage class
4761 *
4762 * @return String
4763 **/
GetStagePrefix(Shader::STAGES stage,Variable::STORAGE storage)4764 const GLchar* ProgramInterface::GetStagePrefix(Shader::STAGES stage, Variable::STORAGE storage)
4765 {
4766 static const GLchar* lut[Shader::STAGE_MAX][Variable::STORAGE_MAX] = {
4767 /* IN OUT UNIFORM SSB MEMBER */
4768 /* CS */ { 0, 0, "cs_uni_", "cs_buf_", "" },
4769 /* VS */ { "in_vs_", "vs_tcs_", "vs_uni_", "vs_buf_", "" },
4770 /* TCS */ { "vs_tcs_", "tcs_tes_", "tcs_uni_", "tcs_buf_", "" },
4771 /* TES */ { "tcs_tes_", "tes_gs_", "tes_uni_", "tes_buf_", "" },
4772 /* GS */ { "tes_gs_", "gs_fs_", "gs_uni_", "gs_buf_", "" },
4773 /* FS */ { "gs_fs_", "fs_out_", "fs_uni_", "fs_buf_", "" },
4774 };
4775
4776 const GLchar* result = 0;
4777
4778 result = lut[stage][storage];
4779
4780 return result;
4781 }
4782
4783 /** Get definitions of all structures used in program interface
4784 *
4785 * @return String with code
4786 **/
GetDefinitionsStructures() const4787 std::string ProgramInterface::GetDefinitionsStructures() const
4788 {
4789 return GetDefinitions(m_structures);
4790 }
4791
4792 /** Get interface code for stage
4793 *
4794 * @param stage Specific stage
4795 *
4796 * @return String with code
4797 **/
GetInterfaceForStage(Shader::STAGES stage) const4798 std::string ProgramInterface::GetInterfaceForStage(Shader::STAGES stage) const
4799 {
4800 size_t position = 0;
4801 std::string interface = "/* Globals */\n"
4802 "GLOBALS\n"
4803 "\n"
4804 "/* Structures */\n"
4805 "STRUCTURES\n"
4806 "\n"
4807 "/* Uniforms */\n"
4808 "UNIFORMS\n"
4809 "\n"
4810 "/* Inputs */\n"
4811 "INPUTS\n"
4812 "\n"
4813 "/* Outputs */\n"
4814 "OUTPUTS\n"
4815 "\n"
4816 "/* Storage */\n"
4817 "STORAGE\n";
4818
4819 const ShaderInterface& si = GetShaderInterface(stage);
4820
4821 const std::string& structures = GetDefinitionsStructures();
4822
4823 const std::string& globals = si.GetDefinitionsGlobals();
4824 const std::string& inputs = si.GetDefinitionsInputs();
4825 const std::string& outputs = si.GetDefinitionsOutputs();
4826 const std::string& uniforms = si.GetDefinitionsUniforms();
4827 const std::string& ssbs = si.GetDefinitionsSSBs();
4828
4829 replaceToken("GLOBALS", position, globals.c_str(), interface);
4830 replaceToken("STRUCTURES", position, structures.c_str(), interface);
4831 replaceToken("UNIFORMS", position, uniforms.c_str(), interface);
4832 replaceToken("INPUTS", position, inputs.c_str(), interface);
4833 replaceToken("OUTPUTS", position, outputs.c_str(), interface);
4834 replaceToken("STORAGE", position, ssbs.c_str(), interface);
4835
4836 return interface;
4837 }
4838
4839 /** Functional object used in find_if algorithm, in search for interface of given name
4840 *
4841 **/
4842 struct matchInterfaceName
4843 {
matchInterfaceNamegl4cts::EnhancedLayouts::Utils::matchInterfaceName4844 matchInterfaceName(const GLchar* name) : m_name(name)
4845 {
4846 }
4847
operator ()gl4cts::EnhancedLayouts::Utils::matchInterfaceName4848 bool operator()(const Interface* interface)
4849 {
4850 return 0 == interface->m_name.compare(m_name);
4851 }
4852
4853 const GLchar* m_name;
4854 };
4855
4856 /** Finds interface of given name in given vector of interfaces
4857 *
4858 * @param vector Collection of interfaces
4859 * @param name Requested name
4860 *
4861 * @return Pointer to interface if available, 0 otherwise
4862 **/
findInterfaceByName(Interface::PtrVector & vector,const GLchar * name)4863 static Interface* findInterfaceByName(Interface::PtrVector& vector, const GLchar* name)
4864 {
4865 Interface::PtrVector::iterator it = std::find_if(vector.begin(), vector.end(), matchInterfaceName(name));
4866
4867 if (vector.end() != it)
4868 {
4869 return *it;
4870 }
4871 else
4872 {
4873 return 0;
4874 }
4875 }
4876
4877 /** Search for block of given name
4878 *
4879 * @param name Name of block
4880 *
4881 * @return Pointer to block or 0
4882 **/
GetBlock(const GLchar * name)4883 Interface* ProgramInterface::GetBlock(const GLchar* name)
4884 {
4885 return findInterfaceByName(m_blocks, name);
4886 }
4887
4888 /** Search for structure of given name
4889 *
4890 * @param name Name of structure
4891 *
4892 * @return Pointer to structure or 0
4893 **/
GetStructure(const GLchar * name)4894 Interface* ProgramInterface::GetStructure(const GLchar* name)
4895 {
4896 return findInterfaceByName(m_structures, name);
4897 }
4898
4899 /** Adds new sturcture to interface
4900 *
4901 * @param name Name of structure
4902 *
4903 * @return Created structure
4904 **/
Structure(const GLchar * name)4905 Interface* ProgramInterface::Structure(const GLchar* name)
4906 {
4907 return AddInterface(name, Interface::STRUCT);
4908 }
4909
4910 /** Replace "BINDING" token in qualifiers string to value specific for given stage
4911 *
4912 * @param variable Variable to modify
4913 * @param stage Requested stage
4914 **/
replaceBinding(Variable & variable,Shader::STAGES stage)4915 void ProgramInterface::replaceBinding(Variable& variable, Shader::STAGES stage)
4916 {
4917 GLchar binding[16];
4918 sprintf(binding, "%d", stage);
4919 replaceAllTokens("BINDING", binding, variable.m_descriptor.m_qualifiers);
4920 }
4921 } /* Utils namespace */
4922
4923 /** Debuging procedure. Logs parameters.
4924 *
4925 * @param source As specified in GL spec.
4926 * @param type As specified in GL spec.
4927 * @param id As specified in GL spec.
4928 * @param severity As specified in GL spec.
4929 * @param ignored
4930 * @param message As specified in GL spec.
4931 * @param info Pointer to instance of Context used by test.
4932 */
debug_proc(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei,const GLchar * message,void * info)4933 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */,
4934 const GLchar* message, void* info)
4935 {
4936 deqp::Context* ctx = (deqp::Context*)info;
4937
4938 const GLchar* source_str = "Unknown";
4939 const GLchar* type_str = "Unknown";
4940 const GLchar* severity_str = "Unknown";
4941
4942 switch (source)
4943 {
4944 case GL_DEBUG_SOURCE_API:
4945 source_str = "API";
4946 break;
4947 case GL_DEBUG_SOURCE_APPLICATION:
4948 source_str = "APP";
4949 break;
4950 case GL_DEBUG_SOURCE_OTHER:
4951 source_str = "OTR";
4952 break;
4953 case GL_DEBUG_SOURCE_SHADER_COMPILER:
4954 source_str = "COM";
4955 break;
4956 case GL_DEBUG_SOURCE_THIRD_PARTY:
4957 source_str = "3RD";
4958 break;
4959 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
4960 source_str = "WS";
4961 break;
4962 default:
4963 break;
4964 }
4965
4966 switch (type)
4967 {
4968 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
4969 type_str = "DEPRECATED_BEHAVIOR";
4970 break;
4971 case GL_DEBUG_TYPE_ERROR:
4972 type_str = "ERROR";
4973 break;
4974 case GL_DEBUG_TYPE_MARKER:
4975 type_str = "MARKER";
4976 break;
4977 case GL_DEBUG_TYPE_OTHER:
4978 type_str = "OTHER";
4979 break;
4980 case GL_DEBUG_TYPE_PERFORMANCE:
4981 type_str = "PERFORMANCE";
4982 break;
4983 case GL_DEBUG_TYPE_POP_GROUP:
4984 type_str = "POP_GROUP";
4985 break;
4986 case GL_DEBUG_TYPE_PORTABILITY:
4987 type_str = "PORTABILITY";
4988 break;
4989 case GL_DEBUG_TYPE_PUSH_GROUP:
4990 type_str = "PUSH_GROUP";
4991 break;
4992 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
4993 type_str = "UNDEFINED_BEHAVIOR";
4994 break;
4995 default:
4996 break;
4997 }
4998
4999 switch (severity)
5000 {
5001 case GL_DEBUG_SEVERITY_HIGH:
5002 severity_str = "H";
5003 break;
5004 case GL_DEBUG_SEVERITY_LOW:
5005 severity_str = "L";
5006 break;
5007 case GL_DEBUG_SEVERITY_MEDIUM:
5008 severity_str = "M";
5009 break;
5010 case GL_DEBUG_SEVERITY_NOTIFICATION:
5011 severity_str = "N";
5012 break;
5013 default:
5014 break;
5015 }
5016
5017 ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|"
5018 << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id
5019 << ": " << message << tcu::TestLog::EndMessage;
5020 }
5021
5022 /** Constructor
5023 *
5024 * @param context Test context
5025 * @param test_name Test name
5026 * @param test_description Test description
5027 **/
TestBase(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)5028 TestBase::TestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5029 : TestCase(context, test_name, test_description)
5030 {
5031 /* Nothing to be done here */
5032 }
5033
5034 /** Execute test
5035 *
5036 * @return tcu::TestNode::STOP otherwise
5037 **/
iterate()5038 tcu::TestNode::IterateResult TestBase::iterate()
5039 {
5040 bool test_result;
5041
5042 #if DEBUG_ENBALE_MESSAGE_CALLBACK
5043 const Functions& gl = m_context.getRenderContext().getFunctions();
5044
5045 gl.debugMessageCallback(debug_proc, &m_context);
5046 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
5047 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
5048
5049 try
5050 {
5051 /* Execute test */
5052 test_result = test();
5053 }
5054 catch (std::exception& exc)
5055 {
5056 TCU_FAIL(exc.what());
5057 }
5058
5059 /* Set result */
5060 if (true == test_result)
5061 {
5062 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5063 }
5064 else
5065 {
5066 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5067 }
5068
5069 /* Done */
5070 return tcu::TestNode::STOP;
5071 }
5072
5073 /** Get last input location available for given type at specific stage
5074 *
5075 * @param stage Shader stage
5076 * @param type Input type
5077 * @param array_length Length of input array
5078 *
5079 * @return Last location index
5080 **/
getLastInputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_prev_stage)5081 GLint TestBase::getLastInputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_prev_stage)
5082 {
5083 GLint divide = 4; /* 4 components per location */
5084 GLint param = 0;
5085 GLenum pname = 0;
5086 GLint paramPrev = 0;
5087 GLenum pnamePrev = 0;
5088
5089 /* Select pnmae */
5090 switch (stage)
5091 {
5092 case Utils::Shader::FRAGMENT:
5093 pname = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5094 pnamePrev = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5095 break;
5096 case Utils::Shader::GEOMETRY:
5097 pname = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5098 pnamePrev = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5099 break;
5100 case Utils::Shader::TESS_CTRL:
5101 pname = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5102 pnamePrev = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5103 break;
5104 case Utils::Shader::TESS_EVAL:
5105 pname = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5106 pnamePrev = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5107 break;
5108 case Utils::Shader::VERTEX:
5109 pname = GL_MAX_VERTEX_ATTRIBS;
5110 divide = 1;
5111 break;
5112 default:
5113 TCU_FAIL("Invalid enum");
5114 break;
5115 }
5116
5117 /* Zero means no array, but 1 slot is required */
5118 if (0 == array_length)
5119 {
5120 array_length += 1;
5121 }
5122
5123 /* Get MAX */
5124 const Functions& gl = m_context.getRenderContext().getFunctions();
5125
5126 gl.getIntegerv(pname, ¶m);
5127 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5128
5129 if (pnamePrev && !ignore_prev_stage) {
5130 gl.getIntegerv(pnamePrev, ¶mPrev);
5131 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5132
5133 /* Don't read from a location that doesn't exist in the previous stage */
5134 param = de::min(param, paramPrev);
5135 }
5136
5137 /* Calculate */
5138 #if WRKARD_VARYINGLOCATIONSTEST
5139
5140 const GLint n_avl_locations = 16;
5141
5142 #else
5143
5144 const GLint n_avl_locations = param / divide;
5145
5146 #endif
5147
5148 const GLuint n_req_location = type.GetLocations(stage == Utils::Shader::VERTEX) * array_length;
5149
5150 return n_avl_locations - n_req_location; /* last is max - 1 */
5151 }
5152
5153 /** Get last output location available for given type at specific stage
5154 *
5155 * @param stage Shader stage
5156 * @param type Input type
5157 * @param array_length Length of input array
5158 *
5159 * @return Last location index
5160 **/
getLastOutputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_next_stage)5161 GLint TestBase::getLastOutputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_next_stage)
5162 {
5163 GLint param = 0;
5164 GLenum pname = 0;
5165 GLint paramNext = 0;
5166 GLenum pnameNext = 0;
5167
5168 /* Select pname */
5169 switch (stage)
5170 {
5171 case Utils::Shader::GEOMETRY:
5172 pname = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5173 pnameNext = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5174 break;
5175 case Utils::Shader::TESS_CTRL:
5176 pname = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5177 pnameNext = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5178 break;
5179 case Utils::Shader::TESS_EVAL:
5180 pname = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5181 pnameNext = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5182 break;
5183 case Utils::Shader::VERTEX:
5184 pname = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5185 pnameNext = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5186 break;
5187 default:
5188 TCU_FAIL("Invalid enum");
5189 break;
5190 }
5191
5192 /* Zero means no array, but 1 slot is required */
5193 if (0 == array_length)
5194 {
5195 array_length += 1;
5196 }
5197
5198 /* Get MAX */
5199 const Functions& gl = m_context.getRenderContext().getFunctions();
5200
5201 gl.getIntegerv(pname, ¶m);
5202 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5203
5204 /* Calculate */
5205 #if WRKARD_VARYINGLOCATIONSTEST
5206
5207 const GLint n_avl_locations = 16;
5208
5209 #else
5210
5211 /* Don't write to a location that doesn't exist in the next stage */
5212 if (!ignore_next_stage)
5213 {
5214 gl.getIntegerv(pnameNext, ¶mNext);
5215 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5216
5217 param = de::min(param, paramNext);
5218 }
5219
5220 const GLint n_avl_locations = param / 4; /* 4 components per location */
5221
5222 #endif
5223
5224 const GLuint n_req_location = type.GetLocations() * array_length;
5225
5226 return n_avl_locations - n_req_location; /* last is max - 1 */
5227 }
5228
5229 /** Basic implementation
5230 *
5231 * @param ignored
5232 *
5233 * @return Empty string
5234 **/
getTestCaseName(GLuint)5235 std::string TestBase::getTestCaseName(GLuint /* test_case_index */)
5236 {
5237 std::string result;
5238
5239 return result;
5240 }
5241
5242 /** Basic implementation
5243 *
5244 * @return 1
5245 **/
getTestCaseNumber()5246 GLuint TestBase::getTestCaseNumber()
5247 {
5248 return 1;
5249 }
5250
5251 /** Check if flat qualifier is required for given type, stage and storage
5252 *
5253 * @param stage Shader stage
5254 * @param type Input type
5255 * @param storage Storage of variable
5256 *
5257 * @return Last location index
5258 **/
isFlatRequired(Utils::Shader::STAGES stage,const Utils::Type & type,Utils::Variable::STORAGE storage) const5259 bool TestBase::isFlatRequired(Utils::Shader::STAGES stage, const Utils::Type& type,
5260 Utils::Variable::STORAGE storage) const
5261 {
5262 /* Float types do not need flat at all */
5263 if (Utils::Type::Float == type.m_basic_type)
5264 {
5265 return false;
5266 }
5267
5268 /* Inputs to fragment shader */
5269 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Variable::VARYING_INPUT == storage))
5270 {
5271 return true;
5272 }
5273
5274 /* Outputs from geometry shader */
5275 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Variable::VARYING_OUTPUT == storage))
5276 {
5277 return true;
5278 }
5279
5280 return false;
5281 }
5282
5283 /** Basic implementation of testInit method
5284 *
5285 **/
testInit()5286 void TestBase::testInit()
5287 {
5288 }
5289
5290 /** Calculate stride for interface
5291 *
5292 * @param interface Interface
5293 *
5294 * @return Calculated value
5295 **/
calculateStride(const Utils::Interface & interface) const5296 GLuint TestBase::calculateStride(const Utils::Interface& interface) const
5297 {
5298 const size_t n_members = interface.m_members.size();
5299
5300 GLuint stride = 0;
5301
5302 for (size_t i = 0; i < n_members; ++i)
5303 {
5304 const Utils::Variable::Descriptor& member = interface.m_members[i];
5305 const GLuint member_offset = member.m_offset;
5306 const GLuint member_stride = member.m_expected_stride_of_element;
5307 const GLuint member_ends_at = member_offset + member_stride;
5308
5309 stride = std::max(stride, member_ends_at);
5310 }
5311
5312 return stride;
5313 }
5314
5315 /** Generate data for interface. This routine is recursive
5316 *
5317 * @param interface Interface
5318 * @param offset Offset in out_data
5319 * @param out_data Buffer to be filled
5320 **/
generateData(const Utils::Interface & interface,GLuint offset,std::vector<GLubyte> & out_data) const5321 void TestBase::generateData(const Utils::Interface& interface, GLuint offset, std::vector<GLubyte>& out_data) const
5322 {
5323 const size_t n_members = interface.m_members.size();
5324 GLubyte* ptr = &out_data[offset];
5325
5326 for (size_t i = 0; i < n_members; ++i)
5327 {
5328 const Utils::Variable::Descriptor& member = interface.m_members[i];
5329 const GLuint member_offset = member.m_offset;
5330 const GLuint n_elements = (0 == member.m_n_array_elements) ? 1 : member.m_n_array_elements;
5331
5332 for (GLuint element = 0; element < n_elements; ++element)
5333 {
5334 const GLuint element_offset = element * member.m_expected_stride_of_element;
5335 const GLuint data_offfset = member_offset + element_offset;
5336
5337 if (Utils::Variable::BUILTIN == member.m_type)
5338 {
5339 const std::vector<GLubyte>& data = member.m_builtin.GenerateData();
5340
5341 memcpy(ptr + data_offfset, &data[0], data.size());
5342 }
5343 else
5344 {
5345 generateData(*member.m_interface, offset + data_offfset, out_data);
5346 }
5347 }
5348 }
5349 }
5350
5351 /** Get type at index
5352 *
5353 * @param index Index of requested type
5354 *
5355 * @return Type
5356 **/
getType(GLuint index) const5357 Utils::Type TestBase::getType(GLuint index) const
5358 {
5359 Utils::Type type;
5360
5361 switch (index)
5362 {
5363 case 0:
5364 type = Utils::Type::_double;
5365 break;
5366 case 1:
5367 type = Utils::Type::dmat2;
5368 break;
5369 case 2:
5370 type = Utils::Type::dmat2x3;
5371 break;
5372 case 3:
5373 type = Utils::Type::dmat2x4;
5374 break;
5375 case 4:
5376 type = Utils::Type::dmat3;
5377 break;
5378 case 5:
5379 type = Utils::Type::dmat3x2;
5380 break;
5381 case 6:
5382 type = Utils::Type::dmat3x4;
5383 break;
5384 case 7:
5385 type = Utils::Type::dmat4;
5386 break;
5387 case 8:
5388 type = Utils::Type::dmat4x2;
5389 break;
5390 case 9:
5391 type = Utils::Type::dmat4x3;
5392 break;
5393 case 10:
5394 type = Utils::Type::dvec2;
5395 break;
5396 case 11:
5397 type = Utils::Type::dvec3;
5398 break;
5399 case 12:
5400 type = Utils::Type::dvec4;
5401 break;
5402 case 13:
5403 type = Utils::Type::_float;
5404 break;
5405 case 14:
5406 type = Utils::Type::mat2;
5407 break;
5408 case 15:
5409 type = Utils::Type::mat2x3;
5410 break;
5411 case 16:
5412 type = Utils::Type::mat2x4;
5413 break;
5414 case 17:
5415 type = Utils::Type::mat3;
5416 break;
5417 case 18:
5418 type = Utils::Type::mat3x2;
5419 break;
5420 case 19:
5421 type = Utils::Type::mat3x4;
5422 break;
5423 case 20:
5424 type = Utils::Type::mat4;
5425 break;
5426 case 21:
5427 type = Utils::Type::mat4x2;
5428 break;
5429 case 22:
5430 type = Utils::Type::mat4x3;
5431 break;
5432 case 23:
5433 type = Utils::Type::vec2;
5434 break;
5435 case 24:
5436 type = Utils::Type::vec3;
5437 break;
5438 case 25:
5439 type = Utils::Type::vec4;
5440 break;
5441 case 26:
5442 type = Utils::Type::_int;
5443 break;
5444 case 27:
5445 type = Utils::Type::ivec2;
5446 break;
5447 case 28:
5448 type = Utils::Type::ivec3;
5449 break;
5450 case 29:
5451 type = Utils::Type::ivec4;
5452 break;
5453 case 30:
5454 type = Utils::Type::uint;
5455 break;
5456 case 31:
5457 type = Utils::Type::uvec2;
5458 break;
5459 case 32:
5460 type = Utils::Type::uvec3;
5461 break;
5462 case 33:
5463 type = Utils::Type::uvec4;
5464 break;
5465 default:
5466 TCU_FAIL("invalid enum");
5467 }
5468
5469 return type;
5470 }
5471
5472 /** Get name of type at index
5473 *
5474 * @param index Index of type
5475 *
5476 * @return Name
5477 **/
getTypeName(GLuint index) const5478 std::string TestBase::getTypeName(GLuint index) const
5479 {
5480 std::string name = getType(index).GetGLSLTypeName();
5481
5482 return name;
5483 }
5484
5485 /** Get number of types
5486 *
5487 * @return 34
5488 **/
getTypesNumber() const5489 glw::GLuint TestBase::getTypesNumber() const
5490 {
5491 return 34;
5492 }
5493
5494 /** Execute test
5495 *
5496 * @return true if test pass, false otherwise
5497 **/
test()5498 bool TestBase::test()
5499 {
5500 bool result = true;
5501 GLuint n_test_cases = 0;
5502
5503 /* Prepare test */
5504 testInit();
5505
5506 /* GL entry points */
5507 const Functions& gl = m_context.getRenderContext().getFunctions();
5508
5509 /* Tessellation patch set up */
5510 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5511 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5512
5513 /* Get number of test cases */
5514 n_test_cases = getTestCaseNumber();
5515
5516 #if DEBUG_REPEAT_TEST_CASE
5517
5518 while (1)
5519 {
5520 GLuint test_case = DEBUG_REPEATED_TEST_CASE;
5521
5522 #else /* DEBUG_REPEAT_TEST_CASE */
5523
5524 for (GLuint test_case = 0; test_case < n_test_cases; ++test_case)
5525 {
5526 #endif /* DEBUG_REPEAT_TEST_CASE */
5527
5528 bool case_result = true;
5529
5530 /* Execute case */
5531 if (false == testCase(test_case))
5532 {
5533 case_result = false;
5534 }
5535
5536 /* Log failure */
5537 if (false == case_result)
5538 {
5539 const std::string& test_case_name = getTestCaseName(test_case);
5540
5541 if (false == test_case_name.empty())
5542 {
5543 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case_name
5544 << ") failed." << tcu::TestLog::EndMessage;
5545 }
5546 else
5547 {
5548 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case
5549 << ") failed." << tcu::TestLog::EndMessage;
5550 }
5551
5552 result = false;
5553 }
5554 }
5555
5556 /* Done */
5557 return result;
5558 }
5559
5560 /* Constants used by BufferTestBase */
5561 const GLuint BufferTestBase::bufferDescriptor::m_non_indexed = -1;
5562
5563 /** Constructor
5564 *
5565 * @param context Test context
5566 * @param test_name Name of test
5567 * @param test_description Description of test
5568 **/
5569 BufferTestBase::BufferTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5570 : TestBase(context, test_name, test_description)
5571 {
5572 }
5573
5574 /** Execute drawArrays for single vertex
5575 *
5576 * @param ignored
5577 *
5578 * @return true
5579 **/
5580 bool BufferTestBase::executeDrawCall(bool tesEnabled, GLuint /* test_case_index */)
5581 {
5582 const Functions& gl = m_context.getRenderContext().getFunctions();
5583
5584 gl.disable(GL_RASTERIZER_DISCARD);
5585 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
5586
5587 gl.beginTransformFeedback(GL_POINTS);
5588 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5589
5590 // Only TES is existed, glDrawArray can use the parameter GL_PATCHES
5591 if (tesEnabled == false)
5592 {
5593 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5594 }
5595 else
5596 {
5597 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5598 }
5599
5600 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5601
5602 gl.endTransformFeedback();
5603 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5604
5605 return true;
5606 }
5607
5608 /** Get descriptors of buffers necessary for test
5609 *
5610 * @param ignored
5611 * @param ignored
5612 **/
5613 void BufferTestBase::getBufferDescriptors(glw::GLuint /* test_case_index */,
5614 bufferDescriptor::Vector& /* out_descriptors */)
5615 {
5616 /* Nothhing to be done */
5617 }
5618
5619 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
5620 *
5621 * @param ignored
5622 * @param ignored
5623 **/
5624 void BufferTestBase::getCapturedVaryings(glw::GLuint /* test_case_index */,
5625 Utils::Program::NameVector& /* captured_varyings */,
5626 GLint* /* xfb_components */)
5627 {
5628 /* Nothing to be done */
5629 }
5630
5631 /** Get body of main function for given shader stage
5632 *
5633 * @param ignored
5634 * @param ignored
5635 * @param out_assignments Set to empty
5636 * @param out_calculations Set to empty
5637 **/
5638 void BufferTestBase::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5639 std::string& out_assignments, std::string& out_calculations)
5640 {
5641 out_assignments = "";
5642 out_calculations = "";
5643 }
5644
5645 /** Get interface of shader
5646 *
5647 * @param ignored
5648 * @param ignored
5649 * @param out_interface Set to ""
5650 **/
5651 void BufferTestBase::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5652 std::string& out_interface)
5653 {
5654 out_interface = "";
5655 }
5656
5657 /** Get source code of shader
5658 *
5659 * @param test_case_index Index of test case
5660 * @param stage Shader stage
5661 *
5662 * @return Source
5663 **/
5664 std::string BufferTestBase::getShaderSource(glw::GLuint test_case_index, Utils::Shader::STAGES stage)
5665 {
5666 std::string assignments;
5667 std::string calculations;
5668 std::string interface;
5669
5670 /* */
5671 getShaderBody(test_case_index, stage, assignments, calculations);
5672 getShaderInterface(test_case_index, stage, interface);
5673
5674 /* */
5675 std::string source = getShaderTemplate(stage);
5676
5677 /* */
5678 size_t position = 0;
5679 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
5680 Utils::replaceToken("CALCULATIONS", position, calculations.c_str(), source);
5681 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
5682
5683 /* */
5684 return source;
5685 }
5686
5687 /** Inspects program to check if all resources are as expected
5688 *
5689 * @param ignored
5690 * @param ignored
5691 * @param ignored
5692 *
5693 * @return true
5694 **/
5695 bool BufferTestBase::inspectProgram(GLuint /* test_case_index */, Utils::Program& /* program */,
5696 std::stringstream& /* out_stream */)
5697 {
5698 return true;
5699 }
5700
5701 /** Runs test case
5702 *
5703 * @param test_case_index Id of test case
5704 *
5705 * @return true if test case pass, false otherwise
5706 **/
5707 bool BufferTestBase::testCase(GLuint test_case_index)
5708 {
5709 try
5710 {
5711 bufferCollection buffers;
5712 Utils::Program::NameVector captured_varyings;
5713 bufferDescriptor::Vector descriptors;
5714 Utils::Program program(m_context);
5715 Utils::VertexArray vao(m_context);
5716
5717 /* Get captured varyings */
5718 GLint xfb_components;
5719 getCapturedVaryings(test_case_index, captured_varyings, &xfb_components);
5720
5721 /* Don't generate shaders that try to capture more XFB components than the implementation's limit */
5722 if (captured_varyings.size() > 0)
5723 {
5724 const Functions& gl = m_context.getRenderContext().getFunctions();
5725
5726 GLint max_xfb_components;
5727 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_components);
5728 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5729
5730 if (xfb_components > max_xfb_components)
5731 return true;
5732 }
5733
5734 /* Get shader sources */
5735 const std::string& fragment_shader = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
5736 const std::string& geometry_shader = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
5737 const std::string& tess_ctrl_shader = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
5738 const std::string& tess_eval_shader = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
5739 const std::string& vertex_shader = getShaderSource(test_case_index, Utils::Shader::VERTEX);
5740
5741 /* Set up program */
5742 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
5743 vertex_shader, captured_varyings, true, false /* is_separable */);
5744
5745 /* Inspection */
5746 {
5747 std::stringstream stream;
5748 if (false == inspectProgram(test_case_index, program, stream))
5749 {
5750 m_context.getTestContext().getLog()
5751 << tcu::TestLog::Message
5752 << "Program inspection failed. Test case: " << getTestCaseName(test_case_index)
5753 << ". Reason: " << stream.str() << tcu::TestLog::EndMessage
5754 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5755 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5756 << tcu::TestLog::KernelSource(fragment_shader);
5757
5758 return false;
5759 }
5760 }
5761
5762 program.Use();
5763
5764 /* Set up buffers */
5765 getBufferDescriptors(test_case_index, descriptors);
5766 cleanBuffers();
5767 prepareBuffers(descriptors, buffers);
5768
5769 /* Set up vao */
5770 vao.Init();
5771 vao.Bind();
5772
5773 /* Draw */
5774 bool result = executeDrawCall((program.m_tess_eval.m_id != 0), test_case_index);
5775
5776 #if USE_NSIGHT
5777 m_context.getRenderContext().postIterate();
5778 #endif
5779
5780 if (false == result)
5781 {
5782 m_context.getTestContext().getLog()
5783 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5784 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5785 << tcu::TestLog::KernelSource(fragment_shader);
5786
5787 return false;
5788 }
5789
5790 /* Verify result */
5791 if (false == verifyBuffers(buffers))
5792 {
5793 m_context.getTestContext().getLog()
5794 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5795 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5796 << tcu::TestLog::KernelSource(fragment_shader);
5797
5798 return false;
5799 }
5800 }
5801 catch (Utils::Shader::InvalidSourceException& exc)
5802 {
5803 exc.log(m_context);
5804 TCU_FAIL(exc.what());
5805 }
5806 catch (Utils::Program::BuildException& exc)
5807 {
5808 exc.log(m_context);
5809 TCU_FAIL(exc.what());
5810 }
5811
5812 /* Done */
5813 return true;
5814 }
5815
5816 /** Verify contents of buffers
5817 *
5818 * @param buffers Collection of buffers to be verified
5819 *
5820 * @return true if everything is as expected, false otherwise
5821 **/
5822 bool BufferTestBase::verifyBuffers(bufferCollection& buffers)
5823 {
5824 bool result = true;
5825
5826 for (bufferCollection::Vector::iterator it = buffers.m_vector.begin(), end = buffers.m_vector.end(); end != it;
5827 ++it)
5828 {
5829 bufferCollection::pair& pair = *it;
5830 Utils::Buffer* buffer = pair.m_buffer;
5831 bufferDescriptor* descriptor = pair.m_descriptor;
5832 size_t size = descriptor->m_expected_data.size();
5833
5834 /* Skip buffers that have no expected data */
5835 if (0 == size)
5836 {
5837 continue;
5838 }
5839
5840 /* Get pointer to contents of buffer */
5841 buffer->Bind();
5842 GLvoid* buffer_data = buffer->Map(Utils::Buffer::ReadOnly);
5843
5844 /* Get pointer to expected data */
5845 GLvoid* expected_data = &descriptor->m_expected_data[0];
5846
5847 /* Compare */
5848 int res = memcmp(buffer_data, expected_data, size);
5849
5850 if (0 != res)
5851 {
5852 m_context.getTestContext().getLog()
5853 << tcu::TestLog::Message
5854 << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
5855 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
5856
5857 result = false;
5858 }
5859
5860 /* Release buffer mapping */
5861 buffer->UnMap();
5862 }
5863
5864 return result;
5865 }
5866
5867 /** Unbinds all uniforms and xfb
5868 *
5869 **/
5870 void BufferTestBase::cleanBuffers()
5871 {
5872 const Functions& gl = m_context.getRenderContext().getFunctions();
5873
5874 GLint max_uni = 0;
5875 GLint max_xfb = 0;
5876
5877 gl.getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uni);
5878 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
5879 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5880
5881 for (GLint i = 0; i < max_uni; ++i)
5882 {
5883 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Uniform, i);
5884 }
5885
5886 for (GLint i = 0; i < max_xfb; ++i)
5887 {
5888 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Transform_feedback, i);
5889 }
5890 }
5891
5892 /** Get template of shader for given stage
5893 *
5894 * @param stage Stage
5895 *
5896 * @return Template of shader source
5897 **/
5898 std::string BufferTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
5899 {
5900 static const GLchar* compute_shader_template = "#version 430 core\n"
5901 "#extension GL_ARB_enhanced_layouts : require\n"
5902 "\n"
5903 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
5904 "\n"
5905 "writeonly uniform uimage2D uni_image;\n"
5906 "\n"
5907 "INTERFACE"
5908 "\n"
5909 "void main()\n"
5910 "{\n"
5911 "CALCULATIONS"
5912 "\n"
5913 "ASSIGNMENTS"
5914 "}\n"
5915 "\n";
5916
5917 static const GLchar* fragment_shader_template = "#version 430 core\n"
5918 "#extension GL_ARB_enhanced_layouts : require\n"
5919 "\n"
5920 "INTERFACE"
5921 "\n"
5922 "void main()\n"
5923 "{\n"
5924 "CALCULATIONS"
5925 "\n"
5926 "ASSIGNMENTS"
5927 "}\n"
5928 "\n";
5929
5930 // max_vertices is set to 3 for the test case "xfb_vertex_streams" declares 3 streams in geometry shader,
5931 // according to spec, max_vertices should be no less than 3 if there are 3 streams in GS.
5932 static const GLchar* geometry_shader_template = "#version 430 core\n"
5933 "#extension GL_ARB_enhanced_layouts : require\n"
5934 "\n"
5935 "layout(points) in;\n"
5936 "layout(points, max_vertices = 3) out;\n"
5937 "\n"
5938 "INTERFACE"
5939 "\n"
5940 "void main()\n"
5941 "{\n"
5942 "CALCULATIONS"
5943 "\n"
5944 "\n"
5945 "ASSIGNMENTS"
5946 " gl_Position = vec4(0, 0, 0, 1);\n"
5947 " EmitVertex();\n"
5948 "}\n"
5949 "\n";
5950
5951 static const GLchar* tess_ctrl_shader_template = "#version 430 core\n"
5952 "#extension GL_ARB_enhanced_layouts : require\n"
5953 "\n"
5954 "layout(vertices = 1) out;\n"
5955 "\n"
5956 "INTERFACE"
5957 "\n"
5958 "void main()\n"
5959 "{\n"
5960 "CALCULATIONS"
5961 "\n"
5962 "ASSIGNMENTS"
5963 "\n"
5964 " gl_TessLevelOuter[0] = 1.0;\n"
5965 " gl_TessLevelOuter[1] = 1.0;\n"
5966 " gl_TessLevelOuter[2] = 1.0;\n"
5967 " gl_TessLevelOuter[3] = 1.0;\n"
5968 " gl_TessLevelInner[0] = 1.0;\n"
5969 " gl_TessLevelInner[1] = 1.0;\n"
5970 "}\n"
5971 "\n";
5972
5973 static const GLchar* tess_eval_shader_template = "#version 430 core\n"
5974 "#extension GL_ARB_enhanced_layouts : require\n"
5975 "\n"
5976 "layout(isolines, point_mode) in;\n"
5977 "\n"
5978 "INTERFACE"
5979 "\n"
5980 "void main()\n"
5981 "{\n"
5982 "CALCULATIONS"
5983 "\n"
5984 "ASSIGNMENTS"
5985 "}\n"
5986 "\n";
5987
5988 static const GLchar* vertex_shader_template = "#version 430 core\n"
5989 "#extension GL_ARB_enhanced_layouts : require\n"
5990 "\n"
5991 "INTERFACE"
5992 "\n"
5993 "void main()\n"
5994 "{\n"
5995 "CALCULATIONS"
5996 "\n"
5997 "ASSIGNMENTS"
5998 "}\n"
5999 "\n";
6000
6001 const GLchar* result = 0;
6002
6003 switch (stage)
6004 {
6005 case Utils::Shader::COMPUTE:
6006 result = compute_shader_template;
6007 break;
6008 case Utils::Shader::FRAGMENT:
6009 result = fragment_shader_template;
6010 break;
6011 case Utils::Shader::GEOMETRY:
6012 result = geometry_shader_template;
6013 break;
6014 case Utils::Shader::TESS_CTRL:
6015 result = tess_ctrl_shader_template;
6016 break;
6017 case Utils::Shader::TESS_EVAL:
6018 result = tess_eval_shader_template;
6019 break;
6020 case Utils::Shader::VERTEX:
6021 result = vertex_shader_template;
6022 break;
6023 default:
6024 TCU_FAIL("Invalid enum");
6025 }
6026
6027 return result;
6028 }
6029
6030 /** Prepare buffer according to descriptor
6031 *
6032 * @param buffer Buffer to prepare
6033 * @param desc Descriptor
6034 **/
6035 void BufferTestBase::prepareBuffer(Utils::Buffer& buffer, bufferDescriptor& desc)
6036 {
6037 GLsizeiptr size = 0;
6038 GLvoid* data = 0;
6039
6040 if (false == desc.m_initial_data.empty())
6041 {
6042 size = desc.m_initial_data.size();
6043 data = &desc.m_initial_data[0];
6044 }
6045 else if (false == desc.m_expected_data.empty())
6046 {
6047 size = desc.m_expected_data.size();
6048 }
6049
6050 buffer.Init(desc.m_target, Utils::Buffer::StaticDraw, size, data);
6051
6052 if (bufferDescriptor::m_non_indexed != desc.m_index)
6053 {
6054 buffer.BindBase(desc.m_index);
6055 }
6056 else
6057 {
6058 buffer.Bind();
6059 }
6060 }
6061
6062 /** Prepare collection of buffer
6063 *
6064 * @param descriptors Collection of descriptors
6065 * @param out_buffers Collection of buffers
6066 **/
6067 void BufferTestBase::prepareBuffers(bufferDescriptor::Vector& descriptors, bufferCollection& out_buffers)
6068 {
6069 for (bufferDescriptor::Vector::iterator it = descriptors.begin(), end = descriptors.end(); end != it; ++it)
6070 {
6071 bufferCollection::pair pair;
6072
6073 pair.m_buffer = new Utils::Buffer(m_context);
6074 if (0 == pair.m_buffer)
6075 {
6076 TCU_FAIL("Memory allocation failed");
6077 }
6078
6079 pair.m_descriptor = &(*it);
6080
6081 prepareBuffer(*pair.m_buffer, *pair.m_descriptor);
6082
6083 out_buffers.m_vector.push_back(pair);
6084 }
6085 }
6086
6087 /** Destructor
6088 *
6089 **/
6090 BufferTestBase::bufferCollection::~bufferCollection()
6091 {
6092 for (Vector::iterator it = m_vector.begin(), end = m_vector.end(); end != it; ++it)
6093 {
6094 if (0 != it->m_buffer)
6095 {
6096 delete it->m_buffer;
6097 it->m_buffer = 0;
6098 }
6099 }
6100 }
6101
6102 /** Constructor
6103 *
6104 * @param context Test context
6105 * @param test_name Name of test
6106 * @param test_description Description of test
6107 **/
6108 NegativeTestBase::NegativeTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6109 : TestBase(context, test_name, test_description)
6110 {
6111 }
6112
6113 /** Selects if "compute" stage is relevant for test
6114 *
6115 * @param ignored
6116 *
6117 * @return true
6118 **/
6119 bool NegativeTestBase::isComputeRelevant(GLuint /* test_case_index */)
6120 {
6121 return true;
6122 }
6123
6124 /** Selects if compilation failure is expected result
6125 *
6126 * @param ignored
6127 *
6128 * @return true
6129 **/
6130 bool NegativeTestBase::isFailureExpected(GLuint /* test_case_index */)
6131 {
6132 return true;
6133 }
6134
6135 /** Runs test case
6136 *
6137 * @param test_case_index Id of test case
6138 *
6139 * @return true if test case pass, false otherwise
6140 **/
6141 bool NegativeTestBase::testCase(GLuint test_case_index)
6142 {
6143 bool test_case_result = true;
6144
6145 /* Compute */
6146 if (true == isComputeRelevant(test_case_index))
6147 {
6148 const std::string& cs_source = getShaderSource(test_case_index, Utils::Shader::COMPUTE);
6149 bool is_build_error = false;
6150 const bool is_failure_expected = isFailureExpected(test_case_index);
6151 Utils::Program program(m_context);
6152
6153 try
6154 {
6155 program.Init(cs_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */,
6156 false /* separable */);
6157 }
6158 catch (Utils::Shader::InvalidSourceException& exc)
6159 {
6160 if (false == is_failure_expected)
6161 {
6162 m_context.getTestContext().getLog()
6163 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6164 exc.log(m_context);
6165 }
6166
6167 #if DEBUG_NEG_LOG_ERROR
6168
6169 else
6170 {
6171 m_context.getTestContext().getLog()
6172 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6173 << tcu::TestLog::EndMessage;
6174 exc.log(m_context);
6175 }
6176
6177 #endif /* DEBUG_NEG_LOG_ERROR */
6178
6179 is_build_error = true;
6180 }
6181 catch (Utils::Program::BuildException& exc)
6182 {
6183 if (false == is_failure_expected)
6184 {
6185 m_context.getTestContext().getLog()
6186 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6187 exc.log(m_context);
6188 }
6189
6190 #if DEBUG_NEG_LOG_ERROR
6191
6192 else
6193 {
6194 m_context.getTestContext().getLog()
6195 << tcu::TestLog::Message
6196 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6197 exc.log(m_context);
6198 }
6199
6200 #endif /* DEBUG_NEG_LOG_ERROR */
6201
6202 is_build_error = true;
6203 }
6204
6205 if (is_build_error != is_failure_expected)
6206 {
6207 if (!is_build_error)
6208 {
6209 m_context.getTestContext().getLog()
6210 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6211 Utils::Shader::LogSource(m_context, cs_source, Utils::Shader::COMPUTE);
6212 }
6213 test_case_result = false;
6214 }
6215 }
6216 else /* Draw */
6217 {
6218 const std::string& fs_source = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
6219 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
6220 bool is_build_error = false;
6221 const bool is_failure_expected = isFailureExpected(test_case_index);
6222 Utils::Program program(m_context);
6223 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
6224 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
6225 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
6226
6227 try
6228 {
6229 program.Init("" /* cs */, fs_source, gs_source, tcs_source, tes_source, vs_source, false /* separable */);
6230 }
6231 catch (Utils::Shader::InvalidSourceException& exc)
6232 {
6233 if (false == is_failure_expected)
6234 {
6235 m_context.getTestContext().getLog()
6236 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6237 exc.log(m_context);
6238 }
6239
6240 #if DEBUG_NEG_LOG_ERROR
6241
6242 else
6243 {
6244 m_context.getTestContext().getLog()
6245 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6246 << tcu::TestLog::EndMessage;
6247 exc.log(m_context);
6248 }
6249
6250 #endif /* DEBUG_NEG_LOG_ERROR */
6251
6252 is_build_error = true;
6253 }
6254 catch (Utils::Program::BuildException& exc)
6255 {
6256 if (false == is_failure_expected)
6257 {
6258 m_context.getTestContext().getLog()
6259 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6260 exc.log(m_context);
6261 }
6262
6263 #if DEBUG_NEG_LOG_ERROR
6264
6265 else
6266 {
6267 m_context.getTestContext().getLog()
6268 << tcu::TestLog::Message
6269 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6270 exc.log(m_context);
6271 }
6272
6273 #endif /* DEBUG_NEG_LOG_ERROR */
6274
6275 is_build_error = true;
6276 }
6277
6278 if (is_build_error != is_failure_expected)
6279 {
6280 if (!is_build_error)
6281 {
6282 m_context.getTestContext().getLog()
6283 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6284 Utils::Shader::LogSource(m_context, vs_source, Utils::Shader::VERTEX);
6285 Utils::Shader::LogSource(m_context, tcs_source, Utils::Shader::TESS_CTRL);
6286 Utils::Shader::LogSource(m_context, tes_source, Utils::Shader::TESS_EVAL);
6287 Utils::Shader::LogSource(m_context, gs_source, Utils::Shader::GEOMETRY);
6288 Utils::Shader::LogSource(m_context, fs_source, Utils::Shader::FRAGMENT);
6289 }
6290 test_case_result = false;
6291 }
6292 }
6293
6294 return test_case_result;
6295 }
6296
6297 /* Constants used by TextureTestBase */
6298 const glw::GLuint TextureTestBase::m_width = 16;
6299 const glw::GLuint TextureTestBase::m_height = 16;
6300
6301 /** Constructor
6302 *
6303 * @param context Test context
6304 * @param test_name Name of test
6305 * @param test_description Description of test
6306 **/
6307 TextureTestBase::TextureTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6308 : TestBase(context, test_name, test_description)
6309 {
6310 }
6311
6312 /** Get locations for all inputs with automatic_location
6313 *
6314 * @param program Program object
6315 * @param program_interface Interface of program
6316 **/
6317 void TextureTestBase::prepareAttribLocation(Utils::Program& program, Utils::ProgramInterface& program_interface)
6318 {
6319 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6320
6321 Utils::Variable::PtrVector& inputs = si.m_inputs;
6322
6323 for (Utils::Variable::PtrVector::iterator it = inputs.begin(); inputs.end() != it; ++it)
6324 {
6325 /* Test does not specify location, query value and set */
6326 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6327 {
6328 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_INPUT);
6329 GLint location = 0;
6330
6331 program.GetResource(GL_PROGRAM_INPUT, index, GL_LOCATION, 1 /* size */, &location);
6332
6333 (*it)->m_descriptor.m_expected_location = location;
6334 }
6335 }
6336 }
6337
6338 /** Verifies contents of drawn image
6339 *
6340 * @param ignored
6341 * @param color_0 Verified image
6342 *
6343 * @return true if image is filled with 1, false otherwise
6344 **/
6345 bool TextureTestBase::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& color_0)
6346 {
6347 static const GLuint size = m_width * m_height;
6348 static const GLuint expected_color = 1;
6349
6350 std::vector<GLuint> data;
6351 data.resize(size);
6352
6353 color_0.Get(GL_RED_INTEGER, GL_UNSIGNED_INT, &data[0]);
6354
6355 for (GLuint i = 0; i < size; ++i)
6356 {
6357 const GLuint color = data[i];
6358
6359 if (expected_color != color)
6360 {
6361 m_context.getTestContext().getLog() << tcu::TestLog::Message << "R32UI[" << i << "]:" << color
6362 << tcu::TestLog::EndMessage;
6363 return false;
6364 }
6365 }
6366
6367 return true;
6368 }
6369
6370 /** Execute dispatch compute for 16x16x1
6371 *
6372 * @param ignored
6373 **/
6374 void TextureTestBase::executeDispatchCall(GLuint /* test_case_index */)
6375 {
6376 const Functions& gl = m_context.getRenderContext().getFunctions();
6377
6378 gl.dispatchCompute(16 /* x */, 16 /* y */, 1 /* z */);
6379 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
6380 }
6381
6382 /** Execute drawArrays for single vertex
6383 *
6384 * @param ignored
6385 **/
6386 void TextureTestBase::executeDrawCall(GLuint /* test_case_index */)
6387 {
6388 const Functions& gl = m_context.getRenderContext().getFunctions();
6389
6390 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
6391 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6392 }
6393
6394 /** Prepare code snippet that will pass in variables to out variables
6395 *
6396 * @param ignored
6397 * @param varying_passthrough Collection of connections between in and out variables
6398 * @param stage Shader stage
6399 *
6400 * @return Code that pass in variables to next stage
6401 **/
6402 std::string TextureTestBase::getPassSnippet(GLuint /* test_case_index */,
6403 Utils::VaryingPassthrough& varying_passthrough, Utils::Shader::STAGES stage)
6404 {
6405 static const GLchar* separator = "\n ";
6406
6407 /* Skip for compute shader */
6408 if (Utils::Shader::COMPUTE == stage)
6409 {
6410 return "";
6411 }
6412
6413 Utils::VaryingConnection::Vector& vector = varying_passthrough.Get(stage);
6414
6415 std::string result = Utils::g_list;
6416 size_t position = 0;
6417
6418 for (GLuint i = 0; i < vector.size(); ++i)
6419 {
6420
6421 Utils::VaryingConnection& connection = vector[i];
6422
6423 Utils::Variable* in = connection.m_in;
6424 Utils::Variable* out = connection.m_out;
6425
6426 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6427 Utils::Variable::FLAVOUR out_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::OUTPUT);
6428
6429 const std::string passthrough =
6430 getVariablePassthrough("", in->m_descriptor, in_flavour, "", out->m_descriptor, out_flavour);
6431
6432 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6433 }
6434
6435 Utils::endList("", position, result);
6436
6437 return result;
6438 }
6439
6440 /** Basic implementation of method getProgramInterface
6441 *
6442 * @param ignored
6443 * @param ignored
6444 * @param ignored
6445 **/
6446 void TextureTestBase::getProgramInterface(GLuint /* test_case_index */,
6447 Utils::ProgramInterface& /* program_interface */,
6448 Utils::VaryingPassthrough& /* varying_passthrough */)
6449 {
6450 }
6451
6452 /** Prepare code snippet that will verify in and uniform variables
6453 *
6454 * @param ignored
6455 * @param program_interface Interface of program
6456 * @param stage Shader stage
6457 *
6458 * @return Code that verify variables
6459 **/
6460 std::string TextureTestBase::getVerificationSnippet(GLuint /* test_case_index */,
6461 Utils::ProgramInterface& program_interface,
6462 Utils::Shader::STAGES stage)
6463 {
6464 static const GLchar* separator = " ||\n ";
6465
6466 std::string verification = "if (LIST)\n"
6467 " {\n"
6468 " result = 0u;\n"
6469 " }\n";
6470
6471 /* Get flavour of in and out variables */
6472 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6473
6474 /* Get interface for shader stage */
6475 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
6476
6477 /* There are no varialbes to verify */
6478 if ((0 == si.m_inputs.size()) && (0 == si.m_uniforms.size()) && (0 == si.m_ssb_blocks.size()))
6479 {
6480 return "";
6481 }
6482
6483 /* For each in variable insert verification code */
6484 size_t position = 0;
6485
6486 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6487 {
6488 const Utils::Variable& var = *si.m_inputs[i];
6489 const std::string& var_verification = getVariableVerification("", var.m_data, var.m_descriptor, in_flavour);
6490
6491 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6492 }
6493
6494 /* For each unifrom variable insert verification code */
6495 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
6496 {
6497 const Utils::Variable& var = *si.m_uniforms[i];
6498 const std::string& var_verification =
6499 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6500
6501 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6502 }
6503
6504 /* For each ssb variable insert verification code */
6505 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
6506 {
6507 const Utils::Variable& var = *si.m_ssb_blocks[i];
6508 const std::string& var_verification =
6509 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6510
6511 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6512 }
6513
6514 Utils::endList("", position, verification);
6515
6516 #if DEBUG_TTB_VERIFICATION_SNIPPET_STAGE
6517
6518 {
6519 GLchar buffer[16];
6520 sprintf(buffer, "%d", stage + 10);
6521 Utils::replaceToken("0u", position, buffer, verification);
6522 }
6523
6524 #elif DEBUG_TTB_VERIFICATION_SNIPPET_VARIABLE
6525
6526 if (Utils::Shader::VERTEX == stage)
6527 {
6528 Utils::replaceToken("0u", position, "in_vs_first.x", verification);
6529 }
6530 else
6531 {
6532 Utils::replaceToken("0u", position, "31u", verification);
6533 }
6534
6535 #endif
6536
6537 /* Done */
6538 return verification;
6539 }
6540
6541 /** Selects if "compute" stage is relevant for test
6542 *
6543 * @param ignored
6544 *
6545 * @return true
6546 **/
6547 bool TextureTestBase::isComputeRelevant(GLuint /* test_case_index */)
6548 {
6549 return true;
6550 }
6551
6552 /** Selects if "draw" stages are relevant for test
6553 *
6554 * @param ignored
6555 *
6556 * @return true
6557 **/
6558 bool TextureTestBase::isDrawRelevant(GLuint /* test_case_index */)
6559 {
6560 return true;
6561 }
6562
6563 /** Prepare code that will do assignment of single in to single out
6564 *
6565 * @param in_parent_name Name of parent in variable
6566 * @param in_variable Descriptor of in variable
6567 * @param in_flavour Flavoud of in variable
6568 * @param out_parent_name Name of parent out variable
6569 * @param out_variable Descriptor of out variable
6570 * @param out_flavour Flavoud of out variable
6571 *
6572 * @return Code that does OUT = IN
6573 **/
6574 std::string TextureTestBase::getVariablePassthrough(const std::string& in_parent_name,
6575 const Utils::Variable::Descriptor& in_variable,
6576 Utils::Variable::FLAVOUR in_flavour,
6577 const std::string& out_parent_name,
6578 const Utils::Variable::Descriptor& out_variable,
6579 Utils::Variable::FLAVOUR out_flavour)
6580 {
6581 bool done = false;
6582 GLuint index = 0;
6583 GLuint member_index = 0;
6584 size_t position = 0;
6585 std::string result = Utils::g_list;
6586 static const GLchar* separator = ";\n ";
6587
6588 /* For each member of each array element */
6589 do
6590 {
6591 const std::string in_name = Utils::Variable::GetReference(in_parent_name, in_variable, in_flavour, index);
6592 const std::string out_name = Utils::Variable::GetReference(out_parent_name, out_variable, out_flavour, index);
6593 std::string passthrough;
6594
6595 /* Prepare verification */
6596 if (Utils::Variable::BUILTIN == in_variable.m_type)
6597 {
6598 size_t pass_position = 0;
6599
6600 passthrough = "OUT = IN;";
6601
6602 Utils::replaceToken("OUT", pass_position, out_name.c_str(), passthrough);
6603 Utils::replaceToken("IN", pass_position, in_name.c_str(), passthrough);
6604
6605 /* Increment index */
6606 ++index;
6607 }
6608 else
6609 {
6610 const Utils::Interface* in_interface = in_variable.m_interface;
6611 const Utils::Interface* out_interface = out_variable.m_interface;
6612
6613 if ((0 == in_interface) || (0 == out_interface))
6614 {
6615 TCU_FAIL("Nullptr");
6616 }
6617
6618 const Utils::Variable::Descriptor& in_member = in_interface->m_members[member_index];
6619 const Utils::Variable::Descriptor& out_member = out_interface->m_members[member_index];
6620
6621 passthrough = getVariablePassthrough(in_name, in_member, Utils::Variable::BASIC, out_name, out_member,
6622 Utils::Variable::BASIC);
6623
6624 /* Increment member_index */
6625 ++member_index;
6626
6627 /* Increment index and reset member_index if all members were processed */
6628 if (in_interface->m_members.size() == member_index)
6629 {
6630 ++index;
6631 member_index = 0;
6632 }
6633 }
6634
6635 /* Check if loop should end */
6636 if ((index >= in_variable.m_n_array_elements) && (0 == member_index))
6637 {
6638 done = true;
6639 }
6640
6641 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6642
6643 } while (true != done);
6644
6645 Utils::endList("", position, result);
6646
6647 /* Done */
6648 return result;
6649 }
6650
6651 /** Get verification of single variable
6652 *
6653 * @param parent_name Name of parent variable
6654 * @param data Data that should be used as EXPECTED
6655 * @param variable Descriptor of variable
6656 * @param flavour Flavour of variable
6657 *
6658 * @return Code that does (EXPECTED != VALUE) ||
6659 **/
6660 std::string TextureTestBase::getVariableVerification(const std::string& parent_name, const GLvoid* data,
6661 const Utils::Variable::Descriptor& variable,
6662 Utils::Variable::FLAVOUR flavour)
6663 {
6664 static const GLchar* logic_op = " ||\n ";
6665 const GLuint n_elements = (0 == variable.m_n_array_elements) ? 1 : variable.m_n_array_elements;
6666 size_t position = 0;
6667 std::string result = Utils::g_list;
6668 GLint stride = variable.m_expected_stride_of_element;
6669
6670 /* For each each array element */
6671 for (GLuint element = 0; element < n_elements; ++element)
6672 {
6673 const std::string name = Utils::Variable::GetReference(parent_name, variable, flavour, element);
6674
6675 /* Calculate data pointer */
6676 GLvoid* data_ptr = (GLvoid*)((GLubyte*)data + element * stride);
6677
6678 /* Prepare verification */
6679 if (Utils::Variable::BUILTIN == variable.m_type)
6680 {
6681 const std::string& expected = variable.m_builtin.GetGLSLConstructor(data_ptr);
6682 std::string verification;
6683 size_t verification_position = 0;
6684
6685 verification = "(EXPECTED != NAME)";
6686
6687 Utils::replaceToken("EXPECTED", verification_position, expected.c_str(), verification);
6688 Utils::replaceToken("NAME", verification_position, name.c_str(), verification);
6689
6690 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6691 }
6692 else
6693 {
6694 const Utils::Interface* interface = variable.m_interface;
6695
6696 if (0 == interface)
6697 {
6698 TCU_FAIL("Nullptr");
6699 }
6700
6701 const GLuint n_members = static_cast<GLuint>(interface->m_members.size());
6702
6703 /* for each member */
6704 for (GLuint member_index = 0; member_index < n_members; ++member_index)
6705 {
6706 const Utils::Variable::Descriptor& member = interface->m_members[member_index];
6707
6708 /* Get verification of member */
6709 const std::string& verification =
6710 getVariableVerification(name, (GLubyte*)data_ptr + member.m_offset, member, Utils::Variable::BASIC);
6711
6712 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6713 }
6714 }
6715 }
6716
6717 Utils::endList("", position, result);
6718
6719 return result;
6720 }
6721
6722 /** Prepare attributes, vertex array object and array buffer
6723 *
6724 * @param test_case_index Index of test case
6725 * @param program_interface Interface of program
6726 * @param buffer Array buffer
6727 * @param vao Vertex array object
6728 **/
6729 void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramInterface& program_interface,
6730 Utils::Buffer& buffer, Utils::VertexArray& vao)
6731 {
6732 bool use_component_qualifier = useComponentQualifier(test_case_index);
6733
6734 /* Get shader interface */
6735 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6736
6737 /* Bind vao and buffer */
6738 vao.Bind();
6739 buffer.Bind();
6740
6741 /* Skip if there are no input variables in vertex shader */
6742 if (0 == si.m_inputs.size())
6743 {
6744 return;
6745 }
6746
6747 const Functions& gl = m_context.getRenderContext().getFunctions();
6748
6749 /* Calculate vertex stride and check */
6750 GLint max_inputs;
6751 gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_inputs);
6752 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
6753
6754 /* dvec3/4 vertex inputs use a single location but require 2x16B slots */
6755 GLint max_slots = max_inputs * 2;
6756
6757 /* Compute used slots */
6758 std::vector<GLint> slot_sizes;
6759 slot_sizes.resize(max_slots);
6760 std::fill(slot_sizes.begin(), slot_sizes.end(), 0);
6761 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6762 {
6763 Utils::Variable& variable = *si.m_inputs[i];
6764
6765 GLint variable_size = static_cast<GLuint>(variable.m_data_size);
6766
6767 GLint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6768 GLint ends_at = variable.m_descriptor.m_offset % 16 + variable_size;
6769
6770 GLint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6771 for (GLint loc = 0; loc < array_length; loc++) {
6772 GLint slot = base_slot + loc;
6773 slot_sizes[slot] = std::max(slot_sizes[slot], ends_at);
6774 }
6775 }
6776
6777 /* Compute the offsets where we need to put vertex buffer data for each slot */
6778 std::vector<GLint> slot_offsets;
6779 slot_offsets.resize(max_slots);
6780 std::fill(slot_offsets.begin(), slot_offsets.end(), -1);
6781 GLint buffer_size = 0;
6782 for (GLint i = 0; i < max_slots; i++)
6783 {
6784 if (slot_sizes[i] == 0)
6785 continue;
6786 slot_offsets[i] = buffer_size;
6787 buffer_size += slot_sizes[i];
6788 }
6789
6790 /* Prepare buffer data and set up vao */
6791 std::vector<GLubyte> buffer_data;
6792 buffer_data.resize(buffer_size);
6793
6794 GLubyte* ptr = &buffer_data[0];
6795
6796 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6797 {
6798 Utils::Variable& variable = *si.m_inputs[i];
6799
6800 GLint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6801 GLint variable_offset = variable.m_descriptor.m_offset % 16;
6802 GLint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6803 for (GLint loc = 0; loc < array_length; loc++) {
6804 GLint slot = base_slot + loc;
6805 memcpy(ptr + slot_offsets[slot] + variable_offset, variable.m_data, variable.m_data_size);
6806 }
6807
6808 if (false == use_component_qualifier)
6809 {
6810 vao.Attribute(variable.m_descriptor.m_expected_location, variable.m_descriptor.m_builtin,
6811 variable.m_descriptor.m_n_array_elements, variable.m_descriptor.m_normalized,
6812 variable.GetStride(), (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6813 }
6814 else if (0 == variable.m_descriptor.m_expected_component)
6815 {
6816 /* Components can only be applied to vectors.
6817 Assumption that test use all 4 components */
6818 const Utils::Type& type =
6819 Utils::Type::GetType(variable.m_descriptor.m_builtin.m_basic_type, 1 /* n_columns */, 4 /* n_rows */);
6820
6821 vao.Attribute(variable.m_descriptor.m_expected_location, type, variable.m_descriptor.m_n_array_elements,
6822 variable.m_descriptor.m_normalized, variable.GetStride(),
6823 (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6824 }
6825 }
6826
6827 /* Update buffer */
6828 buffer.Data(Utils::Buffer::StaticDraw, buffer_size, ptr);
6829 }
6830
6831 /** Get locations for all outputs with automatic_location
6832 *
6833 * @param program Program object
6834 * @param program_interface Interface of program
6835 **/
6836 void TextureTestBase::prepareFragmentDataLoc(Utils::Program& program, Utils::ProgramInterface& program_interface)
6837 {
6838 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
6839 Utils::Variable::PtrVector& outputs = si.m_outputs;
6840
6841 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
6842 {
6843 /* Test does not specify location, query value and set */
6844 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6845 {
6846 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_OUTPUT);
6847 GLint location = 0;
6848
6849 program.GetResource(GL_PROGRAM_OUTPUT, index, GL_LOCATION, 1 /* size */, &location);
6850
6851 (*it)->m_descriptor.m_expected_location = location;
6852 }
6853 }
6854 }
6855
6856 /** Prepare framebuffer with single texture as color attachment
6857 *
6858 * @param framebuffer Framebuffer
6859 * @param color_0_texture Texture that will used as color attachment
6860 **/
6861 void TextureTestBase::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
6862 {
6863 /* Prepare data */
6864 std::vector<GLuint> texture_data;
6865 texture_data.resize(m_width * m_height);
6866
6867 for (GLuint i = 0; i < texture_data.size(); ++i)
6868 {
6869 texture_data[i] = 0x20406080;
6870 }
6871
6872 /* Prepare texture */
6873 color_0_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6874 &texture_data[0]);
6875
6876 /* Prepare framebuffer */
6877 framebuffer.Init();
6878 framebuffer.Bind();
6879 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0, color_0_texture.m_id, m_width, m_height);
6880
6881 framebuffer.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6882 framebuffer.Clear(GL_COLOR_BUFFER_BIT);
6883 }
6884
6885 /** Prepare iamge unit for compute shader
6886 *
6887 * @param location Uniform location
6888 * @param image_texture Texture that will used as color attachment
6889 **/
6890 void TextureTestBase::prepareImage(GLint location, Utils::Texture& image_texture) const
6891 {
6892 static const GLuint image_unit = 0;
6893
6894 std::vector<GLuint> texture_data;
6895 texture_data.resize(m_width * m_height);
6896
6897 for (GLuint i = 0; i < texture_data.size(); ++i)
6898 {
6899 texture_data[i] = 0x20406080;
6900 }
6901
6902 image_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6903 &texture_data[0]);
6904
6905 const Functions& gl = m_context.getRenderContext().getFunctions();
6906
6907 gl.bindImageTexture(image_unit, image_texture.m_id, 0 /* level */, GL_FALSE /* layered */, 0 /* Layer */,
6908 GL_WRITE_ONLY, GL_R32UI);
6909 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6910
6911 Utils::Program::Uniform(gl, Utils::Type::_int, 1 /* count */, location, &image_unit);
6912 }
6913
6914 /** Basic implementation
6915 *
6916 * @param ignored
6917 * @param si Shader interface
6918 * @param program Program
6919 * @param cs_buffer Buffer for ssb blocks
6920 **/
6921 void TextureTestBase::prepareSSBs(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
6922 Utils::Buffer& buffer)
6923 {
6924 /* Skip if there are no input variables in vertex shader */
6925 if (0 == si.m_ssb_blocks.size())
6926 {
6927 return;
6928 }
6929
6930 /* Calculate vertex stride */
6931 GLint ssbs_stride = 0;
6932
6933 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
6934 {
6935 Utils::Variable& variable = *si.m_ssb_blocks[i];
6936
6937 if (false == variable.IsBlock())
6938 {
6939 continue;
6940 }
6941
6942 GLint variable_stride = variable.GetStride();
6943
6944 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
6945
6946 ssbs_stride = std::max(ssbs_stride, ends_at);
6947 }
6948
6949 /* Set active program */
6950 program.Use();
6951
6952 /* Allocate */
6953 buffer.Bind();
6954 buffer.Data(Utils::Buffer::StaticDraw, ssbs_stride, 0);
6955
6956 /* Set up uniforms */
6957 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
6958 {
6959 Utils::Variable& variable = *si.m_ssb_blocks[i];
6960
6961 /* prepareUnifor should work fine for ssb blocks */
6962 prepareUniform(program, variable, buffer);
6963 }
6964 }
6965
6966 /** Basic implementation
6967 *
6968 * @param test_case_index Test case index
6969 * @param program_interface Program interface
6970 * @param program Program
6971 * @param cs_buffer Buffer for compute shader stage
6972 **/
6973 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
6974 Utils::Program& program, Utils::Buffer& cs_buffer)
6975 {
6976 cs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
6977
6978 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
6979
6980 prepareSSBs(test_case_index, cs, program, cs_buffer);
6981
6982 cs_buffer.BindBase(Utils::Shader::COMPUTE);
6983 }
6984
6985 /** Basic implementation
6986 *
6987 * @param test_case_index Test case index
6988 * @param program_interface Program interface
6989 * @param program Program
6990 * @param fs_buffer Buffer for fragment shader stage
6991 * @param gs_buffer Buffer for geometry shader stage
6992 * @param tcs_buffer Buffer for tessellation control shader stage
6993 * @param tes_buffer Buffer for tessellation evaluation shader stage
6994 * @param vs_buffer Buffer for vertex shader stage
6995 **/
6996 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
6997 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
6998 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
6999 {
7000 fs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7001 gs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7002 tcs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7003 tes_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7004 vs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7005
7006 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7007 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7008 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7009 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7010 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7011
7012 prepareSSBs(test_case_index, fs, program, fs_buffer);
7013 prepareSSBs(test_case_index, gs, program, gs_buffer);
7014 prepareSSBs(test_case_index, tcs, program, tcs_buffer);
7015 prepareSSBs(test_case_index, tes, program, tes_buffer);
7016 prepareSSBs(test_case_index, vs, program, vs_buffer);
7017
7018 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7019 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7020 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7021 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7022 vs_buffer.BindBase(Utils::Shader::VERTEX);
7023 }
7024
7025 /** Updates buffer data with variable
7026 *
7027 * @param program Program object
7028 * @param variable Variable
7029 * @param buffer Buffer
7030 **/
7031 void TextureTestBase::prepareUniform(Utils::Program& program, Utils::Variable& variable, Utils::Buffer& buffer)
7032 {
7033 const Functions& gl = m_context.getRenderContext().getFunctions();
7034
7035 GLsizei count = variable.m_descriptor.m_n_array_elements;
7036 if (0 == count)
7037 {
7038 count = 1;
7039 }
7040
7041 if (Utils::Variable::BUILTIN == variable.m_descriptor.m_type)
7042 {
7043 program.Uniform(gl, variable.m_descriptor.m_builtin, count, variable.m_descriptor.m_expected_location,
7044 variable.m_data);
7045 }
7046 else
7047 {
7048 const bool is_block = variable.IsBlock();
7049
7050 if (false == is_block)
7051 {
7052 TCU_FAIL("Not implemented");
7053 }
7054 else
7055 {
7056 buffer.SubData(variable.m_descriptor.m_offset, variable.m_descriptor.m_expected_stride_of_element * count,
7057 variable.m_data);
7058 }
7059 }
7060 }
7061
7062 /** Basic implementation
7063 *
7064 * @param ignored
7065 * @param si Shader interface
7066 * @param program Program
7067 * @param cs_buffer Buffer for uniform blocks
7068 **/
7069 void TextureTestBase::prepareUniforms(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
7070 Utils::Buffer& buffer)
7071 {
7072 /* Skip if there are no input variables in vertex shader */
7073 if (0 == si.m_uniforms.size())
7074 {
7075 return;
7076 }
7077
7078 /* Calculate vertex stride */
7079 GLint uniforms_stride = 0;
7080
7081 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7082 {
7083 Utils::Variable& variable = *si.m_uniforms[i];
7084
7085 if (false == variable.IsBlock())
7086 {
7087 continue;
7088 }
7089
7090 GLint variable_stride = variable.GetStride();
7091
7092 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
7093
7094 uniforms_stride = std::max(uniforms_stride, ends_at);
7095 }
7096
7097 /* Set active program */
7098 program.Use();
7099
7100 /* Allocate */
7101 buffer.Bind();
7102 buffer.Data(Utils::Buffer::StaticDraw, uniforms_stride, 0);
7103
7104 /* Set up uniforms */
7105 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7106 {
7107 Utils::Variable& variable = *si.m_uniforms[i];
7108
7109 prepareUniform(program, variable, buffer);
7110 }
7111 }
7112
7113 /** Basic implementation
7114 *
7115 * @param test_case_index Test case index
7116 * @param program_interface Program interface
7117 * @param program Program
7118 * @param cs_buffer Buffer for compute shader stage
7119 **/
7120 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7121 Utils::Program& program, Utils::Buffer& cs_buffer)
7122 {
7123 cs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7124
7125 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
7126
7127 prepareUniforms(test_case_index, cs, program, cs_buffer);
7128
7129 cs_buffer.BindBase(Utils::Shader::COMPUTE);
7130 }
7131
7132 /** Basic implementation
7133 *
7134 * @param test_case_index Test case index
7135 * @param program_interface Program interface
7136 * @param program Program
7137 * @param fs_buffer Buffer for fragment shader stage
7138 * @param gs_buffer Buffer for geometry shader stage
7139 * @param tcs_buffer Buffer for tessellation control shader stage
7140 * @param tes_buffer Buffer for tessellation evaluation shader stage
7141 * @param vs_buffer Buffer for vertex shader stage
7142 **/
7143 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7144 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7145 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7146 {
7147 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7148 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7149 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7150 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7151 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7152
7153 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7154 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7155 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7156 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7157 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7158
7159 prepareUniforms(test_case_index, fs, program, fs_buffer);
7160 prepareUniforms(test_case_index, gs, program, gs_buffer);
7161 prepareUniforms(test_case_index, tcs, program, tcs_buffer);
7162 prepareUniforms(test_case_index, tes, program, tes_buffer);
7163 prepareUniforms(test_case_index, vs, program, vs_buffer);
7164
7165 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7166 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7167 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7168 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7169 vs_buffer.BindBase(Utils::Shader::VERTEX);
7170 }
7171
7172 /** Basic implementation
7173 *
7174 * @param test_case_index Test case index
7175 * @param program_interface Program interface
7176 * @param program Program
7177 * @param fs_buffer Buffer for fragment shader stage
7178 * @param gs_buffer Buffer for geometry shader stage
7179 * @param tcs_buffer Buffer for tessellation control shader stage
7180 * @param tes_buffer Buffer for tessellation evaluation shader stage
7181 * @param vs_buffer Buffer for vertex shader stage
7182 **/
7183 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7184 Utils::Program& fs_program, Utils::Program& gs_program,
7185 Utils::Program& tcs_program, Utils::Program& tes_program,
7186 Utils::Program& vs_program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7187 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7188 {
7189 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7190 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7191 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7192 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7193 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7194
7195 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7196 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7197 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7198 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7199 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7200
7201 prepareUniforms(test_case_index, fs, fs_program, fs_buffer);
7202 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7203
7204 prepareUniforms(test_case_index, gs, gs_program, gs_buffer);
7205 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7206
7207 prepareUniforms(test_case_index, tcs, tcs_program, tcs_buffer);
7208 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7209
7210 prepareUniforms(test_case_index, tes, tes_program, tes_buffer);
7211 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7212
7213 prepareUniforms(test_case_index, vs, vs_program, vs_buffer);
7214 vs_buffer.BindBase(Utils::Shader::VERTEX);
7215 }
7216
7217 /** Prepare source for shader
7218 *
7219 * @param test_case_index Index of test case
7220 * @param program_interface Interface of program
7221 * @param varying_passthrough Collection of connection between in and out variables
7222 * @param stage Shader stage
7223 *
7224 * @return Source of shader
7225 **/
7226 std::string TextureTestBase::getShaderSource(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7227 Utils::VaryingPassthrough& varying_passthrough,
7228 Utils::Shader::STAGES stage)
7229 {
7230 /* Get strings */
7231 const GLchar* shader_template = getShaderTemplate(stage);
7232 const std::string& shader_interface = program_interface.GetInterfaceForStage(stage);
7233
7234 const std::string& verification = getVerificationSnippet(test_case_index, program_interface, stage);
7235
7236 const std::string& passthrough = getPassSnippet(test_case_index, varying_passthrough, stage);
7237
7238 const GLchar* per_vertex = "";
7239
7240 std::string source = shader_template;
7241 size_t position = 0;
7242
7243 /* Replace tokens in template */
7244 if (Utils::Shader::GEOMETRY == stage)
7245 {
7246 if (false == useMonolithicProgram(test_case_index))
7247 {
7248 per_vertex = "out gl_PerVertex {\n"
7249 "vec4 gl_Position;\n"
7250 "};\n"
7251 "\n";
7252 }
7253
7254 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
7255 }
7256
7257 Utils::replaceToken("INTERFACE", position, shader_interface.c_str(), source);
7258 Utils::replaceToken("VERIFICATION", position, verification.c_str(), source);
7259
7260 if (false == verification.empty())
7261 {
7262 Utils::replaceAllTokens("ELSE", " else ", source);
7263 }
7264 else
7265 {
7266 Utils::replaceAllTokens("ELSE", "", source);
7267 }
7268
7269 Utils::replaceAllTokens("PASSTHROUGH", passthrough.c_str(), source);
7270
7271 /* Done */
7272 return source;
7273 }
7274
7275 /** Returns template of shader for given stage
7276 *
7277 * @param stage Shade stage
7278 *
7279 * @return Proper template
7280 **/
7281 const GLchar* TextureTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
7282 {
7283
7284 static const GLchar* compute_shader_template =
7285 "#version 430 core\n"
7286 "#extension GL_ARB_enhanced_layouts : require\n"
7287 "\n"
7288 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
7289 "\n"
7290 "writeonly uniform uimage2D uni_image;\n"
7291 "\n"
7292 "INTERFACE"
7293 "\n"
7294 "void main()\n"
7295 "{\n"
7296 " uint result = 1u;\n"
7297 "\n"
7298 " VERIFICATION"
7299 "\n"
7300 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
7301 "}\n"
7302 "\n";
7303
7304 static const GLchar* fragment_shader_template = "#version 430 core\n"
7305 "#extension GL_ARB_enhanced_layouts : require\n"
7306 "\n"
7307 "flat in uint gs_fs_result;\n"
7308 " out uint fs_out_result;\n"
7309 "\n"
7310 "INTERFACE"
7311 "\n"
7312 "void main()\n"
7313 "{\n"
7314 " uint result = 1u;\n"
7315 "\n"
7316 " if (1u != gs_fs_result)\n"
7317 " {\n"
7318 " result = gs_fs_result;\n"
7319 " }\n"
7320 "ELSEVERIFICATION"
7321 "\n"
7322 " fs_out_result = result;\n"
7323 " PASSTHROUGH\n"
7324 "}\n"
7325 "\n";
7326
7327 static const GLchar* geometry_shader_template =
7328 "#version 430 core\n"
7329 "#extension GL_ARB_enhanced_layouts : require\n"
7330 "\n"
7331 "layout(points) in;\n"
7332 "layout(triangle_strip, max_vertices = 4) out;\n"
7333 "\n"
7334 " in uint tes_gs_result[];\n"
7335 "flat out uint gs_fs_result;\n"
7336 "\n"
7337 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
7338 "INTERFACE"
7339 "\n"
7340 "void main()\n"
7341 "{\n"
7342 " uint result = 1u;\n"
7343 "\n"
7344 " if (1u != tes_gs_result[0])\n"
7345 " {\n"
7346 " result = tes_gs_result[0];\n"
7347 " }\n"
7348 "ELSEVERIFICATION"
7349 "\n"
7350 " gs_fs_result = result;\n"
7351 " PASSTHROUGH\n"
7352 " gl_Position = vec4(-1, -1, 0, 1);\n"
7353 " EmitVertex();\n"
7354 " gs_fs_result = result;\n"
7355 " PASSTHROUGH\n"
7356 " gl_Position = vec4(-1, 1, 0, 1);\n"
7357 " EmitVertex();\n"
7358 " gs_fs_result = result;\n"
7359 " PASSTHROUGH\n"
7360 " gl_Position = vec4(1, -1, 0, 1);\n"
7361 " EmitVertex();\n"
7362 " gs_fs_result = result;\n"
7363 " PASSTHROUGH\n"
7364 " gl_Position = vec4(1, 1, 0, 1);\n"
7365 " EmitVertex();\n"
7366 "}\n"
7367 "\n";
7368
7369 static const GLchar* tess_ctrl_shader_template = "#version 430 core\n"
7370 "#extension GL_ARB_enhanced_layouts : require\n"
7371 "\n"
7372 "layout(vertices = 1) out;\n"
7373 "\n"
7374 "in uint vs_tcs_result[];\n"
7375 "out uint tcs_tes_result[];\n"
7376 "\n"
7377 "INTERFACE"
7378 "\n"
7379 "void main()\n"
7380 "{\n"
7381 " uint result = 1u;\n"
7382 "\n"
7383 " if (1u != vs_tcs_result[gl_InvocationID])\n"
7384 " {\n"
7385 " result = vs_tcs_result[gl_InvocationID];\n"
7386 " }\n"
7387 "ELSEVERIFICATION"
7388 "\n"
7389 " tcs_tes_result[gl_InvocationID] = result;\n"
7390 "\n"
7391 " PASSTHROUGH\n"
7392 "\n"
7393 " gl_TessLevelOuter[0] = 1.0;\n"
7394 " gl_TessLevelOuter[1] = 1.0;\n"
7395 " gl_TessLevelOuter[2] = 1.0;\n"
7396 " gl_TessLevelOuter[3] = 1.0;\n"
7397 " gl_TessLevelInner[0] = 1.0;\n"
7398 " gl_TessLevelInner[1] = 1.0;\n"
7399 "}\n"
7400 "\n";
7401
7402 static const GLchar* tess_eval_shader_template = "#version 430 core\n"
7403 "#extension GL_ARB_enhanced_layouts : require\n"
7404 "\n"
7405 "layout(isolines, point_mode) in;\n"
7406 "\n"
7407 "in uint tcs_tes_result[];\n"
7408 "out uint tes_gs_result;\n"
7409 "\n"
7410 "INTERFACE"
7411 "\n"
7412 "void main()\n"
7413 "{\n"
7414 " uint result = 1u;\n"
7415 "\n"
7416 " if (1 != tcs_tes_result[0])\n"
7417 " {\n"
7418 " result = tcs_tes_result[0];\n"
7419 " }\n"
7420 "ELSEVERIFICATION"
7421 "\n"
7422 " tes_gs_result = result;\n"
7423 "\n"
7424 " PASSTHROUGH\n"
7425 "}\n"
7426 "\n";
7427
7428 static const GLchar* vertex_shader_template = "#version 430 core\n"
7429 "#extension GL_ARB_enhanced_layouts : require\n"
7430 "\n"
7431 "out uint vs_tcs_result;\n"
7432 "\n"
7433 "INTERFACE"
7434 "\n"
7435 "void main()\n"
7436 "{\n"
7437 " uint result = 1u;\n"
7438 "\n"
7439 " VERIFICATION\n"
7440 "\n"
7441 " vs_tcs_result = result;\n"
7442 "\n"
7443 " PASSTHROUGH\n"
7444 "}\n"
7445 "\n";
7446
7447 const GLchar* result = 0;
7448
7449 switch (stage)
7450 {
7451 case Utils::Shader::COMPUTE:
7452 result = compute_shader_template;
7453 break;
7454 case Utils::Shader::FRAGMENT:
7455 result = fragment_shader_template;
7456 break;
7457 case Utils::Shader::GEOMETRY:
7458 result = geometry_shader_template;
7459 break;
7460 case Utils::Shader::TESS_CTRL:
7461 result = tess_ctrl_shader_template;
7462 break;
7463 case Utils::Shader::TESS_EVAL:
7464 result = tess_eval_shader_template;
7465 break;
7466 case Utils::Shader::VERTEX:
7467 result = vertex_shader_template;
7468 break;
7469 default:
7470 TCU_FAIL("Invalid enum");
7471 }
7472
7473 return result;
7474 }
7475
7476 /** Runs test case
7477 *
7478 * @param test_case_index Id of test case
7479 *
7480 * @return true if test case pass, false otherwise
7481 **/
7482 bool TextureTestBase::testCase(GLuint test_case_index)
7483 {
7484 try
7485 {
7486 if (true == useMonolithicProgram(test_case_index))
7487 {
7488 return testMonolithic(test_case_index);
7489 }
7490 else
7491 {
7492 return testSeparable(test_case_index);
7493 }
7494 }
7495 catch (Utils::Shader::InvalidSourceException& exc)
7496 {
7497 exc.log(m_context);
7498 TCU_FAIL(exc.what());
7499 }
7500 catch (Utils::Program::BuildException& exc)
7501 {
7502 TCU_FAIL(exc.what());
7503 }
7504 }
7505
7506 /** Runs "draw" test with monolithic program
7507 *
7508 * @param test_case_index Id of test case
7509 **/
7510 bool TextureTestBase::testMonolithic(GLuint test_case_index)
7511 {
7512 Utils::ProgramInterface program_interface;
7513 Utils::VaryingPassthrough varying_passthrough;
7514
7515 /* */
7516 const std::string& test_name = getTestCaseName(test_case_index);
7517
7518 /* */
7519 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7520
7521 bool result = true;
7522 /* Draw */
7523 if (true == isDrawRelevant(test_case_index))
7524 {
7525 Utils::Buffer buffer_attr(m_context);
7526 Utils::Buffer buffer_ssb_fs(m_context);
7527 Utils::Buffer buffer_ssb_gs(m_context);
7528 Utils::Buffer buffer_ssb_tcs(m_context);
7529 Utils::Buffer buffer_ssb_tes(m_context);
7530 Utils::Buffer buffer_ssb_vs(m_context);
7531 Utils::Buffer buffer_u_fs(m_context);
7532 Utils::Buffer buffer_u_gs(m_context);
7533 Utils::Buffer buffer_u_tcs(m_context);
7534 Utils::Buffer buffer_u_tes(m_context);
7535 Utils::Buffer buffer_u_vs(m_context);
7536 Utils::Framebuffer framebuffer(m_context);
7537 Utils::Program program(m_context);
7538 Utils::Texture texture_fb(m_context);
7539 Utils::VertexArray vao(m_context);
7540
7541 /* */
7542 const std::string& fragment_shader =
7543 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7544 const std::string& geometry_shader =
7545 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7546 const std::string& tess_ctrl_shader =
7547 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7548 const std::string& tess_eval_shader =
7549 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7550 const std::string& vertex_shader =
7551 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7552
7553 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
7554 vertex_shader, false /* is_separable */);
7555
7556 /* */
7557 prepareAttribLocation(program, program_interface);
7558 prepareFragmentDataLoc(program, program_interface);
7559
7560 /* */
7561 std::stringstream stream;
7562 if (false == Utils::checkMonolithicDrawProgramInterface(program, program_interface, stream))
7563 {
7564 m_context.getTestContext().getLog()
7565 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7566 << ". Inspection of draw program interface failed:\n"
7567 << stream.str() << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7568 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7569 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7570
7571 return false;
7572 }
7573
7574 /* */
7575 program.Use();
7576
7577 /* */
7578 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7579 vao.Init();
7580 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7581
7582 /* */
7583 prepareUniforms(test_case_index, program_interface, program, buffer_u_fs, buffer_u_gs, buffer_u_tcs,
7584 buffer_u_tes, buffer_u_vs);
7585
7586 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_fs, buffer_ssb_gs, buffer_ssb_tcs,
7587 buffer_ssb_tes, buffer_ssb_vs);
7588
7589 /* */
7590 prepareFramebuffer(framebuffer, texture_fb);
7591
7592 /* Draw */
7593 executeDrawCall(test_case_index);
7594
7595 #if USE_NSIGHT
7596 m_context.getRenderContext().postIterate();
7597 #endif
7598
7599 /* Check results */
7600 if (false == checkResults(test_case_index, texture_fb))
7601 {
7602 m_context.getTestContext().getLog()
7603 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7604 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7605 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7606 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7607
7608 result = false;
7609 }
7610 }
7611
7612 /* Compute */
7613 if (true == isComputeRelevant(test_case_index))
7614 {
7615 Utils::Buffer buffer_ssb_cs(m_context);
7616 Utils::Buffer buffer_u_cs(m_context);
7617 Utils::Program program(m_context);
7618 Utils::Texture texture_im(m_context);
7619 Utils::VertexArray vao(m_context);
7620
7621 /* */
7622 const std::string& compute_shader =
7623 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7624
7625 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7626 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7627
7628 /* */
7629 {
7630 std::stringstream stream;
7631
7632 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7633 {
7634 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7635 << ". Inspection of compute program interface failed:\n"
7636 << stream.str() << tcu::TestLog::EndMessage;
7637
7638 return false;
7639 }
7640 }
7641
7642 /* */
7643 program.Use();
7644
7645 /* */
7646 vao.Init();
7647 vao.Bind();
7648
7649 /* */
7650 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7651
7652 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_cs);
7653
7654 /* */
7655 GLint image_location = program.GetUniformLocation("uni_image");
7656 prepareImage(image_location, texture_im);
7657
7658 /* Draw */
7659 executeDispatchCall(test_case_index);
7660
7661 #if USE_NSIGHT
7662 m_context.getRenderContext().postIterate();
7663 #endif
7664
7665 /* Check results */
7666 if (false == checkResults(test_case_index, texture_im))
7667 {
7668 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7669 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7670 << tcu::TestLog::KernelSource(compute_shader);
7671
7672 result = false;
7673 }
7674 }
7675
7676 return result;
7677 }
7678
7679 /** Runs "draw" test with separable program
7680 *
7681 * @param test_case_index Id of test case
7682 **/
7683 bool TextureTestBase::testSeparable(GLuint test_case_index)
7684 {
7685 Utils::ProgramInterface program_interface;
7686 Utils::VaryingPassthrough varying_passthrough;
7687
7688 /* */
7689 const std::string& test_name = getTestCaseName(test_case_index);
7690
7691 /* */
7692 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7693
7694 bool result = true;
7695 /* Draw */
7696 if (true == isDrawRelevant(test_case_index))
7697 {
7698 Utils::Buffer buffer_attr(m_context);
7699 Utils::Buffer buffer_u_fs(m_context);
7700 Utils::Buffer buffer_u_gs(m_context);
7701 Utils::Buffer buffer_u_tcs(m_context);
7702 Utils::Buffer buffer_u_tes(m_context);
7703 Utils::Buffer buffer_u_vs(m_context);
7704 Utils::Framebuffer framebuffer(m_context);
7705 Utils::Pipeline pipeline(m_context);
7706 Utils::Program program_fs(m_context);
7707 Utils::Program program_gs(m_context);
7708 Utils::Program program_tcs(m_context);
7709 Utils::Program program_tes(m_context);
7710 Utils::Program program_vs(m_context);
7711 Utils::Texture texture_fb(m_context);
7712 Utils::VertexArray vao(m_context);
7713
7714 /* */
7715 const std::string& fs =
7716 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7717 const std::string& gs =
7718 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7719 const std::string& tcs =
7720 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7721 const std::string& tes =
7722 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7723 const std::string& vs =
7724 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7725
7726 program_fs.Init("" /*cs*/, fs, "" /*gs*/, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7727 program_gs.Init("" /*cs*/, "" /*fs*/, gs, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7728 program_tcs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, tcs, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7729 program_tes.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, tes, "" /*vs*/, true /* is_separable */);
7730 program_vs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, "" /*tes*/, vs, true /* is_separable */);
7731
7732 /* */
7733 prepareAttribLocation(program_vs, program_interface);
7734 prepareFragmentDataLoc(program_vs, program_interface);
7735
7736 /* */
7737 std::stringstream stream;
7738 if ((false ==
7739 Utils::checkSeparableDrawProgramInterface(program_vs, program_interface, Utils::Shader::VERTEX, stream)) ||
7740 (false == Utils::checkSeparableDrawProgramInterface(program_fs, program_interface, Utils::Shader::FRAGMENT,
7741 stream)) ||
7742 (false == Utils::checkSeparableDrawProgramInterface(program_gs, program_interface, Utils::Shader::GEOMETRY,
7743 stream)) ||
7744 (false == Utils::checkSeparableDrawProgramInterface(program_tcs, program_interface,
7745 Utils::Shader::TESS_CTRL, stream)) ||
7746 (false == Utils::checkSeparableDrawProgramInterface(program_tes, program_interface,
7747 Utils::Shader::TESS_EVAL, stream)))
7748 {
7749 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7750 << ". Inspection of separable draw program interface failed:\n"
7751 << stream.str() << tcu::TestLog::EndMessage
7752 << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7753 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs)
7754 << tcu::TestLog::KernelSource(fs);
7755
7756 return false;
7757 }
7758
7759 /* */
7760 pipeline.Init();
7761 pipeline.UseProgramStages(program_fs.m_id, GL_FRAGMENT_SHADER_BIT);
7762 pipeline.UseProgramStages(program_gs.m_id, GL_GEOMETRY_SHADER_BIT);
7763 pipeline.UseProgramStages(program_tcs.m_id, GL_TESS_CONTROL_SHADER_BIT);
7764 pipeline.UseProgramStages(program_tes.m_id, GL_TESS_EVALUATION_SHADER_BIT);
7765 pipeline.UseProgramStages(program_vs.m_id, GL_VERTEX_SHADER_BIT);
7766 pipeline.Bind();
7767
7768 /* */
7769
7770 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7771 vao.Init();
7772 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7773
7774 /* */
7775 prepareUniforms(test_case_index, program_interface, program_fs, program_gs, program_tcs, program_tes,
7776 program_vs, buffer_u_fs, buffer_u_gs, buffer_u_tcs, buffer_u_tes, buffer_u_vs);
7777
7778 Utils::Program::Use(m_context.getRenderContext().getFunctions(), Utils::Program::m_invalid_id);
7779
7780 /* */
7781 prepareFramebuffer(framebuffer, texture_fb);
7782
7783 /* Draw */
7784 executeDrawCall(test_case_index);
7785
7786 #if USE_NSIGHT
7787 m_context.getRenderContext().postIterate();
7788 #endif
7789
7790 /* Check results */
7791 if (false == checkResults(test_case_index, texture_fb))
7792 {
7793 m_context.getTestContext().getLog()
7794 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7795 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7796 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs) << tcu::TestLog::KernelSource(fs);
7797
7798 result = false;
7799 }
7800 }
7801
7802 /* Compute */
7803 if (true == isComputeRelevant(test_case_index))
7804 {
7805 Utils::Buffer buffer_u_cs(m_context);
7806 Utils::Program program(m_context);
7807 Utils::Texture texture_im(m_context);
7808 Utils::VertexArray vao(m_context);
7809
7810 /* */
7811 const std::string& compute_shader =
7812 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7813
7814 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7815 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7816
7817 /* */
7818 {
7819 std::stringstream stream;
7820
7821 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7822 {
7823 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7824 << ". Inspection of compute program interface failed:\n"
7825 << stream.str() << tcu::TestLog::EndMessage;
7826
7827 return false;
7828 }
7829 }
7830
7831 /* */
7832 program.Use();
7833
7834 /* */
7835 vao.Init();
7836 vao.Bind();
7837
7838 /* */
7839 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7840
7841 /* */
7842 GLint image_location = program.GetUniformLocation("uni_image");
7843 prepareImage(image_location, texture_im);
7844
7845 /* Draw */
7846 executeDispatchCall(test_case_index);
7847
7848 #if USE_NSIGHT
7849 m_context.getRenderContext().postIterate();
7850 #endif
7851
7852 /* Check results */
7853 if (false == checkResults(test_case_index, texture_im))
7854 {
7855 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7856 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7857 << tcu::TestLog::KernelSource(compute_shader);
7858
7859 result = false;
7860 }
7861 }
7862
7863 return result;
7864 }
7865
7866 /** Basic implementation
7867 *
7868 * @param ignored
7869 *
7870 * @return false
7871 **/
7872 bool TextureTestBase::useComponentQualifier(glw::GLuint /* test_case_index */)
7873 {
7874 return false;
7875 }
7876
7877 /** Basic implementation
7878 *
7879 * @param ignored
7880 *
7881 * @return true
7882 **/
7883 bool TextureTestBase::useMonolithicProgram(GLuint /* test_case_index */)
7884 {
7885 return true;
7886 }
7887
7888 /** Constructor
7889 *
7890 * @param context Test framework context
7891 **/
7892 APIConstantValuesTest::APIConstantValuesTest(deqp::Context& context)
7893 : TestCase(context, "api_constant_values", "Test verifies values of api constants")
7894 {
7895 /* Nothing to be done here */
7896 }
7897
7898 /** Execute test
7899 *
7900 * @return tcu::TestNode::STOP otherwise
7901 **/
7902 tcu::TestNode::IterateResult APIConstantValuesTest::iterate()
7903 {
7904 static const GLuint expected_comp = 64;
7905 static const GLuint expected_xfb = 4;
7906 static const GLuint expected_sep = 4;
7907 GLint max_comp = 0;
7908 GLint max_xfb = 0;
7909 GLint max_sep = 0;
7910 bool test_result = true;
7911
7912 const Functions& gl = m_context.getRenderContext().getFunctions();
7913
7914 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
7915 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
7916 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_comp);
7917 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
7918 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_sep);
7919 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
7920
7921 if (expected_xfb > (GLuint)max_xfb)
7922 {
7923 m_context.getTestContext().getLog() << tcu::TestLog::Message
7924 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_BUFFERS. Got " << max_xfb
7925 << " Expected at least " << expected_xfb << tcu::TestLog::EndMessage;
7926
7927 test_result = false;
7928 }
7929
7930 if (expected_comp > (GLuint)max_comp)
7931 {
7932 m_context.getTestContext().getLog()
7933 << tcu::TestLog::Message << "Invalid GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. Got " << max_comp
7934 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
7935
7936 test_result = false;
7937 }
7938
7939 if (expected_sep > (GLuint)max_sep)
7940 {
7941 m_context.getTestContext().getLog() << tcu::TestLog::Message
7942 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS. Got " << max_comp
7943 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
7944
7945 test_result = false;
7946 }
7947
7948 /* Set result */
7949 if (true == test_result)
7950 {
7951 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
7952 }
7953 else
7954 {
7955 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
7956 }
7957
7958 /* Done */
7959 return tcu::TestNode::STOP;
7960 }
7961
7962 /** Constructor
7963 *
7964 * @param context Test framework context
7965 **/
7966 APIErrorsTest::APIErrorsTest(deqp::Context& context)
7967 : TestCase(context, "api_errors", "Test verifies errors reeturned by api")
7968 {
7969 /* Nothing to be done here */
7970 }
7971
7972 /** Execute test
7973 *
7974 * @return tcu::TestNode::STOP otherwise
7975 **/
7976 tcu::TestNode::IterateResult APIErrorsTest::iterate()
7977 {
7978 GLint length = 0;
7979 GLchar name[64];
7980 GLint param = 0;
7981 Utils::Program program(m_context);
7982 bool test_result = true;
7983
7984 const Functions& gl = m_context.getRenderContext().getFunctions();
7985
7986 try
7987 {
7988 program.Init("" /* cs */, "#version 430 core\n"
7989 "#extension GL_ARB_enhanced_layouts : require\n"
7990 "\n"
7991 "in vec4 vs_fs;\n"
7992 "out vec4 fs_out;\n"
7993 "\n"
7994 "void main()\n"
7995 "{\n"
7996 " fs_out = vs_fs;\n"
7997 "}\n"
7998 "\n" /* fs */,
7999 "" /* gs */, "" /* tcs */, "" /* tes */, "#version 430 core\n"
8000 "#extension GL_ARB_enhanced_layouts : require\n"
8001 "\n"
8002 "in vec4 in_vs;\n"
8003 "layout (xfb_offset = 16) out vec4 vs_fs;\n"
8004 "\n"
8005 "void main()\n"
8006 "{\n"
8007 " vs_fs = in_vs;\n"
8008 "}\n"
8009 "\n" /* vs */,
8010 false /* separable */);
8011 }
8012 catch (Utils::Shader::InvalidSourceException& exc)
8013 {
8014 exc.log(m_context);
8015 TCU_FAIL(exc.what());
8016 }
8017 catch (Utils::Program::BuildException& exc)
8018 {
8019 TCU_FAIL(exc.what());
8020 }
8021
8022 /*
8023 * - GetProgramInterfaceiv should generate INVALID_OPERATION when
8024 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER and <pname> is one of the
8025 * following:
8026 * * MAX_NAME_LENGTH,
8027 * * MAX_NUM_ACTIVE_VARIABLES;
8028 */
8029 gl.getProgramInterfaceiv(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH, ¶m);
8030 checkError(GL_INVALID_OPERATION, "GetProgramInterfaceiv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH)",
8031 test_result);
8032
8033 /*
8034 * - GetProgramResourceIndex should generate INVALID_ENUM when
8035 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8036 */
8037 gl.getProgramResourceIndex(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, "0");
8038 checkError(GL_INVALID_ENUM, "GetProgramResourceIndex(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8039 /*
8040 * - GetProgramResourceName should generate INVALID_ENUM when
8041 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8042 */
8043 gl.getProgramResourceName(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 64 /* bufSize */, &length,
8044 name);
8045 checkError(GL_INVALID_ENUM, "GetProgramResourceName(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8046
8047 /* Set result */
8048 if (true == test_result)
8049 {
8050 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
8051 }
8052 else
8053 {
8054 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8055 }
8056
8057 /* Done */
8058 return tcu::TestNode::STOP;
8059 }
8060
8061 /** Check if error is the expected one.
8062 *
8063 * @param expected_error Expected error
8064 * @param message Message to log in case of error
8065 * @param test_result Test result, set to false in case of invalid error
8066 **/
8067 void APIErrorsTest::checkError(GLenum expected_error, const GLchar* message, bool& test_result)
8068 {
8069 const Functions& gl = m_context.getRenderContext().getFunctions();
8070
8071 GLenum error = gl.getError();
8072
8073 if (error != expected_error)
8074 {
8075 m_context.getTestContext().getLog()
8076 << tcu::TestLog::Message << "Failure. Invalid error. Got " << glu::getErrorStr(error) << " expected "
8077 << glu::getErrorStr(expected_error) << " Msg: " << message << tcu::TestLog::EndMessage;
8078
8079 test_result = false;
8080 }
8081 }
8082
8083 /** Constructor
8084 *
8085 * @param context Test framework context
8086 **/
8087 GLSLContantImmutablityTest::GLSLContantImmutablityTest(deqp::Context& context)
8088 : NegativeTestBase(context, "glsl_contant_immutablity", "Test verifies that glsl constants cannot be modified")
8089 {
8090 /* Nothing to be done here */
8091 }
8092
8093 /** Source for given test case and stage
8094 *
8095 * @param test_case_index Index of test case
8096 * @param stage Shader stage
8097 *
8098 * @return Shader source
8099 **/
8100 std::string GLSLContantImmutablityTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
8101 {
8102 static const GLchar* cs = "#version 430 core\n"
8103 "#extension GL_ARB_enhanced_layouts : require\n"
8104 "\n"
8105 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8106 "\n"
8107 "writeonly uniform uimage2D uni_image;\n"
8108 "\n"
8109 "void main()\n"
8110 "{\n"
8111 " uint result = 1u;\n"
8112 " CONSTANT = 3;\n"
8113 "\n"
8114 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
8115 "}\n"
8116 "\n";
8117 static const GLchar* fs = "#version 430 core\n"
8118 "#extension GL_ARB_enhanced_layouts : require\n"
8119 "\n"
8120 "in vec4 gs_fs;\n"
8121 "out vec4 fs_out;\n"
8122 "\n"
8123 "void main()\n"
8124 "{\n"
8125 "ASSIGNMENT"
8126 " fs_out = gs_fs;\n"
8127 "}\n"
8128 "\n";
8129 static const GLchar* gs = "#version 430 core\n"
8130 "#extension GL_ARB_enhanced_layouts : require\n"
8131 "\n"
8132 "layout(points) in;\n"
8133 "layout(triangle_strip, max_vertices = 4) out;\n"
8134 "\n"
8135 "in vec4 tes_gs[];\n"
8136 "out vec4 gs_fs;\n"
8137 "\n"
8138 "void main()\n"
8139 "{\n"
8140 "ASSIGNMENT"
8141 " gs_fs = tes_gs[0];\n"
8142 " gl_Position = vec4(-1, -1, 0, 1);\n"
8143 " EmitVertex();\n"
8144 " gs_fs = tes_gs[0];\n"
8145 " gl_Position = vec4(-1, 1, 0, 1);\n"
8146 " EmitVertex();\n"
8147 " gs_fs = tes_gs[0];\n"
8148 " gl_Position = vec4(1, -1, 0, 1);\n"
8149 " EmitVertex();\n"
8150 " gs_fs = tes_gs[0];\n"
8151 " gl_Position = vec4(1, 1, 0, 1);\n"
8152 " EmitVertex();\n"
8153 "}\n"
8154 "\n";
8155 static const GLchar* tcs = "#version 430 core\n"
8156 "#extension GL_ARB_enhanced_layouts : require\n"
8157 "\n"
8158 "layout(vertices = 1) out;\n"
8159 "\n"
8160 "in vec4 vs_tcs[];\n"
8161 "out vec4 tcs_tes[];\n"
8162 "\n"
8163 "void main()\n"
8164 "{\n"
8165 "\n"
8166 "ASSIGNMENT"
8167 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
8168 "\n"
8169 " gl_TessLevelOuter[0] = 1.0;\n"
8170 " gl_TessLevelOuter[1] = 1.0;\n"
8171 " gl_TessLevelOuter[2] = 1.0;\n"
8172 " gl_TessLevelOuter[3] = 1.0;\n"
8173 " gl_TessLevelInner[0] = 1.0;\n"
8174 " gl_TessLevelInner[1] = 1.0;\n"
8175 "}\n"
8176 "\n";
8177 static const GLchar* tes = "#version 430 core\n"
8178 "#extension GL_ARB_enhanced_layouts : require\n"
8179 "\n"
8180 "layout(isolines, point_mode) in;\n"
8181 "\n"
8182 "in vec4 tcs_tes[];\n"
8183 "out vec4 tes_gs;\n"
8184 "\n"
8185 "void main()\n"
8186 "{\n"
8187 "ASSIGNMENT"
8188 " tes_gs = tcs_tes[0];\n"
8189 "}\n"
8190 "\n";
8191 static const GLchar* vs = "#version 430 core\n"
8192 "#extension GL_ARB_enhanced_layouts : require\n"
8193 "\n"
8194 "in vec4 in_vs;\n"
8195 "out vec4 vs_tcs;\n"
8196 "\n"
8197 "void main()\n"
8198 "{\n"
8199 "ASSIGNMENT"
8200 " vs_tcs = in_vs;\n"
8201 "}\n"
8202 "\n";
8203
8204 std::string source;
8205 testCase& test_case = m_test_cases[test_case_index];
8206
8207 if (Utils::Shader::COMPUTE == test_case.m_stage)
8208 {
8209 size_t position = 0;
8210
8211 source = cs;
8212
8213 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), source);
8214 }
8215 else
8216 {
8217 std::string assignment = " CONSTANT = 3;\n";
8218 size_t position = 0;
8219
8220 switch (stage)
8221 {
8222 case Utils::Shader::FRAGMENT:
8223 source = fs;
8224 break;
8225 case Utils::Shader::GEOMETRY:
8226 source = gs;
8227 break;
8228 case Utils::Shader::TESS_CTRL:
8229 source = tcs;
8230 break;
8231 case Utils::Shader::TESS_EVAL:
8232 source = tes;
8233 break;
8234 case Utils::Shader::VERTEX:
8235 source = vs;
8236 break;
8237 default:
8238 TCU_FAIL("Invalid enum");
8239 }
8240
8241 if (test_case.m_stage == stage)
8242 {
8243 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), assignment);
8244 }
8245 else
8246 {
8247 assignment = "";
8248 }
8249
8250 position = 0;
8251 Utils::replaceToken("ASSIGNMENT", position, assignment.c_str(), source);
8252 }
8253
8254 return source;
8255 }
8256
8257 /** Get description of test case
8258 *
8259 * @param test_case_index Index of test case
8260 *
8261 * @return Constant name
8262 **/
8263 std::string GLSLContantImmutablityTest::getTestCaseName(GLuint test_case_index)
8264 {
8265 std::string result = getConstantName(m_test_cases[test_case_index].m_constant);
8266
8267 return result;
8268 }
8269
8270 /** Get number of test cases
8271 *
8272 * @return Number of test cases
8273 **/
8274 GLuint GLSLContantImmutablityTest::getTestCaseNumber()
8275 {
8276 return static_cast<GLuint>(m_test_cases.size());
8277 }
8278
8279 /** Selects if "compute" stage is relevant for test
8280 *
8281 * @param test_case_index Index of test case
8282 *
8283 * @return true when tested stage is compute
8284 **/
8285 bool GLSLContantImmutablityTest::isComputeRelevant(GLuint test_case_index)
8286 {
8287 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
8288 }
8289
8290 /** Prepare all test cases
8291 *
8292 **/
8293 void GLSLContantImmutablityTest::testInit()
8294 {
8295 for (GLuint constant = 0; constant < CONSTANTS_MAX; ++constant)
8296 {
8297 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
8298 {
8299 testCase test_case = { (CONSTANTS)constant, (Utils::Shader::STAGES)stage };
8300
8301 m_test_cases.push_back(test_case);
8302 }
8303 }
8304 }
8305
8306 /** Get name of glsl constant
8307 *
8308 * @param Constant id
8309 *
8310 * @return Name of constant used in GLSL
8311 **/
8312 const GLchar* GLSLContantImmutablityTest::getConstantName(CONSTANTS constant)
8313 {
8314 const GLchar* name = "";
8315
8316 switch (constant)
8317 {
8318 case GL_ARB_ENHANCED_LAYOUTS:
8319 name = "GL_ARB_enhanced_layouts";
8320 break;
8321 case GL_MAX_XFB:
8322 name = "gl_MaxTransformFeedbackBuffers";
8323 break;
8324 case GL_MAX_XFB_INT_COMP:
8325 name = "gl_MaxTransformFeedbackInterleavedComponents";
8326 break;
8327 default:
8328 TCU_FAIL("Invalid enum");
8329 }
8330
8331 return name;
8332 }
8333
8334 /** Constructor
8335 *
8336 * @param context Test framework context
8337 **/
8338 GLSLContantValuesTest::GLSLContantValuesTest(deqp::Context& context)
8339 : TextureTestBase(context, "glsl_contant_values", "Test verifies values of constant symbols")
8340 {
8341 }
8342
8343 /** Selects if "compute" stage is relevant for test
8344 *
8345 * @param ignored
8346 *
8347 * @return false
8348 **/
8349 bool GLSLContantValuesTest::isComputeRelevant(GLuint /* test_case_index */)
8350 {
8351 return false;
8352 }
8353
8354 /** Prepare code snippet that will verify in and uniform variables
8355 *
8356 * @param ignored
8357 * @param ignored
8358 * @param stage Shader stage
8359 *
8360 * @return Code that verify variables
8361 **/
8362 std::string GLSLContantValuesTest::getVerificationSnippet(GLuint /* test_case_index */,
8363 Utils::ProgramInterface& /* program_interface */,
8364 Utils::Shader::STAGES stage)
8365 {
8366 /* Get constants */
8367 const Functions& gl = m_context.getRenderContext().getFunctions();
8368
8369 GLint max_transform_feedback_buffers = 0;
8370 GLint max_transform_feedback_interleaved_components = 0;
8371
8372 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8373 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8374 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8375 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8376
8377 std::string verification;
8378
8379 if (Utils::Shader::VERTEX == stage)
8380 {
8381 verification = "if (1 != GL_ARB_enhanced_layouts)\n"
8382 " {\n"
8383 " result = 0;\n"
8384 " }\n"
8385 " else if (MAX_TRANSFORM_FEEDBACK_BUFFERS\n"
8386 " != gl_MaxTransformFeedbackBuffers)\n"
8387 " {\n"
8388 " result = 0;\n"
8389 " }\n"
8390 " else if (MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS \n"
8391 " != gl_MaxTransformFeedbackInterleavedComponents)\n"
8392 " {\n"
8393 " result = 0;\n"
8394 " }\n";
8395
8396 size_t position = 0;
8397 GLchar buffer[16];
8398
8399 sprintf(buffer, "%d", max_transform_feedback_buffers);
8400 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_BUFFERS", position, buffer, verification);
8401
8402 sprintf(buffer, "%d", max_transform_feedback_interleaved_components);
8403 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", position, buffer, verification);
8404 }
8405 else
8406 {
8407 verification = "";
8408 }
8409
8410 return verification;
8411 }
8412
8413 /** Constructor
8414 *
8415 * @param context Test framework context
8416 **/
8417 GLSLConstantIntegralExpressionTest::GLSLConstantIntegralExpressionTest(deqp::Context& context)
8418 : TextureTestBase(context, "glsl_constant_integral_expression",
8419 "Test verifies that symbols can be used as constant integral expressions")
8420 {
8421 }
8422
8423 /** Get interface of program
8424 *
8425 * @param ignored
8426 * @param program_interface Interface of program
8427 * @param ignored
8428 **/
8429 void GLSLConstantIntegralExpressionTest::getProgramInterface(GLuint /* test_case_index */,
8430 Utils::ProgramInterface& program_interface,
8431 Utils::VaryingPassthrough& /* varying_passthrough */)
8432 {
8433 /* Get constants */
8434 const Functions& gl = m_context.getRenderContext().getFunctions();
8435
8436 GLint max_transform_feedback_buffers = 0;
8437 GLint max_transform_feedback_interleaved_components = 0;
8438
8439 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8440 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8441 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8442 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8443
8444 GLuint gohan_div = std::max(1, max_transform_feedback_buffers / 16);
8445 GLuint goten_div = std::max(1, max_transform_feedback_interleaved_components / 16);
8446
8447 m_gohan_length = max_transform_feedback_buffers / gohan_div;
8448 m_goten_length = max_transform_feedback_interleaved_components / goten_div;
8449
8450 /* Globals */
8451 std::string globals = "uniform uint goku [GL_ARB_enhanced_layouts / 1];\n"
8452 "uniform uint gohan[gl_MaxTransformFeedbackBuffers / GOHAN_DIV];\n"
8453 "uniform uint goten[gl_MaxTransformFeedbackInterleavedComponents / GOTEN_DIV];\n";
8454
8455 size_t position = 0;
8456 GLchar buffer[16];
8457
8458 sprintf(buffer, "%d", gohan_div);
8459 Utils::replaceToken("GOHAN_DIV", position, buffer, globals);
8460
8461 sprintf(buffer, "%d", goten_div);
8462 Utils::replaceToken("GOTEN_DIV", position, buffer, globals);
8463
8464 program_interface.m_vertex.m_globals = globals;
8465 program_interface.m_tess_ctrl.m_globals = globals;
8466 program_interface.m_tess_eval.m_globals = globals;
8467 program_interface.m_geometry.m_globals = globals;
8468 program_interface.m_fragment.m_globals = globals;
8469 program_interface.m_compute.m_globals = globals;
8470 }
8471
8472 /** Prepare code snippet that will verify in and uniform variables
8473 *
8474 * @param ignored
8475 * @param ignored
8476 * @param ignored
8477 *
8478 * @return Code that verify variables
8479 **/
8480 std::string GLSLConstantIntegralExpressionTest::getVerificationSnippet(GLuint /* test_case_index */,
8481 Utils::ProgramInterface& /* program_interface */,
8482 Utils::Shader::STAGES /* stage */)
8483 {
8484 std::string verification = "{\n"
8485 " uint goku_sum = 0;\n"
8486 " uint gohan_sum = 0;\n"
8487 " uint goten_sum = 0;\n"
8488 "\n"
8489 " for (uint i = 0u; i < goku.length(); ++i)\n"
8490 " {\n"
8491 " goku_sum += goku[i];\n"
8492 " }\n"
8493 "\n"
8494 " for (uint i = 0u; i < gohan.length(); ++i)\n"
8495 " {\n"
8496 " gohan_sum += gohan[i];\n"
8497 " }\n"
8498 "\n"
8499 " for (uint i = 0u; i < goten.length(); ++i)\n"
8500 " {\n"
8501 " goten_sum += goten[i];\n"
8502 " }\n"
8503 "\n"
8504 " if ( (1u != goku_sum) &&\n"
8505 " (EXPECTED_GOHAN_SUMu != gohan_sum) ||\n"
8506 " (EXPECTED_GOTEN_SUMu != goten_sum) )\n"
8507 " {\n"
8508 " result = 0u;\n"
8509 " }\n"
8510 " }\n";
8511
8512 size_t position = 0;
8513 GLchar buffer[16];
8514
8515 sprintf(buffer, "%d", m_gohan_length);
8516 Utils::replaceToken("EXPECTED_GOHAN_SUM", position, buffer, verification);
8517
8518 sprintf(buffer, "%d", m_goten_length);
8519 Utils::replaceToken("EXPECTED_GOTEN_SUM", position, buffer, verification);
8520
8521 return verification;
8522 }
8523
8524 /** Prepare unifroms
8525 *
8526 * @param ignored
8527 * @param ignored
8528 * @param program Program object
8529 * @param ignored
8530 **/
8531 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint /* test_case_index */,
8532 Utils::ProgramInterface& /* program_interface */,
8533 Utils::Program& program, Utils::Buffer& /* cs_buffer */)
8534 {
8535 static const GLuint uniform_data[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
8536
8537 const Functions& gl = m_context.getRenderContext().getFunctions();
8538
8539 GLint goku_location = program.GetUniformLocation("goku");
8540 GLint gohan_location = program.GetUniformLocation("gohan");
8541 GLint goten_location = program.GetUniformLocation("goten");
8542
8543 program.Uniform(gl, Utils::Type::uint, 1 /* count */, goku_location, uniform_data);
8544 program.Uniform(gl, Utils::Type::uint, m_gohan_length, gohan_location, uniform_data);
8545 program.Uniform(gl, Utils::Type::uint, m_goten_length, goten_location, uniform_data);
8546 }
8547
8548 /** Prepare unifroms
8549 *
8550 * @param test_case_index Pass as param to first implemetnation
8551 * @param program_interface Pass as param to first implemetnation
8552 * @param program Pass as param to first implemetnation
8553 * @param ignored
8554 * @param ignored
8555 * @param ignored
8556 * @param ignored
8557 * @param vs_buffer Pass as param to first implemetnation
8558 **/
8559 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint test_case_index,
8560 Utils::ProgramInterface& program_interface,
8561 Utils::Program& program, Utils::Buffer& /* fs_buffer */,
8562 Utils::Buffer& /* gs_buffer */,
8563 Utils::Buffer& /* tcs_buffer */,
8564 Utils::Buffer& /* tes_buffer */, Utils::Buffer& vs_buffer)
8565 {
8566 /* Call first implementation */
8567 prepareUniforms(test_case_index, program_interface, program, vs_buffer);
8568 }
8569
8570 /** Constructor
8571 *
8572 * @param context Test framework context
8573 **/
8574 UniformBlockMemberOffsetAndAlignTest::UniformBlockMemberOffsetAndAlignTest(deqp::Context& context)
8575 : TextureTestBase(context, "uniform_block_member_offset_and_align",
8576 "Test verifies offsets and alignment of uniform buffer members")
8577 {
8578 }
8579
8580 /** Get interface of program
8581 *
8582 * @param test_case_index Test case index
8583 * @param program_interface Interface of program
8584 * @param varying_passthrough Collection of connections between in and out variables
8585 **/
8586 void UniformBlockMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
8587 Utils::ProgramInterface& program_interface,
8588 Utils::VaryingPassthrough& varying_passthrough)
8589 {
8590 std::string globals = "const int basic_size = BASIC_SIZE;\n"
8591 "const int type_align = TYPE_ALIGN;\n"
8592 "const int type_size = TYPE_SIZE;\n";
8593
8594 Utils::Type type = getType(test_case_index);
8595 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
8596 const GLuint base_align = type.GetBaseAlignment(false);
8597 const GLuint array_align = type.GetBaseAlignment(true);
8598 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
8599 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
8600
8601 /* Calculate offsets */
8602 const GLuint first_offset = 0;
8603 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
8604
8605 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
8606
8607 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
8608 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
8609 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8610 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8611 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8612 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
8613
8614 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8615
8616 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
8617 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
8618 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8619 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8620 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8621 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
8622
8623 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8624
8625 /* Prepare data */
8626 const std::vector<GLubyte>& first = type.GenerateData();
8627 const std::vector<GLubyte>& second = type.GenerateData();
8628 const std::vector<GLubyte>& third = type.GenerateData();
8629 const std::vector<GLubyte>& fourth = type.GenerateData();
8630
8631 m_data.resize(eigth_offset + base_stride);
8632 GLubyte* ptr = &m_data[0];
8633 memcpy(ptr + first_offset, &first[0], first.size());
8634 memcpy(ptr + second_offset, &second[0], second.size());
8635 memcpy(ptr + third_offset, &third[0], third.size());
8636 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
8637 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
8638 memcpy(ptr + sixth_offset, &third[0], third.size());
8639 memcpy(ptr + seventh_offset, &second[0], second.size());
8640 memcpy(ptr + eigth_offset, &first[0], first.size());
8641
8642 /* Prepare globals */
8643 size_t position = 0;
8644 GLchar buffer[16];
8645
8646 sprintf(buffer, "%d", basic_size);
8647 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
8648
8649 sprintf(buffer, "%d", type_align);
8650 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
8651
8652 sprintf(buffer, "%d", base_stride);
8653 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
8654
8655 /* Prepare Block */
8656 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
8657
8658 vs_uni_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
8659 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8660 first_offset);
8661
8662 vs_uni_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
8663 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
8664 0 /* n_array_elements */, base_stride, second_offset);
8665
8666 vs_uni_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
8667 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8668 third_offset);
8669
8670 vs_uni_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
8671 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8672 fourth_offset);
8673
8674 vs_uni_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8675 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
8676
8677 vs_uni_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8678 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
8679
8680 vs_uni_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
8681 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8682 eigth_offset);
8683
8684 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
8685
8686 /* Add globals */
8687 vs_si.m_globals = globals;
8688
8689 /* Add uniform BLOCK */
8690 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
8691 static_cast<glw::GLint>(m_data.size()), 0, &m_data[0], m_data.size());
8692
8693 /* */
8694 program_interface.CloneVertexInterface(varying_passthrough);
8695 }
8696
8697 /** Get type name
8698 *
8699 * @param test_case_index Index of test case
8700 *
8701 * @return Name of type test in test_case_index
8702 **/
8703 std::string UniformBlockMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
8704 {
8705 return getTypeName(test_case_index);
8706 }
8707
8708 /** Returns number of types to test
8709 *
8710 * @return Number of types, 34
8711 **/
8712 glw::GLuint UniformBlockMemberOffsetAndAlignTest::getTestCaseNumber()
8713 {
8714 return getTypesNumber();
8715 }
8716
8717 /** Prepare code snippet that will verify in and uniform variables
8718 *
8719 * @param ignored
8720 * @param ignored
8721 * @param stage Shader stage
8722 *
8723 * @return Code that verify variables
8724 **/
8725 std::string UniformBlockMemberOffsetAndAlignTest::getVerificationSnippet(
8726 GLuint /* test_case_index */, Utils::ProgramInterface& /* program_interface */, Utils::Shader::STAGES stage)
8727 {
8728 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
8729 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
8730 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
8731 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
8732 " {\n"
8733 " result = 0;\n"
8734 " }";
8735
8736 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::UNIFORM);
8737
8738 Utils::replaceAllTokens("PREFIX", prefix, verification);
8739
8740 return verification;
8741 }
8742
8743 /** Constructor
8744 *
8745 * @param context Test framework context
8746 **/
8747 UniformBlockLayoutQualifierConflictTest::UniformBlockLayoutQualifierConflictTest(deqp::Context& context)
8748 : NegativeTestBase(
8749 context, "uniform_block_layout_qualifier_conflict",
8750 "Test verifies that std140 is required when offset and/or align qualifiers are used with uniform block")
8751 {
8752 /* Nothing to be done here */
8753 }
8754
8755 /** Source for given test case and stage
8756 *
8757 * @param test_case_index Index of test case
8758 * @param stage Shader stage
8759 *
8760 * @return Shader source
8761 **/
8762 std::string UniformBlockLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index,
8763 Utils::Shader::STAGES stage)
8764 {
8765 static const GLchar* cs = "#version 430 core\n"
8766 "#extension GL_ARB_enhanced_layouts : require\n"
8767 "\n"
8768 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8769 "\n"
8770 "LAYOUTuniform Block {\n"
8771 " layout(offset = 16) vec4 boy;\n"
8772 " layout(align = 64) vec4 man;\n"
8773 "} uni_block;\n"
8774 "\n"
8775 "writeonly uniform image2D uni_image;\n"
8776 "\n"
8777 "void main()\n"
8778 "{\n"
8779 " vec4 result = uni_block.boy + uni_block.man;\n"
8780 "\n"
8781 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
8782 "}\n"
8783 "\n";
8784 static const GLchar* fs = "#version 430 core\n"
8785 "#extension GL_ARB_enhanced_layouts : require\n"
8786 "\n"
8787 "LAYOUTuniform Block {\n"
8788 " layout(offset = 16) vec4 boy;\n"
8789 " layout(align = 64) vec4 man;\n"
8790 "} uni_block;\n"
8791 "\n"
8792 "in vec4 gs_fs;\n"
8793 "out vec4 fs_out;\n"
8794 "\n"
8795 "void main()\n"
8796 "{\n"
8797 " fs_out = gs_fs + uni_block.boy + uni_block.man;\n"
8798 "}\n"
8799 "\n";
8800 static const GLchar* gs = "#version 430 core\n"
8801 "#extension GL_ARB_enhanced_layouts : require\n"
8802 "\n"
8803 "layout(points) in;\n"
8804 "layout(triangle_strip, max_vertices = 4) out;\n"
8805 "\n"
8806 "LAYOUTuniform Block {\n"
8807 " layout(offset = 16) vec4 boy;\n"
8808 " layout(align = 64) vec4 man;\n"
8809 "} uni_block;\n"
8810 "\n"
8811 "in vec4 tes_gs[];\n"
8812 "out vec4 gs_fs;\n"
8813 "\n"
8814 "void main()\n"
8815 "{\n"
8816 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8817 " gl_Position = vec4(-1, -1, 0, 1);\n"
8818 " EmitVertex();\n"
8819 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8820 " gl_Position = vec4(-1, 1, 0, 1);\n"
8821 " EmitVertex();\n"
8822 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8823 " gl_Position = vec4(1, -1, 0, 1);\n"
8824 " EmitVertex();\n"
8825 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8826 " gl_Position = vec4(1, 1, 0, 1);\n"
8827 " EmitVertex();\n"
8828 "}\n"
8829 "\n";
8830 static const GLchar* tcs =
8831 "#version 430 core\n"
8832 "#extension GL_ARB_enhanced_layouts : require\n"
8833 "\n"
8834 "layout(vertices = 1) out;\n"
8835 "\n"
8836 "LAYOUTuniform Block {\n"
8837 " layout(offset = 16) vec4 boy;\n"
8838 " layout(align = 64) vec4 man;\n"
8839 "} uni_block;\n"
8840 "\n"
8841 "in vec4 vs_tcs[];\n"
8842 "out vec4 tcs_tes[];\n"
8843 "\n"
8844 "void main()\n"
8845 "{\n"
8846 "\n"
8847 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.boy + uni_block.man;\n"
8848 "\n"
8849 " gl_TessLevelOuter[0] = 1.0;\n"
8850 " gl_TessLevelOuter[1] = 1.0;\n"
8851 " gl_TessLevelOuter[2] = 1.0;\n"
8852 " gl_TessLevelOuter[3] = 1.0;\n"
8853 " gl_TessLevelInner[0] = 1.0;\n"
8854 " gl_TessLevelInner[1] = 1.0;\n"
8855 "}\n"
8856 "\n";
8857 static const GLchar* tes = "#version 430 core\n"
8858 "#extension GL_ARB_enhanced_layouts : require\n"
8859 "\n"
8860 "layout(isolines, point_mode) in;\n"
8861 "\n"
8862 "LAYOUTuniform Block {\n"
8863 " layout(offset = 16) vec4 boy;\n"
8864 " layout(align = 64) vec4 man;\n"
8865 "} uni_block;\n"
8866 "\n"
8867 "in vec4 tcs_tes[];\n"
8868 "out vec4 tes_gs;\n"
8869 "\n"
8870 "void main()\n"
8871 "{\n"
8872 " tes_gs = tcs_tes[0] + uni_block.boy + uni_block.man;\n"
8873 "}\n"
8874 "\n";
8875 static const GLchar* vs = "#version 430 core\n"
8876 "#extension GL_ARB_enhanced_layouts : require\n"
8877 "\n"
8878 "LAYOUTuniform Block {\n"
8879 " layout(offset = 16) vec4 boy;\n"
8880 " layout(align = 64) vec4 man;\n"
8881 "} uni_block;\n"
8882 "\n"
8883 "in vec4 in_vs;\n"
8884 "out vec4 vs_tcs;\n"
8885 "\n"
8886 "void main()\n"
8887 "{\n"
8888 " vs_tcs = in_vs + uni_block.boy + uni_block.man;\n"
8889 "}\n"
8890 "\n";
8891
8892 std::string layout = "";
8893 size_t position = 0;
8894 testCase& test_case = m_test_cases[test_case_index];
8895 const GLchar* qualifier = getQualifierName(test_case.m_qualifier);
8896 std::string source;
8897
8898 if (0 != qualifier[0])
8899 {
8900 size_t layout_position = 0;
8901
8902 layout = "layout (QUALIFIER) ";
8903
8904 Utils::replaceToken("QUALIFIER", layout_position, qualifier, layout);
8905 }
8906
8907 switch (stage)
8908 {
8909 case Utils::Shader::COMPUTE:
8910 source = cs;
8911 break;
8912 case Utils::Shader::FRAGMENT:
8913 source = fs;
8914 break;
8915 case Utils::Shader::GEOMETRY:
8916 source = gs;
8917 break;
8918 case Utils::Shader::TESS_CTRL:
8919 source = tcs;
8920 break;
8921 case Utils::Shader::TESS_EVAL:
8922 source = tes;
8923 break;
8924 case Utils::Shader::VERTEX:
8925 source = vs;
8926 break;
8927 default:
8928 TCU_FAIL("Invalid enum");
8929 }
8930
8931 if (test_case.m_stage == stage)
8932 {
8933 Utils::replaceToken("LAYOUT", position, layout.c_str(), source);
8934 }
8935 else
8936 {
8937 Utils::replaceToken("LAYOUT", position, "layout (std140) ", source);
8938 }
8939
8940 return source;
8941 }
8942
8943 /** Get description of test case
8944 *
8945 * @param test_case_index Index of test case
8946 *
8947 * @return Qualifier name
8948 **/
8949 std::string UniformBlockLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
8950 {
8951 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
8952
8953 return result;
8954 }
8955
8956 /** Get number of test cases
8957 *
8958 * @return Number of test cases
8959 **/
8960 GLuint UniformBlockLayoutQualifierConflictTest::getTestCaseNumber()
8961 {
8962 return static_cast<GLuint>(m_test_cases.size());
8963 }
8964
8965 /** Selects if "compute" stage is relevant for test
8966 *
8967 * @param test_case_index Index of test case
8968 *
8969 * @return true when tested stage is compute
8970 **/
8971 bool UniformBlockLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
8972 {
8973 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
8974 }
8975
8976 /** Selects if compilation failure is expected result
8977 *
8978 * @param test_case_index Index of test case
8979 *
8980 * @return false for STD140 cases, true otherwise
8981 **/
8982 bool UniformBlockLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
8983 {
8984 return (STD140 != m_test_cases[test_case_index].m_qualifier);
8985 }
8986
8987 /** Prepare all test cases
8988 *
8989 **/
8990 void UniformBlockLayoutQualifierConflictTest::testInit()
8991 {
8992 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
8993 {
8994 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
8995 {
8996 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
8997
8998 m_test_cases.push_back(test_case);
8999 }
9000 }
9001 }
9002
9003 /** Get name of glsl constant
9004 *
9005 * @param Constant id
9006 *
9007 * @return Name of constant used in GLSL
9008 **/
9009 const GLchar* UniformBlockLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
9010 {
9011 const GLchar* name = "";
9012
9013 switch (qualifier)
9014 {
9015 case DEFAULT:
9016 name = "";
9017 break;
9018 case STD140:
9019 name = "std140";
9020 break;
9021 case SHARED:
9022 name = "shared";
9023 break;
9024 case PACKED:
9025 name = "packed";
9026 break;
9027 default:
9028 TCU_FAIL("Invalid enum");
9029 }
9030
9031 return name;
9032 }
9033
9034 /** Constructor
9035 *
9036 * @param context Test framework context
9037 **/
9038 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(deqp::Context& context)
9039 : NegativeTestBase(context, "uniform_block_member_invalid_offset_alignment",
9040 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
9041 {
9042 /* Nothing to be done here */
9043 }
9044
9045 /** Constructor
9046 *
9047 * @param context Test framework context
9048 * @param name Test name
9049 * @param description Test description
9050 **/
9051 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(
9052 deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
9053 : NegativeTestBase(context, name, description)
9054 {
9055 /* Nothing to be done here */
9056 }
9057
9058 /** Source for given test case and stage
9059 *
9060 * @param test_case_index Index of test case
9061 * @param stage Shader stage
9062 *
9063 * @return Shader source
9064 **/
9065 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index,
9066 Utils::Shader::STAGES stage)
9067 {
9068 static const GLchar* cs = "#version 430 core\n"
9069 "#extension GL_ARB_enhanced_layouts : require\n"
9070 "\n"
9071 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9072 "\n"
9073 "layout (std140) uniform Block {\n"
9074 " layout (offset = OFFSET) TYPE member;\n"
9075 "} block;\n"
9076 "\n"
9077 "writeonly uniform image2D uni_image;\n"
9078 "\n"
9079 "void main()\n"
9080 "{\n"
9081 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9082 "\n"
9083 " if (TYPE(1) == block.member)\n"
9084 " {\n"
9085 " result = vec4(1, 1, 1, 1);\n"
9086 " }\n"
9087 "\n"
9088 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9089 "}\n"
9090 "\n";
9091 static const GLchar* fs = "#version 430 core\n"
9092 "#extension GL_ARB_enhanced_layouts : require\n"
9093 "\n"
9094 "in vec4 gs_fs;\n"
9095 "out vec4 fs_out;\n"
9096 "\n"
9097 "void main()\n"
9098 "{\n"
9099 " fs_out = gs_fs;\n"
9100 "}\n"
9101 "\n";
9102 static const GLchar* fs_tested = "#version 430 core\n"
9103 "#extension GL_ARB_enhanced_layouts : require\n"
9104 "\n"
9105 "layout (std140) uniform Block {\n"
9106 " layout (offset = OFFSET) TYPE member;\n"
9107 "} block;\n"
9108 "\n"
9109 "in vec4 gs_fs;\n"
9110 "out vec4 fs_out;\n"
9111 "\n"
9112 "void main()\n"
9113 "{\n"
9114 " if (TYPE(1) == block.member)\n"
9115 " {\n"
9116 " fs_out = vec4(1, 1, 1, 1);\n"
9117 " }\n"
9118 "\n"
9119 " fs_out += gs_fs;\n"
9120 "}\n"
9121 "\n";
9122 static const GLchar* gs = "#version 430 core\n"
9123 "#extension GL_ARB_enhanced_layouts : require\n"
9124 "\n"
9125 "layout(points) in;\n"
9126 "layout(triangle_strip, max_vertices = 4) out;\n"
9127 "\n"
9128 "in vec4 tes_gs[];\n"
9129 "out vec4 gs_fs;\n"
9130 "\n"
9131 "void main()\n"
9132 "{\n"
9133 " gs_fs = tes_gs[0];\n"
9134 " gl_Position = vec4(-1, -1, 0, 1);\n"
9135 " EmitVertex();\n"
9136 " gs_fs = tes_gs[0];\n"
9137 " gl_Position = vec4(-1, 1, 0, 1);\n"
9138 " EmitVertex();\n"
9139 " gs_fs = tes_gs[0];\n"
9140 " gl_Position = vec4(1, -1, 0, 1);\n"
9141 " EmitVertex();\n"
9142 " gs_fs = tes_gs[0];\n"
9143 " gl_Position = vec4(1, 1, 0, 1);\n"
9144 " EmitVertex();\n"
9145 "}\n"
9146 "\n";
9147 static const GLchar* gs_tested = "#version 430 core\n"
9148 "#extension GL_ARB_enhanced_layouts : require\n"
9149 "\n"
9150 "layout(points) in;\n"
9151 "layout(triangle_strip, max_vertices = 4) out;\n"
9152 "\n"
9153 "layout (std140) uniform Block {\n"
9154 " layout (offset = OFFSET) TYPE member;\n"
9155 "} block;\n"
9156 "\n"
9157 "in vec4 tes_gs[];\n"
9158 "out vec4 gs_fs;\n"
9159 "\n"
9160 "void main()\n"
9161 "{\n"
9162 " if (TYPE(1) == block.member)\n"
9163 " {\n"
9164 " gs_fs = vec4(1, 1, 1, 1);\n"
9165 " }\n"
9166 "\n"
9167 " gs_fs += tes_gs[0];\n"
9168 " gl_Position = vec4(-1, -1, 0, 1);\n"
9169 " EmitVertex();\n"
9170 " gs_fs += tes_gs[0];\n"
9171 " gl_Position = vec4(-1, 1, 0, 1);\n"
9172 " EmitVertex();\n"
9173 " gs_fs += tes_gs[0];\n"
9174 " gl_Position = vec4(1, -1, 0, 1);\n"
9175 " EmitVertex();\n"
9176 " gs_fs += tes_gs[0];\n"
9177 " gl_Position = vec4(1, 1, 0, 1);\n"
9178 " EmitVertex();\n"
9179 "}\n"
9180 "\n";
9181 static const GLchar* tcs = "#version 430 core\n"
9182 "#extension GL_ARB_enhanced_layouts : require\n"
9183 "\n"
9184 "layout(vertices = 1) out;\n"
9185 "\n"
9186 "in vec4 vs_tcs[];\n"
9187 "out vec4 tcs_tes[];\n"
9188 "\n"
9189 "void main()\n"
9190 "{\n"
9191 "\n"
9192 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9193 "\n"
9194 " gl_TessLevelOuter[0] = 1.0;\n"
9195 " gl_TessLevelOuter[1] = 1.0;\n"
9196 " gl_TessLevelOuter[2] = 1.0;\n"
9197 " gl_TessLevelOuter[3] = 1.0;\n"
9198 " gl_TessLevelInner[0] = 1.0;\n"
9199 " gl_TessLevelInner[1] = 1.0;\n"
9200 "}\n"
9201 "\n";
9202 static const GLchar* tcs_tested = "#version 430 core\n"
9203 "#extension GL_ARB_enhanced_layouts : require\n"
9204 "\n"
9205 "layout(vertices = 1) out;\n"
9206 "\n"
9207 "layout (std140) uniform Block {\n"
9208 " layout (offset = OFFSET) TYPE member;\n"
9209 "} block;\n"
9210 "\n"
9211 "in vec4 vs_tcs[];\n"
9212 "out vec4 tcs_tes[];\n"
9213 "\n"
9214 "void main()\n"
9215 "{\n"
9216 " if (TYPE(1) == block.member)\n"
9217 " {\n"
9218 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9219 " }\n"
9220 "\n"
9221 "\n"
9222 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9223 "\n"
9224 " gl_TessLevelOuter[0] = 1.0;\n"
9225 " gl_TessLevelOuter[1] = 1.0;\n"
9226 " gl_TessLevelOuter[2] = 1.0;\n"
9227 " gl_TessLevelOuter[3] = 1.0;\n"
9228 " gl_TessLevelInner[0] = 1.0;\n"
9229 " gl_TessLevelInner[1] = 1.0;\n"
9230 "}\n"
9231 "\n";
9232 static const GLchar* tes = "#version 430 core\n"
9233 "#extension GL_ARB_enhanced_layouts : require\n"
9234 "\n"
9235 "layout(isolines, point_mode) in;\n"
9236 "\n"
9237 "in vec4 tcs_tes[];\n"
9238 "out vec4 tes_gs;\n"
9239 "\n"
9240 "void main()\n"
9241 "{\n"
9242 " tes_gs = tcs_tes[0];\n"
9243 "}\n"
9244 "\n";
9245 static const GLchar* tes_tested = "#version 430 core\n"
9246 "#extension GL_ARB_enhanced_layouts : require\n"
9247 "\n"
9248 "layout(isolines, point_mode) in;\n"
9249 "\n"
9250 "layout (std140) uniform Block {\n"
9251 " layout (offset = OFFSET) TYPE member;\n"
9252 "} block;\n"
9253 "\n"
9254 "in vec4 tcs_tes[];\n"
9255 "out vec4 tes_gs;\n"
9256 "\n"
9257 "void main()\n"
9258 "{\n"
9259 " if (TYPE(1) == block.member)\n"
9260 " {\n"
9261 " tes_gs = vec4(1, 1, 1, 1);\n"
9262 " }\n"
9263 "\n"
9264 " tes_gs += tcs_tes[0];\n"
9265 "}\n"
9266 "\n";
9267 static const GLchar* vs = "#version 430 core\n"
9268 "#extension GL_ARB_enhanced_layouts : require\n"
9269 "\n"
9270 "in vec4 in_vs;\n"
9271 "out vec4 vs_tcs;\n"
9272 "\n"
9273 "void main()\n"
9274 "{\n"
9275 " vs_tcs = in_vs;\n"
9276 "}\n"
9277 "\n";
9278 static const GLchar* vs_tested = "#version 430 core\n"
9279 "#extension GL_ARB_enhanced_layouts : require\n"
9280 "\n"
9281 "layout (std140) uniform Block {\n"
9282 " layout (offset = OFFSET) TYPE member;\n"
9283 "} block;\n"
9284 "\n"
9285 "in vec4 in_vs;\n"
9286 "out vec4 vs_tcs;\n"
9287 "\n"
9288 "void main()\n"
9289 "{\n"
9290 " if (TYPE(1) == block.member)\n"
9291 " {\n"
9292 " vs_tcs = vec4(1, 1, 1, 1);\n"
9293 " }\n"
9294 "\n"
9295 " vs_tcs += in_vs;\n"
9296 "}\n"
9297 "\n";
9298
9299 std::string source;
9300 testCase& test_case = m_test_cases[test_case_index];
9301
9302 if (test_case.m_stage == stage)
9303 {
9304 GLchar buffer[16];
9305 const GLuint offset = test_case.m_offset;
9306 size_t position = 0;
9307 const Utils::Type& type = test_case.m_type;
9308 const GLchar* type_name = type.GetGLSLTypeName();
9309
9310 sprintf(buffer, "%d", offset);
9311
9312 switch (stage)
9313 {
9314 case Utils::Shader::COMPUTE:
9315 source = cs;
9316 break;
9317 case Utils::Shader::FRAGMENT:
9318 source = fs_tested;
9319 break;
9320 case Utils::Shader::GEOMETRY:
9321 source = gs_tested;
9322 break;
9323 case Utils::Shader::TESS_CTRL:
9324 source = tcs_tested;
9325 break;
9326 case Utils::Shader::TESS_EVAL:
9327 source = tes_tested;
9328 break;
9329 case Utils::Shader::VERTEX:
9330 source = vs_tested;
9331 break;
9332 default:
9333 TCU_FAIL("Invalid enum");
9334 }
9335
9336 Utils::replaceToken("OFFSET", position, buffer, source);
9337 Utils::replaceToken("TYPE", position, type_name, source);
9338 Utils::replaceToken("TYPE", position, type_name, source);
9339 }
9340 else
9341 {
9342 switch (stage)
9343 {
9344 case Utils::Shader::FRAGMENT:
9345 source = fs;
9346 break;
9347 case Utils::Shader::GEOMETRY:
9348 source = gs;
9349 break;
9350 case Utils::Shader::TESS_CTRL:
9351 source = tcs;
9352 break;
9353 case Utils::Shader::TESS_EVAL:
9354 source = tes;
9355 break;
9356 case Utils::Shader::VERTEX:
9357 source = vs;
9358 break;
9359 default:
9360 TCU_FAIL("Invalid enum");
9361 }
9362 }
9363
9364 return source;
9365 }
9366
9367 /** Get description of test case
9368 *
9369 * @param test_case_index Index of test case
9370 *
9371 * @return Type name and offset
9372 **/
9373 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
9374 {
9375 std::stringstream stream;
9376 testCase& test_case = m_test_cases[test_case_index];
9377
9378 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
9379
9380 return stream.str();
9381 }
9382
9383 /** Get number of test cases
9384 *
9385 * @return Number of test cases
9386 **/
9387 GLuint UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseNumber()
9388 {
9389 return static_cast<GLuint>(m_test_cases.size());
9390 }
9391
9392 /** Get the maximum size for an uniform block
9393 *
9394 * @return The maximum size in basic machine units of a uniform block.
9395 **/
9396 GLint UniformBlockMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
9397 {
9398 const Functions& gl = m_context.getRenderContext().getFunctions();
9399 GLint max_size = 0;
9400
9401 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size);
9402 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
9403
9404 return max_size;
9405 }
9406
9407 /** Selects if "compute" stage is relevant for test
9408 *
9409 * @param test_case_index Index of test case
9410 *
9411 * @return true when tested stage is compute
9412 **/
9413 bool UniformBlockMemberInvalidOffsetAlignmentTest::isComputeRelevant(GLuint test_case_index)
9414 {
9415 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9416 }
9417
9418 /** Selects if compilation failure is expected result
9419 *
9420 * @param test_case_index Index of test case
9421 *
9422 * @return should_fail field from testCase
9423 **/
9424 bool UniformBlockMemberInvalidOffsetAlignmentTest::isFailureExpected(GLuint test_case_index)
9425 {
9426 return m_test_cases[test_case_index].m_should_fail;
9427 }
9428
9429 /** Checks if stage is supported
9430 *
9431 * @param stage ignored
9432 *
9433 * @return true
9434 **/
9435 bool UniformBlockMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9436 {
9437 return true;
9438 }
9439
9440 /** Prepare all test cases
9441 *
9442 **/
9443 void UniformBlockMemberInvalidOffsetAlignmentTest::testInit()
9444 {
9445 const GLuint n_types = getTypesNumber();
9446 bool stage_support[Utils::Shader::STAGE_MAX];
9447
9448 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9449 {
9450 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9451 }
9452
9453 for (GLuint i = 0; i < n_types; ++i)
9454 {
9455 const Utils::Type& type = getType(i);
9456 const GLuint alignment = type.GetBaseAlignment(false);
9457 const GLuint type_size = type.GetSize(true);
9458 const GLuint sec_to_end = getMaxBlockSize() - 2 * type_size;
9459
9460 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9461 {
9462 if (false == stage_support[stage])
9463 {
9464 continue;
9465 }
9466
9467 for (GLuint offset = 0; offset <= type_size; ++offset)
9468 {
9469 const GLuint modulo = offset % alignment;
9470 const bool is_aligned = (0 == modulo) ? true : false;
9471 const bool should_fail = !is_aligned;
9472
9473 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9474
9475 m_test_cases.push_back(test_case);
9476 }
9477
9478 for (GLuint offset = sec_to_end; offset <= sec_to_end + type_size; ++offset)
9479 {
9480 const GLuint modulo = offset % alignment;
9481 const bool is_aligned = (0 == modulo) ? true : false;
9482 const bool should_fail = !is_aligned;
9483
9484 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9485
9486 m_test_cases.push_back(test_case);
9487 }
9488 }
9489 }
9490 }
9491
9492 /** Constructor
9493 *
9494 * @param context Test framework context
9495 **/
9496 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context)
9497 : NegativeTestBase(context, "uniform_block_member_overlapping_offsets",
9498 "Test verifies that overlapping offsets qualifiers cause compilation failure")
9499 {
9500 /* Nothing to be done here */
9501 }
9502
9503 /** Constructor
9504 *
9505 * @param context Test framework context
9506 * @param name Test name
9507 * @param description Test description
9508 **/
9509 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context,
9510 const glw::GLchar* name,
9511 const glw::GLchar* description)
9512 : NegativeTestBase(context, name, description)
9513 {
9514 /* Nothing to be done here */
9515 }
9516
9517 /** Source for given test case and stage
9518 *
9519 * @param test_case_index Index of test case
9520 * @param stage Shader stage
9521 *
9522 * @return Shader source
9523 **/
9524 std::string UniformBlockMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index,
9525 Utils::Shader::STAGES stage)
9526 {
9527 static const GLchar* cs = "#version 430 core\n"
9528 "#extension GL_ARB_enhanced_layouts : require\n"
9529 "\n"
9530 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9531 "\n"
9532 "layout (std140) uniform Block {\n"
9533 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9534 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9535 "} block;\n"
9536 "\n"
9537 "writeonly uniform image2D uni_image;\n"
9538 "\n"
9539 "void main()\n"
9540 "{\n"
9541 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9542 "\n"
9543 " if ((BOY_TYPE(1) == block.boy) ||\n"
9544 " (MAN_TYPE(0) == block.man) )\n"
9545 " {\n"
9546 " result = vec4(1, 1, 1, 1);\n"
9547 " }\n"
9548 "\n"
9549 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9550 "}\n"
9551 "\n";
9552 static const GLchar* fs = "#version 430 core\n"
9553 "#extension GL_ARB_enhanced_layouts : require\n"
9554 "\n"
9555 "in vec4 gs_fs;\n"
9556 "out vec4 fs_out;\n"
9557 "\n"
9558 "void main()\n"
9559 "{\n"
9560 " fs_out = gs_fs;\n"
9561 "}\n"
9562 "\n";
9563 static const GLchar* fs_tested = "#version 430 core\n"
9564 "#extension GL_ARB_enhanced_layouts : require\n"
9565 "\n"
9566 "layout (std140) uniform Block {\n"
9567 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9568 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9569 "} block;\n"
9570 "\n"
9571 "in vec4 gs_fs;\n"
9572 "out vec4 fs_out;\n"
9573 "\n"
9574 "void main()\n"
9575 "{\n"
9576 " if ((BOY_TYPE(1) == block.boy) ||\n"
9577 " (MAN_TYPE(0) == block.man) )\n"
9578 " {\n"
9579 " fs_out = vec4(1, 1, 1, 1);\n"
9580 " }\n"
9581 "\n"
9582 " fs_out += gs_fs;\n"
9583 "}\n"
9584 "\n";
9585 static const GLchar* gs = "#version 430 core\n"
9586 "#extension GL_ARB_enhanced_layouts : require\n"
9587 "\n"
9588 "layout(points) in;\n"
9589 "layout(triangle_strip, max_vertices = 4) out;\n"
9590 "\n"
9591 "in vec4 tes_gs[];\n"
9592 "out vec4 gs_fs;\n"
9593 "\n"
9594 "void main()\n"
9595 "{\n"
9596 " gs_fs = tes_gs[0];\n"
9597 " gl_Position = vec4(-1, -1, 0, 1);\n"
9598 " EmitVertex();\n"
9599 " gs_fs = tes_gs[0];\n"
9600 " gl_Position = vec4(-1, 1, 0, 1);\n"
9601 " EmitVertex();\n"
9602 " gs_fs = tes_gs[0];\n"
9603 " gl_Position = vec4(1, -1, 0, 1);\n"
9604 " EmitVertex();\n"
9605 " gs_fs = tes_gs[0];\n"
9606 " gl_Position = vec4(1, 1, 0, 1);\n"
9607 " EmitVertex();\n"
9608 "}\n"
9609 "\n";
9610 static const GLchar* gs_tested = "#version 430 core\n"
9611 "#extension GL_ARB_enhanced_layouts : require\n"
9612 "\n"
9613 "layout(points) in;\n"
9614 "layout(triangle_strip, max_vertices = 4) out;\n"
9615 "\n"
9616 "layout (std140) uniform Block {\n"
9617 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9618 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9619 "} block;\n"
9620 "\n"
9621 "in vec4 tes_gs[];\n"
9622 "out vec4 gs_fs;\n"
9623 "\n"
9624 "void main()\n"
9625 "{\n"
9626 " if ((BOY_TYPE(1) == block.boy) ||\n"
9627 " (MAN_TYPE(0) == block.man) )\n"
9628 " {\n"
9629 " gs_fs = vec4(1, 1, 1, 1);\n"
9630 " }\n"
9631 "\n"
9632 " gs_fs += tes_gs[0];\n"
9633 " gl_Position = vec4(-1, -1, 0, 1);\n"
9634 " EmitVertex();\n"
9635 " gs_fs += tes_gs[0];\n"
9636 " gl_Position = vec4(-1, 1, 0, 1);\n"
9637 " EmitVertex();\n"
9638 " gs_fs += tes_gs[0];\n"
9639 " gl_Position = vec4(1, -1, 0, 1);\n"
9640 " EmitVertex();\n"
9641 " gs_fs += tes_gs[0];\n"
9642 " gl_Position = vec4(1, 1, 0, 1);\n"
9643 " EmitVertex();\n"
9644 "}\n"
9645 "\n";
9646 static const GLchar* tcs = "#version 430 core\n"
9647 "#extension GL_ARB_enhanced_layouts : require\n"
9648 "\n"
9649 "layout(vertices = 1) out;\n"
9650 "\n"
9651 "in vec4 vs_tcs[];\n"
9652 "out vec4 tcs_tes[];\n"
9653 "\n"
9654 "void main()\n"
9655 "{\n"
9656 "\n"
9657 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9658 "\n"
9659 " gl_TessLevelOuter[0] = 1.0;\n"
9660 " gl_TessLevelOuter[1] = 1.0;\n"
9661 " gl_TessLevelOuter[2] = 1.0;\n"
9662 " gl_TessLevelOuter[3] = 1.0;\n"
9663 " gl_TessLevelInner[0] = 1.0;\n"
9664 " gl_TessLevelInner[1] = 1.0;\n"
9665 "}\n"
9666 "\n";
9667 static const GLchar* tcs_tested = "#version 430 core\n"
9668 "#extension GL_ARB_enhanced_layouts : require\n"
9669 "\n"
9670 "layout(vertices = 1) out;\n"
9671 "\n"
9672 "layout (std140) uniform Block {\n"
9673 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9674 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9675 "} block;\n"
9676 "\n"
9677 "in vec4 vs_tcs[];\n"
9678 "out vec4 tcs_tes[];\n"
9679 "\n"
9680 "void main()\n"
9681 "{\n"
9682 " if ((BOY_TYPE(1) == block.boy) ||\n"
9683 " (MAN_TYPE(0) == block.man) )\n"
9684 " {\n"
9685 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9686 " }\n"
9687 "\n"
9688 "\n"
9689 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9690 "\n"
9691 " gl_TessLevelOuter[0] = 1.0;\n"
9692 " gl_TessLevelOuter[1] = 1.0;\n"
9693 " gl_TessLevelOuter[2] = 1.0;\n"
9694 " gl_TessLevelOuter[3] = 1.0;\n"
9695 " gl_TessLevelInner[0] = 1.0;\n"
9696 " gl_TessLevelInner[1] = 1.0;\n"
9697 "}\n"
9698 "\n";
9699 static const GLchar* tes = "#version 430 core\n"
9700 "#extension GL_ARB_enhanced_layouts : require\n"
9701 "\n"
9702 "layout(isolines, point_mode) in;\n"
9703 "\n"
9704 "in vec4 tcs_tes[];\n"
9705 "out vec4 tes_gs;\n"
9706 "\n"
9707 "void main()\n"
9708 "{\n"
9709 " tes_gs = tcs_tes[0];\n"
9710 "}\n"
9711 "\n";
9712 static const GLchar* tes_tested = "#version 430 core\n"
9713 "#extension GL_ARB_enhanced_layouts : require\n"
9714 "\n"
9715 "layout(isolines, point_mode) in;\n"
9716 "\n"
9717 "layout (std140) uniform Block {\n"
9718 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9719 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9720 "} block;\n"
9721 "\n"
9722 "in vec4 tcs_tes[];\n"
9723 "out vec4 tes_gs;\n"
9724 "\n"
9725 "void main()\n"
9726 "{\n"
9727 " if ((BOY_TYPE(1) == block.boy) ||\n"
9728 " (MAN_TYPE(0) == block.man) )\n"
9729 " {\n"
9730 " tes_gs = vec4(1, 1, 1, 1);\n"
9731 " }\n"
9732 "\n"
9733 " tes_gs += tcs_tes[0];\n"
9734 "}\n"
9735 "\n";
9736 static const GLchar* vs = "#version 430 core\n"
9737 "#extension GL_ARB_enhanced_layouts : require\n"
9738 "\n"
9739 "in vec4 in_vs;\n"
9740 "out vec4 vs_tcs;\n"
9741 "\n"
9742 "void main()\n"
9743 "{\n"
9744 " vs_tcs = in_vs;\n"
9745 "}\n"
9746 "\n";
9747 static const GLchar* vs_tested = "#version 430 core\n"
9748 "#extension GL_ARB_enhanced_layouts : require\n"
9749 "\n"
9750 "layout (std140) uniform Block {\n"
9751 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9752 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9753 "} block;\n"
9754 "\n"
9755 "in vec4 in_vs;\n"
9756 "out vec4 vs_tcs;\n"
9757 "\n"
9758 "void main()\n"
9759 "{\n"
9760 " if ((BOY_TYPE(1) == block.boy) ||\n"
9761 " (MAN_TYPE(0) == block.man) )\n"
9762 " {\n"
9763 " vs_tcs = vec4(1, 1, 1, 1);\n"
9764 " }\n"
9765 "\n"
9766 " vs_tcs += in_vs;\n"
9767 "}\n"
9768 "\n";
9769
9770 std::string source;
9771 testCase& test_case = m_test_cases[test_case_index];
9772
9773 if (test_case.m_stage == stage)
9774 {
9775 GLchar buffer[16];
9776 const GLuint boy_offset = test_case.m_boy_offset;
9777 const Utils::Type& boy_type = test_case.m_boy_type;
9778 const GLchar* boy_type_name = boy_type.GetGLSLTypeName();
9779 const GLuint man_offset = test_case.m_man_offset;
9780 const Utils::Type& man_type = test_case.m_man_type;
9781 const GLchar* man_type_name = man_type.GetGLSLTypeName();
9782 size_t position = 0;
9783
9784 switch (stage)
9785 {
9786 case Utils::Shader::COMPUTE:
9787 source = cs;
9788 break;
9789 case Utils::Shader::FRAGMENT:
9790 source = fs_tested;
9791 break;
9792 case Utils::Shader::GEOMETRY:
9793 source = gs_tested;
9794 break;
9795 case Utils::Shader::TESS_CTRL:
9796 source = tcs_tested;
9797 break;
9798 case Utils::Shader::TESS_EVAL:
9799 source = tes_tested;
9800 break;
9801 case Utils::Shader::VERTEX:
9802 source = vs_tested;
9803 break;
9804 default:
9805 TCU_FAIL("Invalid enum");
9806 }
9807
9808 sprintf(buffer, "%d", boy_offset);
9809 Utils::replaceToken("BOY_OFFSET", position, buffer, source);
9810 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
9811 sprintf(buffer, "%d", man_offset);
9812 Utils::replaceToken("MAN_OFFSET", position, buffer, source);
9813 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
9814 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
9815 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
9816 }
9817 else
9818 {
9819 switch (stage)
9820 {
9821 case Utils::Shader::FRAGMENT:
9822 source = fs;
9823 break;
9824 case Utils::Shader::GEOMETRY:
9825 source = gs;
9826 break;
9827 case Utils::Shader::TESS_CTRL:
9828 source = tcs;
9829 break;
9830 case Utils::Shader::TESS_EVAL:
9831 source = tes;
9832 break;
9833 case Utils::Shader::VERTEX:
9834 source = vs;
9835 break;
9836 default:
9837 TCU_FAIL("Invalid enum");
9838 }
9839 }
9840
9841 return source;
9842 }
9843
9844 /** Get description of test case
9845 *
9846 * @param test_case_index Index of test case
9847 *
9848 * @return Type name and offset
9849 **/
9850 std::string UniformBlockMemberOverlappingOffsetsTest::getTestCaseName(GLuint test_case_index)
9851 {
9852 std::stringstream stream;
9853 testCase& test_case = m_test_cases[test_case_index];
9854
9855 stream << "Type: " << test_case.m_boy_type.GetGLSLTypeName() << ", offset: " << test_case.m_boy_offset
9856 << ". Type: " << test_case.m_man_type.GetGLSLTypeName() << ", offset: " << test_case.m_man_offset;
9857
9858 return stream.str();
9859 }
9860
9861 /** Get number of test cases
9862 *
9863 * @return Number of test cases
9864 **/
9865 GLuint UniformBlockMemberOverlappingOffsetsTest::getTestCaseNumber()
9866 {
9867 return static_cast<GLuint>(m_test_cases.size());
9868 }
9869
9870 /** Selects if "compute" stage is relevant for test
9871 *
9872 * @param test_case_index Index of test case
9873 *
9874 * @return true when tested stage is compute
9875 **/
9876 bool UniformBlockMemberOverlappingOffsetsTest::isComputeRelevant(GLuint test_case_index)
9877 {
9878 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9879 }
9880
9881 /** Checks if stage is supported
9882 *
9883 * @param stage ignored
9884 *
9885 * @return true
9886 **/
9887 bool UniformBlockMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9888 {
9889 return true;
9890 }
9891
9892 /** Prepare all test cases
9893 *
9894 **/
9895 void UniformBlockMemberOverlappingOffsetsTest::testInit()
9896 {
9897 const GLuint n_types = getTypesNumber();
9898 bool stage_support[Utils::Shader::STAGE_MAX];
9899
9900 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9901 {
9902 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9903 }
9904
9905 for (GLuint i = 0; i < n_types; ++i)
9906 {
9907 const Utils::Type& boy_type = getType(i);
9908 const GLuint boy_size = boy_type.GetActualAlignment(1 /* align */, false /* is_array*/);
9909
9910 for (GLuint j = 0; j < n_types; ++j)
9911 {
9912 const Utils::Type& man_type = getType(j);
9913 const GLuint man_align = man_type.GetBaseAlignment(false);
9914 const GLuint man_size = man_type.GetActualAlignment(1 /* align */, false /* is_array*/);
9915
9916 const GLuint boy_offset = lcm(boy_size, man_size);
9917 const GLuint man_after_start = boy_offset + 1;
9918 const GLuint man_after_off = man_type.GetActualOffset(man_after_start, man_size);
9919 const GLuint man_before_start = boy_offset - man_align;
9920 const GLuint man_before_off = man_type.GetActualOffset(man_before_start, man_size);
9921
9922 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9923 {
9924 if (false == stage_support[stage])
9925 {
9926 continue;
9927 }
9928
9929 if ((boy_offset > man_before_off) && (boy_offset < man_before_off + man_size))
9930 {
9931 testCase test_case = { boy_offset, boy_type, man_before_off, man_type,
9932 (Utils::Shader::STAGES)stage };
9933
9934 m_test_cases.push_back(test_case);
9935 }
9936
9937 if ((boy_offset < man_after_off) && (boy_offset + boy_size > man_after_off))
9938 {
9939 testCase test_case = { boy_offset, boy_type, man_after_off, man_type,
9940 (Utils::Shader::STAGES)stage };
9941
9942 m_test_cases.push_back(test_case);
9943 }
9944
9945 /* Boy offset, should be fine for both types */
9946 testCase test_case = { boy_offset, boy_type, boy_offset, man_type, (Utils::Shader::STAGES)stage };
9947
9948 m_test_cases.push_back(test_case);
9949 }
9950 }
9951 }
9952 }
9953
9954 /** Find greatest common divisor for a and b
9955 *
9956 * @param a A argument
9957 * @param b B argument
9958 *
9959 * @return Found gcd value
9960 **/
9961 GLuint UniformBlockMemberOverlappingOffsetsTest::gcd(GLuint a, GLuint b)
9962 {
9963 if ((0 != a) && (0 == b))
9964 {
9965 return a;
9966 }
9967 else
9968 {
9969 GLuint greater = std::max(a, b);
9970 GLuint lesser = std::min(a, b);
9971
9972 return gcd(lesser, greater % lesser);
9973 }
9974 }
9975
9976 /** Find lowest common multiple for a and b
9977 *
9978 * @param a A argument
9979 * @param b B argument
9980 *
9981 * @return Found gcd value
9982 **/
9983 GLuint UniformBlockMemberOverlappingOffsetsTest::lcm(GLuint a, GLuint b)
9984 {
9985 return (a * b) / gcd(a, b);
9986 }
9987
9988 /** Constructor
9989 *
9990 * @param context Test framework context
9991 **/
9992 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context)
9993 : NegativeTestBase(context, "uniform_block_member_align_non_power_of_2",
9994 "Test verifies that align qualifier requires value that is a power of 2")
9995 {
9996 /* Nothing to be done here */
9997 }
9998
9999 /** Constructor
10000 *
10001 * @param context Test framework context
10002 * @param name Test name
10003 * @param description Test description
10004 **/
10005 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context,
10006 const glw::GLchar* name,
10007 const glw::GLchar* description)
10008 : NegativeTestBase(context, name, description)
10009 {
10010 /* Nothing to be done here */
10011 }
10012
10013 /** Source for given test case and stage
10014 *
10015 * @param test_case_index Index of test case
10016 * @param stage Shader stage
10017 *
10018 * @return Shader source
10019 **/
10020 std::string UniformBlockMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10021 {
10022 static const GLchar* cs = "#version 430 core\n"
10023 "#extension GL_ARB_enhanced_layouts : require\n"
10024 "\n"
10025 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10026 "\n"
10027 "layout (std140) uniform Block {\n"
10028 " vec4 boy;\n"
10029 " layout (align = ALIGN) TYPE man;\n"
10030 "} block;\n"
10031 "\n"
10032 "writeonly uniform image2D uni_image;\n"
10033 "\n"
10034 "void main()\n"
10035 "{\n"
10036 " vec4 result = vec4(1, 0, 0.5, 1);\n"
10037 "\n"
10038 " if (TYPE(0) == block.man)\n"
10039 " {\n"
10040 " result = vec4(1, 1, 1, 1) - block.boy;\n"
10041 " }\n"
10042 "\n"
10043 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10044 "}\n"
10045 "\n";
10046 static const GLchar* fs = "#version 430 core\n"
10047 "#extension GL_ARB_enhanced_layouts : require\n"
10048 "\n"
10049 "in vec4 gs_fs;\n"
10050 "out vec4 fs_out;\n"
10051 "\n"
10052 "void main()\n"
10053 "{\n"
10054 " fs_out = gs_fs;\n"
10055 "}\n"
10056 "\n";
10057 static const GLchar* fs_tested = "#version 430 core\n"
10058 "#extension GL_ARB_enhanced_layouts : require\n"
10059 "\n"
10060 "layout (std140) uniform Block {\n"
10061 " vec4 boy;\n"
10062 " layout (align = ALIGN) TYPE man;\n"
10063 "} block;\n"
10064 "\n"
10065 "in vec4 gs_fs;\n"
10066 "out vec4 fs_out;\n"
10067 "\n"
10068 "void main()\n"
10069 "{\n"
10070 " if (TYPE(0) == block.man)\n"
10071 " {\n"
10072 " fs_out = block.boy;\n"
10073 " }\n"
10074 "\n"
10075 " fs_out += gs_fs;\n"
10076 "}\n"
10077 "\n";
10078 static const GLchar* gs = "#version 430 core\n"
10079 "#extension GL_ARB_enhanced_layouts : require\n"
10080 "\n"
10081 "layout(points) in;\n"
10082 "layout(triangle_strip, max_vertices = 4) out;\n"
10083 "\n"
10084 "in vec4 tes_gs[];\n"
10085 "out vec4 gs_fs;\n"
10086 "\n"
10087 "void main()\n"
10088 "{\n"
10089 " gs_fs = tes_gs[0];\n"
10090 " gl_Position = vec4(-1, -1, 0, 1);\n"
10091 " EmitVertex();\n"
10092 " gs_fs = tes_gs[0];\n"
10093 " gl_Position = vec4(-1, 1, 0, 1);\n"
10094 " EmitVertex();\n"
10095 " gs_fs = tes_gs[0];\n"
10096 " gl_Position = vec4(1, -1, 0, 1);\n"
10097 " EmitVertex();\n"
10098 " gs_fs = tes_gs[0];\n"
10099 " gl_Position = vec4(1, 1, 0, 1);\n"
10100 " EmitVertex();\n"
10101 "}\n"
10102 "\n";
10103 static const GLchar* gs_tested = "#version 430 core\n"
10104 "#extension GL_ARB_enhanced_layouts : require\n"
10105 "\n"
10106 "layout(points) in;\n"
10107 "layout(triangle_strip, max_vertices = 4) out;\n"
10108 "\n"
10109 "layout (std140) uniform Block {\n"
10110 " vec4 boy;\n"
10111 " layout (align = ALIGN) TYPE man;\n"
10112 "} block;\n"
10113 "\n"
10114 "in vec4 tes_gs[];\n"
10115 "out vec4 gs_fs;\n"
10116 "\n"
10117 "void main()\n"
10118 "{\n"
10119 " if (TYPE(0) == block.man)\n"
10120 " {\n"
10121 " gs_fs = block.boy;\n"
10122 " }\n"
10123 "\n"
10124 " gs_fs += tes_gs[0];\n"
10125 " gl_Position = vec4(-1, -1, 0, 1);\n"
10126 " EmitVertex();\n"
10127 " gs_fs += tes_gs[0];\n"
10128 " gl_Position = vec4(-1, 1, 0, 1);\n"
10129 " EmitVertex();\n"
10130 " gs_fs += tes_gs[0];\n"
10131 " gl_Position = vec4(1, -1, 0, 1);\n"
10132 " EmitVertex();\n"
10133 " gs_fs += tes_gs[0];\n"
10134 " gl_Position = vec4(1, 1, 0, 1);\n"
10135 " EmitVertex();\n"
10136 "}\n"
10137 "\n";
10138 static const GLchar* tcs = "#version 430 core\n"
10139 "#extension GL_ARB_enhanced_layouts : require\n"
10140 "\n"
10141 "layout(vertices = 1) out;\n"
10142 "\n"
10143 "in vec4 vs_tcs[];\n"
10144 "out vec4 tcs_tes[];\n"
10145 "\n"
10146 "void main()\n"
10147 "{\n"
10148 "\n"
10149 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
10150 "\n"
10151 " gl_TessLevelOuter[0] = 1.0;\n"
10152 " gl_TessLevelOuter[1] = 1.0;\n"
10153 " gl_TessLevelOuter[2] = 1.0;\n"
10154 " gl_TessLevelOuter[3] = 1.0;\n"
10155 " gl_TessLevelInner[0] = 1.0;\n"
10156 " gl_TessLevelInner[1] = 1.0;\n"
10157 "}\n"
10158 "\n";
10159 static const GLchar* tcs_tested = "#version 430 core\n"
10160 "#extension GL_ARB_enhanced_layouts : require\n"
10161 "\n"
10162 "layout(vertices = 1) out;\n"
10163 "\n"
10164 "layout (std140) uniform Block {\n"
10165 " vec4 boy;\n"
10166 " layout (align = ALIGN) TYPE man;\n"
10167 "} block;\n"
10168 "\n"
10169 "in vec4 vs_tcs[];\n"
10170 "out vec4 tcs_tes[];\n"
10171 "\n"
10172 "void main()\n"
10173 "{\n"
10174 " if (TYPE(0) == block.man)\n"
10175 " {\n"
10176 " tcs_tes[gl_InvocationID] = block.boy;\n"
10177 " }\n"
10178 "\n"
10179 "\n"
10180 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
10181 "\n"
10182 " gl_TessLevelOuter[0] = 1.0;\n"
10183 " gl_TessLevelOuter[1] = 1.0;\n"
10184 " gl_TessLevelOuter[2] = 1.0;\n"
10185 " gl_TessLevelOuter[3] = 1.0;\n"
10186 " gl_TessLevelInner[0] = 1.0;\n"
10187 " gl_TessLevelInner[1] = 1.0;\n"
10188 "}\n"
10189 "\n";
10190 static const GLchar* tes = "#version 430 core\n"
10191 "#extension GL_ARB_enhanced_layouts : require\n"
10192 "\n"
10193 "layout(isolines, point_mode) in;\n"
10194 "\n"
10195 "in vec4 tcs_tes[];\n"
10196 "out vec4 tes_gs;\n"
10197 "\n"
10198 "void main()\n"
10199 "{\n"
10200 " tes_gs = tcs_tes[0];\n"
10201 "}\n"
10202 "\n";
10203 static const GLchar* tes_tested = "#version 430 core\n"
10204 "#extension GL_ARB_enhanced_layouts : require\n"
10205 "\n"
10206 "layout(isolines, point_mode) in;\n"
10207 "\n"
10208 "layout (std140) uniform Block {\n"
10209 " vec4 boy;\n"
10210 " layout (align = ALIGN) TYPE man;\n"
10211 "} block;\n"
10212 "\n"
10213 "in vec4 tcs_tes[];\n"
10214 "out vec4 tes_gs;\n"
10215 "\n"
10216 "void main()\n"
10217 "{\n"
10218 " if (TYPE(0) == block.man)\n"
10219 " {\n"
10220 " tes_gs = block.boy;\n"
10221 " }\n"
10222 "\n"
10223 " tes_gs += tcs_tes[0];\n"
10224 "}\n"
10225 "\n";
10226 static const GLchar* vs = "#version 430 core\n"
10227 "#extension GL_ARB_enhanced_layouts : require\n"
10228 "\n"
10229 "in vec4 in_vs;\n"
10230 "out vec4 vs_tcs;\n"
10231 "\n"
10232 "void main()\n"
10233 "{\n"
10234 " vs_tcs = in_vs;\n"
10235 "}\n"
10236 "\n";
10237 static const GLchar* vs_tested = "#version 430 core\n"
10238 "#extension GL_ARB_enhanced_layouts : require\n"
10239 "\n"
10240 "layout (std140) uniform Block {\n"
10241 " vec4 boy;\n"
10242 " layout (align = ALIGN) TYPE man;\n"
10243 "} block;\n"
10244 "\n"
10245 "in vec4 in_vs;\n"
10246 "out vec4 vs_tcs;\n"
10247 "\n"
10248 "void main()\n"
10249 "{\n"
10250 " if (TYPE(0) == block.man)\n"
10251 " {\n"
10252 " vs_tcs = block.boy;\n"
10253 " }\n"
10254 "\n"
10255 " vs_tcs += in_vs;\n"
10256 "}\n"
10257 "\n";
10258
10259 std::string source;
10260 testCase& test_case = m_test_cases[test_case_index];
10261
10262 if (test_case.m_stage == stage)
10263 {
10264 GLchar buffer[16];
10265 const GLuint alignment = test_case.m_alignment;
10266 const Utils::Type& type = test_case.m_type;
10267 const GLchar* type_name = type.GetGLSLTypeName();
10268 size_t position = 0;
10269
10270 switch (stage)
10271 {
10272 case Utils::Shader::COMPUTE:
10273 source = cs;
10274 break;
10275 case Utils::Shader::FRAGMENT:
10276 source = fs_tested;
10277 break;
10278 case Utils::Shader::GEOMETRY:
10279 source = gs_tested;
10280 break;
10281 case Utils::Shader::TESS_CTRL:
10282 source = tcs_tested;
10283 break;
10284 case Utils::Shader::TESS_EVAL:
10285 source = tes_tested;
10286 break;
10287 case Utils::Shader::VERTEX:
10288 source = vs_tested;
10289 break;
10290 default:
10291 TCU_FAIL("Invalid enum");
10292 }
10293
10294 sprintf(buffer, "%d", alignment);
10295 Utils::replaceToken("ALIGN", position, buffer, source);
10296 Utils::replaceToken("TYPE", position, type_name, source);
10297 Utils::replaceToken("TYPE", position, type_name, source);
10298 }
10299 else
10300 {
10301 switch (stage)
10302 {
10303 case Utils::Shader::FRAGMENT:
10304 source = fs;
10305 break;
10306 case Utils::Shader::GEOMETRY:
10307 source = gs;
10308 break;
10309 case Utils::Shader::TESS_CTRL:
10310 source = tcs;
10311 break;
10312 case Utils::Shader::TESS_EVAL:
10313 source = tes;
10314 break;
10315 case Utils::Shader::VERTEX:
10316 source = vs;
10317 break;
10318 default:
10319 TCU_FAIL("Invalid enum");
10320 }
10321 }
10322
10323 return source;
10324 }
10325
10326 /** Get description of test case
10327 *
10328 * @param test_case_index Index of test case
10329 *
10330 * @return Type name and offset
10331 **/
10332 std::string UniformBlockMemberAlignNonPowerOf2Test::getTestCaseName(GLuint test_case_index)
10333 {
10334 std::stringstream stream;
10335 testCase& test_case = m_test_cases[test_case_index];
10336
10337 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", align: " << test_case.m_alignment;
10338
10339 return stream.str();
10340 }
10341
10342 /** Get number of test cases
10343 *
10344 * @return Number of test cases
10345 **/
10346 GLuint UniformBlockMemberAlignNonPowerOf2Test::getTestCaseNumber()
10347 {
10348 return static_cast<GLuint>(m_test_cases.size());
10349 }
10350
10351 /** Selects if "compute" stage is relevant for test
10352 *
10353 * @param test_case_index Index of test case
10354 *
10355 * @return true when tested stage is compute
10356 **/
10357 bool UniformBlockMemberAlignNonPowerOf2Test::isComputeRelevant(GLuint test_case_index)
10358 {
10359 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
10360 }
10361
10362 /** Checks if stage is supported
10363 *
10364 * @param ignored
10365 *
10366 * @return true
10367 **/
10368 bool UniformBlockMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES /* stage */)
10369 {
10370 return true;
10371 }
10372
10373 /** Selects if compilation failure is expected result
10374 *
10375 * @param test_case_index Index of test case
10376 *
10377 * @return should_fail field from testCase
10378 **/
10379 bool UniformBlockMemberAlignNonPowerOf2Test::isFailureExpected(GLuint test_case_index)
10380 {
10381 return m_test_cases[test_case_index].m_should_fail;
10382 }
10383
10384 /** Prepare all test cases
10385 *
10386 **/
10387 void UniformBlockMemberAlignNonPowerOf2Test::testInit()
10388 {
10389 static const GLuint dmat4_size = 128;
10390 const GLuint n_types = getTypesNumber();
10391 bool stage_support[Utils::Shader::STAGE_MAX];
10392
10393 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10394 {
10395 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
10396 }
10397
10398 for (GLuint j = 0; j < n_types; ++j)
10399 {
10400 const Utils::Type& type = getType(j);
10401
10402 for (GLuint align = 0; align <= dmat4_size; ++align)
10403 {
10404
10405 #if WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST
10406
10407 const bool should_fail = (0 == align) ? false : !isPowerOf2(align);
10408
10409 #else /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10410
10411 const bool should_fail = !isPowerOf2(align);
10412
10413 #endif /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10414
10415 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10416 {
10417 if (false == stage_support[stage])
10418 {
10419 continue;
10420 }
10421
10422 testCase test_case = { align, type, should_fail, (Utils::Shader::STAGES)stage };
10423
10424 m_test_cases.push_back(test_case);
10425 }
10426 }
10427 }
10428 }
10429
10430 /** Check if value is power of 2
10431 *
10432 * @param val Tested value
10433 *
10434 * @return true if val is power of 2, false otherwise
10435 **/
10436 bool UniformBlockMemberAlignNonPowerOf2Test::isPowerOf2(GLuint val)
10437 {
10438 if (0 == val)
10439 {
10440 return false;
10441 }
10442
10443 return (0 == (val & (val - 1)));
10444 }
10445
10446 /** Constructor
10447 *
10448 * @param context Test framework context
10449 **/
10450 UniformBlockAlignmentTest::UniformBlockAlignmentTest(deqp::Context& context)
10451 : TextureTestBase(context, "uniform_block_alignment", "Test verifies offset and alignment of uniform buffer")
10452 {
10453 }
10454
10455 /** Get interface of program
10456 *
10457 * @param ignored
10458 * @param program_interface Interface of program
10459 * @param varying_passthrough Collection of connections between in and out variables
10460 **/
10461 void UniformBlockAlignmentTest::getProgramInterface(GLuint /* test_case_index */,
10462 Utils::ProgramInterface& program_interface,
10463 Utils::VaryingPassthrough& varying_passthrough)
10464 {
10465 static const Utils::Type vec4 = Utils::Type::vec4;
10466
10467 #if WRKARD_UNIFORMBLOCKALIGNMENT
10468
10469 static const GLuint block_align = 16;
10470
10471 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10472
10473 static const GLuint block_align = 64;
10474
10475 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10476
10477 static const GLuint vec4_stride = 16;
10478 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
10479
10480 /*Fixed a test issue, the fifth_offset should be calculated by block_align, instead of fifth_align, according to spec, the actual
10481 alignment of a member will be the greater of the specified alignment and the base aligment for the member type
10482 */
10483 const GLuint first_offset = 0; /* vec4 at 0 */
10484 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
10485 const GLuint third_offset =
10486 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
10487 const GLuint fourth_offset =
10488 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
10489 const GLuint fifth_offset =
10490 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, block_align); /* vec4[2] at 160 */
10491 const GLuint sixth_offset =
10492 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
10493
10494 Utils::Interface* structure = program_interface.Structure("Data");
10495
10496 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10497 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
10498
10499 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
10500 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
10501 Utils::Type::vec4.GetSize() /* offset */);
10502
10503 /* Prepare Block */
10504 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
10505
10506 vs_uni_block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10507 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
10508
10509 vs_uni_block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10510 0 /* n_array_elements */, data_stride, second_offset);
10511
10512 vs_uni_block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10513 2 /* n_array_elements */, data_stride, third_offset);
10514
10515 vs_uni_block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
10516 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
10517
10518 vs_uni_block->Member("fifth", "layout(align = 64)", 0 /* expected_component */, 0 /* expected_location */, vec4,
10519 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
10520
10521 vs_uni_block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10522 0 /* n_array_elements */, data_stride, sixth_offset);
10523
10524 const GLuint stride = calculateStride(*vs_uni_block);
10525 m_data.resize(stride);
10526 generateData(*vs_uni_block, 0, m_data);
10527
10528 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10529
10530 /* Add uniform BLOCK */
10531 #if WRKARD_UNIFORMBLOCKALIGNMENT
10532 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
10533 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10534 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10535 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_uni_block, 0,
10536 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10537 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10538
10539 program_interface.CloneVertexInterface(varying_passthrough);
10540 }
10541
10542 /** Constructor
10543 *
10544 * @param context Test framework context
10545 **/
10546 SSBMemberOffsetAndAlignTest::SSBMemberOffsetAndAlignTest(deqp::Context& context)
10547 : TextureTestBase(context, "ssb_member_offset_and_align",
10548 "Test verifies offsets and alignment of storage buffer members")
10549 {
10550 }
10551
10552 /** Get interface of program
10553 *
10554 * @param test_case_index Test case index
10555 * @param program_interface Interface of program
10556 * @param varying_passthrough Collection of connections between in and out variables
10557 **/
10558 void SSBMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
10559 Utils::ProgramInterface& program_interface,
10560 Utils::VaryingPassthrough& varying_passthrough)
10561 {
10562 std::string globals = "const int basic_size = BASIC_SIZE;\n"
10563 "const int type_align = TYPE_ALIGN;\n"
10564 "const int type_size = TYPE_SIZE;\n";
10565
10566 Utils::Type type = getType(test_case_index);
10567 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
10568 const GLuint base_align = type.GetBaseAlignment(false);
10569 const GLuint array_align = type.GetBaseAlignment(true);
10570 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
10571 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
10572
10573 /* Calculate offsets */
10574 const GLuint first_offset = 0;
10575 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
10576
10577 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
10578
10579 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
10580 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
10581 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10582 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10583 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10584 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
10585
10586 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10587
10588 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
10589 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
10590 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10591 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10592 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10593 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
10594
10595 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10596
10597 /* Prepare data */
10598 const std::vector<GLubyte>& first = type.GenerateData();
10599 const std::vector<GLubyte>& second = type.GenerateData();
10600 const std::vector<GLubyte>& third = type.GenerateData();
10601 const std::vector<GLubyte>& fourth = type.GenerateData();
10602
10603 m_data.resize(eigth_offset + base_stride);
10604 GLubyte* ptr = &m_data[0];
10605 memcpy(ptr + first_offset, &first[0], first.size());
10606 memcpy(ptr + second_offset, &second[0], second.size());
10607 memcpy(ptr + third_offset, &third[0], third.size());
10608 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
10609 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
10610 memcpy(ptr + sixth_offset, &third[0], third.size());
10611 memcpy(ptr + seventh_offset, &second[0], second.size());
10612 memcpy(ptr + eigth_offset, &first[0], first.size());
10613
10614 /* Prepare globals */
10615 size_t position = 0;
10616 GLchar buffer[16];
10617
10618 sprintf(buffer, "%d", basic_size);
10619 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
10620
10621 sprintf(buffer, "%d", type_align);
10622 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
10623
10624 sprintf(buffer, "%d", base_stride);
10625 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
10626
10627 /* Prepare Block */
10628 Utils::Interface* vs_buf_block = program_interface.Block("vs_buf_Block");
10629
10630 vs_buf_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
10631 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10632 first_offset);
10633
10634 vs_buf_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
10635 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
10636 0 /* n_array_elements */, base_stride, second_offset);
10637
10638 vs_buf_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
10639 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10640 third_offset);
10641
10642 vs_buf_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
10643 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10644 fourth_offset);
10645
10646 vs_buf_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10647 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
10648
10649 vs_buf_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10650 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
10651
10652 vs_buf_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
10653 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10654 eigth_offset);
10655
10656 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10657
10658 /* Add globals */
10659 vs_si.m_globals = globals;
10660
10661 /* Add uniform BLOCK */
10662 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_block, 0,
10663 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10664
10665 /* */
10666 program_interface.CloneVertexInterface(varying_passthrough);
10667 }
10668
10669 /** Get type name
10670 *
10671 * @param test_case_index Index of test case
10672 *
10673 * @return Name of type test in test_case_index
10674 **/
10675 std::string SSBMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
10676 {
10677 return getTypeName(test_case_index);
10678 }
10679
10680 /** Returns number of types to test
10681 *
10682 * @return Number of types, 34
10683 **/
10684 glw::GLuint SSBMemberOffsetAndAlignTest::getTestCaseNumber()
10685 {
10686 return getTypesNumber();
10687 }
10688
10689 /** Prepare code snippet that will verify in and uniform variables
10690 *
10691 * @param ignored
10692 * @param ignored
10693 * @param stage Shader stage
10694 *
10695 * @return Code that verify variables
10696 **/
10697 std::string SSBMemberOffsetAndAlignTest::getVerificationSnippet(GLuint /* test_case_index */,
10698 Utils::ProgramInterface& /* program_interface */,
10699 Utils::Shader::STAGES stage)
10700 {
10701 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
10702 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
10703 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
10704 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
10705 " {\n"
10706 " result = 0;\n"
10707 " }";
10708
10709 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::SSB);
10710
10711 Utils::replaceAllTokens("PREFIX", prefix, verification);
10712
10713 return verification;
10714 }
10715
10716 /** Selects if "draw" stages are relevant for test
10717 *
10718 * @param ignored
10719 *
10720 * @return true if all stages support shader storage buffers, false otherwise
10721 **/
10722 bool SSBMemberOffsetAndAlignTest::isDrawRelevant(GLuint /* test_case_index */)
10723 {
10724 const Functions& gl = m_context.getRenderContext().getFunctions();
10725 GLint gs_supported_buffers = 0;
10726 GLint tcs_supported_buffers = 0;
10727 GLint tes_supported_buffers = 0;
10728 GLint vs_supported_buffers = 0;
10729
10730 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
10731 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
10732 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
10733 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
10734
10735 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
10736
10737 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
10738 (1 <= vs_supported_buffers));
10739 }
10740
10741 /** Constructor
10742 *
10743 * @param context Test framework context
10744 **/
10745 SSBLayoutQualifierConflictTest::SSBLayoutQualifierConflictTest(deqp::Context& context)
10746 : NegativeTestBase(context, "ssb_layout_qualifier_conflict", "Test verifies that std140 or std430 is required when "
10747 "offset and/or align qualifiers are used with storage "
10748 "block")
10749 {
10750 /* Nothing to be done here */
10751 }
10752
10753 /** Source for given test case and stage
10754 *
10755 * @param test_case_index Index of test case
10756 * @param stage Shader stage
10757 *
10758 * @return Shader source
10759 **/
10760 std::string SSBLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10761 {
10762 static const GLchar* cs = "#version 430 core\n"
10763 "#extension GL_ARB_enhanced_layouts : require\n"
10764 "\n"
10765 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10766 "\n"
10767 "layout (QUALIFIERbinding = BINDING) buffer cs_Block {\n"
10768 " layout(offset = 16) vec4 boy;\n"
10769 " layout(align = 64) vec4 man;\n"
10770 "} uni_block;\n"
10771 "\n"
10772 "writeonly uniform image2D uni_image;\n"
10773 "\n"
10774 "void main()\n"
10775 "{\n"
10776 " vec4 result = uni_block.boy + uni_block.man;\n"
10777 "\n"
10778 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10779 "}\n"
10780 "\n";
10781 static const GLchar* fs = "#version 430 core\n"
10782 "#extension GL_ARB_enhanced_layouts : require\n"
10783 "\n"
10784 "layout (QUALIFIERbinding = BINDING) buffer Block {\n"
10785 " layout(offset = 16) vec4 boy;\n"
10786 " layout(align = 64) vec4 man;\n"
10787 "} uni_block;\n"
10788 "\n"
10789 "in vec4 gs_fs;\n"
10790 "out vec4 fs_out;\n"
10791 "\n"
10792 "void main()\n"
10793 "{\n"
10794 " fs_out = gs_fs + uni_block.boy + uni_block.man;\n"
10795 "}\n"
10796 "\n";
10797 static const GLchar* gs = "#version 430 core\n"
10798 "#extension GL_ARB_enhanced_layouts : require\n"
10799 "\n"
10800 "layout(points) in;\n"
10801 "layout(triangle_strip, max_vertices = 4) out;\n"
10802 "\n"
10803 "layout (QUALIFIERbinding = BINDING) buffer gs_Block {\n"
10804 " layout(offset = 16) vec4 boy;\n"
10805 " layout(align = 64) vec4 man;\n"
10806 "} uni_block;\n"
10807 "\n"
10808 "in vec4 tes_gs[];\n"
10809 "out vec4 gs_fs;\n"
10810 "\n"
10811 "void main()\n"
10812 "{\n"
10813 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10814 " gl_Position = vec4(-1, -1, 0, 1);\n"
10815 " EmitVertex();\n"
10816 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10817 " gl_Position = vec4(-1, 1, 0, 1);\n"
10818 " EmitVertex();\n"
10819 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10820 " gl_Position = vec4(1, -1, 0, 1);\n"
10821 " EmitVertex();\n"
10822 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10823 " gl_Position = vec4(1, 1, 0, 1);\n"
10824 " EmitVertex();\n"
10825 "}\n"
10826 "\n";
10827 static const GLchar* tcs =
10828 "#version 430 core\n"
10829 "#extension GL_ARB_enhanced_layouts : require\n"
10830 "\n"
10831 "layout(vertices = 1) out;\n"
10832 "\n"
10833 "layout (QUALIFIERbinding = BINDING) buffer tcs_Block {\n"
10834 " layout(offset = 16) vec4 boy;\n"
10835 " layout(align = 64) vec4 man;\n"
10836 "} uni_block;\n"
10837 "\n"
10838 "in vec4 vs_tcs[];\n"
10839 "out vec4 tcs_tes[];\n"
10840 "\n"
10841 "void main()\n"
10842 "{\n"
10843 "\n"
10844 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.boy + uni_block.man;\n"
10845 "\n"
10846 " gl_TessLevelOuter[0] = 1.0;\n"
10847 " gl_TessLevelOuter[1] = 1.0;\n"
10848 " gl_TessLevelOuter[2] = 1.0;\n"
10849 " gl_TessLevelOuter[3] = 1.0;\n"
10850 " gl_TessLevelInner[0] = 1.0;\n"
10851 " gl_TessLevelInner[1] = 1.0;\n"
10852 "}\n"
10853 "\n";
10854 static const GLchar* tes = "#version 430 core\n"
10855 "#extension GL_ARB_enhanced_layouts : require\n"
10856 "\n"
10857 "layout(isolines, point_mode) in;\n"
10858 "\n"
10859 "layout (QUALIFIERbinding = BINDING) buffer tes_Block {\n"
10860 " layout(offset = 16) vec4 boy;\n"
10861 " layout(align = 64) vec4 man;\n"
10862 "} uni_block;\n"
10863 "\n"
10864 "in vec4 tcs_tes[];\n"
10865 "out vec4 tes_gs;\n"
10866 "\n"
10867 "void main()\n"
10868 "{\n"
10869 " tes_gs = tcs_tes[0] + uni_block.boy + uni_block.man;\n"
10870 "}\n"
10871 "\n";
10872 static const GLchar* vs = "#version 430 core\n"
10873 "#extension GL_ARB_enhanced_layouts : require\n"
10874 "\n"
10875 "layout (QUALIFIERbinding = BINDING) buffer vs_Block {\n"
10876 " layout(offset = 16) vec4 boy;\n"
10877 " layout(align = 64) vec4 man;\n"
10878 "} uni_block;\n"
10879 "\n"
10880 "in vec4 in_vs;\n"
10881 "out vec4 vs_tcs;\n"
10882 "\n"
10883 "void main()\n"
10884 "{\n"
10885 " vs_tcs = in_vs + uni_block.boy + uni_block.man;\n"
10886 "}\n"
10887 "\n";
10888
10889 GLchar buffer[16];
10890 size_t position = 0;
10891 std::string source;
10892 testCase& test_case = m_test_cases[test_case_index];
10893 std::string qualifier = getQualifierName(test_case.m_qualifier);
10894
10895 if (false == qualifier.empty())
10896 {
10897 qualifier.append(", ");
10898 }
10899
10900 sprintf(buffer, "%d", stage);
10901
10902 switch (stage)
10903 {
10904 case Utils::Shader::COMPUTE:
10905 source = cs;
10906 break;
10907 case Utils::Shader::FRAGMENT:
10908 source = fs;
10909 break;
10910 case Utils::Shader::GEOMETRY:
10911 source = gs;
10912 break;
10913 case Utils::Shader::TESS_CTRL:
10914 source = tcs;
10915 break;
10916 case Utils::Shader::TESS_EVAL:
10917 source = tes;
10918 break;
10919 case Utils::Shader::VERTEX:
10920 source = vs;
10921 break;
10922 default:
10923 TCU_FAIL("Invalid enum");
10924 }
10925
10926 if (test_case.m_stage == stage)
10927 {
10928 Utils::replaceToken("QUALIFIER", position, qualifier.c_str(), source);
10929 }
10930 else
10931 {
10932 Utils::replaceToken("QUALIFIER", position, "std140, ", source);
10933 }
10934
10935 Utils::replaceToken("BINDING", position, buffer, source);
10936
10937 return source;
10938 }
10939
10940 /** Get description of test case
10941 *
10942 * @param test_case_index Index of test case
10943 *
10944 * @return Qualifier name
10945 **/
10946 std::string SSBLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
10947 {
10948 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
10949
10950 return result;
10951 }
10952
10953 /** Get number of test cases
10954 *
10955 * @return Number of test cases
10956 **/
10957 GLuint SSBLayoutQualifierConflictTest::getTestCaseNumber()
10958 {
10959 return static_cast<GLuint>(m_test_cases.size());
10960 }
10961
10962 /** Selects if "compute" stage is relevant for test
10963 *
10964 * @param test_case_index Index of test case
10965 *
10966 * @return true when tested stage is compute
10967 **/
10968 bool SSBLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
10969 {
10970 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
10971 }
10972
10973 /** Selects if compilation failure is expected result
10974 *
10975 * @param test_case_index Index of test case
10976 *
10977 * @return false for STD140 and STD430 cases, true otherwise
10978 **/
10979 bool SSBLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
10980 {
10981 const QUALIFIERS qualifier = m_test_cases[test_case_index].m_qualifier;
10982
10983 return !((STD140 == qualifier) || (STD430 == qualifier));
10984 }
10985
10986 /** Checks if stage is supported
10987 *
10988 * @param stage Shader stage
10989 *
10990 * @return true if supported, false otherwise
10991 **/
10992 bool SSBLayoutQualifierConflictTest::isStageSupported(Utils::Shader::STAGES stage)
10993 {
10994 const Functions& gl = m_context.getRenderContext().getFunctions();
10995 GLint max_supported_buffers = 0;
10996 GLenum pname = 0;
10997
10998 switch (stage)
10999 {
11000 case Utils::Shader::COMPUTE:
11001 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11002 break;
11003 case Utils::Shader::FRAGMENT:
11004 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11005 break;
11006 case Utils::Shader::GEOMETRY:
11007 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11008 break;
11009 case Utils::Shader::TESS_CTRL:
11010 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11011 break;
11012 case Utils::Shader::TESS_EVAL:
11013 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11014 break;
11015 case Utils::Shader::VERTEX:
11016 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11017 break;
11018 default:
11019 TCU_FAIL("Invalid enum");
11020 }
11021
11022 gl.getIntegerv(pname, &max_supported_buffers);
11023 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11024
11025 return 1 <= max_supported_buffers;
11026 }
11027
11028 /** Prepare all test cases
11029 *
11030 **/
11031 void SSBLayoutQualifierConflictTest::testInit()
11032 {
11033 bool stage_support[Utils::Shader::STAGE_MAX];
11034
11035 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11036 {
11037 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
11038 }
11039
11040 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
11041 {
11042 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11043 {
11044 if (false == stage_support[stage])
11045 {
11046 continue;
11047 }
11048
11049 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
11050
11051 m_test_cases.push_back(test_case);
11052 }
11053 }
11054 }
11055
11056 /** Get name of glsl constant
11057 *
11058 * @param Constant id
11059 *
11060 * @return Name of constant used in GLSL
11061 **/
11062 const GLchar* SSBLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
11063 {
11064 const GLchar* name = "";
11065
11066 switch (qualifier)
11067 {
11068 case DEFAULT:
11069 name = "";
11070 break;
11071 case STD140:
11072 name = "std140";
11073 break;
11074 case STD430:
11075 name = "std430";
11076 break;
11077 case SHARED:
11078 name = "shared";
11079 break;
11080 case PACKED:
11081 name = "packed";
11082 break;
11083 default:
11084 TCU_FAIL("Invalid enum");
11085 }
11086
11087 return name;
11088 }
11089
11090 /** Constructor
11091 *
11092 * @param context Test framework context
11093 **/
11094 SSBMemberInvalidOffsetAlignmentTest::SSBMemberInvalidOffsetAlignmentTest(deqp::Context& context)
11095 : UniformBlockMemberInvalidOffsetAlignmentTest(
11096 context, "ssb_member_invalid_offset_alignment",
11097 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
11098 {
11099 /* Nothing to be done here */
11100 }
11101
11102 /** Get the maximum size for a shader storage block
11103 *
11104 * @return The maximum size in basic machine units of a shader storage block.
11105 **/
11106 GLint SSBMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
11107 {
11108 const Functions& gl = m_context.getRenderContext().getFunctions();
11109 GLint max_size = 0;
11110
11111 gl.getIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_size);
11112 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11113
11114 return max_size;
11115 }
11116
11117 /** Source for given test case and stage
11118 *
11119 * @param test_case_index Index of test case
11120 * @param stage Shader stage
11121 *
11122 * @return Shader source
11123 **/
11124 std::string SSBMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11125 {
11126 static const GLchar* cs = "#version 430 core\n"
11127 "#extension GL_ARB_enhanced_layouts : require\n"
11128 "\n"
11129 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11130 "\n"
11131 "layout (std140) buffer Block {\n"
11132 " layout (offset = OFFSET) TYPE member;\n"
11133 "} block;\n"
11134 "\n"
11135 "writeonly uniform image2D uni_image;\n"
11136 "\n"
11137 "void main()\n"
11138 "{\n"
11139 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11140 "\n"
11141 " if (TYPE(1) == block.member)\n"
11142 " {\n"
11143 " result = vec4(1, 1, 1, 1);\n"
11144 " }\n"
11145 "\n"
11146 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11147 "}\n"
11148 "\n";
11149 static const GLchar* fs = "#version 430 core\n"
11150 "#extension GL_ARB_enhanced_layouts : require\n"
11151 "\n"
11152 "in vec4 gs_fs;\n"
11153 "out vec4 fs_out;\n"
11154 "\n"
11155 "void main()\n"
11156 "{\n"
11157 " fs_out = gs_fs;\n"
11158 "}\n"
11159 "\n";
11160 static const GLchar* fs_tested = "#version 430 core\n"
11161 "#extension GL_ARB_enhanced_layouts : require\n"
11162 "\n"
11163 "layout (std140) buffer Block {\n"
11164 " layout (offset = OFFSET) TYPE member;\n"
11165 "} block;\n"
11166 "\n"
11167 "in vec4 gs_fs;\n"
11168 "out vec4 fs_out;\n"
11169 "\n"
11170 "void main()\n"
11171 "{\n"
11172 " if (TYPE(1) == block.member)\n"
11173 " {\n"
11174 " fs_out = vec4(1, 1, 1, 1);\n"
11175 " }\n"
11176 "\n"
11177 " fs_out += gs_fs;\n"
11178 "}\n"
11179 "\n";
11180 static const GLchar* gs = "#version 430 core\n"
11181 "#extension GL_ARB_enhanced_layouts : require\n"
11182 "\n"
11183 "layout(points) in;\n"
11184 "layout(triangle_strip, max_vertices = 4) out;\n"
11185 "\n"
11186 "in vec4 tes_gs[];\n"
11187 "out vec4 gs_fs;\n"
11188 "\n"
11189 "void main()\n"
11190 "{\n"
11191 " gs_fs = tes_gs[0];\n"
11192 " gl_Position = vec4(-1, -1, 0, 1);\n"
11193 " EmitVertex();\n"
11194 " gs_fs = tes_gs[0];\n"
11195 " gl_Position = vec4(-1, 1, 0, 1);\n"
11196 " EmitVertex();\n"
11197 " gs_fs = tes_gs[0];\n"
11198 " gl_Position = vec4(1, -1, 0, 1);\n"
11199 " EmitVertex();\n"
11200 " gs_fs = tes_gs[0];\n"
11201 " gl_Position = vec4(1, 1, 0, 1);\n"
11202 " EmitVertex();\n"
11203 "}\n"
11204 "\n";
11205 static const GLchar* gs_tested = "#version 430 core\n"
11206 "#extension GL_ARB_enhanced_layouts : require\n"
11207 "\n"
11208 "layout(points) in;\n"
11209 "layout(triangle_strip, max_vertices = 4) out;\n"
11210 "\n"
11211 "layout (std140) buffer Block {\n"
11212 " layout (offset = OFFSET) TYPE member;\n"
11213 "} block;\n"
11214 "\n"
11215 "in vec4 tes_gs[];\n"
11216 "out vec4 gs_fs;\n"
11217 "\n"
11218 "void main()\n"
11219 "{\n"
11220 " if (TYPE(1) == block.member)\n"
11221 " {\n"
11222 " gs_fs = vec4(1, 1, 1, 1);\n"
11223 " }\n"
11224 "\n"
11225 " gs_fs += tes_gs[0];\n"
11226 " gl_Position = vec4(-1, -1, 0, 1);\n"
11227 " EmitVertex();\n"
11228 " gs_fs += tes_gs[0];\n"
11229 " gl_Position = vec4(-1, 1, 0, 1);\n"
11230 " EmitVertex();\n"
11231 " gs_fs += tes_gs[0];\n"
11232 " gl_Position = vec4(1, -1, 0, 1);\n"
11233 " EmitVertex();\n"
11234 " gs_fs += tes_gs[0];\n"
11235 " gl_Position = vec4(1, 1, 0, 1);\n"
11236 " EmitVertex();\n"
11237 "}\n"
11238 "\n";
11239 static const GLchar* tcs = "#version 430 core\n"
11240 "#extension GL_ARB_enhanced_layouts : require\n"
11241 "\n"
11242 "layout(vertices = 1) out;\n"
11243 "\n"
11244 "in vec4 vs_tcs[];\n"
11245 "out vec4 tcs_tes[];\n"
11246 "\n"
11247 "void main()\n"
11248 "{\n"
11249 "\n"
11250 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11251 "\n"
11252 " gl_TessLevelOuter[0] = 1.0;\n"
11253 " gl_TessLevelOuter[1] = 1.0;\n"
11254 " gl_TessLevelOuter[2] = 1.0;\n"
11255 " gl_TessLevelOuter[3] = 1.0;\n"
11256 " gl_TessLevelInner[0] = 1.0;\n"
11257 " gl_TessLevelInner[1] = 1.0;\n"
11258 "}\n"
11259 "\n";
11260 static const GLchar* tcs_tested = "#version 430 core\n"
11261 "#extension GL_ARB_enhanced_layouts : require\n"
11262 "\n"
11263 "layout(vertices = 1) out;\n"
11264 "\n"
11265 "layout (std140) buffer Block {\n"
11266 " layout (offset = OFFSET) TYPE member;\n"
11267 "} block;\n"
11268 "\n"
11269 "in vec4 vs_tcs[];\n"
11270 "out vec4 tcs_tes[];\n"
11271 "\n"
11272 "void main()\n"
11273 "{\n"
11274 " if (TYPE(1) == block.member)\n"
11275 " {\n"
11276 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11277 " }\n"
11278 "\n"
11279 "\n"
11280 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11281 "\n"
11282 " gl_TessLevelOuter[0] = 1.0;\n"
11283 " gl_TessLevelOuter[1] = 1.0;\n"
11284 " gl_TessLevelOuter[2] = 1.0;\n"
11285 " gl_TessLevelOuter[3] = 1.0;\n"
11286 " gl_TessLevelInner[0] = 1.0;\n"
11287 " gl_TessLevelInner[1] = 1.0;\n"
11288 "}\n"
11289 "\n";
11290 static const GLchar* tes = "#version 430 core\n"
11291 "#extension GL_ARB_enhanced_layouts : require\n"
11292 "\n"
11293 "layout(isolines, point_mode) in;\n"
11294 "\n"
11295 "in vec4 tcs_tes[];\n"
11296 "out vec4 tes_gs;\n"
11297 "\n"
11298 "void main()\n"
11299 "{\n"
11300 " tes_gs = tcs_tes[0];\n"
11301 "}\n"
11302 "\n";
11303 static const GLchar* tes_tested = "#version 430 core\n"
11304 "#extension GL_ARB_enhanced_layouts : require\n"
11305 "\n"
11306 "layout(isolines, point_mode) in;\n"
11307 "\n"
11308 "layout (std140) buffer Block {\n"
11309 " layout (offset = OFFSET) TYPE member;\n"
11310 "} block;\n"
11311 "\n"
11312 "in vec4 tcs_tes[];\n"
11313 "out vec4 tes_gs;\n"
11314 "\n"
11315 "void main()\n"
11316 "{\n"
11317 " if (TYPE(1) == block.member)\n"
11318 " {\n"
11319 " tes_gs = vec4(1, 1, 1, 1);\n"
11320 " }\n"
11321 "\n"
11322 " tes_gs += tcs_tes[0];\n"
11323 "}\n"
11324 "\n";
11325 static const GLchar* vs = "#version 430 core\n"
11326 "#extension GL_ARB_enhanced_layouts : require\n"
11327 "\n"
11328 "in vec4 in_vs;\n"
11329 "out vec4 vs_tcs;\n"
11330 "\n"
11331 "void main()\n"
11332 "{\n"
11333 " vs_tcs = in_vs;\n"
11334 "}\n"
11335 "\n";
11336 static const GLchar* vs_tested = "#version 430 core\n"
11337 "#extension GL_ARB_enhanced_layouts : require\n"
11338 "\n"
11339 "layout (std140) buffer Block {\n"
11340 " layout (offset = OFFSET) TYPE member;\n"
11341 "} block;\n"
11342 "\n"
11343 "in vec4 in_vs;\n"
11344 "out vec4 vs_tcs;\n"
11345 "\n"
11346 "void main()\n"
11347 "{\n"
11348 " if (TYPE(1) == block.member)\n"
11349 " {\n"
11350 " vs_tcs = vec4(1, 1, 1, 1);\n"
11351 " }\n"
11352 "\n"
11353 " vs_tcs += in_vs;\n"
11354 "}\n"
11355 "\n";
11356
11357 std::string source;
11358 testCase& test_case = m_test_cases[test_case_index];
11359
11360 if (test_case.m_stage == stage)
11361 {
11362 GLchar buffer[16];
11363 const GLuint offset = test_case.m_offset;
11364 size_t position = 0;
11365 const Utils::Type& type = test_case.m_type;
11366 const GLchar* type_name = type.GetGLSLTypeName();
11367
11368 sprintf(buffer, "%d", offset);
11369
11370 switch (stage)
11371 {
11372 case Utils::Shader::COMPUTE:
11373 source = cs;
11374 break;
11375 case Utils::Shader::FRAGMENT:
11376 source = fs_tested;
11377 break;
11378 case Utils::Shader::GEOMETRY:
11379 source = gs_tested;
11380 break;
11381 case Utils::Shader::TESS_CTRL:
11382 source = tcs_tested;
11383 break;
11384 case Utils::Shader::TESS_EVAL:
11385 source = tes_tested;
11386 break;
11387 case Utils::Shader::VERTEX:
11388 source = vs_tested;
11389 break;
11390 default:
11391 TCU_FAIL("Invalid enum");
11392 }
11393
11394 Utils::replaceToken("OFFSET", position, buffer, source);
11395 Utils::replaceToken("TYPE", position, type_name, source);
11396 Utils::replaceToken("TYPE", position, type_name, source);
11397 }
11398 else
11399 {
11400 switch (stage)
11401 {
11402 case Utils::Shader::FRAGMENT:
11403 source = fs;
11404 break;
11405 case Utils::Shader::GEOMETRY:
11406 source = gs;
11407 break;
11408 case Utils::Shader::TESS_CTRL:
11409 source = tcs;
11410 break;
11411 case Utils::Shader::TESS_EVAL:
11412 source = tes;
11413 break;
11414 case Utils::Shader::VERTEX:
11415 source = vs;
11416 break;
11417 default:
11418 TCU_FAIL("Invalid enum");
11419 }
11420 }
11421
11422 return source;
11423 }
11424
11425 /** Checks if stage is supported
11426 *
11427 * @param stage Shader stage
11428 *
11429 * @return true if supported, false otherwise
11430 **/
11431 bool SSBMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES stage)
11432 {
11433 const Functions& gl = m_context.getRenderContext().getFunctions();
11434 GLint max_supported_buffers = 0;
11435 GLenum pname = 0;
11436
11437 switch (stage)
11438 {
11439 case Utils::Shader::COMPUTE:
11440 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11441 break;
11442 case Utils::Shader::FRAGMENT:
11443 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11444 break;
11445 case Utils::Shader::GEOMETRY:
11446 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11447 break;
11448 case Utils::Shader::TESS_CTRL:
11449 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11450 break;
11451 case Utils::Shader::TESS_EVAL:
11452 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11453 break;
11454 case Utils::Shader::VERTEX:
11455 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11456 break;
11457 default:
11458 TCU_FAIL("Invalid enum");
11459 }
11460
11461 gl.getIntegerv(pname, &max_supported_buffers);
11462 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11463
11464 return 1 <= max_supported_buffers;
11465 }
11466
11467 /** Constructor
11468 *
11469 * @param context Test framework context
11470 **/
11471 SSBMemberOverlappingOffsetsTest::SSBMemberOverlappingOffsetsTest(deqp::Context& context)
11472 : UniformBlockMemberOverlappingOffsetsTest(
11473 context, "ssb_member_overlapping_offsets",
11474 "Test verifies that overlapping offsets qualifiers cause compilation failure")
11475 {
11476 /* Nothing to be done here */
11477 }
11478
11479 /** Source for given test case and stage
11480 *
11481 * @param test_case_index Index of test case
11482 * @param stage Shader stage
11483 *
11484 * @return Shader source
11485 **/
11486 std::string SSBMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11487 {
11488 static const GLchar* cs = "#version 430 core\n"
11489 "#extension GL_ARB_enhanced_layouts : require\n"
11490 "\n"
11491 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11492 "\n"
11493 "layout (std140) buffer Block {\n"
11494 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11495 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11496 "} block;\n"
11497 "\n"
11498 "writeonly uniform image2D uni_image;\n"
11499 "\n"
11500 "void main()\n"
11501 "{\n"
11502 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11503 "\n"
11504 " if ((BOY_TYPE(1) == block.boy) ||\n"
11505 " (MAN_TYPE(0) == block.man) )\n"
11506 " {\n"
11507 " result = vec4(1, 1, 1, 1);\n"
11508 " }\n"
11509 "\n"
11510 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11511 "}\n"
11512 "\n";
11513 static const GLchar* fs = "#version 430 core\n"
11514 "#extension GL_ARB_enhanced_layouts : require\n"
11515 "\n"
11516 "in vec4 gs_fs;\n"
11517 "out vec4 fs_out;\n"
11518 "\n"
11519 "void main()\n"
11520 "{\n"
11521 " fs_out = gs_fs;\n"
11522 "}\n"
11523 "\n";
11524 static const GLchar* fs_tested = "#version 430 core\n"
11525 "#extension GL_ARB_enhanced_layouts : require\n"
11526 "\n"
11527 "layout (std140) buffer Block {\n"
11528 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11529 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11530 "} block;\n"
11531 "\n"
11532 "in vec4 gs_fs;\n"
11533 "out vec4 fs_out;\n"
11534 "\n"
11535 "void main()\n"
11536 "{\n"
11537 " if ((BOY_TYPE(1) == block.boy) ||\n"
11538 " (MAN_TYPE(0) == block.man) )\n"
11539 " {\n"
11540 " fs_out = vec4(1, 1, 1, 1);\n"
11541 " }\n"
11542 "\n"
11543 " fs_out += gs_fs;\n"
11544 "}\n"
11545 "\n";
11546 static const GLchar* gs = "#version 430 core\n"
11547 "#extension GL_ARB_enhanced_layouts : require\n"
11548 "\n"
11549 "layout(points) in;\n"
11550 "layout(triangle_strip, max_vertices = 4) out;\n"
11551 "\n"
11552 "in vec4 tes_gs[];\n"
11553 "out vec4 gs_fs;\n"
11554 "\n"
11555 "void main()\n"
11556 "{\n"
11557 " gs_fs = tes_gs[0];\n"
11558 " gl_Position = vec4(-1, -1, 0, 1);\n"
11559 " EmitVertex();\n"
11560 " gs_fs = tes_gs[0];\n"
11561 " gl_Position = vec4(-1, 1, 0, 1);\n"
11562 " EmitVertex();\n"
11563 " gs_fs = tes_gs[0];\n"
11564 " gl_Position = vec4(1, -1, 0, 1);\n"
11565 " EmitVertex();\n"
11566 " gs_fs = tes_gs[0];\n"
11567 " gl_Position = vec4(1, 1, 0, 1);\n"
11568 " EmitVertex();\n"
11569 "}\n"
11570 "\n";
11571 static const GLchar* gs_tested = "#version 430 core\n"
11572 "#extension GL_ARB_enhanced_layouts : require\n"
11573 "\n"
11574 "layout(points) in;\n"
11575 "layout(triangle_strip, max_vertices = 4) out;\n"
11576 "\n"
11577 "layout (std140) buffer Block {\n"
11578 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11579 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11580 "} block;\n"
11581 "\n"
11582 "in vec4 tes_gs[];\n"
11583 "out vec4 gs_fs;\n"
11584 "\n"
11585 "void main()\n"
11586 "{\n"
11587 " if ((BOY_TYPE(1) == block.boy) ||\n"
11588 " (MAN_TYPE(0) == block.man) )\n"
11589 " {\n"
11590 " gs_fs = vec4(1, 1, 1, 1);\n"
11591 " }\n"
11592 "\n"
11593 " gs_fs += tes_gs[0];\n"
11594 " gl_Position = vec4(-1, -1, 0, 1);\n"
11595 " EmitVertex();\n"
11596 " gs_fs += tes_gs[0];\n"
11597 " gl_Position = vec4(-1, 1, 0, 1);\n"
11598 " EmitVertex();\n"
11599 " gs_fs += tes_gs[0];\n"
11600 " gl_Position = vec4(1, -1, 0, 1);\n"
11601 " EmitVertex();\n"
11602 " gs_fs += tes_gs[0];\n"
11603 " gl_Position = vec4(1, 1, 0, 1);\n"
11604 " EmitVertex();\n"
11605 "}\n"
11606 "\n";
11607 static const GLchar* tcs = "#version 430 core\n"
11608 "#extension GL_ARB_enhanced_layouts : require\n"
11609 "\n"
11610 "layout(vertices = 1) out;\n"
11611 "\n"
11612 "in vec4 vs_tcs[];\n"
11613 "out vec4 tcs_tes[];\n"
11614 "\n"
11615 "void main()\n"
11616 "{\n"
11617 "\n"
11618 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11619 "\n"
11620 " gl_TessLevelOuter[0] = 1.0;\n"
11621 " gl_TessLevelOuter[1] = 1.0;\n"
11622 " gl_TessLevelOuter[2] = 1.0;\n"
11623 " gl_TessLevelOuter[3] = 1.0;\n"
11624 " gl_TessLevelInner[0] = 1.0;\n"
11625 " gl_TessLevelInner[1] = 1.0;\n"
11626 "}\n"
11627 "\n";
11628 static const GLchar* tcs_tested = "#version 430 core\n"
11629 "#extension GL_ARB_enhanced_layouts : require\n"
11630 "\n"
11631 "layout(vertices = 1) out;\n"
11632 "\n"
11633 "layout (std140) buffer Block {\n"
11634 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11635 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11636 "} block;\n"
11637 "\n"
11638 "in vec4 vs_tcs[];\n"
11639 "out vec4 tcs_tes[];\n"
11640 "\n"
11641 "void main()\n"
11642 "{\n"
11643 " if ((BOY_TYPE(1) == block.boy) ||\n"
11644 " (MAN_TYPE(0) == block.man) )\n"
11645 " {\n"
11646 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11647 " }\n"
11648 "\n"
11649 "\n"
11650 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11651 "\n"
11652 " gl_TessLevelOuter[0] = 1.0;\n"
11653 " gl_TessLevelOuter[1] = 1.0;\n"
11654 " gl_TessLevelOuter[2] = 1.0;\n"
11655 " gl_TessLevelOuter[3] = 1.0;\n"
11656 " gl_TessLevelInner[0] = 1.0;\n"
11657 " gl_TessLevelInner[1] = 1.0;\n"
11658 "}\n"
11659 "\n";
11660 static const GLchar* tes = "#version 430 core\n"
11661 "#extension GL_ARB_enhanced_layouts : require\n"
11662 "\n"
11663 "layout(isolines, point_mode) in;\n"
11664 "\n"
11665 "in vec4 tcs_tes[];\n"
11666 "out vec4 tes_gs;\n"
11667 "\n"
11668 "void main()\n"
11669 "{\n"
11670 " tes_gs = tcs_tes[0];\n"
11671 "}\n"
11672 "\n";
11673 static const GLchar* tes_tested = "#version 430 core\n"
11674 "#extension GL_ARB_enhanced_layouts : require\n"
11675 "\n"
11676 "layout(isolines, point_mode) in;\n"
11677 "\n"
11678 "layout (std140) buffer Block {\n"
11679 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11680 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11681 "} block;\n"
11682 "\n"
11683 "in vec4 tcs_tes[];\n"
11684 "out vec4 tes_gs;\n"
11685 "\n"
11686 "void main()\n"
11687 "{\n"
11688 " if ((BOY_TYPE(1) == block.boy) ||\n"
11689 " (MAN_TYPE(0) == block.man) )\n"
11690 " {\n"
11691 " tes_gs = vec4(1, 1, 1, 1);\n"
11692 " }\n"
11693 "\n"
11694 " tes_gs += tcs_tes[0];\n"
11695 "}\n"
11696 "\n";
11697 static const GLchar* vs = "#version 430 core\n"
11698 "#extension GL_ARB_enhanced_layouts : require\n"
11699 "\n"
11700 "in vec4 in_vs;\n"
11701 "out vec4 vs_tcs;\n"
11702 "\n"
11703 "void main()\n"
11704 "{\n"
11705 " vs_tcs = in_vs;\n"
11706 "}\n"
11707 "\n";
11708 static const GLchar* vs_tested = "#version 430 core\n"
11709 "#extension GL_ARB_enhanced_layouts : require\n"
11710 "\n"
11711 "layout (std140) buffer Block {\n"
11712 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11713 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11714 "} block;\n"
11715 "\n"
11716 "in vec4 in_vs;\n"
11717 "out vec4 vs_tcs;\n"
11718 "\n"
11719 "void main()\n"
11720 "{\n"
11721 " if ((BOY_TYPE(1) == block.boy) ||\n"
11722 " (MAN_TYPE(0) == block.man) )\n"
11723 " {\n"
11724 " vs_tcs = vec4(1, 1, 1, 1);\n"
11725 " }\n"
11726 "\n"
11727 " vs_tcs += in_vs;\n"
11728 "}\n"
11729 "\n";
11730
11731 std::string source;
11732 testCase& test_case = m_test_cases[test_case_index];
11733
11734 if (test_case.m_stage == stage)
11735 {
11736 GLchar buffer[16];
11737 const GLuint boy_offset = test_case.m_boy_offset;
11738 const Utils::Type& boy_type = test_case.m_boy_type;
11739 const GLchar* boy_type_name = boy_type.GetGLSLTypeName();
11740 const GLuint man_offset = test_case.m_man_offset;
11741 const Utils::Type& man_type = test_case.m_man_type;
11742 const GLchar* man_type_name = man_type.GetGLSLTypeName();
11743 size_t position = 0;
11744
11745 switch (stage)
11746 {
11747 case Utils::Shader::COMPUTE:
11748 source = cs;
11749 break;
11750 case Utils::Shader::FRAGMENT:
11751 source = fs_tested;
11752 break;
11753 case Utils::Shader::GEOMETRY:
11754 source = gs_tested;
11755 break;
11756 case Utils::Shader::TESS_CTRL:
11757 source = tcs_tested;
11758 break;
11759 case Utils::Shader::TESS_EVAL:
11760 source = tes_tested;
11761 break;
11762 case Utils::Shader::VERTEX:
11763 source = vs_tested;
11764 break;
11765 default:
11766 TCU_FAIL("Invalid enum");
11767 }
11768
11769 sprintf(buffer, "%d", boy_offset);
11770 Utils::replaceToken("BOY_OFFSET", position, buffer, source);
11771 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
11772 sprintf(buffer, "%d", man_offset);
11773 Utils::replaceToken("MAN_OFFSET", position, buffer, source);
11774 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
11775 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
11776 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
11777 }
11778 else
11779 {
11780 switch (stage)
11781 {
11782 case Utils::Shader::FRAGMENT:
11783 source = fs;
11784 break;
11785 case Utils::Shader::GEOMETRY:
11786 source = gs;
11787 break;
11788 case Utils::Shader::TESS_CTRL:
11789 source = tcs;
11790 break;
11791 case Utils::Shader::TESS_EVAL:
11792 source = tes;
11793 break;
11794 case Utils::Shader::VERTEX:
11795 source = vs;
11796 break;
11797 default:
11798 TCU_FAIL("Invalid enum");
11799 }
11800 }
11801
11802 return source;
11803 }
11804
11805 /** Checks if stage is supported
11806 *
11807 * @param stage Shader stage
11808 *
11809 * @return true if supported, false otherwise
11810 **/
11811 bool SSBMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES stage)
11812 {
11813 const Functions& gl = m_context.getRenderContext().getFunctions();
11814 GLint max_supported_buffers = 0;
11815 GLenum pname = 0;
11816
11817 switch (stage)
11818 {
11819 case Utils::Shader::COMPUTE:
11820 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11821 break;
11822 case Utils::Shader::FRAGMENT:
11823 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11824 break;
11825 case Utils::Shader::GEOMETRY:
11826 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11827 break;
11828 case Utils::Shader::TESS_CTRL:
11829 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11830 break;
11831 case Utils::Shader::TESS_EVAL:
11832 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11833 break;
11834 case Utils::Shader::VERTEX:
11835 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11836 break;
11837 default:
11838 TCU_FAIL("Invalid enum");
11839 }
11840
11841 gl.getIntegerv(pname, &max_supported_buffers);
11842 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11843
11844 return 1 <= max_supported_buffers;
11845 }
11846
11847 /** Constructor
11848 *
11849 * @param context Test framework context
11850 **/
11851 SSBMemberAlignNonPowerOf2Test::SSBMemberAlignNonPowerOf2Test(deqp::Context& context)
11852 : UniformBlockMemberAlignNonPowerOf2Test(context, "ssb_member_align_non_power_of_2",
11853 "Test verifies that align qualifier requires value that is a power of 2")
11854 {
11855 /* Nothing to be done here */
11856 }
11857
11858 /** Source for given test case and stage
11859 *
11860 * @param test_case_index Index of test case
11861 * @param stage Shader stage
11862 *
11863 * @return Shader source
11864 **/
11865 std::string SSBMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11866 {
11867 static const GLchar* cs = "#version 430 core\n"
11868 "#extension GL_ARB_enhanced_layouts : require\n"
11869 "\n"
11870 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11871 "\n"
11872 "layout (std140) buffer Block {\n"
11873 " vec4 boy;\n"
11874 " layout (align = ALIGN) TYPE man;\n"
11875 "} block;\n"
11876 "\n"
11877 "writeonly uniform image2D uni_image;\n"
11878 "\n"
11879 "void main()\n"
11880 "{\n"
11881 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11882 "\n"
11883 " if (TYPE(0) == block.man)\n"
11884 " {\n"
11885 " result = vec4(1, 1, 1, 1) - block.boy;\n"
11886 " }\n"
11887 "\n"
11888 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11889 "}\n"
11890 "\n";
11891 static const GLchar* fs = "#version 430 core\n"
11892 "#extension GL_ARB_enhanced_layouts : require\n"
11893 "\n"
11894 "in vec4 gs_fs;\n"
11895 "out vec4 fs_out;\n"
11896 "\n"
11897 "void main()\n"
11898 "{\n"
11899 " fs_out = gs_fs;\n"
11900 "}\n"
11901 "\n";
11902 static const GLchar* fs_tested = "#version 430 core\n"
11903 "#extension GL_ARB_enhanced_layouts : require\n"
11904 "\n"
11905 "layout (std140) buffer Block {\n"
11906 " vec4 boy;\n"
11907 " layout (align = ALIGN) TYPE man;\n"
11908 "} block;\n"
11909 "\n"
11910 "in vec4 gs_fs;\n"
11911 "out vec4 fs_out;\n"
11912 "\n"
11913 "void main()\n"
11914 "{\n"
11915 " if (TYPE(0) == block.man)\n"
11916 " {\n"
11917 " fs_out = block.boy;\n"
11918 " }\n"
11919 "\n"
11920 " fs_out += gs_fs;\n"
11921 "}\n"
11922 "\n";
11923 static const GLchar* gs = "#version 430 core\n"
11924 "#extension GL_ARB_enhanced_layouts : require\n"
11925 "\n"
11926 "layout(points) in;\n"
11927 "layout(triangle_strip, max_vertices = 4) out;\n"
11928 "\n"
11929 "in vec4 tes_gs[];\n"
11930 "out vec4 gs_fs;\n"
11931 "\n"
11932 "void main()\n"
11933 "{\n"
11934 " gs_fs = tes_gs[0];\n"
11935 " gl_Position = vec4(-1, -1, 0, 1);\n"
11936 " EmitVertex();\n"
11937 " gs_fs = tes_gs[0];\n"
11938 " gl_Position = vec4(-1, 1, 0, 1);\n"
11939 " EmitVertex();\n"
11940 " gs_fs = tes_gs[0];\n"
11941 " gl_Position = vec4(1, -1, 0, 1);\n"
11942 " EmitVertex();\n"
11943 " gs_fs = tes_gs[0];\n"
11944 " gl_Position = vec4(1, 1, 0, 1);\n"
11945 " EmitVertex();\n"
11946 "}\n"
11947 "\n";
11948 static const GLchar* gs_tested = "#version 430 core\n"
11949 "#extension GL_ARB_enhanced_layouts : require\n"
11950 "\n"
11951 "layout(points) in;\n"
11952 "layout(triangle_strip, max_vertices = 4) out;\n"
11953 "\n"
11954 "layout (std140) buffer Block {\n"
11955 " vec4 boy;\n"
11956 " layout (align = ALIGN) TYPE man;\n"
11957 "} block;\n"
11958 "\n"
11959 "in vec4 tes_gs[];\n"
11960 "out vec4 gs_fs;\n"
11961 "\n"
11962 "void main()\n"
11963 "{\n"
11964 " if (TYPE(0) == block.man)\n"
11965 " {\n"
11966 " gs_fs = block.boy;\n"
11967 " }\n"
11968 "\n"
11969 " gs_fs += tes_gs[0];\n"
11970 " gl_Position = vec4(-1, -1, 0, 1);\n"
11971 " EmitVertex();\n"
11972 " gs_fs += tes_gs[0];\n"
11973 " gl_Position = vec4(-1, 1, 0, 1);\n"
11974 " EmitVertex();\n"
11975 " gs_fs += tes_gs[0];\n"
11976 " gl_Position = vec4(1, -1, 0, 1);\n"
11977 " EmitVertex();\n"
11978 " gs_fs += tes_gs[0];\n"
11979 " gl_Position = vec4(1, 1, 0, 1);\n"
11980 " EmitVertex();\n"
11981 "}\n"
11982 "\n";
11983 static const GLchar* tcs = "#version 430 core\n"
11984 "#extension GL_ARB_enhanced_layouts : require\n"
11985 "\n"
11986 "layout(vertices = 1) out;\n"
11987 "\n"
11988 "in vec4 vs_tcs[];\n"
11989 "out vec4 tcs_tes[];\n"
11990 "\n"
11991 "void main()\n"
11992 "{\n"
11993 "\n"
11994 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11995 "\n"
11996 " gl_TessLevelOuter[0] = 1.0;\n"
11997 " gl_TessLevelOuter[1] = 1.0;\n"
11998 " gl_TessLevelOuter[2] = 1.0;\n"
11999 " gl_TessLevelOuter[3] = 1.0;\n"
12000 " gl_TessLevelInner[0] = 1.0;\n"
12001 " gl_TessLevelInner[1] = 1.0;\n"
12002 "}\n"
12003 "\n";
12004 static const GLchar* tcs_tested = "#version 430 core\n"
12005 "#extension GL_ARB_enhanced_layouts : require\n"
12006 "\n"
12007 "layout(vertices = 1) out;\n"
12008 "\n"
12009 "layout (std140) buffer Block {\n"
12010 " vec4 boy;\n"
12011 " layout (align = ALIGN) TYPE man;\n"
12012 "} block;\n"
12013 "\n"
12014 "in vec4 vs_tcs[];\n"
12015 "out vec4 tcs_tes[];\n"
12016 "\n"
12017 "void main()\n"
12018 "{\n"
12019 " if (TYPE(0) == block.man)\n"
12020 " {\n"
12021 " tcs_tes[gl_InvocationID] = block.boy;\n"
12022 " }\n"
12023 "\n"
12024 "\n"
12025 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
12026 "\n"
12027 " gl_TessLevelOuter[0] = 1.0;\n"
12028 " gl_TessLevelOuter[1] = 1.0;\n"
12029 " gl_TessLevelOuter[2] = 1.0;\n"
12030 " gl_TessLevelOuter[3] = 1.0;\n"
12031 " gl_TessLevelInner[0] = 1.0;\n"
12032 " gl_TessLevelInner[1] = 1.0;\n"
12033 "}\n"
12034 "\n";
12035 static const GLchar* tes = "#version 430 core\n"
12036 "#extension GL_ARB_enhanced_layouts : require\n"
12037 "\n"
12038 "layout(isolines, point_mode) in;\n"
12039 "\n"
12040 "in vec4 tcs_tes[];\n"
12041 "out vec4 tes_gs;\n"
12042 "\n"
12043 "void main()\n"
12044 "{\n"
12045 " tes_gs = tcs_tes[0];\n"
12046 "}\n"
12047 "\n";
12048 static const GLchar* tes_tested = "#version 430 core\n"
12049 "#extension GL_ARB_enhanced_layouts : require\n"
12050 "\n"
12051 "layout(isolines, point_mode) in;\n"
12052 "\n"
12053 "layout (std140) buffer Block {\n"
12054 " vec4 boy;\n"
12055 " layout (align = ALIGN) TYPE man;\n"
12056 "} block;\n"
12057 "\n"
12058 "in vec4 tcs_tes[];\n"
12059 "out vec4 tes_gs;\n"
12060 "\n"
12061 "void main()\n"
12062 "{\n"
12063 " if (TYPE(0) == block.man)\n"
12064 " {\n"
12065 " tes_gs = block.boy;\n"
12066 " }\n"
12067 "\n"
12068 " tes_gs += tcs_tes[0];\n"
12069 "}\n"
12070 "\n";
12071 static const GLchar* vs = "#version 430 core\n"
12072 "#extension GL_ARB_enhanced_layouts : require\n"
12073 "\n"
12074 "in vec4 in_vs;\n"
12075 "out vec4 vs_tcs;\n"
12076 "\n"
12077 "void main()\n"
12078 "{\n"
12079 " vs_tcs = in_vs;\n"
12080 "}\n"
12081 "\n";
12082 static const GLchar* vs_tested = "#version 430 core\n"
12083 "#extension GL_ARB_enhanced_layouts : require\n"
12084 "\n"
12085 "layout (std140) buffer Block {\n"
12086 " vec4 boy;\n"
12087 " layout (align = ALIGN) TYPE man;\n"
12088 "} block;\n"
12089 "\n"
12090 "in vec4 in_vs;\n"
12091 "out vec4 vs_tcs;\n"
12092 "\n"
12093 "void main()\n"
12094 "{\n"
12095 " if (TYPE(0) == block.man)\n"
12096 " {\n"
12097 " vs_tcs = block.boy;\n"
12098 " }\n"
12099 "\n"
12100 " vs_tcs += in_vs;\n"
12101 "}\n"
12102 "\n";
12103
12104 std::string source;
12105 testCase& test_case = m_test_cases[test_case_index];
12106
12107 if (test_case.m_stage == stage)
12108 {
12109 GLchar buffer[16];
12110 const GLuint alignment = test_case.m_alignment;
12111 const Utils::Type& type = test_case.m_type;
12112 const GLchar* type_name = type.GetGLSLTypeName();
12113 size_t position = 0;
12114
12115 switch (stage)
12116 {
12117 case Utils::Shader::COMPUTE:
12118 source = cs;
12119 break;
12120 case Utils::Shader::FRAGMENT:
12121 source = fs_tested;
12122 break;
12123 case Utils::Shader::GEOMETRY:
12124 source = gs_tested;
12125 break;
12126 case Utils::Shader::TESS_CTRL:
12127 source = tcs_tested;
12128 break;
12129 case Utils::Shader::TESS_EVAL:
12130 source = tes_tested;
12131 break;
12132 case Utils::Shader::VERTEX:
12133 source = vs_tested;
12134 break;
12135 default:
12136 TCU_FAIL("Invalid enum");
12137 }
12138
12139 sprintf(buffer, "%d", alignment);
12140 Utils::replaceToken("ALIGN", position, buffer, source);
12141 Utils::replaceToken("TYPE", position, type_name, source);
12142 Utils::replaceToken("TYPE", position, type_name, source);
12143 }
12144 else
12145 {
12146 switch (stage)
12147 {
12148 case Utils::Shader::FRAGMENT:
12149 source = fs;
12150 break;
12151 case Utils::Shader::GEOMETRY:
12152 source = gs;
12153 break;
12154 case Utils::Shader::TESS_CTRL:
12155 source = tcs;
12156 break;
12157 case Utils::Shader::TESS_EVAL:
12158 source = tes;
12159 break;
12160 case Utils::Shader::VERTEX:
12161 source = vs;
12162 break;
12163 default:
12164 TCU_FAIL("Invalid enum");
12165 }
12166 }
12167
12168 return source;
12169 }
12170
12171 /** Checks if stage is supported
12172 *
12173 * @param stage Shader stage
12174 *
12175 * @return true if supported, false otherwise
12176 **/
12177 bool SSBMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES stage)
12178 {
12179 const Functions& gl = m_context.getRenderContext().getFunctions();
12180 GLint max_supported_buffers = 0;
12181 GLenum pname = 0;
12182
12183 switch (stage)
12184 {
12185 case Utils::Shader::COMPUTE:
12186 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
12187 break;
12188 case Utils::Shader::FRAGMENT:
12189 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
12190 break;
12191 case Utils::Shader::GEOMETRY:
12192 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
12193 break;
12194 case Utils::Shader::TESS_CTRL:
12195 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
12196 break;
12197 case Utils::Shader::TESS_EVAL:
12198 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
12199 break;
12200 case Utils::Shader::VERTEX:
12201 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
12202 break;
12203 default:
12204 TCU_FAIL("Invalid enum");
12205 }
12206
12207 gl.getIntegerv(pname, &max_supported_buffers);
12208 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12209
12210 return 1 <= max_supported_buffers;
12211 }
12212
12213 /** Constructor
12214 *
12215 * @param context Test framework context
12216 **/
12217 SSBAlignmentTest::SSBAlignmentTest(deqp::Context& context)
12218 : TextureTestBase(context, "ssb_alignment", "Test verifies offset and alignment of ssb buffer")
12219 {
12220 }
12221
12222 /** Get interface of program
12223 *
12224 * @param ignored
12225 * @param program_interface Interface of program
12226 * @param varying_passthrough Collection of connections between in and out variables
12227 **/
12228 void SSBAlignmentTest::getProgramInterface(GLuint /* test_case_index */, Utils::ProgramInterface& program_interface,
12229 Utils::VaryingPassthrough& varying_passthrough)
12230 {
12231 static const Utils::Type vec4 = Utils::Type::vec4;
12232
12233 #if WRKARD_UNIFORMBLOCKALIGNMENT
12234
12235 static const GLuint block_align = 16;
12236
12237 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12238
12239 static const GLuint block_align = 64;
12240
12241 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12242
12243 static const GLuint fifth_align = 16;
12244 static const GLuint vec4_stride = 16;
12245 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
12246
12247 const GLuint first_offset = 0; /* vec4 at 0 */
12248 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
12249 const GLuint third_offset =
12250 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
12251 const GLuint fourth_offset =
12252 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
12253 const GLuint fifth_offset =
12254 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, fifth_align); /* vec4[2] at 160 */
12255 const GLuint sixth_offset =
12256 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
12257
12258 Utils::Interface* structure = program_interface.Structure("Data");
12259
12260 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12261 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
12262
12263 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
12264 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
12265 Utils::Type::vec4.GetSize() /* offset */);
12266
12267 /* Prepare Block */
12268 Utils::Interface* vs_buf_Block = program_interface.Block("vs_buf_Block");
12269
12270 vs_buf_Block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12271 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
12272
12273 vs_buf_Block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12274 0 /* n_array_elements */, data_stride, second_offset);
12275
12276 vs_buf_Block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12277 2 /* n_array_elements */, data_stride, third_offset);
12278
12279 vs_buf_Block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
12280 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
12281
12282 vs_buf_Block->Member("fifth", "layout(align = 16)", 0 /* expected_component */, 0 /* expected_location */, vec4,
12283 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
12284
12285 vs_buf_Block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12286 0 /* n_array_elements */, data_stride, sixth_offset);
12287
12288 const GLuint stride = calculateStride(*vs_buf_Block);
12289 m_data.resize(stride);
12290 generateData(*vs_buf_Block, 0, m_data);
12291
12292 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12293
12294 /* Add uniform BLOCK */
12295 #if WRKARD_UNIFORMBLOCKALIGNMENT
12296 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_Block, 0,
12297 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12298 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12299 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_buf_Block, 0,
12300 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12301 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12302
12303 program_interface.CloneVertexInterface(varying_passthrough);
12304 }
12305
12306 /** Selects if "draw" stages are relevant for test
12307 *
12308 * @param ignored
12309 *
12310 * @return true if all stages support shader storage buffers, false otherwise
12311 **/
12312 bool SSBAlignmentTest::isDrawRelevant(GLuint /* test_case_index */)
12313 {
12314 const Functions& gl = m_context.getRenderContext().getFunctions();
12315 GLint gs_supported_buffers = 0;
12316 GLint tcs_supported_buffers = 0;
12317 GLint tes_supported_buffers = 0;
12318 GLint vs_supported_buffers = 0;
12319
12320 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
12321 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
12322 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
12323 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
12324
12325 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12326
12327 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
12328 (1 <= vs_supported_buffers));
12329 }
12330
12331 /** Constructor
12332 *
12333 * @param context Test framework context
12334 **/
12335 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context)
12336 : TextureTestBase(context, "varying_locations", "Test verifies that input and output locations are respected")
12337 {
12338 }
12339
12340 /** Constructor
12341 *
12342 * @param context Test context
12343 * @param test_name Name of test
12344 * @param test_description Description of test
12345 **/
12346 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context, const glw::GLchar* test_name,
12347 const glw::GLchar* test_description)
12348 : TextureTestBase(context, test_name, test_description)
12349 {
12350 }
12351
12352 /** Get interface of program
12353 *
12354 * @param test_case_index Test case
12355 * @param program_interface Interface of program
12356 * @param varying_passthrough Collection of connections between in and out variables
12357 **/
12358 void VaryingLocationsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
12359 Utils::VaryingPassthrough& varying_passthrough)
12360 {
12361 const Utils::Type type = getType(test_case_index);
12362
12363 m_first_data = type.GenerateDataPacked();
12364 m_last_data = type.GenerateDataPacked();
12365
12366 prepareShaderStage(Utils::Shader::FRAGMENT, type, program_interface, varying_passthrough);
12367 prepareShaderStage(Utils::Shader::GEOMETRY, type, program_interface, varying_passthrough);
12368 prepareShaderStage(Utils::Shader::TESS_CTRL, type, program_interface, varying_passthrough);
12369 prepareShaderStage(Utils::Shader::TESS_EVAL, type, program_interface, varying_passthrough);
12370 prepareShaderStage(Utils::Shader::VERTEX, type, program_interface, varying_passthrough);
12371 }
12372
12373 /** Get type name
12374 *
12375 * @param test_case_index Index of test case
12376 *
12377 * @return Name of type test in test_case_index
12378 **/
12379 std::string VaryingLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12380 {
12381 return getTypeName(test_case_index);
12382 }
12383
12384 /** Returns number of types to test
12385 *
12386 * @return Number of types, 34
12387 **/
12388 glw::GLuint VaryingLocationsTest::getTestCaseNumber()
12389 {
12390 return getTypesNumber();
12391 }
12392
12393 /** Selects if "compute" stage is relevant for test
12394 *
12395 * @param ignored
12396 *
12397 * @return false
12398 **/
12399 bool VaryingLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12400 {
12401 return false;
12402 }
12403
12404 /**
12405 *
12406 *
12407 **/
12408 std::string VaryingLocationsTest::prepareGlobals(GLint last_in_loc, GLint last_out_loc)
12409 {
12410 GLchar buffer[16];
12411 std::string globals = "const uint first_input_location = 0u;\n"
12412 "const uint first_output_location = 0u;\n"
12413 "const uint last_input_location = LAST_INPUTu;\n"
12414 "const uint last_output_location = LAST_OUTPUTu;\n";
12415 size_t position = 100; /* Skip first part */
12416
12417 sprintf(buffer, "%d", last_in_loc);
12418 Utils::replaceToken("LAST_INPUT", position, buffer, globals);
12419
12420 sprintf(buffer, "%d", last_out_loc);
12421 Utils::replaceToken("LAST_OUTPUT", position, buffer, globals);
12422
12423 return globals;
12424 }
12425
12426 /**
12427 *
12428 **/
12429 void VaryingLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12430 Utils::ProgramInterface& program_interface,
12431 Utils::VaryingPassthrough& varying_passthrough)
12432 {
12433 const GLuint array_length = 1;
12434 const GLuint first_in_loc = 0;
12435 const GLuint first_out_loc = 0;
12436 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12437 size_t position = 0;
12438
12439 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12440
12441 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12442
12443 const GLchar* qual_first_in = "layout (location = first_input_location)";
12444 const GLchar* qual_first_out = "layout (location = first_output_location)";
12445 const GLchar* qual_last_in = "layout (location = last_input_location)";
12446 const GLchar* qual_last_out = "layout (location = last_output_location)";
12447
12448 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12449 const GLuint type_size = type.GetSize();
12450
12451 std::string first_in_name = "PREFIXfirst";
12452 std::string first_out_name = "PREFIXfirst";
12453 std::string last_in_name = "PREFIXlast";
12454 std::string last_out_name = "PREFIXlast";
12455
12456 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12457 position = 0;
12458 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12459 position = 0;
12460 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12461 position = 0;
12462 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12463
12464 if (Utils::Shader::FRAGMENT == stage)
12465 {
12466 qual_first_in = "layout (location = first_input_location) flat";
12467 qual_last_in = "layout (location = last_input_location) flat";
12468 }
12469 if (Utils::Shader::GEOMETRY == stage)
12470 {
12471 qual_first_out = "layout (location = first_output_location) flat";
12472 qual_last_out = "layout (location = last_output_location) flat";
12473 }
12474
12475 Utils::Variable* first_in = si.Input(
12476 first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12477 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12478 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12479
12480 Utils::Variable* last_in =
12481 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12482 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12483 0u /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12484 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12485
12486 if (Utils::Shader::FRAGMENT != stage)
12487 {
12488 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12489
12490 Utils::Variable* first_out =
12491 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12492 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12493 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */,
12494 m_first_data.size() /* data_size */);
12495
12496 Utils::Variable* last_out = si.Output(
12497 last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12498 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12499 0u /* stride */, 0u /* offset */, (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12500
12501 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12502
12503 varying_passthrough.Add(stage, first_in, first_out);
12504 varying_passthrough.Add(stage, last_in, last_out);
12505 }
12506 else
12507 {
12508 /* No outputs for fragment shader, so last_output_location can be 0 */
12509 si.m_globals = prepareGlobals(last_in_loc, 0);
12510 }
12511 }
12512
12513 /** This test should be run with separable programs
12514 *
12515 * @param ignored
12516 *
12517 * @return true
12518 **/
12519 bool VaryingLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12520 {
12521 return false;
12522 }
12523
12524 /* Constants used by VertexAttribLocationsTest */
12525 const GLuint VertexAttribLocationsTest::m_base_vertex = 4;
12526 const GLuint VertexAttribLocationsTest::m_base_instance = 2;
12527 const GLuint VertexAttribLocationsTest::m_loc_vertex = 2;
12528 const GLuint VertexAttribLocationsTest::m_loc_instance = 5;
12529 const GLuint VertexAttribLocationsTest::m_n_instances = 4;
12530
12531 /** Constructor
12532 *
12533 * @param context Test framework context
12534 **/
12535 VertexAttribLocationsTest::VertexAttribLocationsTest(deqp::Context& context)
12536 : TextureTestBase(context, "vertex_attrib_locations",
12537 "Test verifies that attribute locations are respected by drawing operations")
12538 {
12539 }
12540
12541 /** Execute proper draw command for test case
12542 *
12543 * @param test_case_index Index of test case
12544 **/
12545 void VertexAttribLocationsTest::executeDrawCall(GLuint test_case_index)
12546 {
12547 const Functions& gl = m_context.getRenderContext().getFunctions();
12548
12549 switch (test_case_index)
12550 {
12551 case DRAWARRAYS:
12552 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
12553 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
12554 break;
12555 case DRAWARRAYSINSTANCED:
12556 gl.drawArraysInstanced(GL_PATCHES, 0 /* first */, 1 /* count */, m_n_instances);
12557 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArraysInstanced");
12558 break;
12559 case DRAWELEMENTS:
12560 gl.drawElements(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL);
12561 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
12562 break;
12563 case DRAWELEMENTSBASEVERTEX:
12564 gl.drawElementsBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_base_vertex);
12565 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsBaseVertex");
12566 break;
12567 case DRAWELEMENTSINSTANCED:
12568 gl.drawElementsInstanced(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances);
12569 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstanced");
12570 break;
12571 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12572 gl.drawElementsInstancedBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12573 m_base_instance);
12574 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseInstance");
12575 break;
12576 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12577 gl.drawElementsInstancedBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12578 m_base_vertex);
12579 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertex");
12580 break;
12581 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12582 gl.drawElementsInstancedBaseVertexBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL,
12583 m_n_instances, m_base_vertex, m_base_instance);
12584 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertexBaseInstance");
12585 break;
12586 default:
12587 TCU_FAIL("Invalid enum");
12588 }
12589 }
12590
12591 /** Get interface of program
12592 *
12593 * @param ignored
12594 * @param program_interface Interface of program
12595 * @param ignored
12596 **/
12597 void VertexAttribLocationsTest::getProgramInterface(GLuint /* test_case_index */,
12598 Utils::ProgramInterface& program_interface,
12599 Utils::VaryingPassthrough& /* varying_passthrough */)
12600 {
12601 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12602
12603 /* Globals */
12604 si.m_globals = "const uint vertex_index_location = 2;\n"
12605 "const uint instance_index_location = 5;\n";
12606
12607 /* Attributes */
12608 si.Input("vertex_index" /* name */, "layout (location = vertex_index_location)" /* qualifiers */,
12609 0 /* expected_componenet */, m_loc_vertex /* expected_location */, Utils::Type::uint /* type */,
12610 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 0u /* offset */,
12611 (GLvoid*)0 /* data */, 0 /* data_size */);
12612 si.Input("instance_index" /* name */, "layout (location = instance_index_location)" /* qualifiers */,
12613 0 /* expected_componenet */, m_loc_instance /* expected_location */, Utils::Type::uint /* type */,
12614 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 16u /* offset */,
12615 (GLvoid*)0 /* data */, 0 /* data_size */);
12616 }
12617
12618 /** Get name of test case
12619 *
12620 * @param test_case_index Index of test case
12621 *
12622 * @return Name of test case
12623 **/
12624 std::string VertexAttribLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12625 {
12626 std::string result;
12627
12628 switch (test_case_index)
12629 {
12630 case DRAWARRAYS:
12631 result = "DrawArrays";
12632 break;
12633 case DRAWARRAYSINSTANCED:
12634 result = "DrawArraysInstanced";
12635 break;
12636 case DRAWELEMENTS:
12637 result = "DrawElements";
12638 break;
12639 case DRAWELEMENTSBASEVERTEX:
12640 result = "DrawElementsBaseVertex";
12641 break;
12642 case DRAWELEMENTSINSTANCED:
12643 result = "DrawElementsInstanced";
12644 break;
12645 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12646 result = "DrawElementsInstancedBaseInstance";
12647 break;
12648 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12649 result = "DrawElementsInstancedBaseVertex";
12650 break;
12651 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12652 result = "DrawElementsInstancedBaseVertexBaseInstance";
12653 break;
12654 default:
12655 TCU_FAIL("Invalid enum");
12656 }
12657
12658 return result;
12659 }
12660
12661 /** Get number of test cases
12662 *
12663 * @return Number of test cases
12664 **/
12665 GLuint VertexAttribLocationsTest::getTestCaseNumber()
12666 {
12667 return TESTCASES_MAX;
12668 }
12669
12670 /** Prepare code snippet that will verify in and uniform variables
12671 *
12672 * @param ignored
12673 * @param ignored
12674 * @param stage Shader stage
12675 *
12676 * @return Code that verify variables
12677 **/
12678 std::string VertexAttribLocationsTest::getVerificationSnippet(GLuint /* test_case_index */,
12679 Utils::ProgramInterface& /* program_interface */,
12680 Utils::Shader::STAGES stage)
12681 {
12682 std::string verification;
12683
12684 if (Utils::Shader::VERTEX == stage)
12685 {
12686
12687 #if DEBUG_VERTEX_ATTRIB_LOCATIONS_TEST_VARIABLE
12688
12689 verification = "if (gl_InstanceID != instance_index)\n"
12690 " {\n"
12691 " result = 12u;\n"
12692 " }\n"
12693 " else if (gl_VertexID != vertex_index)\n"
12694 " {\n"
12695 " result = 11u;\n"
12696 " }\n";
12697
12698 #else
12699
12700 verification = "if ((gl_VertexID != vertex_index) ||\n"
12701 " (gl_InstanceID != instance_index) )\n"
12702 " {\n"
12703 " result = 0u;\n"
12704 " }\n";
12705
12706 #endif
12707 }
12708 else
12709 {
12710 verification = "";
12711 }
12712
12713 return verification;
12714 }
12715
12716 /** Selects if "compute" stage is relevant for test
12717 *
12718 * @param ignored
12719 *
12720 * @return false
12721 **/
12722 bool VertexAttribLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12723 {
12724 return false;
12725 }
12726
12727 /** Prepare attributes, vertex array object and array buffer
12728 *
12729 * @param ignored
12730 * @param ignored Interface of program
12731 * @param buffer Array buffer
12732 * @param vao Vertex array object
12733 **/
12734 void VertexAttribLocationsTest::prepareAttributes(GLuint test_case_index /* test_case_index */,
12735 Utils::ProgramInterface& /* program_interface */,
12736 Utils::Buffer& buffer, Utils::VertexArray& vao)
12737 {
12738 static const GLuint vertex_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12739 static const GLuint instance_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12740
12741 std::vector<GLuint> buffer_data;
12742 buffer_data.resize(8 + 8); /* vertex_index_data + instance_index_data */
12743
12744 GLubyte* ptr = (GLubyte*)&buffer_data[0];
12745
12746 /*
12747 When case index >=2, the test calls glDrawElement*(), such as glDrawElementsBaseVertex(), glDrawElementsInstanced(), glDrawElementsInstancedBaseInstance() and so on,
12748 So we need to change the buffer type as GL_ELEMENT_ARRAY_BUFFER
12749 */
12750 if (test_case_index >= 2)
12751 {
12752 buffer.m_buffer = Utils::Buffer::Element;
12753 }
12754 vao.Bind();
12755 buffer.Bind();
12756
12757 vao.Attribute(m_loc_vertex /* vertex_index */, Utils::Type::uint, 0 /* array_elements */, false /* normalized */,
12758 0 /* stride */, 0 /* offset */);
12759
12760 vao.Attribute(m_loc_instance /* instance_index */, Utils::Type::uint, 0 /* array_elements */,
12761 false /* normalized */, 0 /* stride */, (GLvoid*)sizeof(vertex_index_data) /* offset */);
12762 // when test_case_index is 5 or 7, the draw call is glDrawElementsInstancedBaseInstance, glDrawElementsInstancedBaseVertexBaseInstance
12763 // the instancecount is 4, the baseinstance is 2, the divisor should be set 2
12764 bool isBaseInstanced = (test_case_index == DRAWELEMENTSINSTANCEDBASEINSTANCE ||
12765 test_case_index == DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE);
12766 vao.Divisor(m_context.getRenderContext().getFunctions() /* gl */, m_loc_instance /* instance_index */,
12767 isBaseInstanced ? 2 : 1 /* divisor. 1 - advance once per instance */);
12768
12769 memcpy(ptr + 0, vertex_index_data, sizeof(vertex_index_data));
12770 memcpy(ptr + sizeof(vertex_index_data), instance_index_data, sizeof(instance_index_data));
12771
12772 buffer.Data(Utils::Buffer::StaticDraw, buffer_data.size() * sizeof(GLuint), ptr);
12773 }
12774
12775 /** This test should be run with separable programs
12776 *
12777 * @param ignored
12778 *
12779 * @return true
12780 **/
12781 bool VertexAttribLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12782 {
12783 return false;
12784 }
12785
12786 /** Constructor
12787 *
12788 * @param context Test framework context
12789 **/
12790 VaryingArrayLocationsTest::VaryingArrayLocationsTest(deqp::Context& context)
12791 : VaryingLocationsTest(context, "varying_array_locations",
12792 "Test verifies that input and output locations are respected for arrays")
12793 {
12794 }
12795
12796 /**
12797 *
12798 **/
12799 void VaryingArrayLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12800 Utils::ProgramInterface& program_interface,
12801 Utils::VaryingPassthrough& varying_passthrough)
12802 {
12803 const GLuint array_length = 1u;
12804 const GLuint first_in_loc = 0;
12805 const GLuint first_out_loc = 0;
12806 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12807 size_t position = 0;
12808
12809 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12810
12811 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12812
12813 const GLchar* qual_first_in = "layout (location = first_input_location)";
12814 const GLchar* qual_first_out = "layout (location = first_output_location)";
12815 const GLchar* qual_last_in = "layout (location = last_input_location)";
12816 const GLchar* qual_last_out = "layout (location = last_output_location)";
12817
12818 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12819 const GLuint type_size = type.GetSize();
12820
12821 std::string first_in_name = "PREFIXfirst";
12822 std::string first_out_name = "PREFIXfirst";
12823 std::string last_in_name = "PREFIXlast";
12824 std::string last_out_name = "PREFIXlast";
12825
12826 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12827 position = 0;
12828 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12829 position = 0;
12830 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12831 position = 0;
12832 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12833
12834 if (Utils::Shader::FRAGMENT == stage)
12835 {
12836 qual_first_in = "layout (location = first_input_location) flat";
12837 qual_last_in = "layout (location = last_input_location) flat";
12838 }
12839 if (Utils::Shader::GEOMETRY == stage)
12840 {
12841 qual_first_out = "layout (location = first_output_location) flat";
12842 qual_last_out = "layout (location = last_output_location) flat";
12843 }
12844
12845 Utils::Variable* first_in =
12846 si.Input(first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12847 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12848 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12849 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12850
12851 Utils::Variable* last_in =
12852 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12853 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12854 array_length /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12855 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12856
12857 if (Utils::Shader::FRAGMENT != stage)
12858 {
12859 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12860
12861 Utils::Variable* first_out =
12862 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12863 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12864 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12865 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12866
12867 Utils::Variable* last_out =
12868 si.Output(last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12869 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12870 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12871 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12872
12873 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12874
12875 varying_passthrough.Add(stage, first_in, first_out);
12876 varying_passthrough.Add(stage, last_in, last_out);
12877 }
12878 else
12879 {
12880 /* No outputs for fragment shader, so last_output_location can be 0 */
12881 si.m_globals = prepareGlobals(last_in_loc, 0);
12882 }
12883 }
12884
12885 /** Constructor
12886 *
12887 * @param context Test framework context
12888 **/
12889 VaryingStructureLocationsTest::VaryingStructureLocationsTest(deqp::Context& context)
12890 : TextureTestBase(context, "varying_structure_locations",
12891 "Test verifies that locations are respected when structures are used as in and out ")
12892 {
12893 }
12894
12895 /** Prepare code snippet that will pass in variables to out variables
12896 *
12897 * @param ignored
12898 * @param varying_passthrough Collection of connections between in and out variables
12899 * @param stage Shader stage
12900 *
12901 * @return Code that pass in variables to next stage
12902 **/
12903 std::string VaryingStructureLocationsTest::getPassSnippet(GLuint /* test_case_index */,
12904 Utils::VaryingPassthrough& varying_passthrough,
12905 Utils::Shader::STAGES stage)
12906 {
12907 std::string result;
12908
12909 if (Utils::Shader::VERTEX != stage)
12910 {
12911 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
12912 }
12913 else
12914 {
12915 result = " vs_tcs_output[0].single = vs_in_single[0];\n"
12916 " vs_tcs_output[0].array[0] = vs_in_array[0];\n";
12917 }
12918
12919 return result;
12920 }
12921
12922 /** Get interface of program
12923 *
12924 * @param test_case_index Test case
12925 * @param program_interface Interface of program
12926 * @param varying_passthrough Collection of connections between in and out variables
12927 **/
12928 void VaryingStructureLocationsTest::getProgramInterface(GLuint test_case_index,
12929 Utils::ProgramInterface& program_interface,
12930 Utils::VaryingPassthrough& varying_passthrough)
12931 {
12932 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12933 const Utils::Type type = getType(test_case_index);
12934
12935 /* Prepare data */
12936 // We should call GenerateDataPacked() to generate data, which can make sure the data in shader is correct
12937 m_single_data = type.GenerateDataPacked();
12938 m_array_data = type.GenerateDataPacked();
12939
12940 m_data.resize(m_single_data.size() + m_array_data.size());
12941 GLubyte* ptr = (GLubyte*)&m_data[0];
12942 memcpy(ptr, &m_single_data[0], m_single_data.size());
12943 memcpy(ptr + m_single_data.size(), &m_array_data[0], m_array_data.size());
12944
12945 Utils::Interface* structure = program_interface.Structure("Data");
12946
12947 structure->Member("single", "" /* qualifiers */, 0 /* component */, 0 /* location */, type, false /* normalized */,
12948 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */);
12949
12950 // the second struct member 's location should not be 0, it is based on by how many the locations the first struct member consumed.
12951 structure->Member("array", "" /* qualifiers */, 0 /* component */, type.GetLocations() /* location */, type,
12952 false /* normalized */, 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */);
12953
12954 si.Input("vs_in_single", "layout (location = 0)", 0 /* component */, 0 /* location */, type, false /* normalized */,
12955 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_single_data[0] /* data */,
12956 m_single_data.size() /* data_size */);
12957
12958 si.Input("vs_in_array", "layout (location = 8)", 0 /* component */, 8 /* location */, type, false /* normalized */,
12959 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */,
12960 (GLvoid*)&m_array_data[0] /* data */, m_array_data.size() /* data_size */);
12961
12962 si.Output("vs_tcs_output", "layout (location = 0)", 0 /* component */, 0 /* location */, structure,
12963 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
12964 m_data.size() /* data_size */);
12965
12966 program_interface.CloneVertexInterface(varying_passthrough);
12967 }
12968
12969 /** Get type name
12970 *
12971 * @param test_case_index Index of test case
12972 *
12973 * @return Name of type test in test_case_index
12974 **/
12975 std::string VaryingStructureLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12976 {
12977 return getTypeName(test_case_index);
12978 }
12979
12980 /** Returns number of types to test
12981 *
12982 * @return Number of types, 34
12983 **/
12984 glw::GLuint VaryingStructureLocationsTest::getTestCaseNumber()
12985 {
12986 return getTypesNumber();
12987 }
12988
12989 /** Selects if "compute" stage is relevant for test
12990 *
12991 * @param ignored
12992 *
12993 * @return false
12994 **/
12995 bool VaryingStructureLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12996 {
12997 return false;
12998 }
12999
13000 /** This test should be run with separable programs
13001 *
13002 * @param ignored
13003 *
13004 * @return true
13005 **/
13006 bool VaryingStructureLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13007 {
13008 return false;
13009 }
13010
13011 /** Constructor
13012 *
13013 * @param context Test context
13014 * @param test_name Name of test
13015 * @param test_description Description of test
13016 **/
13017 VaryingStructureMemberLocationTest::VaryingStructureMemberLocationTest(deqp::Context& context)
13018 : NegativeTestBase(context, "varying_structure_member_location",
13019 "Test verifies that compiler does not allow location qualifier on member of strucure")
13020 {
13021 }
13022
13023 /** Source for given test case and stage
13024 *
13025 * @param test_case_index Index of test case
13026 * @param stage Shader stage
13027 *
13028 * @return Shader source
13029 **/
13030 std::string VaryingStructureMemberLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13031 {
13032 static const GLchar* struct_definition = "struct Data {\n"
13033 " vec4 gohan;\n"
13034 " layout (location = 4) vec4 goten;\n"
13035 "};\n";
13036 static const GLchar* input_var = "in Data data;\n";
13037 static const GLchar* output_var = "out Data data;\n";
13038 static const GLchar* input_use = " result += data.gohan + data.goten;\n";
13039 static const GLchar* output_use = " data.gohan = result / 2;\n"
13040 " data.goten = result / 4 - data.gohan;\n";
13041 static const GLchar* fs = "#version 430 core\n"
13042 "#extension GL_ARB_enhanced_layouts : require\n"
13043 "\n"
13044 "in vec4 gs_fs;\n"
13045 "out vec4 fs_out;\n"
13046 "\n"
13047 "void main()\n"
13048 "{\n"
13049 " fs_out = gs_fs;\n"
13050 "}\n"
13051 "\n";
13052 static const GLchar* fs_tested = "#version 430 core\n"
13053 "#extension GL_ARB_enhanced_layouts : require\n"
13054 "\n"
13055 "STRUCT_DEFINITION"
13056 "\n"
13057 "VARIABLE_DEFINITION"
13058 "\n"
13059 "in vec4 gs_fs;\n"
13060 "out vec4 fs_out;\n"
13061 "\n"
13062 "void main()\n"
13063 "{\n"
13064 " vec4 result = gs_fs;\n"
13065 "\n"
13066 "VARIABLE_USE"
13067 "\n"
13068 " fs_out += result;\n"
13069 "}\n"
13070 "\n";
13071 static const GLchar* gs = "#version 430 core\n"
13072 "#extension GL_ARB_enhanced_layouts : require\n"
13073 "\n"
13074 "layout(points) in;\n"
13075 "layout(triangle_strip, max_vertices = 4) out;\n"
13076 "\n"
13077 "in vec4 tes_gs[];\n"
13078 "out vec4 gs_fs;\n"
13079 "\n"
13080 "void main()\n"
13081 "{\n"
13082 " gs_fs = tes_gs[0];\n"
13083 " gl_Position = vec4(-1, -1, 0, 1);\n"
13084 " EmitVertex();\n"
13085 " gs_fs = tes_gs[0];\n"
13086 " gl_Position = vec4(-1, 1, 0, 1);\n"
13087 " EmitVertex();\n"
13088 " gs_fs = tes_gs[0];\n"
13089 " gl_Position = vec4(1, -1, 0, 1);\n"
13090 " EmitVertex();\n"
13091 " gs_fs = tes_gs[0];\n"
13092 " gl_Position = vec4(1, 1, 0, 1);\n"
13093 " EmitVertex();\n"
13094 "}\n"
13095 "\n";
13096 static const GLchar* gs_tested = "#version 430 core\n"
13097 "#extension GL_ARB_enhanced_layouts : require\n"
13098 "\n"
13099 "layout(points) in;\n"
13100 "layout(triangle_strip, max_vertices = 4) out;\n"
13101 "\n"
13102 "STRUCT_DEFINITION"
13103 "\n"
13104 "VARIABLE_DEFINITION"
13105 "\n"
13106 "in vec4 tes_gs[];\n"
13107 "out vec4 gs_fs;\n"
13108 "\n"
13109 "void main()\n"
13110 "{\n"
13111 " vec4 result = tes_gs[0];\n"
13112 "\n"
13113 "VARIABLE_USE"
13114 "\n"
13115 " gs_fs = result;\n"
13116 " gl_Position = vec4(-1, -1, 0, 1);\n"
13117 " EmitVertex();\n"
13118 " gs_fs = result;\n"
13119 " gl_Position = vec4(-1, 1, 0, 1);\n"
13120 " EmitVertex();\n"
13121 " gs_fs = result;\n"
13122 " gl_Position = vec4(1, -1, 0, 1);\n"
13123 " EmitVertex();\n"
13124 " gs_fs = result;\n"
13125 " gl_Position = vec4(1, 1, 0, 1);\n"
13126 " EmitVertex();\n"
13127 "}\n"
13128 "\n";
13129 static const GLchar* tcs = "#version 430 core\n"
13130 "#extension GL_ARB_enhanced_layouts : require\n"
13131 "\n"
13132 "layout(vertices = 1) out;\n"
13133 "\n"
13134 "in vec4 vs_tcs[];\n"
13135 "out vec4 tcs_tes[];\n"
13136 "\n"
13137 "void main()\n"
13138 "{\n"
13139 "\n"
13140 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13141 "\n"
13142 " gl_TessLevelOuter[0] = 1.0;\n"
13143 " gl_TessLevelOuter[1] = 1.0;\n"
13144 " gl_TessLevelOuter[2] = 1.0;\n"
13145 " gl_TessLevelOuter[3] = 1.0;\n"
13146 " gl_TessLevelInner[0] = 1.0;\n"
13147 " gl_TessLevelInner[1] = 1.0;\n"
13148 "}\n"
13149 "\n";
13150 static const GLchar* tcs_tested = "#version 430 core\n"
13151 "#extension GL_ARB_enhanced_layouts : require\n"
13152 "\n"
13153 "layout(vertices = 1) out;\n"
13154 "\n"
13155 "STRUCT_DEFINITION"
13156 "\n"
13157 "VARIABLE_DEFINITION"
13158 "\n"
13159 "in vec4 vs_tcs[];\n"
13160 "out vec4 tcs_tes[];\n"
13161 "\n"
13162 "void main()\n"
13163 "{\n"
13164 " vec4 result = vs_tcs[gl_InvocationID];\n"
13165 "\n"
13166 "VARIABLE_USE"
13167 "\n"
13168 " tcs_tes[gl_InvocationID] = result;\n"
13169 "\n"
13170 " gl_TessLevelOuter[0] = 1.0;\n"
13171 " gl_TessLevelOuter[1] = 1.0;\n"
13172 " gl_TessLevelOuter[2] = 1.0;\n"
13173 " gl_TessLevelOuter[3] = 1.0;\n"
13174 " gl_TessLevelInner[0] = 1.0;\n"
13175 " gl_TessLevelInner[1] = 1.0;\n"
13176 "}\n"
13177 "\n";
13178 static const GLchar* tes = "#version 430 core\n"
13179 "#extension GL_ARB_enhanced_layouts : require\n"
13180 "\n"
13181 "layout(isolines, point_mode) in;\n"
13182 "\n"
13183 "in vec4 tcs_tes[];\n"
13184 "out vec4 tes_gs;\n"
13185 "\n"
13186 "void main()\n"
13187 "{\n"
13188 " tes_gs = tcs_tes[0];\n"
13189 "}\n"
13190 "\n";
13191 static const GLchar* tes_tested = "#version 430 core\n"
13192 "#extension GL_ARB_enhanced_layouts : require\n"
13193 "\n"
13194 "layout(isolines, point_mode) in;\n"
13195 "\n"
13196 "STRUCT_DEFINITION"
13197 "\n"
13198 "VARIABLE_DEFINITION"
13199 "\n"
13200 "in vec4 tcs_tes[];\n"
13201 "out vec4 tes_gs;\n"
13202 "\n"
13203 "void main()\n"
13204 "{\n"
13205 " vec4 result = tcs_tes[0];\n"
13206 "\n"
13207 "VARIABLE_USE"
13208 "\n"
13209 " tes_gs += result;\n"
13210 "}\n"
13211 "\n";
13212 static const GLchar* vs = "#version 430 core\n"
13213 "#extension GL_ARB_enhanced_layouts : require\n"
13214 "\n"
13215 "in vec4 in_vs;\n"
13216 "out vec4 vs_tcs;\n"
13217 "\n"
13218 "void main()\n"
13219 "{\n"
13220 " vs_tcs = in_vs;\n"
13221 "}\n"
13222 "\n";
13223 static const GLchar* vs_tested = "#version 430 core\n"
13224 "#extension GL_ARB_enhanced_layouts : require\n"
13225 "\n"
13226 "STRUCT_DEFINITION"
13227 "\n"
13228 "VARIABLE_DEFINITION"
13229 "\n"
13230 "in vec4 in_vs;\n"
13231 "out vec4 vs_tcs;\n"
13232 "\n"
13233 "void main()\n"
13234 "{\n"
13235 " vec4 result = in_vs;\n"
13236 "\n"
13237 "VARIABLE_USE"
13238 "\n"
13239 " vs_tcs += result;\n"
13240 "}\n"
13241 "\n";
13242
13243 std::string source;
13244 testCase& test_case = m_test_cases[test_case_index];
13245 const GLchar* var_definition = 0;
13246 const GLchar* var_use = 0;
13247
13248 if (true == test_case.m_is_input)
13249 {
13250 var_definition = input_var;
13251 var_use = input_use;
13252 }
13253 else
13254 {
13255 var_definition = output_var;
13256 var_use = output_use;
13257 }
13258
13259 if (test_case.m_stage == stage)
13260 {
13261 size_t position = 0;
13262
13263 switch (stage)
13264 {
13265 case Utils::Shader::FRAGMENT:
13266 source = fs_tested;
13267 break;
13268 case Utils::Shader::GEOMETRY:
13269 source = gs_tested;
13270 break;
13271 case Utils::Shader::TESS_CTRL:
13272 source = tcs_tested;
13273 break;
13274 case Utils::Shader::TESS_EVAL:
13275 source = tes_tested;
13276 break;
13277 case Utils::Shader::VERTEX:
13278 source = vs_tested;
13279 break;
13280 default:
13281 TCU_FAIL("Invalid enum");
13282 }
13283
13284 Utils::replaceToken("STRUCT_DEFINITION", position, struct_definition, source);
13285 Utils::replaceToken("VARIABLE_DEFINITION", position, var_definition, source);
13286 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13287 }
13288 else
13289 {
13290 switch (stage)
13291 {
13292 case Utils::Shader::FRAGMENT:
13293 source = fs;
13294 break;
13295 case Utils::Shader::GEOMETRY:
13296 source = gs;
13297 break;
13298 case Utils::Shader::TESS_CTRL:
13299 source = tcs;
13300 break;
13301 case Utils::Shader::TESS_EVAL:
13302 source = tes;
13303 break;
13304 case Utils::Shader::VERTEX:
13305 source = vs;
13306 break;
13307 default:
13308 TCU_FAIL("Invalid enum");
13309 }
13310 }
13311
13312 return source;
13313 }
13314
13315 /** Get description of test case
13316 *
13317 * @param test_case_index Index of test case
13318 *
13319 * @return Test case description
13320 **/
13321 std::string VaryingStructureMemberLocationTest::getTestCaseName(GLuint test_case_index)
13322 {
13323 std::stringstream stream;
13324 testCase& test_case = m_test_cases[test_case_index];
13325
13326 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13327
13328 if (true == test_case.m_is_input)
13329 {
13330 stream << "input";
13331 }
13332 else
13333 {
13334 stream << "output";
13335 }
13336
13337 return stream.str();
13338 }
13339
13340 /** Get number of test cases
13341 *
13342 * @return Number of test cases
13343 **/
13344 GLuint VaryingStructureMemberLocationTest::getTestCaseNumber()
13345 {
13346 return static_cast<GLuint>(m_test_cases.size());
13347 }
13348
13349 /** Selects if "compute" stage is relevant for test
13350 *
13351 * @param ignored
13352 *
13353 * @return false
13354 **/
13355 bool VaryingStructureMemberLocationTest::isComputeRelevant(GLuint /* test_case_index */)
13356 {
13357 return false;
13358 }
13359
13360 /** Prepare all test cases
13361 *
13362 **/
13363 void VaryingStructureMemberLocationTest::testInit()
13364 {
13365 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13366 {
13367 if (Utils::Shader::COMPUTE == stage)
13368 {
13369 continue;
13370 }
13371
13372 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
13373 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
13374
13375 m_test_cases.push_back(test_case_in);
13376
13377 if (Utils::Shader::FRAGMENT != stage)
13378 {
13379 m_test_cases.push_back(test_case_out);
13380 }
13381 }
13382 }
13383
13384 /** Constructor
13385 *
13386 * @param context Test framework context
13387 **/
13388 VaryingBlockLocationsTest::VaryingBlockLocationsTest(deqp::Context& context)
13389 : TextureTestBase(context, "varying_block_locations",
13390 "Test verifies that locations are respected when blocks are used as in and out ")
13391 {
13392 }
13393
13394 /** Prepare code snippet that will pass in variables to out variables
13395 *
13396 * @param ignored
13397 * @param varying_passthrough Collection of connections between in and out variables
13398 * @param stage Shader stage
13399 *
13400 * @return Code that pass in variables to next stage
13401 **/
13402 std::string VaryingBlockLocationsTest::getPassSnippet(GLuint /* test_case_index */,
13403 Utils::VaryingPassthrough& varying_passthrough,
13404 Utils::Shader::STAGES stage)
13405 {
13406 std::string result;
13407
13408 if (Utils::Shader::VERTEX != stage)
13409 {
13410 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
13411 }
13412 else
13413 {
13414 result = "vs_tcs_block.third = vs_in_third;\n"
13415 " vs_tcs_block.fourth = vs_in_fourth;\n"
13416 " vs_tcs_block.fifth = vs_in_fifth;\n";
13417 }
13418
13419 return result;
13420 }
13421
13422 /** Get interface of program
13423 *
13424 * @param ignored
13425 * @param program_interface Interface of program
13426 * @param varying_passthrough Collection of connections between in and out variables
13427 **/
13428 void VaryingBlockLocationsTest::getProgramInterface(GLuint /* test_case_index */,
13429 Utils::ProgramInterface& program_interface,
13430 Utils::VaryingPassthrough& varying_passthrough)
13431 {
13432 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
13433 const Utils::Type vec4 = Utils::Type::vec4;
13434
13435 /* Prepare data */
13436 m_third_data = vec4.GenerateData();
13437 m_fourth_data = vec4.GenerateData();
13438 m_fifth_data = vec4.GenerateData();
13439
13440 /* Memory layout is different from location layout */
13441 const GLuint fifth_offset = 0u;
13442 const GLuint third_offset = static_cast<GLuint>(fifth_offset + m_fifth_data.size());
13443 const GLuint fourth_offset = static_cast<GLuint>(third_offset + m_fourth_data.size());
13444
13445 m_data.resize(fourth_offset + m_fourth_data.size());
13446 GLubyte* ptr = (GLubyte*)&m_data[0];
13447 memcpy(ptr + third_offset, &m_third_data[0], m_third_data.size());
13448 memcpy(ptr + fourth_offset, &m_fourth_data[0], m_fourth_data.size());
13449 memcpy(ptr + fifth_offset, &m_fifth_data[0], m_fifth_data.size());
13450
13451 Utils::Interface* block = program_interface.Block("vs_tcs_Block");
13452
13453 block->Member("fifth", "" /* qualifiers */, 0 /* component */, 4 /* location */, vec4, false /* normalized */,
13454 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */);
13455
13456 block->Member("third", "layout (location = 2)" /* qualifiers */, 0 /* component */, 2 /* location */, vec4,
13457 false /* normalized */, 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */);
13458
13459 block->Member("fourth", "" /* qualifiers */, 0 /* component */, 3 /* location */, vec4, false /* normalized */,
13460 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */);
13461
13462 si.Output("vs_tcs_block", "layout (location = 4)", 0 /* component */, 4 /* location */, block,
13463 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
13464 m_data.size() /* data_size */);
13465
13466 si.Input("vs_in_third", "layout (location = 0)", 0 /* component */, 0 /* location */, vec4, false /* normalized */,
13467 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */,
13468 (GLvoid*)&m_third_data[0] /* data */, m_third_data.size() /* data_size */);
13469
13470 si.Input("vs_in_fourth", "layout (location = 1)", 0 /* component */, 1 /* location */, vec4, false /* normalized */,
13471 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */,
13472 (GLvoid*)&m_fourth_data[0] /* data */, m_fourth_data.size() /* data_size */);
13473
13474 si.Input("vs_in_fifth", "layout (location = 2)", 0 /* component */, 2 /* location */, vec4, false /* normalized */,
13475 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */,
13476 (GLvoid*)&m_fifth_data[0] /* data */, m_fifth_data.size() /* data_size */);
13477
13478 program_interface.CloneVertexInterface(varying_passthrough);
13479 }
13480
13481 /** Selects if "compute" stage is relevant for test
13482 *
13483 * @param ignored
13484 *
13485 * @return false
13486 **/
13487 bool VaryingBlockLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13488 {
13489 return false;
13490 }
13491
13492 /** This test should be run with separable programs
13493 *
13494 * @param ignored
13495 *
13496 * @return true
13497 **/
13498 bool VaryingBlockLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13499 {
13500 return false;
13501 }
13502
13503 /** Constructor
13504 *
13505 * @param context Test framework context
13506 **/
13507 VaryingBlockMemberLocationsTest::VaryingBlockMemberLocationsTest(deqp::Context& context)
13508 : NegativeTestBase(
13509 context, "varying_block_member_locations",
13510 "Test verifies that compilation error is reported when not all members of block are qualified with location")
13511 {
13512 }
13513
13514 /** Source for given test case and stage
13515 *
13516 * @param test_case_index Index of test case
13517 * @param stage Shader stage
13518 *
13519 * @return Shader source
13520 **/
13521 std::string VaryingBlockMemberLocationsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13522 {
13523 static const GLchar* block_definition_all = "Goku {\n"
13524 " layout (location = 2) vec4 gohan;\n"
13525 " layout (location = 4) vec4 goten;\n"
13526 " layout (location = 6) vec4 chichi;\n"
13527 "} gokuARRAY;\n";
13528 static const GLchar* block_definition_default = "Goku {\n"
13529 " vec4 gohan;\n"
13530 " vec4 goten;\n"
13531 " vec4 chichi;\n"
13532 "} gokuARRAY;\n";
13533 static const GLchar* block_definition_one = "Goku {\n"
13534 " vec4 gohan;\n"
13535 " layout (location = 4) vec4 goten;\n"
13536 " vec4 chichi;\n"
13537 "} gokuARRAY;\n";
13538 static const GLchar* input_use = " result += gokuINDEX.gohan + gokuINDEX.goten + gokuINDEX.chichi;\n";
13539 static const GLchar* output_use = " gokuINDEX.gohan = result / 2;\n"
13540 " gokuINDEX.goten = result / 4 - gokuINDEX.gohan;\n"
13541 " gokuINDEX.chichi = result / 8 - gokuINDEX.goten;\n";
13542 static const GLchar* fs = "#version 430 core\n"
13543 "#extension GL_ARB_enhanced_layouts : require\n"
13544 "\n"
13545 "in vec4 gs_fs;\n"
13546 "out vec4 fs_out;\n"
13547 "\n"
13548 "void main()\n"
13549 "{\n"
13550 " fs_out = gs_fs;\n"
13551 "}\n"
13552 "\n";
13553 static const GLchar* fs_tested = "#version 430 core\n"
13554 "#extension GL_ARB_enhanced_layouts : require\n"
13555 "\n"
13556 "DIRECTION BLOCK_DEFINITION"
13557 "\n"
13558 "in vec4 gs_fs;\n"
13559 "out vec4 fs_out;\n"
13560 "\n"
13561 "void main()\n"
13562 "{\n"
13563 " vec4 result = gs_fs;\n"
13564 "\n"
13565 "VARIABLE_USE"
13566 "\n"
13567 " fs_out = result;\n"
13568 "}\n"
13569 "\n";
13570 static const GLchar* gs = "#version 430 core\n"
13571 "#extension GL_ARB_enhanced_layouts : require\n"
13572 "\n"
13573 "layout(points) in;\n"
13574 "layout(triangle_strip, max_vertices = 4) out;\n"
13575 "\n"
13576 "in vec4 tes_gs[];\n"
13577 "out vec4 gs_fs;\n"
13578 "\n"
13579 "void main()\n"
13580 "{\n"
13581 " gs_fs = tes_gs[0];\n"
13582 " gl_Position = vec4(-1, -1, 0, 1);\n"
13583 " EmitVertex();\n"
13584 " gs_fs = tes_gs[0];\n"
13585 " gl_Position = vec4(-1, 1, 0, 1);\n"
13586 " EmitVertex();\n"
13587 " gs_fs = tes_gs[0];\n"
13588 " gl_Position = vec4(1, -1, 0, 1);\n"
13589 " EmitVertex();\n"
13590 " gs_fs = tes_gs[0];\n"
13591 " gl_Position = vec4(1, 1, 0, 1);\n"
13592 " EmitVertex();\n"
13593 "}\n"
13594 "\n";
13595 static const GLchar* gs_tested = "#version 430 core\n"
13596 "#extension GL_ARB_enhanced_layouts : require\n"
13597 "\n"
13598 "layout(points) in;\n"
13599 "layout(triangle_strip, max_vertices = 4) out;\n"
13600 "\n"
13601 "DIRECTION BLOCK_DEFINITION"
13602 "\n"
13603 "in vec4 tes_gs[];\n"
13604 "out vec4 gs_fs;\n"
13605 "\n"
13606 "void main()\n"
13607 "{\n"
13608 " vec4 result = tes_gs[0];\n"
13609 "\n"
13610 "VARIABLE_USE"
13611 "\n"
13612 " gs_fs = result;\n"
13613 " gl_Position = vec4(-1, -1, 0, 1);\n"
13614 " EmitVertex();\n"
13615 " gs_fs = result;\n"
13616 " gl_Position = vec4(-1, 1, 0, 1);\n"
13617 " EmitVertex();\n"
13618 " gs_fs = result;\n"
13619 " gl_Position = vec4(1, -1, 0, 1);\n"
13620 " EmitVertex();\n"
13621 " gs_fs = result;\n"
13622 " gl_Position = vec4(1, 1, 0, 1);\n"
13623 " EmitVertex();\n"
13624 "}\n"
13625 "\n";
13626 static const GLchar* tcs = "#version 430 core\n"
13627 "#extension GL_ARB_enhanced_layouts : require\n"
13628 "\n"
13629 "layout(vertices = 1) out;\n"
13630 "\n"
13631 "in vec4 vs_tcs[];\n"
13632 "out vec4 tcs_tes[];\n"
13633 "\n"
13634 "void main()\n"
13635 "{\n"
13636 "\n"
13637 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13638 "\n"
13639 " gl_TessLevelOuter[0] = 1.0;\n"
13640 " gl_TessLevelOuter[1] = 1.0;\n"
13641 " gl_TessLevelOuter[2] = 1.0;\n"
13642 " gl_TessLevelOuter[3] = 1.0;\n"
13643 " gl_TessLevelInner[0] = 1.0;\n"
13644 " gl_TessLevelInner[1] = 1.0;\n"
13645 "}\n"
13646 "\n";
13647 static const GLchar* tcs_tested = "#version 430 core\n"
13648 "#extension GL_ARB_enhanced_layouts : require\n"
13649 "\n"
13650 "layout(vertices = 1) out;\n"
13651 "\n"
13652 "DIRECTION BLOCK_DEFINITION"
13653 "\n"
13654 "in vec4 vs_tcs[];\n"
13655 "out vec4 tcs_tes[];\n"
13656 "\n"
13657 "void main()\n"
13658 "{\n"
13659 " vec4 result = vs_tcs[gl_InvocationID];\n"
13660 "\n"
13661 "VARIABLE_USE"
13662 "\n"
13663 " tcs_tes[gl_InvocationID] = result;\n"
13664 "\n"
13665 " gl_TessLevelOuter[0] = 1.0;\n"
13666 " gl_TessLevelOuter[1] = 1.0;\n"
13667 " gl_TessLevelOuter[2] = 1.0;\n"
13668 " gl_TessLevelOuter[3] = 1.0;\n"
13669 " gl_TessLevelInner[0] = 1.0;\n"
13670 " gl_TessLevelInner[1] = 1.0;\n"
13671 "}\n"
13672 "\n";
13673 static const GLchar* tes = "#version 430 core\n"
13674 "#extension GL_ARB_enhanced_layouts : require\n"
13675 "\n"
13676 "layout(isolines, point_mode) in;\n"
13677 "\n"
13678 "in vec4 tcs_tes[];\n"
13679 "out vec4 tes_gs;\n"
13680 "\n"
13681 "void main()\n"
13682 "{\n"
13683 " tes_gs = tcs_tes[0];\n"
13684 "}\n"
13685 "\n";
13686 static const GLchar* tes_tested = "#version 430 core\n"
13687 "#extension GL_ARB_enhanced_layouts : require\n"
13688 "\n"
13689 "layout(isolines, point_mode) in;\n"
13690 "\n"
13691 "DIRECTION BLOCK_DEFINITION"
13692 "\n"
13693 "in vec4 tcs_tes[];\n"
13694 "out vec4 tes_gs;\n"
13695 "\n"
13696 "void main()\n"
13697 "{\n"
13698 " vec4 result = tcs_tes[0];\n"
13699 "\n"
13700 "VARIABLE_USE"
13701 "\n"
13702 " tes_gs = result;\n"
13703 "}\n"
13704 "\n";
13705 static const GLchar* vs = "#version 430 core\n"
13706 "#extension GL_ARB_enhanced_layouts : require\n"
13707 "\n"
13708 "in vec4 in_vs;\n"
13709 "out vec4 vs_tcs;\n"
13710 "\n"
13711 "void main()\n"
13712 "{\n"
13713 " vs_tcs = in_vs;\n"
13714 "}\n"
13715 "\n";
13716 static const GLchar* vs_tested = "#version 430 core\n"
13717 "#extension GL_ARB_enhanced_layouts : require\n"
13718 "\n"
13719 "DIRECTION BLOCK_DEFINITION"
13720 "\n"
13721 "in vec4 in_vs;\n"
13722 "out vec4 vs_tcs;\n"
13723 "\n"
13724 "void main()\n"
13725 "{\n"
13726 " vec4 result = in_vs;\n"
13727 "\n"
13728 "VARIABLE_USE"
13729 "\n"
13730 " vs_tcs = result;\n"
13731 "}\n"
13732 "\n";
13733
13734 static const GLchar* shaders_in[6][6] = { /* cs */ { 0, 0, 0, 0, 0, 0 },
13735 /* vs */ { 0, vs_tested, tcs, tes, gs, fs },
13736 /* tcs */ { 0, vs_tested, tcs_tested, tes, gs, fs },
13737 /* tes */ { 0, vs, tcs_tested, tes_tested, gs, fs },
13738 /* gs */ { 0, vs, tcs, tes_tested, gs_tested, fs },
13739 /* fs */ { 0, vs, tcs, tes, gs_tested, fs_tested } };
13740
13741 static const GLchar* shaders_out[6][6] = { /* cs */ { 0, 0, 0, 0, 0, 0 },
13742 /* vs */ { 0, vs_tested, tcs_tested, tes, gs, fs },
13743 /* tcs */ { 0, vs, tcs_tested, tes_tested, gs, fs },
13744 /* tes */ { 0, vs, tcs, tes_tested, gs_tested, fs },
13745 /* gs */ { 0, vs, tcs, tes, gs_tested, fs_tested },
13746 /* fs */ { 0, 0, 0, 0, 0, 0 } };
13747
13748 static const bool require_modifications_in[6][6] = {
13749 /* cs */ { false, false, false, false, false, false },
13750 /* vs */ { false, true, false, false, false, false },
13751 /* tcs */ { false, true, true, false, false, false },
13752 /* tes */ { false, false, true, true, false, false },
13753 /* gs */ { false, false, false, true, true, false },
13754 /* fs */ { false, false, false, false, true, true }
13755 };
13756
13757 static const bool require_modifications_out[6][6] = {
13758 /* cs */ { false, false, false, false, false, false },
13759 /* vs */ { false, true, true, false, false, false },
13760 /* tcs */ { false, false, true, true, false, false },
13761 /* tes */ { false, false, false, true, true, false },
13762 /* gs */ { false, false, false, false, true, true },
13763 /* fs */ { false, false, false, false, false, false }
13764 };
13765
13766 const GLchar* array = "";
13767 const GLchar* direction = "out";
13768 const GLchar* index = "";
13769 bool require_modifications = false;
13770 std::string source;
13771 testCase& test_case = m_test_cases[test_case_index];
13772 const GLchar* var_use = output_use;
13773
13774 if (true == test_case.m_is_input)
13775 {
13776 require_modifications = require_modifications_in[test_case.m_stage][stage];
13777 source = shaders_in[test_case.m_stage][stage];
13778
13779 if (test_case.m_stage == stage)
13780 {
13781 direction = "in";
13782 var_use = input_use;
13783 }
13784 }
13785 else
13786 {
13787 require_modifications = require_modifications_out[test_case.m_stage][stage];
13788 source = shaders_out[test_case.m_stage][stage];
13789
13790 if (test_case.m_stage != stage)
13791 {
13792 direction = "in";
13793 var_use = input_use;
13794 }
13795 }
13796
13797 const GLchar* definition = test_case.m_qualify_all ? block_definition_all
13798 : block_definition_default;
13799
13800 if (test_case.m_stage == stage)
13801 {
13802 if (true == test_case.m_qualify_all)
13803 {
13804 definition = block_definition_all;
13805 }
13806 else
13807 {
13808 definition = block_definition_one;
13809 }
13810 }
13811
13812 // Geometry shader inputs, tessellation control shader inputs and outputs, and tessellation evaluation
13813 // inputs all have an additional level of arrayness relative to other shader inputs and outputs.
13814 switch (stage)
13815 {
13816 case Utils::Shader::FRAGMENT:
13817 break;
13818 case Utils::Shader::TESS_CTRL:
13819 array = "[]";
13820 index = "[gl_InvocationID]";
13821 break;
13822 // geometry shader's input must have one more dimension than tessellation evaluation shader's output,
13823 // the GS input block is an array, so the DS output can't be declared as an array
13824 case Utils::Shader::GEOMETRY:
13825 case Utils::Shader::TESS_EVAL:
13826 {
13827 if (std::string(direction) == std::string("in")) // match HS output and DS input
13828 {
13829 array = "[]";
13830 index = "[0]";
13831 }
13832 else // match DS output and GS input
13833 {
13834 array = "";
13835 index = "";
13836 }
13837 }
13838 break;
13839 case Utils::Shader::VERTEX:
13840 break;
13841 default:
13842 TCU_FAIL("Invalid enum");
13843 }
13844
13845 if (true == require_modifications)
13846 {
13847 size_t position = 0;
13848 size_t temp;
13849
13850 Utils::replaceToken("DIRECTION", position, direction, source);
13851 temp = position;
13852 Utils::replaceToken("BLOCK_DEFINITION", position, definition, source);
13853 position = temp;
13854 Utils::replaceToken("ARRAY", position, array, source);
13855 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13856
13857 Utils::replaceAllTokens("INDEX", index, source);
13858 }
13859 else
13860 {
13861 switch (stage)
13862 {
13863 case Utils::Shader::FRAGMENT:
13864 source = fs;
13865 break;
13866 case Utils::Shader::GEOMETRY:
13867 source = gs;
13868 break;
13869 case Utils::Shader::TESS_CTRL:
13870 source = tcs;
13871 break;
13872 case Utils::Shader::TESS_EVAL:
13873 source = tes;
13874 break;
13875 case Utils::Shader::VERTEX:
13876 source = vs;
13877 break;
13878 default:
13879 TCU_FAIL("Invalid enum");
13880 }
13881 }
13882
13883 return source;
13884 }
13885
13886 /** Get description of test case
13887 *
13888 * @param test_case_index Index of test case
13889 *
13890 * @return Test case description
13891 **/
13892 std::string VaryingBlockMemberLocationsTest::getTestCaseName(GLuint test_case_index)
13893 {
13894 std::stringstream stream;
13895 testCase& test_case = m_test_cases[test_case_index];
13896
13897 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13898
13899 if (true == test_case.m_is_input)
13900 {
13901 stream << "input";
13902 }
13903 else
13904 {
13905 stream << "output";
13906 }
13907
13908 if (true == test_case.m_qualify_all)
13909 {
13910 stream << ", all members qualified";
13911 }
13912 else
13913 {
13914 stream << ", not all members qualified";
13915 }
13916
13917 return stream.str();
13918 }
13919
13920 /** Get number of test cases
13921 *
13922 * @return Number of test cases
13923 **/
13924 GLuint VaryingBlockMemberLocationsTest::getTestCaseNumber()
13925 {
13926 return static_cast<GLuint>(m_test_cases.size());
13927 }
13928
13929 /** Selects if "compute" stage is relevant for test
13930 *
13931 * @param ignored
13932 *
13933 * @return false
13934 **/
13935 bool VaryingBlockMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13936 {
13937 return false;
13938 }
13939
13940 /** Selects if compilation failure is expected result
13941 *
13942 * @param test_case_index Index of test case
13943 *
13944 * @return false when all members are qualified, true otherwise
13945 **/
13946 bool VaryingBlockMemberLocationsTest::isFailureExpected(GLuint test_case_index)
13947 {
13948 return (true != m_test_cases[test_case_index].m_qualify_all);
13949 }
13950
13951 /** Prepare all test cases
13952 *
13953 **/
13954 void VaryingBlockMemberLocationsTest::testInit()
13955 {
13956 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13957 {
13958 if (Utils::Shader::COMPUTE == stage)
13959 {
13960 continue;
13961 }
13962
13963 testCase test_case_in_all = { true, true, (Utils::Shader::STAGES)stage };
13964 testCase test_case_in_one = { true, false, (Utils::Shader::STAGES)stage };
13965 testCase test_case_out_all = { false, true, (Utils::Shader::STAGES)stage };
13966 testCase test_case_out_one = { false, false, (Utils::Shader::STAGES)stage };
13967
13968 if (Utils::Shader::VERTEX != stage)
13969 {
13970 m_test_cases.push_back(test_case_in_all);
13971 m_test_cases.push_back(test_case_in_one);
13972 }
13973
13974 if (Utils::Shader::FRAGMENT != stage)
13975 {
13976 m_test_cases.push_back(test_case_out_all);
13977 m_test_cases.push_back(test_case_out_one);
13978 }
13979 }
13980 }
13981
13982 /** Constructor
13983 *
13984 * @param context Test framework context
13985 **/
13986 VaryingBlockAutomaticMemberLocationsTest::VaryingBlockAutomaticMemberLocationsTest(deqp::Context& context)
13987 : NegativeTestBase(
13988 context, "varying_block_automatic_member_locations",
13989 "Test verifies that compiler assigns subsequent locations to block members, even if this causes errors")
13990 {
13991 }
13992
13993 /** Source for given test case and stage
13994 *
13995 * @param test_case_index Index of test case
13996 * @param stage Shader stage
13997 *
13998 * @return Shader source
13999 **/
14000 std::string VaryingBlockAutomaticMemberLocationsTest::getShaderSource(GLuint test_case_index,
14001 Utils::Shader::STAGES stage)
14002 {
14003 static const GLchar* block_definition = "layout (location = 2) DIRECTION DBZ {\n"
14004 " vec4 goku;\n"
14005 " vec4 gohan[4];\n"
14006 " vec4 goten;\n"
14007 " layout (location = 1) vec4 chichi;\n"
14008 " vec4 pan;\n"
14009 "} dbzARRAY;\n";
14010 static const GLchar* input_use = " result += dbzINDEX.goku + dbzINDEX.gohan[0] + dbzINDEX.gohan[1] + "
14011 "dbzINDEX.gohan[3] + dbzINDEX.gohan[2] + dbzINDEX.goten + dbzINDEX.chichi + "
14012 "dbzINDEX.pan;\n";
14013 static const GLchar* output_use = " dbzINDEX.goku = result;\n"
14014 " dbzINDEX.gohan[0] = result / 2;\n"
14015 " dbzINDEX.gohan[1] = result / 2.25;\n"
14016 " dbzINDEX.gohan[2] = result / 2.5;\n"
14017 " dbzINDEX.gohan[3] = result / 2.75;\n"
14018 " dbzINDEX.goten = result / 4 - dbzINDEX.gohan[0] - dbzINDEX.gohan[1] - "
14019 "dbzINDEX.gohan[2] - dbzINDEX.gohan[3];\n"
14020 " dbzINDEX.chichi = result / 8 - dbzINDEX.goten;\n"
14021 " dbzINDEX.pan = result / 16 - dbzINDEX.chichi;\n";
14022 static const GLchar* fs = "#version 430 core\n"
14023 "#extension GL_ARB_enhanced_layouts : require\n"
14024 "\n"
14025 "in vec4 gs_fs;\n"
14026 "out vec4 fs_out;\n"
14027 "\n"
14028 "void main()\n"
14029 "{\n"
14030 " fs_out = gs_fs;\n"
14031 "}\n"
14032 "\n";
14033 static const GLchar* fs_tested = "#version 430 core\n"
14034 "#extension GL_ARB_enhanced_layouts : require\n"
14035 "\n"
14036 "BLOCK_DEFINITION"
14037 "\n"
14038 "in vec4 gs_fs;\n"
14039 "out vec4 fs_out;\n"
14040 "\n"
14041 "void main()\n"
14042 "{\n"
14043 " vec4 result = gs_fs;\n"
14044 "\n"
14045 "VARIABLE_USE"
14046 "\n"
14047 " fs_out += result;\n"
14048 "}\n"
14049 "\n";
14050 static const GLchar* gs = "#version 430 core\n"
14051 "#extension GL_ARB_enhanced_layouts : require\n"
14052 "\n"
14053 "layout(points) in;\n"
14054 "layout(triangle_strip, max_vertices = 4) out;\n"
14055 "\n"
14056 "in vec4 tes_gs[];\n"
14057 "out vec4 gs_fs;\n"
14058 "\n"
14059 "void main()\n"
14060 "{\n"
14061 " gs_fs = tes_gs[0];\n"
14062 " gl_Position = vec4(-1, -1, 0, 1);\n"
14063 " EmitVertex();\n"
14064 " gs_fs = tes_gs[0];\n"
14065 " gl_Position = vec4(-1, 1, 0, 1);\n"
14066 " EmitVertex();\n"
14067 " gs_fs = tes_gs[0];\n"
14068 " gl_Position = vec4(1, -1, 0, 1);\n"
14069 " EmitVertex();\n"
14070 " gs_fs = tes_gs[0];\n"
14071 " gl_Position = vec4(1, 1, 0, 1);\n"
14072 " EmitVertex();\n"
14073 "}\n"
14074 "\n";
14075 static const GLchar* gs_tested = "#version 430 core\n"
14076 "#extension GL_ARB_enhanced_layouts : require\n"
14077 "\n"
14078 "layout(points) in;\n"
14079 "layout(triangle_strip, max_vertices = 4) out;\n"
14080 "\n"
14081 "BLOCK_DEFINITION"
14082 "\n"
14083 "in vec4 tes_gs[];\n"
14084 "out vec4 gs_fs;\n"
14085 "\n"
14086 "void main()\n"
14087 "{\n"
14088 " vec4 result = tes_gs[0];\n"
14089 "\n"
14090 "VARIABLE_USE"
14091 "\n"
14092 " gs_fs = result;\n"
14093 " gl_Position = vec4(-1, -1, 0, 1);\n"
14094 " EmitVertex();\n"
14095 " gs_fs = result;\n"
14096 " gl_Position = vec4(-1, 1, 0, 1);\n"
14097 " EmitVertex();\n"
14098 " gs_fs = result;\n"
14099 " gl_Position = vec4(1, -1, 0, 1);\n"
14100 " EmitVertex();\n"
14101 " gs_fs = result;\n"
14102 " gl_Position = vec4(1, 1, 0, 1);\n"
14103 " EmitVertex();\n"
14104 "}\n"
14105 "\n";
14106 static const GLchar* tcs = "#version 430 core\n"
14107 "#extension GL_ARB_enhanced_layouts : require\n"
14108 "\n"
14109 "layout(vertices = 1) out;\n"
14110 "\n"
14111 "in vec4 vs_tcs[];\n"
14112 "out vec4 tcs_tes[];\n"
14113 "\n"
14114 "void main()\n"
14115 "{\n"
14116 "\n"
14117 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14118 "\n"
14119 " gl_TessLevelOuter[0] = 1.0;\n"
14120 " gl_TessLevelOuter[1] = 1.0;\n"
14121 " gl_TessLevelOuter[2] = 1.0;\n"
14122 " gl_TessLevelOuter[3] = 1.0;\n"
14123 " gl_TessLevelInner[0] = 1.0;\n"
14124 " gl_TessLevelInner[1] = 1.0;\n"
14125 "}\n"
14126 "\n";
14127 static const GLchar* tcs_tested = "#version 430 core\n"
14128 "#extension GL_ARB_enhanced_layouts : require\n"
14129 "\n"
14130 "layout(vertices = 1) out;\n"
14131 "\n"
14132 "BLOCK_DEFINITION"
14133 "\n"
14134 "in vec4 vs_tcs[];\n"
14135 "out vec4 tcs_tes[];\n"
14136 "\n"
14137 "void main()\n"
14138 "{\n"
14139 " vec4 result = vs_tcs[gl_InvocationID];\n"
14140 "\n"
14141 "VARIABLE_USE"
14142 "\n"
14143 " tcs_tes[gl_InvocationID] = result;\n"
14144 "\n"
14145 " gl_TessLevelOuter[0] = 1.0;\n"
14146 " gl_TessLevelOuter[1] = 1.0;\n"
14147 " gl_TessLevelOuter[2] = 1.0;\n"
14148 " gl_TessLevelOuter[3] = 1.0;\n"
14149 " gl_TessLevelInner[0] = 1.0;\n"
14150 " gl_TessLevelInner[1] = 1.0;\n"
14151 "}\n"
14152 "\n";
14153 static const GLchar* tes = "#version 430 core\n"
14154 "#extension GL_ARB_enhanced_layouts : require\n"
14155 "\n"
14156 "layout(isolines, point_mode) in;\n"
14157 "\n"
14158 "in vec4 tcs_tes[];\n"
14159 "out vec4 tes_gs;\n"
14160 "\n"
14161 "void main()\n"
14162 "{\n"
14163 " tes_gs = tcs_tes[0];\n"
14164 "}\n"
14165 "\n";
14166 static const GLchar* tes_tested = "#version 430 core\n"
14167 "#extension GL_ARB_enhanced_layouts : require\n"
14168 "\n"
14169 "layout(isolines, point_mode) in;\n"
14170 "\n"
14171 "BLOCK_DEFINITION"
14172 "\n"
14173 "in vec4 tcs_tes[];\n"
14174 "out vec4 tes_gs;\n"
14175 "\n"
14176 "void main()\n"
14177 "{\n"
14178 " vec4 result = tcs_tes[0];\n"
14179 "\n"
14180 "VARIABLE_USE"
14181 "\n"
14182 " tes_gs += result;\n"
14183 "}\n"
14184 "\n";
14185 static const GLchar* vs = "#version 430 core\n"
14186 "#extension GL_ARB_enhanced_layouts : require\n"
14187 "\n"
14188 "in vec4 in_vs;\n"
14189 "out vec4 vs_tcs;\n"
14190 "\n"
14191 "void main()\n"
14192 "{\n"
14193 " vs_tcs = in_vs;\n"
14194 "}\n"
14195 "\n";
14196 static const GLchar* vs_tested = "#version 430 core\n"
14197 "#extension GL_ARB_enhanced_layouts : require\n"
14198 "\n"
14199 "BLOCK_DEFINITION"
14200 "\n"
14201 "in vec4 in_vs;\n"
14202 "out vec4 vs_tcs;\n"
14203 "\n"
14204 "void main()\n"
14205 "{\n"
14206 " vec4 result = in_vs;\n"
14207 "\n"
14208 "VARIABLE_USE"
14209 "\n"
14210 " vs_tcs += result;\n"
14211 "}\n"
14212 "\n";
14213
14214 const GLchar* array = "";
14215 const GLchar* direction = "out";
14216 const GLchar* index = "";
14217 std::string source;
14218 testCase& test_case = m_test_cases[test_case_index];
14219 const GLchar* var_use = output_use;
14220
14221 if (true == test_case.m_is_input)
14222 {
14223 direction = "in ";
14224 var_use = input_use;
14225 }
14226
14227 if (test_case.m_stage == stage)
14228 {
14229 size_t position = 0;
14230 size_t temp;
14231
14232 switch (stage)
14233 {
14234 case Utils::Shader::FRAGMENT:
14235 source = fs_tested;
14236 break;
14237 case Utils::Shader::GEOMETRY:
14238 source = gs_tested;
14239 array = "[]";
14240 index = "[0]";
14241 break;
14242 case Utils::Shader::TESS_CTRL:
14243 source = tcs_tested;
14244 array = "[]";
14245 index = "[gl_InvocationID]";
14246 break;
14247 case Utils::Shader::TESS_EVAL:
14248 source = tes_tested;
14249 array = "[]";
14250 index = "[0]";
14251 break;
14252 case Utils::Shader::VERTEX:
14253 source = vs_tested;
14254 break;
14255 default:
14256 TCU_FAIL("Invalid enum");
14257 }
14258
14259 temp = position;
14260 Utils::replaceToken("BLOCK_DEFINITION", position, block_definition, source);
14261 position = temp;
14262 Utils::replaceToken("DIRECTION", position, direction, source);
14263 Utils::replaceToken("ARRAY", position, array, source);
14264 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14265
14266 Utils::replaceAllTokens("INDEX", index, source);
14267 }
14268 else
14269 {
14270 switch (stage)
14271 {
14272 case Utils::Shader::FRAGMENT:
14273 source = fs;
14274 break;
14275 case Utils::Shader::GEOMETRY:
14276 source = gs;
14277 break;
14278 case Utils::Shader::TESS_CTRL:
14279 source = tcs;
14280 break;
14281 case Utils::Shader::TESS_EVAL:
14282 source = tes;
14283 break;
14284 case Utils::Shader::VERTEX:
14285 source = vs;
14286 break;
14287 default:
14288 TCU_FAIL("Invalid enum");
14289 }
14290 }
14291
14292 return source;
14293 }
14294
14295 /** Get description of test case
14296 *
14297 * @param test_case_index Index of test case
14298 *
14299 * @return Test case description
14300 **/
14301 std::string VaryingBlockAutomaticMemberLocationsTest::getTestCaseName(GLuint test_case_index)
14302 {
14303 std::stringstream stream;
14304 testCase& test_case = m_test_cases[test_case_index];
14305
14306 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
14307
14308 if (true == test_case.m_is_input)
14309 {
14310 stream << "input";
14311 }
14312 else
14313 {
14314 stream << "output";
14315 }
14316
14317 return stream.str();
14318 }
14319
14320 /** Get number of test cases
14321 *
14322 * @return Number of test cases
14323 **/
14324 GLuint VaryingBlockAutomaticMemberLocationsTest::getTestCaseNumber()
14325 {
14326 return static_cast<GLuint>(m_test_cases.size());
14327 }
14328
14329 /** Selects if "compute" stage is relevant for test
14330 *
14331 * @param ignored
14332 *
14333 * @return false
14334 **/
14335 bool VaryingBlockAutomaticMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
14336 {
14337 return false;
14338 }
14339
14340 /** Prepare all test cases
14341 *
14342 **/
14343 void VaryingBlockAutomaticMemberLocationsTest::testInit()
14344 {
14345 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14346 {
14347 if (Utils::Shader::COMPUTE == stage)
14348 {
14349 continue;
14350 }
14351
14352 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
14353 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
14354
14355 if (Utils::Shader::VERTEX != stage)
14356 {
14357 m_test_cases.push_back(test_case_in);
14358 }
14359
14360 if (Utils::Shader::FRAGMENT != stage)
14361 {
14362 m_test_cases.push_back(test_case_out);
14363 }
14364 }
14365 }
14366
14367 /** Constructor
14368 *
14369 * @param context Test framework context
14370 **/
14371 VaryingLocationLimitTest::VaryingLocationLimitTest(deqp::Context& context)
14372 : NegativeTestBase(context, "varying_location_limit",
14373 "Test verifies that compiler reports error when location qualifier exceed limits")
14374 {
14375 }
14376
14377 /** Source for given test case and stage
14378 *
14379 * @param test_case_index Index of test case
14380 * @param stage Shader stage
14381 *
14382 * @return Shader source
14383 **/
14384 std::string VaryingLocationLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
14385 {
14386 static const GLchar* var_definition = "layout (location = LAST + 1) FLAT DIRECTION TYPE gokuARRAY;\n";
14387 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
14388 " {\n"
14389 " result += vec4(1, 0.5, 0.25, 0.125);\n"
14390 " }\n";
14391 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
14392 " if (vec4(0) == result)\n"
14393 " {\n"
14394 " gokuINDEX = TYPE(1);\n"
14395 " }\n";
14396 static const GLchar* fs = "#version 430 core\n"
14397 "#extension GL_ARB_enhanced_layouts : require\n"
14398 "\n"
14399 "in vec4 gs_fs;\n"
14400 "out vec4 fs_out;\n"
14401 "\n"
14402 "void main()\n"
14403 "{\n"
14404 " fs_out = gs_fs;\n"
14405 "}\n"
14406 "\n";
14407 static const GLchar* fs_tested = "#version 430 core\n"
14408 "#extension GL_ARB_enhanced_layouts : require\n"
14409 "\n"
14410 "VAR_DEFINITION"
14411 "\n"
14412 "in vec4 gs_fs;\n"
14413 "out vec4 fs_out;\n"
14414 "\n"
14415 "void main()\n"
14416 "{\n"
14417 " vec4 result = gs_fs;\n"
14418 "\n"
14419 "VARIABLE_USE"
14420 "\n"
14421 " fs_out += result;\n"
14422 "}\n"
14423 "\n";
14424 static const GLchar* gs = "#version 430 core\n"
14425 "#extension GL_ARB_enhanced_layouts : require\n"
14426 "\n"
14427 "layout(points) in;\n"
14428 "layout(triangle_strip, max_vertices = 4) out;\n"
14429 "\n"
14430 "in vec4 tes_gs[];\n"
14431 "out vec4 gs_fs;\n"
14432 "\n"
14433 "void main()\n"
14434 "{\n"
14435 " gs_fs = tes_gs[0];\n"
14436 " gl_Position = vec4(-1, -1, 0, 1);\n"
14437 " EmitVertex();\n"
14438 " gs_fs = tes_gs[0];\n"
14439 " gl_Position = vec4(-1, 1, 0, 1);\n"
14440 " EmitVertex();\n"
14441 " gs_fs = tes_gs[0];\n"
14442 " gl_Position = vec4(1, -1, 0, 1);\n"
14443 " EmitVertex();\n"
14444 " gs_fs = tes_gs[0];\n"
14445 " gl_Position = vec4(1, 1, 0, 1);\n"
14446 " EmitVertex();\n"
14447 "}\n"
14448 "\n";
14449 static const GLchar* gs_tested = "#version 430 core\n"
14450 "#extension GL_ARB_enhanced_layouts : require\n"
14451 "\n"
14452 "layout(points) in;\n"
14453 "layout(triangle_strip, max_vertices = 4) out;\n"
14454 "\n"
14455 "VAR_DEFINITION"
14456 "\n"
14457 "in vec4 tes_gs[];\n"
14458 "out vec4 gs_fs;\n"
14459 "\n"
14460 "void main()\n"
14461 "{\n"
14462 " vec4 result = tes_gs[0];\n"
14463 "\n"
14464 "VARIABLE_USE"
14465 "\n"
14466 " gs_fs = result;\n"
14467 " gl_Position = vec4(-1, -1, 0, 1);\n"
14468 " EmitVertex();\n"
14469 " gs_fs = result;\n"
14470 " gl_Position = vec4(-1, 1, 0, 1);\n"
14471 " EmitVertex();\n"
14472 " gs_fs = result;\n"
14473 " gl_Position = vec4(1, -1, 0, 1);\n"
14474 " EmitVertex();\n"
14475 " gs_fs = result;\n"
14476 " gl_Position = vec4(1, 1, 0, 1);\n"
14477 " EmitVertex();\n"
14478 "}\n"
14479 "\n";
14480 static const GLchar* tcs = "#version 430 core\n"
14481 "#extension GL_ARB_enhanced_layouts : require\n"
14482 "\n"
14483 "layout(vertices = 1) out;\n"
14484 "\n"
14485 "in vec4 vs_tcs[];\n"
14486 "out vec4 tcs_tes[];\n"
14487 "\n"
14488 "void main()\n"
14489 "{\n"
14490 "\n"
14491 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14492 "\n"
14493 " gl_TessLevelOuter[0] = 1.0;\n"
14494 " gl_TessLevelOuter[1] = 1.0;\n"
14495 " gl_TessLevelOuter[2] = 1.0;\n"
14496 " gl_TessLevelOuter[3] = 1.0;\n"
14497 " gl_TessLevelInner[0] = 1.0;\n"
14498 " gl_TessLevelInner[1] = 1.0;\n"
14499 "}\n"
14500 "\n";
14501 static const GLchar* tcs_tested = "#version 430 core\n"
14502 "#extension GL_ARB_enhanced_layouts : require\n"
14503 "\n"
14504 "layout(vertices = 1) out;\n"
14505 "\n"
14506 "VAR_DEFINITION"
14507 "\n"
14508 "in vec4 vs_tcs[];\n"
14509 "out vec4 tcs_tes[];\n"
14510 "\n"
14511 "void main()\n"
14512 "{\n"
14513 " vec4 result = vs_tcs[gl_InvocationID];\n"
14514 "\n"
14515 "VARIABLE_USE"
14516 "\n"
14517 " tcs_tes[gl_InvocationID] = result;\n"
14518 "\n"
14519 " gl_TessLevelOuter[0] = 1.0;\n"
14520 " gl_TessLevelOuter[1] = 1.0;\n"
14521 " gl_TessLevelOuter[2] = 1.0;\n"
14522 " gl_TessLevelOuter[3] = 1.0;\n"
14523 " gl_TessLevelInner[0] = 1.0;\n"
14524 " gl_TessLevelInner[1] = 1.0;\n"
14525 "}\n"
14526 "\n";
14527 static const GLchar* tes = "#version 430 core\n"
14528 "#extension GL_ARB_enhanced_layouts : require\n"
14529 "\n"
14530 "layout(isolines, point_mode) in;\n"
14531 "\n"
14532 "in vec4 tcs_tes[];\n"
14533 "out vec4 tes_gs;\n"
14534 "\n"
14535 "void main()\n"
14536 "{\n"
14537 " tes_gs = tcs_tes[0];\n"
14538 "}\n"
14539 "\n";
14540 static const GLchar* tes_tested = "#version 430 core\n"
14541 "#extension GL_ARB_enhanced_layouts : require\n"
14542 "\n"
14543 "layout(isolines, point_mode) in;\n"
14544 "\n"
14545 "VAR_DEFINITION"
14546 "\n"
14547 "in vec4 tcs_tes[];\n"
14548 "out vec4 tes_gs;\n"
14549 "\n"
14550 "void main()\n"
14551 "{\n"
14552 " vec4 result = tcs_tes[0];\n"
14553 "\n"
14554 "VARIABLE_USE"
14555 "\n"
14556 " tes_gs += result;\n"
14557 "}\n"
14558 "\n";
14559 static const GLchar* vs = "#version 430 core\n"
14560 "#extension GL_ARB_enhanced_layouts : require\n"
14561 "\n"
14562 "in vec4 in_vs;\n"
14563 "out vec4 vs_tcs;\n"
14564 "\n"
14565 "void main()\n"
14566 "{\n"
14567 " vs_tcs = in_vs;\n"
14568 "}\n"
14569 "\n";
14570 static const GLchar* vs_tested = "#version 430 core\n"
14571 "#extension GL_ARB_enhanced_layouts : require\n"
14572 "\n"
14573 "VAR_DEFINITION"
14574 "\n"
14575 "in vec4 in_vs;\n"
14576 "out vec4 vs_tcs;\n"
14577 "\n"
14578 "void main()\n"
14579 "{\n"
14580 " vec4 result = in_vs;\n"
14581 "\n"
14582 "VARIABLE_USE"
14583 "\n"
14584 " vs_tcs += result;\n"
14585 "}\n"
14586 "\n";
14587
14588 std::string source;
14589 testCase& test_case = m_test_cases[test_case_index];
14590
14591 if (test_case.m_stage == stage)
14592 {
14593 const GLchar* array = "";
14594 GLchar buffer[16];
14595 const GLchar* direction = "in ";
14596 const GLchar* flat = "";
14597 const GLchar* index = "";
14598 GLuint last = getLastInputLocation(stage, test_case.m_type, 0, true);
14599 size_t position = 0;
14600 size_t temp;
14601 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
14602 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
14603 const GLchar* var_use = input_use;
14604
14605 if (false == test_case.m_is_input)
14606 {
14607 direction = "out";
14608 last = getLastOutputLocation(stage, test_case.m_type, 0, true);
14609 storage = Utils::Variable::VARYING_OUTPUT;
14610 var_use = output_use;
14611 }
14612
14613 if (true == isFlatRequired(stage, test_case.m_type, storage))
14614 {
14615 flat = "flat";
14616 }
14617
14618 sprintf(buffer, "%d", last);
14619
14620 switch (stage)
14621 {
14622 case Utils::Shader::FRAGMENT:
14623 source = fs_tested;
14624 break;
14625 case Utils::Shader::GEOMETRY:
14626 source = gs_tested;
14627 array = "[]";
14628 index = "[0]";
14629 break;
14630 case Utils::Shader::TESS_CTRL:
14631 source = tcs_tested;
14632 array = "[]";
14633 index = "[gl_InvocationID]";
14634 break;
14635 case Utils::Shader::TESS_EVAL:
14636 source = tes_tested;
14637 array = "[]";
14638 index = "[0]";
14639 break;
14640 case Utils::Shader::VERTEX:
14641 source = vs_tested;
14642 break;
14643 default:
14644 TCU_FAIL("Invalid enum");
14645 }
14646
14647 temp = position;
14648 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
14649 position = temp;
14650 Utils::replaceToken("LAST", position, buffer, source);
14651 Utils::replaceToken("FLAT", position, flat, source);
14652 Utils::replaceToken("DIRECTION", position, direction, source);
14653 Utils::replaceToken("ARRAY", position, array, source);
14654 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14655
14656 Utils::replaceAllTokens("TYPE", type_name, source);
14657 Utils::replaceAllTokens("INDEX", index, source);
14658 }
14659 else
14660 {
14661 switch (stage)
14662 {
14663 case Utils::Shader::FRAGMENT:
14664 source = fs;
14665 break;
14666 case Utils::Shader::GEOMETRY:
14667 source = gs;
14668 break;
14669 case Utils::Shader::TESS_CTRL:
14670 source = tcs;
14671 break;
14672 case Utils::Shader::TESS_EVAL:
14673 source = tes;
14674 break;
14675 case Utils::Shader::VERTEX:
14676 source = vs;
14677 break;
14678 default:
14679 TCU_FAIL("Invalid enum");
14680 }
14681 }
14682
14683 return source;
14684 }
14685
14686 /** Get description of test case
14687 *
14688 * @param test_case_index Index of test case
14689 *
14690 * @return Test case description
14691 **/
14692 std::string VaryingLocationLimitTest::getTestCaseName(GLuint test_case_index)
14693 {
14694 std::stringstream stream;
14695 testCase& test_case = m_test_cases[test_case_index];
14696
14697 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
14698 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
14699
14700 if (true == test_case.m_is_input)
14701 {
14702 stream << "input";
14703 }
14704 else
14705 {
14706 stream << "output";
14707 }
14708
14709 return stream.str();
14710 }
14711
14712 /** Get number of test cases
14713 *
14714 * @return Number of test cases
14715 **/
14716 GLuint VaryingLocationLimitTest::getTestCaseNumber()
14717 {
14718 return static_cast<GLuint>(m_test_cases.size());
14719 }
14720
14721 /** Selects if "compute" stage is relevant for test
14722 *
14723 * @param ignored
14724 *
14725 * @return false
14726 **/
14727 bool VaryingLocationLimitTest::isComputeRelevant(GLuint /* test_case_index */)
14728 {
14729 return false;
14730 }
14731
14732 /** Prepare all test cases
14733 *
14734 **/
14735 void VaryingLocationLimitTest::testInit()
14736 {
14737 const GLuint n_types = getTypesNumber();
14738
14739 for (GLuint i = 0; i < n_types; ++i)
14740 {
14741 const Utils::Type& type = getType(i);
14742
14743 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14744 {
14745 if (Utils::Shader::COMPUTE == stage)
14746 {
14747 continue;
14748 }
14749
14750 testCase test_case_in = { true, type, (Utils::Shader::STAGES)stage };
14751 testCase test_case_out = { false, type, (Utils::Shader::STAGES)stage };
14752
14753 m_test_cases.push_back(test_case_in);
14754
14755 if (Utils::Shader::FRAGMENT != stage)
14756 {
14757 m_test_cases.push_back(test_case_out);
14758 }
14759 }
14760 }
14761 }
14762
14763 /** Constructor
14764 *
14765 * @param context Test framework context
14766 **/
14767 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context)
14768 : VaryingLocationsTest(context, "varying_components",
14769 "Test verifies that input and output components are respected")
14770 {
14771 }
14772
14773 /** Constructor
14774 *
14775 * @param context Test framework context
14776 * @param test_name Name of test
14777 * @param test_description Description of test
14778 **/
14779 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context, const glw::GLchar* test_name,
14780 const glw::GLchar* test_description)
14781 : VaryingLocationsTest(context, test_name, test_description)
14782 {
14783 }
14784
14785 /** Get interface of program
14786 *
14787 * @param test_case_index Test case
14788 * @param program_interface Interface of program
14789 * @param varying_passthrough Collection of connections between in and out variables
14790 **/
14791 void VaryingComponentsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
14792 Utils::VaryingPassthrough& varying_passthrough)
14793 {
14794 GLuint array_length = getArrayLength();
14795 const testCase& test_case = m_test_cases[test_case_index];
14796 const Utils::Type vector_type = Utils::Type::GetType(test_case.m_type, 1, 4);
14797 Utils::ShaderInterface si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
14798
14799 /* Zero means no array, however we still need at least 1 slot of data */
14800 if (0 == array_length)
14801 {
14802 array_length += 1;
14803 }
14804
14805 /* Generate data */
14806 const std::vector<GLubyte>& data = vector_type.GenerateDataPacked();
14807 const size_t data_size = data.size();
14808
14809 /* Prepare data for variables */
14810 m_data.resize(array_length * data_size);
14811
14812 GLubyte* dst = &m_data[0];
14813 const GLubyte* src = &data[0];
14814
14815 for (GLuint i = 0; i < array_length; ++i)
14816 {
14817 memcpy(dst + data_size * i, src, data_size);
14818 }
14819
14820 /* Prepare interface for each stage */
14821 prepareShaderStage(Utils::Shader::FRAGMENT, vector_type, program_interface, test_case, varying_passthrough);
14822 prepareShaderStage(Utils::Shader::GEOMETRY, vector_type, program_interface, test_case, varying_passthrough);
14823 prepareShaderStage(Utils::Shader::TESS_CTRL, vector_type, program_interface, test_case, varying_passthrough);
14824 prepareShaderStage(Utils::Shader::TESS_EVAL, vector_type, program_interface, test_case, varying_passthrough);
14825 prepareShaderStage(Utils::Shader::VERTEX, vector_type, program_interface, test_case, varying_passthrough);
14826 }
14827
14828 /** Get type name
14829 *
14830 * @param test_case_index Index of test case
14831 *
14832 * @return Name of type test in test_case_index
14833 **/
14834 std::string VaryingComponentsTest::getTestCaseName(glw::GLuint test_case_index)
14835 {
14836 std::string name;
14837
14838 const testCase& test_case = m_test_cases[test_case_index];
14839
14840 name = "Type: ";
14841
14842 switch (test_case.m_type)
14843 {
14844 case Utils::Type::Double:
14845 name.append(Utils::Type::_double.GetGLSLTypeName());
14846 break;
14847 case Utils::Type::Float:
14848 name.append(Utils::Type::_float.GetGLSLTypeName());
14849 break;
14850 case Utils::Type::Int:
14851 name.append(Utils::Type::_int.GetGLSLTypeName());
14852 break;
14853 case Utils::Type::Uint:
14854 name.append(Utils::Type::uint.GetGLSLTypeName());
14855 break;
14856 }
14857
14858 name.append(", layout: ");
14859
14860 switch (test_case.m_layout)
14861 {
14862 case GVEC4:
14863 name.append("GVEC4");
14864 break;
14865 case SCALAR_GVEC3:
14866 name.append("SCALAR_GVEC3");
14867 break;
14868 case GVEC3_SCALAR:
14869 name.append("GVEC3_SCALAR");
14870 break;
14871 case GVEC2_GVEC2:
14872 name.append("GVEC2_GVEC2");
14873 break;
14874 case GVEC2_SCALAR_SCALAR:
14875 name.append("GVEC2_SCALAR_SCALAR");
14876 break;
14877 case SCALAR_GVEC2_SCALAR:
14878 name.append("SCALAR_GVEC2_SCALAR");
14879 break;
14880 case SCALAR_SCALAR_GVEC2:
14881 name.append("SCALAR_SCALAR_GVEC2");
14882 break;
14883 case SCALAR_SCALAR_SCALAR_SCALAR:
14884 name.append("SCALAR_SCALAR_SCALAR_SCALAR");
14885 break;
14886 }
14887
14888 return name;
14889 }
14890
14891 /** Returns number of types to test
14892 *
14893 * @return Number of types, 34
14894 **/
14895 glw::GLuint VaryingComponentsTest::getTestCaseNumber()
14896 {
14897 return static_cast<GLuint>(m_test_cases.size());
14898 }
14899
14900 /* Prepare test cases */
14901 void VaryingComponentsTest::testInit()
14902 {
14903 // FIXME: add tests for doubles, which have specific rules
14904
14905 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Float));
14906 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Float));
14907 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Float));
14908 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Float));
14909 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Float));
14910 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Float));
14911 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Float));
14912 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Float));
14913
14914 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Int));
14915 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Int));
14916 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Int));
14917 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Int));
14918 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Int));
14919 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Int));
14920 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Int));
14921 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Int));
14922
14923 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Uint));
14924 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Uint));
14925 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Uint));
14926 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Uint));
14927 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Uint));
14928 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Uint));
14929 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Uint));
14930 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Uint));
14931 }
14932
14933 /** Inform that test use components
14934 *
14935 * @param ignored
14936 *
14937 * @return true
14938 **/
14939 bool VaryingComponentsTest::useComponentQualifier(glw::GLuint /* test_case_index */)
14940 {
14941 return true;
14942 }
14943
14944 /** Get length of arrays that should be used during test
14945 *
14946 * @return 0u - no array at all
14947 **/
14948 GLuint VaryingComponentsTest::getArrayLength()
14949 {
14950 return 0;
14951 }
14952
14953 std::string VaryingComponentsTest::prepareGlobals(GLuint last_in_location, GLuint last_out_location)
14954 {
14955 std::string globals = VaryingLocationsTest::prepareGlobals(last_in_location, last_out_location);
14956
14957 globals.append("const uint comp_x = 0u;\n"
14958 "const uint comp_y = 1u;\n"
14959 "const uint comp_z = 2u;\n"
14960 "const uint comp_w = 3u;\n");
14961
14962 return globals;
14963 }
14964
14965 /**
14966 *
14967 **/
14968 std::string VaryingComponentsTest::prepareName(const glw::GLchar* name, glw::GLint location, glw::GLint component,
14969 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
14970 {
14971 GLchar buffer[16];
14972 std::string result = "PREFIXNAME_lLOCATION_cCOMPONENT";
14973 size_t position = 0;
14974 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, storage);
14975
14976 Utils::replaceToken("PREFIX", position, prefix, result);
14977 Utils::replaceToken("NAME", position, name, result);
14978
14979 sprintf(buffer, "%d", location);
14980 Utils::replaceToken("LOCATION", position, buffer, result);
14981
14982 sprintf(buffer, "%d", component);
14983 Utils::replaceToken("COMPONENT", position, buffer, result);
14984
14985 return result;
14986 }
14987
14988 std::string VaryingComponentsTest::prepareQualifiers(const glw::GLchar* location, const glw::GLchar* component,
14989 const glw::GLchar* interpolation)
14990 {
14991 size_t position = 0;
14992 std::string qualifiers = "layout (location = LOCATION, component = COMPONENT) INTERPOLATION";
14993
14994 Utils::replaceToken("LOCATION", position, location, qualifiers);
14995 Utils::replaceToken("COMPONENT", position, component, qualifiers);
14996 Utils::replaceToken("INTERPOLATION", position, interpolation, qualifiers);
14997
14998 return qualifiers;
14999 }
15000
15001 /**
15002 *
15003 **/
15004 void VaryingComponentsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& vector_type,
15005 Utils::ProgramInterface& program_interface, const testCase& test_case,
15006 Utils::VaryingPassthrough& varying_passthrough)
15007 {
15008 const GLuint array_length = getArrayLength();
15009 const Utils::Type& basic_type = Utils::Type::GetType(vector_type.m_basic_type, 1 /* n_cols */, 1 /* n_rows */);
15010 descriptor desc_in[8];
15011 descriptor desc_out[8];
15012 const GLuint first_in_loc = 0;
15013 const GLuint first_out_loc = 0;
15014 const GLchar* interpolation = "";
15015 const GLuint last_in_loc = getLastInputLocation(stage, vector_type, array_length, false);
15016 GLuint last_out_loc = 0;
15017 GLuint n_desc = 0;
15018 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
15019
15020 /* Select interpolation */
15021 if ((Utils::Shader::FRAGMENT == stage) || (Utils::Shader::GEOMETRY == stage))
15022 {
15023 interpolation = " flat";
15024 }
15025
15026 if (Utils::Shader::FRAGMENT != stage)
15027 {
15028 last_out_loc = getLastOutputLocation(stage, vector_type, array_length, false);
15029 }
15030
15031 switch (test_case.m_layout)
15032 {
15033 case GVEC4:
15034 n_desc = 2;
15035 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 4, "gvec4");
15036 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 4, "gvec4");
15037
15038 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 4, "gvec4");
15039 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 4, "gvec4");
15040 break;
15041 case SCALAR_GVEC3:
15042 n_desc = 4;
15043 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15044 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15045 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 3, "gvec3");
15046 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 3, "gvec3");
15047
15048 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15049 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15050 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 3, "gvec3");
15051 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 3, "gvec3");
15052 break;
15053 case GVEC3_SCALAR:
15054 n_desc = 4;
15055 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 3, "gvec3");
15056 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 3, "gvec3");
15057 desc_in[2].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15058 desc_in[3].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15059
15060 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 3, "gvec3");
15061 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 3, "gvec3");
15062 desc_out[2].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15063 desc_out[3].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15064 break;
15065 case GVEC2_GVEC2:
15066 n_desc = 4;
15067 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15068 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15069 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15070 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15071
15072 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15073 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15074 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15075 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15076 break;
15077 case GVEC2_SCALAR_SCALAR:
15078 n_desc = 6;
15079 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15080 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15081 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15082 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15083 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15084 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15085
15086 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15087 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15088 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15089 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15090 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15091 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15092 break;
15093 case SCALAR_GVEC2_SCALAR:
15094 n_desc = 6;
15095 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15096 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15097 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 2, "gvec2");
15098 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 2, "gvec2");
15099 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15100 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15101
15102 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15103 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15104 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 2, "gvec2");
15105 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 2, "gvec2");
15106 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15107 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15108 break;
15109 case SCALAR_SCALAR_GVEC2:
15110 n_desc = 6;
15111 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15112 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15113 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15114 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15115 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15116 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15117
15118 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15119 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15120 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15121 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15122 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15123 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15124 break;
15125 case SCALAR_SCALAR_SCALAR_SCALAR:
15126 n_desc = 8;
15127 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15128 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15129 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15130 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15131 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15132 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15133 desc_in[6].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15134 desc_in[7].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15135
15136 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15137 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15138 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15139 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15140 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15141 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15142 desc_out[6].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15143 desc_out[7].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15144 break;
15145 }
15146
15147 for (GLuint i = 0; i < n_desc; ++i)
15148 {
15149 const descriptor& in_desc = desc_in[i];
15150
15151 Utils::Variable* in =
15152 prepareVarying(basic_type, in_desc, interpolation, si, stage, Utils::Variable::VARYING_INPUT);
15153
15154 if (Utils::Shader::FRAGMENT != stage)
15155 {
15156 const descriptor& out_desc = desc_out[i];
15157
15158 Utils::Variable* out =
15159 prepareVarying(basic_type, out_desc, interpolation, si, stage, Utils::Variable::VARYING_OUTPUT);
15160
15161 varying_passthrough.Add(stage, in, out);
15162 }
15163 }
15164
15165 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
15166 }
15167
15168 /**
15169 *
15170 **/
15171 Utils::Variable* VaryingComponentsTest::prepareVarying(const Utils::Type& basic_type, const descriptor& desc,
15172 const GLchar* interpolation, Utils::ShaderInterface& si,
15173 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
15174 {
15175 const GLuint array_length = getArrayLength();
15176 const GLuint component_size = basic_type.GetSize();
15177 const std::string& name = prepareName(desc.m_name, desc.m_location, desc.m_component, stage, storage);
15178 const GLuint offset = desc.m_component * component_size;
15179 const std::string& qual = prepareQualifiers(desc.m_location_str, desc.m_component_str, interpolation);
15180 const GLuint size = desc.m_n_rows * component_size;
15181 const Utils::Type& type = Utils::Type::GetType(basic_type.m_basic_type, 1 /* n_columns */, desc.m_n_rows);
15182 Utils::Variable* var = 0;
15183
15184 if (Utils::Variable::VARYING_INPUT == storage)
15185 {
15186 var = si.Input(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15187 desc.m_location /* expected_location */, type, /* built_in_type */
15188 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15189 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15190 }
15191 else
15192 {
15193 var = si.Output(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15194 desc.m_location /* expected_location */, type, /* built_in_type */
15195 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15196 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15197 }
15198
15199 return var;
15200 }
15201
15202 void VaryingComponentsTest::descriptor::assign(glw::GLint component, const glw::GLchar* component_str,
15203 glw::GLint location, const glw::GLchar* location_str, glw::GLuint n_rows,
15204 const glw::GLchar* name)
15205 {
15206 m_component = component;
15207 m_component_str = component_str;
15208 m_location = location;
15209 m_location_str = location_str;
15210 m_n_rows = n_rows;
15211 m_name = name;
15212 }
15213
15214 VaryingComponentsTest::testCase::testCase(COMPONENTS_LAYOUT layout, Utils::Type::TYPES type)
15215 : m_layout(layout), m_type(type)
15216 {
15217 }
15218
15219 /** Constructor
15220 *
15221 * @param context Test framework context
15222 **/
15223 VaryingArrayComponentsTest::VaryingArrayComponentsTest(deqp::Context& context)
15224 : VaryingComponentsTest(context, "varying_array_components",
15225 "Test verifies that input and output components are respected for arrays")
15226 {
15227 }
15228
15229 /** Get length of arrays that should be used during test
15230 *
15231 * @return 4u
15232 **/
15233 GLuint VaryingArrayComponentsTest::getArrayLength()
15234 {
15235 return 4u;
15236 }
15237
15238 /** Constructor
15239 *
15240 * @param context Test framework context
15241 **/
15242 VaryingExceedingComponentsTest::VaryingExceedingComponentsTest(deqp::Context& context)
15243 : NegativeTestBase(context, "varying_exceeding_components",
15244 "Test verifies that compiler reports error when component qualifier exceed limits")
15245 {
15246 }
15247
15248 /** Source for given test case and stage
15249 *
15250 * @param test_case_index Index of test case
15251 * @param stage Shader stage
15252 *
15253 * @return Shader source
15254 **/
15255 std::string VaryingExceedingComponentsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15256 {
15257 static const GLchar* var_definition_arr =
15258 "layout (location = 1, component = COMPONENT) flat DIRECTION TYPE gokuARRAY[1];\n";
15259 static const GLchar* var_definition_one =
15260 "layout (location = 1, component = COMPONENT) flat DIRECTION TYPE gokuARRAY;\n";
15261 static const GLchar* input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
15262 " {\n"
15263 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15264 " }\n";
15265 static const GLchar* input_use_one = " if (TYPE(0) == gokuINDEX)\n"
15266 " {\n"
15267 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15268 " }\n";
15269 static const GLchar* output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
15270 " if (vec4(0) == result)\n"
15271 " {\n"
15272 " gokuINDEX[0] = TYPE(1);\n"
15273 " }\n";
15274 static const GLchar* output_use_one = " gokuINDEX = TYPE(0);\n"
15275 " if (vec4(0) == result)\n"
15276 " {\n"
15277 " gokuINDEX = TYPE(1);\n"
15278 " }\n";
15279 static const GLchar* fs = "#version 430 core\n"
15280 "#extension GL_ARB_enhanced_layouts : require\n"
15281 "\n"
15282 "in vec4 gs_fs;\n"
15283 "out vec4 fs_out;\n"
15284 "\n"
15285 "void main()\n"
15286 "{\n"
15287 " fs_out = gs_fs;\n"
15288 "}\n"
15289 "\n";
15290 static const GLchar* fs_tested = "#version 430 core\n"
15291 "#extension GL_ARB_enhanced_layouts : require\n"
15292 "\n"
15293 "VAR_DEFINITION"
15294 "\n"
15295 "in vec4 gs_fs;\n"
15296 "out vec4 fs_out;\n"
15297 "\n"
15298 "void main()\n"
15299 "{\n"
15300 " vec4 result = gs_fs;\n"
15301 "\n"
15302 "VARIABLE_USE"
15303 "\n"
15304 " fs_out += result;\n"
15305 "}\n"
15306 "\n";
15307 static const GLchar* gs = "#version 430 core\n"
15308 "#extension GL_ARB_enhanced_layouts : require\n"
15309 "\n"
15310 "layout(points) in;\n"
15311 "layout(triangle_strip, max_vertices = 4) out;\n"
15312 "\n"
15313 "in vec4 tes_gs[];\n"
15314 "out vec4 gs_fs;\n"
15315 "\n"
15316 "void main()\n"
15317 "{\n"
15318 " gs_fs = tes_gs[0];\n"
15319 " gl_Position = vec4(-1, -1, 0, 1);\n"
15320 " EmitVertex();\n"
15321 " gs_fs = tes_gs[0];\n"
15322 " gl_Position = vec4(-1, 1, 0, 1);\n"
15323 " EmitVertex();\n"
15324 " gs_fs = tes_gs[0];\n"
15325 " gl_Position = vec4(1, -1, 0, 1);\n"
15326 " EmitVertex();\n"
15327 " gs_fs = tes_gs[0];\n"
15328 " gl_Position = vec4(1, 1, 0, 1);\n"
15329 " EmitVertex();\n"
15330 "}\n"
15331 "\n";
15332 static const GLchar* gs_tested = "#version 430 core\n"
15333 "#extension GL_ARB_enhanced_layouts : require\n"
15334 "\n"
15335 "layout(points) in;\n"
15336 "layout(triangle_strip, max_vertices = 4) out;\n"
15337 "\n"
15338 "VAR_DEFINITION"
15339 "\n"
15340 "in vec4 tes_gs[];\n"
15341 "out vec4 gs_fs;\n"
15342 "\n"
15343 "void main()\n"
15344 "{\n"
15345 " vec4 result = tes_gs[0];\n"
15346 "\n"
15347 "VARIABLE_USE"
15348 "\n"
15349 " gs_fs = result;\n"
15350 " gl_Position = vec4(-1, -1, 0, 1);\n"
15351 " EmitVertex();\n"
15352 " gs_fs = result;\n"
15353 " gl_Position = vec4(-1, 1, 0, 1);\n"
15354 " EmitVertex();\n"
15355 " gs_fs = result;\n"
15356 " gl_Position = vec4(1, -1, 0, 1);\n"
15357 " EmitVertex();\n"
15358 " gs_fs = result;\n"
15359 " gl_Position = vec4(1, 1, 0, 1);\n"
15360 " EmitVertex();\n"
15361 "}\n"
15362 "\n";
15363 static const GLchar* tcs = "#version 430 core\n"
15364 "#extension GL_ARB_enhanced_layouts : require\n"
15365 "\n"
15366 "layout(vertices = 1) out;\n"
15367 "\n"
15368 "in vec4 vs_tcs[];\n"
15369 "out vec4 tcs_tes[];\n"
15370 "\n"
15371 "void main()\n"
15372 "{\n"
15373 "\n"
15374 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15375 "\n"
15376 " gl_TessLevelOuter[0] = 1.0;\n"
15377 " gl_TessLevelOuter[1] = 1.0;\n"
15378 " gl_TessLevelOuter[2] = 1.0;\n"
15379 " gl_TessLevelOuter[3] = 1.0;\n"
15380 " gl_TessLevelInner[0] = 1.0;\n"
15381 " gl_TessLevelInner[1] = 1.0;\n"
15382 "}\n"
15383 "\n";
15384 static const GLchar* tcs_tested = "#version 430 core\n"
15385 "#extension GL_ARB_enhanced_layouts : require\n"
15386 "\n"
15387 "layout(vertices = 1) out;\n"
15388 "\n"
15389 "VAR_DEFINITION"
15390 "\n"
15391 "in vec4 vs_tcs[];\n"
15392 "out vec4 tcs_tes[];\n"
15393 "\n"
15394 "void main()\n"
15395 "{\n"
15396 " vec4 result = vs_tcs[gl_InvocationID];\n"
15397 "\n"
15398 "VARIABLE_USE"
15399 "\n"
15400 " tcs_tes[gl_InvocationID] = result;\n"
15401 "\n"
15402 " gl_TessLevelOuter[0] = 1.0;\n"
15403 " gl_TessLevelOuter[1] = 1.0;\n"
15404 " gl_TessLevelOuter[2] = 1.0;\n"
15405 " gl_TessLevelOuter[3] = 1.0;\n"
15406 " gl_TessLevelInner[0] = 1.0;\n"
15407 " gl_TessLevelInner[1] = 1.0;\n"
15408 "}\n"
15409 "\n";
15410 static const GLchar* tes = "#version 430 core\n"
15411 "#extension GL_ARB_enhanced_layouts : require\n"
15412 "\n"
15413 "layout(isolines, point_mode) in;\n"
15414 "\n"
15415 "in vec4 tcs_tes[];\n"
15416 "out vec4 tes_gs;\n"
15417 "\n"
15418 "void main()\n"
15419 "{\n"
15420 " tes_gs = tcs_tes[0];\n"
15421 "}\n"
15422 "\n";
15423 static const GLchar* tes_tested = "#version 430 core\n"
15424 "#extension GL_ARB_enhanced_layouts : require\n"
15425 "\n"
15426 "layout(isolines, point_mode) in;\n"
15427 "\n"
15428 "VAR_DEFINITION"
15429 "\n"
15430 "in vec4 tcs_tes[];\n"
15431 "out vec4 tes_gs;\n"
15432 "\n"
15433 "void main()\n"
15434 "{\n"
15435 " vec4 result = tcs_tes[0];\n"
15436 "\n"
15437 "VARIABLE_USE"
15438 "\n"
15439 " tes_gs += result;\n"
15440 "}\n"
15441 "\n";
15442 static const GLchar* vs = "#version 430 core\n"
15443 "#extension GL_ARB_enhanced_layouts : require\n"
15444 "\n"
15445 "in vec4 in_vs;\n"
15446 "out vec4 vs_tcs;\n"
15447 "\n"
15448 "void main()\n"
15449 "{\n"
15450 " vs_tcs = in_vs;\n"
15451 "}\n"
15452 "\n";
15453 static const GLchar* vs_tested = "#version 430 core\n"
15454 "#extension GL_ARB_enhanced_layouts : require\n"
15455 "\n"
15456 "VAR_DEFINITION"
15457 "\n"
15458 "in vec4 in_vs;\n"
15459 "out vec4 vs_tcs;\n"
15460 "\n"
15461 "void main()\n"
15462 "{\n"
15463 " vec4 result = in_vs;\n"
15464 "\n"
15465 "VARIABLE_USE"
15466 "\n"
15467 " vs_tcs += result;\n"
15468 "}\n"
15469 "\n";
15470
15471 std::string source;
15472 testCase& test_case = m_test_cases[test_case_index];
15473
15474 if (test_case.m_stage == stage)
15475 {
15476 const GLchar* array = "";
15477 GLchar buffer[16];
15478 const GLchar* var_definition = 0;
15479 const GLchar* direction = "in ";
15480 const GLchar* index = "";
15481 size_t position = 0;
15482 size_t temp;
15483 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
15484 const GLchar* var_use = 0;
15485
15486 if (false == test_case.m_is_input)
15487 {
15488 direction = "out";
15489
15490 if (false == test_case.m_is_array)
15491 {
15492 var_definition = var_definition_one;
15493 var_use = output_use_one;
15494 }
15495 else
15496 {
15497 var_definition = var_definition_arr;
15498 var_use = output_use_arr;
15499 }
15500 }
15501 else
15502 {
15503 if (false == test_case.m_is_array)
15504 {
15505 var_definition = var_definition_one;
15506 var_use = input_use_one;
15507 }
15508 else
15509 {
15510 var_definition = var_definition_arr;
15511 var_use = input_use_arr;
15512 }
15513 }
15514
15515 sprintf(buffer, "%d", test_case.m_component);
15516
15517 switch (stage)
15518 {
15519 case Utils::Shader::FRAGMENT:
15520 source = fs_tested;
15521 break;
15522 case Utils::Shader::GEOMETRY:
15523 source = gs_tested;
15524 array = "[]";
15525 index = "[0]";
15526 break;
15527 case Utils::Shader::TESS_CTRL:
15528 source = tcs_tested;
15529 array = "[]";
15530 index = "[gl_InvocationID]";
15531 break;
15532 case Utils::Shader::TESS_EVAL:
15533 source = tes_tested;
15534 array = "[]";
15535 index = "[0]";
15536 break;
15537 case Utils::Shader::VERTEX:
15538 source = vs_tested;
15539 break;
15540 default:
15541 TCU_FAIL("Invalid enum");
15542 }
15543
15544 temp = position;
15545 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
15546 position = temp;
15547 Utils::replaceToken("COMPONENT", position, buffer, source);
15548 Utils::replaceToken("DIRECTION", position, direction, source);
15549 Utils::replaceToken("ARRAY", position, array, source);
15550 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
15551
15552 Utils::replaceAllTokens("TYPE", type_name, source);
15553 Utils::replaceAllTokens("INDEX", index, source);
15554 }
15555 else
15556 {
15557 switch (stage)
15558 {
15559 case Utils::Shader::FRAGMENT:
15560 source = fs;
15561 break;
15562 case Utils::Shader::GEOMETRY:
15563 source = gs;
15564 break;
15565 case Utils::Shader::TESS_CTRL:
15566 source = tcs;
15567 break;
15568 case Utils::Shader::TESS_EVAL:
15569 source = tes;
15570 break;
15571 case Utils::Shader::VERTEX:
15572 source = vs;
15573 break;
15574 default:
15575 TCU_FAIL("Invalid enum");
15576 }
15577 }
15578
15579 return source;
15580 }
15581
15582 /** Get description of test case
15583 *
15584 * @param test_case_index Index of test case
15585 *
15586 * @return Test case description
15587 **/
15588 std::string VaryingExceedingComponentsTest::getTestCaseName(GLuint test_case_index)
15589 {
15590 std::stringstream stream;
15591 testCase& test_case = m_test_cases[test_case_index];
15592
15593 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
15594 << " type: " << test_case.m_type.GetGLSLTypeName();
15595
15596 if (true == test_case.m_is_array)
15597 {
15598 stream << "[1]";
15599 }
15600
15601 stream << ", direction: ";
15602
15603 if (true == test_case.m_is_input)
15604 {
15605 stream << "input";
15606 }
15607 else
15608 {
15609 stream << "output";
15610 }
15611
15612 stream << ", component: " << test_case.m_component;
15613
15614 return stream.str();
15615 }
15616
15617 /** Get number of test cases
15618 *
15619 * @return Number of test cases
15620 **/
15621 GLuint VaryingExceedingComponentsTest::getTestCaseNumber()
15622 {
15623 return static_cast<GLuint>(m_test_cases.size());
15624 }
15625
15626 /** Selects if "compute" stage is relevant for test
15627 *
15628 * @param ignored
15629 *
15630 * @return false
15631 **/
15632 bool VaryingExceedingComponentsTest::isComputeRelevant(GLuint /* test_case_index */)
15633 {
15634 return false;
15635 }
15636
15637 /** Prepare all test cases
15638 *
15639 **/
15640 void VaryingExceedingComponentsTest::testInit()
15641 {
15642 static const GLuint n_components_per_location = 4;
15643 const GLuint n_types = getTypesNumber();
15644
15645 for (GLuint i = 0; i < n_types; ++i)
15646 {
15647 const Utils::Type& type = getType(i);
15648 const GLuint n_req_components = type.m_n_rows;
15649 const GLuint valid_component = n_components_per_location - n_req_components;
15650 const GLuint invalid_component = valid_component + 1;
15651
15652 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
15653 {
15654 if (Utils::Shader::COMPUTE == stage)
15655 {
15656 continue;
15657 }
15658
15659 /* Component cannot be used for matrices */
15660 if (1 != type.m_n_columns)
15661 {
15662 continue;
15663 }
15664
15665 testCase test_case_in_arr = { invalid_component, true, true, (Utils::Shader::STAGES)stage, type };
15666 testCase test_case_in_one = { invalid_component, true, false, (Utils::Shader::STAGES)stage, type };
15667 testCase test_case_out_arr = { invalid_component, false, true, (Utils::Shader::STAGES)stage, type };
15668 testCase test_case_out_one = { invalid_component, false, false, (Utils::Shader::STAGES)stage, type };
15669
15670 m_test_cases.push_back(test_case_in_arr);
15671 m_test_cases.push_back(test_case_in_one);
15672
15673 if (Utils::Shader::FRAGMENT != stage)
15674 {
15675 m_test_cases.push_back(test_case_out_arr);
15676 m_test_cases.push_back(test_case_out_one);
15677 }
15678 }
15679 }
15680 }
15681
15682 /** Constructor
15683 *
15684 * @param context Test framework context
15685 **/
15686 VaryingComponentWithoutLocationTest::VaryingComponentWithoutLocationTest(deqp::Context& context)
15687 : NegativeTestBase(context, "varying_component_without_location",
15688 "Test verifies that compiler reports error when component qualifier is used without location")
15689 {
15690 }
15691
15692 /** Source for given test case and stage
15693 *
15694 * @param test_case_index Index of test case
15695 * @param stage Shader stage
15696 *
15697 * @return Shader source
15698 **/
15699 std::string VaryingComponentWithoutLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15700 {
15701 static const GLchar* var_definition = "layout (component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
15702 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
15703 " {\n"
15704 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15705 " }\n";
15706 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
15707 " if (vec4(0) == result)\n"
15708 " {\n"
15709 " gokuINDEX = TYPE(1);\n"
15710 " }\n";
15711 static const GLchar* fs = "#version 430 core\n"
15712 "#extension GL_ARB_enhanced_layouts : require\n"
15713 "\n"
15714 "in vec4 gs_fs;\n"
15715 "out vec4 fs_out;\n"
15716 "\n"
15717 "void main()\n"
15718 "{\n"
15719 " fs_out = gs_fs;\n"
15720 "}\n"
15721 "\n";
15722 static const GLchar* fs_tested = "#version 430 core\n"
15723 "#extension GL_ARB_enhanced_layouts : require\n"
15724 "\n"
15725 "VAR_DEFINITION"
15726 "\n"
15727 "in vec4 gs_fs;\n"
15728 "out vec4 fs_out;\n"
15729 "\n"
15730 "void main()\n"
15731 "{\n"
15732 " vec4 result = gs_fs;\n"
15733 "\n"
15734 "VARIABLE_USE"
15735 "\n"
15736 " fs_out = result;\n"
15737 "}\n"
15738 "\n";
15739 static const GLchar* gs = "#version 430 core\n"
15740 "#extension GL_ARB_enhanced_layouts : require\n"
15741 "\n"
15742 "layout(points) in;\n"
15743 "layout(triangle_strip, max_vertices = 4) out;\n"
15744 "\n"
15745 "in vec4 tes_gs[];\n"
15746 "out vec4 gs_fs;\n"
15747 "\n"
15748 "void main()\n"
15749 "{\n"
15750 " gs_fs = tes_gs[0];\n"
15751 " gl_Position = vec4(-1, -1, 0, 1);\n"
15752 " EmitVertex();\n"
15753 " gs_fs = tes_gs[0];\n"
15754 " gl_Position = vec4(-1, 1, 0, 1);\n"
15755 " EmitVertex();\n"
15756 " gs_fs = tes_gs[0];\n"
15757 " gl_Position = vec4(1, -1, 0, 1);\n"
15758 " EmitVertex();\n"
15759 " gs_fs = tes_gs[0];\n"
15760 " gl_Position = vec4(1, 1, 0, 1);\n"
15761 " EmitVertex();\n"
15762 "}\n"
15763 "\n";
15764 static const GLchar* gs_tested = "#version 430 core\n"
15765 "#extension GL_ARB_enhanced_layouts : require\n"
15766 "\n"
15767 "layout(points) in;\n"
15768 "layout(triangle_strip, max_vertices = 4) out;\n"
15769 "\n"
15770 "VAR_DEFINITION"
15771 "\n"
15772 "in vec4 tes_gs[];\n"
15773 "out vec4 gs_fs;\n"
15774 "\n"
15775 "void main()\n"
15776 "{\n"
15777 " vec4 result = tes_gs[0];\n"
15778 "\n"
15779 "VARIABLE_USE"
15780 "\n"
15781 " gs_fs = result;\n"
15782 " gl_Position = vec4(-1, -1, 0, 1);\n"
15783 " EmitVertex();\n"
15784 " gs_fs = result;\n"
15785 " gl_Position = vec4(-1, 1, 0, 1);\n"
15786 " EmitVertex();\n"
15787 " gs_fs = result;\n"
15788 " gl_Position = vec4(1, -1, 0, 1);\n"
15789 " EmitVertex();\n"
15790 " gs_fs = result;\n"
15791 " gl_Position = vec4(1, 1, 0, 1);\n"
15792 " EmitVertex();\n"
15793 "}\n"
15794 "\n";
15795 static const GLchar* tcs = "#version 430 core\n"
15796 "#extension GL_ARB_enhanced_layouts : require\n"
15797 "\n"
15798 "layout(vertices = 1) out;\n"
15799 "\n"
15800 "in vec4 vs_tcs[];\n"
15801 "out vec4 tcs_tes[];\n"
15802 "\n"
15803 "void main()\n"
15804 "{\n"
15805 "\n"
15806 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15807 "\n"
15808 " gl_TessLevelOuter[0] = 1.0;\n"
15809 " gl_TessLevelOuter[1] = 1.0;\n"
15810 " gl_TessLevelOuter[2] = 1.0;\n"
15811 " gl_TessLevelOuter[3] = 1.0;\n"
15812 " gl_TessLevelInner[0] = 1.0;\n"
15813 " gl_TessLevelInner[1] = 1.0;\n"
15814 "}\n"
15815 "\n";
15816 static const GLchar* tcs_tested = "#version 430 core\n"
15817 "#extension GL_ARB_enhanced_layouts : require\n"
15818 "\n"
15819 "layout(vertices = 1) out;\n"
15820 "\n"
15821 "VAR_DEFINITION"
15822 "\n"
15823 "in vec4 vs_tcs[];\n"
15824 "out vec4 tcs_tes[];\n"
15825 "\n"
15826 "void main()\n"
15827 "{\n"
15828 " vec4 result = vs_tcs[gl_InvocationID];\n"
15829 "\n"
15830 "VARIABLE_USE"
15831 "\n"
15832 " tcs_tes[gl_InvocationID] = result;\n"
15833 "\n"
15834 " gl_TessLevelOuter[0] = 1.0;\n"
15835 " gl_TessLevelOuter[1] = 1.0;\n"
15836 " gl_TessLevelOuter[2] = 1.0;\n"
15837 " gl_TessLevelOuter[3] = 1.0;\n"
15838 " gl_TessLevelInner[0] = 1.0;\n"
15839 " gl_TessLevelInner[1] = 1.0;\n"
15840 "}\n"
15841 "\n";
15842 static const GLchar* tes = "#version 430 core\n"
15843 "#extension GL_ARB_enhanced_layouts : require\n"
15844 "\n"
15845 "layout(isolines, point_mode) in;\n"
15846 "\n"
15847 "in vec4 tcs_tes[];\n"
15848 "out vec4 tes_gs;\n"
15849 "\n"
15850 "void main()\n"
15851 "{\n"
15852 " tes_gs = tcs_tes[0];\n"
15853 "}\n"
15854 "\n";
15855 static const GLchar* tes_tested = "#version 430 core\n"
15856 "#extension GL_ARB_enhanced_layouts : require\n"
15857 "\n"
15858 "layout(isolines, point_mode) in;\n"
15859 "\n"
15860 "VAR_DEFINITION"
15861 "\n"
15862 "in vec4 tcs_tes[];\n"
15863 "out vec4 tes_gs;\n"
15864 "\n"
15865 "void main()\n"
15866 "{\n"
15867 " vec4 result = tcs_tes[0];\n"
15868 "\n"
15869 "VARIABLE_USE"
15870 "\n"
15871 " tes_gs = result;\n"
15872 "}\n"
15873 "\n";
15874 static const GLchar* vs = "#version 430 core\n"
15875 "#extension GL_ARB_enhanced_layouts : require\n"
15876 "\n"
15877 "in vec4 in_vs;\n"
15878 "out vec4 vs_tcs;\n"
15879 "\n"
15880 "void main()\n"
15881 "{\n"
15882 " vs_tcs = in_vs;\n"
15883 "}\n"
15884 "\n";
15885 static const GLchar* vs_tested = "#version 430 core\n"
15886 "#extension GL_ARB_enhanced_layouts : require\n"
15887 "\n"
15888 "VAR_DEFINITION"
15889 "\n"
15890 "in vec4 in_vs;\n"
15891 "out vec4 vs_tcs;\n"
15892 "\n"
15893 "void main()\n"
15894 "{\n"
15895 " vec4 result = in_vs;\n"
15896 "\n"
15897 "VARIABLE_USE"
15898 "\n"
15899 " vs_tcs = result;\n"
15900 "}\n"
15901 "\n";
15902
15903 std::string source;
15904 testCase& test_case = m_test_cases[test_case_index];
15905
15906 if (test_case.m_stage == stage)
15907 {
15908 const GLchar* array = "";
15909 GLchar buffer[16];
15910 const GLchar* direction = "in ";
15911 const GLchar* index = "";
15912 size_t position = 0;
15913 size_t temp;
15914 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
15915 const GLchar* var_use = input_use;
15916 const GLchar* flat = "flat";
15917
15918 if (false == test_case.m_is_input)
15919 {
15920 direction = "out";
15921 var_use = output_use;
15922 }
15923
15924 sprintf(buffer, "%d", test_case.m_component);
15925
15926 switch (stage)
15927 {
15928 case Utils::Shader::FRAGMENT:
15929 source = fs_tested;
15930 break;
15931 case Utils::Shader::GEOMETRY:
15932 source = gs_tested;
15933 array = "[]";
15934 index = "[0]";
15935 break;
15936 case Utils::Shader::TESS_CTRL:
15937 source = tcs_tested;
15938 array = "[]";
15939 index = "[gl_InvocationID]";
15940 break;
15941 case Utils::Shader::TESS_EVAL:
15942 source = tes_tested;
15943 array = "[]";
15944 index = "[0]";
15945 break;
15946 case Utils::Shader::VERTEX:
15947 source = vs_tested;
15948 flat = "";
15949 break;
15950 default:
15951 TCU_FAIL("Invalid enum");
15952 }
15953
15954 temp = position;
15955 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
15956 position = temp;
15957 Utils::replaceToken("COMPONENT", position, buffer, source);
15958 Utils::replaceToken("FLAT", position, flat, source);
15959 Utils::replaceToken("DIRECTION", position, direction, source);
15960 Utils::replaceToken("ARRAY", position, array, source);
15961 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
15962
15963 Utils::replaceAllTokens("TYPE", type_name, source);
15964 Utils::replaceAllTokens("INDEX", index, source);
15965 }
15966 else
15967 {
15968 switch (stage)
15969 {
15970 case Utils::Shader::FRAGMENT:
15971 source = fs;
15972 break;
15973 case Utils::Shader::GEOMETRY:
15974 source = gs;
15975 break;
15976 case Utils::Shader::TESS_CTRL:
15977 source = tcs;
15978 break;
15979 case Utils::Shader::TESS_EVAL:
15980 source = tes;
15981 break;
15982 case Utils::Shader::VERTEX:
15983 source = vs;
15984 break;
15985 default:
15986 TCU_FAIL("Invalid enum");
15987 }
15988 }
15989
15990 return source;
15991 }
15992
15993 /** Get description of test case
15994 *
15995 * @param test_case_index Index of test case
15996 *
15997 * @return Test case description
15998 **/
15999 std::string VaryingComponentWithoutLocationTest::getTestCaseName(GLuint test_case_index)
16000 {
16001 std::stringstream stream;
16002 testCase& test_case = m_test_cases[test_case_index];
16003
16004 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16005 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
16006
16007 if (true == test_case.m_is_input)
16008 {
16009 stream << "input";
16010 }
16011 else
16012 {
16013 stream << "output";
16014 }
16015
16016 stream << ", component: " << test_case.m_component;
16017
16018 return stream.str();
16019 }
16020
16021 /** Get number of test cases
16022 *
16023 * @return Number of test cases
16024 **/
16025 GLuint VaryingComponentWithoutLocationTest::getTestCaseNumber()
16026 {
16027 return static_cast<GLuint>(m_test_cases.size());
16028 }
16029
16030 /** Selects if "compute" stage is relevant for test
16031 *
16032 * @param ignored
16033 *
16034 * @return false
16035 **/
16036 bool VaryingComponentWithoutLocationTest::isComputeRelevant(GLuint /* test_case_index */)
16037 {
16038 return false;
16039 }
16040
16041 /** Prepare all test cases
16042 *
16043 **/
16044 void VaryingComponentWithoutLocationTest::testInit()
16045 {
16046 static const GLuint n_components_per_location = 4;
16047 const GLuint n_types = getTypesNumber();
16048
16049 for (GLuint i = 0; i < n_types; ++i)
16050 {
16051 const Utils::Type& type = getType(i);
16052 const GLuint n_req_components = type.m_n_rows;
16053 const GLuint valid_component = n_components_per_location - n_req_components;
16054
16055 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16056 {
16057 if (Utils::Shader::COMPUTE == stage)
16058 {
16059 continue;
16060 }
16061
16062 /* Component cannot be used for matrices */
16063 if (1 != type.m_n_columns)
16064 {
16065 continue;
16066 }
16067
16068 testCase test_case_in = { valid_component, true, (Utils::Shader::STAGES)stage, type };
16069 testCase test_case_out = { valid_component, false, (Utils::Shader::STAGES)stage, type };
16070
16071 m_test_cases.push_back(test_case_in);
16072
16073 if (Utils::Shader::FRAGMENT != stage)
16074 {
16075 m_test_cases.push_back(test_case_out);
16076 }
16077 }
16078 }
16079 }
16080
16081 /** Constructor
16082 *
16083 * @param context Test framework context
16084 **/
16085 VaryingComponentOfInvalidTypeTest::VaryingComponentOfInvalidTypeTest(deqp::Context& context)
16086 : NegativeTestBase(context, "varying_component_of_invalid_type",
16087 "Test verifies that compiler reports error when component qualifier is used for invalid type")
16088 {
16089 }
16090
16091 /** Source for given test case and stage
16092 *
16093 * @param test_case_index Index of test case
16094 * @param stage Shader stage
16095 *
16096 * @return Shader source
16097 **/
16098 std::string VaryingComponentOfInvalidTypeTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16099 {
16100 static const GLchar* block_definition_arr = "layout (location = 1, component = COMPONENT) flat DIRECTION Goku {\n"
16101 " TYPE member;\n"
16102 "} gokuARRAY[1];\n";
16103 static const GLchar* block_definition_one = "layout (location = 1, component = COMPONENT) flat DIRECTION Goku {\n"
16104 " TYPE member;\n"
16105 "} gokuARRAY;\n";
16106 static const GLchar* matrix_definition_arr =
16107 "layout (location = 1, component = COMPONENT) flat DIRECTION TYPE gokuARRAY[1];\n";
16108 static const GLchar* matrix_definition_one =
16109 "layout (location = 1, component = COMPONENT) flat DIRECTION TYPE gokuARRAY;\n";
16110 static const GLchar* struct_definition_arr =
16111 "struct Goku {\n"
16112 " TYPE member;\n"
16113 "};\n"
16114 "\n"
16115 "layout (location = 1, component = COMPONENT) flat DIRECTION Goku gokuARRAY[1];\n";
16116 static const GLchar* struct_definition_one =
16117 "struct Goku {\n"
16118 " TYPE member;\n"
16119 "};\n"
16120 "\n"
16121 "layout (location = 1, component = COMPONENT) flat DIRECTION Goku gokuARRAY;\n";
16122 static const GLchar* matrix_input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
16123 " {\n"
16124 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16125 " }\n";
16126 static const GLchar* matrix_input_use_one = " if (TYPE(0) == gokuINDEX)\n"
16127 " {\n"
16128 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16129 " }\n";
16130 static const GLchar* matrix_output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
16131 " if (vec4(0) == result)\n"
16132 " {\n"
16133 " gokuINDEX[0] = TYPE(1);\n"
16134 " }\n";
16135 static const GLchar* matrix_output_use_one = " gokuINDEX = TYPE(0);\n"
16136 " if (vec4(0) == result)\n"
16137 " {\n"
16138 " gokuINDEX = TYPE(1);\n"
16139 " }\n";
16140 static const GLchar* member_input_use_arr = " if (TYPE(0) == gokuINDEX[0].member)\n"
16141 " {\n"
16142 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16143 " }\n";
16144 static const GLchar* member_input_use_one = " if (TYPE(0) == gokuINDEX.member)\n"
16145 " {\n"
16146 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16147 " }\n";
16148 static const GLchar* member_output_use_arr = " gokuINDEX[0].member = TYPE(0);\n"
16149 " if (vec4(0) == result)\n"
16150 " {\n"
16151 " gokuINDEX[0].member = TYPE(1);\n"
16152 " }\n";
16153 static const GLchar* member_output_use_one = " gokuINDEX.member = TYPE(0);\n"
16154 " if (vec4(0) == result)\n"
16155 " {\n"
16156 " gokuINDEX.member = TYPE(1);\n"
16157 " }\n";
16158 static const GLchar* fs = "#version 430 core\n"
16159 "#extension GL_ARB_enhanced_layouts : require\n"
16160 "\n"
16161 "in vec4 gs_fs;\n"
16162 "out vec4 fs_out;\n"
16163 "\n"
16164 "void main()\n"
16165 "{\n"
16166 " fs_out = gs_fs;\n"
16167 "}\n"
16168 "\n";
16169 static const GLchar* fs_tested = "#version 430 core\n"
16170 "#extension GL_ARB_enhanced_layouts : require\n"
16171 "\n"
16172 "VAR_DEFINITION"
16173 "\n"
16174 "in vec4 gs_fs;\n"
16175 "out vec4 fs_out;\n"
16176 "\n"
16177 "void main()\n"
16178 "{\n"
16179 " vec4 result = gs_fs;\n"
16180 "\n"
16181 "VARIABLE_USE"
16182 "\n"
16183 " fs_out += result;\n"
16184 "}\n"
16185 "\n";
16186 static const GLchar* gs = "#version 430 core\n"
16187 "#extension GL_ARB_enhanced_layouts : require\n"
16188 "\n"
16189 "layout(points) in;\n"
16190 "layout(triangle_strip, max_vertices = 4) out;\n"
16191 "\n"
16192 "in vec4 tes_gs[];\n"
16193 "out vec4 gs_fs;\n"
16194 "\n"
16195 "void main()\n"
16196 "{\n"
16197 " gs_fs = tes_gs[0];\n"
16198 " gl_Position = vec4(-1, -1, 0, 1);\n"
16199 " EmitVertex();\n"
16200 " gs_fs = tes_gs[0];\n"
16201 " gl_Position = vec4(-1, 1, 0, 1);\n"
16202 " EmitVertex();\n"
16203 " gs_fs = tes_gs[0];\n"
16204 " gl_Position = vec4(1, -1, 0, 1);\n"
16205 " EmitVertex();\n"
16206 " gs_fs = tes_gs[0];\n"
16207 " gl_Position = vec4(1, 1, 0, 1);\n"
16208 " EmitVertex();\n"
16209 "}\n"
16210 "\n";
16211 static const GLchar* gs_tested = "#version 430 core\n"
16212 "#extension GL_ARB_enhanced_layouts : require\n"
16213 "\n"
16214 "layout(points) in;\n"
16215 "layout(triangle_strip, max_vertices = 4) out;\n"
16216 "\n"
16217 "VAR_DEFINITION"
16218 "\n"
16219 "in vec4 tes_gs[];\n"
16220 "out vec4 gs_fs;\n"
16221 "\n"
16222 "void main()\n"
16223 "{\n"
16224 " vec4 result = tes_gs[0];\n"
16225 "\n"
16226 "VARIABLE_USE"
16227 "\n"
16228 " gs_fs = result;\n"
16229 " gl_Position = vec4(-1, -1, 0, 1);\n"
16230 " EmitVertex();\n"
16231 " gs_fs = result;\n"
16232 " gl_Position = vec4(-1, 1, 0, 1);\n"
16233 " EmitVertex();\n"
16234 " gs_fs = result;\n"
16235 " gl_Position = vec4(1, -1, 0, 1);\n"
16236 " EmitVertex();\n"
16237 " gs_fs = result;\n"
16238 " gl_Position = vec4(1, 1, 0, 1);\n"
16239 " EmitVertex();\n"
16240 "}\n"
16241 "\n";
16242 static const GLchar* tcs = "#version 430 core\n"
16243 "#extension GL_ARB_enhanced_layouts : require\n"
16244 "\n"
16245 "layout(vertices = 1) out;\n"
16246 "\n"
16247 "in vec4 vs_tcs[];\n"
16248 "out vec4 tcs_tes[];\n"
16249 "\n"
16250 "void main()\n"
16251 "{\n"
16252 "\n"
16253 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16254 "\n"
16255 " gl_TessLevelOuter[0] = 1.0;\n"
16256 " gl_TessLevelOuter[1] = 1.0;\n"
16257 " gl_TessLevelOuter[2] = 1.0;\n"
16258 " gl_TessLevelOuter[3] = 1.0;\n"
16259 " gl_TessLevelInner[0] = 1.0;\n"
16260 " gl_TessLevelInner[1] = 1.0;\n"
16261 "}\n"
16262 "\n";
16263 static const GLchar* tcs_tested = "#version 430 core\n"
16264 "#extension GL_ARB_enhanced_layouts : require\n"
16265 "\n"
16266 "layout(vertices = 1) out;\n"
16267 "\n"
16268 "VAR_DEFINITION"
16269 "\n"
16270 "in vec4 vs_tcs[];\n"
16271 "out vec4 tcs_tes[];\n"
16272 "\n"
16273 "void main()\n"
16274 "{\n"
16275 " vec4 result = vs_tcs[gl_InvocationID];\n"
16276 "\n"
16277 "VARIABLE_USE"
16278 "\n"
16279 " tcs_tes[gl_InvocationID] = result;\n"
16280 "\n"
16281 " gl_TessLevelOuter[0] = 1.0;\n"
16282 " gl_TessLevelOuter[1] = 1.0;\n"
16283 " gl_TessLevelOuter[2] = 1.0;\n"
16284 " gl_TessLevelOuter[3] = 1.0;\n"
16285 " gl_TessLevelInner[0] = 1.0;\n"
16286 " gl_TessLevelInner[1] = 1.0;\n"
16287 "}\n"
16288 "\n";
16289 static const GLchar* tes = "#version 430 core\n"
16290 "#extension GL_ARB_enhanced_layouts : require\n"
16291 "\n"
16292 "layout(isolines, point_mode) in;\n"
16293 "\n"
16294 "in vec4 tcs_tes[];\n"
16295 "out vec4 tes_gs;\n"
16296 "\n"
16297 "void main()\n"
16298 "{\n"
16299 " tes_gs = tcs_tes[0];\n"
16300 "}\n"
16301 "\n";
16302 static const GLchar* tes_tested = "#version 430 core\n"
16303 "#extension GL_ARB_enhanced_layouts : require\n"
16304 "\n"
16305 "layout(isolines, point_mode) in;\n"
16306 "\n"
16307 "VAR_DEFINITION"
16308 "\n"
16309 "in vec4 tcs_tes[];\n"
16310 "out vec4 tes_gs;\n"
16311 "\n"
16312 "void main()\n"
16313 "{\n"
16314 " vec4 result = tcs_tes[0];\n"
16315 "\n"
16316 "VARIABLE_USE"
16317 "\n"
16318 " tes_gs += result;\n"
16319 "}\n"
16320 "\n";
16321 static const GLchar* vs = "#version 430 core\n"
16322 "#extension GL_ARB_enhanced_layouts : require\n"
16323 "\n"
16324 "in vec4 in_vs;\n"
16325 "out vec4 vs_tcs;\n"
16326 "\n"
16327 "void main()\n"
16328 "{\n"
16329 " vs_tcs = in_vs;\n"
16330 "}\n"
16331 "\n";
16332 static const GLchar* vs_tested = "#version 430 core\n"
16333 "#extension GL_ARB_enhanced_layouts : require\n"
16334 "\n"
16335 "VAR_DEFINITION"
16336 "\n"
16337 "in vec4 in_vs;\n"
16338 "out vec4 vs_tcs;\n"
16339 "\n"
16340 "void main()\n"
16341 "{\n"
16342 " vec4 result = in_vs;\n"
16343 "\n"
16344 "VARIABLE_USE"
16345 "\n"
16346 " vs_tcs += result;\n"
16347 "}\n"
16348 "\n";
16349
16350 std::string source;
16351 testCase& test_case = m_test_cases[test_case_index];
16352
16353 if (test_case.m_stage == stage)
16354 {
16355 const GLchar* array = "";
16356 GLchar buffer[16];
16357 const GLchar* var_definition = 0;
16358 const GLchar* direction = "in ";
16359 const GLchar* index = "";
16360 size_t position = 0;
16361 size_t temp;
16362 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16363 const GLchar* var_use = 0;
16364
16365 if (false == test_case.m_is_input)
16366 {
16367 direction = "out";
16368
16369 if (false == test_case.m_is_array)
16370 {
16371 switch (test_case.m_case)
16372 {
16373 case BLOCK:
16374 var_definition = block_definition_one;
16375 var_use = member_output_use_one;
16376 break;
16377 case MATRIX:
16378 var_definition = matrix_definition_one;
16379 var_use = matrix_output_use_one;
16380 break;
16381 case STRUCT:
16382 var_definition = struct_definition_one;
16383 var_use = member_output_use_one;
16384 break;
16385 default:
16386 TCU_FAIL("Invalid enum");
16387 }
16388 }
16389 else
16390 {
16391 switch (test_case.m_case)
16392 {
16393 case BLOCK:
16394 var_definition = block_definition_arr;
16395 var_use = member_output_use_arr;
16396 break;
16397 case MATRIX:
16398 var_definition = matrix_definition_arr;
16399 var_use = matrix_output_use_arr;
16400 break;
16401 case STRUCT:
16402 var_definition = struct_definition_arr;
16403 var_use = member_output_use_arr;
16404 break;
16405 default:
16406 TCU_FAIL("Invalid enum");
16407 }
16408 }
16409 }
16410 else
16411 {
16412 if (false == test_case.m_is_array)
16413 {
16414 switch (test_case.m_case)
16415 {
16416 case BLOCK:
16417 var_definition = block_definition_one;
16418 var_use = member_input_use_one;
16419 break;
16420 case MATRIX:
16421 var_definition = matrix_definition_one;
16422 var_use = matrix_input_use_one;
16423 break;
16424 case STRUCT:
16425 var_definition = struct_definition_one;
16426 var_use = member_input_use_one;
16427 break;
16428 default:
16429 TCU_FAIL("Invalid enum");
16430 }
16431 }
16432 else
16433 {
16434 switch (test_case.m_case)
16435 {
16436 case BLOCK:
16437 var_definition = block_definition_arr;
16438 var_use = member_input_use_arr;
16439 break;
16440 case MATRIX:
16441 var_definition = matrix_definition_arr;
16442 var_use = matrix_input_use_arr;
16443 break;
16444 case STRUCT:
16445 var_definition = struct_definition_arr;
16446 var_use = member_input_use_arr;
16447 break;
16448 default:
16449 TCU_FAIL("Invalid enum");
16450 }
16451 }
16452 }
16453
16454 sprintf(buffer, "%d", test_case.m_component);
16455
16456 switch (stage)
16457 {
16458 case Utils::Shader::FRAGMENT:
16459 source = fs_tested;
16460 break;
16461 case Utils::Shader::GEOMETRY:
16462 source = gs_tested;
16463 array = "[]";
16464 index = "[0]";
16465 break;
16466 case Utils::Shader::TESS_CTRL:
16467 source = tcs_tested;
16468 array = "[]";
16469 index = "[gl_InvocationID]";
16470 break;
16471 case Utils::Shader::TESS_EVAL:
16472 source = tes_tested;
16473 array = "[]";
16474 index = "[0]";
16475 break;
16476 case Utils::Shader::VERTEX:
16477 source = vs_tested;
16478 break;
16479 default:
16480 TCU_FAIL("Invalid enum");
16481 }
16482
16483 temp = position;
16484 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16485 position = temp;
16486 Utils::replaceToken("COMPONENT", position, buffer, source);
16487 Utils::replaceToken("DIRECTION", position, direction, source);
16488 Utils::replaceToken("ARRAY", position, array, source);
16489 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16490
16491 Utils::replaceAllTokens("TYPE", type_name, source);
16492 Utils::replaceAllTokens("INDEX", index, source);
16493 }
16494 else
16495 {
16496 switch (stage)
16497 {
16498 case Utils::Shader::FRAGMENT:
16499 source = fs;
16500 break;
16501 case Utils::Shader::GEOMETRY:
16502 source = gs;
16503 break;
16504 case Utils::Shader::TESS_CTRL:
16505 source = tcs;
16506 break;
16507 case Utils::Shader::TESS_EVAL:
16508 source = tes;
16509 break;
16510 case Utils::Shader::VERTEX:
16511 source = vs;
16512 break;
16513 default:
16514 TCU_FAIL("Invalid enum");
16515 }
16516 }
16517
16518 return source;
16519 }
16520
16521 /** Get description of test case
16522 *
16523 * @param test_case_index Index of test case
16524 *
16525 * @return Test case description
16526 **/
16527 std::string VaryingComponentOfInvalidTypeTest::getTestCaseName(GLuint test_case_index)
16528 {
16529 std::stringstream stream;
16530 testCase& test_case = m_test_cases[test_case_index];
16531
16532 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16533 << " type: " << test_case.m_type.GetGLSLTypeName();
16534
16535 if (true == test_case.m_is_array)
16536 {
16537 stream << "[1]";
16538 }
16539
16540 stream << ", direction: ";
16541
16542 if (true == test_case.m_is_input)
16543 {
16544 stream << "input";
16545 }
16546 else
16547 {
16548 stream << "output";
16549 }
16550
16551 stream << ", component: " << test_case.m_component;
16552
16553 return stream.str();
16554 }
16555
16556 /** Get number of test cases
16557 *
16558 * @return Number of test cases
16559 **/
16560 GLuint VaryingComponentOfInvalidTypeTest::getTestCaseNumber()
16561 {
16562 return static_cast<GLuint>(m_test_cases.size());
16563 }
16564
16565 /** Selects if "compute" stage is relevant for test
16566 *
16567 * @param ignored
16568 *
16569 * @return false
16570 **/
16571 bool VaryingComponentOfInvalidTypeTest::isComputeRelevant(GLuint /* test_case_index */)
16572 {
16573 return false;
16574 }
16575
16576 /** Prepare all test cases
16577 *
16578 **/
16579 void VaryingComponentOfInvalidTypeTest::testInit()
16580 {
16581 static const GLuint n_components_per_location = 4;
16582 const GLuint n_types = getTypesNumber();
16583
16584 for (GLuint i = 0; i < n_types; ++i)
16585 {
16586 const Utils::Type& type = getType(i);
16587 const GLuint n_req_components = type.m_n_rows;
16588 const GLuint valid_component = n_components_per_location - n_req_components;
16589
16590 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16591 {
16592 if (Utils::Shader::COMPUTE == stage)
16593 {
16594 continue;
16595 }
16596
16597 /* Use different CASE for matrices */
16598 if (1 != type.m_n_columns)
16599 {
16600 testCase test_case_in_arr = { MATRIX, valid_component, true, true, (Utils::Shader::STAGES)stage, type };
16601 testCase test_case_in_one = {
16602 MATRIX, valid_component, false, true, (Utils::Shader::STAGES)stage, type
16603 };
16604 testCase test_case_out_arr = {
16605 MATRIX, valid_component, true, false, (Utils::Shader::STAGES)stage, type
16606 };
16607 testCase test_case_out_one = {
16608 MATRIX, valid_component, false, false, (Utils::Shader::STAGES)stage, type
16609 };
16610
16611 m_test_cases.push_back(test_case_in_arr);
16612 m_test_cases.push_back(test_case_in_one);
16613
16614 if (Utils::Shader::FRAGMENT != stage)
16615 {
16616 m_test_cases.push_back(test_case_out_arr);
16617 m_test_cases.push_back(test_case_out_one);
16618 }
16619 }
16620 else
16621 {
16622 for (GLuint c = BLOCK; c < MAX_CASES; ++c)
16623 {
16624 testCase test_case_in_arr = { (CASES)c, valid_component, true, true, (Utils::Shader::STAGES)stage,
16625 type };
16626 testCase test_case_in_one = { (CASES)c, valid_component, false, true, (Utils::Shader::STAGES)stage,
16627 type };
16628 testCase test_case_out_arr = { (CASES)c, valid_component, true, false, (Utils::Shader::STAGES)stage,
16629 type };
16630 testCase test_case_out_one = {
16631 (CASES)c, valid_component, false, false, (Utils::Shader::STAGES)stage, type
16632 };
16633
16634 if (Utils::Shader::VERTEX != stage)
16635 {
16636 m_test_cases.push_back(test_case_in_arr);
16637 m_test_cases.push_back(test_case_in_one);
16638 }
16639
16640 if (Utils::Shader::FRAGMENT != stage)
16641 {
16642 m_test_cases.push_back(test_case_out_arr);
16643 m_test_cases.push_back(test_case_out_one);
16644 }
16645 }
16646 }
16647 }
16648 }
16649 }
16650
16651 /** Constructor
16652 *
16653 * @param context Test framework context
16654 **/
16655 InputComponentAliasingTest::InputComponentAliasingTest(deqp::Context& context)
16656 : NegativeTestBase(context, "input_component_aliasing",
16657 "Test verifies that compiler reports component aliasing as error")
16658 {
16659 }
16660
16661 /** Source for given test case and stage
16662 *
16663 * @param test_case_index Index of test case
16664 * @param stage Shader stage
16665 *
16666 * @return Shader source
16667 **/
16668 std::string InputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16669 {
16670 static const GLchar* var_definition = "layout (location = 1, component = COMPONENT) FLAT in TYPE gohanARRAY;\n"
16671 "layout (location = 1, component = COMPONENT) FLAT in TYPE gotenARRAY;\n";
16672 static const GLchar* test_one = " if (TYPE(0) == gohanINDEX)\n"
16673 " {\n"
16674 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16675 " }\n";
16676 static const GLchar* fs = "#version 430 core\n"
16677 "#extension GL_ARB_enhanced_layouts : require\n"
16678 "\n"
16679 "in vec4 gs_fs;\n"
16680 "out vec4 fs_out;\n"
16681 "\n"
16682 "void main()\n"
16683 "{\n"
16684 " fs_out = gs_fs;\n"
16685 "}\n"
16686 "\n";
16687 static const GLchar* fs_tested = "#version 430 core\n"
16688 "#extension GL_ARB_enhanced_layouts : require\n"
16689 "\n"
16690 "VAR_DEFINITION"
16691 "\n"
16692 "in vec4 gs_fs;\n"
16693 "out vec4 fs_out;\n"
16694 "\n"
16695 "void main()\n"
16696 "{\n"
16697 " vec4 result = gs_fs;\n"
16698 "\n"
16699 "VARIABLE_USE"
16700 "\n"
16701 " fs_out += result;\n"
16702 "}\n"
16703 "\n";
16704 static const GLchar* gs = "#version 430 core\n"
16705 "#extension GL_ARB_enhanced_layouts : require\n"
16706 "\n"
16707 "layout(points) in;\n"
16708 "layout(triangle_strip, max_vertices = 4) out;\n"
16709 "\n"
16710 "in vec4 tes_gs[];\n"
16711 "out vec4 gs_fs;\n"
16712 "\n"
16713 "void main()\n"
16714 "{\n"
16715 " gs_fs = tes_gs[0];\n"
16716 " gl_Position = vec4(-1, -1, 0, 1);\n"
16717 " EmitVertex();\n"
16718 " gs_fs = tes_gs[0];\n"
16719 " gl_Position = vec4(-1, 1, 0, 1);\n"
16720 " EmitVertex();\n"
16721 " gs_fs = tes_gs[0];\n"
16722 " gl_Position = vec4(1, -1, 0, 1);\n"
16723 " EmitVertex();\n"
16724 " gs_fs = tes_gs[0];\n"
16725 " gl_Position = vec4(1, 1, 0, 1);\n"
16726 " EmitVertex();\n"
16727 "}\n"
16728 "\n";
16729 static const GLchar* gs_tested = "#version 430 core\n"
16730 "#extension GL_ARB_enhanced_layouts : require\n"
16731 "\n"
16732 "layout(points) in;\n"
16733 "layout(triangle_strip, max_vertices = 4) out;\n"
16734 "\n"
16735 "VAR_DEFINITION"
16736 "\n"
16737 "in vec4 tes_gs[];\n"
16738 "out vec4 gs_fs;\n"
16739 "\n"
16740 "void main()\n"
16741 "{\n"
16742 " vec4 result = tes_gs[0];\n"
16743 "\n"
16744 "VARIABLE_USE"
16745 "\n"
16746 " gs_fs = result;\n"
16747 " gl_Position = vec4(-1, -1, 0, 1);\n"
16748 " EmitVertex();\n"
16749 " gs_fs = result;\n"
16750 " gl_Position = vec4(-1, 1, 0, 1);\n"
16751 " EmitVertex();\n"
16752 " gs_fs = result;\n"
16753 " gl_Position = vec4(1, -1, 0, 1);\n"
16754 " EmitVertex();\n"
16755 " gs_fs = result;\n"
16756 " gl_Position = vec4(1, 1, 0, 1);\n"
16757 " EmitVertex();\n"
16758 "}\n"
16759 "\n";
16760 static const GLchar* tcs = "#version 430 core\n"
16761 "#extension GL_ARB_enhanced_layouts : require\n"
16762 "\n"
16763 "layout(vertices = 1) out;\n"
16764 "\n"
16765 "in vec4 vs_tcs[];\n"
16766 "out vec4 tcs_tes[];\n"
16767 "\n"
16768 "void main()\n"
16769 "{\n"
16770 "\n"
16771 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16772 "\n"
16773 " gl_TessLevelOuter[0] = 1.0;\n"
16774 " gl_TessLevelOuter[1] = 1.0;\n"
16775 " gl_TessLevelOuter[2] = 1.0;\n"
16776 " gl_TessLevelOuter[3] = 1.0;\n"
16777 " gl_TessLevelInner[0] = 1.0;\n"
16778 " gl_TessLevelInner[1] = 1.0;\n"
16779 "}\n"
16780 "\n";
16781 static const GLchar* tcs_tested = "#version 430 core\n"
16782 "#extension GL_ARB_enhanced_layouts : require\n"
16783 "\n"
16784 "layout(vertices = 1) out;\n"
16785 "\n"
16786 "VAR_DEFINITION"
16787 "\n"
16788 "in vec4 vs_tcs[];\n"
16789 "out vec4 tcs_tes[];\n"
16790 "\n"
16791 "void main()\n"
16792 "{\n"
16793 " vec4 result = vs_tcs[gl_InvocationID];\n"
16794 "\n"
16795 "VARIABLE_USE"
16796 "\n"
16797 " tcs_tes[gl_InvocationID] = result;\n"
16798 "\n"
16799 " gl_TessLevelOuter[0] = 1.0;\n"
16800 " gl_TessLevelOuter[1] = 1.0;\n"
16801 " gl_TessLevelOuter[2] = 1.0;\n"
16802 " gl_TessLevelOuter[3] = 1.0;\n"
16803 " gl_TessLevelInner[0] = 1.0;\n"
16804 " gl_TessLevelInner[1] = 1.0;\n"
16805 "}\n"
16806 "\n";
16807 static const GLchar* tes = "#version 430 core\n"
16808 "#extension GL_ARB_enhanced_layouts : require\n"
16809 "\n"
16810 "layout(isolines, point_mode) in;\n"
16811 "\n"
16812 "in vec4 tcs_tes[];\n"
16813 "out vec4 tes_gs;\n"
16814 "\n"
16815 "void main()\n"
16816 "{\n"
16817 " tes_gs = tcs_tes[0];\n"
16818 "}\n"
16819 "\n";
16820 static const GLchar* tes_tested = "#version 430 core\n"
16821 "#extension GL_ARB_enhanced_layouts : require\n"
16822 "\n"
16823 "layout(isolines, point_mode) in;\n"
16824 "\n"
16825 "VAR_DEFINITION"
16826 "\n"
16827 "in vec4 tcs_tes[];\n"
16828 "out vec4 tes_gs;\n"
16829 "\n"
16830 "void main()\n"
16831 "{\n"
16832 " vec4 result = tcs_tes[0];\n"
16833 "\n"
16834 "VARIABLE_USE"
16835 "\n"
16836 " tes_gs += result;\n"
16837 "}\n"
16838 "\n";
16839 static const GLchar* vs = "#version 430 core\n"
16840 "#extension GL_ARB_enhanced_layouts : require\n"
16841 "\n"
16842 "in vec4 in_vs;\n"
16843 "out vec4 vs_tcs;\n"
16844 "\n"
16845 "void main()\n"
16846 "{\n"
16847 " vs_tcs = in_vs;\n"
16848 "}\n"
16849 "\n";
16850 static const GLchar* vs_tested = "#version 430 core\n"
16851 "#extension GL_ARB_enhanced_layouts : require\n"
16852 "\n"
16853 "VAR_DEFINITION"
16854 "\n"
16855 "in vec4 in_vs;\n"
16856 "out vec4 vs_tcs;\n"
16857 "\n"
16858 "void main()\n"
16859 "{\n"
16860 " vec4 result = in_vs;\n"
16861 "\n"
16862 "VARIABLE_USE"
16863 "\n"
16864 " vs_tcs += result;\n"
16865 "}\n"
16866 "\n";
16867
16868 std::string source;
16869 testCase& test_case = m_test_cases[test_case_index];
16870
16871 if (test_case.m_stage == stage)
16872 {
16873 const GLchar* array = "";
16874 GLchar buffer_gohan[16];
16875 GLchar buffer_goten[16];
16876 const GLchar* flat = "";
16877 const GLchar* index = "";
16878 const bool is_flat_req = isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_INPUT);
16879 size_t position = 0;
16880 size_t temp;
16881 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16882 const GLchar* var_use = test_one;
16883
16884 if (true == is_flat_req)
16885 {
16886 flat = "flat";
16887 }
16888
16889 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
16890 sprintf(buffer_goten, "%d", test_case.m_component_goten);
16891
16892 switch (stage)
16893 {
16894 case Utils::Shader::FRAGMENT:
16895 source = fs_tested;
16896 break;
16897 case Utils::Shader::GEOMETRY:
16898 source = gs_tested;
16899 array = "[]";
16900 index = "[0]";
16901 break;
16902 case Utils::Shader::TESS_CTRL:
16903 source = tcs_tested;
16904 array = "[]";
16905 index = "[gl_InvocationID]";
16906 break;
16907 case Utils::Shader::TESS_EVAL:
16908 source = tes_tested;
16909 array = "[]";
16910 index = "[0]";
16911 break;
16912 case Utils::Shader::VERTEX:
16913 source = vs_tested;
16914 break;
16915 default:
16916 TCU_FAIL("Invalid enum");
16917 }
16918
16919 temp = position;
16920 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16921 position = temp;
16922 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
16923 Utils::replaceToken("ARRAY", position, array, source);
16924 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
16925 Utils::replaceToken("ARRAY", position, array, source);
16926 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16927
16928 Utils::replaceAllTokens("FLAT", flat, source);
16929 Utils::replaceAllTokens("TYPE", type_name, source);
16930 Utils::replaceAllTokens("INDEX", index, source);
16931 }
16932 else
16933 {
16934 switch (stage)
16935 {
16936 case Utils::Shader::FRAGMENT:
16937 source = fs;
16938 break;
16939 case Utils::Shader::GEOMETRY:
16940 source = gs;
16941 break;
16942 case Utils::Shader::TESS_CTRL:
16943 source = tcs;
16944 break;
16945 case Utils::Shader::TESS_EVAL:
16946 source = tes;
16947 break;
16948 case Utils::Shader::VERTEX:
16949 source = vs;
16950 break;
16951 default:
16952 TCU_FAIL("Invalid enum");
16953 }
16954 }
16955
16956 return source;
16957 }
16958
16959 /** Get description of test case
16960 *
16961 * @param test_case_index Index of test case
16962 *
16963 * @return Test case description
16964 **/
16965 std::string InputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
16966 {
16967 std::stringstream stream;
16968 testCase& test_case = m_test_cases[test_case_index];
16969
16970 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16971 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
16972 << " & " << test_case.m_component_goten;
16973
16974 return stream.str();
16975 }
16976
16977 /** Get number of test cases
16978 *
16979 * @return Number of test cases
16980 **/
16981 GLuint InputComponentAliasingTest::getTestCaseNumber()
16982 {
16983 return static_cast<GLuint>(m_test_cases.size());
16984 }
16985
16986 /** Selects if "compute" stage is relevant for test
16987 *
16988 * @param ignored
16989 *
16990 * @return false
16991 **/
16992 bool InputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
16993 {
16994 return false;
16995 }
16996
16997 /** Selects if compilation failure is expected result
16998 *
16999 * @param test_case_index Index of test case
17000 *
17001 * @return false for VS that use only single variable, true otherwise
17002 **/
17003 bool InputComponentAliasingTest::isFailureExpected(GLuint test_case_index)
17004 {
17005 testCase& test_case = m_test_cases[test_case_index];
17006
17007 return (Utils::Shader::VERTEX != test_case.m_stage);
17008 }
17009
17010 /** Prepare all test cases
17011 *
17012 **/
17013 void InputComponentAliasingTest::testInit()
17014 {
17015 const GLuint n_types = getTypesNumber();
17016
17017 for (GLuint i = 0; i < n_types; ++i)
17018 {
17019 const Utils::Type& type = getType(i);
17020 const bool use_double = (Utils::Type::Double == type.m_basic_type);
17021 const GLuint n_components_per_location = use_double ? 2 : 4;
17022 const GLuint n_req_components = type.m_n_rows;
17023 const GLint valid_component = (GLint)n_components_per_location - (GLint)n_req_components;
17024 const GLuint component_size = use_double ? 2 : 1;
17025 /* Skip matrices */
17026 if (1 != type.m_n_columns)
17027 {
17028 continue;
17029 }
17030 /* Skip dvec3/dvec4 which doesn't support the component qualifier */
17031 if (valid_component < 0)
17032 {
17033 continue;
17034 }
17035
17036 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17037 {
17038 if (Utils::Shader::COMPUTE == stage)
17039 {
17040 continue;
17041 }
17042
17043 for (GLuint gohan = 0; gohan <= (GLuint)valid_component; ++gohan)
17044 {
17045 const GLint first_aliasing = gohan - n_req_components + 1;
17046 const GLint last_aliasing = gohan + n_req_components - 1;
17047
17048 const GLuint goten_start = std::max(0, first_aliasing);
17049 const GLuint goten_stop = std::min(valid_component, last_aliasing);
17050
17051 for (GLuint goten = goten_start; goten <= goten_stop; ++goten)
17052 {
17053 testCase test_case = { gohan * component_size, goten * component_size, (Utils::Shader::STAGES)stage,
17054 type };
17055
17056 m_test_cases.push_back(test_case);
17057 }
17058 }
17059 }
17060 }
17061 }
17062
17063 /** Constructor
17064 *
17065 * @param context Test framework context
17066 **/
17067 OutputComponentAliasingTest::OutputComponentAliasingTest(deqp::Context& context)
17068 : NegativeTestBase(context, "output_component_aliasing",
17069 "Test verifies that compiler reports component aliasing as error")
17070 {
17071 }
17072
17073 /** Source for given test case and stage
17074 *
17075 * @param test_case_index Index of test case
17076 * @param stage Shader stage
17077 *
17078 * @return Shader source
17079 **/
17080 std::string OutputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
17081 {
17082 static const GLchar* var_definition = "layout (location = 1, component = COMPONENT) flat out TYPE gohanARRAY;\n"
17083 "layout (location = 1, component = COMPONENT) flat out TYPE gotenARRAY;\n";
17084 static const GLchar* l_test = " gohanINDEX = TYPE(1);\n"
17085 " gotenINDEX = TYPE(0);\n";
17086 static const GLchar* fs = "#version 430 core\n"
17087 "#extension GL_ARB_enhanced_layouts : require\n"
17088 "\n"
17089 "in vec4 gs_fs;\n"
17090 "out vec4 fs_out;\n"
17091 "\n"
17092 "void main()\n"
17093 "{\n"
17094 " fs_out = gs_fs;\n"
17095 "}\n"
17096 "\n";
17097 static const GLchar* fs_tested = "#version 430 core\n"
17098 "#extension GL_ARB_enhanced_layouts : require\n"
17099 "\n"
17100 "VAR_DEFINITION"
17101 "\n"
17102 "in vec4 gs_fs;\n"
17103 "out vec4 fs_out;\n"
17104 "\n"
17105 "void main()\n"
17106 "{\n"
17107 " vec4 result = gs_fs;\n"
17108 "\n"
17109 "VARIABLE_USE"
17110 "\n"
17111 " fs_out += result;\n"
17112 "}\n"
17113 "\n";
17114 static const GLchar* gs = "#version 430 core\n"
17115 "#extension GL_ARB_enhanced_layouts : require\n"
17116 "\n"
17117 "layout(points) in;\n"
17118 "layout(triangle_strip, max_vertices = 4) out;\n"
17119 "\n"
17120 "in vec4 tes_gs[];\n"
17121 "out vec4 gs_fs;\n"
17122 "\n"
17123 "void main()\n"
17124 "{\n"
17125 " gs_fs = tes_gs[0];\n"
17126 " gl_Position = vec4(-1, -1, 0, 1);\n"
17127 " EmitVertex();\n"
17128 " gs_fs = tes_gs[0];\n"
17129 " gl_Position = vec4(-1, 1, 0, 1);\n"
17130 " EmitVertex();\n"
17131 " gs_fs = tes_gs[0];\n"
17132 " gl_Position = vec4(1, -1, 0, 1);\n"
17133 " EmitVertex();\n"
17134 " gs_fs = tes_gs[0];\n"
17135 " gl_Position = vec4(1, 1, 0, 1);\n"
17136 " EmitVertex();\n"
17137 "}\n"
17138 "\n";
17139 static const GLchar* gs_tested = "#version 430 core\n"
17140 "#extension GL_ARB_enhanced_layouts : require\n"
17141 "\n"
17142 "layout(points) in;\n"
17143 "layout(triangle_strip, max_vertices = 4) out;\n"
17144 "\n"
17145 "VAR_DEFINITION"
17146 "\n"
17147 "in vec4 tes_gs[];\n"
17148 "out vec4 gs_fs;\n"
17149 "\n"
17150 "void main()\n"
17151 "{\n"
17152 " vec4 result = tes_gs[0];\n"
17153 "\n"
17154 "VARIABLE_USE"
17155 "\n"
17156 " gs_fs = result;\n"
17157 " gl_Position = vec4(-1, -1, 0, 1);\n"
17158 " EmitVertex();\n"
17159 " gs_fs = result;\n"
17160 " gl_Position = vec4(-1, 1, 0, 1);\n"
17161 " EmitVertex();\n"
17162 " gs_fs = result;\n"
17163 " gl_Position = vec4(1, -1, 0, 1);\n"
17164 " EmitVertex();\n"
17165 " gs_fs = result;\n"
17166 " gl_Position = vec4(1, 1, 0, 1);\n"
17167 " EmitVertex();\n"
17168 "}\n"
17169 "\n";
17170 static const GLchar* tcs = "#version 430 core\n"
17171 "#extension GL_ARB_enhanced_layouts : require\n"
17172 "\n"
17173 "layout(vertices = 1) out;\n"
17174 "\n"
17175 "in vec4 vs_tcs[];\n"
17176 "out vec4 tcs_tes[];\n"
17177 "\n"
17178 "void main()\n"
17179 "{\n"
17180 "\n"
17181 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17182 "\n"
17183 " gl_TessLevelOuter[0] = 1.0;\n"
17184 " gl_TessLevelOuter[1] = 1.0;\n"
17185 " gl_TessLevelOuter[2] = 1.0;\n"
17186 " gl_TessLevelOuter[3] = 1.0;\n"
17187 " gl_TessLevelInner[0] = 1.0;\n"
17188 " gl_TessLevelInner[1] = 1.0;\n"
17189 "}\n"
17190 "\n";
17191 static const GLchar* tcs_tested = "#version 430 core\n"
17192 "#extension GL_ARB_enhanced_layouts : require\n"
17193 "\n"
17194 "layout(vertices = 1) out;\n"
17195 "\n"
17196 "VAR_DEFINITION"
17197 "\n"
17198 "in vec4 vs_tcs[];\n"
17199 "out vec4 tcs_tes[];\n"
17200 "\n"
17201 "void main()\n"
17202 "{\n"
17203 " vec4 result = vs_tcs[gl_InvocationID];\n"
17204 "\n"
17205 "VARIABLE_USE"
17206 "\n"
17207 " tcs_tes[gl_InvocationID] = result;\n"
17208 "\n"
17209 " gl_TessLevelOuter[0] = 1.0;\n"
17210 " gl_TessLevelOuter[1] = 1.0;\n"
17211 " gl_TessLevelOuter[2] = 1.0;\n"
17212 " gl_TessLevelOuter[3] = 1.0;\n"
17213 " gl_TessLevelInner[0] = 1.0;\n"
17214 " gl_TessLevelInner[1] = 1.0;\n"
17215 "}\n"
17216 "\n";
17217 static const GLchar* tes = "#version 430 core\n"
17218 "#extension GL_ARB_enhanced_layouts : require\n"
17219 "\n"
17220 "layout(isolines, point_mode) in;\n"
17221 "\n"
17222 "in vec4 tcs_tes[];\n"
17223 "out vec4 tes_gs;\n"
17224 "\n"
17225 "void main()\n"
17226 "{\n"
17227 " tes_gs = tcs_tes[0];\n"
17228 "}\n"
17229 "\n";
17230 static const GLchar* tes_tested = "#version 430 core\n"
17231 "#extension GL_ARB_enhanced_layouts : require\n"
17232 "\n"
17233 "layout(isolines, point_mode) in;\n"
17234 "\n"
17235 "VAR_DEFINITION"
17236 "\n"
17237 "in vec4 tcs_tes[];\n"
17238 "out vec4 tes_gs;\n"
17239 "\n"
17240 "void main()\n"
17241 "{\n"
17242 " vec4 result = tcs_tes[0];\n"
17243 "\n"
17244 "VARIABLE_USE"
17245 "\n"
17246 " tes_gs += result;\n"
17247 "}\n"
17248 "\n";
17249 static const GLchar* vs = "#version 430 core\n"
17250 "#extension GL_ARB_enhanced_layouts : require\n"
17251 "\n"
17252 "in vec4 in_vs;\n"
17253 "out vec4 vs_tcs;\n"
17254 "\n"
17255 "void main()\n"
17256 "{\n"
17257 " vs_tcs = in_vs;\n"
17258 "}\n"
17259 "\n";
17260 static const GLchar* vs_tested = "#version 430 core\n"
17261 "#extension GL_ARB_enhanced_layouts : require\n"
17262 "\n"
17263 "VAR_DEFINITION"
17264 "\n"
17265 "in vec4 in_vs;\n"
17266 "out vec4 vs_tcs;\n"
17267 "\n"
17268 "void main()\n"
17269 "{\n"
17270 " vec4 result = in_vs;\n"
17271 "\n"
17272 "VARIABLE_USE"
17273 "\n"
17274 " vs_tcs += result;\n"
17275 "}\n"
17276 "\n";
17277
17278 std::string source;
17279 testCase& test_case = m_test_cases[test_case_index];
17280
17281 if (test_case.m_stage == stage)
17282 {
17283 const GLchar* array = "";
17284 GLchar buffer_gohan[16];
17285 GLchar buffer_goten[16];
17286 const GLchar* index = "";
17287 size_t position = 0;
17288 size_t temp;
17289 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
17290
17291 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17292 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17293
17294 switch (stage)
17295 {
17296 case Utils::Shader::FRAGMENT:
17297 source = fs_tested;
17298 break;
17299 case Utils::Shader::GEOMETRY:
17300 source = gs_tested;
17301 array = "[]";
17302 index = "[0]";
17303 break;
17304 case Utils::Shader::TESS_CTRL:
17305 source = tcs_tested;
17306 array = "[]";
17307 index = "[gl_InvocationID]";
17308 break;
17309 case Utils::Shader::TESS_EVAL:
17310 source = tes_tested;
17311 array = "[]";
17312 index = "[0]";
17313 break;
17314 case Utils::Shader::VERTEX:
17315 source = vs_tested;
17316 break;
17317 default:
17318 TCU_FAIL("Invalid enum");
17319 }
17320
17321 temp = position;
17322 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17323 position = temp;
17324 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17325 Utils::replaceToken("ARRAY", position, array, source);
17326 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17327 Utils::replaceToken("ARRAY", position, array, source);
17328 Utils::replaceToken("VARIABLE_USE", position, l_test, source);
17329
17330 Utils::replaceAllTokens("TYPE", type_name, source);
17331 Utils::replaceAllTokens("INDEX", index, source);
17332 }
17333 else
17334 {
17335 switch (stage)
17336 {
17337 case Utils::Shader::FRAGMENT:
17338 source = fs;
17339 break;
17340 case Utils::Shader::GEOMETRY:
17341 source = gs;
17342 break;
17343 case Utils::Shader::TESS_CTRL:
17344 source = tcs;
17345 break;
17346 case Utils::Shader::TESS_EVAL:
17347 source = tes;
17348 break;
17349 case Utils::Shader::VERTEX:
17350 source = vs;
17351 break;
17352 default:
17353 TCU_FAIL("Invalid enum");
17354 }
17355 }
17356
17357 return source;
17358 }
17359
17360 /** Get description of test case
17361 *
17362 * @param test_case_index Index of test case
17363 *
17364 * @return Test case description
17365 **/
17366 std::string OutputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
17367 {
17368 std::stringstream stream;
17369 testCase& test_case = m_test_cases[test_case_index];
17370
17371 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17372 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
17373 << " & " << test_case.m_component_goten;
17374
17375 return stream.str();
17376 }
17377
17378 /** Get number of test cases
17379 *
17380 * @return Number of test cases
17381 **/
17382 GLuint OutputComponentAliasingTest::getTestCaseNumber()
17383 {
17384 return static_cast<GLuint>(m_test_cases.size());
17385 }
17386
17387 /** Selects if "compute" stage is relevant for test
17388 *
17389 * @param ignored
17390 *
17391 * @return false
17392 **/
17393 bool OutputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
17394 {
17395 return false;
17396 }
17397
17398 /** Prepare all test cases
17399 *
17400 **/
17401 void OutputComponentAliasingTest::testInit()
17402 {
17403 static const GLuint n_components_per_location = 4;
17404 const GLuint n_types = getTypesNumber();
17405
17406 for (GLuint i = 0; i < n_types; ++i)
17407 {
17408 const Utils::Type& type = getType(i);
17409 const GLuint n_req_components = type.m_n_rows;
17410 const GLuint valid_component = n_components_per_location - n_req_components;
17411
17412 /* Skip matrices */
17413 if (1 != type.m_n_columns)
17414 {
17415 continue;
17416 }
17417
17418 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17419 {
17420 if (Utils::Shader::COMPUTE == stage)
17421 {
17422 continue;
17423 }
17424
17425 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Type::Double == type.m_basic_type))
17426 {
17427 continue;
17428 }
17429
17430 for (GLuint gohan = 0; gohan <= valid_component; ++gohan)
17431 {
17432 const GLint first_aliasing = gohan - n_req_components + 1;
17433 const GLint last_aliasing = gohan + n_req_components - 1;
17434
17435 const GLuint goten_start = std::max(0, first_aliasing);
17436 const GLuint goten_stop = std::min((GLint)valid_component, last_aliasing);
17437
17438 for (GLuint goten = goten_start; goten <= goten_stop; ++goten)
17439 {
17440 testCase test_case = { gohan, goten, (Utils::Shader::STAGES)stage, type };
17441
17442 m_test_cases.push_back(test_case);
17443 }
17444 }
17445 }
17446 }
17447 }
17448
17449 /** Constructor
17450 *
17451 * @param context Test framework context
17452 **/
17453 VaryingLocationAliasingWithMixedTypesTest::VaryingLocationAliasingWithMixedTypesTest(deqp::Context& context)
17454 : NegativeTestBase(context, "varying_location_aliasing_with_mixed_types",
17455 "Test verifies that compiler reports error when float/int types are mixed at one location")
17456 {
17457 }
17458
17459 /** Source for given test case and stage
17460 *
17461 * @param test_case_index Index of test case
17462 * @param stage Shader stage
17463 *
17464 * @return Shader source
17465 **/
17466 std::string VaryingLocationAliasingWithMixedTypesTest::getShaderSource(GLuint test_case_index,
17467 Utils::Shader::STAGES stage)
17468 {
17469 static const GLchar* var_definition =
17470 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gohanARRAY;\n"
17471 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gotenARRAY;\n";
17472 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
17473 " (TYPE(1) == gotenINDEX) )\n"
17474 " {\n"
17475 " result += vec4(1, 0.5, 0.25, 0.125);\n"
17476 " }\n";
17477 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
17478 " gotenINDEX = TYPE(1);\n"
17479 " if (vec4(0) == result)\n"
17480 " {\n"
17481 " gohanINDEX = TYPE(1);\n"
17482 " gotenINDEX = TYPE(0);\n"
17483 " }\n";
17484 static const GLchar* fs = "#version 430 core\n"
17485 "#extension GL_ARB_enhanced_layouts : require\n"
17486 "\n"
17487 "in vec4 gs_fs;\n"
17488 "out vec4 fs_out;\n"
17489 "\n"
17490 "void main()\n"
17491 "{\n"
17492 " fs_out = gs_fs;\n"
17493 "}\n"
17494 "\n";
17495 static const GLchar* fs_tested = "#version 430 core\n"
17496 "#extension GL_ARB_enhanced_layouts : require\n"
17497 "\n"
17498 "VAR_DEFINITION"
17499 "\n"
17500 "in vec4 gs_fs;\n"
17501 "out vec4 fs_out;\n"
17502 "\n"
17503 "void main()\n"
17504 "{\n"
17505 " vec4 result = gs_fs;\n"
17506 "\n"
17507 "VARIABLE_USE"
17508 "\n"
17509 " fs_out += result;\n"
17510 "}\n"
17511 "\n";
17512 static const GLchar* gs = "#version 430 core\n"
17513 "#extension GL_ARB_enhanced_layouts : require\n"
17514 "\n"
17515 "layout(points) in;\n"
17516 "layout(triangle_strip, max_vertices = 4) out;\n"
17517 "\n"
17518 "in vec4 tes_gs[];\n"
17519 "out vec4 gs_fs;\n"
17520 "\n"
17521 "void main()\n"
17522 "{\n"
17523 " gs_fs = tes_gs[0];\n"
17524 " gl_Position = vec4(-1, -1, 0, 1);\n"
17525 " EmitVertex();\n"
17526 " gs_fs = tes_gs[0];\n"
17527 " gl_Position = vec4(-1, 1, 0, 1);\n"
17528 " EmitVertex();\n"
17529 " gs_fs = tes_gs[0];\n"
17530 " gl_Position = vec4(1, -1, 0, 1);\n"
17531 " EmitVertex();\n"
17532 " gs_fs = tes_gs[0];\n"
17533 " gl_Position = vec4(1, 1, 0, 1);\n"
17534 " EmitVertex();\n"
17535 "}\n"
17536 "\n";
17537 static const GLchar* gs_tested = "#version 430 core\n"
17538 "#extension GL_ARB_enhanced_layouts : require\n"
17539 "\n"
17540 "layout(points) in;\n"
17541 "layout(triangle_strip, max_vertices = 4) out;\n"
17542 "\n"
17543 "VAR_DEFINITION"
17544 "\n"
17545 "in vec4 tes_gs[];\n"
17546 "out vec4 gs_fs;\n"
17547 "\n"
17548 "void main()\n"
17549 "{\n"
17550 " vec4 result = tes_gs[0];\n"
17551 "\n"
17552 "VARIABLE_USE"
17553 "\n"
17554 " gs_fs = result;\n"
17555 " gl_Position = vec4(-1, -1, 0, 1);\n"
17556 " EmitVertex();\n"
17557 " gs_fs = result;\n"
17558 " gl_Position = vec4(-1, 1, 0, 1);\n"
17559 " EmitVertex();\n"
17560 " gs_fs = result;\n"
17561 " gl_Position = vec4(1, -1, 0, 1);\n"
17562 " EmitVertex();\n"
17563 " gs_fs = result;\n"
17564 " gl_Position = vec4(1, 1, 0, 1);\n"
17565 " EmitVertex();\n"
17566 "}\n"
17567 "\n";
17568 static const GLchar* tcs = "#version 430 core\n"
17569 "#extension GL_ARB_enhanced_layouts : require\n"
17570 "\n"
17571 "layout(vertices = 1) out;\n"
17572 "\n"
17573 "in vec4 vs_tcs[];\n"
17574 "out vec4 tcs_tes[];\n"
17575 "\n"
17576 "void main()\n"
17577 "{\n"
17578 "\n"
17579 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17580 "\n"
17581 " gl_TessLevelOuter[0] = 1.0;\n"
17582 " gl_TessLevelOuter[1] = 1.0;\n"
17583 " gl_TessLevelOuter[2] = 1.0;\n"
17584 " gl_TessLevelOuter[3] = 1.0;\n"
17585 " gl_TessLevelInner[0] = 1.0;\n"
17586 " gl_TessLevelInner[1] = 1.0;\n"
17587 "}\n"
17588 "\n";
17589 static const GLchar* tcs_tested = "#version 430 core\n"
17590 "#extension GL_ARB_enhanced_layouts : require\n"
17591 "\n"
17592 "layout(vertices = 1) out;\n"
17593 "\n"
17594 "VAR_DEFINITION"
17595 "\n"
17596 "in vec4 vs_tcs[];\n"
17597 "out vec4 tcs_tes[];\n"
17598 "\n"
17599 "void main()\n"
17600 "{\n"
17601 " vec4 result = vs_tcs[gl_InvocationID];\n"
17602 "\n"
17603 "VARIABLE_USE"
17604 "\n"
17605 " tcs_tes[gl_InvocationID] = result;\n"
17606 "\n"
17607 " gl_TessLevelOuter[0] = 1.0;\n"
17608 " gl_TessLevelOuter[1] = 1.0;\n"
17609 " gl_TessLevelOuter[2] = 1.0;\n"
17610 " gl_TessLevelOuter[3] = 1.0;\n"
17611 " gl_TessLevelInner[0] = 1.0;\n"
17612 " gl_TessLevelInner[1] = 1.0;\n"
17613 "}\n"
17614 "\n";
17615 static const GLchar* tes = "#version 430 core\n"
17616 "#extension GL_ARB_enhanced_layouts : require\n"
17617 "\n"
17618 "layout(isolines, point_mode) in;\n"
17619 "\n"
17620 "in vec4 tcs_tes[];\n"
17621 "out vec4 tes_gs;\n"
17622 "\n"
17623 "void main()\n"
17624 "{\n"
17625 " tes_gs = tcs_tes[0];\n"
17626 "}\n"
17627 "\n";
17628 static const GLchar* tes_tested = "#version 430 core\n"
17629 "#extension GL_ARB_enhanced_layouts : require\n"
17630 "\n"
17631 "layout(isolines, point_mode) in;\n"
17632 "\n"
17633 "VAR_DEFINITION"
17634 "\n"
17635 "in vec4 tcs_tes[];\n"
17636 "out vec4 tes_gs;\n"
17637 "\n"
17638 "void main()\n"
17639 "{\n"
17640 " vec4 result = tcs_tes[0];\n"
17641 "\n"
17642 "VARIABLE_USE"
17643 "\n"
17644 " tes_gs += result;\n"
17645 "}\n"
17646 "\n";
17647 static const GLchar* vs = "#version 430 core\n"
17648 "#extension GL_ARB_enhanced_layouts : require\n"
17649 "\n"
17650 "in vec4 in_vs;\n"
17651 "out vec4 vs_tcs;\n"
17652 "\n"
17653 "void main()\n"
17654 "{\n"
17655 " vs_tcs = in_vs;\n"
17656 "}\n"
17657 "\n";
17658 static const GLchar* vs_tested = "#version 430 core\n"
17659 "#extension GL_ARB_enhanced_layouts : require\n"
17660 "\n"
17661 "VAR_DEFINITION"
17662 "\n"
17663 "in vec4 in_vs;\n"
17664 "out vec4 vs_tcs;\n"
17665 "\n"
17666 "void main()\n"
17667 "{\n"
17668 " vec4 result = in_vs;\n"
17669 "\n"
17670 "VARIABLE_USE"
17671 "\n"
17672 " vs_tcs += result;\n"
17673 "}\n"
17674 "\n";
17675
17676 std::string source;
17677 testCase& test_case = m_test_cases[test_case_index];
17678
17679 if (test_case.m_stage == stage)
17680 {
17681 const GLchar* array = "";
17682 GLchar buffer_gohan[16];
17683 GLchar buffer_goten[16];
17684 const GLchar* direction = "in ";
17685 const GLchar* flat_gohan = "";
17686 const GLchar* flat_goten = "";
17687 const GLchar* index = "";
17688 size_t position = 0;
17689 size_t temp;
17690 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
17691 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
17692 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
17693 const GLchar* var_use = input_use;
17694
17695 if (false == test_case.m_is_input)
17696 {
17697 direction = "out";
17698 storage = Utils::Variable::VARYING_OUTPUT;
17699 var_use = output_use;
17700 }
17701
17702 if (true == isFlatRequired(stage, test_case.m_type_gohan, storage))
17703 {
17704 flat_gohan = "flat";
17705 }
17706
17707 if (true == isFlatRequired(stage, test_case.m_type_goten, storage))
17708 {
17709 flat_goten = "flat";
17710 }
17711
17712 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17713 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17714
17715 switch (stage)
17716 {
17717 case Utils::Shader::FRAGMENT:
17718 source = fs_tested;
17719 break;
17720 case Utils::Shader::GEOMETRY:
17721 source = gs_tested;
17722 array = "[]";
17723 index = "[0]";
17724 break;
17725 case Utils::Shader::TESS_CTRL:
17726 source = tcs_tested;
17727 array = "[]";
17728 index = "[gl_InvocationID]";
17729 break;
17730 case Utils::Shader::TESS_EVAL:
17731 source = tes_tested;
17732 array = "[]";
17733 index = "[0]";
17734 break;
17735 case Utils::Shader::VERTEX:
17736 source = vs_tested;
17737 break;
17738 default:
17739 TCU_FAIL("Invalid enum");
17740 }
17741
17742 temp = position;
17743 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17744 position = temp;
17745 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17746 Utils::replaceToken("FLAT", position, flat_gohan, source);
17747 Utils::replaceToken("DIRECTION", position, direction, source);
17748 Utils::replaceToken("TYPE", position, type_gohan_name, source);
17749 Utils::replaceToken("ARRAY", position, array, source);
17750 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17751 Utils::replaceToken("FLAT", position, flat_goten, source);
17752 Utils::replaceToken("DIRECTION", position, direction, source);
17753 Utils::replaceToken("TYPE", position, type_goten_name, source);
17754 Utils::replaceToken("ARRAY", position, array, source);
17755
17756 temp = position;
17757 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
17758 position = temp;
17759 if (true == test_case.m_is_input)
17760 {
17761 Utils::replaceToken("TYPE", position, type_gohan_name, source);
17762 Utils::replaceToken("TYPE", position, type_goten_name, source);
17763 }
17764 else
17765 {
17766 Utils::replaceToken("TYPE", position, type_gohan_name, source);
17767 Utils::replaceToken("TYPE", position, type_goten_name, source);
17768 Utils::replaceToken("TYPE", position, type_gohan_name, source);
17769 Utils::replaceToken("TYPE", position, type_goten_name, source);
17770 }
17771
17772 Utils::replaceAllTokens("INDEX", index, source);
17773 }
17774 else
17775 {
17776 switch (stage)
17777 {
17778 case Utils::Shader::FRAGMENT:
17779 source = fs;
17780 break;
17781 case Utils::Shader::GEOMETRY:
17782 source = gs;
17783 break;
17784 case Utils::Shader::TESS_CTRL:
17785 source = tcs;
17786 break;
17787 case Utils::Shader::TESS_EVAL:
17788 source = tes;
17789 break;
17790 case Utils::Shader::VERTEX:
17791 source = vs;
17792 break;
17793 default:
17794 TCU_FAIL("Invalid enum");
17795 }
17796 }
17797
17798 return source;
17799 }
17800
17801 /** Get description of test case
17802 *
17803 * @param test_case_index Index of test case
17804 *
17805 * @return Test case description
17806 **/
17807 std::string VaryingLocationAliasingWithMixedTypesTest::getTestCaseName(GLuint test_case_index)
17808 {
17809 std::stringstream stream;
17810 testCase& test_case = m_test_cases[test_case_index];
17811
17812 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
17813 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
17814 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
17815
17816 if (true == test_case.m_is_input)
17817 {
17818 stream << "input";
17819 }
17820 else
17821 {
17822 stream << "output";
17823 }
17824
17825 return stream.str();
17826 }
17827
17828 /** Get number of test cases
17829 *
17830 * @return Number of test cases
17831 **/
17832 GLuint VaryingLocationAliasingWithMixedTypesTest::getTestCaseNumber()
17833 {
17834 return static_cast<GLuint>(m_test_cases.size());
17835 }
17836
17837 /** Selects if "compute" stage is relevant for test
17838 *
17839 * @param ignored
17840 *
17841 * @return false
17842 **/
17843 bool VaryingLocationAliasingWithMixedTypesTest::isComputeRelevant(GLuint /* test_case_index */)
17844 {
17845 return false;
17846 }
17847
17848 /** Prepare all test cases
17849 *
17850 **/
17851 void VaryingLocationAliasingWithMixedTypesTest::testInit()
17852 {
17853 static const GLuint n_components_per_location = 4;
17854 const GLuint n_types = getTypesNumber();
17855
17856 for (GLuint i = 0; i < n_types; ++i)
17857 {
17858 const Utils::Type& type_gohan = getType(i);
17859 const bool is_float_type_gohan = isFloatType(type_gohan);
17860
17861 /* Skip matrices */
17862 if (1 != type_gohan.m_n_columns)
17863 {
17864 continue;
17865 }
17866
17867 for (GLuint j = 0; j < n_types; ++j)
17868 {
17869 const Utils::Type& type_goten = getType(j);
17870 const bool is_float_type_goten = isFloatType(type_goten);
17871
17872 /* Skip matrices */
17873 if (1 != type_goten.m_n_columns)
17874 {
17875 continue;
17876 }
17877
17878 /* Skip valid combinations */
17879 if (is_float_type_gohan == is_float_type_goten)
17880 {
17881 continue;
17882 }
17883
17884 const GLuint n_req_components_gohan = type_gohan.m_n_rows;
17885 const GLuint n_req_components_goten = type_goten.m_n_rows;
17886 const GLuint valid_component_gohan = n_components_per_location - n_req_components_gohan;
17887 const GLuint valid_component_goten = n_components_per_location - n_req_components_goten;
17888
17889 /* Skip pairs that cannot fit into one location */
17890 if (n_components_per_location < (n_req_components_gohan + n_req_components_goten))
17891 {
17892 continue;
17893 }
17894
17895 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17896 {
17897 /* Skip compute shader */
17898 if (Utils::Shader::COMPUTE == stage)
17899 {
17900 continue;
17901 }
17902
17903 for (GLuint gohan = 0; gohan <= valid_component_gohan; ++gohan)
17904 {
17905 const GLint first_aliasing = gohan - n_req_components_goten + 1;
17906 const GLint last_aliasing = gohan + n_req_components_gohan - 1;
17907
17908 const GLuint goten_lower_limit = std::max(0, first_aliasing);
17909 const GLuint goten_upper_limit = last_aliasing + 1;
17910
17911 /* Compoennets before gohan */
17912 for (GLuint goten = 0; goten < goten_lower_limit; ++goten)
17913 {
17914 testCase test_case_in = { gohan, goten, true, (Utils::Shader::STAGES)stage,
17915 type_gohan, type_goten };
17916 testCase test_case_out = { gohan, goten, false, (Utils::Shader::STAGES)stage,
17917 type_gohan, type_goten };
17918
17919 if (Utils::Shader::VERTEX != stage)
17920 m_test_cases.push_back(test_case_in);
17921
17922 /* Skip double outputs in fragment shader */
17923 if ((Utils::Shader::FRAGMENT != stage) || ((Utils::Type::Double != type_gohan.m_basic_type) &&
17924 (Utils::Type::Double != type_goten.m_basic_type)))
17925 {
17926 m_test_cases.push_back(test_case_out);
17927 }
17928 }
17929
17930 /* Components after gohan */
17931 for (GLuint goten = goten_upper_limit; goten <= valid_component_goten; ++goten)
17932 {
17933 testCase test_case_in = { gohan, goten, true, (Utils::Shader::STAGES)stage,
17934 type_gohan, type_goten };
17935 testCase test_case_out = { gohan, goten, false, (Utils::Shader::STAGES)stage,
17936 type_gohan, type_goten };
17937
17938 if (Utils::Shader::VERTEX != stage)
17939 m_test_cases.push_back(test_case_in);
17940
17941 /* Skip double outputs in fragment shader */
17942 if ((Utils::Shader::FRAGMENT != stage) || ((Utils::Type::Double != type_gohan.m_basic_type) &&
17943 (Utils::Type::Double != type_goten.m_basic_type)))
17944 {
17945 m_test_cases.push_back(test_case_out);
17946 }
17947 }
17948 }
17949 }
17950 }
17951 }
17952 }
17953
17954 /** Check if given type is float
17955 *
17956 * @param type Type in question
17957 *
17958 * @return true if tpye is float, false otherwise
17959 **/
17960 bool VaryingLocationAliasingWithMixedTypesTest::isFloatType(const Utils::Type& type)
17961 {
17962 bool is_float = false;
17963
17964 if ((Utils::Type::Double == type.m_basic_type) || (Utils::Type::Float == type.m_basic_type))
17965 {
17966 is_float = true;
17967 }
17968
17969 return is_float;
17970 }
17971
17972 /** Constructor
17973 *
17974 * @param context Test framework context
17975 **/
17976 VaryingLocationAliasingWithMixedInterpolationTest::VaryingLocationAliasingWithMixedInterpolationTest(
17977 deqp::Context& context)
17978 : NegativeTestBase(
17979 context, "varying_location_aliasing_with_mixed_interpolation",
17980 "Test verifies that compiler reports error when interpolation qualifiers are mixed at one location")
17981 {
17982 }
17983
17984 /** Source for given test case and stage
17985 *
17986 * @param test_case_index Index of test case
17987 * @param stage Shader stage
17988 *
17989 * @return Shader source
17990 **/
17991 std::string VaryingLocationAliasingWithMixedInterpolationTest::getShaderSource(GLuint test_case_index,
17992 Utils::Shader::STAGES stage)
17993 {
17994 static const GLchar* var_definition =
17995 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
17996 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
17997 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
17998 " (TYPE(1) == gotenINDEX) )\n"
17999 " {\n"
18000 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18001 " }\n";
18002 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
18003 " gotenINDEX = TYPE(1);\n"
18004 " if (vec4(0) == result)\n"
18005 " {\n"
18006 " gohanINDEX = TYPE(1);\n"
18007 " gotenINDEX = TYPE(0);\n"
18008 " }\n";
18009 static const GLchar* fs = "#version 430 core\n"
18010 "#extension GL_ARB_enhanced_layouts : require\n"
18011 "\n"
18012 "in vec4 gs_fs;\n"
18013 "out vec4 fs_out;\n"
18014 "\n"
18015 "void main()\n"
18016 "{\n"
18017 " fs_out = gs_fs;\n"
18018 "}\n"
18019 "\n";
18020 static const GLchar* fs_tested = "#version 430 core\n"
18021 "#extension GL_ARB_enhanced_layouts : require\n"
18022 "\n"
18023 "VAR_DEFINITION"
18024 "\n"
18025 "in vec4 gs_fs;\n"
18026 "out vec4 fs_out;\n"
18027 "\n"
18028 "void main()\n"
18029 "{\n"
18030 " vec4 result = gs_fs;\n"
18031 "\n"
18032 "VARIABLE_USE"
18033 "\n"
18034 " fs_out = result;\n"
18035 "}\n"
18036 "\n";
18037 static const GLchar* gs = "#version 430 core\n"
18038 "#extension GL_ARB_enhanced_layouts : require\n"
18039 "\n"
18040 "layout(points) in;\n"
18041 "layout(triangle_strip, max_vertices = 4) out;\n"
18042 "\n"
18043 "in vec4 tes_gs[];\n"
18044 "out vec4 gs_fs;\n"
18045 "\n"
18046 "void main()\n"
18047 "{\n"
18048 " gs_fs = tes_gs[0];\n"
18049 " gl_Position = vec4(-1, -1, 0, 1);\n"
18050 " EmitVertex();\n"
18051 " gs_fs = tes_gs[0];\n"
18052 " gl_Position = vec4(-1, 1, 0, 1);\n"
18053 " EmitVertex();\n"
18054 " gs_fs = tes_gs[0];\n"
18055 " gl_Position = vec4(1, -1, 0, 1);\n"
18056 " EmitVertex();\n"
18057 " gs_fs = tes_gs[0];\n"
18058 " gl_Position = vec4(1, 1, 0, 1);\n"
18059 " EmitVertex();\n"
18060 "}\n"
18061 "\n";
18062 static const GLchar* gs_tested = "#version 430 core\n"
18063 "#extension GL_ARB_enhanced_layouts : require\n"
18064 "\n"
18065 "layout(points) in;\n"
18066 "layout(triangle_strip, max_vertices = 4) out;\n"
18067 "\n"
18068 "VAR_DEFINITION"
18069 "\n"
18070 "in vec4 tes_gs[];\n"
18071 "out vec4 gs_fs;\n"
18072 "\n"
18073 "void main()\n"
18074 "{\n"
18075 " vec4 result = tes_gs[0];\n"
18076 "\n"
18077 "VARIABLE_USE"
18078 "\n"
18079 " gs_fs = result;\n"
18080 " gl_Position = vec4(-1, -1, 0, 1);\n"
18081 " EmitVertex();\n"
18082 " gs_fs = result;\n"
18083 " gl_Position = vec4(-1, 1, 0, 1);\n"
18084 " EmitVertex();\n"
18085 " gs_fs = result;\n"
18086 " gl_Position = vec4(1, -1, 0, 1);\n"
18087 " EmitVertex();\n"
18088 " gs_fs = result;\n"
18089 " gl_Position = vec4(1, 1, 0, 1);\n"
18090 " EmitVertex();\n"
18091 "}\n"
18092 "\n";
18093 static const GLchar* tcs = "#version 430 core\n"
18094 "#extension GL_ARB_enhanced_layouts : require\n"
18095 "\n"
18096 "layout(vertices = 1) out;\n"
18097 "\n"
18098 "in vec4 vs_tcs[];\n"
18099 "out vec4 tcs_tes[];\n"
18100 "\n"
18101 "void main()\n"
18102 "{\n"
18103 "\n"
18104 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18105 "\n"
18106 " gl_TessLevelOuter[0] = 1.0;\n"
18107 " gl_TessLevelOuter[1] = 1.0;\n"
18108 " gl_TessLevelOuter[2] = 1.0;\n"
18109 " gl_TessLevelOuter[3] = 1.0;\n"
18110 " gl_TessLevelInner[0] = 1.0;\n"
18111 " gl_TessLevelInner[1] = 1.0;\n"
18112 "}\n"
18113 "\n";
18114 static const GLchar* tcs_tested = "#version 430 core\n"
18115 "#extension GL_ARB_enhanced_layouts : require\n"
18116 "\n"
18117 "layout(vertices = 1) out;\n"
18118 "\n"
18119 "VAR_DEFINITION"
18120 "\n"
18121 "in vec4 vs_tcs[];\n"
18122 "out vec4 tcs_tes[];\n"
18123 "\n"
18124 "void main()\n"
18125 "{\n"
18126 " vec4 result = vs_tcs[gl_InvocationID];\n"
18127 "\n"
18128 "VARIABLE_USE"
18129 "\n"
18130 " tcs_tes[gl_InvocationID] = result;\n"
18131 "\n"
18132 " gl_TessLevelOuter[0] = 1.0;\n"
18133 " gl_TessLevelOuter[1] = 1.0;\n"
18134 " gl_TessLevelOuter[2] = 1.0;\n"
18135 " gl_TessLevelOuter[3] = 1.0;\n"
18136 " gl_TessLevelInner[0] = 1.0;\n"
18137 " gl_TessLevelInner[1] = 1.0;\n"
18138 "}\n"
18139 "\n";
18140 static const GLchar* tes = "#version 430 core\n"
18141 "#extension GL_ARB_enhanced_layouts : require\n"
18142 "\n"
18143 "layout(isolines, point_mode) in;\n"
18144 "\n"
18145 "in vec4 tcs_tes[];\n"
18146 "out vec4 tes_gs;\n"
18147 "\n"
18148 "void main()\n"
18149 "{\n"
18150 " tes_gs = tcs_tes[0];\n"
18151 "}\n"
18152 "\n";
18153 static const GLchar* tes_tested = "#version 430 core\n"
18154 "#extension GL_ARB_enhanced_layouts : require\n"
18155 "\n"
18156 "layout(isolines, point_mode) in;\n"
18157 "\n"
18158 "VAR_DEFINITION"
18159 "\n"
18160 "in vec4 tcs_tes[];\n"
18161 "out vec4 tes_gs;\n"
18162 "\n"
18163 "void main()\n"
18164 "{\n"
18165 " vec4 result = tcs_tes[0];\n"
18166 "\n"
18167 "VARIABLE_USE"
18168 "\n"
18169 " tes_gs += result;\n"
18170 "}\n"
18171 "\n";
18172 static const GLchar* vs = "#version 430 core\n"
18173 "#extension GL_ARB_enhanced_layouts : require\n"
18174 "\n"
18175 "in vec4 in_vs;\n"
18176 "out vec4 vs_tcs;\n"
18177 "\n"
18178 "void main()\n"
18179 "{\n"
18180 " vs_tcs = in_vs;\n"
18181 "}\n"
18182 "\n";
18183 static const GLchar* vs_tested = "#version 430 core\n"
18184 "#extension GL_ARB_enhanced_layouts : require\n"
18185 "\n"
18186 "VAR_DEFINITION"
18187 "\n"
18188 "in vec4 in_vs;\n"
18189 "out vec4 vs_tcs;\n"
18190 "\n"
18191 "void main()\n"
18192 "{\n"
18193 " vec4 result = in_vs;\n"
18194 "\n"
18195 "VARIABLE_USE"
18196 "\n"
18197 " vs_tcs += result;\n"
18198 "}\n"
18199 "\n";
18200
18201 std::string source;
18202 testCase& test_case = m_test_cases[test_case_index];
18203
18204 if (test_case.m_stage == stage)
18205 {
18206 const GLchar* array = "";
18207 GLchar buffer_gohan[16];
18208 GLchar buffer_goten[16];
18209 const GLchar* direction = "in ";
18210 const GLchar* index = "";
18211 const GLchar* int_gohan = getInterpolationQualifier(test_case.m_interpolation_gohan);
18212 const GLchar* int_goten = getInterpolationQualifier(test_case.m_interpolation_goten);
18213 size_t position = 0;
18214 size_t temp;
18215 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18216 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18217 const GLchar* var_use = input_use;
18218
18219 if (false == test_case.m_is_input)
18220 {
18221 direction = "out";
18222
18223 var_use = output_use;
18224 }
18225
18226 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18227 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18228
18229 switch (stage)
18230 {
18231 case Utils::Shader::FRAGMENT:
18232 source = fs_tested;
18233 break;
18234 case Utils::Shader::GEOMETRY:
18235 source = gs_tested;
18236 array = "[]";
18237 index = "[0]";
18238 break;
18239 case Utils::Shader::TESS_CTRL:
18240 source = tcs_tested;
18241 array = "[]";
18242 index = "[gl_InvocationID]";
18243 break;
18244 case Utils::Shader::TESS_EVAL:
18245 source = tes_tested;
18246 array = "[]";
18247 index = "[0]";
18248 break;
18249 case Utils::Shader::VERTEX:
18250 source = vs_tested;
18251 break;
18252 default:
18253 TCU_FAIL("Invalid enum");
18254 }
18255
18256 temp = position;
18257 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18258 position = temp;
18259 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18260 Utils::replaceToken("INTERPOLATION", position, int_gohan, source);
18261 Utils::replaceToken("DIRECTION", position, direction, source);
18262 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18263 Utils::replaceToken("ARRAY", position, array, source);
18264 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18265 Utils::replaceToken("INTERPOLATION", position, int_goten, source);
18266 Utils::replaceToken("DIRECTION", position, direction, source);
18267 Utils::replaceToken("TYPE", position, type_goten_name, source);
18268 Utils::replaceToken("ARRAY", position, array, source);
18269
18270 temp = position;
18271 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18272 position = temp;
18273 if (true == test_case.m_is_input)
18274 {
18275 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18276 Utils::replaceToken("TYPE", position, type_goten_name, source);
18277 }
18278 else
18279 {
18280 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18281 Utils::replaceToken("TYPE", position, type_goten_name, source);
18282 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18283 Utils::replaceToken("TYPE", position, type_goten_name, source);
18284 }
18285
18286 Utils::replaceAllTokens("INDEX", index, source);
18287 }
18288 else
18289 {
18290 switch (stage)
18291 {
18292 case Utils::Shader::FRAGMENT:
18293 source = fs;
18294 break;
18295 case Utils::Shader::GEOMETRY:
18296 source = gs;
18297 break;
18298 case Utils::Shader::TESS_CTRL:
18299 source = tcs;
18300 break;
18301 case Utils::Shader::TESS_EVAL:
18302 source = tes;
18303 break;
18304 case Utils::Shader::VERTEX:
18305 source = vs;
18306 break;
18307 default:
18308 TCU_FAIL("Invalid enum");
18309 }
18310 }
18311
18312 return source;
18313 }
18314
18315 /** Get description of test case
18316 *
18317 * @param test_case_index Index of test case
18318 *
18319 * @return Test case description
18320 **/
18321 std::string VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseName(GLuint test_case_index)
18322 {
18323 std::stringstream stream;
18324 testCase& test_case = m_test_cases[test_case_index];
18325
18326 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18327 << getInterpolationQualifier(test_case.m_interpolation_gohan) << " "
18328 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
18329 << getInterpolationQualifier(test_case.m_interpolation_goten) << " "
18330 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18331
18332 if (true == test_case.m_is_input)
18333 {
18334 stream << "input";
18335 }
18336 else
18337 {
18338 stream << "output";
18339 }
18340
18341 return stream.str();
18342 }
18343
18344 /** Get number of test cases
18345 *
18346 * @return Number of test cases
18347 **/
18348 GLuint VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseNumber()
18349 {
18350 return static_cast<GLuint>(m_test_cases.size());
18351 }
18352
18353 /** Selects if "compute" stage is relevant for test
18354 *
18355 * @param ignored
18356 *
18357 * @return false
18358 **/
18359 bool VaryingLocationAliasingWithMixedInterpolationTest::isComputeRelevant(GLuint /* test_case_index */)
18360 {
18361 return false;
18362 }
18363
18364 /** Prepare all test cases
18365 *
18366 **/
18367 void VaryingLocationAliasingWithMixedInterpolationTest::testInit()
18368 {
18369 static const GLuint n_components_per_location = 4;
18370 const GLuint n_types = getTypesNumber();
18371
18372 for (GLuint i = 0; i < n_types; ++i)
18373 {
18374 const Utils::Type& type_gohan = getType(i);
18375 const bool is_float_type_gohan = isFloatType(type_gohan);
18376
18377 /* Skip matrices */
18378 if (1 != type_gohan.m_n_columns)
18379 {
18380 continue;
18381 }
18382
18383 for (GLuint j = 0; j < n_types; ++j)
18384 {
18385 const Utils::Type& type_goten = getType(j);
18386 const bool is_float_type_goten = isFloatType(type_goten);
18387
18388 /* Skip matrices */
18389 if (1 != type_goten.m_n_columns)
18390 {
18391 continue;
18392 }
18393
18394 /* Skip invalid combinations */
18395 if (is_float_type_gohan != is_float_type_goten)
18396 {
18397 continue;
18398 }
18399
18400 const GLuint n_req_components_gohan = type_gohan.m_n_rows;
18401 const GLuint n_req_components_goten = type_goten.m_n_rows;
18402
18403 /* Skip pairs that cannot fit into one location */
18404 if (n_components_per_location < (n_req_components_gohan + n_req_components_goten))
18405 {
18406 continue;
18407 }
18408
18409 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18410 {
18411 /* Skip compute shader */
18412 if (Utils::Shader::COMPUTE == stage)
18413 {
18414 continue;
18415 }
18416
18417 const GLuint gohan = 0;
18418 const GLuint goten = gohan + n_req_components_gohan;
18419
18420 for (GLuint int_gohan = 0; int_gohan < INTERPOLATION_MAX; ++int_gohan)
18421 {
18422 for (GLuint int_goten = 0; int_goten < INTERPOLATION_MAX; ++int_goten)
18423 {
18424 const bool is_gohan_double = (Utils::Type::Double == type_gohan.m_basic_type) ? true : false;
18425 const bool is_goten_double = (Utils::Type::Double == type_goten.m_basic_type) ? true : false;
18426 const bool is_gohan_flat = (FLAT == int_gohan) ? true : false;
18427 const bool is_goten_flat = (FLAT == int_goten) ? true : false;
18428 const bool is_gohan_accepted_as_fs_in =
18429 (is_gohan_double && is_gohan_flat) || (!is_gohan_double);
18430 const bool is_goten_accepted_as_fs_in =
18431 (is_goten_double && is_goten_flat) || (!is_goten_double);
18432 const bool is_comb_accepted_as_fs_in = is_gohan_accepted_as_fs_in && is_goten_accepted_as_fs_in;
18433
18434 /* Skip when both are the same */
18435 if (int_gohan == int_goten)
18436 {
18437 continue;
18438 }
18439
18440 testCase test_case_in = { gohan,
18441 goten,
18442 (INTERPOLATIONS)int_gohan,
18443 (INTERPOLATIONS)int_goten,
18444 true,
18445 (Utils::Shader::STAGES)stage,
18446 type_gohan,
18447 type_goten };
18448
18449 testCase test_case_out = { gohan,
18450 goten,
18451 (INTERPOLATIONS)int_gohan,
18452 (INTERPOLATIONS)int_goten,
18453 false,
18454 (Utils::Shader::STAGES)stage,
18455 type_gohan,
18456 type_goten };
18457
18458 /* Skip inputs in:
18459 * vertex shader,
18460 * fragment shader when not flat double is used
18461 */
18462 if ((Utils::Shader::VERTEX != stage) &&
18463 ((Utils::Shader::FRAGMENT != stage) || (true == is_comb_accepted_as_fs_in)))
18464 {
18465 m_test_cases.push_back(test_case_in);
18466 }
18467
18468 /* Skip outputs in fragment shader */
18469 if (Utils::Shader::FRAGMENT != stage)
18470 {
18471 m_test_cases.push_back(test_case_out);
18472 }
18473 }
18474 }
18475 }
18476 }
18477 }
18478 }
18479
18480 /** Get interpolation qualifier
18481 *
18482 * @param interpolation Enumeration
18483 *
18484 * @return GLSL qualifier
18485 **/
18486 const GLchar* VaryingLocationAliasingWithMixedInterpolationTest::getInterpolationQualifier(INTERPOLATIONS interpolation)
18487 {
18488 const GLchar* result = 0;
18489
18490 switch (interpolation)
18491 {
18492 case SMOOTH:
18493 result = "smooth";
18494 break;
18495 case FLAT:
18496 result = "flat";
18497 break;
18498 case NO_PERSPECTIVE:
18499 result = "noperspective";
18500 break;
18501 default:
18502 TCU_FAIL("Invalid enum");
18503 }
18504
18505 return result;
18506 }
18507
18508 /** Check if given type is float
18509 *
18510 * @param type Type in question
18511 *
18512 * @return true if tpye is float, false otherwise
18513 **/
18514 bool VaryingLocationAliasingWithMixedInterpolationTest::isFloatType(const Utils::Type& type)
18515 {
18516 bool is_float = false;
18517
18518 if ((Utils::Type::Double == type.m_basic_type) || (Utils::Type::Float == type.m_basic_type))
18519 {
18520 is_float = true;
18521 }
18522
18523 return is_float;
18524 }
18525
18526 /** Constructor
18527 *
18528 * @param context Test framework context
18529 **/
18530 VaryingLocationAliasingWithMixedAuxiliaryStorageTest::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(
18531 deqp::Context& context)
18532 : NegativeTestBase(
18533 context, "varying_location_aliasing_with_mixed_auxiliary_storage",
18534 "Test verifies that compiler reports error when auxiliary storage qualifiers are mixed at one location")
18535 {
18536 }
18537
18538 /** Source for given test case and stage
18539 *
18540 * @param test_case_index Index of test case
18541 * @param stage Shader stage
18542 *
18543 * @return Shader source
18544 **/
18545 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getShaderSource(GLuint test_case_index,
18546 Utils::Shader::STAGES stage)
18547 {
18548 static const GLchar* var_definition =
18549 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
18550 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
18551 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX_GOHAN) &&\n"
18552 " (TYPE(1) == gotenINDEX_GOTEN) )\n"
18553 " {\n"
18554 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18555 " }\n";
18556 static const GLchar* output_use = " gohanINDEX_GOHAN = TYPE(0);\n"
18557 " gotenINDEX_GOTEN = TYPE(1);\n"
18558 " if (vec4(0) == result)\n"
18559 " {\n"
18560 " gohanINDEX_GOHAN = TYPE(1);\n"
18561 " gotenINDEX_GOTEN = TYPE(0);\n"
18562 " }\n";
18563 static const GLchar* fs = "#version 430 core\n"
18564 "#extension GL_ARB_enhanced_layouts : require\n"
18565 "\n"
18566 "in vec4 gs_fs;\n"
18567 "out vec4 fs_out;\n"
18568 "\n"
18569 "void main()\n"
18570 "{\n"
18571 " fs_out = gs_fs;\n"
18572 "}\n"
18573 "\n";
18574 static const GLchar* fs_tested = "#version 430 core\n"
18575 "#extension GL_ARB_enhanced_layouts : require\n"
18576 "\n"
18577 "VAR_DEFINITION"
18578 "\n"
18579 "in vec4 gs_fs;\n"
18580 "out vec4 fs_out;\n"
18581 "\n"
18582 "void main()\n"
18583 "{\n"
18584 " vec4 result = gs_fs;\n"
18585 "\n"
18586 "VARIABLE_USE"
18587 "\n"
18588 " fs_out = result;\n"
18589 "}\n"
18590 "\n";
18591 static const GLchar* gs = "#version 430 core\n"
18592 "#extension GL_ARB_enhanced_layouts : require\n"
18593 "\n"
18594 "layout(points) in;\n"
18595 "layout(triangle_strip, max_vertices = 4) out;\n"
18596 "\n"
18597 "in vec4 tes_gs[];\n"
18598 "out vec4 gs_fs;\n"
18599 "\n"
18600 "void main()\n"
18601 "{\n"
18602 " gs_fs = tes_gs[0];\n"
18603 " gl_Position = vec4(-1, -1, 0, 1);\n"
18604 " EmitVertex();\n"
18605 " gs_fs = tes_gs[0];\n"
18606 " gl_Position = vec4(-1, 1, 0, 1);\n"
18607 " EmitVertex();\n"
18608 " gs_fs = tes_gs[0];\n"
18609 " gl_Position = vec4(1, -1, 0, 1);\n"
18610 " EmitVertex();\n"
18611 " gs_fs = tes_gs[0];\n"
18612 " gl_Position = vec4(1, 1, 0, 1);\n"
18613 " EmitVertex();\n"
18614 "}\n"
18615 "\n";
18616 static const GLchar* gs_tested = "#version 430 core\n"
18617 "#extension GL_ARB_enhanced_layouts : require\n"
18618 "\n"
18619 "layout(points) in;\n"
18620 "layout(triangle_strip, max_vertices = 4) out;\n"
18621 "\n"
18622 "VAR_DEFINITION"
18623 "\n"
18624 "in vec4 tes_gs[];\n"
18625 "out vec4 gs_fs;\n"
18626 "\n"
18627 "void main()\n"
18628 "{\n"
18629 " vec4 result = tes_gs[0];\n"
18630 "\n"
18631 "VARIABLE_USE"
18632 "\n"
18633 " gs_fs = result;\n"
18634 " gl_Position = vec4(-1, -1, 0, 1);\n"
18635 " EmitVertex();\n"
18636 " gs_fs = result;\n"
18637 " gl_Position = vec4(-1, 1, 0, 1);\n"
18638 " EmitVertex();\n"
18639 " gs_fs = result;\n"
18640 " gl_Position = vec4(1, -1, 0, 1);\n"
18641 " EmitVertex();\n"
18642 " gs_fs = result;\n"
18643 " gl_Position = vec4(1, 1, 0, 1);\n"
18644 " EmitVertex();\n"
18645 "}\n"
18646 "\n";
18647 static const GLchar* tcs = "#version 430 core\n"
18648 "#extension GL_ARB_enhanced_layouts : require\n"
18649 "\n"
18650 "layout(vertices = 1) out;\n"
18651 "\n"
18652 "in vec4 vs_tcs[];\n"
18653 "out vec4 tcs_tes[];\n"
18654 "\n"
18655 "void main()\n"
18656 "{\n"
18657 "\n"
18658 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18659 "\n"
18660 " gl_TessLevelOuter[0] = 1.0;\n"
18661 " gl_TessLevelOuter[1] = 1.0;\n"
18662 " gl_TessLevelOuter[2] = 1.0;\n"
18663 " gl_TessLevelOuter[3] = 1.0;\n"
18664 " gl_TessLevelInner[0] = 1.0;\n"
18665 " gl_TessLevelInner[1] = 1.0;\n"
18666 "}\n"
18667 "\n";
18668 static const GLchar* tcs_tested = "#version 430 core\n"
18669 "#extension GL_ARB_enhanced_layouts : require\n"
18670 "\n"
18671 "layout(vertices = 1) out;\n"
18672 "\n"
18673 "VAR_DEFINITION"
18674 "\n"
18675 "in vec4 vs_tcs[];\n"
18676 "out vec4 tcs_tes[];\n"
18677 "\n"
18678 "void main()\n"
18679 "{\n"
18680 " vec4 result = vs_tcs[gl_InvocationID];\n"
18681 "\n"
18682 "VARIABLE_USE"
18683 "\n"
18684 " tcs_tes[gl_InvocationID] = result;\n"
18685 "\n"
18686 " gl_TessLevelOuter[0] = 1.0;\n"
18687 " gl_TessLevelOuter[1] = 1.0;\n"
18688 " gl_TessLevelOuter[2] = 1.0;\n"
18689 " gl_TessLevelOuter[3] = 1.0;\n"
18690 " gl_TessLevelInner[0] = 1.0;\n"
18691 " gl_TessLevelInner[1] = 1.0;\n"
18692 "}\n"
18693 "\n";
18694 static const GLchar* tes = "#version 430 core\n"
18695 "#extension GL_ARB_enhanced_layouts : require\n"
18696 "\n"
18697 "layout(isolines, point_mode) in;\n"
18698 "\n"
18699 "in vec4 tcs_tes[];\n"
18700 "out vec4 tes_gs;\n"
18701 "\n"
18702 "void main()\n"
18703 "{\n"
18704 " tes_gs = tcs_tes[0];\n"
18705 "}\n"
18706 "\n";
18707 static const GLchar* tes_tested = "#version 430 core\n"
18708 "#extension GL_ARB_enhanced_layouts : require\n"
18709 "\n"
18710 "layout(isolines, point_mode) in;\n"
18711 "\n"
18712 "VAR_DEFINITION"
18713 "\n"
18714 "in vec4 tcs_tes[];\n"
18715 "out vec4 tes_gs;\n"
18716 "\n"
18717 "void main()\n"
18718 "{\n"
18719 " vec4 result = tcs_tes[0];\n"
18720 "\n"
18721 "VARIABLE_USE"
18722 "\n"
18723 " tes_gs += result;\n"
18724 "}\n"
18725 "\n";
18726 static const GLchar* vs = "#version 430 core\n"
18727 "#extension GL_ARB_enhanced_layouts : require\n"
18728 "\n"
18729 "in vec4 in_vs;\n"
18730 "out vec4 vs_tcs;\n"
18731 "\n"
18732 "void main()\n"
18733 "{\n"
18734 " vs_tcs = in_vs;\n"
18735 "}\n"
18736 "\n";
18737 static const GLchar* vs_tested = "#version 430 core\n"
18738 "#extension GL_ARB_enhanced_layouts : require\n"
18739 "\n"
18740 "VAR_DEFINITION"
18741 "\n"
18742 "in vec4 in_vs;\n"
18743 "out vec4 vs_tcs;\n"
18744 "\n"
18745 "void main()\n"
18746 "{\n"
18747 " vec4 result = in_vs;\n"
18748 "\n"
18749 "VARIABLE_USE"
18750 "\n"
18751 " vs_tcs += result;\n"
18752 "}\n"
18753 "\n";
18754
18755 std::string source;
18756 testCase& test_case = m_test_cases[test_case_index];
18757
18758 if (test_case.m_stage == stage)
18759 {
18760 const GLchar* array_gohan = "";
18761 const GLchar* array_goten = "";
18762 const GLchar* aux_gohan = getAuxiliaryQualifier(test_case.m_aux_gohan);
18763 const GLchar* aux_goten = getAuxiliaryQualifier(test_case.m_aux_goten);
18764 GLchar buffer_gohan[16];
18765 GLchar buffer_goten[16];
18766 const GLchar* direction = "in ";
18767 const GLchar* index_gohan = "";
18768 const GLchar* index_goten = "";
18769 const GLchar* int_gohan = test_case.m_int_gohan;
18770 const GLchar* int_goten = test_case.m_int_goten;
18771 size_t position = 0;
18772 size_t temp;
18773 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18774 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18775 const GLchar* var_use = input_use;
18776
18777 if (false == test_case.m_is_input)
18778 {
18779 direction = "out";
18780
18781 var_use = output_use;
18782 }
18783
18784 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18785 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18786
18787 switch (stage)
18788 {
18789 case Utils::Shader::FRAGMENT:
18790 source = fs_tested;
18791 break;
18792 case Utils::Shader::GEOMETRY:
18793 source = gs_tested;
18794 array_gohan = "[]";
18795 index_gohan = "[0]";
18796 array_goten = "[]";
18797 index_goten = "[0]";
18798 break;
18799 case Utils::Shader::TESS_CTRL:
18800 source = tcs_tested;
18801 if (PATCH != test_case.m_aux_gohan)
18802 {
18803 array_gohan = "[]";
18804 index_gohan = "[gl_InvocationID]";
18805 }
18806 if (PATCH != test_case.m_aux_goten)
18807 {
18808 array_goten = "[]";
18809 index_goten = "[gl_InvocationID]";
18810 }
18811 break;
18812 case Utils::Shader::TESS_EVAL:
18813 source = tes_tested;
18814 array_gohan = "[]";
18815 index_gohan = "[0]";
18816 array_goten = "[]";
18817 index_goten = "[0]";
18818 break;
18819 case Utils::Shader::VERTEX:
18820 source = vs_tested;
18821 break;
18822 default:
18823 TCU_FAIL("Invalid enum");
18824 }
18825
18826 temp = position;
18827 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18828 position = temp;
18829 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18830 Utils::replaceToken("AUX", position, aux_gohan, source);
18831 Utils::replaceToken("INTERPOLATION", position, int_gohan, source);
18832 Utils::replaceToken("DIRECTION", position, direction, source);
18833 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18834 Utils::replaceToken("ARRAY", position, array_gohan, source);
18835 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18836 Utils::replaceToken("AUX", position, aux_goten, source);
18837 Utils::replaceToken("INTERPOLATION", position, int_goten, source);
18838 Utils::replaceToken("DIRECTION", position, direction, source);
18839 Utils::replaceToken("TYPE", position, type_goten_name, source);
18840 Utils::replaceToken("ARRAY", position, array_goten, source);
18841
18842 temp = position;
18843 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18844 position = temp;
18845 if (true == test_case.m_is_input)
18846 {
18847 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18848 Utils::replaceToken("TYPE", position, type_goten_name, source);
18849 }
18850 else
18851 {
18852 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18853 Utils::replaceToken("TYPE", position, type_goten_name, source);
18854 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18855 Utils::replaceToken("TYPE", position, type_goten_name, source);
18856 }
18857
18858 Utils::replaceAllTokens("INDEX_GOHAN", index_gohan, source);
18859 Utils::replaceAllTokens("INDEX_GOTEN", index_goten, source);
18860 }
18861 else
18862 {
18863 switch (stage)
18864 {
18865 case Utils::Shader::FRAGMENT:
18866 source = fs;
18867 break;
18868 case Utils::Shader::GEOMETRY:
18869 source = gs;
18870 break;
18871 case Utils::Shader::TESS_CTRL:
18872 source = tcs;
18873 break;
18874 case Utils::Shader::TESS_EVAL:
18875 source = tes;
18876 break;
18877 case Utils::Shader::VERTEX:
18878 source = vs;
18879 break;
18880 default:
18881 TCU_FAIL("Invalid enum");
18882 }
18883 }
18884
18885 return source;
18886 }
18887
18888 /** Get description of test case
18889 *
18890 * @param test_case_index Index of test case
18891 *
18892 * @return Test case description
18893 **/
18894 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseName(GLuint test_case_index)
18895 {
18896 std::stringstream stream;
18897 testCase& test_case = m_test_cases[test_case_index];
18898
18899 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18900 << getAuxiliaryQualifier(test_case.m_aux_gohan) << " " << test_case.m_type_gohan.GetGLSLTypeName() << " at "
18901 << test_case.m_component_gohan << ", " << getAuxiliaryQualifier(test_case.m_aux_goten) << " "
18902 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18903
18904 if (true == test_case.m_is_input)
18905 {
18906 stream << "input";
18907 }
18908 else
18909 {
18910 stream << "output";
18911 }
18912
18913 return stream.str();
18914 }
18915
18916 /** Get number of test cases
18917 *
18918 * @return Number of test cases
18919 **/
18920 GLuint VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseNumber()
18921 {
18922 return static_cast<GLuint>(m_test_cases.size());
18923 }
18924
18925 /** Selects if "compute" stage is relevant for test
18926 *
18927 * @param ignored
18928 *
18929 * @return false
18930 **/
18931 bool VaryingLocationAliasingWithMixedAuxiliaryStorageTest::isComputeRelevant(GLuint /* test_case_index */)
18932 {
18933 return false;
18934 }
18935
18936 /** Prepare all test cases
18937 *
18938 **/
18939 void VaryingLocationAliasingWithMixedAuxiliaryStorageTest::testInit()
18940 {
18941 static const GLuint n_components_per_location = 4;
18942 const GLuint n_types = getTypesNumber();
18943
18944 for (GLuint i = 0; i < n_types; ++i)
18945 {
18946 const Utils::Type& type_gohan = getType(i);
18947 const bool is_float_type_gohan = isFloatType(type_gohan);
18948
18949 /* Skip matrices */
18950 if (1 != type_gohan.m_n_columns)
18951 {
18952 continue;
18953 }
18954
18955 for (GLuint j = 0; j < n_types; ++j)
18956 {
18957 const Utils::Type& type_goten = getType(j);
18958 const bool is_flat_req_gohan = (Utils::Type::Float == type_gohan.m_basic_type) ? false : true;
18959 const bool is_flat_req_goten = (Utils::Type::Float == type_goten.m_basic_type) ? false : true;
18960 const bool is_float_type_goten = isFloatType(type_goten);
18961
18962 /* Skip matrices */
18963 if (1 != type_goten.m_n_columns)
18964 {
18965 continue;
18966 }
18967
18968 /* Skip invalid combinations */
18969 if (is_float_type_gohan != is_float_type_goten)
18970 {
18971 continue;
18972 }
18973
18974 const GLuint n_req_components_gohan = type_gohan.m_n_rows;
18975 const GLuint n_req_components_goten = type_goten.m_n_rows;
18976
18977 /* Skip pairs that cannot fit into one location */
18978 if (n_components_per_location < (n_req_components_gohan + n_req_components_goten))
18979 {
18980 continue;
18981 }
18982
18983 const GLuint gohan = 0;
18984 const GLuint goten = gohan + n_req_components_gohan;
18985
18986 const GLchar* fs_int_gohan = is_flat_req_gohan ? "flat" : "";
18987 const GLchar* fs_int_goten = is_flat_req_goten ? "flat" : "";
18988
18989 testCase test_case_tcs_np = { gohan, goten, NONE, PATCH, "", "", false, Utils::Shader::TESS_CTRL,
18990 type_gohan, type_goten };
18991
18992 testCase test_case_tcs_pn = { gohan, goten, PATCH, NONE, "", "", false, Utils::Shader::TESS_CTRL,
18993 type_gohan, type_goten };
18994
18995 testCase test_case_tes_np = { gohan, goten, NONE, PATCH, "", "", true, Utils::Shader::TESS_EVAL,
18996 type_gohan, type_goten };
18997
18998 testCase test_case_tes_pn = { gohan, goten, PATCH, NONE, "", "", true, Utils::Shader::TESS_EVAL,
18999 type_gohan, type_goten };
19000
19001 testCase test_case_fs_nc = { gohan, goten, NONE, CENTROID,
19002 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19003 type_gohan, type_goten };
19004
19005 testCase test_case_fs_cn = { gohan, goten, CENTROID, NONE,
19006 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19007 type_gohan, type_goten };
19008
19009 testCase test_case_fs_ns = { gohan, goten, NONE, SAMPLE,
19010 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19011 type_gohan, type_goten };
19012
19013 testCase test_case_fs_sn = { gohan, goten, SAMPLE, NONE,
19014 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19015 type_gohan, type_goten };
19016
19017 testCase test_case_fs_cs = { gohan, goten, CENTROID, SAMPLE,
19018 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19019 type_gohan, type_goten };
19020
19021 testCase test_case_fs_sc = { gohan, goten, SAMPLE, CENTROID,
19022 fs_int_gohan, fs_int_goten, true, Utils::Shader::FRAGMENT,
19023 type_gohan, type_goten };
19024
19025 m_test_cases.push_back(test_case_tcs_np);
19026 m_test_cases.push_back(test_case_tcs_pn);
19027 m_test_cases.push_back(test_case_tes_np);
19028 m_test_cases.push_back(test_case_tes_pn);
19029 m_test_cases.push_back(test_case_fs_nc);
19030 m_test_cases.push_back(test_case_fs_cn);
19031 m_test_cases.push_back(test_case_fs_ns);
19032 m_test_cases.push_back(test_case_fs_sn);
19033 m_test_cases.push_back(test_case_fs_cs);
19034 m_test_cases.push_back(test_case_fs_sc);
19035 }
19036 }
19037 }
19038
19039 /** Get auxiliary storage qualifier
19040 *
19041 * @param aux Enumeration
19042 *
19043 * @return GLSL qualifier
19044 **/
19045 const GLchar* VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getAuxiliaryQualifier(AUXILIARIES aux)
19046 {
19047 const GLchar* result = 0;
19048
19049 switch (aux)
19050 {
19051 case NONE:
19052 result = "";
19053 break;
19054 case PATCH:
19055 result = "patch";
19056 break;
19057 case CENTROID:
19058 result = "centroid";
19059 break;
19060 case SAMPLE:
19061 result = "sample";
19062 break;
19063 default:
19064 TCU_FAIL("Invalid enum");
19065 }
19066
19067 return result;
19068 }
19069
19070 /** Check if given type is float
19071 *
19072 * @param type Type in question
19073 *
19074 * @return true if tpye is float, false otherwise
19075 **/
19076 bool VaryingLocationAliasingWithMixedAuxiliaryStorageTest::isFloatType(const Utils::Type& type)
19077 {
19078 bool is_float = false;
19079
19080 if ((Utils::Type::Double == type.m_basic_type) || (Utils::Type::Float == type.m_basic_type))
19081 {
19082 is_float = true;
19083 }
19084
19085 return is_float;
19086 }
19087
19088 /* Constants used by VertexAttribLocationAPITest */
19089 const GLuint VertexAttribLocationAPITest::m_goten_location = 6;
19090
19091 /** Constructor
19092 *
19093 * @param context Test framework context
19094 **/
19095 VertexAttribLocationAPITest::VertexAttribLocationAPITest(deqp::Context& context)
19096 : TextureTestBase(context, "vertex_attrib_location_api",
19097 "Test verifies that attribute locations API works as expected")
19098 {
19099 }
19100
19101 /** Does BindAttribLocation for "goten" and relink program
19102 *
19103 * @param program Program object
19104 * @param program_interface Interface of program
19105 **/
19106 void VertexAttribLocationAPITest::prepareAttribLocation(Utils::Program& program,
19107 Utils::ProgramInterface& program_interface)
19108 {
19109 const Functions& gl = m_context.getRenderContext().getFunctions();
19110
19111 gl.bindAttribLocation(program.m_id, m_goten_location, "goten");
19112 GLU_EXPECT_NO_ERROR(gl.getError(), "BindAttribLocation");
19113
19114 program.Link(gl, program.m_id);
19115
19116 /* We still need to get locations for gohan and chichi */
19117 TextureTestBase::prepareAttribLocation(program, program_interface);
19118 }
19119
19120 /** Get interface of program
19121 *
19122 * @param ignored
19123 * @param program_interface Interface of program
19124 * @param ignored
19125 **/
19126 void VertexAttribLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19127 Utils::ProgramInterface& program_interface,
19128 Utils::VaryingPassthrough& /* varying_passthrough */)
19129 {
19130 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
19131 const Utils::Type& type = Utils::Type::vec4;
19132 const GLuint type_size = type.GetSize();
19133
19134 /* Offsets */
19135 const GLuint chichi_offset = 0;
19136 const GLuint goten_offset = chichi_offset + type_size;
19137 const GLuint gohan_offset = goten_offset + type_size;
19138 const GLuint goku_offset = gohan_offset + type_size;
19139
19140 /* Locations */
19141 const GLuint goku_location = 2;
19142 const GLuint goten_location = m_goten_location;
19143
19144 /* Generate data */
19145 m_goku_data = type.GenerateDataPacked();
19146 m_gohan_data = type.GenerateDataPacked();
19147 m_goten_data = type.GenerateDataPacked();
19148 m_chichi_data = type.GenerateDataPacked();
19149
19150 /* Globals */
19151 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19152
19153 /* Attributes */
19154 si.Input("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19155 goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19156 0u /* n_array_elements */, 0u /* stride */, goku_offset /* offset */, (GLvoid*)&m_goku_data[0] /* data */,
19157 m_goku_data.size() /* data_size */);
19158
19159 si.Input("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19160 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19161 0u /* n_array_elements */, 0u /* stride */, gohan_offset /* offset */,
19162 (GLvoid*)&m_gohan_data[0] /* data */, m_gohan_data.size() /* data_size */);
19163
19164 si.Input("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19165 goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19166 0u /* n_array_elements */, 0u /* stride */, goten_offset /* offset */,
19167 (GLvoid*)&m_goten_data[0] /* data */, m_goten_data.size() /* data_size */);
19168
19169 si.Input("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19170 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19171 0u /* n_array_elements */, 0u /* stride */, chichi_offset /* offset */,
19172 (GLvoid*)&m_chichi_data[0] /* data */, m_chichi_data.size() /* data_size */);
19173 }
19174
19175 /** Selects if "compute" stage is relevant for test
19176 *
19177 * @param ignored
19178 *
19179 * @return false
19180 **/
19181 bool VertexAttribLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19182 {
19183 return false;
19184 }
19185
19186 /* Constants used by FragmentDataLocationAPITest */
19187 const GLuint FragmentDataLocationAPITest::m_goten_location = 6;
19188
19189 /** Constructor
19190 *
19191 * @param context Test framework context
19192 **/
19193 FragmentDataLocationAPITest::FragmentDataLocationAPITest(deqp::Context& context)
19194 : TextureTestBase(context, "fragment_data_location_api",
19195 "Test verifies that fragment data locations API works as expected")
19196 , m_goku(context)
19197 , m_gohan(context)
19198 , m_goten(context)
19199 , m_chichi(context)
19200 {
19201 }
19202
19203 /** Verifies contents of drawn images
19204 *
19205 * @param ignored
19206 * @param ignored
19207 *
19208 * @return true if images are filled with expected values, false otherwise
19209 **/
19210 bool FragmentDataLocationAPITest::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& /* color_0 */)
19211 {
19212 static const GLuint size = m_width * m_height;
19213 static const GLuint expected_goku = 0xff000000;
19214 static const GLuint expected_gohan = 0xff0000ff;
19215 static const GLuint expected_goten = 0xff00ff00;
19216 static const GLuint expected_chichi = 0xffff0000;
19217
19218 std::vector<GLuint> data;
19219 data.resize(size);
19220
19221 m_goku.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19222
19223 for (GLuint i = 0; i < size; ++i)
19224 {
19225 const GLuint color = data[i];
19226
19227 if (expected_goku != color)
19228 {
19229 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19230 << tcu::TestLog::EndMessage;
19231 return false;
19232 }
19233 }
19234
19235 m_gohan.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19236
19237 for (GLuint i = 0; i < size; ++i)
19238 {
19239 const GLuint color = data[i];
19240
19241 if (expected_gohan != color)
19242 {
19243 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19244 << tcu::TestLog::EndMessage;
19245 return false;
19246 }
19247 }
19248
19249 m_goten.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19250
19251 for (GLuint i = 0; i < size; ++i)
19252 {
19253 const GLuint color = data[i];
19254
19255 if (expected_goten != color)
19256 {
19257 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19258 << tcu::TestLog::EndMessage;
19259 return false;
19260 }
19261 }
19262
19263 m_chichi.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19264
19265 for (GLuint i = 0; i < size; ++i)
19266 {
19267 const GLuint color = data[i];
19268
19269 if (expected_chichi != color)
19270 {
19271 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19272 << tcu::TestLog::EndMessage;
19273 return false;
19274 }
19275 }
19276
19277 return true;
19278 }
19279
19280 /** Prepare code snippet that will set out variables
19281 *
19282 * @param ignored
19283 * @param ignored
19284 * @param stage Shader stage
19285 *
19286 * @return Code that pass in variables to next stage
19287 **/
19288 std::string FragmentDataLocationAPITest::getPassSnippet(GLuint /* test_case_index */,
19289 Utils::VaryingPassthrough& /* varying_passthrough */,
19290 Utils::Shader::STAGES stage)
19291 {
19292 std::string result;
19293
19294 /* Skip for compute shader */
19295 if (Utils::Shader::FRAGMENT != stage)
19296 {
19297 result = "";
19298 }
19299 else
19300 {
19301 result = "chichi = vec4(0, 0, 1, 1);\n"
19302 " goku = vec4(0, 0, 0, 1);\n"
19303 " goten = vec4(0, 1, 0, 1);\n"
19304 " gohan = vec4(1, 0, 0, 1);\n";
19305 }
19306
19307 return result;
19308 }
19309
19310 /** Get interface of program
19311 *
19312 * @param ignored
19313 * @param program_interface Interface of program
19314 * @param ignored
19315 **/
19316 void FragmentDataLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19317 Utils::ProgramInterface& program_interface,
19318 Utils::VaryingPassthrough& /* varying_passthrough */)
19319 {
19320 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19321 const Utils::Type& type = Utils::Type::vec4;
19322
19323 /* Locations */
19324 m_goku_location = 2;
19325
19326 /* Globals */
19327 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19328
19329 /* Attributes */
19330 si.Output("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19331 m_goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19332 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19333
19334 si.Output("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19335 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19336 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19337
19338 si.Output("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19339 m_goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19340 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19341
19342 si.Output("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19343 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19344 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19345 }
19346
19347 /** Selects if "compute" stage is relevant for test
19348 *
19349 * @param ignored
19350 *
19351 * @return false
19352 **/
19353 bool FragmentDataLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19354 {
19355 return false;
19356 }
19357
19358 /** Get locations for all outputs with automatic_location
19359 *
19360 * @param program Program object
19361 * @param program_interface Interface of program
19362 **/
19363 void FragmentDataLocationAPITest::prepareFragmentDataLoc(Utils::Program& program,
19364 Utils::ProgramInterface& program_interface)
19365 {
19366 /* Bind location of goten */
19367 const Functions& gl = m_context.getRenderContext().getFunctions();
19368
19369 gl.bindFragDataLocation(program.m_id, m_goten_location, "goten");
19370 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFragDataLocation");
19371
19372 program.Link(gl, program.m_id);
19373
19374 /* Prepare locations for gohan and chichi */
19375 TextureTestBase::prepareFragmentDataLoc(program, program_interface);
19376
19377 /* Get all locations */
19378 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19379
19380 Utils::Variable::PtrVector& outputs = si.m_outputs;
19381
19382 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
19383 {
19384 const Utils::Variable::Descriptor& desc = (*it)->m_descriptor;
19385
19386 if (0 == desc.m_name.compare("gohan"))
19387 {
19388 m_gohan_location = desc.m_expected_location;
19389 }
19390 else if (0 == desc.m_name.compare("chichi"))
19391 {
19392 m_chichi_location = desc.m_expected_location;
19393 }
19394
19395 /* Locations of goku and goten are fixed */
19396 }
19397 }
19398
19399 /** Prepare framebuffer with single texture as color attachment
19400 *
19401 * @param framebuffer Framebuffer
19402 * @param color_0_texture Texture that will used as color attachment
19403 **/
19404 void FragmentDataLocationAPITest::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
19405 {
19406 /* Let parent prepare its stuff */
19407 TextureTestBase::prepareFramebuffer(framebuffer, color_0_texture);
19408
19409 /* Prepare data */
19410 std::vector<GLuint> texture_data;
19411 texture_data.resize(m_width * m_height);
19412
19413 for (GLuint i = 0; i < texture_data.size(); ++i)
19414 {
19415 texture_data[i] = 0x20406080;
19416 }
19417
19418 /* Prepare textures */
19419 m_goku.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
19420
19421 m_gohan.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
19422
19423 m_goten.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
19424
19425 m_chichi.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
19426
19427 /* Attach textures to framebuffer */
19428 framebuffer.Bind();
19429 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goku_location, m_goku.m_id, m_width, m_height);
19430 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_gohan_location, m_gohan.m_id, m_width, m_height);
19431 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goten_location, m_goten.m_id, m_width, m_height);
19432 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_chichi_location, m_chichi.m_id, m_width, m_height);
19433
19434 /* Set up drawbuffers */
19435 const Functions& gl = m_context.getRenderContext().getFunctions();
19436 // The fragment shader can have more than 4 color outputs, but it only care about 4 (goku, gohan, goten, chichi).
19437 // We will first initialize all draw buffers to NONE and then set the real value for the 4 outputs we care about
19438 GLint maxDrawBuffers = 0;
19439 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
19440
19441 std::vector<GLenum> buffers(maxDrawBuffers, GL_NONE);
19442 buffers[m_chichi_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_chichi_location);
19443 buffers[m_goten_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goten_location);
19444 buffers[m_goku_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goku_location);
19445 buffers[m_gohan_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_gohan_location);
19446
19447 gl.drawBuffers(maxDrawBuffers, buffers.data());
19448 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers");
19449 }
19450
19451 /** Constructor
19452 *
19453 * @param context Test framework context
19454 **/
19455 XFBInputTest::XFBInputTest(deqp::Context& context)
19456 : NegativeTestBase(context, "xfb_input",
19457 "Test verifies that compiler reports error when xfb qualifiers are used with input")
19458 {
19459 }
19460
19461 /** Source for given test case and stage
19462 *
19463 * @param test_case_index Index of test case
19464 * @param stage Shader stage
19465 *
19466 * @return Shader source
19467 **/
19468 std::string XFBInputTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
19469 {
19470 static const GLchar* buffer_var_definition = "layout (xfb_buffer = 2) in vec4 gohanARRAY;\n";
19471 static const GLchar* offset_var_definition = "layout (xfb_offset = 16) in vec4 gohanARRAY;\n";
19472 static const GLchar* stride_var_definition = "layout (xfb_stride = 32) in vec4 gohanARRAY;\n";
19473 static const GLchar* input_use = " result += gohanINDEX;\n";
19474 static const GLchar* fs = "#version 430 core\n"
19475 "#extension GL_ARB_enhanced_layouts : require\n"
19476 "\n"
19477 "in vec4 gs_fs;\n"
19478 "out vec4 fs_out;\n"
19479 "\n"
19480 "void main()\n"
19481 "{\n"
19482 " fs_out = gs_fs;\n"
19483 "}\n"
19484 "\n";
19485 static const GLchar* fs_tested = "#version 430 core\n"
19486 "#extension GL_ARB_enhanced_layouts : require\n"
19487 "\n"
19488 "VAR_DEFINITION"
19489 "\n"
19490 "in vec4 gs_fs;\n"
19491 "out vec4 fs_out;\n"
19492 "\n"
19493 "void main()\n"
19494 "{\n"
19495 " vec4 result = gs_fs;\n"
19496 "\n"
19497 "VARIABLE_USE"
19498 "\n"
19499 " fs_out = result;\n"
19500 "}\n"
19501 "\n";
19502 static const GLchar* gs = "#version 430 core\n"
19503 "#extension GL_ARB_enhanced_layouts : require\n"
19504 "\n"
19505 "layout(points) in;\n"
19506 "layout(triangle_strip, max_vertices = 4) out;\n"
19507 "\n"
19508 "in vec4 tes_gs[];\n"
19509 "out vec4 gs_fs;\n"
19510 "\n"
19511 "void main()\n"
19512 "{\n"
19513 " gs_fs = tes_gs[0];\n"
19514 " gl_Position = vec4(-1, -1, 0, 1);\n"
19515 " EmitVertex();\n"
19516 " gs_fs = tes_gs[0];\n"
19517 " gl_Position = vec4(-1, 1, 0, 1);\n"
19518 " EmitVertex();\n"
19519 " gs_fs = tes_gs[0];\n"
19520 " gl_Position = vec4(1, -1, 0, 1);\n"
19521 " EmitVertex();\n"
19522 " gs_fs = tes_gs[0];\n"
19523 " gl_Position = vec4(1, 1, 0, 1);\n"
19524 " EmitVertex();\n"
19525 "}\n"
19526 "\n";
19527 static const GLchar* gs_tested = "#version 430 core\n"
19528 "#extension GL_ARB_enhanced_layouts : require\n"
19529 "\n"
19530 "layout(points) in;\n"
19531 "layout(triangle_strip, max_vertices = 4) out;\n"
19532 "\n"
19533 "VAR_DEFINITION"
19534 "\n"
19535 "in vec4 tes_gs[];\n"
19536 "out vec4 gs_fs;\n"
19537 "\n"
19538 "void main()\n"
19539 "{\n"
19540 " vec4 result = tes_gs[0];\n"
19541 "\n"
19542 "VARIABLE_USE"
19543 "\n"
19544 " gs_fs = result;\n"
19545 " gl_Position = vec4(-1, -1, 0, 1);\n"
19546 " EmitVertex();\n"
19547 " gs_fs = result;\n"
19548 " gl_Position = vec4(-1, 1, 0, 1);\n"
19549 " EmitVertex();\n"
19550 " gs_fs = result;\n"
19551 " gl_Position = vec4(1, -1, 0, 1);\n"
19552 " EmitVertex();\n"
19553 " gs_fs = result;\n"
19554 " gl_Position = vec4(1, 1, 0, 1);\n"
19555 " EmitVertex();\n"
19556 "}\n"
19557 "\n";
19558 static const GLchar* tcs = "#version 430 core\n"
19559 "#extension GL_ARB_enhanced_layouts : require\n"
19560 "\n"
19561 "layout(vertices = 1) out;\n"
19562 "\n"
19563 "in vec4 vs_tcs[];\n"
19564 "out vec4 tcs_tes[];\n"
19565 "\n"
19566 "void main()\n"
19567 "{\n"
19568 "\n"
19569 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
19570 "\n"
19571 " gl_TessLevelOuter[0] = 1.0;\n"
19572 " gl_TessLevelOuter[1] = 1.0;\n"
19573 " gl_TessLevelOuter[2] = 1.0;\n"
19574 " gl_TessLevelOuter[3] = 1.0;\n"
19575 " gl_TessLevelInner[0] = 1.0;\n"
19576 " gl_TessLevelInner[1] = 1.0;\n"
19577 "}\n"
19578 "\n";
19579 static const GLchar* tcs_tested = "#version 430 core\n"
19580 "#extension GL_ARB_enhanced_layouts : require\n"
19581 "\n"
19582 "layout(vertices = 1) out;\n"
19583 "\n"
19584 "VAR_DEFINITION"
19585 "\n"
19586 "in vec4 vs_tcs[];\n"
19587 "out vec4 tcs_tes[];\n"
19588 "\n"
19589 "void main()\n"
19590 "{\n"
19591 " vec4 result = vs_tcs[gl_InvocationID];\n"
19592 "\n"
19593 "VARIABLE_USE"
19594 "\n"
19595 " tcs_tes[gl_InvocationID] = result;\n"
19596 "\n"
19597 " gl_TessLevelOuter[0] = 1.0;\n"
19598 " gl_TessLevelOuter[1] = 1.0;\n"
19599 " gl_TessLevelOuter[2] = 1.0;\n"
19600 " gl_TessLevelOuter[3] = 1.0;\n"
19601 " gl_TessLevelInner[0] = 1.0;\n"
19602 " gl_TessLevelInner[1] = 1.0;\n"
19603 "}\n"
19604 "\n";
19605 static const GLchar* tes = "#version 430 core\n"
19606 "#extension GL_ARB_enhanced_layouts : require\n"
19607 "\n"
19608 "layout(isolines, point_mode) in;\n"
19609 "\n"
19610 "in vec4 tcs_tes[];\n"
19611 "out vec4 tes_gs;\n"
19612 "\n"
19613 "void main()\n"
19614 "{\n"
19615 " tes_gs = tcs_tes[0];\n"
19616 "}\n"
19617 "\n";
19618 static const GLchar* tes_tested = "#version 430 core\n"
19619 "#extension GL_ARB_enhanced_layouts : require\n"
19620 "\n"
19621 "layout(isolines, point_mode) in;\n"
19622 "\n"
19623 "VAR_DEFINITION"
19624 "\n"
19625 "in vec4 tcs_tes[];\n"
19626 "out vec4 tes_gs;\n"
19627 "\n"
19628 "void main()\n"
19629 "{\n"
19630 " vec4 result = tcs_tes[0];\n"
19631 "\n"
19632 "VARIABLE_USE"
19633 "\n"
19634 " tes_gs += result;\n"
19635 "}\n"
19636 "\n";
19637 static const GLchar* vs = "#version 430 core\n"
19638 "#extension GL_ARB_enhanced_layouts : require\n"
19639 "\n"
19640 "in vec4 in_vs;\n"
19641 "out vec4 vs_tcs;\n"
19642 "\n"
19643 "void main()\n"
19644 "{\n"
19645 " vs_tcs = in_vs;\n"
19646 "}\n"
19647 "\n";
19648 static const GLchar* vs_tested = "#version 430 core\n"
19649 "#extension GL_ARB_enhanced_layouts : require\n"
19650 "\n"
19651 "VAR_DEFINITION"
19652 "\n"
19653 "in vec4 in_vs;\n"
19654 "out vec4 vs_tcs;\n"
19655 "\n"
19656 "void main()\n"
19657 "{\n"
19658 " vec4 result = in_vs;\n"
19659 "\n"
19660 "VARIABLE_USE"
19661 "\n"
19662 " vs_tcs += result;\n"
19663 "}\n"
19664 "\n";
19665
19666 std::string source;
19667 testCase& test_case = m_test_cases[test_case_index];
19668
19669 if (test_case.m_stage == stage)
19670 {
19671 const GLchar* array = "";
19672 const GLchar* index = "";
19673 size_t position = 0;
19674 size_t temp;
19675 const GLchar* var_definition = 0;
19676 const GLchar* var_use = input_use;
19677
19678 switch (test_case.m_qualifier)
19679 {
19680 case BUFFER:
19681 var_definition = buffer_var_definition;
19682 break;
19683 case OFFSET:
19684 var_definition = offset_var_definition;
19685 break;
19686 case STRIDE:
19687 var_definition = stride_var_definition;
19688 break;
19689 default:
19690 TCU_FAIL("Invalid enum");
19691 }
19692
19693 switch (stage)
19694 {
19695 case Utils::Shader::FRAGMENT:
19696 source = fs_tested;
19697 break;
19698 case Utils::Shader::GEOMETRY:
19699 source = gs_tested;
19700 array = "[]";
19701 index = "[0]";
19702 break;
19703 case Utils::Shader::TESS_CTRL:
19704 source = tcs_tested;
19705 array = "[]";
19706 index = "[gl_InvocationID]";
19707 break;
19708 case Utils::Shader::TESS_EVAL:
19709 source = tes_tested;
19710 array = "[]";
19711 index = "[0]";
19712 break;
19713 case Utils::Shader::VERTEX:
19714 source = vs_tested;
19715 break;
19716 default:
19717 TCU_FAIL("Invalid enum");
19718 }
19719
19720 temp = position;
19721 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
19722 position = temp;
19723 Utils::replaceToken("ARRAY", position, array, source);
19724 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
19725
19726 Utils::replaceAllTokens("INDEX", index, source);
19727 }
19728 else
19729 {
19730 switch (stage)
19731 {
19732 case Utils::Shader::FRAGMENT:
19733 source = fs;
19734 break;
19735 case Utils::Shader::GEOMETRY:
19736 source = gs;
19737 break;
19738 case Utils::Shader::TESS_CTRL:
19739 source = tcs;
19740 break;
19741 case Utils::Shader::TESS_EVAL:
19742 source = tes;
19743 break;
19744 case Utils::Shader::VERTEX:
19745 source = vs;
19746 break;
19747 default:
19748 TCU_FAIL("Invalid enum");
19749 }
19750 }
19751
19752 return source;
19753 }
19754
19755 /** Get description of test case
19756 *
19757 * @param test_case_index Index of test case
19758 *
19759 * @return Test case description
19760 **/
19761 std::string XFBInputTest::getTestCaseName(GLuint test_case_index)
19762 {
19763 std::stringstream stream;
19764 testCase& test_case = m_test_cases[test_case_index];
19765
19766 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", qualifier: ";
19767
19768 switch (test_case.m_qualifier)
19769 {
19770 case BUFFER:
19771 stream << "xfb_buffer";
19772 break;
19773 case OFFSET:
19774 stream << "xfb_offset";
19775 break;
19776 case STRIDE:
19777 stream << "xfb_stride";
19778 break;
19779 default:
19780 TCU_FAIL("Invalid enum");
19781 }
19782
19783 return stream.str();
19784 }
19785
19786 /** Get number of test cases
19787 *
19788 * @return Number of test cases
19789 **/
19790 GLuint XFBInputTest::getTestCaseNumber()
19791 {
19792 return static_cast<GLuint>(m_test_cases.size());
19793 }
19794
19795 /** Selects if "compute" stage is relevant for test
19796 *
19797 * @param ignored
19798 *
19799 * @return false
19800 **/
19801 bool XFBInputTest::isComputeRelevant(GLuint /* test_case_index */)
19802 {
19803 return false;
19804 }
19805
19806 /** Prepare all test cases
19807 *
19808 **/
19809 void XFBInputTest::testInit()
19810 {
19811 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
19812 {
19813 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
19814 {
19815 if (Utils::Shader::COMPUTE == stage)
19816 {
19817 continue;
19818 }
19819
19820 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
19821
19822 m_test_cases.push_back(test_case);
19823 }
19824 }
19825 }
19826
19827 /* Constants used by XFBAllStagesTest */
19828 const GLuint XFBAllStagesTest::m_gs_index = 3;
19829
19830 /** Constructor
19831 *
19832 * @param context Test context
19833 **/
19834 XFBAllStagesTest::XFBAllStagesTest(deqp::Context& context)
19835 : BufferTestBase(context, "xfb_all_stages",
19836 "Test verifies that only last stage in vertex processing can output to transform feedback")
19837 {
19838 /* Nothing to be done here */
19839 }
19840
19841 /** Get descriptors of buffers necessary for test
19842 *
19843 * @param ignored
19844 * @param out_descriptors Descriptors of buffers used by test
19845 **/
19846 void XFBAllStagesTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
19847 bufferDescriptor::Vector& out_descriptors)
19848 {
19849 static const GLuint n_stages = 4;
19850 const Utils::Type& vec4 = Utils::Type::vec4;
19851
19852 /* Data */
19853 tcu::Vec4 sum;
19854
19855 /* Test uses single uniform and xfb per stage + uniform for fragment shader */
19856 out_descriptors.resize(n_stages * 2 + 1);
19857
19858 /* */
19859 for (GLuint i = 0; i < n_stages; ++i)
19860 {
19861 /* Get references */
19862 bufferDescriptor& uniform = out_descriptors[i + 0];
19863 bufferDescriptor& xfb = out_descriptors[i + n_stages];
19864
19865 /* Index */
19866 uniform.m_index = i;
19867 xfb.m_index = i;
19868
19869 /* Target */
19870 uniform.m_target = Utils::Buffer::Uniform;
19871 xfb.m_target = Utils::Buffer::Transform_feedback;
19872
19873 /* Data */
19874 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
19875
19876 sum += var;
19877
19878 uniform.m_initial_data.resize(vec4.GetSize());
19879 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
19880
19881 xfb.m_initial_data = vec4.GenerateDataPacked();
19882
19883 if (m_gs_index != i)
19884 {
19885 xfb.m_expected_data = xfb.m_initial_data;
19886 }
19887 else
19888 {
19889 xfb.m_expected_data.resize(vec4.GetSize());
19890 memcpy(&xfb.m_expected_data[0], sum.getPtr(), vec4.GetSize());
19891 }
19892 }
19893
19894 /* FS */
19895 {
19896 /* Get reference */
19897 bufferDescriptor& uniform = out_descriptors[n_stages * 2];
19898
19899 /* Index */
19900 uniform.m_index = n_stages;
19901
19902 /* Target */
19903 uniform.m_target = Utils::Buffer::Uniform;
19904
19905 /* Data */
19906 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
19907
19908 uniform.m_initial_data.resize(vec4.GetSize());
19909 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
19910 }
19911 }
19912
19913 /** Get body of main function for given shader stage
19914 *
19915 * @param ignored
19916 * @param stage Shader stage
19917 * @param out_assignments Set to empty
19918 * @param out_calculations Set to empty
19919 **/
19920 void XFBAllStagesTest::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
19921 std::string& out_assignments, std::string& out_calculations)
19922 {
19923 out_calculations = "";
19924
19925 static const GLchar* vs = " vs_tcs = uni_vs;\n";
19926 static const GLchar* tcs = " tcs_tes[gl_InvocationID] = uni_tcs + vs_tcs[gl_InvocationID];\n";
19927 static const GLchar* tes = " tes_gs = uni_tes + tcs_tes[0];\n";
19928 static const GLchar* gs = " gs_fs = uni_gs + tes_gs[0];\n";
19929 static const GLchar* fs = " fs_out = uni_fs + gs_fs;\n";
19930
19931 const GLchar* assignments = 0;
19932 switch (stage)
19933 {
19934 case Utils::Shader::FRAGMENT:
19935 assignments = fs;
19936 break;
19937 case Utils::Shader::GEOMETRY:
19938 assignments = gs;
19939 break;
19940 case Utils::Shader::TESS_CTRL:
19941 assignments = tcs;
19942 break;
19943 case Utils::Shader::TESS_EVAL:
19944 assignments = tes;
19945 break;
19946 case Utils::Shader::VERTEX:
19947 assignments = vs;
19948 break;
19949 default:
19950 TCU_FAIL("Invalid enum");
19951 }
19952
19953 out_assignments = assignments;
19954 }
19955
19956 /** Get interface of shader
19957 *
19958 * @param ignored
19959 * @param stage Shader stage
19960 * @param out_interface Set to ""
19961 **/
19962 void XFBAllStagesTest::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
19963 std::string& out_interface)
19964 {
19965 static const GLchar* vs = "layout(xfb_buffer = 0, xfb_offset = 0) out vec4 vs_tcs;\n"
19966 "layout(binding = 0) uniform vs_block {\n"
19967 " vec4 uni_vs;\n"
19968 "};\n";
19969 static const GLchar* tcs = " in vec4 vs_tcs[];\n"
19970 "layout(xfb_buffer = 1, xfb_offset = 0) out vec4 tcs_tes[1];\n"
19971 "layout(binding = 1) uniform tcs_block {\n"
19972 " vec4 uni_tcs;\n"
19973 "};\n";
19974 static const GLchar* tes = " in vec4 tcs_tes[];\n"
19975 "layout(xfb_buffer = 2, xfb_offset = 0) out vec4 tes_gs;\n"
19976 "layout(binding = 2) uniform tes_block {\n"
19977 " vec4 uni_tes;\n"
19978 "};\n";
19979 static const GLchar* gs = " in vec4 tes_gs[];\n"
19980 "layout(xfb_buffer = 3, xfb_offset = 0) out vec4 gs_fs;\n"
19981 "layout(binding = 3) uniform gs_block {\n"
19982 " vec4 uni_gs;\n"
19983 "};\n";
19984 static const GLchar* fs = " in vec4 gs_fs;\n"
19985 " out vec4 fs_out;\n"
19986 "layout(binding = 4) uniform fs_block {\n"
19987 " vec4 uni_fs;\n"
19988 "};\n";
19989
19990 const GLchar* interface = 0;
19991 switch (stage)
19992 {
19993 case Utils::Shader::FRAGMENT:
19994 interface = fs;
19995 break;
19996 case Utils::Shader::GEOMETRY:
19997 interface = gs;
19998 break;
19999 case Utils::Shader::TESS_CTRL:
20000 interface = tcs;
20001 break;
20002 case Utils::Shader::TESS_EVAL:
20003 interface = tes;
20004 break;
20005 case Utils::Shader::VERTEX:
20006 interface = vs;
20007 break;
20008 default:
20009 TCU_FAIL("Invalid enum");
20010 }
20011
20012 out_interface = interface;
20013 }
20014
20015 /* Constants used by XFBStrideOfEmptyListTest */
20016 const GLuint XFBStrideOfEmptyListTest::m_stride = 64;
20017
20018 /** Constructor
20019 *
20020 * @param context Test context
20021 **/
20022 XFBStrideOfEmptyListTest::XFBStrideOfEmptyListTest(deqp::Context& context)
20023 : BufferTestBase(
20024 context, "xfb_stride_of_empty_list",
20025 "Test verifies correct behavior when xfb_stride qualifier is specified but no xfb_offset is specified")
20026 {
20027 /* Nothing to be done here */
20028 }
20029
20030 /** Execute drawArrays for single vertex
20031 *
20032 * @param test_case_index Index of test case
20033 *
20034 * @return true if proper error is reported
20035 **/
20036 bool XFBStrideOfEmptyListTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20037 {
20038 const Functions& gl = m_context.getRenderContext().getFunctions();
20039 bool result = true;
20040
20041 /* Draw */
20042 gl.disable(GL_RASTERIZER_DISCARD);
20043 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20044
20045 gl.beginTransformFeedback(GL_POINTS);
20046 GLenum error = gl.getError();
20047 switch (test_case_index)
20048 {
20049 case VALID:
20050 if (GL_NO_ERROR != error)
20051 {
20052 gl.endTransformFeedback();
20053 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20054 }
20055
20056 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20057 error = gl.getError();
20058
20059 gl.endTransformFeedback();
20060 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20061 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20062
20063 break;
20064
20065 case FIRST_MISSING:
20066 if (GL_NO_ERROR == error)
20067 {
20068 gl.endTransformFeedback();
20069 }
20070
20071 if (GL_INVALID_OPERATION != error)
20072 {
20073 m_context.getTestContext().getLog()
20074 << tcu::TestLog::Message << "XFB at index 0, that is written by GS, is missing. It was expected that "
20075 "INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20076 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20077
20078 result = false;
20079 }
20080
20081 break;
20082
20083 case SECOND_MISSING:
20084 if (GL_NO_ERROR != error)
20085 {
20086 gl.endTransformFeedback();
20087 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20088 }
20089
20090 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20091 error = gl.getError();
20092
20093 gl.endTransformFeedback();
20094 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20095 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20096
20097 break;
20098 }
20099
20100 /* Done */
20101 return result;
20102 }
20103
20104 /** Get descriptors of buffers necessary for test
20105 *
20106 * @param test_case_index Index of test case
20107 * @param out_descriptors Descriptors of buffers used by test
20108 **/
20109 void XFBStrideOfEmptyListTest::getBufferDescriptors(glw::GLuint test_case_index,
20110 bufferDescriptor::Vector& out_descriptors)
20111 {
20112 switch (test_case_index)
20113 {
20114 case VALID:
20115 {
20116 /* Test needs single uniform and two xfbs */
20117 out_descriptors.resize(3);
20118
20119 /* Get references */
20120 bufferDescriptor& uniform = out_descriptors[0];
20121 bufferDescriptor& xfb_0 = out_descriptors[1];
20122 bufferDescriptor& xfb_1 = out_descriptors[2];
20123
20124 /* Index */
20125 uniform.m_index = 0;
20126 xfb_0.m_index = 0;
20127 xfb_1.m_index = 1;
20128
20129 /* Target */
20130 uniform.m_target = Utils::Buffer::Uniform;
20131 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20132 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20133
20134 /* Data */
20135 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20136
20137 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20138 xfb_0.m_expected_data = uniform.m_initial_data;
20139
20140 /* Data, contents are the same as no modification is expected */
20141 xfb_1.m_initial_data.resize(m_stride);
20142 xfb_1.m_expected_data.resize(m_stride);
20143
20144 for (GLuint i = 0; i < m_stride; ++i)
20145 {
20146 xfb_1.m_initial_data[0] = (glw::GLubyte)i;
20147 xfb_1.m_expected_data[0] = (glw::GLubyte)i;
20148 }
20149 }
20150
20151 break;
20152
20153 case FIRST_MISSING:
20154 {
20155 /* Test needs single uniform and two xfbs */
20156 out_descriptors.resize(2);
20157
20158 /* Get references */
20159 bufferDescriptor& uniform = out_descriptors[0];
20160 bufferDescriptor& xfb_1 = out_descriptors[1];
20161
20162 /* Index */
20163 uniform.m_index = 0;
20164 xfb_1.m_index = 1;
20165
20166 /* Target */
20167 uniform.m_target = Utils::Buffer::Uniform;
20168 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20169
20170 /* Data */
20171 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20172
20173 /* Draw call will not be executed, contents does not matter */
20174 xfb_1.m_initial_data.resize(m_stride);
20175 }
20176
20177 break;
20178
20179 case SECOND_MISSING:
20180 {
20181 /* Test needs single uniform and two xfbs */
20182 out_descriptors.resize(2);
20183
20184 /* Get references */
20185 bufferDescriptor& uniform = out_descriptors[0];
20186 bufferDescriptor& xfb_0 = out_descriptors[1];
20187
20188 /* Index */
20189 uniform.m_index = 0;
20190 xfb_0.m_index = 0;
20191
20192 /* Target */
20193 uniform.m_target = Utils::Buffer::Uniform;
20194 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20195
20196 /* Data */
20197 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20198
20199 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20200 xfb_0.m_expected_data = uniform.m_initial_data;
20201 }
20202
20203 break;
20204 }
20205 }
20206
20207 /** Get body of main function for given shader stage
20208 *
20209 * @param ignored
20210 * @param stage Shader stage
20211 * @param out_assignments Set to empty
20212 * @param out_calculations Set to empty
20213 **/
20214 void XFBStrideOfEmptyListTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20215 std::string& out_assignments, std::string& out_calculations)
20216 {
20217 out_calculations = "";
20218
20219 static const GLchar* gs = " gs_fs = uni_gs;\n";
20220 static const GLchar* fs = " fs_out = vec4(gs_fs);\n";
20221
20222 const GLchar* assignments = "";
20223 switch (stage)
20224 {
20225 case Utils::Shader::FRAGMENT:
20226 assignments = fs;
20227 break;
20228 case Utils::Shader::GEOMETRY:
20229 assignments = gs;
20230 break;
20231 default:
20232 break;
20233 }
20234
20235 out_assignments = assignments;
20236 }
20237
20238 /** Get interface of shader
20239 *
20240 * @param ignored
20241 * @param stage Shader stage
20242 * @param out_interface Set to ""
20243 **/
20244 void XFBStrideOfEmptyListTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20245 std::string& out_interface)
20246 {
20247 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out vec4 gs_fs;\n"
20248 "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
20249 "\n"
20250 "layout (binding = 0) uniform gs_block {\n"
20251 " vec4 uni_gs;\n"
20252 "};\n";
20253 static const GLchar* fs = "in vec4 gs_fs;\n"
20254 "out vec4 fs_out;\n";
20255
20256 switch (stage)
20257 {
20258 case Utils::Shader::FRAGMENT:
20259 out_interface = fs;
20260 break;
20261 case Utils::Shader::GEOMETRY:
20262 out_interface = gs;
20263 break;
20264 default:
20265 out_interface = "";
20266 return;
20267 }
20268 }
20269
20270 /** Returns buffer details in human readable form.
20271 *
20272 * @param test_case_index Index of test case
20273 *
20274 * @return Case description
20275 **/
20276 std::string XFBStrideOfEmptyListTest::getTestCaseName(GLuint test_case_index)
20277 {
20278 std::string result;
20279
20280 switch (test_case_index)
20281 {
20282 case VALID:
20283 result = "Valid case";
20284 break;
20285 case FIRST_MISSING:
20286 result = "Missing xfb at index 0";
20287 break;
20288 case SECOND_MISSING:
20289 result = "Missing xfb at index 1";
20290 break;
20291 default:
20292 TCU_FAIL("Invalid enum");
20293 }
20294
20295 return result;
20296 }
20297
20298 /** Get number of test cases
20299 *
20300 * @return 3
20301 **/
20302 GLuint XFBStrideOfEmptyListTest::getTestCaseNumber()
20303 {
20304 return 3;
20305 }
20306
20307 /* Constants used by XFBStrideOfEmptyListTest */
20308 const GLuint XFBStrideOfEmptyListAndAPITest::m_stride = 64;
20309
20310 /** Constructor
20311 *
20312 * @param context Test context
20313 **/
20314 XFBStrideOfEmptyListAndAPITest::XFBStrideOfEmptyListAndAPITest(deqp::Context& context)
20315 : BufferTestBase(context, "xfb_stride_of_empty_list_and_api",
20316 "Test verifies that xfb_stride qualifier is not overriden by API")
20317 {
20318 /* Nothing to be done here */
20319 }
20320
20321 /** Execute drawArrays for single vertex
20322 *
20323 * @param test_case_index Index of test case
20324 *
20325 * @return true if proper error is reported
20326 **/
20327 bool XFBStrideOfEmptyListAndAPITest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20328 {
20329 const Functions& gl = m_context.getRenderContext().getFunctions();
20330 bool result = true;
20331
20332 /* Draw */
20333 gl.disable(GL_RASTERIZER_DISCARD);
20334 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20335
20336 gl.beginTransformFeedback(GL_POINTS);
20337 GLenum error = gl.getError();
20338 switch (test_case_index)
20339 {
20340 case VALID:
20341 if (GL_NO_ERROR != error)
20342 {
20343 gl.endTransformFeedback();
20344 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20345 }
20346
20347 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20348 error = gl.getError();
20349
20350 gl.endTransformFeedback();
20351 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20352 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20353
20354 break;
20355
20356 case FIRST_MISSING:
20357 if (GL_NO_ERROR != error)
20358 {
20359 gl.endTransformFeedback();
20360 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20361 }
20362
20363 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20364 error = gl.getError();
20365
20366 gl.endTransformFeedback();
20367 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20368 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20369
20370 break;
20371
20372 case SECOND_MISSING:
20373 if (GL_NO_ERROR == error)
20374 {
20375 gl.endTransformFeedback();
20376 }
20377
20378 if (GL_INVALID_OPERATION != error)
20379 {
20380 m_context.getTestContext().getLog()
20381 << tcu::TestLog::Message << "XFB at index 1, that is declared as empty, is missing. It was expected "
20382 "that INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20383 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20384
20385 result = false;
20386 }
20387
20388 break;
20389 }
20390
20391 /* Done */
20392 return result;
20393 }
20394
20395 /** Get descriptors of buffers necessary for test
20396 *
20397 * @param test_case_index Index of test case
20398 * @param out_descriptors Descriptors of buffers used by test
20399 **/
20400 void XFBStrideOfEmptyListAndAPITest::getBufferDescriptors(glw::GLuint test_case_index,
20401 bufferDescriptor::Vector& out_descriptors)
20402 {
20403 switch (test_case_index)
20404 {
20405 case VALID:
20406 {
20407 /* Test needs single uniform and two xfbs */
20408 out_descriptors.resize(3);
20409
20410 /* Get references */
20411 bufferDescriptor& uniform = out_descriptors[0];
20412 bufferDescriptor& xfb_0 = out_descriptors[1];
20413 bufferDescriptor& xfb_1 = out_descriptors[2];
20414
20415 /* Index */
20416 uniform.m_index = 0;
20417 xfb_0.m_index = 0;
20418 xfb_1.m_index = 1;
20419
20420 /* Target */
20421 uniform.m_target = Utils::Buffer::Uniform;
20422 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20423 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20424
20425 /* Data */
20426 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20427
20428 /* Data, contents are the same as no modification is expected */
20429 xfb_0.m_initial_data.resize(m_stride);
20430 xfb_0.m_expected_data.resize(m_stride);
20431
20432 for (GLuint i = 0; i < m_stride; ++i)
20433 {
20434 xfb_0.m_initial_data[0] = (glw::GLubyte)i;
20435 xfb_0.m_expected_data[0] = (glw::GLubyte)i;
20436 }
20437
20438 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20439 xfb_1.m_expected_data = uniform.m_initial_data;
20440 }
20441
20442 break;
20443
20444 case FIRST_MISSING:
20445 {
20446 /* Test needs single uniform and two xfbs */
20447 out_descriptors.resize(2);
20448
20449 /* Get references */
20450 bufferDescriptor& uniform = out_descriptors[0];
20451 bufferDescriptor& xfb_1 = out_descriptors[1];
20452
20453 /* Index */
20454 uniform.m_index = 0;
20455 xfb_1.m_index = 1;
20456
20457 /* Target */
20458 uniform.m_target = Utils::Buffer::Uniform;
20459 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20460
20461 /* Data */
20462 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20463
20464 /* Data, contents are the same as no modification is expected */
20465 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20466 xfb_1.m_expected_data = uniform.m_initial_data;
20467 }
20468
20469 break;
20470
20471 case SECOND_MISSING:
20472 {
20473 /* Test needs single uniform and two xfbs */
20474 out_descriptors.resize(2);
20475
20476 /* Get references */
20477 bufferDescriptor& uniform = out_descriptors[0];
20478 bufferDescriptor& xfb_0 = out_descriptors[1];
20479
20480 /* Index */
20481 uniform.m_index = 0;
20482 xfb_0.m_index = 0;
20483
20484 /* Target */
20485 uniform.m_target = Utils::Buffer::Uniform;
20486 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20487
20488 /* Data */
20489 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20490
20491 /* Draw call will not be executed, contents does not matter */
20492 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20493 }
20494
20495 break;
20496 }
20497 }
20498
20499 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
20500 *
20501 * @param ignored
20502 * @param captured_varyings Vector of varying names to be captured
20503 **/
20504 void XFBStrideOfEmptyListAndAPITest::getCapturedVaryings(glw::GLuint /* test_case_index */,
20505 Utils::Program::NameVector& captured_varyings,
20506 GLint* xfb_components)
20507 {
20508 captured_varyings.push_back("gs_fs1");
20509 captured_varyings.push_back("gs_fs2");
20510 *xfb_components = 4;
20511 }
20512
20513 /** Get body of main function for given shader stage
20514 *
20515 * @param ignored
20516 * @param stage Shader stage
20517 * @param out_assignments Set to empty
20518 * @param out_calculations Set to empty
20519 **/
20520 void XFBStrideOfEmptyListAndAPITest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20521 std::string& out_assignments, std::string& out_calculations)
20522 {
20523 out_calculations = "";
20524
20525 static const GLchar* gs = " gs_fs1 = -uni_gs;\n"
20526 " gs_fs2 = uni_gs;\n";
20527 static const GLchar* fs = " fs_out = vec4(gs_fs2);\n";
20528
20529 const GLchar* assignments = "";
20530 switch (stage)
20531 {
20532 case Utils::Shader::FRAGMENT:
20533 assignments = fs;
20534 break;
20535 case Utils::Shader::GEOMETRY:
20536 assignments = gs;
20537 break;
20538 default:
20539 break;
20540 }
20541
20542 out_assignments = assignments;
20543 }
20544
20545 /** Get interface of shader
20546 *
20547 * @param ignored
20548 * @param stage Shader stage
20549 * @param out_interface Set to ""
20550 **/
20551 void XFBStrideOfEmptyListAndAPITest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20552 std::string& out_interface)
20553 {
20554 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_stride = 64) out vec4 gs_fs1;\n"
20555 "layout (xfb_buffer = 1, xfb_offset = 0) out vec4 gs_fs2;\n"
20556 "\n"
20557 "layout(binding = 0) uniform gs_block {\n"
20558 " vec4 uni_gs;\n"
20559 "};\n";
20560 static const GLchar* fs = "in vec4 gs_fs2;\n"
20561 "out vec4 fs_out;\n";
20562
20563 switch (stage)
20564 {
20565 case Utils::Shader::FRAGMENT:
20566 out_interface = fs;
20567 break;
20568 case Utils::Shader::GEOMETRY:
20569 out_interface = gs;
20570 break;
20571 default:
20572 out_interface = "";
20573 return;
20574 }
20575 }
20576
20577 /** Returns buffer details in human readable form.
20578 *
20579 * @param test_case_index Index of test case
20580 *
20581 * @return Case description
20582 **/
20583 std::string XFBStrideOfEmptyListAndAPITest::getTestCaseName(GLuint test_case_index)
20584 {
20585 std::string result;
20586
20587 switch (test_case_index)
20588 {
20589 case VALID:
20590 result = "Valid case";
20591 break;
20592 case FIRST_MISSING:
20593 result = "Missing xfb at index 0";
20594 break;
20595 case SECOND_MISSING:
20596 result = "Missing xfb at index 1";
20597 break;
20598 default:
20599 TCU_FAIL("Invalid enum");
20600 }
20601
20602 return result;
20603 }
20604
20605 /** Get number of test cases
20606 *
20607 * @return 2
20608 **/
20609 GLuint XFBStrideOfEmptyListAndAPITest::getTestCaseNumber()
20610 {
20611 return 3;
20612 }
20613
20614 /** Constructor
20615 *
20616 * @param context Test framework context
20617 **/
20618 XFBTooSmallStrideTest::XFBTooSmallStrideTest(deqp::Context& context)
20619 : NegativeTestBase(context, "xfb_too_small_stride",
20620 "Test verifies that compiler reports error when xfb_stride sets not enough space")
20621 {
20622 }
20623
20624 /** Source for given test case and stage
20625 *
20626 * @param test_case_index Index of test case
20627 * @param stage Shader stage
20628 *
20629 * @return Shader source
20630 **/
20631 std::string XFBTooSmallStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
20632 {
20633 static const GLchar* array_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
20634 "\n"
20635 "layout (xfb_offset = 16) out vec4 gohanARRAY[4];\n";
20636 static const GLchar* block_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
20637 "\n"
20638 "layout (xfb_offset = 0) out Goku {\n"
20639 " vec4 gohan;\n"
20640 " vec4 goten;\n"
20641 " vec4 chichi;\n"
20642 "} gokuARRAY;\n";
20643 static const GLchar* offset_var_definition = "layout (xfb_buffer = 0, xfb_stride = 40) out;\n"
20644 "\n"
20645 "layout (xfb_offset = 32) out vec4 gohanARRAY;\n";
20646 // The test considers gohan overflows the buffer 0, but according to spec, it is valid to declare the variable with qualifier "layout (xfb_offset = 16, xfb_stride = 32) out vec4 gohan;"
20647 // To make the shader failed to compile, change xfb_stride to a value that is smaller than 32
20648 static const GLchar* stride_var_definition = "layout (xfb_buffer = 0, xfb_stride = 28) out;\n"
20649 "\n"
20650 "layout (xfb_offset = 16, xfb_stride = 28) out vec4 gohanARRAY;\n";
20651 static const GLchar* array_use = " gohanINDEX[0] = result / 2;\n"
20652 " gohanINDEX[1] = result / 4;\n"
20653 " gohanINDEX[2] = result / 6;\n"
20654 " gohanINDEX[3] = result / 8;\n";
20655 static const GLchar* block_use = " gokuINDEX.gohan = result / 2;\n"
20656 " gokuINDEX.goten = result / 4;\n"
20657 " gokuINDEX.chichi = result / 6;\n";
20658 static const GLchar* output_use = "gohanINDEX = result / 4;\n";
20659 static const GLchar* fs = "#version 430 core\n"
20660 "#extension GL_ARB_enhanced_layouts : require\n"
20661 "\n"
20662 "in vec4 gs_fs;\n"
20663 "out vec4 fs_out;\n"
20664 "\n"
20665 "void main()\n"
20666 "{\n"
20667 " fs_out = gs_fs;\n"
20668 "}\n"
20669 "\n";
20670 static const GLchar* gs_tested = "#version 430 core\n"
20671 "#extension GL_ARB_enhanced_layouts : require\n"
20672 "\n"
20673 "layout(points) in;\n"
20674 "layout(triangle_strip, max_vertices = 4) out;\n"
20675 "\n"
20676 "VAR_DEFINITION"
20677 "\n"
20678 "in vec4 tes_gs[];\n"
20679 "out vec4 gs_fs;\n"
20680 "\n"
20681 "void main()\n"
20682 "{\n"
20683 " vec4 result = tes_gs[0];\n"
20684 "\n"
20685 "VARIABLE_USE"
20686 "\n"
20687 " gs_fs = result;\n"
20688 " gl_Position = vec4(-1, -1, 0, 1);\n"
20689 " EmitVertex();\n"
20690 " gs_fs = result;\n"
20691 " gl_Position = vec4(-1, 1, 0, 1);\n"
20692 " EmitVertex();\n"
20693 " gs_fs = result;\n"
20694 " gl_Position = vec4(1, -1, 0, 1);\n"
20695 " EmitVertex();\n"
20696 " gs_fs = result;\n"
20697 " gl_Position = vec4(1, 1, 0, 1);\n"
20698 " EmitVertex();\n"
20699 "}\n"
20700 "\n";
20701 static const GLchar* tcs = "#version 430 core\n"
20702 "#extension GL_ARB_enhanced_layouts : require\n"
20703 "\n"
20704 "layout(vertices = 1) out;\n"
20705 "\n"
20706 "in vec4 vs_tcs[];\n"
20707 "out vec4 tcs_tes[];\n"
20708 "\n"
20709 "void main()\n"
20710 "{\n"
20711 "\n"
20712 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
20713 "\n"
20714 " gl_TessLevelOuter[0] = 1.0;\n"
20715 " gl_TessLevelOuter[1] = 1.0;\n"
20716 " gl_TessLevelOuter[2] = 1.0;\n"
20717 " gl_TessLevelOuter[3] = 1.0;\n"
20718 " gl_TessLevelInner[0] = 1.0;\n"
20719 " gl_TessLevelInner[1] = 1.0;\n"
20720 "}\n"
20721 "\n";
20722 static const GLchar* tcs_tested = "#version 430 core\n"
20723 "#extension GL_ARB_enhanced_layouts : require\n"
20724 "\n"
20725 "layout(vertices = 1) out;\n"
20726 "\n"
20727 "VAR_DEFINITION"
20728 "\n"
20729 "in vec4 vs_tcs[];\n"
20730 "out vec4 tcs_tes[];\n"
20731 "\n"
20732 "void main()\n"
20733 "{\n"
20734 " vec4 result = vs_tcs[gl_InvocationID];\n"
20735 "\n"
20736 "VARIABLE_USE"
20737 "\n"
20738 " tcs_tes[gl_InvocationID] = result;\n"
20739 "\n"
20740 " gl_TessLevelOuter[0] = 1.0;\n"
20741 " gl_TessLevelOuter[1] = 1.0;\n"
20742 " gl_TessLevelOuter[2] = 1.0;\n"
20743 " gl_TessLevelOuter[3] = 1.0;\n"
20744 " gl_TessLevelInner[0] = 1.0;\n"
20745 " gl_TessLevelInner[1] = 1.0;\n"
20746 "}\n"
20747 "\n";
20748 static const GLchar* tes_tested = "#version 430 core\n"
20749 "#extension GL_ARB_enhanced_layouts : require\n"
20750 "\n"
20751 "layout(isolines, point_mode) in;\n"
20752 "\n"
20753 "VAR_DEFINITION"
20754 "\n"
20755 "in vec4 tcs_tes[];\n"
20756 "out vec4 tes_gs;\n"
20757 "\n"
20758 "void main()\n"
20759 "{\n"
20760 " vec4 result = tcs_tes[0];\n"
20761 "\n"
20762 "VARIABLE_USE"
20763 "\n"
20764 " tes_gs += result;\n"
20765 "}\n"
20766 "\n";
20767 static const GLchar* vs = "#version 430 core\n"
20768 "#extension GL_ARB_enhanced_layouts : require\n"
20769 "\n"
20770 "in vec4 in_vs;\n"
20771 "out vec4 vs_tcs;\n"
20772 "\n"
20773 "void main()\n"
20774 "{\n"
20775 " vs_tcs = in_vs;\n"
20776 "}\n"
20777 "\n";
20778 static const GLchar* vs_tested = "#version 430 core\n"
20779 "#extension GL_ARB_enhanced_layouts : require\n"
20780 "\n"
20781 "VAR_DEFINITION"
20782 "\n"
20783 "in vec4 in_vs;\n"
20784 "out vec4 vs_tcs;\n"
20785 "\n"
20786 "void main()\n"
20787 "{\n"
20788 " vec4 result = in_vs;\n"
20789 "\n"
20790 "VARIABLE_USE"
20791 "\n"
20792 " vs_tcs += result;\n"
20793 "}\n"
20794 "\n";
20795
20796 std::string source;
20797 testCase& test_case = m_test_cases[test_case_index];
20798
20799 if (test_case.m_stage == stage)
20800 {
20801 const GLchar* array = "";
20802 const GLchar* index = "";
20803 size_t position = 0;
20804 size_t temp;
20805 const GLchar* var_definition = 0;
20806 const GLchar* var_use = 0;
20807
20808 switch (test_case.m_case)
20809 {
20810 case OFFSET:
20811 var_definition = offset_var_definition;
20812 var_use = output_use;
20813 break;
20814 case STRIDE:
20815 var_definition = stride_var_definition;
20816 var_use = output_use;
20817 break;
20818 case BLOCK:
20819 var_definition = block_var_definition;
20820 var_use = block_use;
20821 break;
20822 case ARRAY:
20823 var_definition = array_var_definition;
20824 var_use = array_use;
20825 break;
20826 default:
20827 TCU_FAIL("Invalid enum");
20828 }
20829
20830 switch (stage)
20831 {
20832 case Utils::Shader::GEOMETRY:
20833 source = gs_tested;
20834 array = "[]";
20835 index = "[0]";
20836 break;
20837 case Utils::Shader::TESS_CTRL:
20838 source = tcs_tested;
20839 array = "[]";
20840 index = "[gl_InvocationID]";
20841 break;
20842 case Utils::Shader::TESS_EVAL:
20843 source = tes_tested;
20844 array = "[]";
20845 index = "[0]";
20846 break;
20847 case Utils::Shader::VERTEX:
20848 source = vs_tested;
20849 break;
20850 default:
20851 TCU_FAIL("Invalid enum");
20852 }
20853
20854 temp = position;
20855 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
20856 position = temp;
20857 Utils::replaceToken("ARRAY", position, array, source);
20858 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
20859
20860 Utils::replaceAllTokens("INDEX", index, source);
20861 }
20862 else
20863 {
20864 switch (test_case.m_stage)
20865 {
20866 case Utils::Shader::GEOMETRY:
20867 switch (stage)
20868 {
20869 case Utils::Shader::FRAGMENT:
20870 source = fs;
20871 break;
20872 case Utils::Shader::VERTEX:
20873 source = vs;
20874 break;
20875 default:
20876 source = "";
20877 }
20878 break;
20879 case Utils::Shader::TESS_CTRL:
20880 switch (stage)
20881 {
20882 case Utils::Shader::FRAGMENT:
20883 source = fs;
20884 break;
20885 case Utils::Shader::VERTEX:
20886 source = vs;
20887 break;
20888 default:
20889 source = "";
20890 }
20891 break;
20892 case Utils::Shader::TESS_EVAL:
20893 switch (stage)
20894 {
20895 case Utils::Shader::FRAGMENT:
20896 source = fs;
20897 break;
20898 case Utils::Shader::TESS_CTRL:
20899 source = tcs;
20900 break;
20901 case Utils::Shader::VERTEX:
20902 source = vs;
20903 break;
20904 default:
20905 source = "";
20906 }
20907 break;
20908 case Utils::Shader::VERTEX:
20909 switch (stage)
20910 {
20911 case Utils::Shader::FRAGMENT:
20912 source = fs;
20913 break;
20914 default:
20915 source = "";
20916 }
20917 break;
20918 default:
20919 TCU_FAIL("Invalid enum");
20920 break;
20921 }
20922 }
20923
20924 return source;
20925 }
20926
20927 /** Get description of test case
20928 *
20929 * @param test_case_index Index of test case
20930 *
20931 * @return Test case description
20932 **/
20933 std::string XFBTooSmallStrideTest::getTestCaseName(GLuint test_case_index)
20934 {
20935 std::stringstream stream;
20936 testCase& test_case = m_test_cases[test_case_index];
20937
20938 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
20939
20940 switch (test_case.m_case)
20941 {
20942 case OFFSET:
20943 stream << "buffer stride: 40, vec4 offset: 32";
20944 break;
20945 case STRIDE:
20946 stream << "buffer stride: 32, vec4 off 16 stride: 32";
20947 break;
20948 case BLOCK:
20949 stream << "buffer stride: 32, block 3xvec4 offset 0";
20950 break;
20951 case ARRAY:
20952 stream << "buffer stride: 32, vec4[4] offset 16";
20953 break;
20954 default:
20955 TCU_FAIL("Invalid enum");
20956 }
20957
20958 return stream.str();
20959 }
20960
20961 /** Get number of test cases
20962 *
20963 * @return Number of test cases
20964 **/
20965 GLuint XFBTooSmallStrideTest::getTestCaseNumber()
20966 {
20967 return static_cast<GLuint>(m_test_cases.size());
20968 }
20969
20970 /** Selects if "compute" stage is relevant for test
20971 *
20972 * @param ignored
20973 *
20974 * @return false
20975 **/
20976 bool XFBTooSmallStrideTest::isComputeRelevant(GLuint /* test_case_index */)
20977 {
20978 return false;
20979 }
20980
20981 /** Prepare all test cases
20982 *
20983 **/
20984 void XFBTooSmallStrideTest::testInit()
20985 {
20986 for (GLuint c = 0; c < CASE_MAX; ++c)
20987 {
20988 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
20989 {
20990 /*
20991 It is invalid to define transform feedback output in TCS, according to spec:
20992 The data captured in transform feedback mode depends on the active programs on each of the shader stages.
20993 If a program is active for the geometry shader stage, transform feedback captures the vertices of each
20994 primitive emitted by the geometry shader. Otherwise, if a program is active for the tessellation evaluation
20995 shader stage, transform feedback captures each primitive produced by the tessellation primitive generator,
20996 whose vertices are processed by the tessellation evaluation shader. Otherwise, transform feedback captures
20997 each primitive processed by the vertex shader.
20998 */
20999 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21000 (Utils::Shader::FRAGMENT == stage))
21001 {
21002 continue;
21003 }
21004
21005 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
21006
21007 m_test_cases.push_back(test_case);
21008 }
21009 }
21010 }
21011
21012 /** Constructor
21013 *
21014 * @param context Test framework context
21015 **/
21016 XFBVariableStrideTest::XFBVariableStrideTest(deqp::Context& context)
21017 : NegativeTestBase(context, "xfb_variable_stride", "Test verifies that stride qualifier is respected")
21018 {
21019 }
21020
21021 /** Source for given test case and stage
21022 *
21023 * @param test_case_index Index of test case
21024 * @param stage Shader stage
21025 *
21026 * @return Shader source
21027 **/
21028 std::string XFBVariableStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21029 {
21030 static const GLchar* invalid_var_definition =
21031 "const uint type_size = SIZE;\n"
21032 "\n"
21033 "layout (xfb_offset = 0, xfb_stride = 2 * type_size) out TYPE gokuARRAY;\n"
21034 "layout (xfb_offset = type_size) out TYPE vegetaARRAY;\n";
21035 static const GLchar* valid_var_definition =
21036 "const uint type_size = SIZE;\n"
21037 "\n"
21038 "layout (xfb_offset = 0, xfb_stride = 2 * type_size) out TYPE gokuARRAY;\n";
21039 static const GLchar* invalid_use = " gokuINDEX = TYPE(1);\n"
21040 " vegetaINDEX = TYPE(0);\n"
21041 " if (vec4(0) == result)\n"
21042 " {\n"
21043 " gokuINDEX = TYPE(0);\n"
21044 " vegetaINDEX = TYPE(1);\n"
21045 " }\n";
21046 static const GLchar* valid_use = " gokuINDEX = TYPE(1);\n"
21047 " if (vec4(0) == result)\n"
21048 " {\n"
21049 " gokuINDEX = TYPE(0);\n"
21050 " }\n";
21051 static const GLchar* fs = "#version 430 core\n"
21052 "#extension GL_ARB_enhanced_layouts : require\n"
21053 "\n"
21054 "in vec4 any_fs;\n"
21055 "out vec4 fs_out;\n"
21056 "\n"
21057 "void main()\n"
21058 "{\n"
21059 " fs_out = any_fs;\n"
21060 "}\n"
21061 "\n";
21062 static const GLchar* gs_tested = "#version 430 core\n"
21063 "#extension GL_ARB_enhanced_layouts : require\n"
21064 "\n"
21065 "layout(points) in;\n"
21066 "layout(triangle_strip, max_vertices = 4) out;\n"
21067 "\n"
21068 "VAR_DEFINITION"
21069 "\n"
21070 "in vec4 vs_any[];\n"
21071 "out vec4 any_fs;\n"
21072 "\n"
21073 "void main()\n"
21074 "{\n"
21075 " vec4 result = vs_any[0];\n"
21076 "\n"
21077 "VARIABLE_USE"
21078 "\n"
21079 " any_fs = result;\n"
21080 " gl_Position = vec4(-1, -1, 0, 1);\n"
21081 " EmitVertex();\n"
21082 " any_fs = result;\n"
21083 " gl_Position = vec4(-1, 1, 0, 1);\n"
21084 " EmitVertex();\n"
21085 " any_fs = result;\n"
21086 " gl_Position = vec4(1, -1, 0, 1);\n"
21087 " EmitVertex();\n"
21088 " any_fs = result;\n"
21089 " gl_Position = vec4(1, 1, 0, 1);\n"
21090 " EmitVertex();\n"
21091 "}\n"
21092 "\n";
21093 static const GLchar* tcs = "#version 430 core\n"
21094 "#extension GL_ARB_enhanced_layouts : require\n"
21095 "\n"
21096 "layout(vertices = 1) out;\n"
21097 "\n"
21098 "in vec4 vs_any[];\n"
21099 "out vec4 tcs_tes[];\n"
21100 "\n"
21101 "void main()\n"
21102 "{\n"
21103 "\n"
21104 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
21105 "\n"
21106 " gl_TessLevelOuter[0] = 1.0;\n"
21107 " gl_TessLevelOuter[1] = 1.0;\n"
21108 " gl_TessLevelOuter[2] = 1.0;\n"
21109 " gl_TessLevelOuter[3] = 1.0;\n"
21110 " gl_TessLevelInner[0] = 1.0;\n"
21111 " gl_TessLevelInner[1] = 1.0;\n"
21112 "}\n"
21113 "\n";
21114 static const GLchar* tcs_tested = "#version 430 core\n"
21115 "#extension GL_ARB_enhanced_layouts : require\n"
21116 "\n"
21117 "layout(vertices = 1) out;\n"
21118 "\n"
21119 "VAR_DEFINITION"
21120 "\n"
21121 "in vec4 vs_any[];\n"
21122 "out vec4 any_fs[];\n"
21123 "\n"
21124 "void main()\n"
21125 "{\n"
21126 " vec4 result = vs_any[gl_InvocationID];\n"
21127 "\n"
21128 "VARIABLE_USE"
21129 "\n"
21130 " any_fs[gl_InvocationID] = result;\n"
21131 "\n"
21132 " gl_TessLevelOuter[0] = 1.0;\n"
21133 " gl_TessLevelOuter[1] = 1.0;\n"
21134 " gl_TessLevelOuter[2] = 1.0;\n"
21135 " gl_TessLevelOuter[3] = 1.0;\n"
21136 " gl_TessLevelInner[0] = 1.0;\n"
21137 " gl_TessLevelInner[1] = 1.0;\n"
21138 "}\n"
21139 "\n";
21140 static const GLchar* tes_tested = "#version 430 core\n"
21141 "#extension GL_ARB_enhanced_layouts : require\n"
21142 "\n"
21143 "layout(isolines, point_mode) in;\n"
21144 "\n"
21145 "VAR_DEFINITION"
21146 "\n"
21147 "in vec4 tcs_tes[];\n"
21148 "out vec4 any_fs;\n"
21149 "\n"
21150 "void main()\n"
21151 "{\n"
21152 " vec4 result = tcs_tes[0];\n"
21153 "\n"
21154 "VARIABLE_USE"
21155 "\n"
21156 " any_fs = result;\n"
21157 "}\n"
21158 "\n";
21159 static const GLchar* vs = "#version 430 core\n"
21160 "#extension GL_ARB_enhanced_layouts : require\n"
21161 "\n"
21162 "in vec4 in_vs;\n"
21163 "out vec4 vs_any;\n"
21164 "\n"
21165 "void main()\n"
21166 "{\n"
21167 " vs_any = in_vs;\n"
21168 "}\n"
21169 "\n";
21170 static const GLchar* vs_tested = "#version 430 core\n"
21171 "#extension GL_ARB_enhanced_layouts : require\n"
21172 "\n"
21173 "VAR_DEFINITION"
21174 "\n"
21175 "in vec4 in_vs;\n"
21176 "out vec4 any_fs;\n"
21177 "\n"
21178 "void main()\n"
21179 "{\n"
21180 " vec4 result = in_vs;\n"
21181 "\n"
21182 "VARIABLE_USE"
21183 "\n"
21184 " any_fs = result;\n"
21185 "}\n"
21186 "\n";
21187
21188 std::string source;
21189 testCase& test_case = m_test_cases[test_case_index];
21190
21191 if (test_case.m_stage == stage)
21192 {
21193 const GLchar* array = "";
21194 GLchar buffer[16];
21195 const GLchar* index = "";
21196 size_t position = 0;
21197 size_t temp;
21198 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
21199 const GLchar* var_definition = 0;
21200 const GLchar* var_use = 0;
21201
21202 sprintf(buffer, "%d", test_case.m_type.GetSize());
21203
21204 switch (test_case.m_case)
21205 {
21206 case VALID:
21207 var_definition = valid_var_definition;
21208 var_use = valid_use;
21209 break;
21210 case INVALID:
21211 var_definition = invalid_var_definition;
21212 var_use = invalid_use;
21213 break;
21214 default:
21215 TCU_FAIL("Invalid enum");
21216 }
21217
21218 switch (stage)
21219 {
21220 case Utils::Shader::GEOMETRY:
21221 source = gs_tested;
21222 array = "[1]";
21223 index = "[0]";
21224 break;
21225 case Utils::Shader::TESS_CTRL:
21226 source = tcs_tested;
21227 array = "[1]";
21228 index = "[gl_InvocationID]";
21229 break;
21230 case Utils::Shader::TESS_EVAL:
21231 source = tes_tested;
21232 array = "[1]";
21233 index = "[0]";
21234 break;
21235 case Utils::Shader::VERTEX:
21236 source = vs_tested;
21237 break;
21238 default:
21239 TCU_FAIL("Invalid enum");
21240 }
21241
21242 temp = position;
21243 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21244 position = temp;
21245 Utils::replaceToken("SIZE", position, buffer, source);
21246 Utils::replaceToken("ARRAY", position, array, source);
21247 if (INVALID == test_case.m_case)
21248 {
21249 Utils::replaceToken("ARRAY", position, array, source);
21250 }
21251 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21252
21253 Utils::replaceAllTokens("TYPE", type_name, source);
21254 Utils::replaceAllTokens("INDEX", index, source);
21255 }
21256 else
21257 {
21258 switch (test_case.m_stage)
21259 {
21260 case Utils::Shader::GEOMETRY:
21261 switch (stage)
21262 {
21263 case Utils::Shader::FRAGMENT:
21264 source = fs;
21265 break;
21266 case Utils::Shader::VERTEX:
21267 source = vs;
21268 break;
21269 default:
21270 source = "";
21271 }
21272 break;
21273 case Utils::Shader::TESS_CTRL:
21274 switch (stage)
21275 {
21276 case Utils::Shader::FRAGMENT:
21277 source = fs;
21278 break;
21279 case Utils::Shader::VERTEX:
21280 source = vs;
21281 break;
21282 default:
21283 source = "";
21284 }
21285 break;
21286 case Utils::Shader::TESS_EVAL:
21287 switch (stage)
21288 {
21289 case Utils::Shader::FRAGMENT:
21290 source = fs;
21291 break;
21292 case Utils::Shader::TESS_CTRL:
21293 source = tcs;
21294 break;
21295 case Utils::Shader::VERTEX:
21296 source = vs;
21297 break;
21298 default:
21299 source = "";
21300 }
21301 break;
21302 case Utils::Shader::VERTEX:
21303 switch (stage)
21304 {
21305 case Utils::Shader::FRAGMENT:
21306 source = fs;
21307 break;
21308 default:
21309 source = "";
21310 }
21311 break;
21312 default:
21313 TCU_FAIL("Invalid enum");
21314 break;
21315 }
21316 }
21317
21318 return source;
21319 }
21320
21321 /** Get description of test case
21322 *
21323 * @param test_case_index Index of test case
21324 *
21325 * @return Test case description
21326 **/
21327 std::string XFBVariableStrideTest::getTestCaseName(GLuint test_case_index)
21328 {
21329 std::stringstream stream;
21330 testCase& test_case = m_test_cases[test_case_index];
21331
21332 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
21333 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
21334
21335 switch (test_case.m_case)
21336 {
21337 case VALID:
21338 stream << "valid";
21339 break;
21340 case INVALID:
21341 stream << "invalid";
21342 break;
21343 default:
21344 TCU_FAIL("Invalid enum");
21345 }
21346
21347 return stream.str();
21348 }
21349
21350 /** Get number of test cases
21351 *
21352 * @return Number of test cases
21353 **/
21354 GLuint XFBVariableStrideTest::getTestCaseNumber()
21355 {
21356 return static_cast<GLuint>(m_test_cases.size());
21357 }
21358
21359 /** Selects if "compute" stage is relevant for test
21360 *
21361 * @param ignored
21362 *
21363 * @return false
21364 **/
21365 bool XFBVariableStrideTest::isComputeRelevant(GLuint /* test_case_index */)
21366 {
21367 return false;
21368 }
21369
21370 /** Selects if compilation failure is expected result
21371 *
21372 * @param test_case_index Index of test case
21373 *
21374 * @return true
21375 **/
21376 bool XFBVariableStrideTest::isFailureExpected(GLuint test_case_index)
21377 {
21378 testCase& test_case = m_test_cases[test_case_index];
21379
21380 return (INVALID == test_case.m_case);
21381 }
21382
21383 /** Prepare all test cases
21384 *
21385 **/
21386 void XFBVariableStrideTest::testInit()
21387 {
21388 const GLuint n_types = getTypesNumber();
21389
21390 for (GLuint i = 0; i < n_types; ++i)
21391 {
21392 const Utils::Type& type = getType(i);
21393
21394 /*
21395 Some of the cases are declared as following are considered as invalid,
21396 but accoring to spec, the following declaration is valid: shaders in the
21397 transform feedback capturing mode have an initial global default of layout(xfb_buffer=0) out,
21398 so for the first variable's declaration, the xfb_stride = 16 is applied on buffer 0, for the
21399 second variable, its buffer is also inherited from global buffer 0, and its offset does not overflows
21400 the stride.
21401
21402 The xfb_stride is the memory width of given buffer, not for variable even though xfb_stride
21403 is declared on the variable. It seems that the writter of this case misunderstand the concept of
21404 xfb_stride, because spec describes that xfb_stride can be declared multiple times for the same buffer,
21405 it is a compile or link-time error to have different values specified for the stride for the same buffer.
21406
21407 int type_size = 8;
21408 layout (xfb_offset = 0, xfb_stride = 2 * type_size) out double goku;
21409 layout (xfb_offset = type_size) out double vegeta;
21410 */
21411 // all the shaders are valid, so remove the following loop(it contains CASE_MAX is enum of valid and invalid)
21412 // for (GLuint c = 0; c < CASE_MAX; ++c)
21413 {
21414 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21415 {
21416 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21417 (Utils::Shader::FRAGMENT == stage))
21418 {
21419 continue;
21420 }
21421
21422 testCase test_case = { (CASES)VALID, (Utils::Shader::STAGES)stage, type };
21423
21424 m_test_cases.push_back(test_case);
21425 }
21426 }
21427 }
21428 }
21429
21430 /** Constructor
21431 *
21432 * @param context Test framework context
21433 **/
21434 XFBBlockStrideTest::XFBBlockStrideTest(deqp::Context& context)
21435 : TestBase(context, "xfb_block_stride", "Test verifies that stride qualifier is respected for blocks")
21436 {
21437 }
21438
21439 /** Source for given test case and stage
21440 *
21441 * @param test_case_index Index of test case
21442 * @param stage Shader stage
21443 *
21444 * @return Shader source
21445 **/
21446 std::string XFBBlockStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21447 {
21448 static const GLchar* var_definition = "layout (xfb_offset = 0, xfb_stride = 128) out Goku {\n"
21449 " vec4 gohan;\n"
21450 " vec4 goten;\n"
21451 " vec4 chichi;\n"
21452 "} gokuARRAY;\n";
21453 static const GLchar* var_use = " gokuINDEX.gohan = vec4(1, 0, 0, 0);\n"
21454 " gokuINDEX.goten = vec4(0, 0, 1, 0);\n"
21455 " gokuINDEX.chichi = vec4(0, 1, 0, 0);\n"
21456 " if (vec4(0) == result)\n"
21457 " {\n"
21458 " gokuINDEX.gohan = vec4(0, 1, 1, 1);\n"
21459 " gokuINDEX.goten = vec4(1, 1, 0, 1);\n"
21460 " gokuINDEX.chichi = vec4(1, 0, 1, 1);\n"
21461 " }\n";
21462 static const GLchar* gs_tested =
21463 "#version 430 core\n"
21464 "#extension GL_ARB_enhanced_layouts : require\n"
21465 "\n"
21466 "layout(points) in;\n"
21467 "layout(triangle_strip, max_vertices = 4) out;\n"
21468 "\n"
21469 "VAR_DEFINITION"
21470 "\n"
21471 "out gl_PerVertex \n"
21472 "{ \n"
21473 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
21474 "}; \n"
21475 "in vec4 tes_gs[];\n"
21476 "out vec4 gs_fs;\n"
21477 "\n"
21478 "void main()\n"
21479 "{\n"
21480 " vec4 result = tes_gs[0];\n"
21481 "\n"
21482 "VARIABLE_USE"
21483 "\n"
21484 " gs_fs = result;\n"
21485 " gl_Position = vec4(-1, -1, 0, 1);\n"
21486 " EmitVertex();\n"
21487 " gs_fs = result;\n"
21488 " gl_Position = vec4(-1, 1, 0, 1);\n"
21489 " EmitVertex();\n"
21490 " gs_fs = result;\n"
21491 " gl_Position = vec4(1, -1, 0, 1);\n"
21492 " EmitVertex();\n"
21493 " gs_fs = result;\n"
21494 " gl_Position = vec4(1, 1, 0, 1);\n"
21495 " EmitVertex();\n"
21496 "}\n"
21497 "\n";
21498 static const GLchar* tcs = "#version 430 core\n"
21499 "#extension GL_ARB_enhanced_layouts : require\n"
21500 "\n"
21501 "layout(vertices = 1) out;\n"
21502 "\n"
21503 "in vec4 vs_tcs[];\n"
21504 "out vec4 tcs_tes[];\n"
21505 "\n"
21506 "void main()\n"
21507 "{\n"
21508 "\n"
21509 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
21510 "\n"
21511 " gl_TessLevelOuter[0] = 1.0;\n"
21512 " gl_TessLevelOuter[1] = 1.0;\n"
21513 " gl_TessLevelOuter[2] = 1.0;\n"
21514 " gl_TessLevelOuter[3] = 1.0;\n"
21515 " gl_TessLevelInner[0] = 1.0;\n"
21516 " gl_TessLevelInner[1] = 1.0;\n"
21517 "}\n"
21518 "\n";
21519 #if 0
21520 static const GLchar* tcs_tested =
21521 "#version 430 core\n"
21522 "#extension GL_ARB_enhanced_layouts : require\n"
21523 "\n"
21524 "layout(vertices = 1) out;\n"
21525 "\n"
21526 "VAR_DEFINITION"
21527 "\n"
21528 "in vec4 vs_tcs[];\n"
21529 "out vec4 tcs_tes[];\n"
21530 "\n"
21531 "void main()\n"
21532 "{\n"
21533 " vec4 result = vs_tcs[gl_InvocationID];\n"
21534 "\n"
21535 "VARIABLE_USE"
21536 "\n"
21537 " tcs_tes[gl_InvocationID] = result;\n"
21538 "\n"
21539 " gl_TessLevelOuter[0] = 1.0;\n"
21540 " gl_TessLevelOuter[1] = 1.0;\n"
21541 " gl_TessLevelOuter[2] = 1.0;\n"
21542 " gl_TessLevelOuter[3] = 1.0;\n"
21543 " gl_TessLevelInner[0] = 1.0;\n"
21544 " gl_TessLevelInner[1] = 1.0;\n"
21545 "}\n"
21546 "\n";
21547 #endif
21548 static const GLchar* tes_tested = "#version 430 core\n"
21549 "#extension GL_ARB_enhanced_layouts : require\n"
21550 "\n"
21551 "layout(isolines, point_mode) in;\n"
21552 "\n"
21553 "VAR_DEFINITION"
21554 "\n"
21555 "in vec4 tcs_tes[];\n"
21556 "out vec4 tes_gs;\n"
21557 "\n"
21558 "void main()\n"
21559 "{\n"
21560 " vec4 result = tcs_tes[0];\n"
21561 "\n"
21562 "VARIABLE_USE"
21563 "\n"
21564 " tes_gs += result;\n"
21565 "}\n"
21566 "\n";
21567 static const GLchar* vs = "#version 430 core\n"
21568 "#extension GL_ARB_enhanced_layouts : require\n"
21569 "\n"
21570 "in vec4 in_vs;\n"
21571 "out vec4 vs_tcs;\n"
21572 "out vec4 tes_gs;\n"
21573 "\n"
21574 "void main()\n"
21575 "{\n"
21576 " vs_tcs = tes_gs = in_vs;\n"
21577 "}\n"
21578 "\n";
21579 static const GLchar* vs_tested = "#version 430 core\n"
21580 "#extension GL_ARB_enhanced_layouts : require\n"
21581 "\n"
21582 "VAR_DEFINITION"
21583 "\n"
21584 "in vec4 in_vs;\n"
21585 "out vec4 vs_tcs;\n"
21586 "\n"
21587 "void main()\n"
21588 "{\n"
21589 " vec4 result = in_vs;\n"
21590 "\n"
21591 "VARIABLE_USE"
21592 "\n"
21593 " vs_tcs += result;\n"
21594 "}\n"
21595 "\n";
21596
21597 std::string source;
21598 Utils::Shader::STAGES test_case = m_test_cases[test_case_index];
21599
21600 if (test_case == stage)
21601 {
21602 const GLchar* array = "";
21603 const GLchar* index = "";
21604 size_t position = 0;
21605 size_t temp;
21606 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
21607 // change array = "[]" to "[1]"
21608 switch (stage)
21609 {
21610 case Utils::Shader::GEOMETRY:
21611 source = gs_tested;
21612 array = "[1]";
21613 index = "[0]";
21614 break;
21615 /*
21616 It is invalid to define transform feedback output in HS
21617 */
21618 #if 0
21619 case Utils::Shader::TESS_CTRL:
21620 source = tcs_tested;
21621 array = "[]";
21622 index = "[gl_InvocationID]";
21623 break;
21624 #endif
21625 case Utils::Shader::TESS_EVAL:
21626 source = tes_tested;
21627 array = "[1]";
21628 index = "[0]";
21629 break;
21630 case Utils::Shader::VERTEX:
21631 source = vs_tested;
21632 break;
21633 default:
21634 TCU_FAIL("Invalid enum");
21635 }
21636
21637 temp = position;
21638 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21639 position = temp;
21640 Utils::replaceToken("ARRAY", position, array, source);
21641 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21642
21643 Utils::replaceAllTokens("INDEX", index, source);
21644 }
21645 else
21646 {
21647 switch (test_case)
21648 {
21649 case Utils::Shader::GEOMETRY:
21650 switch (stage)
21651 {
21652 case Utils::Shader::VERTEX:
21653 source = vs;
21654 break;
21655 default:
21656 source = "";
21657 }
21658 break;
21659 case Utils::Shader::TESS_CTRL:
21660 switch (stage)
21661 {
21662 case Utils::Shader::VERTEX:
21663 source = vs;
21664 break;
21665 default:
21666 source = "";
21667 }
21668 break;
21669 case Utils::Shader::TESS_EVAL:
21670 switch (stage)
21671 {
21672 case Utils::Shader::TESS_CTRL:
21673 source = tcs;
21674 break;
21675 case Utils::Shader::VERTEX:
21676 source = vs;
21677 break;
21678 default:
21679 source = "";
21680 }
21681 break;
21682 case Utils::Shader::VERTEX:
21683 source = "";
21684 break;
21685 default:
21686 TCU_FAIL("Invalid enum");
21687 break;
21688 }
21689 }
21690
21691 return source;
21692 }
21693
21694 /** Get description of test case
21695 *
21696 * @param test_case_index Index of test case
21697 *
21698 * @return Test case description
21699 **/
21700 std::string XFBBlockStrideTest::getTestCaseName(GLuint test_case_index)
21701 {
21702 std::stringstream stream;
21703
21704 stream << "Stage: " << Utils::Shader::GetStageName(m_test_cases[test_case_index]);
21705
21706 return stream.str();
21707 }
21708
21709 /** Get number of test cases
21710 *
21711 * @return Number of test cases
21712 **/
21713 GLuint XFBBlockStrideTest::getTestCaseNumber()
21714 {
21715 return static_cast<GLuint>(m_test_cases.size());
21716 }
21717
21718 /** Inspects program for xfb stride
21719 *
21720 * @param program Program to query
21721 *
21722 * @return true if query results match expected values, false otherwise
21723 **/
21724 bool XFBBlockStrideTest::inspectProgram(Utils::Program& program)
21725 {
21726 GLint stride = 0;
21727
21728 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
21729 1 /* buf_size */, &stride);
21730
21731 return (128 == stride);
21732 }
21733
21734 /** Runs test case
21735 *
21736 * @param test_case_index Id of test case
21737 *
21738 * @return true if test case pass, false otherwise
21739 **/
21740 bool XFBBlockStrideTest::testCase(GLuint test_case_index)
21741 {
21742 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
21743 Utils::Program program(m_context);
21744 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
21745 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
21746 bool test_case_result = true;
21747 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
21748
21749 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
21750
21751 test_case_result = inspectProgram(program);
21752
21753 return test_case_result;
21754 }
21755
21756 /** Prepare all test cases
21757 *
21758 **/
21759 void XFBBlockStrideTest::testInit()
21760 {
21761 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21762 {
21763 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21764 (Utils::Shader::FRAGMENT == stage))
21765 {
21766 continue;
21767 }
21768
21769 m_test_cases.push_back((Utils::Shader::STAGES)stage);
21770 }
21771 }
21772
21773 /** Constructor
21774 *
21775 * @param context Test context
21776 **/
21777 XFBBlockMemberStrideTest::XFBBlockMemberStrideTest(deqp::Context& context)
21778 : BufferTestBase(context, "xfb_block_member_stride",
21779 "Test verifies that xfb_stride qualifier is respected for block member")
21780 {
21781 /* Nothing to be done here */
21782 }
21783
21784 /** Get descriptors of buffers necessary for test
21785 *
21786 * @param ignored
21787 * @param out_descriptors Descriptors of buffers used by test
21788 **/
21789 void XFBBlockMemberStrideTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
21790 bufferDescriptor::Vector& out_descriptors)
21791 {
21792 const Utils::Type& vec4 = Utils::Type::vec4;
21793
21794 /* Test needs single uniform and xfb */
21795 out_descriptors.resize(2);
21796
21797 /* Get references */
21798 bufferDescriptor& uniform = out_descriptors[0];
21799 bufferDescriptor& xfb = out_descriptors[1];
21800
21801 /* Index */
21802 uniform.m_index = 0;
21803 xfb.m_index = 0;
21804
21805 /* Target */
21806 uniform.m_target = Utils::Buffer::Uniform;
21807 xfb.m_target = Utils::Buffer::Transform_feedback;
21808
21809 /* Data */
21810 static const GLuint vec4_size = 16;
21811 const std::vector<GLubyte>& gohan_data = vec4.GenerateDataPacked();
21812 const std::vector<GLubyte>& goten_data = vec4.GenerateDataPacked();
21813 const std::vector<GLubyte>& chichi_data = vec4.GenerateDataPacked();
21814
21815 /* Uniform data */
21816 uniform.m_initial_data.resize(3 * vec4_size);
21817 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], vec4_size);
21818 memcpy(&uniform.m_initial_data[0] + vec4_size, &goten_data[0], vec4_size);
21819 memcpy(&uniform.m_initial_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
21820
21821 /* XFB data */
21822 xfb.m_initial_data.resize(4 * vec4_size);
21823 xfb.m_expected_data.resize(4 * vec4_size);
21824
21825 for (GLuint i = 0; i < 4 * vec4_size; ++i)
21826 {
21827 xfb.m_initial_data[i] = (glw::GLubyte)i;
21828 xfb.m_expected_data[i] = (glw::GLubyte)i;
21829 }
21830
21831 // the xfb_offset of "chichi" should be 32
21832 memcpy(&xfb.m_expected_data[0] + 0, &gohan_data[0], vec4_size);
21833 memcpy(&xfb.m_expected_data[0] + vec4_size, &goten_data[0], vec4_size);
21834 memcpy(&xfb.m_expected_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
21835 }
21836
21837 /** Get body of main function for given shader stage
21838 *
21839 * @param ignored
21840 * @param stage Shader stage
21841 * @param out_assignments Set to empty
21842 * @param out_calculations Set to empty
21843 **/
21844 void XFBBlockMemberStrideTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21845 std::string& out_assignments, std::string& out_calculations)
21846 {
21847 out_calculations = "";
21848
21849 static const GLchar* gs = " gohan = uni_gohan;\n"
21850 " goten = uni_goten;\n"
21851 " chichi = uni_chichi;\n";
21852 static const GLchar* fs = " fs_out = gohan + goten + chichi;\n";
21853
21854 const GLchar* assignments = "";
21855 switch (stage)
21856 {
21857 case Utils::Shader::FRAGMENT:
21858 assignments = fs;
21859 break;
21860 case Utils::Shader::GEOMETRY:
21861 assignments = gs;
21862 break;
21863 default:
21864 break;
21865 }
21866
21867 out_assignments = assignments;
21868 }
21869
21870 /** Get interface of shader
21871 *
21872 * @param ignored
21873 * @param stage Shader stage
21874 * @param out_interface Set to ""
21875 **/
21876 void XFBBlockMemberStrideTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21877 std::string& out_interface)
21878 {
21879 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
21880 " vec4 gohan;\n"
21881 " layout (xfb_stride = 48) vec4 goten;\n"
21882 " vec4 chichi;\n"
21883 "};\n"
21884 "layout(binding = 0) uniform gs_block {\n"
21885 " vec4 uni_gohan;\n"
21886 " vec4 uni_goten;\n"
21887 " vec4 uni_chichi;\n"
21888 "};\n";
21889 static const GLchar* fs = "in Goku {\n"
21890 " vec4 gohan;\n"
21891 " vec4 goten;\n"
21892 " vec4 chichi;\n"
21893 "};\n"
21894 "out vec4 fs_out;\n";
21895
21896 switch (stage)
21897 {
21898 case Utils::Shader::FRAGMENT:
21899 out_interface = fs;
21900 break;
21901 case Utils::Shader::GEOMETRY:
21902 out_interface = gs;
21903 break;
21904 default:
21905 out_interface = "";
21906 return;
21907 }
21908 }
21909
21910 /** Inspects program to check if all resources are as expected
21911 *
21912 * @param ignored
21913 * @param program Program instance
21914 * @param out_stream Error message
21915 *
21916 * @return true if everything is ok, false otherwise
21917 **/
21918 bool XFBBlockMemberStrideTest::inspectProgram(GLuint /* test_case_index*/, Utils::Program& program,
21919 std::stringstream& out_stream)
21920 {
21921 const GLuint gohan_id = program.GetResourceIndex("gohan", GL_TRANSFORM_FEEDBACK_VARYING);
21922 const GLuint goten_id = program.GetResourceIndex("goten", GL_TRANSFORM_FEEDBACK_VARYING);
21923 const GLuint chichi_id = program.GetResourceIndex("chichi", GL_TRANSFORM_FEEDBACK_VARYING);
21924
21925 GLint gohan_offset = 0;
21926 GLint goten_offset = 0;
21927 GLint chichi_offset = 0;
21928
21929 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, gohan_id, GL_OFFSET, 1, &gohan_offset);
21930 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, goten_id, GL_OFFSET, 1, &goten_offset);
21931 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, chichi_id, GL_OFFSET, 1, &chichi_offset);
21932
21933 // the xfb_offset of "chichi" should be 32
21934 if ((0 != gohan_offset) || (16 != goten_offset) || (32 != chichi_offset))
21935 {
21936 out_stream << "Got wrong offset: [" << gohan_offset << ", " << goten_offset << ", " << chichi_offset
21937 << "] expected: [0, 16, 32]";
21938 return false;
21939 }
21940
21941 return true;
21942 }
21943
21944 /** Constructor
21945 *
21946 * @param context Test framework context
21947 **/
21948 XFBDuplicatedStrideTest::XFBDuplicatedStrideTest(deqp::Context& context)
21949 : NegativeTestBase(context, "xfb_duplicated_stride",
21950 "Test verifies that compiler reports error when conflicting stride qualifiers are used")
21951 {
21952 }
21953
21954 /** Source for given test case and stage
21955 *
21956 * @param test_case_index Index of test case
21957 * @param stage Shader stage
21958 *
21959 * @return Shader source
21960 **/
21961 std::string XFBDuplicatedStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21962 {
21963 static const GLchar* invalid_var_definition = "const uint valid_stride = 64;\n"
21964 "const uint conflicting_stride = 128;\n"
21965 "\n"
21966 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
21967 "layout (xfb_buffer = 0, xfb_stride = conflicting_stride) out;\n";
21968 static const GLchar* valid_var_definition = "const uint valid_stride = 64;\n"
21969 "\n"
21970 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
21971 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n";
21972 static const GLchar* fs = "#version 430 core\n"
21973 "#extension GL_ARB_enhanced_layouts : require\n"
21974 "\n"
21975 "in vec4 any_fs;\n"
21976 "out vec4 fs_out;\n"
21977 "\n"
21978 "void main()\n"
21979 "{\n"
21980 " fs_out = any_fs;\n"
21981 "}\n"
21982 "\n";
21983 static const GLchar* gs_tested = "#version 430 core\n"
21984 "#extension GL_ARB_enhanced_layouts : require\n"
21985 "\n"
21986 "layout(points) in;\n"
21987 "layout(triangle_strip, max_vertices = 4) out;\n"
21988 "\n"
21989 "VAR_DEFINITION"
21990 "\n"
21991 "in vec4 vs_any[];\n"
21992 "out vec4 any_fs;\n"
21993 "\n"
21994 "void main()\n"
21995 "{\n"
21996 " vec4 result = vs_any[0];\n"
21997 "\n"
21998 "VARIABLE_USE"
21999 "\n"
22000 " any_fs = result;\n"
22001 " gl_Position = vec4(-1, -1, 0, 1);\n"
22002 " EmitVertex();\n"
22003 " any_fs = result;\n"
22004 " gl_Position = vec4(-1, 1, 0, 1);\n"
22005 " EmitVertex();\n"
22006 " any_fs = result;\n"
22007 " gl_Position = vec4(1, -1, 0, 1);\n"
22008 " EmitVertex();\n"
22009 " any_fs = result;\n"
22010 " gl_Position = vec4(1, 1, 0, 1);\n"
22011 " EmitVertex();\n"
22012 "}\n"
22013 "\n";
22014 static const GLchar* tcs = "#version 430 core\n"
22015 "#extension GL_ARB_enhanced_layouts : require\n"
22016 "\n"
22017 "layout(vertices = 1) out;\n"
22018 "\n"
22019 "in vec4 vs_any[];\n"
22020 "out vec4 tcs_tes[];\n"
22021 "\n"
22022 "void main()\n"
22023 "{\n"
22024 "\n"
22025 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
22026 "\n"
22027 " gl_TessLevelOuter[0] = 1.0;\n"
22028 " gl_TessLevelOuter[1] = 1.0;\n"
22029 " gl_TessLevelOuter[2] = 1.0;\n"
22030 " gl_TessLevelOuter[3] = 1.0;\n"
22031 " gl_TessLevelInner[0] = 1.0;\n"
22032 " gl_TessLevelInner[1] = 1.0;\n"
22033 "}\n"
22034 "\n";
22035 static const GLchar* tcs_tested = "#version 430 core\n"
22036 "#extension GL_ARB_enhanced_layouts : require\n"
22037 "\n"
22038 "layout(vertices = 1) out;\n"
22039 "\n"
22040 "VAR_DEFINITION"
22041 "\n"
22042 "in vec4 vs_any[];\n"
22043 "out vec4 any_fs[];\n"
22044 "\n"
22045 "void main()\n"
22046 "{\n"
22047 " vec4 result = vs_any[gl_InvocationID];\n"
22048 "\n"
22049 "VARIABLE_USE"
22050 "\n"
22051 " any_fs[gl_InvocationID] = result;\n"
22052 "\n"
22053 " gl_TessLevelOuter[0] = 1.0;\n"
22054 " gl_TessLevelOuter[1] = 1.0;\n"
22055 " gl_TessLevelOuter[2] = 1.0;\n"
22056 " gl_TessLevelOuter[3] = 1.0;\n"
22057 " gl_TessLevelInner[0] = 1.0;\n"
22058 " gl_TessLevelInner[1] = 1.0;\n"
22059 "}\n"
22060 "\n";
22061 static const GLchar* tes_tested = "#version 430 core\n"
22062 "#extension GL_ARB_enhanced_layouts : require\n"
22063 "\n"
22064 "layout(isolines, point_mode) in;\n"
22065 "\n"
22066 "VAR_DEFINITION"
22067 "\n"
22068 "in vec4 tcs_tes[];\n"
22069 "out vec4 any_fs;\n"
22070 "\n"
22071 "void main()\n"
22072 "{\n"
22073 " vec4 result = tcs_tes[0];\n"
22074 "\n"
22075 "VARIABLE_USE"
22076 "\n"
22077 " any_fs = result;\n"
22078 "}\n"
22079 "\n";
22080 static const GLchar* vs = "#version 430 core\n"
22081 "#extension GL_ARB_enhanced_layouts : require\n"
22082 "\n"
22083 "in vec4 in_vs;\n"
22084 "out vec4 vs_any;\n"
22085 "\n"
22086 "void main()\n"
22087 "{\n"
22088 " vs_any = in_vs;\n"
22089 "}\n"
22090 "\n";
22091 static const GLchar* vs_tested = "#version 430 core\n"
22092 "#extension GL_ARB_enhanced_layouts : require\n"
22093 "\n"
22094 "VAR_DEFINITION"
22095 "\n"
22096 "in vec4 in_vs;\n"
22097 "out vec4 any_fs;\n"
22098 "\n"
22099 "void main()\n"
22100 "{\n"
22101 " vec4 result = in_vs;\n"
22102 "\n"
22103 "VARIABLE_USE"
22104 "\n"
22105 " any_fs += result;\n"
22106 "}\n"
22107 "\n";
22108
22109 std::string source;
22110 testCase& test_case = m_test_cases[test_case_index];
22111
22112 if (test_case.m_stage == stage)
22113 {
22114 size_t position = 0;
22115 const GLchar* var_definition = 0;
22116 const GLchar* var_use = "";
22117
22118 switch (test_case.m_case)
22119 {
22120 case VALID:
22121 var_definition = valid_var_definition;
22122 break;
22123 case INVALID:
22124 var_definition = invalid_var_definition;
22125 break;
22126 default:
22127 TCU_FAIL("Invalid enum");
22128 }
22129
22130 switch (stage)
22131 {
22132 case Utils::Shader::GEOMETRY:
22133 source = gs_tested;
22134 break;
22135 case Utils::Shader::TESS_CTRL:
22136 source = tcs_tested;
22137 break;
22138 case Utils::Shader::TESS_EVAL:
22139 source = tes_tested;
22140 break;
22141 case Utils::Shader::VERTEX:
22142 source = vs_tested;
22143 break;
22144 default:
22145 TCU_FAIL("Invalid enum");
22146 }
22147
22148 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22149 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22150 }
22151 else
22152 {
22153 switch (test_case.m_stage)
22154 {
22155 case Utils::Shader::GEOMETRY:
22156 switch (stage)
22157 {
22158 case Utils::Shader::FRAGMENT:
22159 source = fs;
22160 break;
22161 case Utils::Shader::VERTEX:
22162 source = vs;
22163 break;
22164 default:
22165 source = "";
22166 }
22167 break;
22168 case Utils::Shader::TESS_CTRL:
22169 switch (stage)
22170 {
22171 case Utils::Shader::FRAGMENT:
22172 source = fs;
22173 break;
22174 case Utils::Shader::VERTEX:
22175 source = vs;
22176 break;
22177 default:
22178 source = "";
22179 }
22180 break;
22181 case Utils::Shader::TESS_EVAL:
22182 switch (stage)
22183 {
22184 case Utils::Shader::FRAGMENT:
22185 source = fs;
22186 break;
22187 case Utils::Shader::TESS_CTRL:
22188 source = tcs;
22189 break;
22190 case Utils::Shader::VERTEX:
22191 source = vs;
22192 break;
22193 default:
22194 source = "";
22195 }
22196 break;
22197 case Utils::Shader::VERTEX:
22198 switch (stage)
22199 {
22200 case Utils::Shader::FRAGMENT:
22201 source = fs;
22202 break;
22203 default:
22204 source = "";
22205 }
22206 break;
22207 default:
22208 TCU_FAIL("Invalid enum");
22209 break;
22210 }
22211 }
22212
22213 return source;
22214 }
22215
22216 /** Get description of test case
22217 *
22218 * @param test_case_index Index of test case
22219 *
22220 * @return Test case description
22221 **/
22222 std::string XFBDuplicatedStrideTest::getTestCaseName(GLuint test_case_index)
22223 {
22224 std::stringstream stream;
22225 testCase& test_case = m_test_cases[test_case_index];
22226
22227 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
22228
22229 switch (test_case.m_case)
22230 {
22231 case VALID:
22232 stream << "valid";
22233 break;
22234 case INVALID:
22235 stream << "invalid";
22236 break;
22237 default:
22238 TCU_FAIL("Invalid enum");
22239 }
22240
22241 return stream.str();
22242 }
22243
22244 /** Get number of test cases
22245 *
22246 * @return Number of test cases
22247 **/
22248 GLuint XFBDuplicatedStrideTest::getTestCaseNumber()
22249 {
22250 return static_cast<GLuint>(m_test_cases.size());
22251 }
22252
22253 /** Selects if "compute" stage is relevant for test
22254 *
22255 * @param ignored
22256 *
22257 * @return false
22258 **/
22259 bool XFBDuplicatedStrideTest::isComputeRelevant(GLuint /* test_case_index */)
22260 {
22261 return false;
22262 }
22263
22264 /** Selects if compilation failure is expected result
22265 *
22266 * @param test_case_index Index of test case
22267 *
22268 * @return true
22269 **/
22270 bool XFBDuplicatedStrideTest::isFailureExpected(GLuint test_case_index)
22271 {
22272 testCase& test_case = m_test_cases[test_case_index];
22273
22274 return (INVALID == test_case.m_case);
22275 }
22276
22277 /** Prepare all test cases
22278 *
22279 **/
22280 void XFBDuplicatedStrideTest::testInit()
22281 {
22282 for (GLuint c = 0; c < CASE_MAX; ++c)
22283 {
22284 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22285 {
22286 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22287 (Utils::Shader::FRAGMENT == stage))
22288 {
22289 continue;
22290 }
22291
22292 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
22293
22294 m_test_cases.push_back(test_case);
22295 }
22296 }
22297 }
22298
22299 /** Constructor
22300 *
22301 * @param context Test framework context
22302 **/
22303 XFBGetProgramResourceAPITest::XFBGetProgramResourceAPITest(deqp::Context& context)
22304 : TestBase(context, "xfb_get_program_resource_api",
22305 "Test verifies that get program resource reports correct results for XFB")
22306 {
22307 }
22308
22309 /** Source for given test case and stage
22310 *
22311 * @param test_case_index Index of test case
22312 * @param stage Shader stage
22313 *
22314 * @return Shader source
22315 **/
22316 std::string XFBGetProgramResourceAPITest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
22317 {
22318 static const GLchar* api_var_definition = "out TYPE b0_v1ARRAY;\n"
22319 "out TYPE b1_v1ARRAY;\n"
22320 "out TYPE b0_v3ARRAY;\n"
22321 "out TYPE b0_v0ARRAY;\n";
22322 static const GLchar* xfb_var_definition =
22323 "const uint type_size = SIZE;\n"
22324 "\n"
22325 "layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;\n"
22326 "\n"
22327 "layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out TYPE b0_v1ARRAY;\n"
22328 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out TYPE b1_v1ARRAY;\n"
22329 "layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out TYPE b0_v3ARRAY;\n"
22330 "layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out TYPE b0_v0ARRAY;\n";
22331 static const GLchar* var_use = " b0_v1INDEX = TYPE(0);\n"
22332 " b1_v1INDEX = TYPE(1);\n"
22333 " b0_v3INDEX = TYPE(0);\n"
22334 " b0_v0INDEX = TYPE(1);\n"
22335 " if (vec4(0) == result)\n"
22336 " {\n"
22337 " b0_v1INDEX = TYPE(1);\n"
22338 " b1_v1INDEX = TYPE(0);\n"
22339 " b0_v3INDEX = TYPE(1);\n"
22340 " b0_v0INDEX = TYPE(0);\n"
22341 " }\n";
22342 static const GLchar* gs_tested =
22343 "#version 430 core\n"
22344 "#extension GL_ARB_enhanced_layouts : require\n"
22345 "\n"
22346 "layout(points) in;\n"
22347 "layout(triangle_strip, max_vertices = 4) out;\n"
22348 "\n"
22349 "VAR_DEFINITION"
22350 "\n"
22351 "out gl_PerVertex \n"
22352 "{ \n"
22353 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
22354 "}; \n"
22355 "in vec4 tes_gs[];\n"
22356 "out vec4 gs_fs;\n"
22357 "\n"
22358 "void main()\n"
22359 "{\n"
22360 " vec4 result = tes_gs[0];\n"
22361 "\n"
22362 "VARIABLE_USE"
22363 "\n"
22364 " gs_fs = result;\n"
22365 " gl_Position = vec4(-1, -1, 0, 1);\n"
22366 " EmitVertex();\n"
22367 " gs_fs = result;\n"
22368 " gl_Position = vec4(-1, 1, 0, 1);\n"
22369 " EmitVertex();\n"
22370 " gs_fs = result;\n"
22371 " gl_Position = vec4(1, -1, 0, 1);\n"
22372 " EmitVertex();\n"
22373 " gs_fs = result;\n"
22374 " gl_Position = vec4(1, 1, 0, 1);\n"
22375 " EmitVertex();\n"
22376 "}\n"
22377 "\n";
22378 #if 0
22379 static const GLchar* tcs_tested =
22380 "#version 430 core\n"
22381 "#extension GL_ARB_enhanced_layouts : require\n"
22382 "\n"
22383 "layout(vertices = 1) out;\n"
22384 "\n"
22385 "VAR_DEFINITION"
22386 "\n"
22387 "in vec4 vs_tcs[];\n"
22388 "out vec4 tcs_tes[];\n"
22389 "\n"
22390 "void main()\n"
22391 "{\n"
22392 " vec4 result = vs_tcs[gl_InvocationID];\n"
22393 "\n"
22394 "VARIABLE_USE"
22395 "\n"
22396 " tcs_tes[gl_InvocationID] = result;\n"
22397 "\n"
22398 " gl_TessLevelOuter[0] = 1.0;\n"
22399 " gl_TessLevelOuter[1] = 1.0;\n"
22400 " gl_TessLevelOuter[2] = 1.0;\n"
22401 " gl_TessLevelOuter[3] = 1.0;\n"
22402 " gl_TessLevelInner[0] = 1.0;\n"
22403 " gl_TessLevelInner[1] = 1.0;\n"
22404 "}\n"
22405 "\n";
22406 #endif
22407 static const GLchar* tes_tested = "#version 430 core\n"
22408 "#extension GL_ARB_enhanced_layouts : require\n"
22409 "\n"
22410 "layout(isolines, point_mode) in;\n"
22411 "\n"
22412 "VAR_DEFINITION"
22413 "\n"
22414 "in vec4 tcs_tes[];\n"
22415 "out vec4 tes_gs;\n"
22416 "\n"
22417 "void main()\n"
22418 "{\n"
22419 " vec4 result = tcs_tes[0];\n"
22420 "\n"
22421 "VARIABLE_USE"
22422 "\n"
22423 " tes_gs = result;\n"
22424 "}\n"
22425 "\n";
22426 static const GLchar* vs_tested = "#version 430 core\n"
22427 "#extension GL_ARB_enhanced_layouts : require\n"
22428 "\n"
22429 "VAR_DEFINITION"
22430 "\n"
22431 "in vec4 in_vs;\n"
22432 "out vec4 vs_tcs;\n"
22433 "\n"
22434 "void main()\n"
22435 "{\n"
22436 " vec4 result = in_vs;\n"
22437 "\n"
22438 "VARIABLE_USE"
22439 "\n"
22440 " vs_tcs = result;\n"
22441 "}\n"
22442 "\n";
22443
22444 std::string source;
22445 const test_Case& test_case = m_test_cases[test_case_index];
22446
22447 if (test_case.m_stage == stage)
22448 {
22449 const GLchar* array = "";
22450 GLchar buffer[16];
22451 const GLchar* index = "";
22452 size_t position = 0;
22453 size_t temp;
22454 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
22455 const GLchar* var_definition = 0;
22456
22457 sprintf(buffer, "%d", test_case.m_type.GetSize());
22458
22459 if (XFB == test_case.m_case)
22460 {
22461 var_definition = xfb_var_definition;
22462 }
22463 else
22464 {
22465 var_definition = api_var_definition;
22466 }
22467
22468 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
22469 // change array = "[]" to "[1]"
22470 switch (stage)
22471 {
22472 case Utils::Shader::GEOMETRY:
22473 source = gs_tested;
22474 array = "[1]";
22475 index = "[0]";
22476 break;
22477 // It is invalid to output transform feedback varyings in tessellation control shader
22478 #if 0
22479 case Utils::Shader::TESS_CTRL:
22480 source = tcs_tested;
22481 array = "[]";
22482 index = "[gl_InvocationID]";
22483 break;
22484 #endif
22485 case Utils::Shader::TESS_EVAL:
22486 source = tes_tested;
22487 array = "[1]";
22488 index = "[0]";
22489 break;
22490 case Utils::Shader::VERTEX:
22491 source = vs_tested;
22492 break;
22493 default:
22494 TCU_FAIL("Invalid enum");
22495 }
22496
22497 temp = position;
22498 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22499 if (XFB == test_case.m_case)
22500 {
22501 position = temp;
22502 Utils::replaceToken("SIZE", position, buffer, source);
22503 }
22504 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22505
22506 Utils::replaceAllTokens("ARRAY", array, source);
22507 Utils::replaceAllTokens("INDEX", index, source);
22508 Utils::replaceAllTokens("TYPE", type_name, source);
22509 }
22510 else
22511 {
22512 source = "";
22513 }
22514
22515 return source;
22516 }
22517
22518 /** Get description of test case
22519 *
22520 * @param test_case_index Index of test case
22521 *
22522 * @return Test case description
22523 **/
22524 std::string XFBGetProgramResourceAPITest::getTestCaseName(GLuint test_case_index)
22525 {
22526 std::stringstream stream;
22527 const test_Case& test_case = m_test_cases[test_case_index];
22528
22529 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
22530 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
22531
22532 switch (test_case.m_case)
22533 {
22534 case INTERLEAVED:
22535 stream << "interleaved";
22536 break;
22537 case SEPARATED:
22538 stream << "separated";
22539 break;
22540 case XFB:
22541 stream << "xfb";
22542 break;
22543 default:
22544 TCU_FAIL("Invalid enum");
22545 }
22546
22547 return stream.str();
22548 }
22549
22550 /** Get number of test cases
22551 *
22552 * @return Number of test cases
22553 **/
22554 GLuint XFBGetProgramResourceAPITest::getTestCaseNumber()
22555 {
22556 return static_cast<GLuint>(m_test_cases.size());
22557 }
22558
22559 /** Inspects program for offset, buffer index, buffer stride and type
22560 *
22561 * @param test_case_index Index of test case
22562 * @param program Program to query
22563 *
22564 * @return true if query results match expected values, false otherwise
22565 **/
22566 bool XFBGetProgramResourceAPITest::inspectProgram(glw::GLuint test_case_index, Utils::Program& program)
22567 {
22568 GLint b0_stride = 0;
22569 GLint b1_stride = 0;
22570 GLint b0_v0_buf = 0;
22571 GLint b0_v0_offset = 0;
22572 GLint b0_v0_type = 0;
22573 GLint b0_v1_buf = 0;
22574 GLint b0_v1_offset = 0;
22575 GLint b0_v1_type = 0;
22576 GLint b0_v3_buf = 0;
22577 GLint b0_v3_offset = 0;
22578 GLint b0_v3_type = 0;
22579 GLint b1_v1_buf = 0;
22580 GLint b1_v1_offset = 0;
22581 GLint b1_v1_type = 0;
22582 const test_Case& test_case = m_test_cases[test_case_index];
22583 const GLenum type_enum = test_case.m_type.GetTypeGLenum();
22584 const GLint type_size = test_case.m_type.GetSize();
22585
22586 GLuint b0_v0_index = program.GetResourceIndex("b0_v0", GL_TRANSFORM_FEEDBACK_VARYING);
22587 GLuint b0_v1_index = program.GetResourceIndex("b0_v1", GL_TRANSFORM_FEEDBACK_VARYING);
22588 GLuint b0_v3_index = program.GetResourceIndex("b0_v3", GL_TRANSFORM_FEEDBACK_VARYING);
22589 GLuint b1_v1_index = program.GetResourceIndex("b1_v1", GL_TRANSFORM_FEEDBACK_VARYING);
22590
22591 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_OFFSET, 1 /* buf_size */, &b0_v0_offset);
22592 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_OFFSET, 1 /* buf_size */, &b0_v1_offset);
22593 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_OFFSET, 1 /* buf_size */, &b0_v3_offset);
22594 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_OFFSET, 1 /* buf_size */, &b1_v1_offset);
22595
22596 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TYPE, 1 /* buf_size */, &b0_v0_type);
22597 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TYPE, 1 /* buf_size */, &b0_v1_type);
22598 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TYPE, 1 /* buf_size */, &b0_v3_type);
22599 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TYPE, 1 /* buf_size */, &b1_v1_type);
22600
22601 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
22602 1 /* buf_size */, &b0_v0_buf);
22603 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
22604 1 /* buf_size */, &b0_v1_buf);
22605 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
22606 1 /* buf_size */, &b0_v3_buf);
22607 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
22608 1 /* buf_size */, &b1_v1_buf);
22609
22610 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b0_v0_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
22611 &b0_stride);
22612 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b1_v1_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
22613 &b1_stride);
22614
22615 if (SEPARATED != test_case.m_case)
22616 {
22617 return (((GLint)(4 * type_size) == b0_stride) && ((GLint)(4 * type_size) == b1_stride) &&
22618 ((GLint)(0) == b0_v0_buf) && ((GLint)(0 * type_size) == b0_v0_offset) &&
22619 ((GLint)(type_enum) == b0_v0_type) && ((GLint)(0) == b0_v1_buf) &&
22620 ((GLint)(1 * type_size) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
22621 ((GLint)(0) == b0_v3_buf) && ((GLint)(3 * type_size) == b0_v3_offset) &&
22622 ((GLint)(type_enum) == b0_v3_type) && ((GLint)(1) == b1_v1_buf) &&
22623 ((GLint)(1 * type_size) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
22624 }
22625 else
22626 {
22627 return (((GLint)(1 * type_size) == b0_stride) && ((GLint)(1 * type_size) == b1_stride) &&
22628 ((GLint)(0) == b0_v0_buf) && ((GLint)(0) == b0_v0_offset) && ((GLint)(type_enum) == b0_v0_type) &&
22629 ((GLint)(1) == b0_v1_buf) && ((GLint)(0) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
22630 ((GLint)(2) == b0_v3_buf) && ((GLint)(0) == b0_v3_offset) && ((GLint)(type_enum) == b0_v3_type) &&
22631 ((GLint)(3) == b1_v1_buf) && ((GLint)(0) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
22632 }
22633 }
22634
22635 /** Insert gl_SkipComponents
22636 *
22637 * @param num_components How many gl_SkipComponents1 need to be inserted
22638 * @param varyings The transform feedback varyings string vector
22639 *
22640 **/
22641 void XFBGetProgramResourceAPITest::insertSkipComponents(int num_components, Utils::Program::NameVector& varyings)
22642 {
22643 int num_component_4 = num_components / 4;
22644 int num_component_1 = num_components % 4;
22645 for (int i = 0; i < num_component_4; i++)
22646 {
22647 varyings.push_back("gl_SkipComponents4");
22648 }
22649 switch (num_component_1)
22650 {
22651 case 1:
22652 varyings.push_back("gl_SkipComponents1");
22653 break;
22654 case 2:
22655 varyings.push_back("gl_SkipComponents2");
22656 break;
22657 case 3:
22658 varyings.push_back("gl_SkipComponents3");
22659 break;
22660 default:
22661 break;
22662 }
22663 }
22664
22665 /** Runs test case
22666 *
22667 * @param test_case_index Id of test case
22668 *
22669 * @return true if test case pass, false otherwise
22670 **/
22671 bool XFBGetProgramResourceAPITest::testCase(GLuint test_case_index)
22672 {
22673 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
22674 Utils::Program program(m_context);
22675 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
22676 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
22677 const test_Case& test_case = m_test_cases[test_case_index];
22678 bool test_case_result = true;
22679 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
22680
22681 // According to spec: gl_SkipComponents1 ~ gl_SkipComponents4 is treated as specifying a one- to four-component floating point output variables with undefined values.
22682 // No data will be recorded for such strings, but the offset assigned to the next variable in varyings and the stride of the assigned bingding point will be affected.
22683
22684 if (INTERLEAVED == test_case.m_case)
22685 {
22686 /*
22687 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
22688 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
22689 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
22690 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
22691
22692 Note: the type can be float, double, mat2, mat3x2, dmat2, dmat3x2..., so to make the each variable of "captured_varyings" has the same xfb_offset with the above shaders,
22693 we need to calculate how many "gl_SkipComponents" need to be inserted.
22694 */
22695 Utils::Program::NameVector captured_varyings;
22696 captured_varyings.push_back("b0_v0");
22697 captured_varyings.push_back("b0_v1");
22698 // Compute how many gl_SkipComponents to be inserted
22699 int numComponents = test_case.m_type.GetSize() / 4;
22700 insertSkipComponents(numComponents, captured_varyings);
22701 captured_varyings.push_back("b0_v3");
22702 captured_varyings.push_back("gl_NextBuffer");
22703 insertSkipComponents(numComponents, captured_varyings);
22704 captured_varyings.push_back("b1_v1");
22705 insertSkipComponents(numComponents * 2, captured_varyings);
22706
22707 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, true,
22708 true /* separable */);
22709 }
22710 else if (SEPARATED == test_case.m_case)
22711 {
22712 Utils::Program::NameVector captured_varyings;
22713
22714 captured_varyings.push_back("b0_v0");
22715 captured_varyings.push_back("b0_v1");
22716 captured_varyings.push_back("b0_v3");
22717 captured_varyings.push_back("b1_v1");
22718
22719 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, false,
22720 true /* separable */);
22721 }
22722 else
22723 {
22724
22725 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
22726 }
22727
22728 test_case_result = inspectProgram(test_case_index, program);
22729
22730 return test_case_result;
22731 }
22732
22733 /** Prepare all test cases
22734 *
22735 **/
22736 void XFBGetProgramResourceAPITest::testInit()
22737 {
22738 const Functions& gl = m_context.getRenderContext().getFunctions();
22739 const GLuint n_types = getTypesNumber();
22740 GLint max_xfb_int;
22741 GLint max_xfb_sep;
22742
22743 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_int);
22744 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
22745
22746 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_xfb_sep);
22747 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
22748
22749 GLint max_varyings;
22750 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings);
22751
22752 for (GLuint i = 0; i < n_types; ++i)
22753 {
22754 // When i == 7, the type is dmat4, i == 9 the type is dmat4x3, the number of output components exceeds the maximum value that AMD's driver supported,
22755 // the MAX_VARYING_COMPONENTS is 32 in our driver, but when the variable type is dmat4 or dmat4x3, the number of output component is 33, to make the
22756 // shader valid, we can either skip the dmat4, dmat4x3 or query the implementation-dependent value MAX_VARYING_COMPONENTS before generating the shader
22757 // to guarantee the number of varying not exceeded.
22758 /*
22759 layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;
22760 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
22761 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
22762 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
22763 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
22764 in vec4 in_vs;
22765 out vec4 vs_tcs;
22766 */
22767 if (i == 7 || i == 9)
22768 continue;
22769 const Utils::Type& type = getType(i);
22770 if (4 * type.GetNumComponents() + 4 > (GLuint)max_varyings)
22771 {
22772 continue;
22773 }
22774 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22775 {
22776 /*
22777 It is invalid to define transform feedback output in HS
22778 */
22779 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22780 (Utils::Shader::FRAGMENT == stage))
22781 {
22782 continue;
22783 }
22784
22785 test_Case test_case_int = { INTERLEAVED, (Utils::Shader::STAGES)stage, type };
22786 test_Case test_case_sep = { SEPARATED, (Utils::Shader::STAGES)stage, type };
22787 test_Case test_case_xfb = { XFB, (Utils::Shader::STAGES)stage, type };
22788
22789 if ((int)type.GetSize() <= max_xfb_int)
22790 {
22791 m_test_cases.push_back(test_case_xfb);
22792 m_test_cases.push_back(test_case_int);
22793 }
22794
22795 if ((int)type.GetSize() <= max_xfb_sep)
22796 {
22797 m_test_cases.push_back(test_case_sep);
22798 }
22799 }
22800 }
22801 }
22802
22803 /** Constructor
22804 *
22805 * @param context Test context
22806 **/
22807 XFBOverrideQualifiersWithAPITest::XFBOverrideQualifiersWithAPITest(deqp::Context& context)
22808 : BufferTestBase(context, "xfb_override_qualifiers_with_api",
22809 "Test verifies that xfb_offset qualifier is not overriden with API")
22810 {
22811 /* Nothing to be done here */
22812 }
22813
22814 /** Get descriptors of buffers necessary for test
22815 *
22816 * @param test_case_index Index of test case
22817 * @param out_descriptors Descriptors of buffers used by test
22818 **/
22819 void XFBOverrideQualifiersWithAPITest::getBufferDescriptors(glw::GLuint test_case_index,
22820 bufferDescriptor::Vector& out_descriptors)
22821 {
22822 const Utils::Type& type = getType(test_case_index);
22823
22824 /* Test needs single uniform and xfb */
22825 out_descriptors.resize(2);
22826
22827 /* Get references */
22828 bufferDescriptor& uniform = out_descriptors[0];
22829 bufferDescriptor& xfb = out_descriptors[1];
22830
22831 /* Index */
22832 uniform.m_index = 0;
22833 xfb.m_index = 0;
22834
22835 /* Target */
22836 uniform.m_target = Utils::Buffer::Uniform;
22837 xfb.m_target = Utils::Buffer::Transform_feedback;
22838
22839 /* Data */
22840 const GLuint gen_start = Utils::s_rand;
22841 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
22842 const std::vector<GLubyte>& trunks_data = type.GenerateData();
22843 const std::vector<GLubyte>& goku_data = type.GenerateData();
22844
22845 Utils::s_rand = gen_start;
22846 const std::vector<GLubyte>& vegeta_data_pck = type.GenerateDataPacked();
22847 type.GenerateDataPacked(); // generate the data for trunks
22848 const std::vector<GLubyte>& goku_data_pck = type.GenerateDataPacked();
22849
22850 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
22851 const GLuint type_size_pck = static_cast<GLuint>(vegeta_data_pck.size());
22852
22853 /* Uniform data */
22854 uniform.m_initial_data.resize(3 * type_size);
22855 memcpy(&uniform.m_initial_data[0] + 0, &vegeta_data[0], type_size);
22856 memcpy(&uniform.m_initial_data[0] + type_size, &trunks_data[0], type_size);
22857 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goku_data[0], type_size);
22858
22859 /* XFB data */
22860 xfb.m_initial_data.resize(3 * type_size_pck);
22861 xfb.m_expected_data.resize(3 * type_size_pck);
22862
22863 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
22864 {
22865 xfb.m_initial_data[i] = (glw::GLubyte)i;
22866 xfb.m_expected_data[i] = (glw::GLubyte)i;
22867 }
22868
22869 memcpy(&xfb.m_expected_data[0] + 0, &goku_data_pck[0], type_size_pck);
22870 memcpy(&xfb.m_expected_data[0] + 2 * type_size_pck, &vegeta_data_pck[0], type_size_pck);
22871 }
22872
22873 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
22874 *
22875 * @param ignored
22876 * @param captured_varyings List of names
22877 **/
22878 void XFBOverrideQualifiersWithAPITest::getCapturedVaryings(glw::GLuint test_case_index,
22879 Utils::Program::NameVector& captured_varyings,
22880 GLint* xfb_components)
22881 {
22882 captured_varyings.resize(1);
22883
22884 captured_varyings[0] = "trunks";
22885
22886 /* The test captures 3 varyings of type 'type' */
22887 Utils::Type type = getType(test_case_index);
22888 GLint type_size = type.GetSize(false);
22889 *xfb_components = 3 * type_size / 4;
22890 }
22891
22892 /** Get body of main function for given shader stage
22893 *
22894 * @param test_case_index Index of test case
22895 * @param stage Shader stage
22896 * @param out_assignments Set to empty
22897 * @param out_calculations Set to empty
22898 **/
22899 void XFBOverrideQualifiersWithAPITest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
22900 std::string& out_assignments, std::string& out_calculations)
22901 {
22902 out_calculations = "";
22903
22904 static const GLchar* gs = " vegeta = uni_vegeta;\n"
22905 " trunks = uni_trunks;\n"
22906 " goku = uni_goku;\n";
22907 static const GLchar* fs = " fs_out = vec4(0);\n"
22908 " if (TYPE(1) == goku + trunks + vegeta)\n"
22909 " {\n"
22910 " fs_out = vec4(1);\n"
22911 " }\n";
22912
22913 const GLchar* assignments = "";
22914 switch (stage)
22915 {
22916 case Utils::Shader::FRAGMENT:
22917 assignments = fs;
22918 break;
22919 case Utils::Shader::GEOMETRY:
22920 assignments = gs;
22921 break;
22922 default:
22923 break;
22924 }
22925
22926 out_assignments = assignments;
22927
22928 if (Utils::Shader::FRAGMENT == stage)
22929 {
22930 const Utils::Type& type = getType(test_case_index);
22931
22932 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_assignments);
22933 }
22934 }
22935
22936 /** Get interface of shader
22937 *
22938 * @param test_case_index Index of test case
22939 * @param stage Shader stage
22940 * @param out_interface Set to ""
22941 **/
22942 void XFBOverrideQualifiersWithAPITest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
22943 std::string& out_interface)
22944 {
22945 static const GLchar* gs = "const uint sizeof_type = SIZE;\n"
22946 "\n"
22947 "layout (xfb_offset = 2 * sizeof_type) flat out TYPE vegeta;\n"
22948 " flat out TYPE trunks;\n"
22949 "layout (xfb_offset = 0) flat out TYPE goku;\n"
22950 "\n"
22951 /*
22952 There is no packing qualifier for uniform block gs_block, according to spec, it should be "shared" by default,
22953 the definition equals to "layout(binding=0, shared)", if the block is declared as shared, each block member will
22954 not be packed, and each block member's layout in memory is implementation dependent, so we can't use the API
22955 glBufferData() to update the UBO directly, we need to query each block member's offset first, then upload the
22956 data to the corresponding offset, otherwise we can't get the correct data from UBO; to make the test passed,
22957 we need to add the qualifier std140, and change the declaration as layout(binding=0, std140), which can make
22958 sure all the block members are packed and the application can upload the data by glBufferData() directly.
22959 */
22960 "layout(binding = 0, std140) uniform gs_block {\n"
22961 " TYPE uni_vegeta;\n"
22962 " TYPE uni_trunks;\n"
22963 " TYPE uni_goku;\n"
22964 "};\n";
22965 static const GLchar* fs = "flat in TYPE vegeta;\n"
22966 "flat in TYPE trunks;\n"
22967 "flat in TYPE goku;\n"
22968 "\n"
22969 "out vec4 fs_out;\n";
22970
22971 const Utils::Type& type = getType(test_case_index);
22972
22973 switch (stage)
22974 {
22975 case Utils::Shader::FRAGMENT:
22976 out_interface = fs;
22977 break;
22978 case Utils::Shader::GEOMETRY:
22979 out_interface = gs;
22980 break;
22981 default:
22982 out_interface = "";
22983 return;
22984 }
22985
22986 if (Utils::Shader::GEOMETRY == stage)
22987 {
22988 GLchar buffer[16];
22989 size_t position = 0;
22990 const GLuint type_size = type.GetSize();
22991
22992 sprintf(buffer, "%d", type_size);
22993
22994 Utils::replaceToken("SIZE", position, buffer, out_interface);
22995 }
22996
22997 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_interface);
22998 }
22999
23000 /** Get type name
23001 *
23002 * @param test_case_index Index of test case
23003 *
23004 * @return Name of type test in test_case_index
23005 **/
23006 std::string XFBOverrideQualifiersWithAPITest::getTestCaseName(glw::GLuint test_case_index)
23007 {
23008 return getTypeName(test_case_index);
23009 }
23010
23011 /** Returns number of types to test
23012 *
23013 * @return Number of types, 34
23014 **/
23015 glw::GLuint XFBOverrideQualifiersWithAPITest::getTestCaseNumber()
23016 {
23017 return getTypesNumber();
23018 }
23019
23020 /** Inspects program to check if all resources are as expected
23021 *
23022 * @param test_case_index Index of test case
23023 * @param program Program instance
23024 * @param out_stream Error message
23025 *
23026 * @return true if everything is ok, false otherwise
23027 **/
23028 bool XFBOverrideQualifiersWithAPITest::inspectProgram(GLuint test_case_index, Utils::Program& program,
23029 std::stringstream& out_stream)
23030 {
23031 GLint stride = 0;
23032 const Utils::Type& type = getType(test_case_index);
23033 const GLuint type_size = type.GetSize(false);
23034
23035 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
23036 1 /* buf_size */, &stride);
23037
23038 if ((GLint)(3 * type_size) != stride)
23039 {
23040 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
23041
23042 return false;
23043 }
23044
23045 return true;
23046 }
23047
23048 /** Constructor
23049 *
23050 * @param context Test context
23051 **/
23052 XFBVertexStreamsTest::XFBVertexStreamsTest(deqp::Context& context)
23053 : BufferTestBase(context, "xfb_vertex_streams",
23054 "Test verifies that xfb qualifier works with multiple output streams")
23055 {
23056 /* Nothing to be done here */
23057 }
23058
23059 /** Get descriptors of buffers necessary for test
23060 *
23061 * @param ignored
23062 * @param out_descriptors Descriptors of buffers used by test
23063 **/
23064 void XFBVertexStreamsTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
23065 bufferDescriptor::Vector& out_descriptors)
23066 {
23067 const Utils::Type& type = Utils::Type::vec4;
23068
23069 /* Test needs single uniform and three xfbs */
23070 out_descriptors.resize(4);
23071
23072 /* Get references */
23073 bufferDescriptor& uniform = out_descriptors[0];
23074 bufferDescriptor& xfb_1 = out_descriptors[1];
23075 bufferDescriptor& xfb_2 = out_descriptors[2];
23076 bufferDescriptor& xfb_3 = out_descriptors[3];
23077
23078 /* Index */
23079 uniform.m_index = 0;
23080 xfb_1.m_index = 1;
23081 xfb_2.m_index = 2;
23082 xfb_3.m_index = 3;
23083
23084 /* Target */
23085 uniform.m_target = Utils::Buffer::Uniform;
23086 xfb_1.m_target = Utils::Buffer::Transform_feedback;
23087 xfb_2.m_target = Utils::Buffer::Transform_feedback;
23088 xfb_3.m_target = Utils::Buffer::Transform_feedback;
23089
23090 /* Data */
23091 const std::vector<GLubyte>& goku_data = type.GenerateData();
23092 const std::vector<GLubyte>& gohan_data = type.GenerateData();
23093 const std::vector<GLubyte>& goten_data = type.GenerateData();
23094 const std::vector<GLubyte>& picolo_data = type.GenerateData();
23095 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
23096 const std::vector<GLubyte>& bulma_data = type.GenerateData();
23097
23098 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
23099
23100 /* Uniform data */
23101 uniform.m_initial_data.resize(6 * type_size);
23102 memcpy(&uniform.m_initial_data[0] + 0, &goku_data[0], type_size);
23103 memcpy(&uniform.m_initial_data[0] + type_size, &gohan_data[0], type_size);
23104 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
23105 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &picolo_data[0], type_size);
23106 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
23107 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &bulma_data[0], type_size);
23108
23109 /* XFB data */
23110 static const GLuint xfb_stride = 64;
23111 xfb_1.m_initial_data.resize(xfb_stride);
23112 xfb_1.m_expected_data.resize(xfb_stride);
23113 xfb_2.m_initial_data.resize(xfb_stride);
23114 xfb_2.m_expected_data.resize(xfb_stride);
23115 xfb_3.m_initial_data.resize(xfb_stride);
23116 xfb_3.m_expected_data.resize(xfb_stride);
23117
23118 for (GLuint i = 0; i < xfb_stride; ++i)
23119 {
23120 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
23121 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
23122 xfb_2.m_initial_data[i] = (glw::GLubyte)i;
23123 xfb_2.m_expected_data[i] = (glw::GLubyte)i;
23124 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
23125 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
23126 }
23127
23128 memcpy(&xfb_1.m_expected_data[0] + 48, &goku_data[0], type_size);
23129 memcpy(&xfb_1.m_expected_data[0] + 32, &gohan_data[0], type_size);
23130 memcpy(&xfb_1.m_expected_data[0] + 16, &goten_data[0], type_size);
23131 memcpy(&xfb_3.m_expected_data[0] + 48, &picolo_data[0], type_size);
23132 memcpy(&xfb_3.m_expected_data[0] + 32, &vegeta_data[0], type_size);
23133 memcpy(&xfb_2.m_expected_data[0] + 32, &bulma_data[0], type_size);
23134 }
23135
23136 /** Get body of main function for given shader stage
23137 *
23138 * @param ignored
23139 * @param stage Shader stage
23140 * @param out_assignments Set to empty
23141 * @param out_calculations Set to empty
23142 **/
23143 void XFBVertexStreamsTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23144 std::string& out_assignments, std::string& out_calculations)
23145 {
23146 out_calculations = "";
23147
23148 // the shader declares the output variables with different "stream" qualifier, to make the data can export to
23149 // each stream, we must call the function EmitStreamVertex() and EndStreamPrimitive() to make each vertex emitted
23150 // by the GS is assigned to specific stream.
23151 static const GLchar* gs = " goku = uni_goku;\n"
23152 " gohan = uni_gohan;\n"
23153 " goten = uni_goten;\n"
23154 " EmitStreamVertex(0);\n"
23155 " EndStreamPrimitive(0);\n"
23156 " picolo = uni_picolo;\n"
23157 " vegeta = uni_vegeta;\n"
23158 " EmitStreamVertex(1);\n"
23159 " EndStreamPrimitive(1);\n"
23160 " bulma = uni_bulma;\n"
23161 " EmitStreamVertex(2);\n"
23162 " EndStreamPrimitive(2);\n";
23163
23164 static const GLchar* fs = " fs_out = gohan + goku + goten;\n";
23165
23166 const GLchar* assignments = "";
23167 switch (stage)
23168 {
23169 case Utils::Shader::FRAGMENT:
23170 assignments = fs;
23171 break;
23172 case Utils::Shader::GEOMETRY:
23173 assignments = gs;
23174 break;
23175 default:
23176 break;
23177 }
23178
23179 out_assignments = assignments;
23180 }
23181
23182 /** Get interface of shader
23183 *
23184 * @param ignored
23185 * @param stage Shader stage
23186 * @param out_interface Set to ""
23187 **/
23188 void XFBVertexStreamsTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23189 std::string& out_interface)
23190 {
23191 static const GLchar* gs = "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
23192 "layout (xfb_buffer = 2, xfb_stride = 64) out;\n"
23193 "layout (xfb_buffer = 3, xfb_stride = 64) out;\n"
23194 "\n"
23195 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23196 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23197 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n"
23198 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 48) out vec4 picolo;\n"
23199 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 32) out vec4 vegeta;\n"
23200 "layout (stream = 2, xfb_buffer = 2, xfb_offset = 32) out vec4 bulma;\n"
23201 "\n"
23202 "layout(binding = 0) uniform gs_block {\n"
23203 " vec4 uni_goku;\n"
23204 " vec4 uni_gohan;\n"
23205 " vec4 uni_goten;\n"
23206 " vec4 uni_picolo;\n"
23207 " vec4 uni_vegeta;\n"
23208 " vec4 uni_bulma;\n"
23209 "};\n";
23210 /*
23211 Fixed incorrect usage of in/out qualifier, the following variable should be input symbols for fragment shader
23212 */
23213 static const GLchar* fs = "in vec4 goku;\n"
23214 "in vec4 gohan;\n"
23215 "in vec4 goten;\n"
23216 "\n"
23217 "out vec4 fs_out;\n";
23218
23219 switch (stage)
23220 {
23221 case Utils::Shader::FRAGMENT:
23222 out_interface = fs;
23223 break;
23224 case Utils::Shader::GEOMETRY:
23225 out_interface = gs;
23226 break;
23227 default:
23228 out_interface = "";
23229 return;
23230 }
23231 }
23232
23233 /** Constructor
23234 *
23235 * @param context Test framework context
23236 **/
23237 XFBMultipleVertexStreamsTest::XFBMultipleVertexStreamsTest(deqp::Context& context)
23238 : NegativeTestBase(
23239 context, "xfb_multiple_vertex_streams",
23240 "Test verifies that compiler reports error when multiple streams are captured with same xfb_buffer")
23241 {
23242 }
23243
23244 /** Source for given test case and stage
23245 *
23246 * @param ignored
23247 * @param stage Shader stage
23248 *
23249 * @return Shader source
23250 **/
23251 std::string XFBMultipleVertexStreamsTest::getShaderSource(GLuint /* test_case_index */, Utils::Shader::STAGES stage)
23252 {
23253 static const GLchar* var_definition = "const uint valid_stride = 64;\n"
23254 "\n"
23255 "layout (xfb_buffer = 1, xfb_stride = valid_stride) out;\n"
23256 "layout (xfb_buffer = 3, xfb_stride = valid_stride) out;\n"
23257 "\n"
23258 "\n"
23259 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23260 "layout (stream = 1, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23261 "layout (stream = 2, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n";
23262 static const GLchar* var_use = " goku = result / 2;\n"
23263 " gohan = result / 4;\n"
23264 " goten = result / 6;\n";
23265 static const GLchar* fs = "#version 430 core\n"
23266 "#extension GL_ARB_enhanced_layouts : require\n"
23267 "\n"
23268 "in vec4 gs_fs;\n"
23269 "in vec4 goku;\n"
23270 "out vec4 fs_out;\n"
23271 "\n"
23272 "void main()\n"
23273 "{\n"
23274 " fs_out = gs_fs + goku;\n"
23275 "}\n"
23276 "\n";
23277 static const GLchar* gs = "#version 430 core\n"
23278 "#extension GL_ARB_enhanced_layouts : require\n"
23279 "\n"
23280 "layout(points) in;\n"
23281 "layout(triangle_strip, max_vertices = 4) out;\n"
23282 "\n"
23283 "VAR_DEFINITION"
23284 "\n"
23285 "in vec4 tes_gs[];\n"
23286 "out vec4 gs_fs;\n"
23287 "\n"
23288 "void main()\n"
23289 "{\n"
23290 " vec4 result = tes_gs[0];\n"
23291 "\n"
23292 "VARIABLE_USE"
23293 "\n"
23294 " gs_fs = result;\n"
23295 " gl_Position = vec4(-1, -1, 0, 1);\n"
23296 " EmitVertex();\n"
23297 " gs_fs = result;\n"
23298 " gl_Position = vec4(-1, 1, 0, 1);\n"
23299 " EmitVertex();\n"
23300 " gs_fs = result;\n"
23301 " gl_Position = vec4(1, -1, 0, 1);\n"
23302 " EmitVertex();\n"
23303 " gs_fs = result;\n"
23304 " gl_Position = vec4(1, 1, 0, 1);\n"
23305 " EmitVertex();\n"
23306 "}\n"
23307 "\n";
23308 static const GLchar* vs = "#version 430 core\n"
23309 "#extension GL_ARB_enhanced_layouts : require\n"
23310 "\n"
23311 "in vec4 in_vs;\n"
23312 "out vec4 vs_tcs;\n"
23313 "\n"
23314 "void main()\n"
23315 "{\n"
23316 " vs_tcs = in_vs;\n"
23317 "}\n"
23318 "\n";
23319
23320 std::string source;
23321
23322 if (Utils::Shader::GEOMETRY == stage)
23323 {
23324 size_t position = 0;
23325
23326 source = gs;
23327
23328 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23329 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23330 }
23331 else
23332 {
23333 switch (stage)
23334 {
23335 case Utils::Shader::FRAGMENT:
23336 source = fs;
23337 break;
23338 case Utils::Shader::VERTEX:
23339 source = vs;
23340 break;
23341 default:
23342 source = "";
23343 }
23344 }
23345
23346 return source;
23347 }
23348
23349 /** Selects if "compute" stage is relevant for test
23350 *
23351 * @param ignored
23352 *
23353 * @return false
23354 **/
23355 bool XFBMultipleVertexStreamsTest::isComputeRelevant(GLuint /* test_case_index */)
23356 {
23357 return false;
23358 }
23359
23360 /** Constructor
23361 *
23362 * @param context Test framework context
23363 **/
23364 XFBExceedBufferLimitTest::XFBExceedBufferLimitTest(deqp::Context& context)
23365 : NegativeTestBase(context, "xfb_exceed_buffer_limit",
23366 "Test verifies that compiler reports error when xfb_buffer qualifier exceeds limit")
23367 {
23368 }
23369
23370 /** Source for given test case and stage
23371 *
23372 * @param test_case_index Index of test case
23373 * @param stage Shader stage
23374 *
23375 * @return Shader source
23376 **/
23377 std::string XFBExceedBufferLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
23378 {
23379 static const GLchar* block_var_definition = "const uint buffer_index = BUFFER;\n"
23380 "\n"
23381 "layout (xfb_buffer = buffer_index, xfb_offset = 0) out Goku {\n"
23382 " vec4 member;\n"
23383 "} gokuARRAY;\n";
23384 static const GLchar* global_var_definition = "const uint buffer_index = BUFFER;\n"
23385 "\n"
23386 "layout (xfb_buffer = buffer_index) out;\n";
23387 static const GLchar* vector_var_definition = "const uint buffer_index = BUFFER;\n"
23388 "\n"
23389 "layout (xfb_buffer = buffer_index) out vec4 gokuARRAY;\n";
23390 static const GLchar* block_use = " gokuINDEX.member = result / 2;\n";
23391 static const GLchar* global_use = "";
23392 static const GLchar* vector_use = " gokuINDEX = result / 2;\n";
23393 static const GLchar* fs = "#version 430 core\n"
23394 "#extension GL_ARB_enhanced_layouts : require\n"
23395 "\n"
23396 "in vec4 gs_fs;\n"
23397 "out vec4 fs_out;\n"
23398 "\n"
23399 "void main()\n"
23400 "{\n"
23401 " fs_out = gs_fs;\n"
23402 "}\n"
23403 "\n";
23404 static const GLchar* gs_tested = "#version 430 core\n"
23405 "#extension GL_ARB_enhanced_layouts : require\n"
23406 "\n"
23407 "layout(points) in;\n"
23408 "layout(triangle_strip, max_vertices = 4) out;\n"
23409 "\n"
23410 "VAR_DEFINITION"
23411 "\n"
23412 "in vec4 tes_gs[];\n"
23413 "out vec4 gs_fs;\n"
23414 "\n"
23415 "void main()\n"
23416 "{\n"
23417 " vec4 result = tes_gs[0];\n"
23418 "\n"
23419 "VARIABLE_USE"
23420 "\n"
23421 " gs_fs = result;\n"
23422 " gl_Position = vec4(-1, -1, 0, 1);\n"
23423 " EmitVertex();\n"
23424 " gs_fs = result;\n"
23425 " gl_Position = vec4(-1, 1, 0, 1);\n"
23426 " EmitVertex();\n"
23427 " gs_fs = result;\n"
23428 " gl_Position = vec4(1, -1, 0, 1);\n"
23429 " EmitVertex();\n"
23430 " gs_fs = result;\n"
23431 " gl_Position = vec4(1, 1, 0, 1);\n"
23432 " EmitVertex();\n"
23433 "}\n"
23434 "\n";
23435 static const GLchar* tcs = "#version 430 core\n"
23436 "#extension GL_ARB_enhanced_layouts : require\n"
23437 "\n"
23438 "layout(vertices = 1) out;\n"
23439 "\n"
23440 "in vec4 vs_tcs[];\n"
23441 "out vec4 tcs_tes[];\n"
23442 "\n"
23443 "void main()\n"
23444 "{\n"
23445 "\n"
23446 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
23447 "\n"
23448 " gl_TessLevelOuter[0] = 1.0;\n"
23449 " gl_TessLevelOuter[1] = 1.0;\n"
23450 " gl_TessLevelOuter[2] = 1.0;\n"
23451 " gl_TessLevelOuter[3] = 1.0;\n"
23452 " gl_TessLevelInner[0] = 1.0;\n"
23453 " gl_TessLevelInner[1] = 1.0;\n"
23454 "}\n"
23455 "\n";
23456 static const GLchar* tcs_tested = "#version 430 core\n"
23457 "#extension GL_ARB_enhanced_layouts : require\n"
23458 "\n"
23459 "layout(vertices = 1) out;\n"
23460 "\n"
23461 "VAR_DEFINITION"
23462 "\n"
23463 "in vec4 vs_tcs[];\n"
23464 "out vec4 tcs_tes[];\n"
23465 "\n"
23466 "void main()\n"
23467 "{\n"
23468 " vec4 result = vs_tcs[gl_InvocationID];\n"
23469 "\n"
23470 "VARIABLE_USE"
23471 "\n"
23472 " tcs_tes[gl_InvocationID] = result;\n"
23473 "\n"
23474 " gl_TessLevelOuter[0] = 1.0;\n"
23475 " gl_TessLevelOuter[1] = 1.0;\n"
23476 " gl_TessLevelOuter[2] = 1.0;\n"
23477 " gl_TessLevelOuter[3] = 1.0;\n"
23478 " gl_TessLevelInner[0] = 1.0;\n"
23479 " gl_TessLevelInner[1] = 1.0;\n"
23480 "}\n"
23481 "\n";
23482 static const GLchar* tes_tested = "#version 430 core\n"
23483 "#extension GL_ARB_enhanced_layouts : require\n"
23484 "\n"
23485 "layout(isolines, point_mode) in;\n"
23486 "\n"
23487 "VAR_DEFINITION"
23488 "\n"
23489 "in vec4 tcs_tes[];\n"
23490 "out vec4 tes_gs;\n"
23491 "\n"
23492 "void main()\n"
23493 "{\n"
23494 " vec4 result = tcs_tes[0];\n"
23495 "\n"
23496 "VARIABLE_USE"
23497 "\n"
23498 " tes_gs += result;\n"
23499 "}\n"
23500 "\n";
23501 static const GLchar* vs = "#version 430 core\n"
23502 "#extension GL_ARB_enhanced_layouts : require\n"
23503 "\n"
23504 "in vec4 in_vs;\n"
23505 "out vec4 vs_tcs;\n"
23506 "\n"
23507 "void main()\n"
23508 "{\n"
23509 " vs_tcs = in_vs;\n"
23510 "}\n"
23511 "\n";
23512 static const GLchar* vs_tested = "#version 430 core\n"
23513 "#extension GL_ARB_enhanced_layouts : require\n"
23514 "\n"
23515 "VAR_DEFINITION"
23516 "\n"
23517 "in vec4 in_vs;\n"
23518 "out vec4 vs_tcs;\n"
23519 "\n"
23520 "void main()\n"
23521 "{\n"
23522 " vec4 result = in_vs;\n"
23523 "\n"
23524 "VARIABLE_USE"
23525 "\n"
23526 " vs_tcs = result;\n"
23527 "}\n"
23528 "\n";
23529
23530 std::string source;
23531 testCase& test_case = m_test_cases[test_case_index];
23532
23533 if (test_case.m_stage == stage)
23534 {
23535 const GLchar* array = "";
23536 GLchar buffer[16];
23537 const Functions& gl = m_context.getRenderContext().getFunctions();
23538 const GLchar* index = "";
23539 GLint max_n_xfb = 0;
23540 size_t position = 0;
23541 size_t temp;
23542 const GLchar* var_definition = 0;
23543 const GLchar* var_use = 0;
23544
23545 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_n_xfb);
23546 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23547
23548 sprintf(buffer, "%d", max_n_xfb);
23549
23550 switch (test_case.m_case)
23551 {
23552 case BLOCK:
23553 var_definition = block_var_definition;
23554 var_use = block_use;
23555 break;
23556 case GLOBAL:
23557 var_definition = global_var_definition;
23558 var_use = global_use;
23559 break;
23560 case VECTOR:
23561 var_definition = vector_var_definition;
23562 var_use = vector_use;
23563 break;
23564 default:
23565 TCU_FAIL("Invalid enum");
23566 }
23567
23568 switch (stage)
23569 {
23570 case Utils::Shader::GEOMETRY:
23571 source = gs_tested;
23572 array = "[]";
23573 index = "[0]";
23574 break;
23575 case Utils::Shader::TESS_CTRL:
23576 source = tcs_tested;
23577 array = "[]";
23578 index = "[gl_InvocationID]";
23579 break;
23580 case Utils::Shader::TESS_EVAL:
23581 source = tes_tested;
23582 array = "[]";
23583 index = "[0]";
23584 break;
23585 case Utils::Shader::VERTEX:
23586 source = vs_tested;
23587 break;
23588 default:
23589 TCU_FAIL("Invalid enum");
23590 }
23591
23592 temp = position;
23593 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23594 position = temp;
23595 Utils::replaceToken("BUFFER", position, buffer, source);
23596 if (GLOBAL != test_case.m_case)
23597 {
23598 Utils::replaceToken("ARRAY", position, array, source);
23599 }
23600 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23601
23602 Utils::replaceAllTokens("INDEX", index, source);
23603 }
23604 else
23605 {
23606 switch (test_case.m_stage)
23607 {
23608 case Utils::Shader::GEOMETRY:
23609 switch (stage)
23610 {
23611 case Utils::Shader::FRAGMENT:
23612 source = fs;
23613 break;
23614 case Utils::Shader::VERTEX:
23615 source = vs;
23616 break;
23617 default:
23618 source = "";
23619 }
23620 break;
23621 case Utils::Shader::TESS_CTRL:
23622 switch (stage)
23623 {
23624 case Utils::Shader::FRAGMENT:
23625 source = fs;
23626 break;
23627 case Utils::Shader::VERTEX:
23628 source = vs;
23629 break;
23630 default:
23631 source = "";
23632 }
23633 break;
23634 case Utils::Shader::TESS_EVAL:
23635 switch (stage)
23636 {
23637 case Utils::Shader::FRAGMENT:
23638 source = fs;
23639 break;
23640 case Utils::Shader::TESS_CTRL:
23641 source = tcs;
23642 break;
23643 case Utils::Shader::VERTEX:
23644 source = vs;
23645 break;
23646 default:
23647 source = "";
23648 }
23649 break;
23650 case Utils::Shader::VERTEX:
23651 switch (stage)
23652 {
23653 case Utils::Shader::FRAGMENT:
23654 source = fs;
23655 break;
23656 default:
23657 source = "";
23658 }
23659 break;
23660 default:
23661 TCU_FAIL("Invalid enum");
23662 break;
23663 }
23664 }
23665
23666 return source;
23667 }
23668
23669 /** Get description of test case
23670 *
23671 * @param test_case_index Index of test case
23672 *
23673 * @return Test case description
23674 **/
23675 std::string XFBExceedBufferLimitTest::getTestCaseName(GLuint test_case_index)
23676 {
23677 std::stringstream stream;
23678 testCase& test_case = m_test_cases[test_case_index];
23679
23680 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
23681
23682 switch (test_case.m_case)
23683 {
23684 case BLOCK:
23685 stream << "BLOCK";
23686 break;
23687 case GLOBAL:
23688 stream << "GLOBAL";
23689 break;
23690 case VECTOR:
23691 stream << "VECTOR";
23692 break;
23693 default:
23694 TCU_FAIL("Invalid enum");
23695 }
23696
23697 return stream.str();
23698 }
23699
23700 /** Get number of test cases
23701 *
23702 * @return Number of test cases
23703 **/
23704 GLuint XFBExceedBufferLimitTest::getTestCaseNumber()
23705 {
23706 return static_cast<GLuint>(m_test_cases.size());
23707 }
23708
23709 /** Selects if "compute" stage is relevant for test
23710 *
23711 * @param ignored
23712 *
23713 * @return false
23714 **/
23715 bool XFBExceedBufferLimitTest::isComputeRelevant(GLuint /* test_case_index */)
23716 {
23717 return false;
23718 }
23719
23720 /** Prepare all test cases
23721 *
23722 **/
23723 void XFBExceedBufferLimitTest::testInit()
23724 {
23725 for (GLuint c = 0; c < CASE_MAX; ++c)
23726 {
23727 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
23728 {
23729 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
23730 (Utils::Shader::FRAGMENT == stage))
23731 {
23732 continue;
23733 }
23734
23735 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
23736
23737 m_test_cases.push_back(test_case);
23738 }
23739 }
23740 }
23741
23742 /** Constructor
23743 *
23744 * @param context Test framework context
23745 **/
23746 XFBExceedOffsetLimitTest::XFBExceedOffsetLimitTest(deqp::Context& context)
23747 : NegativeTestBase(context, "xfb_exceed_offset_limit",
23748 "Test verifies that compiler reports error when xfb_offset qualifier exceeds limit")
23749 {
23750 }
23751
23752 /** Source for given test case and stage
23753 *
23754 * @param test_case_index Index of test case
23755 * @param stage Shader stage
23756 *
23757 * @return Shader source
23758 **/
23759 std::string XFBExceedOffsetLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
23760 {
23761 static const GLchar* block_var_definition = "const uint max_size = SIZE;\n"
23762 "\n"
23763 "layout (xfb_buffer = 0, xfb_offset = max_size + 16) out Goku {\n"
23764 " vec4 member;\n"
23765 "} gokuARRAY;\n";
23766 static const GLchar* global_var_definition = "const uint max_size = SIZE;\n"
23767 "\n"
23768 "layout (xfb_buffer = 0, xfb_stride = max_size + 16) out;\n";
23769 static const GLchar* vector_var_definition =
23770 "const uint max_size = SIZE;\n"
23771 "\n"
23772 "layout (xfb_buffer = 0, xfb_offset = max_size + 16) out vec4 gokuARRAY;\n";
23773 static const GLchar* block_use = " gokuINDEX.member = result / 2;\n";
23774 static const GLchar* global_use = "";
23775 static const GLchar* vector_use = " gokuINDEX = result / 2;\n";
23776 static const GLchar* fs = "#version 430 core\n"
23777 "#extension GL_ARB_enhanced_layouts : require\n"
23778 "\n"
23779 "in vec4 gs_fs;\n"
23780 "out vec4 fs_out;\n"
23781 "\n"
23782 "void main()\n"
23783 "{\n"
23784 " fs_out = gs_fs;\n"
23785 "}\n"
23786 "\n";
23787 static const GLchar* gs_tested = "#version 430 core\n"
23788 "#extension GL_ARB_enhanced_layouts : require\n"
23789 "\n"
23790 "layout(points) in;\n"
23791 "layout(triangle_strip, max_vertices = 4) out;\n"
23792 "\n"
23793 "VAR_DEFINITION"
23794 "\n"
23795 "in vec4 tes_gs[];\n"
23796 "out vec4 gs_fs;\n"
23797 "\n"
23798 "void main()\n"
23799 "{\n"
23800 " vec4 result = tes_gs[0];\n"
23801 "\n"
23802 "VARIABLE_USE"
23803 "\n"
23804 " gs_fs = result;\n"
23805 " gl_Position = vec4(-1, -1, 0, 1);\n"
23806 " EmitVertex();\n"
23807 " gs_fs = result;\n"
23808 " gl_Position = vec4(-1, 1, 0, 1);\n"
23809 " EmitVertex();\n"
23810 " gs_fs = result;\n"
23811 " gl_Position = vec4(1, -1, 0, 1);\n"
23812 " EmitVertex();\n"
23813 " gs_fs = result;\n"
23814 " gl_Position = vec4(1, 1, 0, 1);\n"
23815 " EmitVertex();\n"
23816 "}\n"
23817 "\n";
23818 static const GLchar* tcs = "#version 430 core\n"
23819 "#extension GL_ARB_enhanced_layouts : require\n"
23820 "\n"
23821 "layout(vertices = 1) out;\n"
23822 "\n"
23823 "in vec4 vs_tcs[];\n"
23824 "out vec4 tcs_tes[];\n"
23825 "\n"
23826 "void main()\n"
23827 "{\n"
23828 "\n"
23829 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
23830 "\n"
23831 " gl_TessLevelOuter[0] = 1.0;\n"
23832 " gl_TessLevelOuter[1] = 1.0;\n"
23833 " gl_TessLevelOuter[2] = 1.0;\n"
23834 " gl_TessLevelOuter[3] = 1.0;\n"
23835 " gl_TessLevelInner[0] = 1.0;\n"
23836 " gl_TessLevelInner[1] = 1.0;\n"
23837 "}\n"
23838 "\n";
23839 static const GLchar* tcs_tested = "#version 430 core\n"
23840 "#extension GL_ARB_enhanced_layouts : require\n"
23841 "\n"
23842 "layout(vertices = 1) out;\n"
23843 "\n"
23844 "VAR_DEFINITION"
23845 "\n"
23846 "in vec4 vs_tcs[];\n"
23847 "out vec4 tcs_tes[];\n"
23848 "\n"
23849 "void main()\n"
23850 "{\n"
23851 " vec4 result = vs_tcs[gl_InvocationID];\n"
23852 "\n"
23853 "VARIABLE_USE"
23854 "\n"
23855 " tcs_tes[gl_InvocationID] = result;\n"
23856 "\n"
23857 " gl_TessLevelOuter[0] = 1.0;\n"
23858 " gl_TessLevelOuter[1] = 1.0;\n"
23859 " gl_TessLevelOuter[2] = 1.0;\n"
23860 " gl_TessLevelOuter[3] = 1.0;\n"
23861 " gl_TessLevelInner[0] = 1.0;\n"
23862 " gl_TessLevelInner[1] = 1.0;\n"
23863 "}\n"
23864 "\n";
23865 static const GLchar* tes_tested = "#version 430 core\n"
23866 "#extension GL_ARB_enhanced_layouts : require\n"
23867 "\n"
23868 "layout(isolines, point_mode) in;\n"
23869 "\n"
23870 "VAR_DEFINITION"
23871 "\n"
23872 "in vec4 tcs_tes[];\n"
23873 "out vec4 tes_gs;\n"
23874 "\n"
23875 "void main()\n"
23876 "{\n"
23877 " vec4 result = tcs_tes[0];\n"
23878 "\n"
23879 "VARIABLE_USE"
23880 "\n"
23881 " tes_gs += result;\n"
23882 "}\n"
23883 "\n";
23884 static const GLchar* vs = "#version 430 core\n"
23885 "#extension GL_ARB_enhanced_layouts : require\n"
23886 "\n"
23887 "in vec4 in_vs;\n"
23888 "out vec4 vs_tcs;\n"
23889 "\n"
23890 "void main()\n"
23891 "{\n"
23892 " vs_tcs = in_vs;\n"
23893 "}\n"
23894 "\n";
23895 static const GLchar* vs_tested = "#version 430 core\n"
23896 "#extension GL_ARB_enhanced_layouts : require\n"
23897 "\n"
23898 "VAR_DEFINITION"
23899 "\n"
23900 "in vec4 in_vs;\n"
23901 "out vec4 vs_tcs;\n"
23902 "\n"
23903 "void main()\n"
23904 "{\n"
23905 " vec4 result = in_vs;\n"
23906 "\n"
23907 "VARIABLE_USE"
23908 "\n"
23909 " vs_tcs = result;\n"
23910 "}\n"
23911 "\n";
23912
23913 std::string source;
23914 testCase& test_case = m_test_cases[test_case_index];
23915
23916 if (test_case.m_stage == stage)
23917 {
23918 const GLchar* array = "";
23919 GLchar buffer[16];
23920 const Functions& gl = m_context.getRenderContext().getFunctions();
23921 const GLchar* index = "";
23922 GLint max_n_xfb_comp = 0;
23923 GLint max_n_xfb_bytes = 0;
23924 size_t position = 0;
23925 size_t temp;
23926 const GLchar* var_definition = 0;
23927 const GLchar* var_use = 0;
23928
23929 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_n_xfb_comp);
23930 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23931
23932 max_n_xfb_bytes = max_n_xfb_comp * 4;
23933
23934 sprintf(buffer, "%d", max_n_xfb_bytes);
23935
23936 switch (test_case.m_case)
23937 {
23938 case BLOCK:
23939 var_definition = block_var_definition;
23940 var_use = block_use;
23941 break;
23942 case GLOBAL:
23943 var_definition = global_var_definition;
23944 var_use = global_use;
23945 break;
23946 case VECTOR:
23947 var_definition = vector_var_definition;
23948 var_use = vector_use;
23949 break;
23950 default:
23951 TCU_FAIL("Invalid enum");
23952 }
23953 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
23954 // change array = "[]" to "[1]"
23955 switch (stage)
23956 {
23957 case Utils::Shader::GEOMETRY:
23958 source = gs_tested;
23959 array = "[1]";
23960 index = "[0]";
23961 break;
23962 case Utils::Shader::TESS_CTRL:
23963 source = tcs_tested;
23964 array = "[1]";
23965 index = "[gl_InvocationID]";
23966 break;
23967 case Utils::Shader::TESS_EVAL:
23968 source = tes_tested;
23969 array = "[1]";
23970 index = "[0]";
23971 break;
23972 case Utils::Shader::VERTEX:
23973 source = vs_tested;
23974 break;
23975 default:
23976 TCU_FAIL("Invalid enum");
23977 }
23978
23979 temp = position;
23980 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23981 position = temp;
23982 Utils::replaceToken("SIZE", position, buffer, source);
23983 if (GLOBAL != test_case.m_case)
23984 {
23985 Utils::replaceToken("ARRAY", position, array, source);
23986 }
23987 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23988
23989 Utils::replaceAllTokens("INDEX", index, source);
23990 }
23991 else
23992 {
23993 switch (test_case.m_stage)
23994 {
23995 case Utils::Shader::GEOMETRY:
23996 switch (stage)
23997 {
23998 case Utils::Shader::FRAGMENT:
23999 source = fs;
24000 break;
24001 case Utils::Shader::VERTEX:
24002 source = vs;
24003 break;
24004 default:
24005 source = "";
24006 }
24007 break;
24008 case Utils::Shader::TESS_CTRL:
24009 switch (stage)
24010 {
24011 case Utils::Shader::FRAGMENT:
24012 source = fs;
24013 break;
24014 case Utils::Shader::VERTEX:
24015 source = vs;
24016 break;
24017 default:
24018 source = "";
24019 }
24020 break;
24021 case Utils::Shader::TESS_EVAL:
24022 switch (stage)
24023 {
24024 case Utils::Shader::FRAGMENT:
24025 source = fs;
24026 break;
24027 case Utils::Shader::TESS_CTRL:
24028 source = tcs;
24029 break;
24030 case Utils::Shader::VERTEX:
24031 source = vs;
24032 break;
24033 default:
24034 source = "";
24035 }
24036 break;
24037 case Utils::Shader::VERTEX:
24038 switch (stage)
24039 {
24040 case Utils::Shader::FRAGMENT:
24041 source = fs;
24042 break;
24043 default:
24044 source = "";
24045 }
24046 break;
24047 default:
24048 TCU_FAIL("Invalid enum");
24049 break;
24050 }
24051 }
24052
24053 return source;
24054 }
24055
24056 /** Get description of test case
24057 *
24058 * @param test_case_index Index of test case
24059 *
24060 * @return Test case description
24061 **/
24062 std::string XFBExceedOffsetLimitTest::getTestCaseName(GLuint test_case_index)
24063 {
24064 std::stringstream stream;
24065 testCase& test_case = m_test_cases[test_case_index];
24066
24067 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
24068
24069 switch (test_case.m_case)
24070 {
24071 case BLOCK:
24072 stream << "BLOCK";
24073 break;
24074 case GLOBAL:
24075 stream << "GLOBAL";
24076 break;
24077 case VECTOR:
24078 stream << "VECTOR";
24079 break;
24080 default:
24081 TCU_FAIL("Invalid enum");
24082 }
24083
24084 return stream.str();
24085 }
24086
24087 /** Get number of test cases
24088 *
24089 * @return Number of test cases
24090 **/
24091 GLuint XFBExceedOffsetLimitTest::getTestCaseNumber()
24092 {
24093 return static_cast<GLuint>(m_test_cases.size());
24094 }
24095
24096 /** Selects if "compute" stage is relevant for test
24097 *
24098 * @param ignored
24099 *
24100 * @return false
24101 **/
24102 bool XFBExceedOffsetLimitTest::isComputeRelevant(GLuint /* test_case_index */)
24103 {
24104 return false;
24105 }
24106
24107 /** Prepare all test cases
24108 *
24109 **/
24110 void XFBExceedOffsetLimitTest::testInit()
24111 {
24112 for (GLuint c = 0; c < CASE_MAX; ++c)
24113 {
24114 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24115 {
24116 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
24117 (Utils::Shader::FRAGMENT == stage))
24118 {
24119 continue;
24120 }
24121
24122 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
24123
24124 m_test_cases.push_back(test_case);
24125 }
24126 }
24127 }
24128
24129 /** Constructor
24130 *
24131 * @param context Test context
24132 **/
24133 XFBGlobalBufferTest::XFBGlobalBufferTest(deqp::Context& context)
24134 : BufferTestBase(context, "xfb_global_buffer", "Test verifies that global xfb_buffer qualifier is respected")
24135 {
24136 /* Nothing to be done here */
24137 }
24138
24139 /** Get descriptors of buffers necessary for test
24140 *
24141 * @param test_case_index Index of test case
24142 * @param out_descriptors Descriptors of buffers used by test
24143 **/
24144 void XFBGlobalBufferTest::getBufferDescriptors(glw::GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24145 {
24146 // the function "getType(test_case_index)" can't return correct data type, so change code as following:
24147 const Utils::Type& type = m_test_cases[test_case_index].m_type;
24148
24149 /* Test needs single uniform and two xfbs */
24150 out_descriptors.resize(3);
24151
24152 /* Get references */
24153 bufferDescriptor& uniform = out_descriptors[0];
24154 bufferDescriptor& xfb_1 = out_descriptors[1];
24155 bufferDescriptor& xfb_3 = out_descriptors[2];
24156
24157 /* Index */
24158 uniform.m_index = 0;
24159 xfb_1.m_index = 1;
24160 xfb_3.m_index = 3;
24161
24162 /* Target */
24163 uniform.m_target = Utils::Buffer::Uniform;
24164 xfb_1.m_target = Utils::Buffer::Transform_feedback;
24165 xfb_3.m_target = Utils::Buffer::Transform_feedback;
24166
24167 /* Data */
24168 const GLuint gen_start = Utils::s_rand;
24169 const std::vector<GLubyte>& chichi_data = type.GenerateData();
24170 const std::vector<GLubyte>& bulma_data = type.GenerateData();
24171 const std::vector<GLubyte>& trunks_data = type.GenerateData();
24172 const std::vector<GLubyte>& bra_data = type.GenerateData();
24173 const std::vector<GLubyte>& gohan_data = type.GenerateData();
24174 const std::vector<GLubyte>& goten_data = type.GenerateData();
24175
24176 Utils::s_rand = gen_start;
24177 const std::vector<GLubyte>& chichi_data_pck = type.GenerateDataPacked();
24178 const std::vector<GLubyte>& bulma_data_pck = type.GenerateDataPacked();
24179 const std::vector<GLubyte>& trunks_data_pck = type.GenerateDataPacked();
24180 const std::vector<GLubyte>& bra_data_pck = type.GenerateDataPacked();
24181 const std::vector<GLubyte>& gohan_data_pck = type.GenerateDataPacked();
24182 const std::vector<GLubyte>& goten_data_pck = type.GenerateDataPacked();
24183
24184 const GLuint type_size = static_cast<GLuint>(chichi_data.size());
24185 const GLuint type_size_pck = static_cast<GLuint>(chichi_data_pck.size());
24186
24187 /* Uniform data */
24188 uniform.m_initial_data.resize(6 * type_size);
24189 memcpy(&uniform.m_initial_data[0] + 0, &chichi_data[0], type_size);
24190 memcpy(&uniform.m_initial_data[0] + type_size, &bulma_data[0], type_size);
24191 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &trunks_data[0], type_size);
24192 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &bra_data[0], type_size);
24193 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &gohan_data[0], type_size);
24194 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &goten_data[0], type_size);
24195
24196 /* XFB data */
24197 xfb_1.m_initial_data.resize(3 * type_size_pck);
24198 xfb_1.m_expected_data.resize(3 * type_size_pck);
24199 xfb_3.m_initial_data.resize(3 * type_size_pck);
24200 xfb_3.m_expected_data.resize(3 * type_size_pck);
24201
24202 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
24203 {
24204 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
24205 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
24206 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
24207 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
24208 }
24209
24210 memcpy(&xfb_3.m_expected_data[0] + 2 * type_size_pck, &chichi_data_pck[0], type_size_pck);
24211 memcpy(&xfb_1.m_expected_data[0] + 0 * type_size_pck, &bulma_data_pck[0], type_size_pck);
24212 memcpy(&xfb_1.m_expected_data[0] + 1 * type_size_pck, &trunks_data_pck[0], type_size_pck);
24213 memcpy(&xfb_1.m_expected_data[0] + 2 * type_size_pck, &bra_data_pck[0], type_size_pck);
24214 memcpy(&xfb_3.m_expected_data[0] + 0 * type_size_pck, &gohan_data_pck[0], type_size_pck);
24215 memcpy(&xfb_3.m_expected_data[0] + 1 * type_size_pck, &goten_data_pck[0], type_size_pck);
24216 }
24217
24218 /** Source for given test case and stage
24219 *
24220 * @param test_case_index Index of test case
24221 * @param stage Shader stage
24222 *
24223 * @return Shader source
24224 **/
24225 std::string XFBGlobalBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24226 {
24227 static const GLchar* fs =
24228 "#version 430 core\n"
24229 "#extension GL_ARB_enhanced_layouts : require\n"
24230 "\n"
24231 "flat in TYPE chichi;\n"
24232 "flat in TYPE bulma;\n"
24233 "in Vegeta {\n"
24234 " flat TYPE trunk;\n"
24235 " flat TYPE bra;\n"
24236 "} vegeta;\n"
24237 "in Goku {\n"
24238 " flat TYPE gohan;\n"
24239 " flat TYPE goten;\n"
24240 "} goku;\n"
24241 "\n"
24242 "out vec4 fs_out;\n"
24243 "\n"
24244 "void main()\n"
24245 "{\n"
24246 " fs_out = vec4(1);\n"
24247 " if (TYPE(1) != chichi + bulma + vegeta.trunk + vegeta.bra + goku.gohan + goku.goten)\n"
24248 " {\n"
24249 " fs_out = vec4(0);\n"
24250 " }\n"
24251 "}\n"
24252 "\n";
24253
24254 static const GLchar* gs = "#version 430 core\n"
24255 "#extension GL_ARB_enhanced_layouts : require\n"
24256 "\n"
24257 "layout(points) in;\n"
24258 "layout(points, max_vertices = 1) out;\n"
24259 "\n"
24260 "INTERFACE"
24261 "\n"
24262 "void main()\n"
24263 "{\n"
24264 "ASSIGNMENTS"
24265 " EmitVertex();\n"
24266 "}\n"
24267 "\n";
24268
24269 static const GLchar* tcs = "#version 430 core\n"
24270 "#extension GL_ARB_enhanced_layouts : require\n"
24271 "\n"
24272 "layout(vertices = 1) out;\n"
24273 "\n"
24274 "\n"
24275 "void main()\n"
24276 "{\n"
24277 " gl_TessLevelOuter[0] = 1.0;\n"
24278 " gl_TessLevelOuter[1] = 1.0;\n"
24279 " gl_TessLevelOuter[2] = 1.0;\n"
24280 " gl_TessLevelOuter[3] = 1.0;\n"
24281 " gl_TessLevelInner[0] = 1.0;\n"
24282 " gl_TessLevelInner[1] = 1.0;\n"
24283 "}\n"
24284 "\n";
24285
24286 static const GLchar* tes = "#version 430 core\n"
24287 "#extension GL_ARB_enhanced_layouts : require\n"
24288 "\n"
24289 "layout(isolines, point_mode) in;\n"
24290 "\n"
24291 "INTERFACE"
24292 "\n"
24293 "void main()\n"
24294 "{\n"
24295 "ASSIGNMENTS"
24296 "}\n"
24297 "\n";
24298
24299 static const GLchar* vs = "#version 430 core\n"
24300 "#extension GL_ARB_enhanced_layouts : require\n"
24301 "\n"
24302 "void main()\n"
24303 "{\n"
24304 "}\n"
24305 "\n";
24306
24307 static const GLchar* vs_tested = "#version 430 core\n"
24308 "#extension GL_ARB_enhanced_layouts : require\n"
24309 "\n"
24310 "INTERFACE"
24311 "\n"
24312 "void main()\n"
24313 "{\n"
24314 "ASSIGNMENTS"
24315 "}\n"
24316 "\n";
24317
24318 std::string source;
24319 const _testCase& test_case = m_test_cases[test_case_index];
24320 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
24321
24322 if (test_case.m_stage == stage)
24323 {
24324 std::string assignments = " chichi = uni_chichi;\n"
24325 " bulma = uni_bulma;\n"
24326 " vegeta.trunk = uni_trunk;\n"
24327 " vegeta.bra = uni_bra;\n"
24328 " goku.gohan = uni_gohan;\n"
24329 " goku.goten = uni_goten;\n";
24330
24331 std::string interface = "layout (xfb_buffer = 3) out;\n"
24332 "\n"
24333 "const uint type_size = SIZE;\n"
24334 "\n"
24335 "layout ( xfb_offset = 2 * type_size) flat out TYPE chichi;\n"
24336 "layout (xfb_buffer = 1, xfb_offset = 0) flat out TYPE bulma;\n"
24337 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out Vegeta {\n"
24338 " flat TYPE trunk;\n"
24339 " flat TYPE bra;\n"
24340 "} vegeta;\n"
24341 "layout ( xfb_offset = 0) out Goku {\n"
24342 " flat TYPE gohan;\n"
24343 " flat TYPE goten;\n"
24344 "} goku;\n"
24345 "\n"
24346 // Uniform block must be declared with std140, otherwise each block member is not packed
24347 "layout(binding = 0, std140) uniform block {\n"
24348 " TYPE uni_chichi;\n"
24349 " TYPE uni_bulma;\n"
24350 " TYPE uni_trunk;\n"
24351 " TYPE uni_bra;\n"
24352 " TYPE uni_gohan;\n"
24353 " TYPE uni_goten;\n"
24354 "};\n";
24355
24356 /* Prepare interface string */
24357 {
24358 GLchar buffer[16];
24359 size_t position = 0;
24360 const GLuint type_size = test_case.m_type.GetSize();
24361
24362 sprintf(buffer, "%d", type_size);
24363
24364 Utils::replaceToken("SIZE", position, buffer, interface);
24365 Utils::replaceAllTokens("TYPE", type_name, interface);
24366 }
24367
24368 switch (stage)
24369 {
24370 case Utils::Shader::GEOMETRY:
24371 source = gs;
24372 break;
24373 case Utils::Shader::TESS_EVAL:
24374 source = tes;
24375 break;
24376 case Utils::Shader::VERTEX:
24377 source = vs_tested;
24378 break;
24379 default:
24380 TCU_FAIL("Invalid enum");
24381 }
24382
24383 /* Replace tokens */
24384 {
24385 size_t position = 0;
24386
24387 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
24388 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
24389 }
24390 }
24391 else
24392 {
24393 switch (test_case.m_stage)
24394 {
24395 case Utils::Shader::GEOMETRY:
24396 switch (stage)
24397 {
24398 case Utils::Shader::FRAGMENT:
24399 source = fs;
24400 Utils::replaceAllTokens("TYPE", type_name, source);
24401 break;
24402 case Utils::Shader::VERTEX:
24403 source = vs;
24404 break;
24405 default:
24406 source = "";
24407 }
24408 break;
24409 case Utils::Shader::TESS_EVAL:
24410 switch (stage)
24411 {
24412 case Utils::Shader::FRAGMENT:
24413 source = fs;
24414 Utils::replaceAllTokens("TYPE", type_name, source);
24415 break;
24416 case Utils::Shader::TESS_CTRL:
24417 source = tcs;
24418 break;
24419 case Utils::Shader::VERTEX:
24420 source = vs;
24421 break;
24422 default:
24423 source = "";
24424 }
24425 break;
24426 case Utils::Shader::VERTEX:
24427 switch (stage)
24428 {
24429 case Utils::Shader::FRAGMENT:
24430 source = fs;
24431 Utils::replaceAllTokens("TYPE", type_name, source);
24432 break;
24433 default:
24434 source = "";
24435 }
24436 break;
24437 default:
24438 TCU_FAIL("Invalid enum");
24439 break;
24440 }
24441 }
24442
24443 return source;
24444 }
24445
24446 /** Get name of test case
24447 *
24448 * @param test_case_index Index of test case
24449 *
24450 * @return Name of case
24451 **/
24452 std::string XFBGlobalBufferTest::getTestCaseName(GLuint test_case_index)
24453 {
24454 std::string name;
24455 const _testCase& test_case = m_test_cases[test_case_index];
24456
24457 name = "Tested stage: ";
24458 name.append(Utils::Shader::GetStageName(test_case.m_stage));
24459 name.append(". Tested type: ");
24460 name.append(test_case.m_type.GetGLSLTypeName());
24461
24462 return name;
24463 }
24464
24465 /** Get number of cases
24466 *
24467 * @return Number of test cases
24468 **/
24469 GLuint XFBGlobalBufferTest::getTestCaseNumber()
24470 {
24471 return static_cast<GLuint>(m_test_cases.size());
24472 }
24473
24474 /** Prepare set of test cases
24475 *
24476 **/
24477 void XFBGlobalBufferTest::testInit()
24478 {
24479 GLuint n_types = getTypesNumber();
24480
24481 for (GLuint i = 0; i < n_types; ++i)
24482 {
24483 const Utils::Type& type = getType(i);
24484 /*
24485 When the tfx varying is the following type, the number of output exceeds the gl_MaxVaryingComponents, which will
24486 cause a link time error.
24487 */
24488 if (strcmp(type.GetGLSLTypeName(), "dmat3") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4") == 0 ||
24489 strcmp(type.GetGLSLTypeName(), "dmat3x4") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4x3") == 0)
24490 {
24491 continue;
24492 }
24493 const _testCase test_cases[] = { { Utils::Shader::VERTEX, type },
24494 { Utils::Shader::GEOMETRY, type },
24495 { Utils::Shader::TESS_EVAL, type } };
24496
24497 m_test_cases.push_back(test_cases[0]);
24498 m_test_cases.push_back(test_cases[1]);
24499 m_test_cases.push_back(test_cases[2]);
24500 }
24501 }
24502
24503 /** Constructor
24504 *
24505 * @param context Test context
24506 **/
24507 XFBStrideTest::XFBStrideTest(deqp::Context& context)
24508 : BufferTestBase(context, "xfb_stride", "Test verifies that correct stride is used for all types")
24509 {
24510 /* Nothing to be done here */
24511 }
24512
24513 /** Execute drawArrays for single vertex
24514 *
24515 * @param test_case_index
24516 *
24517 * @return true
24518 **/
24519 bool XFBStrideTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
24520 {
24521 const Functions& gl = m_context.getRenderContext().getFunctions();
24522 GLenum primitive_type = GL_PATCHES;
24523 const testCase& test_case = m_test_cases[test_case_index];
24524
24525 if (Utils::Shader::VERTEX == test_case.m_stage)
24526 {
24527 primitive_type = GL_POINTS;
24528 }
24529
24530 gl.disable(GL_RASTERIZER_DISCARD);
24531 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
24532
24533 gl.beginTransformFeedback(GL_POINTS);
24534 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
24535
24536 gl.drawArrays(primitive_type, 0 /* first */, 2 /* count */);
24537 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
24538
24539 gl.endTransformFeedback();
24540 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
24541
24542 return true;
24543 }
24544
24545 /** Get descriptors of buffers necessary for test
24546 *
24547 * @param test_case_index Index of test case
24548 * @param out_descriptors Descriptors of buffers used by test
24549 **/
24550 void XFBStrideTest::getBufferDescriptors(GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24551 {
24552 const testCase& test_case = m_test_cases[test_case_index];
24553 const Utils::Type& type = test_case.m_type;
24554
24555 /* Test needs single uniform and xfb */
24556 out_descriptors.resize(2);
24557
24558 /* Get references */
24559 bufferDescriptor& uniform = out_descriptors[0];
24560 bufferDescriptor& xfb = out_descriptors[1];
24561
24562 /* Index */
24563 uniform.m_index = 0;
24564 xfb.m_index = 0;
24565
24566 /* Target */
24567 uniform.m_target = Utils::Buffer::Uniform;
24568 xfb.m_target = Utils::Buffer::Transform_feedback;
24569
24570 /* Data */
24571 const GLuint rand_start = Utils::s_rand;
24572 const std::vector<GLubyte>& uniform_data = type.GenerateData();
24573
24574 Utils::s_rand = rand_start;
24575 const std::vector<GLubyte>& xfb_data = type.GenerateDataPacked();
24576
24577 const GLuint uni_type_size = static_cast<GLuint>(uniform_data.size());
24578 const GLuint xfb_type_size = static_cast<GLuint>(xfb_data.size());
24579 /*
24580 Note: If xfb varying output from vertex shader, the variable "goku" will only output once to transform feedback buffer,
24581 if xfb varying output from TES or GS, because the input primitive type in TES is defined as "layout(isolines, point_mode) in;",
24582 the primitive type is line which make the variable "goku" will output twice to transform feedback buffer, so for vertex shader
24583 only one valid data should be initialized in xfb.m_expected_data
24584 */
24585 const GLuint xfb_data_size = (test_case.m_stage == Utils::Shader::VERTEX) ? xfb_type_size : xfb_type_size * 2;
24586 /* Uniform data */
24587 uniform.m_initial_data.resize(uni_type_size);
24588 memcpy(&uniform.m_initial_data[0] + 0 * uni_type_size, &uniform_data[0], uni_type_size);
24589
24590 /* XFB data */
24591 xfb.m_initial_data.resize(xfb_data_size);
24592 xfb.m_expected_data.resize(xfb_data_size);
24593
24594 for (GLuint i = 0; i < xfb_data_size; ++i)
24595 {
24596 xfb.m_initial_data[i] = (glw::GLubyte)i;
24597 xfb.m_expected_data[i] = (glw::GLubyte)i;
24598 }
24599
24600 if (test_case.m_stage == Utils::Shader::VERTEX)
24601 {
24602 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24603 }
24604 else
24605 {
24606 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24607 memcpy(&xfb.m_expected_data[0] + 1 * xfb_type_size, &xfb_data[0], xfb_type_size);
24608 }
24609 }
24610
24611 /** Get body of main function for given shader stage
24612 *
24613 * @param test_case_index Index of test case
24614 * @param stage Shader stage
24615 * @param out_assignments Set to empty
24616 * @param out_calculations Set to empty
24617 **/
24618 void XFBStrideTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_assignments,
24619 std::string& out_calculations)
24620 {
24621 const testCase& test_case = m_test_cases[test_case_index];
24622
24623 out_calculations = "";
24624
24625 static const GLchar* vs_tes_gs = " goku = uni_goku;\n";
24626 static const GLchar* fs = " fs_out = vec4(1, 0.25, 0.5, 0.75);\n"
24627 " if (TYPE(0) == goku)\n"
24628 " {\n"
24629 " fs_out = vec4(1, 0.75, 0.5, 0.5);\n"
24630 " }\n";
24631
24632 const GLchar* assignments = "";
24633
24634 if (test_case.m_stage == stage)
24635 {
24636 switch (stage)
24637 {
24638 case Utils::Shader::GEOMETRY:
24639 assignments = vs_tes_gs;
24640 break;
24641 case Utils::Shader::TESS_EVAL:
24642 assignments = vs_tes_gs;
24643 break;
24644 case Utils::Shader::VERTEX:
24645 assignments = vs_tes_gs;
24646 break;
24647 default:
24648 TCU_FAIL("Invalid enum");
24649 }
24650 }
24651 else
24652 {
24653 switch (stage)
24654 {
24655 case Utils::Shader::FRAGMENT:
24656 assignments = fs;
24657 break;
24658 case Utils::Shader::GEOMETRY:
24659 case Utils::Shader::TESS_CTRL:
24660 case Utils::Shader::TESS_EVAL:
24661 case Utils::Shader::VERTEX:
24662 break;
24663 default:
24664 TCU_FAIL("Invalid enum");
24665 }
24666 }
24667
24668 out_assignments = assignments;
24669
24670 if (Utils::Shader::FRAGMENT == stage)
24671 {
24672 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_assignments);
24673 }
24674 }
24675
24676 /** Get interface of shader
24677 *
24678 * @param test_case_index Index of test case
24679 * @param stage Shader stage
24680 * @param out_interface Set to ""
24681 **/
24682 void XFBStrideTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_interface)
24683 {
24684 static const GLchar* vs_tes_gs = "layout (xfb_offset = 0) FLAT out TYPE goku;\n"
24685 "\n"
24686 "layout(std140, binding = 0) uniform Goku {\n"
24687 " TYPE uni_goku;\n"
24688 "};\n";
24689 static const GLchar* fs = "FLAT in TYPE goku;\n"
24690 "\n"
24691 "out vec4 fs_out;\n";
24692
24693 const testCase& test_case = m_test_cases[test_case_index];
24694 const GLchar* interface = "";
24695 const GLchar* flat = "";
24696
24697 if (test_case.m_stage == stage)
24698 {
24699 switch (stage)
24700 {
24701 case Utils::Shader::GEOMETRY:
24702 interface = vs_tes_gs;
24703 break;
24704 case Utils::Shader::TESS_EVAL:
24705 interface = vs_tes_gs;
24706 break;
24707 case Utils::Shader::VERTEX:
24708 interface = vs_tes_gs;
24709 break;
24710 default:
24711 TCU_FAIL("Invalid enum");
24712 }
24713 }
24714 else
24715 {
24716 switch (stage)
24717 {
24718 case Utils::Shader::FRAGMENT:
24719 interface = fs;
24720 break;
24721 case Utils::Shader::GEOMETRY:
24722 case Utils::Shader::TESS_CTRL:
24723 case Utils::Shader::TESS_EVAL:
24724 case Utils::Shader::VERTEX:
24725 break;
24726 default:
24727 TCU_FAIL("Invalid enum");
24728 }
24729 }
24730
24731 out_interface = interface;
24732
24733 if (Utils::Type::Float != test_case.m_type.m_basic_type)
24734 {
24735 flat = "flat";
24736 }
24737
24738 Utils::replaceAllTokens("FLAT", flat, out_interface);
24739 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_interface);
24740 }
24741
24742 /** Get source code of shader
24743 *
24744 * @param test_case_index Index of test case
24745 * @param stage Shader stage
24746 *
24747 * @return Source
24748 **/
24749 std::string XFBStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24750 {
24751 std::string source;
24752 const testCase& test_case = m_test_cases[test_case_index];
24753
24754 switch (test_case.m_stage)
24755 {
24756 case Utils::Shader::VERTEX:
24757 switch (stage)
24758 {
24759 case Utils::Shader::FRAGMENT:
24760 case Utils::Shader::VERTEX:
24761 source = BufferTestBase::getShaderSource(test_case_index, stage);
24762 break;
24763 default:
24764 break;
24765 }
24766 break;
24767
24768 case Utils::Shader::TESS_EVAL:
24769 switch (stage)
24770 {
24771 case Utils::Shader::FRAGMENT:
24772 case Utils::Shader::TESS_CTRL:
24773 case Utils::Shader::TESS_EVAL:
24774 case Utils::Shader::VERTEX:
24775 source = BufferTestBase::getShaderSource(test_case_index, stage);
24776 break;
24777 default:
24778 break;
24779 }
24780 break;
24781
24782 case Utils::Shader::GEOMETRY:
24783 source = BufferTestBase::getShaderSource(test_case_index, stage);
24784 break;
24785
24786 default:
24787 TCU_FAIL("Invalid enum");
24788 break;
24789 }
24790
24791 /* */
24792 return source;
24793 }
24794
24795 /** Get name of test case
24796 *
24797 * @param test_case_index Index of test case
24798 *
24799 * @return Name of tested stage
24800 **/
24801 std::string XFBStrideTest::getTestCaseName(glw::GLuint test_case_index)
24802 {
24803 std::stringstream stream;
24804 const testCase& test_case = m_test_cases[test_case_index];
24805
24806 stream << "Type: " << test_case.m_type.GetGLSLTypeName()
24807 << ", stage: " << Utils::Shader::GetStageName(test_case.m_stage);
24808
24809 return stream.str();
24810 }
24811
24812 /** Returns number of test cases
24813 *
24814 * @return TEST_MAX
24815 **/
24816 glw::GLuint XFBStrideTest::getTestCaseNumber()
24817 {
24818 return static_cast<GLuint>(m_test_cases.size());
24819 }
24820
24821 /** Prepare all test cases
24822 *
24823 **/
24824 void XFBStrideTest::testInit()
24825 {
24826 const GLuint n_types = getTypesNumber();
24827
24828 for (GLuint i = 0; i < n_types; ++i)
24829 {
24830 const Utils::Type& type = getType(i);
24831
24832 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24833 {
24834 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
24835 (Utils::Shader::TESS_CTRL == stage))
24836 {
24837 continue;
24838 }
24839
24840 testCase test_case = { (Utils::Shader::STAGES)stage, type };
24841
24842 m_test_cases.push_back(test_case);
24843 }
24844 }
24845 }
24846
24847 /** Constructor
24848 *
24849 * @param context Test framework context
24850 **/
24851 XFBBlockMemberBufferTest::XFBBlockMemberBufferTest(deqp::Context& context)
24852 : NegativeTestBase(
24853 context, "xfb_block_member_buffer",
24854 "Test verifies that compiler reports error when block member has different xfb_buffer qualifier than buffer")
24855 {
24856 }
24857
24858 /** Source for given test case and stage
24859 *
24860 * @param test_case_index Index of test case
24861 * @param stage Shader stage
24862 *
24863 * @return Shader source
24864 **/
24865 std::string XFBBlockMemberBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24866 {
24867 static const GLchar* var_definition = "layout (xfb_offset = 0) out Goku {\n"
24868 " vec4 gohan;\n"
24869 " layout (xfb_buffer = 1) vec4 goten;\n"
24870 "} gokuARRAY;\n";
24871 static const GLchar* var_use = " gokuINDEX.gohan = result / 2;\n"
24872 " gokuINDEX.goten = result / 4;\n";
24873 static const GLchar* fs = "#version 430 core\n"
24874 "#extension GL_ARB_enhanced_layouts : require\n"
24875 "\n"
24876 "in vec4 gs_fs;\n"
24877 "out vec4 fs_out;\n"
24878 "\n"
24879 "void main()\n"
24880 "{\n"
24881 " fs_out = gs_fs;\n"
24882 "}\n"
24883 "\n";
24884 static const GLchar* gs_tested = "#version 430 core\n"
24885 "#extension GL_ARB_enhanced_layouts : require\n"
24886 "\n"
24887 "layout(points) in;\n"
24888 "layout(triangle_strip, max_vertices = 4) out;\n"
24889 "\n"
24890 "VAR_DEFINITION"
24891 "\n"
24892 "in vec4 tes_gs[];\n"
24893 "out vec4 gs_fs;\n"
24894 "\n"
24895 "void main()\n"
24896 "{\n"
24897 " vec4 result = tes_gs[0];\n"
24898 "\n"
24899 "VARIABLE_USE"
24900 "\n"
24901 " gs_fs = result;\n"
24902 " gl_Position = vec4(-1, -1, 0, 1);\n"
24903 " EmitVertex();\n"
24904 " gs_fs = result;\n"
24905 " gl_Position = vec4(-1, 1, 0, 1);\n"
24906 " EmitVertex();\n"
24907 " gs_fs = result;\n"
24908 " gl_Position = vec4(1, -1, 0, 1);\n"
24909 " EmitVertex();\n"
24910 " gs_fs = result;\n"
24911 " gl_Position = vec4(1, 1, 0, 1);\n"
24912 " EmitVertex();\n"
24913 "}\n"
24914 "\n";
24915 static const GLchar* tcs = "#version 430 core\n"
24916 "#extension GL_ARB_enhanced_layouts : require\n"
24917 "\n"
24918 "layout(vertices = 1) out;\n"
24919 "\n"
24920 "in vec4 vs_tcs[];\n"
24921 "out vec4 tcs_tes[];\n"
24922 "\n"
24923 "void main()\n"
24924 "{\n"
24925 "\n"
24926 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
24927 "\n"
24928 " gl_TessLevelOuter[0] = 1.0;\n"
24929 " gl_TessLevelOuter[1] = 1.0;\n"
24930 " gl_TessLevelOuter[2] = 1.0;\n"
24931 " gl_TessLevelOuter[3] = 1.0;\n"
24932 " gl_TessLevelInner[0] = 1.0;\n"
24933 " gl_TessLevelInner[1] = 1.0;\n"
24934 "}\n"
24935 "\n";
24936 static const GLchar* tcs_tested = "#version 430 core\n"
24937 "#extension GL_ARB_enhanced_layouts : require\n"
24938 "\n"
24939 "layout(vertices = 1) out;\n"
24940 "\n"
24941 "VAR_DEFINITION"
24942 "\n"
24943 "in vec4 vs_tcs[];\n"
24944 "out vec4 tcs_tes[];\n"
24945 "\n"
24946 "void main()\n"
24947 "{\n"
24948 " vec4 result = vs_tcs[gl_InvocationID];\n"
24949 "\n"
24950 "VARIABLE_USE"
24951 "\n"
24952 " tcs_tes[gl_InvocationID] = result;\n"
24953 "\n"
24954 " gl_TessLevelOuter[0] = 1.0;\n"
24955 " gl_TessLevelOuter[1] = 1.0;\n"
24956 " gl_TessLevelOuter[2] = 1.0;\n"
24957 " gl_TessLevelOuter[3] = 1.0;\n"
24958 " gl_TessLevelInner[0] = 1.0;\n"
24959 " gl_TessLevelInner[1] = 1.0;\n"
24960 "}\n"
24961 "\n";
24962 static const GLchar* tes_tested = "#version 430 core\n"
24963 "#extension GL_ARB_enhanced_layouts : require\n"
24964 "\n"
24965 "layout(isolines, point_mode) in;\n"
24966 "\n"
24967 "VAR_DEFINITION"
24968 "\n"
24969 "in vec4 tcs_tes[];\n"
24970 "out vec4 tes_gs;\n"
24971 "\n"
24972 "void main()\n"
24973 "{\n"
24974 " vec4 result = tcs_tes[0];\n"
24975 "\n"
24976 "VARIABLE_USE"
24977 "\n"
24978 " tes_gs += result;\n"
24979 "}\n"
24980 "\n";
24981 static const GLchar* vs = "#version 430 core\n"
24982 "#extension GL_ARB_enhanced_layouts : require\n"
24983 "\n"
24984 "in vec4 in_vs;\n"
24985 "out vec4 vs_tcs;\n"
24986 "\n"
24987 "void main()\n"
24988 "{\n"
24989 " vs_tcs = in_vs;\n"
24990 "}\n"
24991 "\n";
24992 static const GLchar* vs_tested = "#version 430 core\n"
24993 "#extension GL_ARB_enhanced_layouts : require\n"
24994 "\n"
24995 "VAR_DEFINITION"
24996 "\n"
24997 "in vec4 in_vs;\n"
24998 "out vec4 vs_tcs;\n"
24999 "\n"
25000 "void main()\n"
25001 "{\n"
25002 " vec4 result = in_vs;\n"
25003 "\n"
25004 "VARIABLE_USE"
25005 "\n"
25006 " vs_tcs = result;\n"
25007 "}\n"
25008 "\n";
25009
25010 std::string source;
25011 testCase& test_case = m_test_cases[test_case_index];
25012
25013 if (test_case.m_stage == stage)
25014 {
25015 const GLchar* array = "";
25016 const GLchar* index = "";
25017 size_t position = 0;
25018
25019 switch (stage)
25020 {
25021 case Utils::Shader::GEOMETRY:
25022 source = gs_tested;
25023 array = "[]";
25024 index = "[0]";
25025 break;
25026 case Utils::Shader::TESS_CTRL:
25027 source = tcs_tested;
25028 array = "[]";
25029 index = "[gl_InvocationID]";
25030 break;
25031 case Utils::Shader::TESS_EVAL:
25032 source = tes_tested;
25033 array = "[]";
25034 index = "[0]";
25035 break;
25036 case Utils::Shader::VERTEX:
25037 source = vs_tested;
25038 break;
25039 default:
25040 TCU_FAIL("Invalid enum");
25041 }
25042
25043 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25044 position = 0;
25045 Utils::replaceToken("ARRAY", position, array, source);
25046 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25047
25048 Utils::replaceAllTokens("INDEX", index, source);
25049 }
25050 else
25051 {
25052 switch (test_case.m_stage)
25053 {
25054 case Utils::Shader::GEOMETRY:
25055 switch (stage)
25056 {
25057 case Utils::Shader::FRAGMENT:
25058 source = fs;
25059 break;
25060 case Utils::Shader::VERTEX:
25061 source = vs;
25062 break;
25063 default:
25064 source = "";
25065 }
25066 break;
25067 case Utils::Shader::TESS_CTRL:
25068 switch (stage)
25069 {
25070 case Utils::Shader::FRAGMENT:
25071 source = fs;
25072 break;
25073 case Utils::Shader::VERTEX:
25074 source = vs;
25075 break;
25076 default:
25077 source = "";
25078 }
25079 break;
25080 case Utils::Shader::TESS_EVAL:
25081 switch (stage)
25082 {
25083 case Utils::Shader::FRAGMENT:
25084 source = fs;
25085 break;
25086 case Utils::Shader::TESS_CTRL:
25087 source = tcs;
25088 break;
25089 case Utils::Shader::VERTEX:
25090 source = vs;
25091 break;
25092 default:
25093 source = "";
25094 }
25095 break;
25096 case Utils::Shader::VERTEX:
25097 switch (stage)
25098 {
25099 case Utils::Shader::FRAGMENT:
25100 source = fs;
25101 break;
25102 default:
25103 source = "";
25104 }
25105 break;
25106 default:
25107 TCU_FAIL("Invalid enum");
25108 break;
25109 }
25110 }
25111
25112 return source;
25113 }
25114
25115 /** Get description of test case
25116 *
25117 * @param test_case_index Index of test case
25118 *
25119 * @return Test case description
25120 **/
25121 std::string XFBBlockMemberBufferTest::getTestCaseName(GLuint test_case_index)
25122 {
25123 std::stringstream stream;
25124 testCase& test_case = m_test_cases[test_case_index];
25125
25126 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
25127
25128 return stream.str();
25129 }
25130
25131 /** Get number of test cases
25132 *
25133 * @return Number of test cases
25134 **/
25135 GLuint XFBBlockMemberBufferTest::getTestCaseNumber()
25136 {
25137 return static_cast<GLuint>(m_test_cases.size());
25138 }
25139
25140 /** Selects if "compute" stage is relevant for test
25141 *
25142 * @param ignored
25143 *
25144 * @return false
25145 **/
25146 bool XFBBlockMemberBufferTest::isComputeRelevant(GLuint /* test_case_index */)
25147 {
25148 return false;
25149 }
25150
25151 /** Prepare all test cases
25152 *
25153 **/
25154 void XFBBlockMemberBufferTest::testInit()
25155 {
25156 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25157 {
25158 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25159 (Utils::Shader::FRAGMENT == stage))
25160 {
25161 continue;
25162 }
25163
25164 testCase test_case = { (Utils::Shader::STAGES)stage };
25165
25166 m_test_cases.push_back(test_case);
25167 }
25168 }
25169
25170 /** Constructor
25171 *
25172 * @param context Test framework context
25173 **/
25174 XFBOutputOverlappingTest::XFBOutputOverlappingTest(deqp::Context& context)
25175 : NegativeTestBase(context, "xfb_output_overlapping",
25176 "Test verifies that compiler reports error when two xfb qualified outputs overlap")
25177 {
25178 }
25179
25180 /** Source for given test case and stage
25181 *
25182 * @param test_case_index Index of test case
25183 * @param stage Shader stage
25184 *
25185 * @return Shader source
25186 **/
25187 std::string XFBOutputOverlappingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25188 {
25189 static const GLchar* var_definition = "layout (xfb_offset = OFFSET) out TYPE gohanARRAY;\n"
25190 "layout (xfb_offset = OFFSET) out TYPE gotenARRAY;\n";
25191 static const GLchar* var_use = " gohanINDEX = TYPE(0);\n"
25192 " gotenINDEX = TYPE(1);\n"
25193 " if (vec4(0) == result)\n"
25194 " {\n"
25195 " gohanINDEX = TYPE(1);\n"
25196 " gotenINDEX = TYPE(0);\n"
25197 " }\n";
25198 static const GLchar* fs = "#version 430 core\n"
25199 "#extension GL_ARB_enhanced_layouts : require\n"
25200 "\n"
25201 "in vec4 gs_fs;\n"
25202 "out vec4 fs_out;\n"
25203 "\n"
25204 "void main()\n"
25205 "{\n"
25206 " fs_out = gs_fs;\n"
25207 "}\n"
25208 "\n";
25209 static const GLchar* gs_tested = "#version 430 core\n"
25210 "#extension GL_ARB_enhanced_layouts : require\n"
25211 "\n"
25212 "layout(points) in;\n"
25213 "layout(triangle_strip, max_vertices = 4) out;\n"
25214 "\n"
25215 "VAR_DEFINITION"
25216 "\n"
25217 "in vec4 tes_gs[];\n"
25218 "out vec4 gs_fs;\n"
25219 "\n"
25220 "void main()\n"
25221 "{\n"
25222 " vec4 result = tes_gs[0];\n"
25223 "\n"
25224 "VARIABLE_USE"
25225 "\n"
25226 " gs_fs = result;\n"
25227 " gl_Position = vec4(-1, -1, 0, 1);\n"
25228 " EmitVertex();\n"
25229 " gs_fs = result;\n"
25230 " gl_Position = vec4(-1, 1, 0, 1);\n"
25231 " EmitVertex();\n"
25232 " gs_fs = result;\n"
25233 " gl_Position = vec4(1, -1, 0, 1);\n"
25234 " EmitVertex();\n"
25235 " gs_fs = result;\n"
25236 " gl_Position = vec4(1, 1, 0, 1);\n"
25237 " EmitVertex();\n"
25238 "}\n"
25239 "\n";
25240 static const GLchar* tcs = "#version 430 core\n"
25241 "#extension GL_ARB_enhanced_layouts : require\n"
25242 "\n"
25243 "layout(vertices = 1) out;\n"
25244 "\n"
25245 "in vec4 vs_tcs[];\n"
25246 "out vec4 tcs_tes[];\n"
25247 "\n"
25248 "void main()\n"
25249 "{\n"
25250 "\n"
25251 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
25252 "\n"
25253 " gl_TessLevelOuter[0] = 1.0;\n"
25254 " gl_TessLevelOuter[1] = 1.0;\n"
25255 " gl_TessLevelOuter[2] = 1.0;\n"
25256 " gl_TessLevelOuter[3] = 1.0;\n"
25257 " gl_TessLevelInner[0] = 1.0;\n"
25258 " gl_TessLevelInner[1] = 1.0;\n"
25259 "}\n"
25260 "\n";
25261 static const GLchar* tcs_tested = "#version 430 core\n"
25262 "#extension GL_ARB_enhanced_layouts : require\n"
25263 "\n"
25264 "layout(vertices = 1) out;\n"
25265 "\n"
25266 "VAR_DEFINITION"
25267 "\n"
25268 "in vec4 vs_tcs[];\n"
25269 "out vec4 tcs_tes[];\n"
25270 "\n"
25271 "void main()\n"
25272 "{\n"
25273 " vec4 result = vs_tcs[gl_InvocationID];\n"
25274 "\n"
25275 "VARIABLE_USE"
25276 "\n"
25277 " tcs_tes[gl_InvocationID] = result;\n"
25278 "\n"
25279 " gl_TessLevelOuter[0] = 1.0;\n"
25280 " gl_TessLevelOuter[1] = 1.0;\n"
25281 " gl_TessLevelOuter[2] = 1.0;\n"
25282 " gl_TessLevelOuter[3] = 1.0;\n"
25283 " gl_TessLevelInner[0] = 1.0;\n"
25284 " gl_TessLevelInner[1] = 1.0;\n"
25285 "}\n"
25286 "\n";
25287 static const GLchar* tes_tested = "#version 430 core\n"
25288 "#extension GL_ARB_enhanced_layouts : require\n"
25289 "\n"
25290 "layout(isolines, point_mode) in;\n"
25291 "\n"
25292 "VAR_DEFINITION"
25293 "\n"
25294 "in vec4 tcs_tes[];\n"
25295 "out vec4 tes_gs;\n"
25296 "\n"
25297 "void main()\n"
25298 "{\n"
25299 " vec4 result = tcs_tes[0];\n"
25300 "\n"
25301 "VARIABLE_USE"
25302 "\n"
25303 " tes_gs += result;\n"
25304 "}\n"
25305 "\n";
25306 static const GLchar* vs = "#version 430 core\n"
25307 "#extension GL_ARB_enhanced_layouts : require\n"
25308 "\n"
25309 "in vec4 in_vs;\n"
25310 "out vec4 vs_tcs;\n"
25311 "\n"
25312 "void main()\n"
25313 "{\n"
25314 " vs_tcs = in_vs;\n"
25315 "}\n"
25316 "\n";
25317 static const GLchar* vs_tested = "#version 430 core\n"
25318 "#extension GL_ARB_enhanced_layouts : require\n"
25319 "\n"
25320 "VAR_DEFINITION"
25321 "\n"
25322 "in vec4 in_vs;\n"
25323 "out vec4 vs_tcs;\n"
25324 "\n"
25325 "void main()\n"
25326 "{\n"
25327 " vec4 result = in_vs;\n"
25328 "\n"
25329 "VARIABLE_USE"
25330 "\n"
25331 " vs_tcs = result;\n"
25332 "}\n"
25333 "\n";
25334
25335 std::string source;
25336 testCase& test_case = m_test_cases[test_case_index];
25337
25338 if (test_case.m_stage == stage)
25339 {
25340 const GLchar* array = "";
25341 GLchar buffer_gohan[16];
25342 GLchar buffer_goten[16];
25343 const GLchar* index = "";
25344 size_t position = 0;
25345 size_t position_start = 0;
25346 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25347
25348 sprintf(buffer_gohan, "%d", test_case.m_offset_gohan);
25349 sprintf(buffer_goten, "%d", test_case.m_offset_goten);
25350
25351 switch (stage)
25352 {
25353 case Utils::Shader::GEOMETRY:
25354 source = gs_tested;
25355 array = "[]";
25356 index = "[0]";
25357 break;
25358 case Utils::Shader::TESS_CTRL:
25359 source = tcs_tested;
25360 array = "[]";
25361 index = "[gl_InvocationID]";
25362 break;
25363 case Utils::Shader::TESS_EVAL:
25364 source = tes_tested;
25365 array = "[]";
25366 index = "[0]";
25367 break;
25368 case Utils::Shader::VERTEX:
25369 source = vs_tested;
25370 break;
25371 default:
25372 TCU_FAIL("Invalid enum");
25373 }
25374
25375 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25376 position = 0;
25377 Utils::replaceToken("OFFSET", position, buffer_gohan, source);
25378 Utils::replaceToken("TYPE", position, type_name, source);
25379 Utils::replaceToken("ARRAY", position, array, source);
25380 Utils::replaceToken("OFFSET", position, buffer_goten, source);
25381 Utils::replaceToken("TYPE", position, type_name, source);
25382 Utils::replaceToken("ARRAY", position, array, source);
25383 position_start = position;
25384 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25385 position = position_start;
25386 Utils::replaceToken("INDEX", position, index, source);
25387 Utils::replaceToken("TYPE", position, type_name, source);
25388 Utils::replaceToken("INDEX", position, index, source);
25389 Utils::replaceToken("TYPE", position, type_name, source);
25390 Utils::replaceToken("INDEX", position, index, source);
25391 Utils::replaceToken("TYPE", position, type_name, source);
25392 Utils::replaceToken("INDEX", position, index, source);
25393 Utils::replaceToken("TYPE", position, type_name, source);
25394 }
25395 else
25396 {
25397 switch (test_case.m_stage)
25398 {
25399 case Utils::Shader::GEOMETRY:
25400 switch (stage)
25401 {
25402 case Utils::Shader::FRAGMENT:
25403 source = fs;
25404 break;
25405 case Utils::Shader::VERTEX:
25406 source = vs;
25407 break;
25408 default:
25409 source = "";
25410 }
25411 break;
25412 case Utils::Shader::TESS_CTRL:
25413 switch (stage)
25414 {
25415 case Utils::Shader::FRAGMENT:
25416 source = fs;
25417 break;
25418 case Utils::Shader::VERTEX:
25419 source = vs;
25420 break;
25421 default:
25422 source = "";
25423 }
25424 break;
25425 case Utils::Shader::TESS_EVAL:
25426 switch (stage)
25427 {
25428 case Utils::Shader::FRAGMENT:
25429 source = fs;
25430 break;
25431 case Utils::Shader::TESS_CTRL:
25432 source = tcs;
25433 break;
25434 case Utils::Shader::VERTEX:
25435 source = vs;
25436 break;
25437 default:
25438 source = "";
25439 }
25440 break;
25441 case Utils::Shader::VERTEX:
25442 switch (stage)
25443 {
25444 case Utils::Shader::FRAGMENT:
25445 source = fs;
25446 break;
25447 default:
25448 source = "";
25449 }
25450 break;
25451 default:
25452 TCU_FAIL("Invalid enum");
25453 break;
25454 }
25455 }
25456
25457 return source;
25458 }
25459
25460 /** Get description of test case
25461 *
25462 * @param test_case_index Index of test case
25463 *
25464 * @return Test case description
25465 **/
25466 std::string XFBOutputOverlappingTest::getTestCaseName(GLuint test_case_index)
25467 {
25468 std::stringstream stream;
25469 testCase& test_case = m_test_cases[test_case_index];
25470
25471 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25472 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offsets: " << test_case.m_offset_gohan << " & "
25473 << test_case.m_offset_goten;
25474
25475 return stream.str();
25476 }
25477
25478 /** Get number of test cases
25479 *
25480 * @return Number of test cases
25481 **/
25482 GLuint XFBOutputOverlappingTest::getTestCaseNumber()
25483 {
25484 return static_cast<GLuint>(m_test_cases.size());
25485 }
25486
25487 /** Selects if "compute" stage is relevant for test
25488 *
25489 * @param ignored
25490 *
25491 * @return false
25492 **/
25493 bool XFBOutputOverlappingTest::isComputeRelevant(GLuint /* test_case_index */)
25494 {
25495 return false;
25496 }
25497
25498 /** Prepare all test cases
25499 *
25500 **/
25501 void XFBOutputOverlappingTest::testInit()
25502 {
25503 const GLuint n_types = getTypesNumber();
25504
25505 for (GLuint i = 0; i < n_types; ++i)
25506 {
25507 const Utils::Type& type = getType(i);
25508 const GLuint base_alingment = Utils::Type::GetTypeSize(type.m_basic_type);
25509
25510 /* Skip scalars, not applicable as:
25511 *
25512 * The offset must be a multiple of the size of the first component of the first
25513 * qualified variable or block member, or a compile-time error results.
25514 */
25515 if ((1 == type.m_n_columns) && (1 == type.m_n_rows))
25516 {
25517 continue;
25518 }
25519
25520 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25521 {
25522 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25523 (Utils::Shader::FRAGMENT == stage))
25524 {
25525 continue;
25526 }
25527
25528 testCase test_case = { 0 /* gohan offset */, base_alingment /* goten_offset */,
25529 (Utils::Shader::STAGES)stage, type };
25530
25531 m_test_cases.push_back(test_case);
25532 }
25533 }
25534 }
25535
25536 /** Constructor
25537 *
25538 * @param context Test framework context
25539 **/
25540 XFBInvalidOffsetAlignmentTest::XFBInvalidOffsetAlignmentTest(deqp::Context& context)
25541 : NegativeTestBase(context, "xfb_invalid_offset_alignment",
25542 "Test verifies that compiler reports error when xfb_offset has invalid alignment")
25543 {
25544 }
25545
25546 /** Source for given test case and stage
25547 *
25548 * @param test_case_index Index of test case
25549 * @param stage Shader stage
25550 *
25551 * @return Shader source
25552 **/
25553 std::string XFBInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25554 {
25555 static const GLchar* var_definition = "layout (xfb_offset = OFFSET) out TYPE gohanARRAY;\n";
25556 static const GLchar* var_use = " gohanINDEX = TYPE(0);\n"
25557 " if (vec4(0) == result)\n"
25558 " {\n"
25559 " gohanINDEX = TYPE(1);\n"
25560 " }\n";
25561 static const GLchar* fs = "#version 430 core\n"
25562 "#extension GL_ARB_enhanced_layouts : require\n"
25563 "\n"
25564 "in vec4 gs_fs;\n"
25565 "out vec4 fs_out;\n"
25566 "\n"
25567 "void main()\n"
25568 "{\n"
25569 " fs_out = gs_fs;\n"
25570 "}\n"
25571 "\n";
25572 static const GLchar* gs_tested = "#version 430 core\n"
25573 "#extension GL_ARB_enhanced_layouts : require\n"
25574 "\n"
25575 "layout(points) in;\n"
25576 "layout(triangle_strip, max_vertices = 4) out;\n"
25577 "\n"
25578 "VAR_DEFINITION"
25579 "\n"
25580 "in vec4 tes_gs[];\n"
25581 "out vec4 gs_fs;\n"
25582 "\n"
25583 "void main()\n"
25584 "{\n"
25585 " vec4 result = tes_gs[0];\n"
25586 "\n"
25587 "VARIABLE_USE"
25588 "\n"
25589 " gs_fs = result;\n"
25590 " gl_Position = vec4(-1, -1, 0, 1);\n"
25591 " EmitVertex();\n"
25592 " gs_fs = result;\n"
25593 " gl_Position = vec4(-1, 1, 0, 1);\n"
25594 " EmitVertex();\n"
25595 " gs_fs = result;\n"
25596 " gl_Position = vec4(1, -1, 0, 1);\n"
25597 " EmitVertex();\n"
25598 " gs_fs = result;\n"
25599 " gl_Position = vec4(1, 1, 0, 1);\n"
25600 " EmitVertex();\n"
25601 "}\n"
25602 "\n";
25603 static const GLchar* tcs = "#version 430 core\n"
25604 "#extension GL_ARB_enhanced_layouts : require\n"
25605 "\n"
25606 "layout(vertices = 1) out;\n"
25607 "\n"
25608 "in vec4 vs_tcs[];\n"
25609 "out vec4 tcs_tes[];\n"
25610 "\n"
25611 "void main()\n"
25612 "{\n"
25613 "\n"
25614 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
25615 "\n"
25616 " gl_TessLevelOuter[0] = 1.0;\n"
25617 " gl_TessLevelOuter[1] = 1.0;\n"
25618 " gl_TessLevelOuter[2] = 1.0;\n"
25619 " gl_TessLevelOuter[3] = 1.0;\n"
25620 " gl_TessLevelInner[0] = 1.0;\n"
25621 " gl_TessLevelInner[1] = 1.0;\n"
25622 "}\n"
25623 "\n";
25624 static const GLchar* tcs_tested = "#version 430 core\n"
25625 "#extension GL_ARB_enhanced_layouts : require\n"
25626 "\n"
25627 "layout(vertices = 1) out;\n"
25628 "\n"
25629 "VAR_DEFINITION"
25630 "\n"
25631 "in vec4 vs_tcs[];\n"
25632 "out vec4 tcs_tes[];\n"
25633 "\n"
25634 "void main()\n"
25635 "{\n"
25636 " vec4 result = vs_tcs[gl_InvocationID];\n"
25637 "\n"
25638 "VARIABLE_USE"
25639 "\n"
25640 " tcs_tes[gl_InvocationID] = result;\n"
25641 "\n"
25642 " gl_TessLevelOuter[0] = 1.0;\n"
25643 " gl_TessLevelOuter[1] = 1.0;\n"
25644 " gl_TessLevelOuter[2] = 1.0;\n"
25645 " gl_TessLevelOuter[3] = 1.0;\n"
25646 " gl_TessLevelInner[0] = 1.0;\n"
25647 " gl_TessLevelInner[1] = 1.0;\n"
25648 "}\n"
25649 "\n";
25650 static const GLchar* tes_tested = "#version 430 core\n"
25651 "#extension GL_ARB_enhanced_layouts : require\n"
25652 "\n"
25653 "layout(isolines, point_mode) in;\n"
25654 "\n"
25655 "VAR_DEFINITION"
25656 "\n"
25657 "in vec4 tcs_tes[];\n"
25658 "out vec4 tes_gs;\n"
25659 "\n"
25660 "void main()\n"
25661 "{\n"
25662 " vec4 result = tcs_tes[0];\n"
25663 "\n"
25664 "VARIABLE_USE"
25665 "\n"
25666 " tes_gs += result;\n"
25667 "}\n"
25668 "\n";
25669 static const GLchar* vs = "#version 430 core\n"
25670 "#extension GL_ARB_enhanced_layouts : require\n"
25671 "\n"
25672 "in vec4 in_vs;\n"
25673 "out vec4 vs_tcs;\n"
25674 "\n"
25675 "void main()\n"
25676 "{\n"
25677 " vs_tcs = in_vs;\n"
25678 "}\n"
25679 "\n";
25680 static const GLchar* vs_tested = "#version 430 core\n"
25681 "#extension GL_ARB_enhanced_layouts : require\n"
25682 "\n"
25683 "VAR_DEFINITION"
25684 "\n"
25685 "in vec4 in_vs;\n"
25686 "out vec4 vs_tcs;\n"
25687 "\n"
25688 "void main()\n"
25689 "{\n"
25690 " vec4 result = in_vs;\n"
25691 "\n"
25692 "VARIABLE_USE"
25693 "\n"
25694 " vs_tcs = result;\n"
25695 "}\n"
25696 "\n";
25697
25698 std::string source;
25699 testCase& test_case = m_test_cases[test_case_index];
25700
25701 if (test_case.m_stage == stage)
25702 {
25703 const GLchar* array = "";
25704 GLchar buffer[16];
25705 const GLchar* index = "";
25706 size_t position = 0;
25707 size_t position_start = 0;
25708 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25709
25710 sprintf(buffer, "%d", test_case.m_offset);
25711
25712 switch (stage)
25713 {
25714 case Utils::Shader::GEOMETRY:
25715 source = gs_tested;
25716 array = "[]";
25717 index = "[0]";
25718 break;
25719 case Utils::Shader::TESS_CTRL:
25720 source = tcs_tested;
25721 array = "[]";
25722 index = "[gl_InvocationID]";
25723 break;
25724 case Utils::Shader::TESS_EVAL:
25725 source = tes_tested;
25726 array = "[]";
25727 index = "[0]";
25728 break;
25729 case Utils::Shader::VERTEX:
25730 source = vs_tested;
25731 break;
25732 default:
25733 TCU_FAIL("Invalid enum");
25734 }
25735
25736 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25737 position = 0;
25738 Utils::replaceToken("OFFSET", position, buffer, source);
25739 Utils::replaceToken("TYPE", position, type_name, source);
25740 Utils::replaceToken("ARRAY", position, array, source);
25741 position_start = position;
25742 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25743 position = position_start;
25744 Utils::replaceToken("INDEX", position, index, source);
25745 Utils::replaceToken("TYPE", position, type_name, source);
25746 Utils::replaceToken("INDEX", position, index, source);
25747 Utils::replaceToken("TYPE", position, type_name, source);
25748 }
25749 else
25750 {
25751 switch (test_case.m_stage)
25752 {
25753 case Utils::Shader::GEOMETRY:
25754 switch (stage)
25755 {
25756 case Utils::Shader::FRAGMENT:
25757 source = fs;
25758 break;
25759 case Utils::Shader::VERTEX:
25760 source = vs;
25761 break;
25762 default:
25763 source = "";
25764 }
25765 break;
25766 case Utils::Shader::TESS_CTRL:
25767 switch (stage)
25768 {
25769 case Utils::Shader::FRAGMENT:
25770 source = fs;
25771 break;
25772 case Utils::Shader::VERTEX:
25773 source = vs;
25774 break;
25775 default:
25776 source = "";
25777 }
25778 break;
25779 case Utils::Shader::TESS_EVAL:
25780 switch (stage)
25781 {
25782 case Utils::Shader::FRAGMENT:
25783 source = fs;
25784 break;
25785 case Utils::Shader::TESS_CTRL:
25786 source = tcs;
25787 break;
25788 case Utils::Shader::VERTEX:
25789 source = vs;
25790 break;
25791 default:
25792 source = "";
25793 }
25794 break;
25795 case Utils::Shader::VERTEX:
25796 switch (stage)
25797 {
25798 case Utils::Shader::FRAGMENT:
25799 source = fs;
25800 break;
25801 default:
25802 source = "";
25803 }
25804 break;
25805 default:
25806 TCU_FAIL("Invalid enum");
25807 break;
25808 }
25809 }
25810
25811 return source;
25812 }
25813
25814 /** Get description of test case
25815 *
25816 * @param test_case_index Index of test case
25817 *
25818 * @return Test case description
25819 **/
25820 std::string XFBInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
25821 {
25822 std::stringstream stream;
25823 testCase& test_case = m_test_cases[test_case_index];
25824
25825 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25826 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
25827
25828 return stream.str();
25829 }
25830
25831 /** Get number of test cases
25832 *
25833 * @return Number of test cases
25834 **/
25835 GLuint XFBInvalidOffsetAlignmentTest::getTestCaseNumber()
25836 {
25837 return static_cast<GLuint>(m_test_cases.size());
25838 }
25839
25840 /** Selects if "compute" stage is relevant for test
25841 *
25842 * @param ignored
25843 *
25844 * @return false
25845 **/
25846 bool XFBInvalidOffsetAlignmentTest::isComputeRelevant(GLuint /* test_case_index */)
25847 {
25848 return false;
25849 }
25850
25851 /** Prepare all test cases
25852 *
25853 **/
25854 void XFBInvalidOffsetAlignmentTest::testInit()
25855 {
25856 const GLuint n_types = getTypesNumber();
25857
25858 for (GLuint i = 0; i < n_types; ++i)
25859 {
25860 const Utils::Type& type = getType(i);
25861 const GLuint base_alingment = Utils::Type::GetTypeSize(type.m_basic_type);
25862
25863 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25864 {
25865 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25866 (Utils::Shader::FRAGMENT == stage))
25867 {
25868 continue;
25869 }
25870
25871 for (GLuint offset = base_alingment + 1; offset < 2 * base_alingment; ++offset)
25872 {
25873 testCase test_case = { offset, (Utils::Shader::STAGES)stage, type };
25874
25875 m_test_cases.push_back(test_case);
25876 }
25877 }
25878 }
25879 }
25880
25881 /** Constructor
25882 *
25883 * @param context Test context
25884 **/
25885 XFBCaptureInactiveOutputVariableTest::XFBCaptureInactiveOutputVariableTest(deqp::Context& context)
25886 : BufferTestBase(context, "xfb_capture_inactive_output_variable",
25887 "Test verifies that inactive variables are captured")
25888 {
25889 /* Nothing to be done here */
25890 }
25891
25892 /** Execute drawArrays for single vertex
25893 *
25894 * @param test_case_index
25895 *
25896 * @return true
25897 **/
25898 bool XFBCaptureInactiveOutputVariableTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
25899 {
25900 const Functions& gl = m_context.getRenderContext().getFunctions();
25901 GLenum primitive_type = GL_PATCHES;
25902
25903 if (TEST_VS == test_case_index)
25904 {
25905 primitive_type = GL_POINTS;
25906 }
25907
25908 gl.disable(GL_RASTERIZER_DISCARD);
25909 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
25910
25911 gl.beginTransformFeedback(GL_POINTS);
25912 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
25913
25914 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
25915 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
25916
25917 gl.endTransformFeedback();
25918 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
25919
25920 return true;
25921 }
25922
25923 /** Get descriptors of buffers necessary for test
25924 *
25925 * @param ignored
25926 * @param out_descriptors Descriptors of buffers used by test
25927 **/
25928 void XFBCaptureInactiveOutputVariableTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
25929 bufferDescriptor::Vector& out_descriptors)
25930 {
25931 const Utils::Type& type = Utils::Type::vec4;
25932
25933 /* Test needs single uniform and xfb */
25934 out_descriptors.resize(2);
25935
25936 /* Get references */
25937 bufferDescriptor& uniform = out_descriptors[0];
25938 bufferDescriptor& xfb = out_descriptors[1];
25939
25940 /* Index */
25941 uniform.m_index = 0;
25942 xfb.m_index = 0;
25943
25944 /* Target */
25945 uniform.m_target = Utils::Buffer::Uniform;
25946 xfb.m_target = Utils::Buffer::Transform_feedback;
25947
25948 /* Data */
25949 const std::vector<GLubyte>& gohan_data = type.GenerateData();
25950 const std::vector<GLubyte>& goten_data = type.GenerateData();
25951
25952 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
25953
25954 /* Uniform data */
25955 uniform.m_initial_data.resize(2 * type_size);
25956 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
25957 memcpy(&uniform.m_initial_data[0] + type_size, &goten_data[0], type_size);
25958
25959 /* XFB data */
25960 xfb.m_initial_data.resize(3 * type_size);
25961 xfb.m_expected_data.resize(3 * type_size);
25962
25963 for (GLuint i = 0; i < 3 * type_size; ++i)
25964 {
25965 xfb.m_initial_data[i] = (glw::GLubyte)i;
25966 xfb.m_expected_data[i] = (glw::GLubyte)i;
25967 }
25968
25969 memcpy(&xfb.m_expected_data[0] + 2 * type_size, &gohan_data[0], type_size);
25970 memcpy(&xfb.m_expected_data[0] + 0 * type_size, &goten_data[0], type_size);
25971 }
25972
25973 /** Get body of main function for given shader stage
25974 *
25975 * @param test_case_index Index of test case
25976 * @param stage Shader stage
25977 * @param out_assignments Set to empty
25978 * @param out_calculations Set to empty
25979 **/
25980 void XFBCaptureInactiveOutputVariableTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
25981 std::string& out_assignments, std::string& out_calculations)
25982 {
25983 out_calculations = "";
25984
25985 static const GLchar* vs_tes_gs = " goten = uni_goten;\n"
25986 " gohan = uni_gohan;\n";
25987 static const GLchar* fs = " fs_out = goku + gohan + goten;\n";
25988
25989 const GLchar* assignments = "";
25990
25991 switch (stage)
25992 {
25993 case Utils::Shader::FRAGMENT:
25994 assignments = fs;
25995 break;
25996
25997 case Utils::Shader::GEOMETRY:
25998 if (TEST_GS == test_case_index)
25999 {
26000 assignments = vs_tes_gs;
26001 }
26002 break;
26003
26004 case Utils::Shader::TESS_CTRL:
26005 break;
26006
26007 case Utils::Shader::TESS_EVAL:
26008 if (TEST_TES == test_case_index)
26009 {
26010 assignments = vs_tes_gs;
26011 }
26012 break;
26013
26014 case Utils::Shader::VERTEX:
26015 if (TEST_VS == test_case_index)
26016 {
26017 assignments = vs_tes_gs;
26018 }
26019 break;
26020
26021 default:
26022 TCU_FAIL("Invalid enum");
26023 }
26024
26025 out_assignments = assignments;
26026 }
26027
26028 /** Get interface of shader
26029 *
26030 * @param test_case_index Index of test case
26031 * @param stage Shader stage
26032 * @param out_interface Set to ""
26033 **/
26034 void XFBCaptureInactiveOutputVariableTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26035 std::string& out_interface)
26036 {
26037 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26038 "\n"
26039 "layout (xfb_offset = 1 * sizeof_type) out vec4 goku;\n"
26040 "layout (xfb_offset = 2 * sizeof_type) out vec4 gohan;\n"
26041 "layout (xfb_offset = 0 * sizeof_type) out vec4 goten;\n"
26042 "\n"
26043 "layout(binding = 0) uniform block {\n"
26044 " vec4 uni_gohan;\n"
26045 " vec4 uni_goten;\n"
26046 "};\n";
26047 static const GLchar* fs = "in vec4 goku;\n"
26048 "in vec4 gohan;\n"
26049 "in vec4 goten;\n"
26050 "out vec4 fs_out;\n";
26051
26052 const GLchar* interface = "";
26053
26054 switch (stage)
26055 {
26056 case Utils::Shader::FRAGMENT:
26057 interface = fs;
26058 break;
26059
26060 case Utils::Shader::GEOMETRY:
26061 if (TEST_GS == test_case_index)
26062 {
26063 interface = vs_tes_gs;
26064 }
26065 break;
26066
26067 case Utils::Shader::TESS_CTRL:
26068 break;
26069
26070 case Utils::Shader::TESS_EVAL:
26071 if (TEST_TES == test_case_index)
26072 {
26073 interface = vs_tes_gs;
26074 }
26075 break;
26076
26077 case Utils::Shader::VERTEX:
26078 if (TEST_VS == test_case_index)
26079 {
26080 interface = vs_tes_gs;
26081 }
26082 break;
26083
26084 default:
26085 TCU_FAIL("Invalid enum");
26086 }
26087
26088 out_interface = interface;
26089 }
26090
26091 /** Get source code of shader
26092 *
26093 * @param test_case_index Index of test case
26094 * @param stage Shader stage
26095 *
26096 * @return Source
26097 **/
26098 std::string XFBCaptureInactiveOutputVariableTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26099 {
26100 std::string source;
26101
26102 switch (test_case_index)
26103 {
26104 case TEST_VS:
26105 switch (stage)
26106 {
26107 case Utils::Shader::FRAGMENT:
26108 case Utils::Shader::VERTEX:
26109 source = BufferTestBase::getShaderSource(test_case_index, stage);
26110 break;
26111 default:
26112 break;
26113 }
26114 break;
26115
26116 case TEST_TES:
26117 switch (stage)
26118 {
26119 case Utils::Shader::FRAGMENT:
26120 case Utils::Shader::TESS_CTRL:
26121 case Utils::Shader::TESS_EVAL:
26122 case Utils::Shader::VERTEX:
26123 source = BufferTestBase::getShaderSource(test_case_index, stage);
26124 break;
26125 default:
26126 break;
26127 }
26128 break;
26129
26130 case TEST_GS:
26131 source = BufferTestBase::getShaderSource(test_case_index, stage);
26132 break;
26133
26134 default:
26135 TCU_FAIL("Invalid enum");
26136 break;
26137 }
26138
26139 /* */
26140 return source;
26141 }
26142
26143 /** Get name of test case
26144 *
26145 * @param test_case_index Index of test case
26146 *
26147 * @return Name of tested stage
26148 **/
26149 std::string XFBCaptureInactiveOutputVariableTest::getTestCaseName(glw::GLuint test_case_index)
26150 {
26151 const GLchar* name = 0;
26152
26153 switch (test_case_index)
26154 {
26155 case TEST_VS:
26156 name = "vertex";
26157 break;
26158 case TEST_TES:
26159 name = "tessellation evaluation";
26160 break;
26161 case TEST_GS:
26162 name = "geometry";
26163 break;
26164 default:
26165 TCU_FAIL("Invalid enum");
26166 }
26167
26168 return name;
26169 }
26170
26171 /** Returns number of test cases
26172 *
26173 * @return TEST_MAX
26174 **/
26175 glw::GLuint XFBCaptureInactiveOutputVariableTest::getTestCaseNumber()
26176 {
26177 return TEST_MAX;
26178 }
26179
26180 /** Inspects program to check if all resources are as expected
26181 *
26182 * @param ignored
26183 * @param program Program instance
26184 * @param out_stream Error message
26185 *
26186 * @return true if everything is ok, false otherwise
26187 **/
26188 bool XFBCaptureInactiveOutputVariableTest::inspectProgram(GLuint /* test_case_index */, Utils::Program& program,
26189 std::stringstream& out_stream)
26190 {
26191 GLint stride = 0;
26192 const Utils::Type& type = Utils::Type::vec4;
26193 const GLuint type_size = type.GetSize();
26194
26195 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
26196 1 /* buf_size */, &stride);
26197
26198 if ((GLint)(3 * type_size) != stride)
26199 {
26200 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
26201
26202 return false;
26203 }
26204
26205 return true;
26206 }
26207
26208 /** Verify contents of buffers
26209 *
26210 * @param buffers Collection of buffers to be verified
26211 *
26212 * @return true if everything is as expected, false otherwise
26213 **/
26214 bool XFBCaptureInactiveOutputVariableTest::verifyBuffers(bufferCollection& buffers)
26215 {
26216 bool result = true;
26217
26218 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26219 Utils::Buffer* buffer = pair.m_buffer;
26220 bufferDescriptor* descriptor = pair.m_descriptor;
26221
26222 /* Get pointer to contents of buffer */
26223 buffer->Bind();
26224 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26225
26226 /* Get pointer to expected data */
26227 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26228
26229 /* Compare */
26230 static const GLuint vec4_size = 16;
26231
26232 int res_gohan = memcmp(buffer_data + 2 * vec4_size, expected_data + 2 * vec4_size, vec4_size);
26233 int res_goten = memcmp(buffer_data + 0 * vec4_size, expected_data + 0 * vec4_size, vec4_size);
26234
26235 if ((0 != res_gohan) || (0 != res_goten))
26236 {
26237 m_context.getTestContext().getLog()
26238 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26239 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26240
26241 result = false;
26242 }
26243
26244 /* Release buffer mapping */
26245 buffer->UnMap();
26246
26247 return result;
26248 }
26249
26250 /** Constructor
26251 *
26252 * @param context Test context
26253 **/
26254 XFBCaptureInactiveOutputComponentTest::XFBCaptureInactiveOutputComponentTest(deqp::Context& context)
26255 : BufferTestBase(context, "xfb_capture_inactive_output_component",
26256 "Test verifies that inactive components are not modified")
26257 {
26258 /* Nothing to be done here */
26259 }
26260
26261 /** Execute drawArrays for single vertex
26262 *
26263 * @param test_case_index
26264 *
26265 * @return true
26266 **/
26267 bool XFBCaptureInactiveOutputComponentTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26268 {
26269 const Functions& gl = m_context.getRenderContext().getFunctions();
26270 GLenum primitive_type = GL_PATCHES;
26271
26272 if (TEST_VS == test_case_index)
26273 {
26274 primitive_type = GL_POINTS;
26275 }
26276
26277 gl.disable(GL_RASTERIZER_DISCARD);
26278 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26279
26280 gl.beginTransformFeedback(GL_POINTS);
26281 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26282
26283 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26284 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26285
26286 gl.endTransformFeedback();
26287 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26288
26289 return true;
26290 }
26291
26292 /** Get descriptors of buffers necessary for test
26293 *
26294 * @param ignored
26295 * @param out_descriptors Descriptors of buffers used by test
26296 **/
26297 void XFBCaptureInactiveOutputComponentTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26298 bufferDescriptor::Vector& out_descriptors)
26299 {
26300 const Utils::Type& type = Utils::Type::vec4;
26301
26302 /* Test needs single uniform and xfb */
26303 out_descriptors.resize(2);
26304
26305 /* Get references */
26306 bufferDescriptor& uniform = out_descriptors[0];
26307 bufferDescriptor& xfb = out_descriptors[1];
26308
26309 /* Index */
26310 uniform.m_index = 0;
26311 xfb.m_index = 0;
26312
26313 /* Target */
26314 uniform.m_target = Utils::Buffer::Uniform;
26315 xfb.m_target = Utils::Buffer::Transform_feedback;
26316
26317 /* Data */
26318 const std::vector<GLubyte>& goku_data = type.GenerateData();
26319 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26320 const std::vector<GLubyte>& goten_data = type.GenerateData();
26321 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26322 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
26323 const std::vector<GLubyte>& trunks_data = type.GenerateData();
26324 const std::vector<GLubyte>& bra_data = type.GenerateData();
26325 const std::vector<GLubyte>& bulma_data = type.GenerateData();
26326
26327 const GLuint comp_size = Utils::Type::GetTypeSize(type.m_basic_type);
26328 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26329
26330 /* Uniform data */
26331 uniform.m_initial_data.resize(8 * type_size);
26332 memcpy(&uniform.m_initial_data[0] + 0 * type_size, &goku_data[0], type_size);
26333 memcpy(&uniform.m_initial_data[0] + 1 * type_size, &gohan_data[0], type_size);
26334 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
26335 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &chichi_data[0], type_size);
26336 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
26337 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &trunks_data[0], type_size);
26338 memcpy(&uniform.m_initial_data[0] + 6 * type_size, &bra_data[0], type_size);
26339 memcpy(&uniform.m_initial_data[0] + 7 * type_size, &bulma_data[0], type_size);
26340
26341 /* XFB data */
26342 xfb.m_initial_data.resize(8 * type_size);
26343 xfb.m_expected_data.resize(8 * type_size);
26344
26345 for (GLuint i = 0; i < 8 * type_size; ++i)
26346 {
26347 xfb.m_initial_data[i] = (glw::GLubyte)i;
26348 xfb.m_expected_data[i] = (glw::GLubyte)i;
26349 }
26350
26351 /* goku - x, z - 32 */
26352 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 0 * comp_size, &goku_data[0] + 0 * comp_size, comp_size);
26353 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 2 * comp_size, &goku_data[0] + 2 * comp_size, comp_size);
26354
26355 /* gohan - y, w - 0 */
26356 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 1 * comp_size, &gohan_data[0] + 1 * comp_size, comp_size);
26357 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 3 * comp_size, &gohan_data[0] + 3 * comp_size, comp_size);
26358
26359 /* goten - x, y - 16 */
26360 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 0 * comp_size, &goten_data[0] + 0 * comp_size, comp_size);
26361 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 1 * comp_size, &goten_data[0] + 1 * comp_size, comp_size);
26362
26363 /* chichi - z, w - 48 */
26364 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 2 * comp_size, &chichi_data[0] + 2 * comp_size, comp_size);
26365 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 3 * comp_size, &chichi_data[0] + 3 * comp_size, comp_size);
26366
26367 /* vegeta - x - 112 */
26368 memcpy(&xfb.m_expected_data[0] + 7 * type_size + 0 * comp_size, &vegeta_data[0] + 0 * comp_size, comp_size);
26369
26370 /* trunks - y - 96 */
26371 memcpy(&xfb.m_expected_data[0] + 6 * type_size + 1 * comp_size, &trunks_data[0] + 1 * comp_size, comp_size);
26372
26373 /* bra - z - 80 */
26374 memcpy(&xfb.m_expected_data[0] + 5 * type_size + 2 * comp_size, &bra_data[0] + 2 * comp_size, comp_size);
26375
26376 /* bulma - w - 64 */
26377 memcpy(&xfb.m_expected_data[0] + 4 * type_size + 3 * comp_size, &bulma_data[0] + 3 * comp_size, comp_size);
26378 }
26379
26380 /** Get body of main function for given shader stage
26381 *
26382 * @param test_case_index Index of test case
26383 * @param stage Shader stage
26384 * @param out_assignments Set to empty
26385 * @param out_calculations Set to empty
26386 **/
26387 void XFBCaptureInactiveOutputComponentTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26388 std::string& out_assignments, std::string& out_calculations)
26389 {
26390 out_calculations = "";
26391
26392 static const GLchar* vs_tes_gs = " goku.x = uni_goku.x ;\n"
26393 " goku.z = uni_goku.z ;\n"
26394 " gohan.y = uni_gohan.y ;\n"
26395 " gohan.w = uni_gohan.w ;\n"
26396 " goten.x = uni_goten.x ;\n"
26397 " goten.y = uni_goten.y ;\n"
26398 " chichi.z = uni_chichi.z ;\n"
26399 " chichi.w = uni_chichi.w ;\n"
26400 " vegeta.x = uni_vegeta.x ;\n"
26401 " trunks.y = uni_trunks.y ;\n"
26402 " bra.z = uni_bra.z ;\n"
26403 " bulma.w = uni_bulma.w ;\n";
26404 static const GLchar* fs = " fs_out = goku + gohan + goten + chichi + vegeta + trunks + bra + bulma;\n";
26405
26406 const GLchar* assignments = "";
26407
26408 switch (stage)
26409 {
26410 case Utils::Shader::FRAGMENT:
26411 assignments = fs;
26412 break;
26413
26414 case Utils::Shader::GEOMETRY:
26415 if (TEST_GS == test_case_index)
26416 {
26417 assignments = vs_tes_gs;
26418 }
26419 break;
26420
26421 case Utils::Shader::TESS_CTRL:
26422 break;
26423
26424 case Utils::Shader::TESS_EVAL:
26425 if (TEST_TES == test_case_index)
26426 {
26427 assignments = vs_tes_gs;
26428 }
26429 break;
26430
26431 case Utils::Shader::VERTEX:
26432 if (TEST_VS == test_case_index)
26433 {
26434 assignments = vs_tes_gs;
26435 }
26436 break;
26437
26438 default:
26439 TCU_FAIL("Invalid enum");
26440 }
26441
26442 out_assignments = assignments;
26443 }
26444
26445 /** Get interface of shader
26446 *
26447 * @param test_case_index Index of test case
26448 * @param stage Shader stage
26449 * @param out_interface Set to ""
26450 **/
26451 void XFBCaptureInactiveOutputComponentTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26452 std::string& out_interface)
26453 {
26454 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26455 "\n"
26456 "layout (xfb_offset = 2 * sizeof_type) out vec4 goku;\n"
26457 "layout (xfb_offset = 0 * sizeof_type) out vec4 gohan;\n"
26458 "layout (xfb_offset = 1 * sizeof_type) out vec4 goten;\n"
26459 "layout (xfb_offset = 3 * sizeof_type) out vec4 chichi;\n"
26460 "layout (xfb_offset = 7 * sizeof_type) out vec4 vegeta;\n"
26461 "layout (xfb_offset = 6 * sizeof_type) out vec4 trunks;\n"
26462 "layout (xfb_offset = 5 * sizeof_type) out vec4 bra;\n"
26463 "layout (xfb_offset = 4 * sizeof_type) out vec4 bulma;\n"
26464 "\n"
26465 "layout(binding = 0) uniform block {\n"
26466 " vec4 uni_goku;\n"
26467 " vec4 uni_gohan;\n"
26468 " vec4 uni_goten;\n"
26469 " vec4 uni_chichi;\n"
26470 " vec4 uni_vegeta;\n"
26471 " vec4 uni_trunks;\n"
26472 " vec4 uni_bra;\n"
26473 " vec4 uni_bulma;\n"
26474 "};\n";
26475 static const GLchar* fs = "in vec4 vegeta;\n"
26476 "in vec4 trunks;\n"
26477 "in vec4 bra;\n"
26478 "in vec4 bulma;\n"
26479 "in vec4 goku;\n"
26480 "in vec4 gohan;\n"
26481 "in vec4 goten;\n"
26482 "in vec4 chichi;\n"
26483 "\n"
26484 "out vec4 fs_out;\n";
26485
26486 const GLchar* interface = "";
26487
26488 switch (stage)
26489 {
26490 case Utils::Shader::FRAGMENT:
26491 interface = fs;
26492 break;
26493
26494 case Utils::Shader::GEOMETRY:
26495 if (TEST_GS == test_case_index)
26496 {
26497 interface = vs_tes_gs;
26498 }
26499 break;
26500
26501 case Utils::Shader::TESS_CTRL:
26502 break;
26503
26504 case Utils::Shader::TESS_EVAL:
26505 if (TEST_TES == test_case_index)
26506 {
26507 interface = vs_tes_gs;
26508 }
26509 break;
26510
26511 case Utils::Shader::VERTEX:
26512 if (TEST_VS == test_case_index)
26513 {
26514 interface = vs_tes_gs;
26515 }
26516 break;
26517
26518 default:
26519 TCU_FAIL("Invalid enum");
26520 }
26521
26522 out_interface = interface;
26523 }
26524
26525 /** Get source code of shader
26526 *
26527 * @param test_case_index Index of test case
26528 * @param stage Shader stage
26529 *
26530 * @return Source
26531 **/
26532 std::string XFBCaptureInactiveOutputComponentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26533 {
26534 std::string source;
26535
26536 switch (test_case_index)
26537 {
26538 case TEST_VS:
26539 switch (stage)
26540 {
26541 case Utils::Shader::FRAGMENT:
26542 case Utils::Shader::VERTEX:
26543 source = BufferTestBase::getShaderSource(test_case_index, stage);
26544 break;
26545 default:
26546 break;
26547 }
26548 break;
26549
26550 case TEST_TES:
26551 switch (stage)
26552 {
26553 case Utils::Shader::FRAGMENT:
26554 case Utils::Shader::TESS_CTRL:
26555 case Utils::Shader::TESS_EVAL:
26556 case Utils::Shader::VERTEX:
26557 source = BufferTestBase::getShaderSource(test_case_index, stage);
26558 break;
26559 default:
26560 break;
26561 }
26562 break;
26563
26564 case TEST_GS:
26565 source = BufferTestBase::getShaderSource(test_case_index, stage);
26566 break;
26567
26568 default:
26569 TCU_FAIL("Invalid enum");
26570 break;
26571 }
26572
26573 /* */
26574 return source;
26575 }
26576
26577 /** Get name of test case
26578 *
26579 * @param test_case_index Index of test case
26580 *
26581 * @return Name of tested stage
26582 **/
26583 std::string XFBCaptureInactiveOutputComponentTest::getTestCaseName(glw::GLuint test_case_index)
26584 {
26585 const GLchar* name = 0;
26586
26587 switch (test_case_index)
26588 {
26589 case TEST_VS:
26590 name = "vertex";
26591 break;
26592 case TEST_TES:
26593 name = "tessellation evaluation";
26594 break;
26595 case TEST_GS:
26596 name = "geometry";
26597 break;
26598 default:
26599 TCU_FAIL("Invalid enum");
26600 }
26601
26602 return name;
26603 }
26604
26605 /** Returns number of test cases
26606 *
26607 * @return TEST_MAX
26608 **/
26609 glw::GLuint XFBCaptureInactiveOutputComponentTest::getTestCaseNumber()
26610 {
26611 return TEST_MAX;
26612 }
26613
26614 /** Verify contents of buffers
26615 *
26616 * @param buffers Collection of buffers to be verified
26617 *
26618 * @return true if everything is as expected, false otherwise
26619 **/
26620 bool XFBCaptureInactiveOutputComponentTest::verifyBuffers(bufferCollection& buffers)
26621 {
26622 bool result = true;
26623
26624 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26625 Utils::Buffer* buffer = pair.m_buffer;
26626 bufferDescriptor* descriptor = pair.m_descriptor;
26627
26628 /* Get pointer to contents of buffer */
26629 buffer->Bind();
26630 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26631
26632 /* Get pointer to expected data */
26633 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26634
26635 /* Compare */
26636 static const GLuint comp_size = 4;
26637 static const GLuint vec4_size = 16;
26638
26639 int res_goku_x =
26640 memcmp(buffer_data + 2 * vec4_size + 0 * comp_size, expected_data + 2 * vec4_size + 0 * comp_size, comp_size);
26641 int res_goku_z =
26642 memcmp(buffer_data + 2 * vec4_size + 2 * comp_size, expected_data + 2 * vec4_size + 2 * comp_size, comp_size);
26643
26644 int res_gohan_y =
26645 memcmp(buffer_data + 0 * vec4_size + 1 * comp_size, expected_data + 0 * vec4_size + 1 * comp_size, comp_size);
26646 int res_gohan_w =
26647 memcmp(buffer_data + 0 * vec4_size + 3 * comp_size, expected_data + 0 * vec4_size + 3 * comp_size, comp_size);
26648
26649 int res_goten_x =
26650 memcmp(buffer_data + 1 * vec4_size + 0 * comp_size, expected_data + 1 * vec4_size + 0 * comp_size, comp_size);
26651 int res_goten_y =
26652 memcmp(buffer_data + 1 * vec4_size + 1 * comp_size, expected_data + 1 * vec4_size + 1 * comp_size, comp_size);
26653
26654 int res_chichi_z =
26655 memcmp(buffer_data + 3 * vec4_size + 2 * comp_size, expected_data + 3 * vec4_size + 2 * comp_size, comp_size);
26656 int res_chichi_w =
26657 memcmp(buffer_data + 3 * vec4_size + 3 * comp_size, expected_data + 3 * vec4_size + 3 * comp_size, comp_size);
26658
26659 int res_vegeta_x =
26660 memcmp(buffer_data + 7 * vec4_size + 0 * comp_size, expected_data + 7 * vec4_size + 0 * comp_size, comp_size);
26661
26662 int res_trunks_y =
26663 memcmp(buffer_data + 6 * vec4_size + 1 * comp_size, expected_data + 6 * vec4_size + 1 * comp_size, comp_size);
26664
26665 int res_bra_z =
26666 memcmp(buffer_data + 5 * vec4_size + 2 * comp_size, expected_data + 5 * vec4_size + 2 * comp_size, comp_size);
26667
26668 int res_bulma_w =
26669 memcmp(buffer_data + 4 * vec4_size + 3 * comp_size, expected_data + 4 * vec4_size + 3 * comp_size, comp_size);
26670
26671 if ((0 != res_goku_x) || (0 != res_goku_z) || (0 != res_gohan_y) || (0 != res_gohan_w) || (0 != res_goten_x) ||
26672 (0 != res_goten_y) || (0 != res_chichi_z) || (0 != res_chichi_w) || (0 != res_vegeta_x) ||
26673 (0 != res_trunks_y) || (0 != res_bra_z) || (0 != res_bulma_w))
26674 {
26675 m_context.getTestContext().getLog()
26676 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26677 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26678
26679 result = false;
26680 }
26681
26682 /* Release buffer mapping */
26683 buffer->UnMap();
26684
26685 return result;
26686 }
26687
26688 /** Constructor
26689 *
26690 * @param context Test context
26691 **/
26692 XFBCaptureInactiveOutputBlockMemberTest::XFBCaptureInactiveOutputBlockMemberTest(deqp::Context& context)
26693 : BufferTestBase(context, "xfb_capture_inactive_output_block_member",
26694 "Test verifies that inactive block members are captured")
26695 {
26696 /* Nothing to be done here */
26697 }
26698
26699 /** Execute drawArrays for single vertex
26700 *
26701 * @param test_case_index
26702 *
26703 * @return true
26704 **/
26705 bool XFBCaptureInactiveOutputBlockMemberTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26706 {
26707 const Functions& gl = m_context.getRenderContext().getFunctions();
26708 GLenum primitive_type = GL_PATCHES;
26709
26710 if (TEST_VS == test_case_index)
26711 {
26712 primitive_type = GL_POINTS;
26713 }
26714
26715 gl.disable(GL_RASTERIZER_DISCARD);
26716 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26717
26718 gl.beginTransformFeedback(GL_POINTS);
26719 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26720
26721 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26722 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26723
26724 gl.endTransformFeedback();
26725 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26726
26727 return true;
26728 }
26729
26730 /** Get descriptors of buffers necessary for test
26731 *
26732 * @param ignored
26733 * @param out_descriptors Descriptors of buffers used by test
26734 **/
26735 void XFBCaptureInactiveOutputBlockMemberTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26736 bufferDescriptor::Vector& out_descriptors)
26737 {
26738 const Utils::Type& type = Utils::Type::vec4;
26739
26740 /* Test needs single uniform and xfb */
26741 out_descriptors.resize(2);
26742
26743 /* Get references */
26744 bufferDescriptor& uniform = out_descriptors[0];
26745 bufferDescriptor& xfb = out_descriptors[1];
26746
26747 /* Index */
26748 uniform.m_index = 0;
26749 xfb.m_index = 0;
26750
26751 /* Target */
26752 uniform.m_target = Utils::Buffer::Uniform;
26753 xfb.m_target = Utils::Buffer::Transform_feedback;
26754
26755 /* Data */
26756 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26757 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26758
26759 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26760
26761 /* Uniform data */
26762 uniform.m_initial_data.resize(2 * type_size);
26763 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
26764 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
26765
26766 /* XFB data */
26767 xfb.m_initial_data.resize(4 * type_size);
26768 xfb.m_expected_data.resize(4 * type_size);
26769
26770 for (GLuint i = 0; i < 4 * type_size; ++i)
26771 {
26772 xfb.m_initial_data[i] = (glw::GLubyte)i;
26773 xfb.m_expected_data[i] = (glw::GLubyte)i;
26774 }
26775
26776 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
26777 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
26778 }
26779
26780 /** Get body of main function for given shader stage
26781 *
26782 * @param test_case_index Index of test case
26783 * @param stage Shader stage
26784 * @param out_assignments Set to empty
26785 * @param out_calculations Set to empty
26786 **/
26787 void XFBCaptureInactiveOutputBlockMemberTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26788 std::string& out_assignments, std::string& out_calculations)
26789 {
26790 out_calculations = "";
26791
26792 static const GLchar* vs_tes_gs = " chichi = uni_chichi;\n"
26793 " gohan = uni_gohan;\n";
26794 static const GLchar* fs = " fs_out = goten + gohan + chichi;\n";
26795
26796 const GLchar* assignments = "";
26797
26798 switch (stage)
26799 {
26800 case Utils::Shader::FRAGMENT:
26801 assignments = fs;
26802 break;
26803
26804 case Utils::Shader::GEOMETRY:
26805 if (TEST_GS == test_case_index)
26806 {
26807 assignments = vs_tes_gs;
26808 }
26809 break;
26810
26811 case Utils::Shader::TESS_CTRL:
26812 break;
26813
26814 case Utils::Shader::TESS_EVAL:
26815 if (TEST_TES == test_case_index)
26816 {
26817 assignments = vs_tes_gs;
26818 }
26819 break;
26820
26821 case Utils::Shader::VERTEX:
26822 if (TEST_VS == test_case_index)
26823 {
26824 assignments = vs_tes_gs;
26825 }
26826 break;
26827
26828 default:
26829 TCU_FAIL("Invalid enum");
26830 }
26831
26832 out_assignments = assignments;
26833 }
26834
26835 /** Get interface of shader
26836 *
26837 * @param test_case_index Index of test case
26838 * @param stage Shader stage
26839 * @param out_interface Set to ""
26840 **/
26841 void XFBCaptureInactiveOutputBlockMemberTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26842 std::string& out_interface)
26843 {
26844 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26845 "\n"
26846 "layout (xfb_offset = 1 * sizeof_type) out Goku {\n"
26847 " vec4 gohan;\n"
26848 " vec4 goten;\n"
26849 " vec4 chichi;\n"
26850 "};\n"
26851 "\n"
26852 "layout(binding = 0) uniform block {\n"
26853 " vec4 uni_gohan;\n"
26854 " vec4 uni_chichi;\n"
26855 "};\n";
26856 static const GLchar* fs = "in Goku {\n"
26857 " vec4 gohan;\n"
26858 " vec4 goten;\n"
26859 " vec4 chichi;\n"
26860 "};\n"
26861 "out vec4 fs_out;\n";
26862
26863 const GLchar* interface = "";
26864
26865 switch (stage)
26866 {
26867 case Utils::Shader::FRAGMENT:
26868 interface = fs;
26869 break;
26870
26871 case Utils::Shader::GEOMETRY:
26872 if (TEST_GS == test_case_index)
26873 {
26874 interface = vs_tes_gs;
26875 }
26876 break;
26877
26878 case Utils::Shader::TESS_CTRL:
26879 break;
26880
26881 case Utils::Shader::TESS_EVAL:
26882 if (TEST_TES == test_case_index)
26883 {
26884 interface = vs_tes_gs;
26885 }
26886 break;
26887
26888 case Utils::Shader::VERTEX:
26889 if (TEST_VS == test_case_index)
26890 {
26891 interface = vs_tes_gs;
26892 }
26893 break;
26894
26895 default:
26896 TCU_FAIL("Invalid enum");
26897 }
26898
26899 out_interface = interface;
26900 }
26901
26902 /** Get source code of shader
26903 *
26904 * @param test_case_index Index of test case
26905 * @param stage Shader stage
26906 *
26907 * @return Source
26908 **/
26909 std::string XFBCaptureInactiveOutputBlockMemberTest::getShaderSource(GLuint test_case_index,
26910 Utils::Shader::STAGES stage)
26911 {
26912 std::string source;
26913
26914 switch (test_case_index)
26915 {
26916 case TEST_VS:
26917 switch (stage)
26918 {
26919 case Utils::Shader::FRAGMENT:
26920 case Utils::Shader::VERTEX:
26921 source = BufferTestBase::getShaderSource(test_case_index, stage);
26922 break;
26923 default:
26924 break;
26925 }
26926 break;
26927
26928 case TEST_TES:
26929 switch (stage)
26930 {
26931 case Utils::Shader::FRAGMENT:
26932 case Utils::Shader::TESS_CTRL:
26933 case Utils::Shader::TESS_EVAL:
26934 case Utils::Shader::VERTEX:
26935 source = BufferTestBase::getShaderSource(test_case_index, stage);
26936 break;
26937 default:
26938 break;
26939 }
26940 break;
26941
26942 case TEST_GS:
26943 source = BufferTestBase::getShaderSource(test_case_index, stage);
26944 break;
26945
26946 default:
26947 TCU_FAIL("Invalid enum");
26948 break;
26949 }
26950
26951 /* */
26952 return source;
26953 }
26954
26955 /** Get name of test case
26956 *
26957 * @param test_case_index Index of test case
26958 *
26959 * @return Name of tested stage
26960 **/
26961 std::string XFBCaptureInactiveOutputBlockMemberTest::getTestCaseName(glw::GLuint test_case_index)
26962 {
26963 const GLchar* name = 0;
26964
26965 switch (test_case_index)
26966 {
26967 case TEST_VS:
26968 name = "vertex";
26969 break;
26970 case TEST_TES:
26971 name = "tessellation evaluation";
26972 break;
26973 case TEST_GS:
26974 name = "geometry";
26975 break;
26976 default:
26977 TCU_FAIL("Invalid enum");
26978 }
26979
26980 return name;
26981 }
26982
26983 /** Returns number of test cases
26984 *
26985 * @return TEST_MAX
26986 **/
26987 glw::GLuint XFBCaptureInactiveOutputBlockMemberTest::getTestCaseNumber()
26988 {
26989 return TEST_MAX;
26990 }
26991
26992 /** Verify contents of buffers
26993 *
26994 * @param buffers Collection of buffers to be verified
26995 *
26996 * @return true if everything is as expected, false otherwise
26997 **/
26998 bool XFBCaptureInactiveOutputBlockMemberTest::verifyBuffers(bufferCollection& buffers)
26999 {
27000 bool result = true;
27001
27002 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27003 Utils::Buffer* buffer = pair.m_buffer;
27004 bufferDescriptor* descriptor = pair.m_descriptor;
27005
27006 /* Get pointer to contents of buffer */
27007 buffer->Bind();
27008 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27009
27010 /* Get pointer to expected data */
27011 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27012
27013 /* Compare */
27014 static const GLuint vec4_size = 16;
27015
27016 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27017 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27018 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27019
27020 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27021 {
27022 m_context.getTestContext().getLog()
27023 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27024 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27025
27026 result = false;
27027 }
27028
27029 /* Release buffer mapping */
27030 buffer->UnMap();
27031
27032 return result;
27033 }
27034
27035 /** Constructor
27036 *
27037 * @param context Test context
27038 **/
27039 XFBCaptureStructTest::XFBCaptureStructTest(deqp::Context& context)
27040 : BufferTestBase(context, "xfb_capture_struct", "Test verifies that inactive structure members are captured")
27041 {
27042 /* Nothing to be done here */
27043 }
27044
27045 /** Execute drawArrays for single vertex
27046 *
27047 * @param test_case_index
27048 *
27049 * @return true
27050 **/
27051 bool XFBCaptureStructTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
27052 {
27053 const Functions& gl = m_context.getRenderContext().getFunctions();
27054 GLenum primitive_type = GL_PATCHES;
27055
27056 if (TEST_VS == test_case_index)
27057 {
27058 primitive_type = GL_POINTS;
27059 }
27060
27061 gl.disable(GL_RASTERIZER_DISCARD);
27062 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
27063
27064 gl.beginTransformFeedback(GL_POINTS);
27065 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
27066
27067 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
27068 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
27069
27070 gl.endTransformFeedback();
27071 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
27072
27073 return true;
27074 }
27075
27076 /** Get descriptors of buffers necessary for test
27077 *
27078 * @param ignored
27079 * @param out_descriptors Descriptors of buffers used by test
27080 **/
27081 void XFBCaptureStructTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
27082 bufferDescriptor::Vector& out_descriptors)
27083 {
27084 const Utils::Type& type = Utils::Type::vec4;
27085
27086 /* Test needs single uniform and xfb */
27087 out_descriptors.resize(2);
27088
27089 /* Get references */
27090 bufferDescriptor& uniform = out_descriptors[0];
27091 bufferDescriptor& xfb = out_descriptors[1];
27092
27093 /* Index */
27094 uniform.m_index = 0;
27095 xfb.m_index = 0;
27096
27097 /* Target */
27098 uniform.m_target = Utils::Buffer::Uniform;
27099 xfb.m_target = Utils::Buffer::Transform_feedback;
27100
27101 /* Data */
27102 const std::vector<GLubyte>& gohan_data = type.GenerateData();
27103 const std::vector<GLubyte>& chichi_data = type.GenerateData();
27104
27105 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
27106
27107 /* Uniform data */
27108 uniform.m_initial_data.resize(2 * type_size);
27109 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
27110 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
27111
27112 /* XFB data */
27113 xfb.m_initial_data.resize(4 * type_size);
27114 xfb.m_expected_data.resize(4 * type_size);
27115
27116 for (GLuint i = 0; i < 4 * type_size; ++i)
27117 {
27118 xfb.m_initial_data[i] = (glw::GLubyte)i;
27119 xfb.m_expected_data[i] = (glw::GLubyte)i;
27120 }
27121
27122 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
27123 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
27124 }
27125
27126 /** Get body of main function for given shader stage
27127 *
27128 * @param test_case_index Index of test case
27129 * @param stage Shader stage
27130 * @param out_assignments Set to empty
27131 * @param out_calculations Set to empty
27132 **/
27133 void XFBCaptureStructTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
27134 std::string& out_assignments, std::string& out_calculations)
27135 {
27136 out_calculations = "";
27137
27138 static const GLchar* vs_tes_gs = " goku.chichi = uni_chichi;\n"
27139 " goku.gohan = uni_gohan;\n";
27140 static const GLchar* fs = " fs_out = goku.goten + goku.gohan + goku.chichi;\n";
27141
27142 const GLchar* assignments = "";
27143
27144 switch (stage)
27145 {
27146 case Utils::Shader::FRAGMENT:
27147 assignments = fs;
27148 break;
27149
27150 case Utils::Shader::GEOMETRY:
27151 if (TEST_GS == test_case_index)
27152 {
27153 assignments = vs_tes_gs;
27154 }
27155 break;
27156
27157 case Utils::Shader::TESS_CTRL:
27158 break;
27159
27160 case Utils::Shader::TESS_EVAL:
27161 if (TEST_TES == test_case_index)
27162 {
27163 assignments = vs_tes_gs;
27164 }
27165 break;
27166
27167 case Utils::Shader::VERTEX:
27168 if (TEST_VS == test_case_index)
27169 {
27170 assignments = vs_tes_gs;
27171 }
27172 break;
27173
27174 default:
27175 TCU_FAIL("Invalid enum");
27176 }
27177
27178 out_assignments = assignments;
27179 }
27180
27181 /** Get interface of shader
27182 *
27183 * @param test_case_index Index of test case
27184 * @param stage Shader stage
27185 * @param out_interface Set to ""
27186 **/
27187 void XFBCaptureStructTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
27188 std::string& out_interface)
27189 {
27190 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
27191 "\n"
27192 "struct Goku {\n"
27193 " vec4 gohan;\n"
27194 " vec4 goten;\n"
27195 " vec4 chichi;\n"
27196 "};\n"
27197 "\n"
27198 "layout (xfb_offset = sizeof_type) out Goku goku;\n"
27199 "\n"
27200 "layout(binding = 0, std140) uniform block {\n"
27201 " vec4 uni_gohan;\n"
27202 " vec4 uni_chichi;\n"
27203 "};\n";
27204 static const GLchar* fs = "struct Goku {\n"
27205 " vec4 gohan;\n"
27206 " vec4 goten;\n"
27207 " vec4 chichi;\n"
27208 "};\n"
27209 "\n"
27210 "in Goku goku;\n"
27211 "\n"
27212 "out vec4 fs_out;\n";
27213
27214 const GLchar* interface = "";
27215
27216 switch (stage)
27217 {
27218 case Utils::Shader::FRAGMENT:
27219 interface = fs;
27220 break;
27221
27222 case Utils::Shader::GEOMETRY:
27223 if (TEST_GS == test_case_index)
27224 {
27225 interface = vs_tes_gs;
27226 }
27227 break;
27228
27229 case Utils::Shader::TESS_CTRL:
27230 break;
27231
27232 case Utils::Shader::TESS_EVAL:
27233 if (TEST_TES == test_case_index)
27234 {
27235 interface = vs_tes_gs;
27236 }
27237 break;
27238
27239 case Utils::Shader::VERTEX:
27240 if (TEST_VS == test_case_index)
27241 {
27242 interface = vs_tes_gs;
27243 }
27244 break;
27245
27246 default:
27247 TCU_FAIL("Invalid enum");
27248 }
27249
27250 out_interface = interface;
27251 }
27252
27253 /** Get source code of shader
27254 *
27255 * @param test_case_index Index of test case
27256 * @param stage Shader stage
27257 *
27258 * @return Source
27259 **/
27260 std::string XFBCaptureStructTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27261 {
27262 std::string source;
27263
27264 switch (test_case_index)
27265 {
27266 case TEST_VS:
27267 switch (stage)
27268 {
27269 case Utils::Shader::FRAGMENT:
27270 case Utils::Shader::VERTEX:
27271 source = BufferTestBase::getShaderSource(test_case_index, stage);
27272 break;
27273 default:
27274 break;
27275 }
27276 break;
27277
27278 case TEST_TES:
27279 switch (stage)
27280 {
27281 case Utils::Shader::FRAGMENT:
27282 case Utils::Shader::TESS_CTRL:
27283 case Utils::Shader::TESS_EVAL:
27284 case Utils::Shader::VERTEX:
27285 source = BufferTestBase::getShaderSource(test_case_index, stage);
27286 break;
27287 default:
27288 break;
27289 }
27290 break;
27291
27292 case TEST_GS:
27293 source = BufferTestBase::getShaderSource(test_case_index, stage);
27294 break;
27295
27296 default:
27297 TCU_FAIL("Invalid enum");
27298 break;
27299 }
27300
27301 /* */
27302 return source;
27303 }
27304
27305 /** Get name of test case
27306 *
27307 * @param test_case_index Index of test case
27308 *
27309 * @return Name of tested stage
27310 **/
27311 std::string XFBCaptureStructTest::getTestCaseName(glw::GLuint test_case_index)
27312 {
27313 const GLchar* name = 0;
27314
27315 switch (test_case_index)
27316 {
27317 case TEST_VS:
27318 name = "vertex";
27319 break;
27320 case TEST_TES:
27321 name = "tessellation evaluation";
27322 break;
27323 case TEST_GS:
27324 name = "geometry";
27325 break;
27326 default:
27327 TCU_FAIL("Invalid enum");
27328 }
27329
27330 return name;
27331 }
27332
27333 /** Returns number of test cases
27334 *
27335 * @return TEST_MAX
27336 **/
27337 glw::GLuint XFBCaptureStructTest::getTestCaseNumber()
27338 {
27339 return TEST_MAX;
27340 }
27341
27342 /** Verify contents of buffers
27343 *
27344 * @param buffers Collection of buffers to be verified
27345 *
27346 * @return true if everything is as expected, false otherwise
27347 **/
27348 bool XFBCaptureStructTest::verifyBuffers(bufferCollection& buffers)
27349 {
27350 bool result = true;
27351
27352 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27353 Utils::Buffer* buffer = pair.m_buffer;
27354 bufferDescriptor* descriptor = pair.m_descriptor;
27355
27356 /* Get pointer to contents of buffer */
27357 buffer->Bind();
27358 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27359
27360 /* Get pointer to expected data */
27361 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27362
27363 /* Compare */
27364 static const GLuint vec4_size = 16;
27365
27366 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27367 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27368 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27369
27370 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27371 {
27372 m_context.getTestContext().getLog()
27373 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27374 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27375
27376 result = false;
27377 }
27378
27379 /* Release buffer mapping */
27380 buffer->UnMap();
27381
27382 return result;
27383 }
27384
27385 /** Constructor
27386 *
27387 * @param context Test framework context
27388 **/
27389 XFBCaptureUnsizedArrayTest::XFBCaptureUnsizedArrayTest(deqp::Context& context)
27390 : NegativeTestBase(context, "xfb_capture_unsized_array",
27391 "Test verifies that compiler reports error when unsized array is qualified with xfb_offset")
27392 {
27393 }
27394
27395 /** Source for given test case and stage
27396 *
27397 * @param test_case_index Index of test case
27398 * @param stage Shader stage
27399 *
27400 * @return Shader source
27401 **/
27402 std::string XFBCaptureUnsizedArrayTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27403 {
27404 static const GLchar* var_definition = "layout (xfb_offset = 0) out vec4 gokuARRAY[];\n";
27405 static const GLchar* var_use = " gokuINDEX[0] = result / 2;\n";
27406 static const GLchar* fs = "#version 430 core\n"
27407 "#extension GL_ARB_enhanced_layouts : require\n"
27408 "\n"
27409 "in vec4 gs_fs;\n"
27410 "out vec4 fs_out;\n"
27411 "\n"
27412 "void main()\n"
27413 "{\n"
27414 " fs_out = gs_fs;\n"
27415 "}\n"
27416 "\n";
27417 static const GLchar* gs_tested = "#version 430 core\n"
27418 "#extension GL_ARB_enhanced_layouts : require\n"
27419 "\n"
27420 "layout(points) in;\n"
27421 "layout(triangle_strip, max_vertices = 4) out;\n"
27422 "\n"
27423 "VAR_DEFINITION"
27424 "\n"
27425 "in vec4 tes_gs[];\n"
27426 "out vec4 gs_fs;\n"
27427 "\n"
27428 "void main()\n"
27429 "{\n"
27430 " vec4 result = tes_gs[0];\n"
27431 "\n"
27432 "VARIABLE_USE"
27433 "\n"
27434 " gs_fs = result;\n"
27435 " gl_Position = vec4(-1, -1, 0, 1);\n"
27436 " EmitVertex();\n"
27437 " gs_fs = result;\n"
27438 " gl_Position = vec4(-1, 1, 0, 1);\n"
27439 " EmitVertex();\n"
27440 " gs_fs = result;\n"
27441 " gl_Position = vec4(1, -1, 0, 1);\n"
27442 " EmitVertex();\n"
27443 " gs_fs = result;\n"
27444 " gl_Position = vec4(1, 1, 0, 1);\n"
27445 " EmitVertex();\n"
27446 "}\n"
27447 "\n";
27448 static const GLchar* tcs = "#version 430 core\n"
27449 "#extension GL_ARB_enhanced_layouts : require\n"
27450 "\n"
27451 "layout(vertices = 1) out;\n"
27452 "\n"
27453 "in vec4 vs_tcs[];\n"
27454 "out vec4 tcs_tes[];\n"
27455 "\n"
27456 "void main()\n"
27457 "{\n"
27458 "\n"
27459 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
27460 "\n"
27461 " gl_TessLevelOuter[0] = 1.0;\n"
27462 " gl_TessLevelOuter[1] = 1.0;\n"
27463 " gl_TessLevelOuter[2] = 1.0;\n"
27464 " gl_TessLevelOuter[3] = 1.0;\n"
27465 " gl_TessLevelInner[0] = 1.0;\n"
27466 " gl_TessLevelInner[1] = 1.0;\n"
27467 "}\n"
27468 "\n";
27469 static const GLchar* tcs_tested = "#version 430 core\n"
27470 "#extension GL_ARB_enhanced_layouts : require\n"
27471 "\n"
27472 "layout(vertices = 1) out;\n"
27473 "\n"
27474 "VAR_DEFINITION"
27475 "\n"
27476 "in vec4 vs_tcs[];\n"
27477 "out vec4 tcs_tes[];\n"
27478 "\n"
27479 "void main()\n"
27480 "{\n"
27481 " vec4 result = vs_tcs[gl_InvocationID];\n"
27482 "\n"
27483 "VARIABLE_USE"
27484 "\n"
27485 " tcs_tes[gl_InvocationID] = result;\n"
27486 "\n"
27487 " gl_TessLevelOuter[0] = 1.0;\n"
27488 " gl_TessLevelOuter[1] = 1.0;\n"
27489 " gl_TessLevelOuter[2] = 1.0;\n"
27490 " gl_TessLevelOuter[3] = 1.0;\n"
27491 " gl_TessLevelInner[0] = 1.0;\n"
27492 " gl_TessLevelInner[1] = 1.0;\n"
27493 "}\n"
27494 "\n";
27495 static const GLchar* tes_tested = "#version 430 core\n"
27496 "#extension GL_ARB_enhanced_layouts : require\n"
27497 "\n"
27498 "layout(isolines, point_mode) in;\n"
27499 "\n"
27500 "VAR_DEFINITION"
27501 "\n"
27502 "in vec4 tcs_tes[];\n"
27503 "out vec4 tes_gs;\n"
27504 "\n"
27505 "void main()\n"
27506 "{\n"
27507 " vec4 result = tcs_tes[0];\n"
27508 "\n"
27509 "VARIABLE_USE"
27510 "\n"
27511 " tes_gs += result;\n"
27512 "}\n"
27513 "\n";
27514 static const GLchar* vs = "#version 430 core\n"
27515 "#extension GL_ARB_enhanced_layouts : require\n"
27516 "\n"
27517 "in vec4 in_vs;\n"
27518 "out vec4 vs_tcs;\n"
27519 "\n"
27520 "void main()\n"
27521 "{\n"
27522 " vs_tcs = in_vs;\n"
27523 "}\n"
27524 "\n";
27525 static const GLchar* vs_tested = "#version 430 core\n"
27526 "#extension GL_ARB_enhanced_layouts : require\n"
27527 "\n"
27528 "VAR_DEFINITION"
27529 "\n"
27530 "in vec4 in_vs;\n"
27531 "out vec4 vs_tcs;\n"
27532 "\n"
27533 "void main()\n"
27534 "{\n"
27535 " vec4 result = in_vs;\n"
27536 "\n"
27537 "VARIABLE_USE"
27538 "\n"
27539 " vs_tcs = result;\n"
27540 "}\n"
27541 "\n";
27542
27543 std::string source;
27544 testCase& test_case = m_test_cases[test_case_index];
27545
27546 if (test_case.m_stage == stage)
27547 {
27548 const GLchar* array = "";
27549 const GLchar* index = "";
27550 size_t position = 0;
27551
27552 switch (stage)
27553 {
27554 case Utils::Shader::GEOMETRY:
27555 source = gs_tested;
27556 array = "[]";
27557 index = "[0]";
27558 break;
27559 case Utils::Shader::TESS_CTRL:
27560 source = tcs_tested;
27561 array = "[]";
27562 index = "[gl_InvocationID]";
27563 break;
27564 case Utils::Shader::TESS_EVAL:
27565 source = tes_tested;
27566 array = "[]";
27567 index = "[0]";
27568 break;
27569 case Utils::Shader::VERTEX:
27570 source = vs_tested;
27571 break;
27572 default:
27573 TCU_FAIL("Invalid enum");
27574 }
27575
27576 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
27577 position = 0;
27578 Utils::replaceToken("ARRAY", position, array, source);
27579 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
27580
27581 Utils::replaceAllTokens("INDEX", index, source);
27582 }
27583 else
27584 {
27585 switch (test_case.m_stage)
27586 {
27587 case Utils::Shader::GEOMETRY:
27588 switch (stage)
27589 {
27590 case Utils::Shader::FRAGMENT:
27591 source = fs;
27592 break;
27593 case Utils::Shader::VERTEX:
27594 source = vs;
27595 break;
27596 default:
27597 source = "";
27598 }
27599 break;
27600 case Utils::Shader::TESS_CTRL:
27601 switch (stage)
27602 {
27603 case Utils::Shader::FRAGMENT:
27604 source = fs;
27605 break;
27606 case Utils::Shader::VERTEX:
27607 source = vs;
27608 break;
27609 default:
27610 source = "";
27611 }
27612 break;
27613 case Utils::Shader::TESS_EVAL:
27614 switch (stage)
27615 {
27616 case Utils::Shader::FRAGMENT:
27617 source = fs;
27618 break;
27619 case Utils::Shader::TESS_CTRL:
27620 source = tcs;
27621 break;
27622 case Utils::Shader::VERTEX:
27623 source = vs;
27624 break;
27625 default:
27626 source = "";
27627 }
27628 break;
27629 case Utils::Shader::VERTEX:
27630 switch (stage)
27631 {
27632 case Utils::Shader::FRAGMENT:
27633 source = fs;
27634 break;
27635 default:
27636 source = "";
27637 }
27638 break;
27639 default:
27640 TCU_FAIL("Invalid enum");
27641 break;
27642 }
27643 }
27644
27645 return source;
27646 }
27647
27648 /** Get description of test case
27649 *
27650 * @param test_case_index Index of test case
27651 *
27652 * @return Test case description
27653 **/
27654 std::string XFBCaptureUnsizedArrayTest::getTestCaseName(GLuint test_case_index)
27655 {
27656 std::stringstream stream;
27657 testCase& test_case = m_test_cases[test_case_index];
27658
27659 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
27660
27661 return stream.str();
27662 }
27663
27664 /** Get number of test cases
27665 *
27666 * @return Number of test cases
27667 **/
27668 GLuint XFBCaptureUnsizedArrayTest::getTestCaseNumber()
27669 {
27670 return static_cast<GLuint>(m_test_cases.size());
27671 }
27672
27673 /** Selects if "compute" stage is relevant for test
27674 *
27675 * @param ignored
27676 *
27677 * @return false
27678 **/
27679 bool XFBCaptureUnsizedArrayTest::isComputeRelevant(GLuint /* test_case_index */)
27680 {
27681 return false;
27682 }
27683
27684 /** Prepare all test cases
27685 *
27686 **/
27687 void XFBCaptureUnsizedArrayTest::testInit()
27688 {
27689 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
27690 {
27691 /* Not aplicable for */
27692 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
27693 (Utils::Shader::GEOMETRY == stage) || (Utils::Shader::TESS_EVAL == stage))
27694 {
27695 continue;
27696 }
27697
27698 testCase test_case = { (Utils::Shader::STAGES)stage };
27699
27700 m_test_cases.push_back(test_case);
27701 }
27702 }
27703 } /* EnhancedLayouts namespace */
27704
27705 /** Constructor.
27706 *
27707 * @param context Rendering context.
27708 **/
EnhancedLayoutsTests(deqp::Context & context)27709 EnhancedLayoutsTests::EnhancedLayoutsTests(deqp::Context& context)
27710 : TestCaseGroup(context, "enhanced_layouts", "Verifies \"enhanced layouts\" functionality")
27711 {
27712 /* Left blank on purpose */
27713 }
27714
27715 /** Initializes a texture_storage_multisample test group.
27716 *
27717 **/
init(void)27718 void EnhancedLayoutsTests::init(void)
27719 {
27720 addChild(new EnhancedLayouts::APIConstantValuesTest(m_context));
27721 addChild(new EnhancedLayouts::APIErrorsTest(m_context));
27722 addChild(new EnhancedLayouts::GLSLContantValuesTest(m_context));
27723 addChild(new EnhancedLayouts::GLSLContantImmutablityTest(m_context));
27724 addChild(new EnhancedLayouts::GLSLConstantIntegralExpressionTest(m_context));
27725 addChild(new EnhancedLayouts::UniformBlockLayoutQualifierConflictTest(m_context));
27726 addChild(new EnhancedLayouts::SSBMemberInvalidOffsetAlignmentTest(m_context));
27727 addChild(new EnhancedLayouts::SSBMemberOverlappingOffsetsTest(m_context));
27728 addChild(new EnhancedLayouts::VaryingExceedingComponentsTest(m_context));
27729 addChild(new EnhancedLayouts::VaryingComponentOfInvalidTypeTest(m_context));
27730 addChild(new EnhancedLayouts::OutputComponentAliasingTest(m_context));
27731 addChild(new EnhancedLayouts::VertexAttribLocationAPITest(m_context));
27732 addChild(new EnhancedLayouts::XFBInputTest(m_context));
27733 addChild(new EnhancedLayouts::XFBAllStagesTest(m_context));
27734 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputVariableTest(m_context));
27735 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputComponentTest(m_context));
27736 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputBlockMemberTest(m_context));
27737 addChild(new EnhancedLayouts::XFBStrideTest(m_context));
27738
27739 addChild(new EnhancedLayouts::UniformBlockMemberOffsetAndAlignTest(m_context));
27740 addChild(new EnhancedLayouts::UniformBlockMemberInvalidOffsetAlignmentTest(m_context));
27741 addChild(new EnhancedLayouts::UniformBlockMemberOverlappingOffsetsTest(m_context));
27742 addChild(new EnhancedLayouts::UniformBlockMemberAlignNonPowerOf2Test(m_context));
27743 addChild(new EnhancedLayouts::SSBLayoutQualifierConflictTest(m_context));
27744 addChild(new EnhancedLayouts::SSBMemberAlignNonPowerOf2Test(m_context));
27745 addChild(new EnhancedLayouts::SSBAlignmentTest(m_context));
27746 addChild(new EnhancedLayouts::VaryingStructureMemberLocationTest(m_context));
27747 addChild(new EnhancedLayouts::VaryingBlockAutomaticMemberLocationsTest(m_context));
27748 addChild(new EnhancedLayouts::VaryingComponentWithoutLocationTest(m_context));
27749 addChild(new EnhancedLayouts::InputComponentAliasingTest(m_context));
27750 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedTypesTest(m_context));
27751 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedInterpolationTest(m_context));
27752 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(m_context));
27753 addChild(new EnhancedLayouts::XFBStrideOfEmptyListTest(m_context));
27754 addChild(new EnhancedLayouts::XFBStrideOfEmptyListAndAPITest(m_context));
27755 addChild(new EnhancedLayouts::XFBTooSmallStrideTest(m_context));
27756 addChild(new EnhancedLayouts::XFBBlockMemberStrideTest(m_context));
27757 addChild(new EnhancedLayouts::XFBDuplicatedStrideTest(m_context));
27758 addChild(new EnhancedLayouts::XFBGetProgramResourceAPITest(m_context));
27759 addChild(new EnhancedLayouts::XFBMultipleVertexStreamsTest(m_context));
27760 addChild(new EnhancedLayouts::XFBExceedBufferLimitTest(m_context));
27761 addChild(new EnhancedLayouts::XFBExceedOffsetLimitTest(m_context));
27762 addChild(new EnhancedLayouts::XFBBlockMemberBufferTest(m_context));
27763 addChild(new EnhancedLayouts::XFBOutputOverlappingTest(m_context));
27764 addChild(new EnhancedLayouts::XFBInvalidOffsetAlignmentTest(m_context));
27765 addChild(new EnhancedLayouts::XFBCaptureStructTest(m_context));
27766 addChild(new EnhancedLayouts::XFBCaptureUnsizedArrayTest(m_context));
27767 addChild(new EnhancedLayouts::UniformBlockAlignmentTest(m_context));
27768 addChild(new EnhancedLayouts::SSBMemberOffsetAndAlignTest(m_context));
27769 addChild(new EnhancedLayouts::VertexAttribLocationsTest(m_context));
27770 addChild(new EnhancedLayouts::VaryingLocationsTest(m_context));
27771 addChild(new EnhancedLayouts::VaryingArrayLocationsTest(m_context));
27772 addChild(new EnhancedLayouts::VaryingStructureLocationsTest(m_context));
27773 addChild(new EnhancedLayouts::VaryingBlockLocationsTest(m_context));
27774 addChild(new EnhancedLayouts::VaryingBlockMemberLocationsTest(m_context));
27775 addChild(new EnhancedLayouts::XFBVariableStrideTest(m_context));
27776 addChild(new EnhancedLayouts::XFBBlockStrideTest(m_context));
27777 addChild(new EnhancedLayouts::XFBOverrideQualifiersWithAPITest(m_context));
27778 addChild(new EnhancedLayouts::XFBVertexStreamsTest(m_context));
27779 addChild(new EnhancedLayouts::XFBGlobalBufferTest(m_context));
27780 addChild(new EnhancedLayouts::FragmentDataLocationAPITest(m_context));
27781 addChild(new EnhancedLayouts::VaryingLocationLimitTest(m_context));
27782 addChild(new EnhancedLayouts::VaryingComponentsTest(m_context));
27783 addChild(new EnhancedLayouts::VaryingArrayComponentsTest(m_context));
27784 }
27785
27786 } /* gl4cts namespace */
27787