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 "gluShaderUtil.hpp"
34 #include "gluStrUtil.hpp"
35 #include "glwEnums.hpp"
36 #include "glwFunctions.hpp"
37 #include "tcuTestLog.hpp"
38
39 #include <algorithm>
40 #include <iomanip>
41 #include <string>
42 #include <vector>
43
44 /* DEBUG */
45 #define USE_NSIGHT 0
46 #define DEBUG_ENBALE_MESSAGE_CALLBACK 0
47 #define DEBUG_NEG_LOG_ERROR 0
48 #define DEBUG_NEG_REMOVE_ERROR 0
49 #define DEBUG_REPLACE_TOKEN 0
50 #define DEBUG_REPEAT_TEST_CASE 0
51 #define DEBUG_REPEATED_TEST_CASE 0
52
53 /* Texture test base */
54 #define DEBUG_TTB_VERIFICATION_SNIPPET_STAGE 0
55 #define DEBUG_TTB_VERIFICATION_SNIPPET_VARIABLE 0
56
57 /* Tests */
58 #define DEBUG_VERTEX_ATTRIB_LOCATIONS_TEST_VARIABLE 0
59
60 /* WORKAROUNDS */
61 #define WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST 0
62 #define WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST 0
63 #define WRKARD_UNIFORMBLOCKALIGNMENT 0
64 #define WRKARD_VARYINGLOCATIONSTEST 0
65
66 using namespace glw;
67
68 namespace gl4cts
69 {
70 namespace EnhancedLayouts
71 {
72 namespace Utils
73 {
74 /** Constants used by "random" generators **/
75 static const GLuint s_rand_start = 3;
76 static const GLuint s_rand_max = 16;
77 static const GLuint s_rand_max_half = s_rand_max / 2;
78
79 /** Seed used by "random" generators **/
80 static GLuint s_rand = s_rand_start;
81
82 /** Get "random" unsigned int value
83 *
84 * @return Value
85 **/
GetRandUint()86 static GLuint GetRandUint()
87 {
88 const GLuint rand = s_rand++;
89
90 if (s_rand_max <= s_rand)
91 {
92 s_rand = s_rand_start;
93 }
94
95 return rand;
96 }
97
98 /** Get "random" int value
99 *
100 * @return Value
101 **/
GetRandInt()102 GLint GetRandInt()
103 {
104 const GLint rand = GetRandUint() - s_rand_max_half;
105
106 return rand;
107 }
108
109 /** Get "random" double value
110 *
111 * @return Value
112 **/
GetRandDouble()113 GLdouble GetRandDouble()
114 {
115 const GLint rand = GetRandInt();
116
117 GLdouble result = (GLfloat)rand / (GLdouble)s_rand_max_half;
118
119 return result;
120 }
121
122 /** Get "random" float value
123 *
124 * @return Value
125 **/
GetRandFloat()126 GLfloat GetRandFloat()
127 {
128 const GLint rand = GetRandInt();
129
130 GLfloat result = (GLfloat)rand / (GLfloat)s_rand_max_half;
131
132 return result;
133 }
134
135 /** String used by list routines **/
136 static const GLchar* const g_list = "LIST";
137
138 /** Type constants **/
139 const Type Type::_double = Type::GetType(Type::Double, 1, 1);
140 const Type Type::dmat2 = Type::GetType(Type::Double, 2, 2);
141 const Type Type::dmat2x3 = Type::GetType(Type::Double, 2, 3);
142 const Type Type::dmat2x4 = Type::GetType(Type::Double, 2, 4);
143 const Type Type::dmat3x2 = Type::GetType(Type::Double, 3, 2);
144 const Type Type::dmat3 = Type::GetType(Type::Double, 3, 3);
145 const Type Type::dmat3x4 = Type::GetType(Type::Double, 3, 4);
146 const Type Type::dmat4x2 = Type::GetType(Type::Double, 4, 2);
147 const Type Type::dmat4x3 = Type::GetType(Type::Double, 4, 3);
148 const Type Type::dmat4 = Type::GetType(Type::Double, 4, 4);
149 const Type Type::dvec2 = Type::GetType(Type::Double, 1, 2);
150 const Type Type::dvec3 = Type::GetType(Type::Double, 1, 3);
151 const Type Type::dvec4 = Type::GetType(Type::Double, 1, 4);
152 const Type Type::_int = Type::GetType(Type::Int, 1, 1);
153 const Type Type::ivec2 = Type::GetType(Type::Int, 1, 2);
154 const Type Type::ivec3 = Type::GetType(Type::Int, 1, 3);
155 const Type Type::ivec4 = Type::GetType(Type::Int, 1, 4);
156 const Type Type::_float = Type::GetType(Type::Float, 1, 1);
157 const Type Type::mat2 = Type::GetType(Type::Float, 2, 2);
158 const Type Type::mat2x3 = Type::GetType(Type::Float, 2, 3);
159 const Type Type::mat2x4 = Type::GetType(Type::Float, 2, 4);
160 const Type Type::mat3x2 = Type::GetType(Type::Float, 3, 2);
161 const Type Type::mat3 = Type::GetType(Type::Float, 3, 3);
162 const Type Type::mat3x4 = Type::GetType(Type::Float, 3, 4);
163 const Type Type::mat4x2 = Type::GetType(Type::Float, 4, 2);
164 const Type Type::mat4x3 = Type::GetType(Type::Float, 4, 3);
165 const Type Type::mat4 = Type::GetType(Type::Float, 4, 4);
166 const Type Type::vec2 = Type::GetType(Type::Float, 1, 2);
167 const Type Type::vec3 = Type::GetType(Type::Float, 1, 3);
168 const Type Type::vec4 = Type::GetType(Type::Float, 1, 4);
169 const Type Type::uint = Type::GetType(Type::Uint, 1, 1);
170 const Type Type::uvec2 = Type::GetType(Type::Uint, 1, 2);
171 const Type Type::uvec3 = Type::GetType(Type::Uint, 1, 3);
172 const Type Type::uvec4 = Type::GetType(Type::Uint, 1, 4);
173
174 /** Generate data for type. This routine follows STD140 rules
175 *
176 * @return Vector of bytes filled with data
177 **/
GenerateData() const178 std::vector<GLubyte> Type::GenerateData() const
179 {
180 const GLuint alignment = GetActualAlignment(0, false);
181 const GLuint padding = alignment - GetTypeSize(m_basic_type) * m_n_rows;
182 const GLuint data_size = alignment * m_n_columns - padding;
183
184 std::vector<GLubyte> data;
185 data.resize(data_size);
186
187 for (GLuint column = 0; column < m_n_columns; ++column)
188 {
189 GLvoid* ptr = (GLvoid*)&data[column * alignment];
190
191 switch (m_basic_type)
192 {
193 case Double:
194 {
195 GLdouble* d_ptr = (GLdouble*)ptr;
196
197 for (GLuint i = 0; i < m_n_rows; ++i)
198 {
199 d_ptr[i] = GetRandDouble();
200 }
201 }
202 break;
203 case Float:
204 {
205 GLfloat* f_ptr = (GLfloat*)ptr;
206
207 for (GLuint i = 0; i < m_n_rows; ++i)
208 {
209 f_ptr[i] = GetRandFloat();
210 }
211 }
212 break;
213 case Int:
214 {
215 GLint* i_ptr = (GLint*)ptr;
216
217 for (GLuint i = 0; i < m_n_rows; ++i)
218 {
219 i_ptr[i] = GetRandInt();
220 }
221 }
222 break;
223 case Uint:
224 {
225 GLuint* ui_ptr = (GLuint*)ptr;
226
227 for (GLuint i = 0; i < m_n_rows; ++i)
228 {
229 ui_ptr[i] = GetRandUint();
230 }
231 }
232 break;
233 }
234 }
235
236 return data;
237 }
238
239 /** Generate data for type. This routine packs data tightly.
240 *
241 * @return Vector of bytes filled with data
242 **/
GenerateDataPacked() const243 std::vector<GLubyte> Type::GenerateDataPacked() const
244 {
245 const GLuint basic_size = GetTypeSize(m_basic_type);
246 const GLuint n_elements = m_n_columns * m_n_rows;
247 const GLuint size = basic_size * n_elements;
248
249 std::vector<GLubyte> data;
250 data.resize(size);
251
252 GLvoid* ptr = (GLvoid*)&data[0];
253
254 switch (m_basic_type)
255 {
256 case Double:
257 {
258 GLdouble* d_ptr = (GLdouble*)ptr;
259
260 for (GLuint i = 0; i < n_elements; ++i)
261 {
262 d_ptr[i] = GetRandDouble();
263 }
264 }
265 break;
266 case Float:
267 {
268 GLfloat* f_ptr = (GLfloat*)ptr;
269
270 for (GLuint i = 0; i < n_elements; ++i)
271 {
272 f_ptr[i] = GetRandFloat();
273 }
274 }
275 break;
276 case Int:
277 {
278 GLint* i_ptr = (GLint*)ptr;
279
280 for (GLuint i = 0; i < n_elements; ++i)
281 {
282 i_ptr[i] = GetRandInt();
283 }
284 }
285 break;
286 case Uint:
287 {
288 GLuint* ui_ptr = (GLuint*)ptr;
289
290 for (GLuint i = 0; i < n_elements; ++i)
291 {
292 ui_ptr[i] = GetRandUint();
293 }
294 }
295 break;
296 }
297
298 return data;
299 }
300
301 /** Calculate "actual alignment". It work under assumption that align value is valid
302 *
303 * @param align Requested alignment, eg with "align" qualifier
304 * @param is_array Selects if an array of type or single instance should be considered
305 *
306 * @return Calculated value
307 **/
GetActualAlignment(GLuint align,bool is_array) const308 GLuint Type::GetActualAlignment(GLuint align, bool is_array) const
309 {
310 const GLuint base_alignment = GetBaseAlignment(is_array);
311
312 return std::max(align, base_alignment);
313 }
314
315 /** Align given ofset with specified alignment
316 *
317 * @param offset Offset
318 * @param alignment Alignment
319 *
320 * @return Calculated value
321 **/
align(GLuint offset,GLuint alignment)322 GLuint align(GLuint offset, GLuint alignment)
323 {
324 const GLuint rest = offset % alignment;
325
326 if (0 != rest)
327 {
328 GLuint missing = alignment - rest;
329 offset += missing;
330 }
331
332 return offset;
333 }
334
335 /** Calculate "actual offset"
336 *
337 * @param start_offset Requested offset
338 * @param actual_alignment Actual alignemnt
339 *
340 * @return Calculated value
341 **/
GetActualOffset(GLuint start_offset,GLuint actual_alignment)342 GLuint Type::GetActualOffset(GLuint start_offset, GLuint actual_alignment)
343 {
344 GLuint offset = align(start_offset, actual_alignment);
345
346 return offset;
347 }
348
349 /** Calculate "base alignment" for given type
350 *
351 * @param is_array Select if array or single instance should be considered
352 *
353 * @return Calculated value
354 **/
GetBaseAlignment(bool is_array) const355 GLuint Type::GetBaseAlignment(bool is_array) const
356 {
357 GLuint elements = 1;
358
359 switch (m_n_rows)
360 {
361 case 2:
362 elements = 2;
363 break;
364 case 3:
365 case 4:
366 elements = 4;
367 break;
368 default:
369 break;
370 }
371
372 GLuint N = GetTypeSize(m_basic_type);
373 GLuint alignment = N * elements;
374
375 if ((true == is_array) || (1 != m_n_columns))
376 {
377 alignment = align(alignment, 16 /* vec4 alignment */);
378 }
379
380 return alignment;
381 }
382
383 /** Returns string representing GLSL constructor of type with arguments provided in data
384 *
385 * @param data Array of values that will be used as construcotr arguments.
386 * It is interpreted as tightly packed array of type matching this type.
387 *
388 * @return String in form "Type(args)"
389 **/
GetGLSLConstructor(const GLvoid * data) const390 std::string Type::GetGLSLConstructor(const GLvoid* data) const
391 {
392 const GLchar* type = GetGLSLTypeName();
393
394 std::stringstream stream;
395
396 stream << type << "(";
397
398 /* Scalar or vector */
399 if (1 == m_n_columns)
400 {
401 for (GLuint row = 0; row < m_n_rows; ++row)
402 {
403 switch (m_basic_type)
404 {
405 case Double:
406 stream << ((GLdouble*)data)[row];
407 break;
408 case Float:
409 stream << ((GLfloat*)data)[row];
410 break;
411 case Int:
412 stream << ((GLint*)data)[row];
413 break;
414 case Uint:
415 stream << ((GLuint*)data)[row];
416 break;
417 }
418
419 if (row + 1 != m_n_rows)
420 {
421 stream << ", ";
422 }
423 }
424 }
425 else /* Matrix: mat(vec(), vec() .. ) */
426 {
427 const GLuint basic_size = GetTypeSize(m_basic_type);
428 // 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)
429 const GLuint column_stride = m_n_rows * basic_size;
430 const Type column_type = GetType(m_basic_type, 1, m_n_rows);
431
432 for (GLuint column = 0; column < m_n_columns; ++column)
433 {
434 const GLuint column_offset = column * column_stride;
435 const GLvoid* column_data = (GLubyte*)data + column_offset;
436
437 stream << column_type.GetGLSLConstructor(column_data);
438
439 if (column + 1 != m_n_columns)
440 {
441 stream << ", ";
442 }
443 }
444 }
445
446 stream << ")";
447
448 return stream.str();
449 }
450
451 /** Get glsl name of the type
452 *
453 * @return Name of glsl type
454 **/
GetGLSLTypeName() const455 const glw::GLchar* Type::GetGLSLTypeName() const
456 {
457 static const GLchar* float_lut[4][4] = {
458 { "float", "vec2", "vec3", "vec4" },
459 { 0, "mat2", "mat2x3", "mat2x4" },
460 { 0, "mat3x2", "mat3", "mat3x4" },
461 { 0, "mat4x2", "mat4x3", "mat4" },
462 };
463
464 static const GLchar* double_lut[4][4] = {
465 { "double", "dvec2", "dvec3", "dvec4" },
466 { 0, "dmat2", "dmat2x3", "dmat2x4" },
467 { 0, "dmat3x2", "dmat3", "dmat3x4" },
468 { 0, "dmat4x2", "dmat4x3", "dmat4" },
469 };
470
471 static const GLchar* int_lut[4] = { "int", "ivec2", "ivec3", "ivec4" };
472
473 static const GLchar* uint_lut[4] = { "uint", "uvec2", "uvec3", "uvec4" };
474
475 const GLchar* result = 0;
476
477 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
478 {
479 return 0;
480 }
481
482 switch (m_basic_type)
483 {
484 case Float:
485 result = float_lut[m_n_columns - 1][m_n_rows - 1];
486 break;
487 case Double:
488 result = double_lut[m_n_columns - 1][m_n_rows - 1];
489 break;
490 case Int:
491 result = int_lut[m_n_rows - 1];
492 break;
493 case Uint:
494 result = uint_lut[m_n_rows - 1];
495 break;
496 default:
497 TCU_FAIL("Invalid enum");
498 }
499
500 return result;
501 }
502
503 /** Get number of locations required for the type
504 *
505 * @return Number of columns times:
506 * - 2 when type is double with 3 or 4 rows,
507 * - 1 otherwise or if it's a vertex shader input.
508 **/
GetLocations(bool is_vs_input) const509 GLuint Type::GetLocations(bool is_vs_input) const
510 {
511 GLuint n_loc_per_column;
512
513 /* 1 or 2 doubles any for rest */
514 if ((2 >= m_n_rows) || (Double != m_basic_type) || is_vs_input)
515 {
516 n_loc_per_column = 1;
517 }
518 else
519 {
520 /* 3 and 4 doubles */
521 n_loc_per_column = 2;
522 }
523
524 return n_loc_per_column * m_n_columns;
525 }
526
527 /** Get size of the type in bytes.
528 * Note that this routine doesn't consider arrays and assumes
529 * column_major matrices.
530 *
531 * @return Formula:
532 * - If std140 packaging and matrix; number of columns * base alignment
533 * - Otherwise; number of elements * sizeof(base_type)
534 **/
GetSize(const bool is_std140) const535 GLuint Type::GetSize(const bool is_std140) const
536 {
537 const GLuint basic_type_size = GetTypeSize(m_basic_type);
538 const GLuint n_elements = m_n_columns * m_n_rows;
539
540 if (is_std140 && m_n_columns > 1)
541 {
542 return m_n_columns * GetBaseAlignment(false);
543 }
544
545 return basic_type_size * n_elements;
546 }
547
548 /** Get GLenum representing the type
549 *
550 * @return GLenum
551 **/
GetTypeGLenum() const552 GLenum Type::GetTypeGLenum() const
553 {
554 static const GLenum float_lut[4][4] = {
555 { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 },
556 { 0, GL_FLOAT_MAT2, GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4 },
557 { 0, GL_FLOAT_MAT3x2, GL_FLOAT_MAT3, GL_FLOAT_MAT3x4 },
558 { 0, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3, GL_FLOAT_MAT4 },
559 };
560
561 static const GLenum double_lut[4][4] = {
562 { GL_DOUBLE, GL_DOUBLE_VEC2, GL_DOUBLE_VEC3, GL_DOUBLE_VEC4 },
563 { 0, GL_DOUBLE_MAT2, GL_DOUBLE_MAT2x3, GL_DOUBLE_MAT2x4 },
564 { 0, GL_DOUBLE_MAT3x2, GL_DOUBLE_MAT3, GL_DOUBLE_MAT3x4 },
565 { 0, GL_DOUBLE_MAT4x2, GL_DOUBLE_MAT4x3, GL_DOUBLE_MAT4 },
566 };
567
568 static const GLenum int_lut[4] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 };
569
570 static const GLenum uint_lut[4] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3,
571 GL_UNSIGNED_INT_VEC4 };
572
573 GLenum result = 0;
574
575 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
576 {
577 return 0;
578 }
579
580 switch (m_basic_type)
581 {
582 case Float:
583 result = float_lut[m_n_columns - 1][m_n_rows - 1];
584 break;
585 case Double:
586 result = double_lut[m_n_columns - 1][m_n_rows - 1];
587 break;
588 case Int:
589 result = int_lut[m_n_rows - 1];
590 break;
591 case Uint:
592 result = uint_lut[m_n_rows - 1];
593 break;
594 default:
595 TCU_FAIL("Invalid enum");
596 }
597
598 return result;
599 }
600
601 /** Calculate the number of components consumed by a type
602 * according to 11.1.2.1 Output Variables
603 *
604 * @return Calculated number of components for the type
605 **/
GetNumComponents() const606 GLuint Type::GetNumComponents() const
607 {
608 // Rule 3 of Section 7.6.2.2
609 // If the member is a three-component vector with components consuming N
610 // basic machine units, the base alignment is 4N.
611 GLuint num_components = (m_n_rows == 3 ? 4 : m_n_rows) * m_n_columns;
612
613 if (m_basic_type == Double)
614 {
615 num_components *= 2;
616 }
617
618 return num_components;
619 }
620
621 /** Calculate the valid values to use with the component qualifier
622 *
623 * @return Vector with the valid values, in growing order, or empty if
624 * the component qualifier is not allowed
625 **/
GetValidComponents() const626 std::vector<GLuint> Type::GetValidComponents() const
627 {
628 const GLuint component_size = Utils::Type::Double == m_basic_type ? 2 : 1;
629 const GLuint n_components_per_location = Utils::Type::Double == m_basic_type ? 2 : 4;
630 const GLuint n_req_components = m_n_rows;
631 const GLint max_valid_component = (GLint)n_components_per_location - (GLint)n_req_components;
632 std::vector<GLuint> data;
633
634 /* The component qualifier cannot be used for matrices */
635 if (1 != m_n_columns)
636 {
637 return data;
638 }
639
640 /* The component qualifier cannot be used for dvec3/dvec4 */
641 if (max_valid_component < 0)
642 {
643 return data;
644 }
645
646 for (GLuint i = 0; i <= (GLuint)max_valid_component; ++i)
647 {
648 data.push_back(i * component_size);
649 }
650
651 return data;
652 }
653
654 /** Calculate stride for the type according to std140 rules
655 *
656 * @param alignment Alignment of type
657 * @param n_columns Number of columns
658 * @param n_array_elements Number of elements in array
659 *
660 * @return Calculated value
661 **/
CalculateStd140Stride(GLuint alignment,GLuint n_columns,GLuint n_array_elements)662 GLuint Type::CalculateStd140Stride(GLuint alignment, GLuint n_columns, GLuint n_array_elements)
663 {
664 GLuint stride = alignment * n_columns;
665 if (0 != n_array_elements)
666 {
667 stride *= n_array_elements;
668 }
669
670 return stride;
671 }
672
673 /** Check if glsl support matrices for specific basic type
674 *
675 * @param type Basic type
676 *
677 * @return true if matrices of <type> are supported, false otherwise
678 **/
DoesTypeSupportMatrix(TYPES type)679 bool Type::DoesTypeSupportMatrix(TYPES type)
680 {
681 bool result = false;
682
683 switch (type)
684 {
685 case Float:
686 case Double:
687 result = true;
688 break;
689 case Int:
690 case Uint:
691 result = false;
692 break;
693 default:
694 TCU_FAIL("Invalid enum");
695 }
696
697 return result;
698 }
699
700 /** Creates instance of Type
701 *
702 * @param basic_type Select basic type of instance
703 * @param n_columns Number of columns
704 * @param n_rows Number of rows
705 *
706 * @return Type instance
707 **/
GetType(TYPES basic_type,glw::GLuint n_columns,glw::GLuint n_rows)708 Type Type::GetType(TYPES basic_type, glw::GLuint n_columns, glw::GLuint n_rows)
709 {
710 Type type = { basic_type, n_columns, n_rows };
711
712 return type;
713 }
714
715 /** Get Size of given type in bytes
716 *
717 * @param type
718 *
719 * @return Size of type
720 **/
GetTypeSize(TYPES type)721 GLuint Type::GetTypeSize(TYPES type)
722 {
723 GLuint result = 0;
724
725 switch (type)
726 {
727 case Float:
728 result = sizeof(GLfloat);
729 break;
730 case Double:
731 result = sizeof(GLdouble);
732 break;
733 case Int:
734 result = sizeof(GLint);
735 break;
736 case Uint:
737 result = sizeof(GLuint);
738 break;
739 default:
740 TCU_FAIL("Invalid enum");
741 }
742
743 return result;
744 }
745
746 /** Get GLenum representing given type
747 *
748 * @param type
749 *
750 * @return GLenum value
751 **/
GetTypeGLenum(TYPES type)752 GLenum Type::GetTypeGLenum(TYPES type)
753 {
754 GLenum result = 0;
755
756 switch (type)
757 {
758 case Float:
759 result = GL_FLOAT;
760 break;
761 case Double:
762 result = GL_DOUBLE;
763 break;
764 case Int:
765 result = GL_INT;
766 break;
767 case Uint:
768 result = GL_UNSIGNED_INT;
769 break;
770 default:
771 TCU_FAIL("Invalid enum");
772 }
773
774 return result;
775 }
776
777 /** Check if two types can share the same location, based on the underlying numerical type and bit width
778 *
779 * @param first First type to compare
780 * @param second Second type to compare
781 *
782 * @return true if the types can share the same location
783 **/
CanTypesShareLocation(TYPES first,TYPES second)784 bool Type::CanTypesShareLocation(TYPES first, TYPES second)
785 {
786 if (first == second)
787 {
788 return true;
789 }
790
791 if (Float == first || Float == second || Double == first || Double == second)
792 {
793 return false;
794 }
795
796 return true;
797 }
798
799 /** Get proper glUniformNdv routine for vectors with specified number of rows
800 *
801 * @param gl GL functions
802 * @param n_rows Number of rows
803 *
804 * @return Function address
805 **/
getUniformNdv(const glw::Functions & gl,glw::GLuint n_rows)806 uniformNdv getUniformNdv(const glw::Functions& gl, glw::GLuint n_rows)
807 {
808 uniformNdv result = 0;
809
810 switch (n_rows)
811 {
812 case 1:
813 result = gl.uniform1dv;
814 break;
815 case 2:
816 result = gl.uniform2dv;
817 break;
818 case 3:
819 result = gl.uniform3dv;
820 break;
821 case 4:
822 result = gl.uniform4dv;
823 break;
824 default:
825 TCU_FAIL("Invalid number of rows");
826 }
827
828 return result;
829 }
830
831 /** Get proper glUniformNfv routine for vectors with specified number of rows
832 *
833 * @param gl GL functions
834 * @param n_rows Number of rows
835 *
836 * @return Function address
837 **/
getUniformNfv(const glw::Functions & gl,glw::GLuint n_rows)838 uniformNfv getUniformNfv(const glw::Functions& gl, glw::GLuint n_rows)
839 {
840 uniformNfv result = 0;
841
842 switch (n_rows)
843 {
844 case 1:
845 result = gl.uniform1fv;
846 break;
847 case 2:
848 result = gl.uniform2fv;
849 break;
850 case 3:
851 result = gl.uniform3fv;
852 break;
853 case 4:
854 result = gl.uniform4fv;
855 break;
856 default:
857 TCU_FAIL("Invalid number of rows");
858 }
859
860 return result;
861 }
862
863 /** Get proper glUniformNiv routine for vectors with specified number of rows
864 *
865 * @param gl GL functions
866 * @param n_rows Number of rows
867 *
868 * @return Function address
869 **/
getUniformNiv(const glw::Functions & gl,glw::GLuint n_rows)870 uniformNiv getUniformNiv(const glw::Functions& gl, glw::GLuint n_rows)
871 {
872 uniformNiv result = 0;
873
874 switch (n_rows)
875 {
876 case 1:
877 result = gl.uniform1iv;
878 break;
879 case 2:
880 result = gl.uniform2iv;
881 break;
882 case 3:
883 result = gl.uniform3iv;
884 break;
885 case 4:
886 result = gl.uniform4iv;
887 break;
888 default:
889 TCU_FAIL("Invalid number of rows");
890 }
891
892 return result;
893 }
894
895 /** Get proper glUniformNuiv routine for vectors with specified number of rows
896 *
897 * @param gl GL functions
898 * @param n_rows Number of rows
899 *
900 * @return Function address
901 **/
getUniformNuiv(const glw::Functions & gl,glw::GLuint n_rows)902 uniformNuiv getUniformNuiv(const glw::Functions& gl, glw::GLuint n_rows)
903 {
904 uniformNuiv result = 0;
905
906 switch (n_rows)
907 {
908 case 1:
909 result = gl.uniform1uiv;
910 break;
911 case 2:
912 result = gl.uniform2uiv;
913 break;
914 case 3:
915 result = gl.uniform3uiv;
916 break;
917 case 4:
918 result = gl.uniform4uiv;
919 break;
920 default:
921 TCU_FAIL("Invalid number of rows");
922 }
923
924 return result;
925 }
926
927 /** Get proper glUniformMatrixNdv routine for matrix with specified number of columns and rows
928 *
929 * @param gl GL functions
930 * @param n_rows Number of rows
931 *
932 * @return Function address
933 **/
getUniformMatrixNdv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)934 uniformMatrixNdv getUniformMatrixNdv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
935 {
936 uniformMatrixNdv result = 0;
937
938 switch (n_columns)
939 {
940 case 2:
941 switch (n_rows)
942 {
943 case 2:
944 result = gl.uniformMatrix2dv;
945 break;
946 case 3:
947 result = gl.uniformMatrix2x3dv;
948 break;
949 case 4:
950 result = gl.uniformMatrix2x4dv;
951 break;
952 default:
953 TCU_FAIL("Invalid number of rows");
954 }
955 break;
956 case 3:
957 switch (n_rows)
958 {
959 case 2:
960 result = gl.uniformMatrix3x2dv;
961 break;
962 case 3:
963 result = gl.uniformMatrix3dv;
964 break;
965 case 4:
966 result = gl.uniformMatrix3x4dv;
967 break;
968 default:
969 TCU_FAIL("Invalid number of rows");
970 }
971 break;
972 case 4:
973 switch (n_rows)
974 {
975 case 2:
976 result = gl.uniformMatrix4x2dv;
977 break;
978 case 3:
979 result = gl.uniformMatrix4x3dv;
980 break;
981 case 4:
982 result = gl.uniformMatrix4dv;
983 break;
984 default:
985 TCU_FAIL("Invalid number of rows");
986 }
987 break;
988 default:
989 TCU_FAIL("Invalid number of columns");
990 }
991
992 return result;
993 }
994
995 /** Get proper glUniformMatrixNfv routine for vectors with specified number of columns and rows
996 *
997 * @param gl GL functions
998 * @param n_rows Number of rows
999 *
1000 * @return Function address
1001 **/
getUniformMatrixNfv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)1002 uniformMatrixNfv getUniformMatrixNfv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
1003 {
1004 uniformMatrixNfv result = 0;
1005
1006 switch (n_columns)
1007 {
1008 case 2:
1009 switch (n_rows)
1010 {
1011 case 2:
1012 result = gl.uniformMatrix2fv;
1013 break;
1014 case 3:
1015 result = gl.uniformMatrix2x3fv;
1016 break;
1017 case 4:
1018 result = gl.uniformMatrix2x4fv;
1019 break;
1020 default:
1021 TCU_FAIL("Invalid number of rows");
1022 }
1023 break;
1024 case 3:
1025 switch (n_rows)
1026 {
1027 case 2:
1028 result = gl.uniformMatrix3x2fv;
1029 break;
1030 case 3:
1031 result = gl.uniformMatrix3fv;
1032 break;
1033 case 4:
1034 result = gl.uniformMatrix3x4fv;
1035 break;
1036 default:
1037 TCU_FAIL("Invalid number of rows");
1038 }
1039 break;
1040 case 4:
1041 switch (n_rows)
1042 {
1043 case 2:
1044 result = gl.uniformMatrix4x2fv;
1045 break;
1046 case 3:
1047 result = gl.uniformMatrix4x3fv;
1048 break;
1049 case 4:
1050 result = gl.uniformMatrix4fv;
1051 break;
1052 default:
1053 TCU_FAIL("Invalid number of rows");
1054 }
1055 break;
1056 default:
1057 TCU_FAIL("Invalid number of columns");
1058 }
1059
1060 return result;
1061 }
1062
verifyVarying(Program & program,const std::string & parent_name,const Variable::Descriptor & desc,std::stringstream & stream,bool is_input)1063 bool verifyVarying(Program& program, const std::string& parent_name, const Variable::Descriptor& desc,
1064 std::stringstream& stream, bool is_input)
1065 {
1066 GLint component = 0;
1067 GLuint index = 0;
1068 GLenum interface = GL_PROGRAM_INPUT;
1069 GLint location = 0;
1070
1071 if (false == is_input)
1072 {
1073 interface = GL_PROGRAM_OUTPUT;
1074 }
1075
1076 const std::string& name = Utils::Variable::GetReference(parent_name, desc, Utils::Variable::BASIC, 0);
1077
1078 try
1079 {
1080 index = program.GetResourceIndex(name, interface);
1081
1082 program.GetResource(interface, index, GL_LOCATION, 1 /* size */, &location);
1083 program.GetResource(interface, index, GL_LOCATION_COMPONENT, 1 /* size */, &component);
1084 }
1085 catch (std::exception& exc)
1086 {
1087 stream << "Failed to query program for varying: " << desc.m_name << ". Reason: " << exc.what() << "\n";
1088
1089 return false;
1090 }
1091
1092 bool result = true;
1093
1094 if (location != desc.m_expected_location)
1095 {
1096 stream << "Attribute: " << desc.m_name << " - invalid location: " << location
1097 << " expected: " << desc.m_expected_location << std::endl;
1098 result = false;
1099 }
1100 if (component != desc.m_expected_component)
1101 {
1102 stream << "Attribute: " << desc.m_name << " - invalid component: " << component
1103 << " expected: " << desc.m_expected_component << std::endl;
1104 result = false;
1105 }
1106
1107 return result;
1108 }
1109
1110 /** Query program resource for given variable and verify that everything is as expected
1111 *
1112 * @param program Program object
1113 * @param variable Variable object
1114 * @param stream Stream that will be used to log any error
1115 * @param is_input Selects if varying is input or output
1116 *
1117 * @return true if verification is positive, false otherwise
1118 **/
checkVarying(Program & program,Shader::STAGES stage,const Variable & variable,std::stringstream & stream,bool is_input)1119 bool checkVarying(Program& program, Shader::STAGES stage, const Variable& variable, std::stringstream& stream, bool is_input)
1120 {
1121 bool result = true;
1122
1123 if (variable.IsBlock())
1124 {
1125 Utils::Interface* interface = variable.m_descriptor.m_interface;
1126 const size_t n_members = interface->m_members.size();
1127
1128 for (size_t i = 0; i < n_members; ++i)
1129 {
1130 const Variable::Descriptor& member = interface->m_members[i];
1131 bool member_result = verifyVarying(program, interface->m_name, member, stream, is_input);
1132
1133 if (false == member_result)
1134 {
1135 result = false;
1136 }
1137 }
1138 }
1139 /*
1140 To query the the location of struct member by glGetProgramResource, we need pass the variable name "gs_fs_output[0].single",
1141 but in original implementation, the test pass the name "Data.single", which can't get any valid result.
1142 struct Data {
1143 dmat2 single;
1144 dmat2 array[1];
1145 };
1146 layout (location = 0) in Data gs_fs_output[1];
1147 */
1148 else if (variable.IsStruct())
1149 {
1150 Utils::Interface* interface = variable.m_descriptor.m_interface;
1151 const size_t n_members = interface->m_members.size();
1152 std::string structVariable = variable.m_descriptor.m_name;
1153
1154 switch (Variable::GetFlavour(stage, is_input ? Variable::INPUT : Variable::OUTPUT))
1155 {
1156 case Variable::ARRAY:
1157 case Variable::INDEXED_BY_INVOCATION_ID:
1158 structVariable.append("[0]");
1159 break;
1160 default:
1161 break;
1162 }
1163
1164 // If struct variable is an array
1165 if (0 != variable.m_descriptor.m_n_array_elements)
1166 {
1167 for (GLuint i = 0; i < variable.m_descriptor.m_n_array_elements; i++)
1168 {
1169 GLchar buffer[16];
1170 sprintf(buffer, "%d", i);
1171 structVariable.append("[");
1172 structVariable.append(buffer);
1173 structVariable.append("]");
1174 for (size_t j = 0; j < n_members; ++j)
1175 {
1176 const Variable::Descriptor& member = interface->m_members[j];
1177 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1178
1179 if (false == member_result)
1180 {
1181 result = false;
1182 }
1183 }
1184 }
1185 }
1186 else
1187 {
1188 for (GLuint i = 0; i < n_members; ++i)
1189 {
1190 const Variable::Descriptor& member = interface->m_members[i];
1191 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1192
1193 if (false == member_result)
1194 {
1195 result = false;
1196 }
1197 }
1198 }
1199 }
1200 else
1201 {
1202 result = verifyVarying(program, "", variable.m_descriptor, stream, is_input);
1203 }
1204 return result;
1205 }
1206
1207 /** Query program resource for given variable and verify that everything is as expected
1208 *
1209 * @param program Program object
1210 * @param variable Variable object
1211 * @param stream Stream that will be used to log any error
1212 *
1213 * @return true if verification is positive, false otherwise
1214 **/
checkUniform(Program & program,const Utils::Variable & variable,std::stringstream & stream)1215 bool checkUniform(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1216 {
1217 bool result = true;
1218
1219 if (false == variable.IsBlock())
1220 {
1221 TCU_FAIL("Not implemented");
1222 }
1223 else
1224 {
1225 Utils::Interface* interface = variable.m_descriptor.m_interface;
1226
1227 size_t size = interface->m_members.size();
1228
1229 std::vector<GLuint> indices;
1230 std::vector<const char*> names;
1231 std::vector<std::string> names_str;
1232 std::vector<GLint> offsets;
1233
1234 indices.resize(size);
1235 names.resize(size);
1236 names_str.resize(size);
1237 offsets.resize(size);
1238
1239 for (size_t i = 0; i < size; ++i)
1240 {
1241 indices[i] = 0;
1242 offsets[i] = 0;
1243
1244 const std::string& name =
1245 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1246
1247 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1248 {
1249 const std::string& member_name = Utils::Variable::GetReference(
1250 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1251
1252 names_str[i] = member_name;
1253 }
1254 else
1255 {
1256 names_str[i] = name;
1257 }
1258
1259 names[i] = names_str[i].c_str();
1260 }
1261
1262 try
1263 {
1264 program.GetUniformIndices(static_cast<glw::GLsizei>(size), &names[0], &indices[0]);
1265 program.GetActiveUniformsiv(static_cast<glw::GLsizei>(size), &indices[0], GL_UNIFORM_OFFSET, &offsets[0]);
1266 }
1267 catch (std::exception& exc)
1268 {
1269 stream << "Failed to query program for uniforms in block: " << variable.m_descriptor.m_name
1270 << ". Reason: " << exc.what() << "\n";
1271
1272 return false;
1273 }
1274
1275 for (size_t i = 0; i < size; ++i)
1276 {
1277 Utils::Variable::Descriptor& desc = interface->m_members[i];
1278
1279 if (offsets[i] != (GLint)desc.m_offset)
1280 {
1281 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offsets[i]
1282 << " expected: " << desc.m_offset << std::endl;
1283 result = false;
1284 }
1285 }
1286 }
1287
1288 return result;
1289 }
1290
1291 /** Query program resource for given variable and verify that everything is as expected
1292 *
1293 * @param program Program object
1294 * @param variable Variable object
1295 * @param stream Stream that will be used to log any error
1296 *
1297 * @return true if verification is positive, false otherwise
1298 **/
checkSSB(Program & program,const Utils::Variable & variable,std::stringstream & stream)1299 bool checkSSB(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1300 {
1301 bool result = true;
1302
1303 if (false == variable.IsBlock())
1304 {
1305 TCU_FAIL("Not implemented");
1306 }
1307 else
1308 {
1309 Utils::Interface* interface = variable.m_descriptor.m_interface;
1310
1311 size_t size = interface->m_members.size();
1312
1313 for (size_t i = 0; i < size; ++i)
1314 {
1315 GLuint index = 0;
1316 std::string name_str = "";
1317 GLint offset = 0;
1318
1319 const std::string& name =
1320 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1321
1322 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1323 {
1324 const std::string& member_name = Utils::Variable::GetReference(
1325 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1326
1327 name_str = member_name;
1328 }
1329 else
1330 {
1331 name_str = name;
1332 }
1333
1334 try
1335 {
1336 index = program.GetResourceIndex(name_str, GL_BUFFER_VARIABLE);
1337
1338 program.GetResource(GL_BUFFER_VARIABLE, index, GL_OFFSET, 1, &offset);
1339 }
1340 catch (std::exception& exc)
1341 {
1342 stream << "Failed to query program for buffer variable: " << variable.m_descriptor.m_name
1343 << ". Reason: " << exc.what() << "\n";
1344
1345 return false;
1346 }
1347
1348 Utils::Variable::Descriptor& desc = interface->m_members[i];
1349
1350 if (offset != (GLint)desc.m_offset)
1351 {
1352 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offset
1353 << " expected: " << desc.m_offset << std::endl;
1354 result = false;
1355 }
1356 }
1357 }
1358
1359 return result;
1360 }
1361
1362 /** Query program resources at given stage and verifies results
1363 *
1364 * @param program Program object
1365 * @param program_interface Definition of program interface
1366 * @param stage Stage to be verified
1367 * @param check_inputs Select if inputs should be verified
1368 * @param check_outputs Select if output should be verified
1369 * @param check_uniforms Select if uniforms should be verified
1370 * @param check_ssbs Select if buffers should be verified
1371 * @param stream Stream that will be used to log any error
1372 *
1373 * @return true if verification is positive, false otherwise
1374 **/
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)1375 bool checkProgramStage(Program& program, const ProgramInterface& program_interface, Utils::Shader::STAGES stage,
1376 bool check_inputs, bool check_outputs, bool check_uniforms, bool check_ssbs,
1377 std::stringstream& stream)
1378 {
1379 typedef Variable::PtrVector::const_iterator const_iterator;
1380
1381 const ShaderInterface& interface = program_interface.GetShaderInterface(stage);
1382
1383 bool result = true;
1384
1385 /* Inputs */
1386 if (true == check_inputs)
1387 {
1388 const Variable::PtrVector& inputs = interface.m_inputs;
1389
1390 for (const_iterator it = inputs.begin(); it != inputs.end(); ++it)
1391 {
1392 if (false == checkVarying(program, stage, **it, stream, true))
1393 {
1394 result = false;
1395 }
1396 }
1397 }
1398
1399 /* Outputs */
1400 if (true == check_outputs)
1401 {
1402 const Variable::PtrVector& outputs = interface.m_outputs;
1403
1404 for (const_iterator it = outputs.begin(); it != outputs.end(); ++it)
1405 {
1406 if (false == checkVarying(program, stage, **it, stream, false))
1407 {
1408 result = false;
1409 }
1410 }
1411 }
1412
1413 /* Uniforms */
1414 if (true == check_uniforms)
1415 {
1416 const Variable::PtrVector& uniforms = interface.m_uniforms;
1417
1418 for (const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
1419 {
1420 if (false == checkUniform(program, **it, stream))
1421 {
1422 result = false;
1423 }
1424 }
1425 }
1426
1427 /* SSBs */
1428 if (true == check_ssbs)
1429 {
1430 const Variable::PtrVector& ssbs = interface.m_ssb_blocks;
1431
1432 for (const_iterator it = ssbs.begin(); it != ssbs.end(); ++it)
1433 {
1434 if (false == checkSSB(program, **it, stream))
1435 {
1436 result = false;
1437 }
1438 }
1439 }
1440
1441 return result;
1442 }
1443
1444 /** Query resources of monolithic compute program and verifies results
1445 *
1446 * @param program Program object
1447 * @param program_interface Definition of program interface
1448 * @param stream Stream that will be used to log any error
1449 *
1450 * @return true if verification is positive, false otherwise
1451 **/
checkMonolithicComputeProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1452 bool checkMonolithicComputeProgramInterface(Program& program, const ProgramInterface& program_interface,
1453 std::stringstream& stream)
1454 {
1455 bool result = true;
1456
1457 if (false == checkProgramStage(program, program_interface, Shader::COMPUTE, false, false, true, true, stream))
1458 {
1459 result = false;
1460 }
1461
1462 /* Done */
1463 return result;
1464 }
1465
1466 /** Query resources of monolithic draw program and verifies results
1467 *
1468 * @param program Program object
1469 * @param program_interface Definition of program interface
1470 * @param stream Stream that will be used to log any error
1471 *
1472 * @return true if verification is positive, false otherwise
1473 **/
checkMonolithicDrawProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1474 bool checkMonolithicDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1475 std::stringstream& stream)
1476 {
1477 bool result = true;
1478
1479 if (false == checkProgramStage(program, program_interface, Shader::VERTEX, true, false, true, true, stream))
1480 {
1481 result = false;
1482 }
1483
1484 /* Done */
1485 return result;
1486 }
1487
1488 /** Query resources of separable draw program and verifies results
1489 *
1490 * @param program Program object
1491 * @param program_interface Definition of program interface
1492 * @param stream Stream that will be used to log any error
1493 *
1494 * @return true if verification is positive, false otherwise
1495 **/
checkSeparableDrawProgramInterface(Program & program,const ProgramInterface & program_interface,Utils::Shader::STAGES stage,std::stringstream & stream)1496 bool checkSeparableDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1497 Utils::Shader::STAGES stage, std::stringstream& stream)
1498 {
1499 bool result = true;
1500
1501 if (false == checkProgramStage(program, program_interface, stage, true, true, true, true, stream))
1502 {
1503 result = false;
1504 }
1505
1506 /* Done */
1507 return result;
1508 }
1509
1510 /** Check if extension is supported
1511 *
1512 * @param context Test context
1513 * @param extension_name Name of extension
1514 *
1515 * @return true if extension is supported, false otherwise
1516 **/
isExtensionSupported(deqp::Context & context,const GLchar * extension_name)1517 bool isExtensionSupported(deqp::Context& context, const GLchar* extension_name)
1518 {
1519 const std::vector<std::string>& extensions = context.getContextInfo().getExtensions();
1520
1521 if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
1522 {
1523 return false;
1524 }
1525
1526 return true;
1527 }
1528
1529 /** Check if GL context meets version requirements
1530 *
1531 * @param gl Functions
1532 * @param required_major Minimum required MAJOR_VERSION
1533 * @param required_minor Minimum required MINOR_VERSION
1534 *
1535 * @return true if GL context version is at least as requested, false otherwise
1536 **/
isGLVersionAtLeast(const Functions & gl,GLint required_major,GLint required_minor)1537 bool isGLVersionAtLeast(const Functions& gl, GLint required_major, GLint required_minor)
1538 {
1539 glw::GLint major = 0;
1540 glw::GLint minor = 0;
1541
1542 gl.getIntegerv(GL_MAJOR_VERSION, &major);
1543 gl.getIntegerv(GL_MINOR_VERSION, &minor);
1544
1545 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1546
1547 if (major > required_major)
1548 {
1549 /* Major is higher than required one */
1550 return true;
1551 }
1552 else if (major == required_major)
1553 {
1554 if (minor >= required_minor)
1555 {
1556 /* Major is equal to required one */
1557 /* Minor is higher than or equal to required one */
1558 return true;
1559 }
1560 else
1561 {
1562 /* Major is equal to required one */
1563 /* Minor is lower than required one */
1564 return false;
1565 }
1566 }
1567 else
1568 {
1569 /* Major is lower than required one */
1570 return false;
1571 }
1572 }
1573
1574 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1575 *
1576 * @param token Token string
1577 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1578 * @param text String that will be used as replacement for <token>
1579 * @param string String to work on
1580 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1581 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1582 {
1583 const size_t text_length = strlen(text);
1584 const size_t token_length = strlen(token);
1585 const size_t token_position = string.find(token, search_position);
1586
1587 #if DEBUG_REPLACE_TOKEN
1588 if (std::string::npos == token_position)
1589 {
1590 string.append("\n\nInvalid token: ");
1591 string.append(token);
1592
1593 TCU_FAIL(string.c_str());
1594 }
1595 #endif /* DEBUG_REPLACE_TOKEN */
1596
1597 string.replace(token_position, token_length, text, text_length);
1598
1599 search_position = token_position + text_length;
1600 }
1601
1602 /** Replace all occurances of <token> with <text> in <string>
1603 *
1604 * @param token Token string
1605 * @param text String that will be used as replacement for <token>
1606 * @param string String to work on
1607 **/
replaceAllTokens(const GLchar * token,const GLchar * text,std::string & string)1608 void replaceAllTokens(const GLchar* token, const GLchar* text, std::string& string)
1609 {
1610 const size_t text_length = strlen(text);
1611 const size_t token_length = strlen(token);
1612
1613 size_t search_position = 0;
1614
1615 while (1)
1616 {
1617 const size_t token_position = string.find(token, search_position);
1618
1619 if (std::string::npos == token_position)
1620 {
1621 break;
1622 }
1623
1624 search_position = token_position + text_length;
1625
1626 string.replace(token_position, token_length, text, text_length);
1627 }
1628 }
1629
1630 /** Rounds up the value to the next power of 2.
1631 * This routine does not work for 0, see the url for explanations.
1632 *
1633 * @param value Starting point
1634 *
1635 * @return Calculated value
1636 **/
roundUpToPowerOf2(glw::GLuint value)1637 glw::GLuint roundUpToPowerOf2(glw::GLuint value)
1638 {
1639 /* Taken from: graphics.stanford.edu/~seander/bithacks.html */
1640 --value;
1641
1642 value |= value >> 1;
1643 value |= value >> 2;
1644 value |= value >> 4;
1645 value |= value >> 8;
1646 value |= value >> 16;
1647
1648 ++value;
1649
1650 return value;
1651 }
1652
1653 /** Insert elements of list into string.
1654 * List in string is represented either by token "LIST" or "SEPARATORLIST".
1655 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>.
1656 * LIST is replaced with <element>SEPARATORLIST
1657 *
1658 * @param element Element to be inserted
1659 * @param separator Separator inserted between elements
1660 * @param search_position Position in string, where search for list should start
1661 * @param string String
1662 **/
insertElementOfList(const GLchar * element,const GLchar * separator,size_t & search_position,std::string & string)1663 void insertElementOfList(const GLchar* element, const GLchar* separator, size_t& search_position, std::string& string)
1664 {
1665 static const char* list = g_list;
1666 static const char* sep_list = "SEPARATORLIST";
1667
1668 /* Try to get "list" positions */
1669 const size_t list_position = string.find(list, search_position);
1670 const size_t sep_list_position = string.find(sep_list, search_position);
1671
1672 /* There is no list in string */
1673 if (std::string::npos == list_position)
1674 {
1675 return;
1676 }
1677
1678 if (9 /* strlen(SEPARATOR) */ == list_position - sep_list_position)
1679 {
1680 replaceToken("SEPARATOR", search_position, separator, string);
1681 }
1682
1683 /* Save search_position */
1684 const size_t start_position = search_position;
1685
1686 /* Prepare new element */
1687 replaceToken("LIST", search_position, "ELEMENTSEPARATORLIST", string);
1688
1689 /* Restore search_position */
1690 search_position = start_position;
1691
1692 /* Replace element and separator */
1693 replaceToken("ELEMENT", search_position, element, string);
1694 }
1695
1696 /** Close list in string.
1697 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>
1698 * LIST is replaced with ""
1699 *
1700 * @param separator Separator inserted between elements
1701 * @param search_position Position in string, where search for list should start
1702 * @param string String
1703 **/
endList(const glw::GLchar * separator,size_t & search_position,std::string & string)1704 void endList(const glw::GLchar* separator, size_t& search_position, std::string& string)
1705 {
1706 const size_t sep_position = string.find("SEPARATOR", search_position);
1707 if (std::string::npos != sep_position)
1708 {
1709 replaceToken("SEPARATOR", search_position, separator, string);
1710 }
1711
1712 replaceToken("LIST", search_position, "", string);
1713 }
1714
1715 /* Buffer constants */
1716 const GLuint Buffer::m_invalid_id = -1;
1717
1718 /** Constructor.
1719 *
1720 * @param context CTS context.
1721 **/
Buffer(deqp::Context & context)1722 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_buffer(Array), m_context(context)
1723 {
1724 }
1725
1726 /** Destructor
1727 *
1728 **/
~Buffer()1729 Buffer::~Buffer()
1730 {
1731 Release();
1732 }
1733
1734 /** Initialize buffer instance
1735 *
1736 * @param buffer Buffer type
1737 * @param usage Buffer usage enum
1738 * @param size <size> parameter
1739 * @param data <data> parameter
1740 **/
Init(BUFFERS buffer,USAGE usage,GLsizeiptr size,GLvoid * data)1741 void Buffer::Init(BUFFERS buffer, USAGE usage, GLsizeiptr size, GLvoid* data)
1742 {
1743 /* Delete previous buffer instance */
1744 Release();
1745
1746 m_buffer = buffer;
1747
1748 const Functions& gl = m_context.getRenderContext().getFunctions();
1749
1750 Generate(gl, m_id);
1751 Bind(gl, m_id, m_buffer);
1752 Data(gl, m_buffer, usage, size, data);
1753 }
1754
1755 /** Release buffer instance
1756 *
1757 **/
Release()1758 void Buffer::Release()
1759 {
1760 if (m_invalid_id != m_id)
1761 {
1762 const Functions& gl = m_context.getRenderContext().getFunctions();
1763
1764 gl.deleteBuffers(1, &m_id);
1765 m_id = m_invalid_id;
1766 }
1767 }
1768
1769 /** Binds buffer to its target
1770 *
1771 **/
Bind() const1772 void Buffer::Bind() const
1773 {
1774 const Functions& gl = m_context.getRenderContext().getFunctions();
1775
1776 Bind(gl, m_id, m_buffer);
1777 }
1778
1779 /** Binds indexed buffer
1780 *
1781 * @param index <index> parameter
1782 **/
BindBase(GLuint index) const1783 void Buffer::BindBase(GLuint index) const
1784 {
1785 const Functions& gl = m_context.getRenderContext().getFunctions();
1786
1787 BindBase(gl, m_id, m_buffer, index);
1788 }
1789
1790 /** Binds range of buffer
1791 *
1792 * @param index <index> parameter
1793 * @param offset <offset> parameter
1794 * @param size <size> parameter
1795 **/
BindRange(GLuint index,GLintptr offset,GLsizeiptr size) const1796 void Buffer::BindRange(GLuint index, GLintptr offset, GLsizeiptr size) const
1797 {
1798 const Functions& gl = m_context.getRenderContext().getFunctions();
1799
1800 BindRange(gl, m_id, m_buffer, index, offset, size);
1801 }
1802
1803 /** Allocate memory for buffer and sends initial content
1804 *
1805 * @param usage Buffer usage enum
1806 * @param size <size> parameter
1807 * @param data <data> parameter
1808 **/
Data(USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1809 void Buffer::Data(USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1810 {
1811 const Functions& gl = m_context.getRenderContext().getFunctions();
1812
1813 Data(gl, m_buffer, usage, size, data);
1814 }
1815
1816 /** Maps contents of buffer into CPU space
1817 *
1818 * @param access Requested access
1819 *
1820 * @return Pointer to memory region available for CPU
1821 **/
Map(ACCESS access)1822 GLvoid* Buffer::Map(ACCESS access)
1823 {
1824 const Functions& gl = m_context.getRenderContext().getFunctions();
1825
1826 return Map(gl, m_buffer, access);
1827 }
1828
1829 /** Allocate memory for buffer and sends initial content
1830 *
1831 * @param offset Offset in buffer
1832 * @param size <size> parameter
1833 * @param data <data> parameter
1834 **/
SubData(glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1835 void Buffer::SubData(glw::GLintptr offset, glw::GLsizeiptr size, glw::GLvoid* data)
1836 {
1837 const Functions& gl = m_context.getRenderContext().getFunctions();
1838
1839 SubData(gl, m_buffer, offset, size, data);
1840 }
1841
1842 /** Maps contents of buffer into CPU space
1843 **/
UnMap()1844 void Buffer::UnMap()
1845 {
1846 const Functions& gl = m_context.getRenderContext().getFunctions();
1847
1848 return UnMap(gl, m_buffer);
1849 }
1850
1851 /** Bind buffer to given target
1852 *
1853 * @param gl GL functions
1854 * @param id Id of buffer
1855 * @param buffer Buffer enum
1856 **/
Bind(const Functions & gl,GLuint id,BUFFERS buffer)1857 void Buffer::Bind(const Functions& gl, GLuint id, BUFFERS buffer)
1858 {
1859 GLenum target = GetBufferGLenum(buffer);
1860
1861 gl.bindBuffer(target, id);
1862 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
1863 }
1864
1865 /** Binds indexed buffer
1866 *
1867 * @param gl GL functions
1868 * @param id Id of buffer
1869 * @param buffer Buffer enum
1870 * @param index <index> parameter
1871 **/
BindBase(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index)1872 void Buffer::BindBase(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index)
1873 {
1874 GLenum target = GetBufferGLenum(buffer);
1875
1876 gl.bindBufferBase(target, index, id);
1877 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
1878 }
1879
1880 /** Binds buffer range
1881 *
1882 * @param gl GL functions
1883 * @param id Id of buffer
1884 * @param buffer Buffer enum
1885 * @param index <index> parameter
1886 * @param offset <offset> parameter
1887 * @param size <size> parameter
1888 **/
BindRange(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index,GLintptr offset,GLsizeiptr size)1889 void Buffer::BindRange(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index, GLintptr offset, GLsizeiptr size)
1890 {
1891 GLenum target = GetBufferGLenum(buffer);
1892
1893 gl.bindBufferRange(target, index, id, offset, size);
1894 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
1895 }
1896
1897 /** Allocate memory for buffer and sends initial content
1898 *
1899 * @param gl GL functions
1900 * @param buffer Buffer enum
1901 * @param usage Buffer usage enum
1902 * @param size <size> parameter
1903 * @param data <data> parameter
1904 **/
Data(const glw::Functions & gl,BUFFERS buffer,USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1905 void Buffer::Data(const glw::Functions& gl, BUFFERS buffer, USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1906 {
1907 GLenum target = GetBufferGLenum(buffer);
1908 GLenum gl_usage = GetUsageGLenum(usage);
1909
1910 gl.bufferData(target, size, data, gl_usage);
1911 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
1912 }
1913
1914 /** Allocate memory for buffer and sends initial content
1915 *
1916 * @param gl GL functions
1917 * @param buffer Buffer enum
1918 * @param offset Offset in buffer
1919 * @param size <size> parameter
1920 * @param data <data> parameter
1921 **/
SubData(const glw::Functions & gl,BUFFERS buffer,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1922 void Buffer::SubData(const glw::Functions& gl, BUFFERS buffer, glw::GLintptr offset, glw::GLsizeiptr size,
1923 glw::GLvoid* data)
1924 {
1925 GLenum target = GetBufferGLenum(buffer);
1926
1927 gl.bufferSubData(target, offset, size, data);
1928 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
1929 }
1930
1931 /** Generate buffer
1932 *
1933 * @param gl GL functions
1934 * @param out_id Id of buffer
1935 **/
Generate(const Functions & gl,GLuint & out_id)1936 void Buffer::Generate(const Functions& gl, GLuint& out_id)
1937 {
1938 GLuint id = m_invalid_id;
1939
1940 gl.genBuffers(1, &id);
1941 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
1942
1943 if (m_invalid_id == id)
1944 {
1945 TCU_FAIL("Got invalid id");
1946 }
1947
1948 out_id = id;
1949 }
1950
1951 /** Maps buffer content
1952 *
1953 * @param gl GL functions
1954 * @param buffer Buffer enum
1955 * @param access Access rights for mapped region
1956 *
1957 * @return Mapped memory
1958 **/
Map(const Functions & gl,BUFFERS buffer,ACCESS access)1959 void* Buffer::Map(const Functions& gl, BUFFERS buffer, ACCESS access)
1960 {
1961 GLenum target = GetBufferGLenum(buffer);
1962 GLenum gl_access = GetAccessGLenum(access);
1963
1964 void* result = gl.mapBuffer(target, gl_access);
1965 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
1966
1967 return result;
1968 }
1969
1970 /** Unmaps buffer
1971 *
1972 **/
UnMap(const Functions & gl,BUFFERS buffer)1973 void Buffer::UnMap(const Functions& gl, BUFFERS buffer)
1974 {
1975 GLenum target = GetBufferGLenum(buffer);
1976
1977 gl.unmapBuffer(target);
1978 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
1979 }
1980
1981 /** Return GLenum representation of requested access
1982 *
1983 * @param access Requested access
1984 *
1985 * @return GLenum value
1986 **/
GetAccessGLenum(ACCESS access)1987 GLenum Buffer::GetAccessGLenum(ACCESS access)
1988 {
1989 GLenum result = 0;
1990
1991 switch (access)
1992 {
1993 case ReadOnly:
1994 result = GL_READ_ONLY;
1995 break;
1996 case WriteOnly:
1997 result = GL_WRITE_ONLY;
1998 break;
1999 case ReadWrite:
2000 result = GL_READ_WRITE;
2001 break;
2002 default:
2003 TCU_FAIL("Invalid enum");
2004 }
2005
2006 return result;
2007 }
2008
2009 /** Return GLenum representation of requested buffer type
2010 *
2011 * @param buffer Requested buffer type
2012 *
2013 * @return GLenum value
2014 **/
GetBufferGLenum(BUFFERS buffer)2015 GLenum Buffer::GetBufferGLenum(BUFFERS buffer)
2016 {
2017 GLenum result = 0;
2018
2019 switch (buffer)
2020 {
2021 case Array:
2022 result = GL_ARRAY_BUFFER;
2023 break;
2024 case Element:
2025 result = GL_ELEMENT_ARRAY_BUFFER;
2026 break;
2027 case Shader_Storage:
2028 result = GL_SHADER_STORAGE_BUFFER;
2029 break;
2030 case Texture:
2031 result = GL_TEXTURE_BUFFER;
2032 break;
2033 case Transform_feedback:
2034 result = GL_TRANSFORM_FEEDBACK_BUFFER;
2035 break;
2036 case Uniform:
2037 result = GL_UNIFORM_BUFFER;
2038 break;
2039 default:
2040 TCU_FAIL("Invalid enum");
2041 }
2042
2043 return result;
2044 }
2045
2046 /** Return GLenum representation of requested usage
2047 *
2048 * @param usage Requested usage
2049 *
2050 * @return GLenum value
2051 **/
GetUsageGLenum(USAGE usage)2052 GLenum Buffer::GetUsageGLenum(USAGE usage)
2053 {
2054 GLenum result = 0;
2055
2056 switch (usage)
2057 {
2058 case DynamicCopy:
2059 result = GL_DYNAMIC_COPY;
2060 break;
2061 case DynamicDraw:
2062 result = GL_DYNAMIC_DRAW;
2063 break;
2064 case DynamicRead:
2065 result = GL_DYNAMIC_READ;
2066 break;
2067 case StaticCopy:
2068 result = GL_STATIC_COPY;
2069 break;
2070 case StaticDraw:
2071 result = GL_STATIC_DRAW;
2072 break;
2073 case StaticRead:
2074 result = GL_STATIC_READ;
2075 break;
2076 case StreamCopy:
2077 result = GL_STREAM_COPY;
2078 break;
2079 case StreamDraw:
2080 result = GL_STREAM_DRAW;
2081 break;
2082 case StreamRead:
2083 result = GL_STREAM_READ;
2084 break;
2085 default:
2086 TCU_FAIL("Invalid enum");
2087 }
2088
2089 return result;
2090 }
2091
2092 /** Returns name of buffer target
2093 *
2094 * @param buffer Target enum
2095 *
2096 * @return Name of target
2097 **/
GetBufferName(BUFFERS buffer)2098 const GLchar* Buffer::GetBufferName(BUFFERS buffer)
2099 {
2100 const GLchar* name = 0;
2101
2102 switch (buffer)
2103 {
2104 case Array:
2105 name = "Array";
2106 break;
2107 case Element:
2108 name = "Element";
2109 break;
2110 case Shader_Storage:
2111 name = "Shader_Storage";
2112 break;
2113 case Texture:
2114 name = "Texture";
2115 break;
2116 case Transform_feedback:
2117 name = "Transform_feedback";
2118 break;
2119 case Uniform:
2120 name = "Uniform";
2121 break;
2122 default:
2123 TCU_FAIL("Invalid enum");
2124 }
2125
2126 return name;
2127 }
2128
2129 /* Framebuffer constants */
2130 const GLuint Framebuffer::m_invalid_id = -1;
2131
2132 /** Constructor
2133 *
2134 * @param context CTS context
2135 **/
Framebuffer(deqp::Context & context)2136 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2137 {
2138 /* Nothing to be done here */
2139 }
2140
2141 /** Destructor
2142 *
2143 **/
~Framebuffer()2144 Framebuffer::~Framebuffer()
2145 {
2146 Release();
2147 }
2148
2149 /** Initialize framebuffer instance
2150 *
2151 **/
Init()2152 void Framebuffer::Init()
2153 {
2154 /* Delete previous instance */
2155 Release();
2156
2157 const Functions& gl = m_context.getRenderContext().getFunctions();
2158
2159 Generate(gl, m_id);
2160 }
2161
2162 /** Release framebuffer instance
2163 *
2164 **/
Release()2165 void Framebuffer::Release()
2166 {
2167 if (m_invalid_id != m_id)
2168 {
2169 const Functions& gl = m_context.getRenderContext().getFunctions();
2170
2171 gl.deleteFramebuffers(1, &m_id);
2172 m_id = m_invalid_id;
2173 }
2174 }
2175
2176 /** Attach texture to specified attachment
2177 *
2178 * @param attachment Attachment
2179 * @param texture_id Texture id
2180 * @param width Texture width
2181 * @param height Texture height
2182 **/
AttachTexture(GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2183 void Framebuffer::AttachTexture(GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2184 {
2185 const Functions& gl = m_context.getRenderContext().getFunctions();
2186
2187 AttachTexture(gl, attachment, texture_id, width, height);
2188 }
2189
2190 /** Binds framebuffer to DRAW_FRAMEBUFFER
2191 *
2192 **/
Bind()2193 void Framebuffer::Bind()
2194 {
2195 const Functions& gl = m_context.getRenderContext().getFunctions();
2196
2197 Bind(gl, m_id);
2198 }
2199
2200 /** Clear framebuffer
2201 *
2202 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2203 **/
Clear(GLenum mask)2204 void Framebuffer::Clear(GLenum mask)
2205 {
2206 const Functions& gl = m_context.getRenderContext().getFunctions();
2207
2208 Clear(gl, mask);
2209 }
2210
2211 /** Specifies clear color
2212 *
2213 * @param red Red channel
2214 * @param green Green channel
2215 * @param blue Blue channel
2216 * @param alpha Alpha channel
2217 **/
ClearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2218 void Framebuffer::ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2219 {
2220 const Functions& gl = m_context.getRenderContext().getFunctions();
2221
2222 ClearColor(gl, red, green, blue, alpha);
2223 }
2224
2225 /** Attach texture to specified attachment
2226 *
2227 * @param gl GL functions
2228 * @param attachment Attachment
2229 * @param texture_id Texture id
2230 * @param width Texture width
2231 * @param height Texture height
2232 **/
AttachTexture(const Functions & gl,GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2233 void Framebuffer::AttachTexture(const Functions& gl, GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2234 {
2235 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
2236 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
2237
2238 gl.viewport(0 /* x */, 0 /* y */, width, height);
2239 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
2240 }
2241
2242 /** Binds framebuffer to DRAW_FRAMEBUFFER
2243 *
2244 * @param gl GL functions
2245 * @param id ID of framebuffer
2246 **/
Bind(const Functions & gl,GLuint id)2247 void Framebuffer::Bind(const Functions& gl, GLuint id)
2248 {
2249 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
2250 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
2251 }
2252
2253 /** Clear framebuffer
2254 *
2255 * @param gl GL functions
2256 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2257 **/
Clear(const Functions & gl,GLenum mask)2258 void Framebuffer::Clear(const Functions& gl, GLenum mask)
2259 {
2260 gl.clear(mask);
2261 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2262 }
2263
2264 /** Specifies clear color
2265 *
2266 * @param gl GL functions
2267 * @param red Red channel
2268 * @param green Green channel
2269 * @param blue Blue channel
2270 * @param alpha Alpha channel
2271 **/
ClearColor(const Functions & gl,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2272 void Framebuffer::ClearColor(const Functions& gl, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2273 {
2274 gl.clearColor(red, green, blue, alpha);
2275 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2276 }
2277
2278 /** Generate framebuffer
2279 *
2280 **/
Generate(const Functions & gl,GLuint & out_id)2281 void Framebuffer::Generate(const Functions& gl, GLuint& out_id)
2282 {
2283 GLuint id = m_invalid_id;
2284
2285 gl.genFramebuffers(1, &id);
2286 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
2287
2288 if (m_invalid_id == id)
2289 {
2290 TCU_FAIL("Invalid id");
2291 }
2292
2293 out_id = id;
2294 }
2295
2296 /* Shader's constants */
2297 const GLuint Shader::m_invalid_id = 0;
2298
2299 /** Constructor.
2300 *
2301 * @param context CTS context.
2302 **/
Shader(deqp::Context & context)2303 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2304 {
2305 /* Nothing to be done here */
2306 }
2307
2308 /** Destructor
2309 *
2310 **/
~Shader()2311 Shader::~Shader()
2312 {
2313 Release();
2314 }
2315
2316 /** Initialize shader instance
2317 *
2318 * @param stage Shader stage
2319 * @param source Source code
2320 **/
Init(STAGES stage,const std::string & source)2321 void Shader::Init(STAGES stage, const std::string& source)
2322 {
2323 if (true == source.empty())
2324 {
2325 /* No source == no shader */
2326 return;
2327 }
2328
2329 /* Delete any previous shader */
2330 Release();
2331
2332 /* Create, set source and compile */
2333 const Functions& gl = m_context.getRenderContext().getFunctions();
2334
2335 Create(gl, stage, m_id);
2336 Source(gl, m_id, source);
2337
2338 try
2339 {
2340 Compile(gl, m_id);
2341 }
2342 catch (const CompilationException& exc)
2343 {
2344 throw InvalidSourceException(exc.what(), source, stage);
2345 }
2346 }
2347
2348 /** Release shader instance
2349 *
2350 **/
Release()2351 void Shader::Release()
2352 {
2353 if (m_invalid_id != m_id)
2354 {
2355 const Functions& gl = m_context.getRenderContext().getFunctions();
2356
2357 gl.deleteShader(m_id);
2358 m_id = m_invalid_id;
2359 }
2360 }
2361
2362 /** Compile shader
2363 *
2364 * @param gl GL functions
2365 * @param id Shader id
2366 **/
Compile(const Functions & gl,GLuint id)2367 void Shader::Compile(const Functions& gl, GLuint id)
2368 {
2369 GLint status = GL_FALSE;
2370
2371 /* Compile */
2372 gl.compileShader(id);
2373 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
2374
2375 /* Get compilation status */
2376 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
2377 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2378
2379 /* Log compilation error */
2380 if (GL_TRUE != status)
2381 {
2382 glw::GLint length = 0;
2383 std::string message;
2384
2385 /* Error log length */
2386 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
2387 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2388
2389 /* Prepare storage */
2390 message.resize(length, 0);
2391
2392 /* Get error log */
2393 gl.getShaderInfoLog(id, length, 0, &message[0]);
2394 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
2395
2396 throw CompilationException(message.c_str());
2397 }
2398 }
2399
2400 /** Create shader
2401 *
2402 * @param gl GL functions
2403 * @param stage Shader stage
2404 * @param out_id Shader id
2405 **/
Create(const Functions & gl,STAGES stage,GLuint & out_id)2406 void Shader::Create(const Functions& gl, STAGES stage, GLuint& out_id)
2407 {
2408 const GLenum shaderType = GetShaderStageGLenum(stage);
2409 const GLuint id = gl.createShader(shaderType);
2410 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
2411
2412 if (m_invalid_id == id)
2413 {
2414 TCU_FAIL("Failed to create shader");
2415 }
2416
2417 out_id = id;
2418 }
2419
2420 /** Set shader's source code
2421 *
2422 * @param gl GL functions
2423 * @param id Shader id
2424 * @param source Shader source code
2425 **/
Source(const Functions & gl,GLuint id,const std::string & source)2426 void Shader::Source(const Functions& gl, GLuint id, const std::string& source)
2427 {
2428 const GLchar* code = source.c_str();
2429
2430 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
2431 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
2432 }
2433
2434 /** Get GLenum repesenting shader stage
2435 *
2436 * @param stage Shader stage
2437 *
2438 * @return GLenum
2439 **/
GetShaderStageGLenum(STAGES stage)2440 GLenum Shader::GetShaderStageGLenum(STAGES stage)
2441 {
2442 GLenum result = 0;
2443
2444 switch (stage)
2445 {
2446 case COMPUTE:
2447 result = GL_COMPUTE_SHADER;
2448 break;
2449 case FRAGMENT:
2450 result = GL_FRAGMENT_SHADER;
2451 break;
2452 case GEOMETRY:
2453 result = GL_GEOMETRY_SHADER;
2454 break;
2455 case TESS_CTRL:
2456 result = GL_TESS_CONTROL_SHADER;
2457 break;
2458 case TESS_EVAL:
2459 result = GL_TESS_EVALUATION_SHADER;
2460 break;
2461 case VERTEX:
2462 result = GL_VERTEX_SHADER;
2463 break;
2464 default:
2465 TCU_FAIL("Invalid enum");
2466 }
2467
2468 return result;
2469 }
2470
2471 /** Get string representing name of shader stage
2472 *
2473 * @param stage Shader stage
2474 *
2475 * @return String with name of shader stage
2476 **/
GetStageName(STAGES stage)2477 const glw::GLchar* Shader::GetStageName(STAGES stage)
2478 {
2479 const GLchar* result = 0;
2480
2481 switch (stage)
2482 {
2483 case COMPUTE:
2484 result = "compute";
2485 break;
2486 case VERTEX:
2487 result = "vertex";
2488 break;
2489 case TESS_CTRL:
2490 result = "tessellation control";
2491 break;
2492 case TESS_EVAL:
2493 result = "tessellation evaluation";
2494 break;
2495 case GEOMETRY:
2496 result = "geometry";
2497 break;
2498 case FRAGMENT:
2499 result = "fragment";
2500 break;
2501 default:
2502 TCU_FAIL("Invalid enum");
2503 }
2504
2505 return result;
2506 }
2507
2508 /** Logs shader source
2509 *
2510 * @param context CTS context
2511 * @param source Source of shader
2512 * @param stage Shader stage
2513 **/
LogSource(deqp::Context & context,const std::string & source,STAGES stage)2514 void Shader::LogSource(deqp::Context& context, const std::string& source, STAGES stage)
2515 {
2516 /* Skip empty shaders */
2517 if (true == source.empty())
2518 {
2519 return;
2520 }
2521
2522 context.getTestContext().getLog() << tcu::TestLog::Message
2523 << "Shader source. Stage: " << Shader::GetStageName(stage)
2524 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(source);
2525 }
2526
2527 /** Constructor
2528 *
2529 * @param message Compilation error message
2530 **/
CompilationException(const GLchar * message)2531 Shader::CompilationException::CompilationException(const GLchar* message)
2532 {
2533 m_message = message;
2534 }
2535
2536 /** Returns error messages
2537 *
2538 * @return Compilation error message
2539 **/
what() const2540 const char* Shader::CompilationException::what() const throw()
2541 {
2542 return m_message.c_str();
2543 }
2544
2545 /** Constructor
2546 *
2547 * @param message Compilation error message
2548 **/
InvalidSourceException(const GLchar * error_message,const std::string & source,STAGES stage)2549 Shader::InvalidSourceException::InvalidSourceException(const GLchar* error_message, const std::string& source,
2550 STAGES stage)
2551 : m_message(error_message), m_source(source), m_stage(stage)
2552 {
2553 }
2554
2555 /** Returns error messages
2556 *
2557 * @return Compilation error message
2558 **/
what() const2559 const char* Shader::InvalidSourceException::what() const throw()
2560 {
2561 return "Compilation error";
2562 }
2563
2564 /** Logs error message and shader sources **/
log(deqp::Context & context) const2565 void Shader::InvalidSourceException::log(deqp::Context& context) const
2566 {
2567 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader: " << m_message.c_str()
2568 << tcu::TestLog::EndMessage;
2569
2570 LogSource(context, m_source, m_stage);
2571 }
2572
2573 /* Program constants */
2574 const GLuint Pipeline::m_invalid_id = 0;
2575
2576 /** Constructor.
2577 *
2578 * @param context CTS context.
2579 **/
Pipeline(deqp::Context & context)2580 Pipeline::Pipeline(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2581 {
2582 /* Nothing to be done here */
2583 }
2584
2585 /** Destructor
2586 *
2587 **/
~Pipeline()2588 Pipeline::~Pipeline()
2589 {
2590 Release();
2591 }
2592
2593 /** Initialize pipline object
2594 *
2595 **/
Init()2596 void Pipeline::Init()
2597 {
2598 Release();
2599
2600 const Functions& gl = m_context.getRenderContext().getFunctions();
2601
2602 /* Generate */
2603 gl.genProgramPipelines(1, &m_id);
2604 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
2605 }
2606
2607 /** Release pipeline object
2608 *
2609 **/
Release()2610 void Pipeline::Release()
2611 {
2612 if (m_invalid_id != m_id)
2613 {
2614 const Functions& gl = m_context.getRenderContext().getFunctions();
2615
2616 /* Generate */
2617 gl.deleteProgramPipelines(1, &m_id);
2618 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines");
2619
2620 m_id = m_invalid_id;
2621 }
2622 }
2623
2624 /** Bind pipeline
2625 *
2626 **/
Bind()2627 void Pipeline::Bind()
2628 {
2629 const Functions& gl = m_context.getRenderContext().getFunctions();
2630
2631 Bind(gl, m_id);
2632 }
2633
2634 /** Set which stages should be active
2635 *
2636 * @param program_id Id of program
2637 * @param stages Logical combination of enums representing stages
2638 **/
UseProgramStages(GLuint program_id,GLenum stages)2639 void Pipeline::UseProgramStages(GLuint program_id, GLenum stages)
2640 {
2641 const Functions& gl = m_context.getRenderContext().getFunctions();
2642
2643 UseProgramStages(gl, m_id, program_id, stages);
2644 }
2645
2646 /** Bind pipeline
2647 *
2648 * @param gl Functiions
2649 * @param id Pipeline id
2650 **/
Bind(const Functions & gl,GLuint id)2651 void Pipeline::Bind(const Functions& gl, GLuint id)
2652 {
2653 gl.bindProgramPipeline(id);
2654 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
2655 }
2656
2657 /** Set which stages should be active
2658 *
2659 * @param gl Functiions
2660 * @param id Pipeline id
2661 * @param program_id Id of program
2662 * @param stages Logical combination of enums representing stages
2663 **/
UseProgramStages(const Functions & gl,GLuint id,GLuint program_id,GLenum stages)2664 void Pipeline::UseProgramStages(const Functions& gl, GLuint id, GLuint program_id, GLenum stages)
2665 {
2666 gl.useProgramStages(id, stages, program_id);
2667 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
2668 }
2669
2670 /* Program constants */
2671 const GLuint Program::m_invalid_id = 0;
2672
2673 /** Constructor.
2674 *
2675 * @param context CTS context.
2676 **/
Program(deqp::Context & context)2677 Program::Program(deqp::Context& context)
2678 : m_id(m_invalid_id)
2679 , m_compute(context)
2680 , m_fragment(context)
2681 , m_geometry(context)
2682 , m_tess_ctrl(context)
2683 , m_tess_eval(context)
2684 , m_vertex(context)
2685 , m_context(context)
2686 {
2687 /* Nothing to be done here */
2688 }
2689
2690 /** Destructor
2691 *
2692 **/
~Program()2693 Program::~Program()
2694 {
2695 Release();
2696 }
2697
2698 /** Initialize program instance
2699 *
2700 * @param compute_shader Compute shader source code
2701 * @param fragment_shader Fragment shader source code
2702 * @param geometry_shader Geometry shader source code
2703 * @param tessellation_control_shader Tessellation control shader source code
2704 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2705 * @param vertex_shader Vertex shader source code
2706 * @param captured_varyings Vector of variables to be captured with transfrom feedback
2707 * @param capture_interleaved Select mode of transform feedback (separate or interleaved)
2708 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2709 **/
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)2710 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2711 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2712 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2713 const NameVector& captured_varyings, bool capture_interleaved, bool is_separable)
2714 {
2715 /* Delete previous program */
2716 Release();
2717
2718 /* GL entry points */
2719 const Functions& gl = m_context.getRenderContext().getFunctions();
2720
2721 /* Initialize shaders */
2722 m_compute.Init(Shader::COMPUTE, compute_shader);
2723 m_fragment.Init(Shader::FRAGMENT, fragment_shader);
2724 m_geometry.Init(Shader::GEOMETRY, geometry_shader);
2725 m_tess_ctrl.Init(Shader::TESS_CTRL, tessellation_control_shader);
2726 m_tess_eval.Init(Shader::TESS_EVAL, tessellation_evaluation_shader);
2727 m_vertex.Init(Shader::VERTEX, vertex_shader);
2728
2729 /* Create program, set up transform feedback and attach shaders */
2730 Create(gl, m_id);
2731 Capture(gl, m_id, captured_varyings, capture_interleaved);
2732 Attach(gl, m_id, m_compute.m_id);
2733 Attach(gl, m_id, m_fragment.m_id);
2734 Attach(gl, m_id, m_geometry.m_id);
2735 Attach(gl, m_id, m_tess_ctrl.m_id);
2736 Attach(gl, m_id, m_tess_eval.m_id);
2737 Attach(gl, m_id, m_vertex.m_id);
2738
2739 /* Set separable parameter */
2740 if (true == is_separable)
2741 {
2742 gl.programParameteri(m_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2743 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
2744 }
2745
2746 try
2747 {
2748 /* Link program */
2749 Link(gl, m_id);
2750 }
2751 catch (const LinkageException& exc)
2752 {
2753 throw BuildException(exc.what(), compute_shader, fragment_shader, geometry_shader, tessellation_control_shader,
2754 tessellation_evaluation_shader, vertex_shader);
2755 }
2756 }
2757
2758 /** Initialize program instance
2759 *
2760 * @param compute_shader Compute shader source code
2761 * @param fragment_shader Fragment shader source code
2762 * @param geometry_shader Geometry shader source code
2763 * @param tessellation_control_shader Tessellation control shader source code
2764 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2765 * @param vertex_shader Vertex shader source code
2766 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2767 **/
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)2768 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2769 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2770 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2771 bool is_separable)
2772 {
2773 NameVector captured_varying;
2774
2775 Init(compute_shader, fragment_shader, geometry_shader, tessellation_control_shader, tessellation_evaluation_shader,
2776 vertex_shader, captured_varying, true, is_separable);
2777 }
2778
2779 /** Release program instance
2780 *
2781 **/
Release()2782 void Program::Release()
2783 {
2784 const Functions& gl = m_context.getRenderContext().getFunctions();
2785
2786 if (m_invalid_id != m_id)
2787 {
2788 Use(gl, m_invalid_id);
2789
2790 gl.deleteProgram(m_id);
2791 m_id = m_invalid_id;
2792 }
2793
2794 m_compute.Release();
2795 m_fragment.Release();
2796 m_geometry.Release();
2797 m_tess_ctrl.Release();
2798 m_tess_eval.Release();
2799 m_vertex.Release();
2800 }
2801
2802 /** Get <pname> for a set of active uniforms
2803 *
2804 * @param count Number of indices
2805 * @param indices Indices of uniforms
2806 * @param pname Queired pname
2807 * @param params Array that will be filled with values of parameters
2808 **/
GetActiveUniformsiv(GLsizei count,const GLuint * indices,GLenum pname,GLint * params) const2809 void Program::GetActiveUniformsiv(GLsizei count, const GLuint* indices, GLenum pname, GLint* params) const
2810 {
2811 const Functions& gl = m_context.getRenderContext().getFunctions();
2812
2813 GetActiveUniformsiv(gl, m_id, count, indices, pname, params);
2814 }
2815
2816 /** Get location of attribute
2817 *
2818 * @param name Name of attribute
2819 *
2820 * @return Result of query
2821 **/
GetAttribLocation(const std::string & name) const2822 glw::GLint Program::GetAttribLocation(const std::string& name) const
2823 {
2824 const Functions& gl = m_context.getRenderContext().getFunctions();
2825
2826 return GetAttribLocation(gl, m_id, name);
2827 }
2828
2829 /** Query resource
2830 *
2831 * @param interface Interface to be queried
2832 * @param index Index of resource
2833 * @param property Property to be queried
2834 * @param buf_size Size of <params> buffer
2835 * @param params Results of query
2836 **/
GetResource(GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params) const2837 void Program::GetResource(GLenum interface, GLuint index, GLenum property, GLsizei buf_size, GLint* params) const
2838 {
2839 const Functions& gl = m_context.getRenderContext().getFunctions();
2840
2841 GetResource(gl, m_id, interface, index, property, buf_size, params);
2842 }
2843
2844 /** Query for index of resource
2845 *
2846 * @param name Name of resource
2847 * @param interface Interface to be queried
2848 *
2849 * @return Result of query
2850 **/
GetResourceIndex(const std::string & name,GLenum interface) const2851 glw::GLuint Program::GetResourceIndex(const std::string& name, GLenum interface) const
2852 {
2853 const Functions& gl = m_context.getRenderContext().getFunctions();
2854
2855 return GetResourceIndex(gl, m_id, name, interface);
2856 }
2857
2858 /** Get indices for a set of uniforms
2859 *
2860 * @param count Count number of uniforms
2861 * @param names Names of uniforms
2862 * @param indices Buffer that will be filled with indices
2863 **/
GetUniformIndices(GLsizei count,const GLchar ** names,GLuint * indices) const2864 void Program::GetUniformIndices(GLsizei count, const GLchar** names, GLuint* indices) const
2865 {
2866 const Functions& gl = m_context.getRenderContext().getFunctions();
2867
2868 GetUniformIndices(gl, m_id, count, names, indices);
2869 }
2870
2871 /** Get uniform location
2872 *
2873 * @param name Name of uniform
2874 *
2875 * @return Results of query
2876 **/
GetUniformLocation(const std::string & name) const2877 glw::GLint Program::GetUniformLocation(const std::string& name) const
2878 {
2879 const Functions& gl = m_context.getRenderContext().getFunctions();
2880
2881 return GetUniformLocation(gl, m_id, name);
2882 }
2883
2884 /** Set program as active
2885 *
2886 **/
Use() const2887 void Program::Use() const
2888 {
2889 const Functions& gl = m_context.getRenderContext().getFunctions();
2890
2891 Use(gl, m_id);
2892 }
2893
2894 /** Attach shader to program
2895 *
2896 * @param gl GL functions
2897 * @param program_id Id of program
2898 * @param shader_id Id of shader
2899 **/
Attach(const Functions & gl,GLuint program_id,GLuint shader_id)2900 void Program::Attach(const Functions& gl, GLuint program_id, GLuint shader_id)
2901 {
2902 /* Sanity checks */
2903 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
2904 {
2905 return;
2906 }
2907
2908 gl.attachShader(program_id, shader_id);
2909 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
2910 }
2911
2912 /** Set up captured varyings
2913 *
2914 * @param gl GL functions
2915 * @param id Id of program
2916 * @param captured_varyings Vector of varyings
2917 * @param capture_interleaved Selects if interleaved or separate mode should be used
2918 **/
Capture(const Functions & gl,GLuint id,const NameVector & captured_varyings,bool capture_interleaved)2919 void Program::Capture(const Functions& gl, GLuint id, const NameVector& captured_varyings, bool capture_interleaved)
2920 {
2921 const size_t n_varyings = captured_varyings.size();
2922
2923 if (0 == n_varyings)
2924 {
2925 /* empty list, skip */
2926 return;
2927 }
2928
2929 std::vector<const GLchar*> varying_names;
2930 varying_names.resize(n_varyings);
2931
2932 for (size_t i = 0; i < n_varyings; ++i)
2933 {
2934 varying_names[i] = captured_varyings[i].c_str();
2935 }
2936
2937 GLenum mode = 0;
2938 if (true == capture_interleaved)
2939 {
2940 mode = GL_INTERLEAVED_ATTRIBS;
2941 }
2942 else
2943 {
2944 mode = GL_SEPARATE_ATTRIBS;
2945 }
2946
2947 gl.transformFeedbackVaryings(id, static_cast<GLsizei>(n_varyings), &varying_names[0], mode);
2948 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
2949 }
2950
2951 /** Create program instance
2952 *
2953 * @param gl GL functions
2954 * @param out_id Id of program
2955 **/
Create(const Functions & gl,GLuint & out_id)2956 void Program::Create(const Functions& gl, GLuint& out_id)
2957 {
2958 const GLuint id = gl.createProgram();
2959 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
2960
2961 if (m_invalid_id == id)
2962 {
2963 TCU_FAIL("Failed to create program");
2964 }
2965
2966 out_id = id;
2967 }
2968
2969 /** Get <pname> for a set of active uniforms
2970 *
2971 * @param gl Functions
2972 * @param program_id Id of program
2973 * @param count Number of indices
2974 * @param indices Indices of uniforms
2975 * @param pname Queired pname
2976 * @param params Array that will be filled with values of parameters
2977 **/
GetActiveUniformsiv(const Functions & gl,GLuint program_id,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)2978 void Program::GetActiveUniformsiv(const Functions& gl, GLuint program_id, GLsizei count, const GLuint* indices,
2979 GLenum pname, GLint* params)
2980 {
2981 gl.getActiveUniformsiv(program_id, count, indices, pname, params);
2982 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
2983 }
2984
2985 /** Get indices for a set of uniforms
2986 *
2987 * @param gl Functions
2988 * @param program_id Id of program
2989 * @param count Count number of uniforms
2990 * @param names Names of uniforms
2991 * @param indices Buffer that will be filled with indices
2992 **/
GetUniformIndices(const Functions & gl,GLuint program_id,GLsizei count,const GLchar ** names,GLuint * indices)2993 void Program::GetUniformIndices(const Functions& gl, GLuint program_id, GLsizei count, const GLchar** names,
2994 GLuint* indices)
2995 {
2996 gl.getUniformIndices(program_id, count, names, indices);
2997 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
2998 }
2999
3000 /** Link program
3001 *
3002 * @param gl GL functions
3003 * @param id Id of program
3004 **/
Link(const Functions & gl,GLuint id)3005 void Program::Link(const Functions& gl, GLuint id)
3006 {
3007 GLint status = GL_FALSE;
3008
3009 gl.linkProgram(id);
3010 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
3011
3012 /* Get link status */
3013 gl.getProgramiv(id, GL_LINK_STATUS, &status);
3014 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
3015
3016 /* Log link error */
3017 if (GL_TRUE != status)
3018 {
3019 glw::GLint length = 0;
3020 std::string message;
3021
3022 /* Get error log length */
3023 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
3024 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
3025
3026 message.resize(length, 0);
3027
3028 /* Get error log */
3029 gl.getProgramInfoLog(id, length, 0, &message[0]);
3030 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
3031
3032 throw LinkageException(message.c_str());
3033 }
3034 }
3035
3036 /** Set generic uniform
3037 *
3038 * @param gl Functions
3039 * @param type Type of uniform
3040 * @param count Length of array
3041 * @param location Location of uniform
3042 * @param data Data that will be used
3043 **/
Uniform(const Functions & gl,const Type & type,GLsizei count,GLint location,const GLvoid * data)3044 void Program::Uniform(const Functions& gl, const Type& type, GLsizei count, GLint location, const GLvoid* data)
3045 {
3046 if (-1 == location)
3047 {
3048 TCU_FAIL("Uniform is inactive");
3049 }
3050
3051 switch (type.m_basic_type)
3052 {
3053 case Type::Double:
3054 if (1 == type.m_n_columns)
3055 {
3056 getUniformNdv(gl, type.m_n_rows)(location, count, (const GLdouble*)data);
3057 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNdv");
3058 }
3059 else
3060 {
3061 getUniformMatrixNdv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLdouble*)data);
3062 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNdv");
3063 }
3064 break;
3065 case Type::Float:
3066 if (1 == type.m_n_columns)
3067 {
3068 getUniformNfv(gl, type.m_n_rows)(location, count, (const GLfloat*)data);
3069 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNfv");
3070 }
3071 else
3072 {
3073 getUniformMatrixNfv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLfloat*)data);
3074 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNfv");
3075 }
3076 break;
3077 case Type::Int:
3078 getUniformNiv(gl, type.m_n_rows)(location, count, (const GLint*)data);
3079 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNiv");
3080 break;
3081 case Type::Uint:
3082 getUniformNuiv(gl, type.m_n_rows)(location, count, (const GLuint*)data);
3083 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNuiv");
3084 break;
3085 default:
3086 TCU_FAIL("Invalid enum");
3087 }
3088 }
3089
3090 /** Use program
3091 *
3092 * @param gl GL functions
3093 * @param id Id of program
3094 **/
Use(const Functions & gl,GLuint id)3095 void Program::Use(const Functions& gl, GLuint id)
3096 {
3097 gl.useProgram(id);
3098 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
3099 }
3100
3101 /** Get location of attribute
3102 *
3103 * @param gl GL functions
3104 * @param id Id of program
3105 * @param name Name of attribute
3106 *
3107 * @return Location of attribute
3108 **/
GetAttribLocation(const Functions & gl,GLuint id,const std::string & name)3109 GLint Program::GetAttribLocation(const Functions& gl, GLuint id, const std::string& name)
3110 {
3111 GLint location = gl.getAttribLocation(id, name.c_str());
3112 GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
3113
3114 return location;
3115 }
3116
3117 /** Query resource
3118 *
3119 * @param gl GL functions
3120 * @param id Id of program
3121 * @param interface Interface to be queried
3122 * @param index Index of resource
3123 * @param property Property to be queried
3124 * @param buf_size Size of <params> buffer
3125 * @param params Results of query
3126 **/
GetResource(const Functions & gl,GLuint id,GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params)3127 void Program::GetResource(const Functions& gl, GLuint id, GLenum interface, GLuint index, GLenum property,
3128 GLsizei buf_size, GLint* params)
3129 {
3130 gl.getProgramResourceiv(id, interface, index, 1 /* propCount */, &property, buf_size /* bufSize */, 0 /* length */,
3131 params);
3132 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3133 }
3134
3135 /** Get index of resource
3136 *
3137 * @param gl GL functions
3138 * @param id Id of program
3139 * @param name Name of resource
3140 * @param interface Program interface to queried
3141 *
3142 * @return Location of attribute
3143 **/
GetResourceIndex(const Functions & gl,GLuint id,const std::string & name,GLenum interface)3144 GLuint Program::GetResourceIndex(const Functions& gl, GLuint id, const std::string& name, GLenum interface)
3145 {
3146 GLuint index = gl.getProgramResourceIndex(id, interface, name.c_str());
3147 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3148
3149 return index;
3150 }
3151
3152 /** Get location of attribute
3153 *
3154 * @param gl GL functions
3155 * @param id Id of program
3156 * @param name Name of attribute
3157 *
3158 * @return Location of uniform
3159 **/
GetUniformLocation(const Functions & gl,GLuint id,const std::string & name)3160 GLint Program::GetUniformLocation(const Functions& gl, GLuint id, const std::string& name)
3161 {
3162 GLint location = gl.getUniformLocation(id, name.c_str());
3163 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3164
3165 return location;
3166 }
3167
3168 /** Constructor
3169 *
3170 * @param error_message Error message
3171 * @param compute_shader Source code for compute stage
3172 * @param fragment_shader Source code for fragment stage
3173 * @param geometry_shader Source code for geometry stage
3174 * @param tess_ctrl_shader Source code for tessellation control stage
3175 * @param tess_eval_shader Source code for tessellation evaluation stage
3176 * @param vertex_shader Source code for vertex stage
3177 **/
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)3178 Program::BuildException::BuildException(const glw::GLchar* error_message, const std::string compute_shader,
3179 const std::string fragment_shader, const std::string geometry_shader,
3180 const std::string tess_ctrl_shader, const std::string tess_eval_shader,
3181 const std::string vertex_shader)
3182 : m_error_message(error_message)
3183 , m_compute_shader(compute_shader)
3184 , m_fragment_shader(fragment_shader)
3185 , m_geometry_shader(geometry_shader)
3186 , m_tess_ctrl_shader(tess_ctrl_shader)
3187 , m_tess_eval_shader(tess_eval_shader)
3188 , m_vertex_shader(vertex_shader)
3189 {
3190 }
3191
3192 /** Overwrites std::exception::what method
3193 *
3194 * @return Message compossed from error message and shader sources
3195 **/
what() const3196 const char* Program::BuildException::what() const throw()
3197 {
3198 return "Failed to link program";
3199 }
3200
3201 /** Logs error message and shader sources **/
log(deqp::Context & context) const3202 void Program::BuildException::log(deqp::Context& context) const
3203 {
3204 context.getTestContext().getLog() << tcu::TestLog::Message << "Link failure: " << m_error_message
3205 << tcu::TestLog::EndMessage;
3206
3207 Shader::LogSource(context, m_vertex_shader, Shader::VERTEX);
3208 Shader::LogSource(context, m_tess_ctrl_shader, Shader::TESS_CTRL);
3209 Shader::LogSource(context, m_tess_eval_shader, Shader::TESS_EVAL);
3210 Shader::LogSource(context, m_geometry_shader, Shader::GEOMETRY);
3211 Shader::LogSource(context, m_fragment_shader, Shader::FRAGMENT);
3212 Shader::LogSource(context, m_compute_shader, Shader::COMPUTE);
3213 }
3214
3215 /** Constructor
3216 *
3217 * @param message Linking error message
3218 **/
LinkageException(const glw::GLchar * message)3219 Program::LinkageException::LinkageException(const glw::GLchar* message) : m_error_message(message)
3220 {
3221 /* Nothing to be done */
3222 }
3223
3224 /** Returns error messages
3225 *
3226 * @return Linking error message
3227 **/
what() const3228 const char* Program::LinkageException::what() const throw()
3229 {
3230 return m_error_message.c_str();
3231 }
3232
3233 /* Texture constants */
3234 const GLuint Texture::m_invalid_id = -1;
3235
3236 /** Constructor.
3237 *
3238 * @param context CTS context.
3239 **/
Texture(deqp::Context & context)3240 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_type(TEX_2D)
3241 {
3242 /* Nothing to done here */
3243 }
3244
3245 /** Destructor
3246 *
3247 **/
~Texture()3248 Texture::~Texture()
3249 {
3250 Release();
3251 }
3252
3253 /** Initialize texture instance
3254 *
3255 * @param tex_type Type of texture
3256 * @param width Width of texture
3257 * @param height Height of texture
3258 * @param depth Depth of texture
3259 * @param internal_format Internal format of texture
3260 * @param format Format of texture data
3261 * @param type Type of texture data
3262 * @param data Texture data
3263 **/
Init(TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format,GLenum format,GLenum type,GLvoid * data)3264 void Texture::Init(TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum internal_format, GLenum format,
3265 GLenum type, GLvoid* data)
3266 {
3267 const Functions& gl = m_context.getRenderContext().getFunctions();
3268
3269 /* Delete previous texture */
3270 Release();
3271
3272 m_type = tex_type;
3273
3274 /* Generate, bind, allocate storage and upload data */
3275 Generate(gl, m_id);
3276 Bind(gl, m_id, tex_type);
3277 Storage(gl, tex_type, width, height, depth, internal_format);
3278 Update(gl, tex_type, width, height, depth, format, type, data);
3279 }
3280
3281 /** Initialize buffer texture
3282 *
3283 * @param internal_format Internal format of texture
3284 * @param buffer_id Id of buffer that will be used as data source
3285 **/
Init(GLenum internal_format,GLuint buffer_id)3286 void Texture::Init(GLenum internal_format, GLuint buffer_id)
3287 {
3288 const Functions& gl = m_context.getRenderContext().getFunctions();
3289
3290 /* Delete previous texture */
3291 Release();
3292
3293 m_type = TEX_BUFFER;
3294
3295 /* Generate, bind and attach buffer */
3296 Generate(gl, m_id);
3297 Bind(gl, m_id, TEX_BUFFER);
3298 TexBuffer(gl, buffer_id, internal_format);
3299 }
3300
3301 /** Release texture instance
3302 *
3303 **/
Release()3304 void Texture::Release()
3305 {
3306 if (m_invalid_id != m_id)
3307 {
3308 const Functions& gl = m_context.getRenderContext().getFunctions();
3309
3310 gl.deleteTextures(1, &m_id);
3311 m_id = m_invalid_id;
3312 }
3313 }
3314
3315 /** Bind texture to its target
3316 *
3317 **/
Bind() const3318 void Texture::Bind() const
3319 {
3320 const Functions& gl = m_context.getRenderContext().getFunctions();
3321
3322 Bind(gl, m_id, m_type);
3323 }
3324
3325 /** Get texture data
3326 *
3327 * @param format Format of data
3328 * @param type Type of data
3329 * @param out_data Buffer for data
3330 **/
Get(GLenum format,GLenum type,GLvoid * out_data) const3331 void Texture::Get(GLenum format, GLenum type, GLvoid* out_data) const
3332 {
3333 const Functions& gl = m_context.getRenderContext().getFunctions();
3334
3335 Bind(gl, m_id, m_type);
3336 Get(gl, m_type, format, type, out_data);
3337 }
3338
3339 /** Bind texture to target
3340 *
3341 * @param gl GL functions
3342 * @param id Id of texture
3343 * @param tex_type Type of texture
3344 **/
Bind(const Functions & gl,GLuint id,TYPES tex_type)3345 void Texture::Bind(const Functions& gl, GLuint id, TYPES tex_type)
3346 {
3347 GLenum target = GetTargetGLenum(tex_type);
3348
3349 gl.bindTexture(target, id);
3350 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3351 }
3352
3353 /** Generate texture instance
3354 *
3355 * @param gl GL functions
3356 * @param out_id Id of texture
3357 **/
Generate(const Functions & gl,GLuint & out_id)3358 void Texture::Generate(const Functions& gl, GLuint& out_id)
3359 {
3360 GLuint id = m_invalid_id;
3361
3362 gl.genTextures(1, &id);
3363 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
3364
3365 if (m_invalid_id == id)
3366 {
3367 TCU_FAIL("Invalid id");
3368 }
3369
3370 out_id = id;
3371 }
3372
3373 /** Get texture data
3374 *
3375 * @param gl GL functions
3376 * @param format Format of data
3377 * @param type Type of data
3378 * @param out_data Buffer for data
3379 **/
Get(const Functions & gl,TYPES tex_type,GLenum format,GLenum type,GLvoid * out_data)3380 void Texture::Get(const Functions& gl, TYPES tex_type, GLenum format, GLenum type, GLvoid* out_data)
3381 {
3382 GLenum target = GetTargetGLenum(tex_type);
3383
3384 if (TEX_CUBE != tex_type)
3385 {
3386 gl.getTexImage(target, 0 /* level */, format, type, out_data);
3387 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3388 }
3389 else
3390 {
3391 GLint width;
3392 GLint height;
3393
3394 if ((GL_RGBA != format) && (GL_UNSIGNED_BYTE != type))
3395 {
3396 TCU_FAIL("Not implemented");
3397 }
3398
3399 GLuint texel_size = 4;
3400
3401 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_WIDTH, &width);
3402 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3403
3404 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_HEIGHT, &height);
3405 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3406
3407 const GLuint image_size = width * height * texel_size;
3408
3409 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, format, type,
3410 (GLvoid*)((GLchar*)out_data + (image_size * 0)));
3411 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, format, type,
3412 (GLvoid*)((GLchar*)out_data + (image_size * 1)));
3413 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, format, type,
3414 (GLvoid*)((GLchar*)out_data + (image_size * 2)));
3415 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, format, type,
3416 (GLvoid*)((GLchar*)out_data + (image_size * 3)));
3417 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, format, type,
3418 (GLvoid*)((GLchar*)out_data + (image_size * 4)));
3419 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, format, type,
3420 (GLvoid*)((GLchar*)out_data + (image_size * 5)));
3421 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3422 }
3423 }
3424
3425 /** Allocate storage for texture
3426 *
3427 * @param gl GL functions
3428 * @param tex_type Type of texture
3429 * @param width Width of texture
3430 * @param height Height of texture
3431 * @param depth Depth of texture
3432 * @param internal_format Internal format of texture
3433 **/
Storage(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format)3434 void Texture::Storage(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth,
3435 GLenum internal_format)
3436 {
3437 static const GLuint levels = 1;
3438
3439 GLenum target = GetTargetGLenum(tex_type);
3440
3441 switch (tex_type)
3442 {
3443 case TEX_1D:
3444 gl.texStorage1D(target, levels, internal_format, width);
3445 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3446 break;
3447 case TEX_2D:
3448 case TEX_1D_ARRAY:
3449 case TEX_2D_RECT:
3450 case TEX_CUBE:
3451 gl.texStorage2D(target, levels, internal_format, width, height);
3452 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3453 break;
3454 case TEX_3D:
3455 case TEX_2D_ARRAY:
3456 gl.texStorage3D(target, levels, internal_format, width, height, depth);
3457 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3458 break;
3459 default:
3460 TCU_FAIL("Invalid enum");
3461 }
3462 }
3463
3464 /** Attach buffer as source of texture buffer data
3465 *
3466 * @param gl GL functions
3467 * @param internal_format Internal format of texture
3468 * @param buffer_id Id of buffer that will be used as data source
3469 **/
TexBuffer(const Functions & gl,GLenum internal_format,GLuint & buffer_id)3470 void Texture::TexBuffer(const Functions& gl, GLenum internal_format, GLuint& buffer_id)
3471 {
3472 gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id);
3473 GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
3474 }
3475
3476 /** Update contents of texture
3477 *
3478 * @param gl GL functions
3479 * @param tex_type Type of texture
3480 * @param width Width of texture
3481 * @param height Height of texture
3482 * @param format Format of data
3483 * @param type Type of data
3484 * @param data Buffer with image data
3485 **/
Update(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum format,GLenum type,GLvoid * data)3486 void Texture::Update(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum format,
3487 GLenum type, GLvoid* data)
3488 {
3489 static const GLuint level = 0;
3490
3491 GLenum target = GetTargetGLenum(tex_type);
3492
3493 switch (tex_type)
3494 {
3495 case TEX_1D:
3496 gl.texSubImage1D(target, level, 0 /* x */, width, format, type, data);
3497 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3498 break;
3499 case TEX_2D:
3500 case TEX_1D_ARRAY:
3501 case TEX_2D_RECT:
3502 gl.texSubImage2D(target, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
3503 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3504 break;
3505 case TEX_CUBE:
3506 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3507 data);
3508 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3509 data);
3510 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3511 data);
3512 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3513 data);
3514 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3515 data);
3516 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3517 data);
3518 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3519 break;
3520 case TEX_3D:
3521 case TEX_2D_ARRAY:
3522 gl.texSubImage3D(target, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format, type, data);
3523 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3524 break;
3525 default:
3526 TCU_FAIL("Invalid enum");
3527 }
3528 }
3529
3530 /** Get target for given texture type
3531 *
3532 * @param type Type of texture
3533 *
3534 * @return Target
3535 **/
GetTargetGLenum(TYPES type)3536 GLenum Texture::GetTargetGLenum(TYPES type)
3537 {
3538 GLenum result = 0;
3539
3540 switch (type)
3541 {
3542 case TEX_BUFFER:
3543 result = GL_TEXTURE_BUFFER;
3544 break;
3545 case TEX_2D:
3546 result = GL_TEXTURE_2D;
3547 break;
3548 case TEX_2D_RECT:
3549 result = GL_TEXTURE_RECTANGLE;
3550 break;
3551 case TEX_2D_ARRAY:
3552 result = GL_TEXTURE_2D_ARRAY;
3553 break;
3554 case TEX_3D:
3555 result = GL_TEXTURE_3D;
3556 break;
3557 case TEX_CUBE:
3558 result = GL_TEXTURE_CUBE_MAP;
3559 break;
3560 case TEX_1D:
3561 result = GL_TEXTURE_1D;
3562 break;
3563 case TEX_1D_ARRAY:
3564 result = GL_TEXTURE_1D_ARRAY;
3565 break;
3566 }
3567
3568 return result;
3569 }
3570
3571 /* VertexArray constants */
3572 const GLuint VertexArray::m_invalid_id = -1;
3573
3574 /** Constructor.
3575 *
3576 * @param context CTS context.
3577 **/
VertexArray(deqp::Context & context)3578 VertexArray::VertexArray(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
3579 {
3580 }
3581
3582 /** Destructor
3583 *
3584 **/
~VertexArray()3585 VertexArray::~VertexArray()
3586 {
3587 Release();
3588 }
3589
3590 /** Initialize vertex array instance
3591 *
3592 **/
Init()3593 void VertexArray::Init()
3594 {
3595 /* Delete previous instance */
3596 Release();
3597
3598 const Functions& gl = m_context.getRenderContext().getFunctions();
3599
3600 Generate(gl, m_id);
3601 }
3602
3603 /** Release vertex array object instance
3604 *
3605 **/
Release()3606 void VertexArray::Release()
3607 {
3608 if (m_invalid_id != m_id)
3609 {
3610 const Functions& gl = m_context.getRenderContext().getFunctions();
3611
3612 gl.deleteVertexArrays(1, &m_id);
3613
3614 m_id = m_invalid_id;
3615 }
3616 }
3617
3618 /** Set attribute in VAO
3619 *
3620 * @param index Index of attribute
3621 * @param type Type of attribute
3622 * @param n_array_elements Arary length
3623 * @param normalized Selects if values should be normalized
3624 * @param stride Stride
3625 * @param pointer Pointer to data, or offset in buffer
3626 **/
Attribute(GLuint index,const Type & type,GLuint n_array_elements,GLboolean normalized,GLsizei stride,const GLvoid * pointer)3627 void VertexArray::Attribute(GLuint index, const Type& type, GLuint n_array_elements, GLboolean normalized,
3628 GLsizei stride, const GLvoid* pointer)
3629 {
3630 const Functions& gl = m_context.getRenderContext().getFunctions();
3631
3632 AttribPointer(gl, index, type, n_array_elements, normalized, stride, pointer);
3633 Enable(gl, index, type, n_array_elements);
3634 }
3635
3636 /** Binds Vertex array object
3637 *
3638 **/
Bind()3639 void VertexArray::Bind()
3640 {
3641 const Functions& gl = m_context.getRenderContext().getFunctions();
3642
3643 Bind(gl, m_id);
3644 }
3645
3646 /** Set attribute in VAO
3647 *
3648 * @param gl Functions
3649 * @param index Index of attribute
3650 * @param type Type of attribute
3651 * @param n_array_elements Arary length
3652 * @param normalized Selects if values should be normalized
3653 * @param stride Stride
3654 * @param pointer Pointer to data, or offset in buffer
3655 **/
AttribPointer(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements,GLboolean normalized,GLsizei stride,const GLvoid * pointer)3656 void VertexArray::AttribPointer(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements,
3657 GLboolean normalized, GLsizei stride, const GLvoid* pointer)
3658 {
3659 const GLuint basic_type_size = Type::GetTypeSize(type.m_basic_type);
3660 const GLint size = (GLint)type.m_n_rows;
3661 const GLuint column_size = (GLuint)size * basic_type_size;
3662 const GLenum gl_type = Type::GetTypeGLenum(type.m_basic_type);
3663
3664 GLuint offset = 0;
3665
3666 /* If attribute is not an array */
3667 if (0 == n_array_elements)
3668 {
3669 n_array_elements = 1;
3670 }
3671
3672 /* For each element in array */
3673 for (GLuint element = 0; element < n_array_elements; ++element)
3674 {
3675 /* For each column in matrix */
3676 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3677 {
3678 /* Calculate offset */
3679 const GLvoid* ptr = (GLubyte*)pointer + offset;
3680
3681 /* Set up attribute */
3682 switch (type.m_basic_type)
3683 {
3684 case Type::Float:
3685 gl.vertexAttribPointer(index, size, gl_type, normalized, stride, ptr);
3686 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribPointer");
3687 break;
3688 case Type::Int:
3689 case Type::Uint:
3690 gl.vertexAttribIPointer(index, size, gl_type, stride, ptr);
3691 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribIPointer");
3692 break;
3693 case Type::Double:
3694 gl.vertexAttribLPointer(index, size, gl_type, stride, ptr);
3695 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribLPointer");
3696 break;
3697 default:
3698 TCU_FAIL("Invalid enum");
3699 }
3700
3701 /* Next location */
3702 offset += column_size;
3703 index += 1;
3704 }
3705 }
3706 }
3707
3708 /** Binds Vertex array object
3709 *
3710 * @param gl GL functions
3711 * @param id ID of vertex array object
3712 **/
Bind(const glw::Functions & gl,glw::GLuint id)3713 void VertexArray::Bind(const glw::Functions& gl, glw::GLuint id)
3714 {
3715 gl.bindVertexArray(id);
3716 GLU_EXPECT_NO_ERROR(gl.getError(), "BindVertexArray");
3717 }
3718
3719 /** Disable attribute in VAO
3720 *
3721 * @param gl Functions
3722 * @param index Index of attribute
3723 * @param type Type of attribute
3724 * @param n_array_elements Arary length
3725 **/
Disable(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements)3726 void VertexArray::Disable(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements)
3727 {
3728 /* If attribute is not an array */
3729 if (0 == n_array_elements)
3730 {
3731 n_array_elements = 1;
3732 }
3733
3734 /* For each element in array */
3735 for (GLuint element = 0; element < n_array_elements; ++element)
3736 {
3737 /* For each column in matrix */
3738 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3739 {
3740 /* Enable attribute array */
3741 gl.disableVertexAttribArray(index);
3742 GLU_EXPECT_NO_ERROR(gl.getError(), "DisableVertexAttribArray");
3743
3744 /* Next location */
3745 index += 1;
3746 }
3747 }
3748 }
3749
3750 /** Set divisor for attribute
3751 *
3752 * @param gl Functions
3753 * @param index Index of attribute
3754 * @param divisor New divisor value
3755 **/
Divisor(const Functions & gl,GLuint index,GLuint divisor)3756 void VertexArray::Divisor(const Functions& gl, GLuint index, GLuint divisor)
3757 {
3758 gl.vertexAttribDivisor(index, divisor);
3759 GLU_EXPECT_NO_ERROR(gl.getError(), "VertexAttribDivisor");
3760 }
3761
3762 /** Enables attribute in VAO
3763 *
3764 * @param gl Functions
3765 * @param index Index of attribute
3766 * @param type Type of attribute
3767 * @param n_array_elements Arary length
3768 **/
Enable(const Functions & gl,GLuint index,const Type & type,GLuint n_array_elements)3769 void VertexArray::Enable(const Functions& gl, GLuint index, const Type& type, GLuint n_array_elements)
3770 {
3771 /* If attribute is not an array */
3772 if (0 == n_array_elements)
3773 {
3774 n_array_elements = 1;
3775 }
3776
3777 /* For each element in array */
3778 for (GLuint element = 0; element < n_array_elements; ++element)
3779 {
3780 /* For each column in matrix */
3781 for (GLuint column = 1; column <= type.m_n_columns; ++column)
3782 {
3783 /* Enable attribute array */
3784 gl.enableVertexAttribArray(index);
3785 GLU_EXPECT_NO_ERROR(gl.getError(), "EnableVertexAttribArray");
3786
3787 /* Next location */
3788 index += 1;
3789 }
3790 }
3791 }
3792
3793 /** Generates Vertex array object
3794 *
3795 * @param gl GL functions
3796 * @param out_id ID of vertex array object
3797 **/
Generate(const glw::Functions & gl,glw::GLuint & out_id)3798 void VertexArray::Generate(const glw::Functions& gl, glw::GLuint& out_id)
3799 {
3800 GLuint id = m_invalid_id;
3801
3802 gl.genVertexArrays(1, &id);
3803 GLU_EXPECT_NO_ERROR(gl.getError(), "GenVertexArrays");
3804
3805 if (m_invalid_id == id)
3806 {
3807 TCU_FAIL("Invalid id");
3808 }
3809
3810 out_id = id;
3811 }
3812
3813 /* Constatns used by Variable */
3814 const GLint Variable::m_automatic_location = -1;
3815
3816 /** Copy constructor
3817 *
3818 **/
Variable(const Variable & var)3819 Variable::Variable(const Variable& var)
3820 : m_data(var.m_data)
3821 , m_data_size(var.m_data_size)
3822 , m_descriptor(var.m_descriptor.m_name.c_str(), var.m_descriptor.m_qualifiers.c_str(),
3823 var.m_descriptor.m_expected_component, var.m_descriptor.m_expected_location,
3824 var.m_descriptor.m_builtin, var.m_descriptor.m_normalized, var.m_descriptor.m_n_array_elements,
3825 var.m_descriptor.m_expected_stride_of_element, var.m_descriptor.m_offset)
3826 , m_storage(var.m_storage)
3827 {
3828 m_descriptor.m_type = var.m_descriptor.m_type;
3829
3830 if (BUILTIN != var.m_descriptor.m_type)
3831 {
3832 m_descriptor.m_interface = var.m_descriptor.m_interface;
3833 }
3834 }
3835
3836 /** Get code that defines variable
3837 *
3838 * @param flavour Provides info if variable is array or not
3839 *
3840 * @return String with code
3841 **/
GetDefinition(FLAVOUR flavour) const3842 std::string Variable::GetDefinition(FLAVOUR flavour) const
3843 {
3844 return m_descriptor.GetDefinition(flavour, m_storage);
3845 }
3846
3847 /** Calcualtes stride of variable
3848 *
3849 * @return Calculated value
3850 **/
GetStride() const3851 GLuint Variable::GetStride() const
3852 {
3853 GLint variable_stride = 0;
3854
3855 if (0 == m_descriptor.m_n_array_elements)
3856 {
3857 variable_stride = m_descriptor.m_expected_stride_of_element;
3858 }
3859 else
3860 {
3861 variable_stride = m_descriptor.m_expected_stride_of_element * m_descriptor.m_n_array_elements;
3862 }
3863
3864 return variable_stride;
3865 }
3866
3867 /** Check if variable is block
3868 *
3869 * @return true if variable type is block, false otherwise
3870 **/
IsBlock() const3871 bool Variable::IsBlock() const
3872 {
3873 if (BUILTIN == m_descriptor.m_type)
3874 {
3875 return false;
3876 }
3877
3878 const Interface* interface = m_descriptor.m_interface;
3879 if (0 == interface)
3880 {
3881 TCU_FAIL("Nullptr");
3882 }
3883
3884 return (Interface::BLOCK == interface->m_type);
3885 }
3886
3887 /** Check if variable is struct
3888 *
3889 * @return true if variable type is struct, false otherwise
3890 **/
IsStruct() const3891 bool Variable::IsStruct() const
3892 {
3893 if (BUILTIN == m_descriptor.m_type)
3894 {
3895 return false;
3896 }
3897
3898 const Interface* interface = m_descriptor.m_interface;
3899 if (0 == interface)
3900 {
3901 TCU_FAIL("Nullptr");
3902 }
3903
3904 return (Interface::STRUCT == interface->m_type);
3905 }
3906 /** Get code that reference variable
3907 *
3908 * @param parent_name Name of parent
3909 * @param variable Descriptor of variable
3910 * @param flavour Provides info about how variable should be referenced
3911 * @param array_index Index of array, ignored when variable is not array
3912 *
3913 * @return String with code
3914 **/
GetReference(const std::string & parent_name,const Descriptor & variable,FLAVOUR flavour,GLuint array_index)3915 std::string Variable::GetReference(const std::string& parent_name, const Descriptor& variable, FLAVOUR flavour,
3916 GLuint array_index)
3917 {
3918 std::string name;
3919
3920 /* Prepare name */
3921 if (false == parent_name.empty())
3922 {
3923 name = parent_name;
3924 name.append(".");
3925 name.append(variable.m_name);
3926 }
3927 else
3928 {
3929 name = variable.m_name;
3930 }
3931
3932 /* */
3933 switch (flavour)
3934 {
3935 case Utils::Variable::BASIC:
3936 break;
3937
3938 case Utils::Variable::ARRAY:
3939 name.append("[0]");
3940 break;
3941
3942 case Utils::Variable::INDEXED_BY_INVOCATION_ID:
3943 name.append("[gl_InvocationID]");
3944 break;
3945 }
3946
3947 /* Assumption that both variables have same lengths */
3948 if (0 != variable.m_n_array_elements)
3949 {
3950 GLchar buffer[16];
3951 sprintf(buffer, "%d", array_index);
3952 name.append("[");
3953 name.append(buffer);
3954 name.append("]");
3955 }
3956
3957 return name;
3958 }
3959
3960 /** Get "flavour" of varying
3961 *
3962 * @param stage Stage of shader
3963 * @param direction Selects if varying is in or out
3964 *
3965 * @return Flavour
3966 **/
GetFlavour(Shader::STAGES stage,VARYING_DIRECTION direction)3967 Variable::FLAVOUR Variable::GetFlavour(Shader::STAGES stage, VARYING_DIRECTION direction)
3968 {
3969 FLAVOUR result = BASIC;
3970
3971 switch (stage)
3972 {
3973 case Shader::GEOMETRY:
3974 case Shader::TESS_EVAL:
3975 if (INPUT == direction)
3976 {
3977 result = ARRAY;
3978 }
3979 break;
3980 case Shader::TESS_CTRL:
3981 result = INDEXED_BY_INVOCATION_ID;
3982 break;
3983 default:
3984 break;
3985 }
3986
3987 return result;
3988 }
3989
3990 /** Constructor, for built-in types
3991 *
3992 * @param name Name
3993 * @param qualifiers Qualifiers
3994 * @param expected_component Expected component of variable
3995 * @param expected_location Expected location
3996 * @param type Type
3997 * @param normalized Selects if data should be normalized
3998 * @param n_array_elements Length of array
3999 * @param expected_stride_of_element Expected stride of element
4000 * @param offset Offset
4001 **/
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)4002 Variable::Descriptor::Descriptor(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4003 GLint expected_location, const Type& type, GLboolean normalized,
4004 GLuint n_array_elements, GLint expected_stride_of_element, GLuint offset)
4005 : m_expected_component(expected_component)
4006 , m_expected_location(expected_location)
4007 , m_expected_stride_of_element(expected_stride_of_element)
4008 , m_n_array_elements(n_array_elements)
4009 , m_name(name)
4010 , m_normalized(normalized)
4011 , m_offset(offset)
4012 , m_qualifiers(qualifiers)
4013 , m_type(BUILTIN)
4014 , m_builtin(type)
4015 {
4016 }
4017
4018 /** Constructor, for interface types
4019 *
4020 * @param name Name
4021 * @param qualifiers Qualifiers
4022 * @param expected_component Expected component of variable
4023 * @param expected_location Expected location
4024 * @param interface Interface of variable
4025 * @param n_array_elements Length of array
4026 * @param expected_stride_of_element Expected stride of element
4027 * @param offset Offset
4028 **/
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)4029 Variable::Descriptor::Descriptor(const GLchar* name, const GLchar* qualifiers, GLint expected_componenet,
4030 GLint expected_location, Interface* interface, GLuint n_array_elements,
4031 GLint expected_stride_of_element, GLuint offset)
4032 : m_expected_component(expected_componenet)
4033 , m_expected_location(expected_location)
4034 , m_expected_stride_of_element(expected_stride_of_element)
4035 , m_n_array_elements(n_array_elements)
4036 , m_name(name)
4037 , m_normalized(GL_FALSE)
4038 , m_offset(offset)
4039 , m_qualifiers(qualifiers)
4040 , m_type(INTERFACE)
4041 , m_interface(interface)
4042 {
4043 }
4044
4045 /** Get definition of variable
4046 *
4047 * @param flavour Flavour of variable
4048 * @param storage Storage used for variable
4049 *
4050 * @return code with defintion
4051 **/
GetDefinition(FLAVOUR flavour,STORAGE storage) const4052 std::string Variable::Descriptor::GetDefinition(FLAVOUR flavour, STORAGE storage) const
4053 {
4054 static const GLchar* basic_template = "QUALIFIERS STORAGETYPE NAMEARRAY;";
4055 static const GLchar* array_template = "QUALIFIERS STORAGETYPE NAME[]ARRAY;";
4056 const GLchar* storage_str = 0;
4057
4058 std::string definition;
4059 size_t position = 0;
4060
4061 /* Select definition template */
4062 switch (flavour)
4063 {
4064 case BASIC:
4065 definition = basic_template;
4066 break;
4067 case ARRAY:
4068 case INDEXED_BY_INVOCATION_ID:
4069 definition = array_template;
4070 break;
4071 default:
4072 TCU_FAIL("Invalid enum");
4073 }
4074
4075 if (BUILTIN != m_type)
4076 {
4077 if (0 == m_interface)
4078 {
4079 TCU_FAIL("Nullptr");
4080 }
4081 }
4082
4083 /* Qualifiers */
4084 if (true == m_qualifiers.empty())
4085 {
4086 replaceToken("QUALIFIERS ", position, "", definition);
4087 }
4088 else
4089 {
4090 replaceToken("QUALIFIERS", position, m_qualifiers.c_str(), definition);
4091 }
4092
4093 // According to spec: int, uint, and double type must always be declared with flat qualifier
4094 bool flat_qualifier = false;
4095 if (m_type != BUILTIN && m_interface != NULL)
4096 {
4097 if (m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Int ||
4098 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Uint ||
4099 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Double)
4100 {
4101 flat_qualifier = true;
4102 }
4103 }
4104 /* Storage */
4105 switch (storage)
4106 {
4107 case VARYING_INPUT:
4108 storage_str = flat_qualifier ? "flat in " : "in ";
4109 break;
4110 case VARYING_OUTPUT:
4111 storage_str = "out ";
4112 break;
4113 case UNIFORM:
4114 storage_str = "uniform ";
4115 break;
4116 case SSB:
4117 storage_str = "buffer ";
4118 break;
4119 case MEMBER:
4120 storage_str = "";
4121 break;
4122 default:
4123 TCU_FAIL("Invalid enum");
4124 }
4125
4126 replaceToken("STORAGE", position, storage_str, definition);
4127
4128 /* Type */
4129 if (BUILTIN == m_type)
4130 {
4131 replaceToken("TYPE", position, m_builtin.GetGLSLTypeName(), definition);
4132 }
4133 else
4134 {
4135 if (Interface::STRUCT == m_interface->m_type)
4136 {
4137 replaceToken("TYPE", position, m_interface->m_name.c_str(), definition);
4138 }
4139 else
4140 {
4141 const std::string& block_definition = m_interface->GetDefinition();
4142
4143 replaceToken("TYPE", position, block_definition.c_str(), definition);
4144 }
4145 }
4146
4147 /* Name */
4148 replaceToken("NAME", position, m_name.c_str(), definition);
4149
4150 /* Array size */
4151 if (0 == m_n_array_elements)
4152 {
4153 replaceToken("ARRAY", position, "", definition);
4154 }
4155 else
4156 {
4157 char buffer[16];
4158 sprintf(buffer, "[%d]", m_n_array_elements);
4159
4160 replaceToken("ARRAY", position, buffer, definition);
4161 }
4162
4163 /* Done */
4164 return definition;
4165 }
4166
4167 /** Get definitions for variables collected in vector
4168 *
4169 * @param vector Collection of variables
4170 * @param flavour Flavour of variables
4171 *
4172 * @return Code with definitions
4173 **/
GetDefinitions(const Variable::PtrVector & vector,Variable::FLAVOUR flavour)4174 std::string GetDefinitions(const Variable::PtrVector& vector, Variable::FLAVOUR flavour)
4175 {
4176 std::string list = Utils::g_list;
4177 size_t position = 0;
4178
4179 for (GLuint i = 0; i < vector.size(); ++i)
4180 {
4181 Utils::insertElementOfList(vector[i]->GetDefinition(flavour).c_str(), "\n", position, list);
4182 }
4183
4184 Utils::endList("", position, list);
4185
4186 return list;
4187 }
4188
4189 /** Get definitions for interfaces collected in vector
4190 *
4191 * @param vector Collection of interfaces
4192 *
4193 * @return Code with definitions
4194 **/
GetDefinitions(const Interface::PtrVector & vector)4195 std::string GetDefinitions(const Interface::PtrVector& vector)
4196 {
4197 std::string list = Utils::g_list;
4198 size_t position = 0;
4199
4200 for (GLuint i = 0; i < vector.size(); ++i)
4201 {
4202 Utils::insertElementOfList(vector[i]->GetDefinition().c_str(), "\n", position, list);
4203 }
4204
4205 Utils::endList("", position, list);
4206
4207 return list;
4208 }
4209
4210 /** Constructor
4211 *
4212 * @param name Name
4213 * @param type Type of interface
4214 **/
Interface(const GLchar * name,Interface::TYPE type)4215 Interface::Interface(const GLchar* name, Interface::TYPE type) : m_name(name), m_type(type)
4216 {
4217 }
4218
4219 /** Adds member to interface
4220 *
4221 * @param member Descriptor of new member
4222 *
4223 * @return Pointer to just created member
4224 **/
AddMember(const Variable::Descriptor & member)4225 Variable::Descriptor* Interface::AddMember(const Variable::Descriptor& member)
4226 {
4227 m_members.push_back(member);
4228
4229 return &m_members.back();
4230 }
4231
4232 /** Get definition of interface
4233 *
4234 * @param Code with definition
4235 **/
GetDefinition() const4236 std::string Interface::GetDefinition() const
4237 {
4238 std::string definition;
4239 size_t position = 0;
4240
4241 const GLchar* member_list = " MEMBER_DEFINITION\nMEMBER_LIST";
4242
4243 if (STRUCT == m_type)
4244 {
4245 definition = "struct NAME {\nMEMBER_LIST};";
4246 }
4247 else
4248 {
4249 definition = "NAME {\nMEMBER_LIST}";
4250 }
4251
4252 /* Name */
4253 replaceToken("NAME", position, m_name.c_str(), definition);
4254
4255 /* Member list */
4256 for (GLuint i = 0; i < m_members.size(); ++i)
4257 {
4258 const size_t start_position = position;
4259 const std::string& member_definition = m_members[i].GetDefinition(Variable::BASIC, Variable::MEMBER);
4260
4261 /* Member list */
4262 replaceToken("MEMBER_LIST", position, member_list, definition);
4263
4264 /* Move back position */
4265 position = start_position;
4266
4267 /* Member definition */
4268 replaceToken("MEMBER_DEFINITION", position, member_definition.c_str(), definition);
4269 }
4270
4271 /* Remove last member list */
4272 replaceToken("MEMBER_LIST", position, "", definition);
4273
4274 /* Done */
4275 return definition;
4276 }
4277
4278 /** Adds member of built-in type to interface
4279 *
4280 * @param name Name
4281 * @param qualifiers Qualifiers
4282 * @param expected_component Expected component of variable
4283 * @param expected_location Expected location
4284 * @param type Type
4285 * @param normalized Selects if data should be normalized
4286 * @param n_array_elements Length of array
4287 * @param expected_stride_of_element Expected stride of element
4288 * @param offset Offset
4289 *
4290 * @return Pointer to just created member
4291 **/
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)4292 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4293 GLint expected_location, const Type& type, GLboolean normalized,
4294 GLuint n_array_elements, GLint expected_stride_of_element, GLuint offset)
4295 {
4296 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, type, normalized,
4297 n_array_elements, expected_stride_of_element, offset));
4298 }
4299
4300 /** Adds member of interface type to interface
4301 *
4302 * @param name Name
4303 * @param qualifiers Qualifiers
4304 * @param expected_component Expected component of variable
4305 * @param expected_location Expected location
4306 * @param type Type
4307 * @param normalized Selects if data should be normalized
4308 * @param n_array_elements Length of array
4309 * @param expected_stride_of_element Expected stride of element
4310 * @param offset Offset
4311 *
4312 * @return Pointer to just created member
4313 **/
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)4314 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4315 GLint expected_location, Interface* nterface, GLuint n_array_elements,
4316 GLint expected_stride_of_element, GLuint offset)
4317 {
4318 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, nterface,
4319 n_array_elements, expected_stride_of_element, offset));
4320 }
4321
4322 /** Clears contents of vector of pointers
4323 *
4324 * @tparam T Type of elements
4325 *
4326 * @param vector Collection to be cleared
4327 **/
4328 template <typename T>
clearPtrVector(std::vector<T * > & vector)4329 void clearPtrVector(std::vector<T*>& vector)
4330 {
4331 for (size_t i = 0; i < vector.size(); ++i)
4332 {
4333 T* t = vector[i];
4334
4335 vector[i] = 0;
4336
4337 if (0 != t)
4338 {
4339 delete t;
4340 }
4341 }
4342
4343 vector.clear();
4344 }
4345
4346 /** Constructor
4347 *
4348 * @param stage Stage described by that interface
4349 **/
ShaderInterface(Shader::STAGES stage)4350 ShaderInterface::ShaderInterface(Shader::STAGES stage) : m_stage(stage)
4351 {
4352 /* Nothing to be done */
4353 }
4354
4355 /** Get definitions of globals
4356 *
4357 * @return Code with definitions
4358 **/
GetDefinitionsGlobals() const4359 std::string ShaderInterface::GetDefinitionsGlobals() const
4360 {
4361 return m_globals;
4362 }
4363
4364 /** Get definitions of inputs
4365 *
4366 * @return Code with definitions
4367 **/
GetDefinitionsInputs() const4368 std::string ShaderInterface::GetDefinitionsInputs() const
4369 {
4370 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::INPUT);
4371
4372 return GetDefinitions(m_inputs, flavour);
4373 }
4374
4375 /** Get definitions of outputs
4376 *
4377 * @return Code with definitions
4378 **/
GetDefinitionsOutputs() const4379 std::string ShaderInterface::GetDefinitionsOutputs() const
4380 {
4381 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::OUTPUT);
4382
4383 return GetDefinitions(m_outputs, flavour);
4384 }
4385
4386 /** Get definitions of buffers
4387 *
4388 * @return Code with definitions
4389 **/
GetDefinitionsSSBs() const4390 std::string ShaderInterface::GetDefinitionsSSBs() const
4391 {
4392 return GetDefinitions(m_ssb_blocks, Variable::BASIC);
4393 }
4394
4395 /** Get definitions of uniforms
4396 *
4397 * @return Code with definitions
4398 **/
GetDefinitionsUniforms() const4399 std::string ShaderInterface::GetDefinitionsUniforms() const
4400 {
4401 return GetDefinitions(m_uniforms, Variable::BASIC);
4402 }
4403
4404 /** Constructor
4405 *
4406 * @param in Input variable
4407 * @param out Output variable
4408 **/
VaryingConnection(Variable * in,Variable * out)4409 VaryingConnection::VaryingConnection(Variable* in, Variable* out) : m_in(in), m_out(out)
4410 {
4411 /* NBothing to be done here */
4412 }
4413
4414 /** Adds new varying connection to given stage
4415 *
4416 * @param stage Shader stage
4417 * @param in In varying
4418 * @param out Out varying
4419 **/
Add(Shader::STAGES stage,Variable * in,Variable * out)4420 void VaryingPassthrough::Add(Shader::STAGES stage, Variable* in, Variable* out)
4421 {
4422 VaryingConnection::Vector& vector = Get(stage);
4423
4424 vector.push_back(VaryingConnection(in, out));
4425 }
4426
4427 /** Get all passthrough connections for given stage
4428 *
4429 * @param stage Shader stage
4430 *
4431 * @return Vector of connections
4432 **/
Get(Shader::STAGES stage)4433 VaryingConnection::Vector& VaryingPassthrough::Get(Shader::STAGES stage)
4434 {
4435 VaryingConnection::Vector* result = 0;
4436
4437 switch (stage)
4438 {
4439 case Shader::FRAGMENT:
4440 result = &m_fragment;
4441 break;
4442 case Shader::GEOMETRY:
4443 result = &m_geometry;
4444 break;
4445 case Shader::TESS_CTRL:
4446 result = &m_tess_ctrl;
4447 break;
4448 case Shader::TESS_EVAL:
4449 result = &m_tess_eval;
4450 break;
4451 case Shader::VERTEX:
4452 result = &m_vertex;
4453 break;
4454 default:
4455 TCU_FAIL("Invalid enum");
4456 }
4457
4458 return *result;
4459 }
4460
4461 /** Constructor
4462 *
4463 **/
ProgramInterface()4464 ProgramInterface::ProgramInterface()
4465 : m_compute(Shader::COMPUTE)
4466 , m_vertex(Shader::VERTEX)
4467 , m_tess_ctrl(Shader::TESS_CTRL)
4468 , m_tess_eval(Shader::TESS_EVAL)
4469 , m_geometry(Shader::GEOMETRY)
4470 , m_fragment(Shader::FRAGMENT)
4471 {
4472 }
4473
4474 /** Destructor
4475 *
4476 **/
~ProgramInterface()4477 ProgramInterface::~ProgramInterface()
4478 {
4479 clearPtrVector(m_blocks);
4480 clearPtrVector(m_structures);
4481 }
4482
4483 /** Adds new interface
4484 *
4485 * @param name
4486 * @param type
4487 *
4488 * @return Pointer to created interface
4489 **/
AddInterface(const GLchar * name,Interface::TYPE type)4490 Interface* ProgramInterface::AddInterface(const GLchar* name, Interface::TYPE type)
4491 {
4492 Interface* interface = 0;
4493
4494 if (Interface::STRUCT == type)
4495 {
4496 interface = new Interface(name, type);
4497
4498 m_structures.push_back(interface);
4499 }
4500 else
4501 {
4502 interface = new Interface(name, type);
4503
4504 m_blocks.push_back(interface);
4505 }
4506
4507 return interface;
4508 }
4509
4510 /** Adds new block interface
4511 *
4512 * @param name
4513 *
4514 * @return Pointer to created interface
4515 **/
Block(const GLchar * name)4516 Interface* ProgramInterface::Block(const GLchar* name)
4517 {
4518 return AddInterface(name, Interface::BLOCK);
4519 }
4520
4521 /** Get interface of given shader stage
4522 *
4523 * @param stage Shader stage
4524 *
4525 * @return Reference to stage interface
4526 **/
GetShaderInterface(Shader::STAGES stage)4527 ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage)
4528 {
4529 ShaderInterface* interface = 0;
4530
4531 switch (stage)
4532 {
4533 case Shader::COMPUTE:
4534 interface = &m_compute;
4535 break;
4536 case Shader::FRAGMENT:
4537 interface = &m_fragment;
4538 break;
4539 case Shader::GEOMETRY:
4540 interface = &m_geometry;
4541 break;
4542 case Shader::TESS_CTRL:
4543 interface = &m_tess_ctrl;
4544 break;
4545 case Shader::TESS_EVAL:
4546 interface = &m_tess_eval;
4547 break;
4548 case Shader::VERTEX:
4549 interface = &m_vertex;
4550 break;
4551 default:
4552 TCU_FAIL("Invalid enum");
4553 }
4554
4555 return *interface;
4556 }
4557
4558 /** Get interface of given shader stage
4559 *
4560 * @param stage Shader stage
4561 *
4562 * @return Reference to stage interface
4563 **/
GetShaderInterface(Shader::STAGES stage) const4564 const ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage) const
4565 {
4566 const ShaderInterface* interface = 0;
4567
4568 switch (stage)
4569 {
4570 case Shader::COMPUTE:
4571 interface = &m_compute;
4572 break;
4573 case Shader::FRAGMENT:
4574 interface = &m_fragment;
4575 break;
4576 case Shader::GEOMETRY:
4577 interface = &m_geometry;
4578 break;
4579 case Shader::TESS_CTRL:
4580 interface = &m_tess_ctrl;
4581 break;
4582 case Shader::TESS_EVAL:
4583 interface = &m_tess_eval;
4584 break;
4585 case Shader::VERTEX:
4586 interface = &m_vertex;
4587 break;
4588 default:
4589 TCU_FAIL("Invalid enum");
4590 }
4591
4592 return *interface;
4593 }
4594
4595 /** Clone interface of Vertex shader stage to other stages
4596 * It creates matching inputs, outputs, uniforms and buffers in other stages.
4597 * There are no additional outputs for FRAGMENT shader generated.
4598 *
4599 * @param varying_passthrough Collection of varyings connections
4600 **/
CloneVertexInterface(VaryingPassthrough & varying_passthrough)4601 void ProgramInterface::CloneVertexInterface(VaryingPassthrough& varying_passthrough)
4602 {
4603 /* VS outputs >> TCS inputs >> TCS outputs >> .. >> FS inputs */
4604 for (size_t i = 0; i < m_vertex.m_outputs.size(); ++i)
4605 {
4606 const Variable& vs_var = *m_vertex.m_outputs[i];
4607 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4608
4609 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4610 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4611 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4612 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4613 }
4614
4615 /* Copy uniforms from VS to other stages */
4616 for (size_t i = 0; i < m_vertex.m_uniforms.size(); ++i)
4617 {
4618 Variable& vs_var = *m_vertex.m_uniforms[i];
4619 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4620
4621 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4622 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4623 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4624 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4625 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4626
4627 /* Uniform blocks needs unique binding */
4628 if (true == vs_var.IsBlock())
4629 {
4630 replaceBinding(vs_var, Shader::VERTEX);
4631 }
4632 }
4633
4634 /* Copy SSBs from VS to other stages */
4635 for (size_t i = 0; i < m_vertex.m_ssb_blocks.size(); ++i)
4636 {
4637 Variable& vs_var = *m_vertex.m_ssb_blocks[i];
4638 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4639
4640 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4641 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4642 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4643 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4644 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4645
4646 /* SSBs blocks needs unique binding */
4647 if (true == vs_var.IsBlock())
4648 {
4649 replaceBinding(vs_var, Shader::VERTEX);
4650 }
4651 }
4652
4653 m_compute.m_globals = m_vertex.m_globals;
4654 m_fragment.m_globals = m_vertex.m_globals;
4655 m_geometry.m_globals = m_vertex.m_globals;
4656 m_tess_ctrl.m_globals = m_vertex.m_globals;
4657 m_tess_eval.m_globals = m_vertex.m_globals;
4658 }
4659
4660 /** Clone variable for specific stage
4661 *
4662 * @param variable Variable
4663 * @param stage Requested stage
4664 * @param prefix Prefix used in variable name that is specific for original stage
4665 * @param varying_passthrough Collection of varyings connections
4666 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,const GLchar * prefix,VaryingPassthrough & varying_passthrough)4667 void ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage, const GLchar* prefix,
4668 VaryingPassthrough& varying_passthrough)
4669 {
4670 switch (variable.m_storage)
4671 {
4672 case Variable::VARYING_OUTPUT:
4673 {
4674 Variable* in = cloneVariableForStage(variable, stage, Variable::VARYING_INPUT, prefix);
4675
4676 if (Shader::FRAGMENT != stage)
4677 {
4678 Variable* out = cloneVariableForStage(variable, stage, Variable::VARYING_OUTPUT, prefix);
4679 varying_passthrough.Add(stage, in, out);
4680 }
4681 }
4682 break;
4683 case Variable::UNIFORM:
4684 case Variable::SSB:
4685 cloneVariableForStage(variable, stage, variable.m_storage, prefix);
4686 break;
4687 default:
4688 TCU_FAIL("Invalid enum");
4689 }
4690 }
4691
4692 /** Clone variable for specific stage
4693 *
4694 * @param variable Variable
4695 * @param stage Requested stage
4696 * @param storage Storage used by variable
4697 * @param prefix Prefix used in variable name that is specific for original stage
4698 *
4699 * @return New variable
4700 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4701 Variable* ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage,
4702 Variable::STORAGE storage, const GLchar* prefix)
4703 {
4704 /* Initialize with original variable */
4705 Variable* var = new Variable(variable);
4706 if (0 == var)
4707 {
4708 TCU_FAIL("Memory allocation");
4709 }
4710
4711 /* Set up storage */
4712 var->m_storage = storage;
4713
4714 /* Get name */
4715 std::string name = variable.m_descriptor.m_name;
4716
4717 /* Prefix name with stage ID, empty means default block */
4718 if (false == name.empty())
4719 {
4720 size_t position = 0;
4721 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4722 Utils::replaceToken(prefix, position, stage_prefix, name);
4723 }
4724 var->m_descriptor.m_name = name;
4725
4726 /* Clone block */
4727 const bool is_block = variable.IsBlock();
4728 if (true == is_block)
4729 {
4730 const Interface* interface = variable.m_descriptor.m_interface;
4731
4732 Interface* block = CloneBlockForStage(*interface, stage, storage, prefix);
4733
4734 var->m_descriptor.m_interface = block;
4735 }
4736
4737 /* Store variable */
4738 ShaderInterface& si = GetShaderInterface(stage);
4739 Variable* result = 0;
4740
4741 switch (storage)
4742 {
4743 case Variable::VARYING_INPUT:
4744 si.m_inputs.push_back(var);
4745 result = si.m_inputs.back();
4746 break;
4747 case Variable::VARYING_OUTPUT:
4748 si.m_outputs.push_back(var);
4749 result = si.m_outputs.back();
4750 break;
4751 case Variable::UNIFORM:
4752 /* Uniform blocks needs unique binding */
4753 if (true == is_block)
4754 {
4755 replaceBinding(*var, stage);
4756 }
4757
4758 si.m_uniforms.push_back(var);
4759 result = si.m_uniforms.back();
4760 break;
4761 case Variable::SSB:
4762 /* SSBs needs unique binding */
4763 if (true == is_block)
4764 {
4765 replaceBinding(*var, stage);
4766 }
4767
4768 si.m_ssb_blocks.push_back(var);
4769 result = si.m_ssb_blocks.back();
4770 break;
4771 default:
4772 TCU_FAIL("Invalid enum");
4773 }
4774
4775 return result;
4776 }
4777
4778 /** clone block to specific stage
4779 *
4780 * @param block Block to be copied
4781 * @param stage Specific stage
4782 * @param storage Storage used by block
4783 * @param prefix Prefix used in block name
4784 *
4785 * @return New interface
4786 **/
CloneBlockForStage(const Interface & block,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4787 Interface* ProgramInterface::CloneBlockForStage(const Interface& block, Shader::STAGES stage, Variable::STORAGE storage,
4788 const GLchar* prefix)
4789 {
4790 /* Get name */
4791 std::string name = block.m_name;
4792
4793 /* Prefix name with stage ID */
4794 size_t position = 0;
4795 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4796 Utils::replaceToken(prefix, position, stage_prefix, name);
4797
4798 Interface* ptr = GetBlock(name.c_str());
4799
4800 if (0 == ptr)
4801 {
4802 ptr = AddInterface(name.c_str(), Interface::BLOCK);
4803 }
4804
4805 ptr->m_members = block.m_members;
4806
4807 return ptr;
4808 }
4809
4810 /** Get stage specific prefix used in names
4811 *
4812 * @param stage Stage
4813 * @param storage Storage class
4814 *
4815 * @return String
4816 **/
GetStagePrefix(Shader::STAGES stage,Variable::STORAGE storage)4817 const GLchar* ProgramInterface::GetStagePrefix(Shader::STAGES stage, Variable::STORAGE storage)
4818 {
4819 static const GLchar* lut[Shader::STAGE_MAX][Variable::STORAGE_MAX] = {
4820 /* IN OUT UNIFORM SSB MEMBER */
4821 /* CS */ { 0, 0, "cs_uni_", "cs_buf_", "" },
4822 /* VS */ { "in_vs_", "vs_tcs_", "vs_uni_", "vs_buf_", "" },
4823 /* TCS */ { "vs_tcs_", "tcs_tes_", "tcs_uni_", "tcs_buf_", "" },
4824 /* TES */ { "tcs_tes_", "tes_gs_", "tes_uni_", "tes_buf_", "" },
4825 /* GS */ { "tes_gs_", "gs_fs_", "gs_uni_", "gs_buf_", "" },
4826 /* FS */ { "gs_fs_", "fs_out_", "fs_uni_", "fs_buf_", "" },
4827 };
4828
4829 const GLchar* result = 0;
4830
4831 result = lut[stage][storage];
4832
4833 return result;
4834 }
4835
4836 /** Get definitions of all structures used in program interface
4837 *
4838 * @return String with code
4839 **/
GetDefinitionsStructures() const4840 std::string ProgramInterface::GetDefinitionsStructures() const
4841 {
4842 return GetDefinitions(m_structures);
4843 }
4844
4845 /** Get interface code for stage
4846 *
4847 * @param stage Specific stage
4848 *
4849 * @return String with code
4850 **/
GetInterfaceForStage(Shader::STAGES stage) const4851 std::string ProgramInterface::GetInterfaceForStage(Shader::STAGES stage) const
4852 {
4853 size_t position = 0;
4854 std::string interface = "/* Globals */\n"
4855 "GLOBALS\n"
4856 "\n"
4857 "/* Structures */\n"
4858 "STRUCTURES\n"
4859 "\n"
4860 "/* Uniforms */\n"
4861 "UNIFORMS\n"
4862 "\n"
4863 "/* Inputs */\n"
4864 "INPUTS\n"
4865 "\n"
4866 "/* Outputs */\n"
4867 "OUTPUTS\n"
4868 "\n"
4869 "/* Storage */\n"
4870 "STORAGE\n";
4871
4872 const ShaderInterface& si = GetShaderInterface(stage);
4873
4874 const std::string& structures = GetDefinitionsStructures();
4875
4876 const std::string& globals = si.GetDefinitionsGlobals();
4877 const std::string& inputs = si.GetDefinitionsInputs();
4878 const std::string& outputs = si.GetDefinitionsOutputs();
4879 const std::string& uniforms = si.GetDefinitionsUniforms();
4880 const std::string& ssbs = si.GetDefinitionsSSBs();
4881
4882 replaceToken("GLOBALS", position, globals.c_str(), interface);
4883 replaceToken("STRUCTURES", position, structures.c_str(), interface);
4884 replaceToken("UNIFORMS", position, uniforms.c_str(), interface);
4885 replaceToken("INPUTS", position, inputs.c_str(), interface);
4886 replaceToken("OUTPUTS", position, outputs.c_str(), interface);
4887 replaceToken("STORAGE", position, ssbs.c_str(), interface);
4888
4889 return interface;
4890 }
4891
4892 /** Functional object used in find_if algorithm, in search for interface of given name
4893 *
4894 **/
4895 struct matchInterfaceName
4896 {
matchInterfaceNamegl4cts::EnhancedLayouts::Utils::matchInterfaceName4897 matchInterfaceName(const GLchar* name) : m_name(name)
4898 {
4899 }
4900
operator ()gl4cts::EnhancedLayouts::Utils::matchInterfaceName4901 bool operator()(const Interface* interface)
4902 {
4903 return 0 == interface->m_name.compare(m_name);
4904 }
4905
4906 const GLchar* m_name;
4907 };
4908
4909 /** Finds interface of given name in given vector of interfaces
4910 *
4911 * @param vector Collection of interfaces
4912 * @param name Requested name
4913 *
4914 * @return Pointer to interface if available, 0 otherwise
4915 **/
findInterfaceByName(Interface::PtrVector & vector,const GLchar * name)4916 static Interface* findInterfaceByName(Interface::PtrVector& vector, const GLchar* name)
4917 {
4918 Interface::PtrVector::iterator it = std::find_if(vector.begin(), vector.end(), matchInterfaceName(name));
4919
4920 if (vector.end() != it)
4921 {
4922 return *it;
4923 }
4924 else
4925 {
4926 return 0;
4927 }
4928 }
4929
4930 /** Search for block of given name
4931 *
4932 * @param name Name of block
4933 *
4934 * @return Pointer to block or 0
4935 **/
GetBlock(const GLchar * name)4936 Interface* ProgramInterface::GetBlock(const GLchar* name)
4937 {
4938 return findInterfaceByName(m_blocks, name);
4939 }
4940
4941 /** Search for structure of given name
4942 *
4943 * @param name Name of structure
4944 *
4945 * @return Pointer to structure or 0
4946 **/
GetStructure(const GLchar * name)4947 Interface* ProgramInterface::GetStructure(const GLchar* name)
4948 {
4949 return findInterfaceByName(m_structures, name);
4950 }
4951
4952 /** Adds new sturcture to interface
4953 *
4954 * @param name Name of structure
4955 *
4956 * @return Created structure
4957 **/
Structure(const GLchar * name)4958 Interface* ProgramInterface::Structure(const GLchar* name)
4959 {
4960 return AddInterface(name, Interface::STRUCT);
4961 }
4962
4963 /** Replace "BINDING" token in qualifiers string to value specific for given stage
4964 *
4965 * @param variable Variable to modify
4966 * @param stage Requested stage
4967 **/
replaceBinding(Variable & variable,Shader::STAGES stage)4968 void ProgramInterface::replaceBinding(Variable& variable, Shader::STAGES stage)
4969 {
4970 GLchar binding[16];
4971 sprintf(binding, "%d", stage);
4972 replaceAllTokens("BINDING", binding, variable.m_descriptor.m_qualifiers);
4973 }
4974 } /* Utils namespace */
4975
4976 /** Debuging procedure. Logs parameters.
4977 *
4978 * @param source As specified in GL spec.
4979 * @param type As specified in GL spec.
4980 * @param id As specified in GL spec.
4981 * @param severity As specified in GL spec.
4982 * @param ignored
4983 * @param message As specified in GL spec.
4984 * @param info Pointer to instance of Context used by test.
4985 */
debug_proc(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei,const GLchar * message,void * info)4986 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */,
4987 const GLchar* message, void* info)
4988 {
4989 deqp::Context* ctx = (deqp::Context*)info;
4990
4991 const GLchar* source_str = "Unknown";
4992 const GLchar* type_str = "Unknown";
4993 const GLchar* severity_str = "Unknown";
4994
4995 switch (source)
4996 {
4997 case GL_DEBUG_SOURCE_API:
4998 source_str = "API";
4999 break;
5000 case GL_DEBUG_SOURCE_APPLICATION:
5001 source_str = "APP";
5002 break;
5003 case GL_DEBUG_SOURCE_OTHER:
5004 source_str = "OTR";
5005 break;
5006 case GL_DEBUG_SOURCE_SHADER_COMPILER:
5007 source_str = "COM";
5008 break;
5009 case GL_DEBUG_SOURCE_THIRD_PARTY:
5010 source_str = "3RD";
5011 break;
5012 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
5013 source_str = "WS";
5014 break;
5015 default:
5016 break;
5017 }
5018
5019 switch (type)
5020 {
5021 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
5022 type_str = "DEPRECATED_BEHAVIOR";
5023 break;
5024 case GL_DEBUG_TYPE_ERROR:
5025 type_str = "ERROR";
5026 break;
5027 case GL_DEBUG_TYPE_MARKER:
5028 type_str = "MARKER";
5029 break;
5030 case GL_DEBUG_TYPE_OTHER:
5031 type_str = "OTHER";
5032 break;
5033 case GL_DEBUG_TYPE_PERFORMANCE:
5034 type_str = "PERFORMANCE";
5035 break;
5036 case GL_DEBUG_TYPE_POP_GROUP:
5037 type_str = "POP_GROUP";
5038 break;
5039 case GL_DEBUG_TYPE_PORTABILITY:
5040 type_str = "PORTABILITY";
5041 break;
5042 case GL_DEBUG_TYPE_PUSH_GROUP:
5043 type_str = "PUSH_GROUP";
5044 break;
5045 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
5046 type_str = "UNDEFINED_BEHAVIOR";
5047 break;
5048 default:
5049 break;
5050 }
5051
5052 switch (severity)
5053 {
5054 case GL_DEBUG_SEVERITY_HIGH:
5055 severity_str = "H";
5056 break;
5057 case GL_DEBUG_SEVERITY_LOW:
5058 severity_str = "L";
5059 break;
5060 case GL_DEBUG_SEVERITY_MEDIUM:
5061 severity_str = "M";
5062 break;
5063 case GL_DEBUG_SEVERITY_NOTIFICATION:
5064 severity_str = "N";
5065 break;
5066 default:
5067 break;
5068 }
5069
5070 ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|"
5071 << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id
5072 << ": " << message << tcu::TestLog::EndMessage;
5073 }
5074
5075 /** Constructor
5076 *
5077 * @param context Test context
5078 * @param test_name Test name
5079 * @param test_description Test description
5080 **/
TestBase(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)5081 TestBase::TestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5082 : TestCase(context, test_name, test_description)
5083 {
5084 /* Nothing to be done here */
5085 }
5086
5087 /** Execute test
5088 *
5089 * @return tcu::TestNode::STOP otherwise
5090 **/
iterate()5091 tcu::TestNode::IterateResult TestBase::iterate()
5092 {
5093 bool test_result;
5094
5095 #if DEBUG_ENBALE_MESSAGE_CALLBACK
5096 const Functions& gl = m_context.getRenderContext().getFunctions();
5097
5098 gl.debugMessageCallback(debug_proc, &m_context);
5099 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
5100 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
5101
5102 try
5103 {
5104 /* Execute test */
5105 test_result = test();
5106 }
5107 catch (std::exception& exc)
5108 {
5109 TCU_FAIL(exc.what());
5110 }
5111
5112 /* Set result */
5113 if (true == test_result)
5114 {
5115 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5116 }
5117 else
5118 {
5119 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5120 }
5121
5122 /* Done */
5123 return tcu::TestNode::STOP;
5124 }
5125
5126 /** Get last input location available for given type at specific stage
5127 *
5128 * @param stage Shader stage
5129 * @param type Input type
5130 * @param array_length Length of input array
5131 *
5132 * @return Last location index
5133 **/
getLastInputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_prev_stage)5134 GLint TestBase::getLastInputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_prev_stage)
5135 {
5136 GLint divide = 4; /* 4 components per location */
5137 GLint param = 0;
5138 GLenum pname = 0;
5139 GLint paramPrev = 0;
5140 GLenum pnamePrev = 0;
5141
5142 /* Select pnmae */
5143 switch (stage)
5144 {
5145 case Utils::Shader::FRAGMENT:
5146 pname = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5147 pnamePrev = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5148 break;
5149 case Utils::Shader::GEOMETRY:
5150 pname = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5151 pnamePrev = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5152 break;
5153 case Utils::Shader::TESS_CTRL:
5154 pname = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5155 pnamePrev = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5156 break;
5157 case Utils::Shader::TESS_EVAL:
5158 pname = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5159 pnamePrev = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5160 break;
5161 case Utils::Shader::VERTEX:
5162 pname = GL_MAX_VERTEX_ATTRIBS;
5163 divide = 1;
5164 break;
5165 default:
5166 TCU_FAIL("Invalid enum");
5167 }
5168
5169 /* Zero means no array, but 1 slot is required */
5170 if (0 == array_length)
5171 {
5172 array_length += 1;
5173 }
5174
5175 /* Get MAX */
5176 const Functions& gl = m_context.getRenderContext().getFunctions();
5177
5178 gl.getIntegerv(pname, ¶m);
5179 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5180
5181 if (pnamePrev && !ignore_prev_stage) {
5182 gl.getIntegerv(pnamePrev, ¶mPrev);
5183 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5184
5185 /* Don't read from a location that doesn't exist in the previous stage */
5186 param = de::min(param, paramPrev);
5187 }
5188
5189 /* Calculate */
5190 #if WRKARD_VARYINGLOCATIONSTEST
5191
5192 const GLint n_avl_locations = 16;
5193
5194 #else
5195
5196 const GLint n_avl_locations = param / divide;
5197
5198 #endif
5199
5200 const GLuint n_req_location = type.GetLocations(stage == Utils::Shader::VERTEX) * array_length;
5201
5202 return n_avl_locations - n_req_location; /* last is max - 1 */
5203 }
5204
5205 /** Get last output location available for given type at specific stage
5206 *
5207 * @param stage Shader stage
5208 * @param type Input type
5209 * @param array_length Length of input array
5210 *
5211 * @return Last location index
5212 **/
getLastOutputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_next_stage)5213 GLint TestBase::getLastOutputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_next_stage)
5214 {
5215 GLint param = 0;
5216 GLenum pname = 0;
5217 GLint paramNext = 0;
5218 GLenum pnameNext = 0;
5219
5220 /* Select pname */
5221 switch (stage)
5222 {
5223 case Utils::Shader::GEOMETRY:
5224 pname = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5225 pnameNext = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5226 break;
5227 case Utils::Shader::TESS_CTRL:
5228 pname = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5229 pnameNext = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5230 break;
5231 case Utils::Shader::TESS_EVAL:
5232 pname = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5233 pnameNext = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5234 break;
5235 case Utils::Shader::VERTEX:
5236 pname = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5237 pnameNext = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5238 break;
5239 default:
5240 TCU_FAIL("Invalid enum");
5241 }
5242
5243 /* Zero means no array, but 1 slot is required */
5244 if (0 == array_length)
5245 {
5246 array_length += 1;
5247 }
5248
5249 /* Get MAX */
5250 const Functions& gl = m_context.getRenderContext().getFunctions();
5251
5252 gl.getIntegerv(pname, ¶m);
5253 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5254
5255 /* Calculate */
5256 #if WRKARD_VARYINGLOCATIONSTEST
5257
5258 const GLint n_avl_locations = 16;
5259
5260 #else
5261
5262 /* Don't write to a location that doesn't exist in the next stage */
5263 if (!ignore_next_stage)
5264 {
5265 gl.getIntegerv(pnameNext, ¶mNext);
5266 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5267
5268 param = de::min(param, paramNext);
5269 }
5270
5271 const GLint n_avl_locations = param / 4; /* 4 components per location */
5272
5273 #endif
5274
5275 const GLuint n_req_location = type.GetLocations() * array_length;
5276
5277 return n_avl_locations - n_req_location; /* last is max - 1 */
5278 }
5279
5280 /** Basic implementation
5281 *
5282 * @param ignored
5283 *
5284 * @return Empty string
5285 **/
getTestCaseName(GLuint)5286 std::string TestBase::getTestCaseName(GLuint /* test_case_index */)
5287 {
5288 std::string result;
5289
5290 return result;
5291 }
5292
5293 /** Basic implementation
5294 *
5295 * @return 1
5296 **/
getTestCaseNumber()5297 GLuint TestBase::getTestCaseNumber()
5298 {
5299 return 1;
5300 }
5301
5302 /** Check if flat qualifier is required for given type, stage and storage
5303 *
5304 * @param stage Shader stage
5305 * @param type Input type
5306 * @param storage Storage of variable
5307 *
5308 * @return Last location index
5309 **/
isFlatRequired(Utils::Shader::STAGES stage,const Utils::Type & type,Utils::Variable::STORAGE storage,const bool coherent) const5310 bool TestBase::isFlatRequired(Utils::Shader::STAGES stage, const Utils::Type& type, Utils::Variable::STORAGE storage,
5311 const bool coherent) const
5312 {
5313 /* Float types do not need flat at all */
5314 if (Utils::Type::Float == type.m_basic_type)
5315 {
5316 return false;
5317 }
5318
5319 /* Inputs to fragment shader */
5320 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Variable::VARYING_INPUT == storage))
5321 {
5322 return true;
5323 }
5324
5325 /* Outputs from geometry shader
5326 *
5327 * This is not strictly needed since fragment shader input
5328 * interpolation qualifiers will override whatever comes from the
5329 * previous stage. However, if we want to have a coherent
5330 * interface, let's better do it.
5331 */
5332 if ((Utils::Shader::GEOMETRY == stage) && (Utils::Variable::VARYING_OUTPUT == storage) && coherent)
5333 {
5334 return true;
5335 }
5336
5337 return false;
5338 }
5339
5340 /** Basic implementation of testInit method
5341 *
5342 **/
testInit()5343 void TestBase::testInit()
5344 {
5345 }
5346
5347 /** Calculate stride for interface
5348 *
5349 * @param interface Interface
5350 *
5351 * @return Calculated value
5352 **/
calculateStride(const Utils::Interface & interface) const5353 GLuint TestBase::calculateStride(const Utils::Interface& interface) const
5354 {
5355 const size_t n_members = interface.m_members.size();
5356
5357 GLuint stride = 0;
5358
5359 for (size_t i = 0; i < n_members; ++i)
5360 {
5361 const Utils::Variable::Descriptor& member = interface.m_members[i];
5362 const GLuint member_offset = member.m_offset;
5363 const GLuint member_stride = member.m_expected_stride_of_element;
5364 const GLuint member_ends_at = member_offset + member_stride;
5365
5366 stride = std::max(stride, member_ends_at);
5367 }
5368
5369 return stride;
5370 }
5371
5372 /** Generate data for interface. This routine is recursive
5373 *
5374 * @param interface Interface
5375 * @param offset Offset in out_data
5376 * @param out_data Buffer to be filled
5377 **/
generateData(const Utils::Interface & interface,GLuint offset,std::vector<GLubyte> & out_data) const5378 void TestBase::generateData(const Utils::Interface& interface, GLuint offset, std::vector<GLubyte>& out_data) const
5379 {
5380 const size_t n_members = interface.m_members.size();
5381 GLubyte* ptr = &out_data[offset];
5382
5383 for (size_t i = 0; i < n_members; ++i)
5384 {
5385 const Utils::Variable::Descriptor& member = interface.m_members[i];
5386 const GLuint member_offset = member.m_offset;
5387 const GLuint n_elements = (0 == member.m_n_array_elements) ? 1 : member.m_n_array_elements;
5388
5389 for (GLuint element = 0; element < n_elements; ++element)
5390 {
5391 const GLuint element_offset = element * member.m_expected_stride_of_element;
5392 const GLuint data_offfset = member_offset + element_offset;
5393
5394 if (Utils::Variable::BUILTIN == member.m_type)
5395 {
5396 const std::vector<GLubyte>& data = member.m_builtin.GenerateData();
5397
5398 memcpy(ptr + data_offfset, &data[0], data.size());
5399 }
5400 else
5401 {
5402 generateData(*member.m_interface, offset + data_offfset, out_data);
5403 }
5404 }
5405 }
5406 }
5407
5408 /** Get type at index
5409 *
5410 * @param index Index of requested type
5411 *
5412 * @return Type
5413 **/
getType(GLuint index) const5414 Utils::Type TestBase::getType(GLuint index) const
5415 {
5416 Utils::Type type;
5417
5418 switch (index)
5419 {
5420 case 0:
5421 type = Utils::Type::_double;
5422 break;
5423 case 1:
5424 type = Utils::Type::dmat2;
5425 break;
5426 case 2:
5427 type = Utils::Type::dmat2x3;
5428 break;
5429 case 3:
5430 type = Utils::Type::dmat2x4;
5431 break;
5432 case 4:
5433 type = Utils::Type::dmat3;
5434 break;
5435 case 5:
5436 type = Utils::Type::dmat3x2;
5437 break;
5438 case 6:
5439 type = Utils::Type::dmat3x4;
5440 break;
5441 case 7:
5442 type = Utils::Type::dmat4;
5443 break;
5444 case 8:
5445 type = Utils::Type::dmat4x2;
5446 break;
5447 case 9:
5448 type = Utils::Type::dmat4x3;
5449 break;
5450 case 10:
5451 type = Utils::Type::dvec2;
5452 break;
5453 case 11:
5454 type = Utils::Type::dvec3;
5455 break;
5456 case 12:
5457 type = Utils::Type::dvec4;
5458 break;
5459 case 13:
5460 type = Utils::Type::_float;
5461 break;
5462 case 14:
5463 type = Utils::Type::mat2;
5464 break;
5465 case 15:
5466 type = Utils::Type::mat2x3;
5467 break;
5468 case 16:
5469 type = Utils::Type::mat2x4;
5470 break;
5471 case 17:
5472 type = Utils::Type::mat3;
5473 break;
5474 case 18:
5475 type = Utils::Type::mat3x2;
5476 break;
5477 case 19:
5478 type = Utils::Type::mat3x4;
5479 break;
5480 case 20:
5481 type = Utils::Type::mat4;
5482 break;
5483 case 21:
5484 type = Utils::Type::mat4x2;
5485 break;
5486 case 22:
5487 type = Utils::Type::mat4x3;
5488 break;
5489 case 23:
5490 type = Utils::Type::vec2;
5491 break;
5492 case 24:
5493 type = Utils::Type::vec3;
5494 break;
5495 case 25:
5496 type = Utils::Type::vec4;
5497 break;
5498 case 26:
5499 type = Utils::Type::_int;
5500 break;
5501 case 27:
5502 type = Utils::Type::ivec2;
5503 break;
5504 case 28:
5505 type = Utils::Type::ivec3;
5506 break;
5507 case 29:
5508 type = Utils::Type::ivec4;
5509 break;
5510 case 30:
5511 type = Utils::Type::uint;
5512 break;
5513 case 31:
5514 type = Utils::Type::uvec2;
5515 break;
5516 case 32:
5517 type = Utils::Type::uvec3;
5518 break;
5519 case 33:
5520 type = Utils::Type::uvec4;
5521 break;
5522 default:
5523 TCU_FAIL("invalid enum");
5524 }
5525
5526 return type;
5527 }
5528
5529 /** Get name of type at index
5530 *
5531 * @param index Index of type
5532 *
5533 * @return Name
5534 **/
getTypeName(GLuint index) const5535 std::string TestBase::getTypeName(GLuint index) const
5536 {
5537 std::string name = getType(index).GetGLSLTypeName();
5538
5539 return name;
5540 }
5541
5542 /** Get number of types
5543 *
5544 * @return 34
5545 **/
getTypesNumber() const5546 glw::GLuint TestBase::getTypesNumber() const
5547 {
5548 return 34;
5549 }
5550
5551 /** Execute test
5552 *
5553 * @return true if test pass, false otherwise
5554 **/
test()5555 bool TestBase::test()
5556 {
5557 bool result = true;
5558 GLuint n_test_cases = 0;
5559
5560 /* Prepare test */
5561 testInit();
5562
5563 /* GL entry points */
5564 const Functions& gl = m_context.getRenderContext().getFunctions();
5565
5566 /* Tessellation patch set up */
5567 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5568 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5569
5570 /* Get number of test cases */
5571 n_test_cases = getTestCaseNumber();
5572
5573 #if DEBUG_REPEAT_TEST_CASE
5574
5575 while (1)
5576 {
5577 GLuint test_case = DEBUG_REPEATED_TEST_CASE;
5578
5579 #else /* DEBUG_REPEAT_TEST_CASE */
5580
5581 for (GLuint test_case = 0; test_case < n_test_cases; ++test_case)
5582 {
5583 #endif /* DEBUG_REPEAT_TEST_CASE */
5584
5585 /* Execute case */
5586 if (!testCase(test_case))
5587 {
5588 const std::string& test_case_name = getTestCaseName(test_case);
5589
5590 if (false == test_case_name.empty())
5591 {
5592 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case_name
5593 << ") failed." << tcu::TestLog::EndMessage;
5594 }
5595 else
5596 {
5597 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case
5598 << ") failed." << tcu::TestLog::EndMessage;
5599 }
5600
5601 result = false;
5602 }
5603 }
5604
5605 /* Done */
5606 return result;
5607 }
5608
5609 /* Constants used by BufferTestBase */
5610 const GLuint BufferTestBase::bufferDescriptor::m_non_indexed = -1;
5611
5612 /** Constructor
5613 *
5614 * @param context Test context
5615 * @param test_name Name of test
5616 * @param test_description Description of test
5617 **/
5618 BufferTestBase::BufferTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5619 : TestBase(context, test_name, test_description)
5620 {
5621 }
5622
5623 /** Execute drawArrays for single vertex
5624 *
5625 * @param ignored
5626 *
5627 * @return true
5628 **/
5629 bool BufferTestBase::executeDrawCall(bool tesEnabled, GLuint /* test_case_index */)
5630 {
5631 const Functions& gl = m_context.getRenderContext().getFunctions();
5632
5633 gl.disable(GL_RASTERIZER_DISCARD);
5634 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
5635
5636 gl.beginTransformFeedback(GL_POINTS);
5637 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5638
5639 // Only TES is existed, glDrawArray can use the parameter GL_PATCHES
5640 if (tesEnabled == false)
5641 {
5642 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5643 }
5644 else
5645 {
5646 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5647 }
5648
5649 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5650
5651 gl.endTransformFeedback();
5652 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5653
5654 return true;
5655 }
5656
5657 /** Get descriptors of buffers necessary for test
5658 *
5659 * @param ignored
5660 * @param ignored
5661 **/
5662 void BufferTestBase::getBufferDescriptors(glw::GLuint /* test_case_index */,
5663 bufferDescriptor::Vector& /* out_descriptors */)
5664 {
5665 /* Nothhing to be done */
5666 }
5667
5668 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
5669 *
5670 * @param ignored
5671 * @param ignored
5672 **/
5673 void BufferTestBase::getCapturedVaryings(glw::GLuint /* test_case_index */,
5674 Utils::Program::NameVector& /* captured_varyings */,
5675 GLint* /* xfb_components */)
5676 {
5677 /* Nothing to be done */
5678 }
5679
5680 /** Get body of main function for given shader stage
5681 *
5682 * @param ignored
5683 * @param ignored
5684 * @param out_assignments Set to empty
5685 * @param out_calculations Set to empty
5686 **/
5687 void BufferTestBase::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5688 std::string& out_assignments, std::string& out_calculations)
5689 {
5690 out_assignments = "";
5691 out_calculations = "";
5692 }
5693
5694 /** Get interface of shader
5695 *
5696 * @param ignored
5697 * @param ignored
5698 * @param out_interface Set to ""
5699 **/
5700 void BufferTestBase::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5701 std::string& out_interface)
5702 {
5703 out_interface = "";
5704 }
5705
5706 /** Get source code of shader
5707 *
5708 * @param test_case_index Index of test case
5709 * @param stage Shader stage
5710 *
5711 * @return Source
5712 **/
5713 std::string BufferTestBase::getShaderSource(glw::GLuint test_case_index, Utils::Shader::STAGES stage)
5714 {
5715 std::string assignments;
5716 std::string calculations;
5717 std::string interface;
5718
5719 /* */
5720 getShaderBody(test_case_index, stage, assignments, calculations);
5721 getShaderInterface(test_case_index, stage, interface);
5722
5723 /* */
5724 std::string source = getShaderTemplate(stage);
5725
5726 /* */
5727 size_t position = 0;
5728 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
5729 Utils::replaceToken("CALCULATIONS", position, calculations.c_str(), source);
5730 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
5731
5732 /* */
5733 return source;
5734 }
5735
5736 /** Inspects program to check if all resources are as expected
5737 *
5738 * @param ignored
5739 * @param ignored
5740 * @param ignored
5741 *
5742 * @return true
5743 **/
5744 bool BufferTestBase::inspectProgram(GLuint /* test_case_index */, Utils::Program& /* program */,
5745 std::stringstream& /* out_stream */)
5746 {
5747 return true;
5748 }
5749
5750 /** Runs test case
5751 *
5752 * @param test_case_index Id of test case
5753 *
5754 * @return true if test case pass, false otherwise
5755 **/
5756 bool BufferTestBase::testCase(GLuint test_case_index)
5757 {
5758 try
5759 {
5760 bufferCollection buffers;
5761 Utils::Program::NameVector captured_varyings;
5762 bufferDescriptor::Vector descriptors;
5763 Utils::Program program(m_context);
5764 Utils::VertexArray vao(m_context);
5765
5766 /* Get captured varyings */
5767 GLint xfb_components;
5768 getCapturedVaryings(test_case_index, captured_varyings, &xfb_components);
5769
5770 /* Don't generate shaders that try to capture more XFB components than the implementation's limit */
5771 if (captured_varyings.size() > 0)
5772 {
5773 const Functions& gl = m_context.getRenderContext().getFunctions();
5774
5775 GLint max_xfb_components;
5776 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_components);
5777 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5778
5779 if (xfb_components > max_xfb_components)
5780 return true;
5781 }
5782
5783 /* Get shader sources */
5784 const std::string& fragment_shader = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
5785 const std::string& geometry_shader = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
5786 const std::string& tess_ctrl_shader = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
5787 const std::string& tess_eval_shader = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
5788 const std::string& vertex_shader = getShaderSource(test_case_index, Utils::Shader::VERTEX);
5789
5790 /* Set up program */
5791 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
5792 vertex_shader, captured_varyings, true, false /* is_separable */);
5793
5794 /* Inspection */
5795 {
5796 std::stringstream stream;
5797 if (false == inspectProgram(test_case_index, program, stream))
5798 {
5799 m_context.getTestContext().getLog()
5800 << tcu::TestLog::Message
5801 << "Program inspection failed. Test case: " << getTestCaseName(test_case_index)
5802 << ". Reason: " << stream.str() << tcu::TestLog::EndMessage
5803 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5804 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5805 << tcu::TestLog::KernelSource(fragment_shader);
5806
5807 return false;
5808 }
5809 }
5810
5811 program.Use();
5812
5813 /* Set up buffers */
5814 getBufferDescriptors(test_case_index, descriptors);
5815 cleanBuffers();
5816 prepareBuffers(descriptors, buffers);
5817
5818 /* Set up vao */
5819 vao.Init();
5820 vao.Bind();
5821
5822 /* Draw */
5823 bool result = executeDrawCall((program.m_tess_eval.m_id != 0), test_case_index);
5824
5825 #if USE_NSIGHT
5826 m_context.getRenderContext().postIterate();
5827 #endif
5828
5829 if (false == result)
5830 {
5831 m_context.getTestContext().getLog()
5832 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5833 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5834 << tcu::TestLog::KernelSource(fragment_shader);
5835
5836 return false;
5837 }
5838
5839 /* Verify result */
5840 if (false == verifyBuffers(buffers))
5841 {
5842 m_context.getTestContext().getLog()
5843 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5844 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5845 << tcu::TestLog::KernelSource(fragment_shader);
5846
5847 return false;
5848 }
5849 }
5850 catch (Utils::Shader::InvalidSourceException& exc)
5851 {
5852 exc.log(m_context);
5853 TCU_FAIL(exc.what());
5854 }
5855 catch (Utils::Program::BuildException& exc)
5856 {
5857 exc.log(m_context);
5858 TCU_FAIL(exc.what());
5859 }
5860
5861 /* Done */
5862 return true;
5863 }
5864
5865 /** Verify contents of buffers
5866 *
5867 * @param buffers Collection of buffers to be verified
5868 *
5869 * @return true if everything is as expected, false otherwise
5870 **/
5871 bool BufferTestBase::verifyBuffers(bufferCollection& buffers)
5872 {
5873 bool result = true;
5874
5875 for (bufferCollection::Vector::iterator it = buffers.m_vector.begin(), end = buffers.m_vector.end(); end != it;
5876 ++it)
5877 {
5878 bufferCollection::pair& pair = *it;
5879 Utils::Buffer* buffer = pair.m_buffer;
5880 bufferDescriptor* descriptor = pair.m_descriptor;
5881 size_t size = descriptor->m_expected_data.size();
5882
5883 /* Skip buffers that have no expected data */
5884 if (0 == size)
5885 {
5886 continue;
5887 }
5888
5889 /* Get pointer to contents of buffer */
5890 buffer->Bind();
5891 GLvoid* buffer_data = buffer->Map(Utils::Buffer::ReadOnly);
5892
5893 /* Get pointer to expected data */
5894 GLvoid* expected_data = &descriptor->m_expected_data[0];
5895
5896 /* Compare */
5897 int res = memcmp(buffer_data, expected_data, size);
5898
5899 if (0 != res)
5900 {
5901 m_context.getTestContext().getLog()
5902 << tcu::TestLog::Message
5903 << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
5904 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
5905
5906 result = false;
5907 }
5908
5909 /* Release buffer mapping */
5910 buffer->UnMap();
5911 }
5912
5913 return result;
5914 }
5915
5916 /** Unbinds all uniforms and xfb
5917 *
5918 **/
5919 void BufferTestBase::cleanBuffers()
5920 {
5921 const Functions& gl = m_context.getRenderContext().getFunctions();
5922
5923 GLint max_uni = 0;
5924 GLint max_xfb = 0;
5925
5926 gl.getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uni);
5927 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
5928 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5929
5930 for (GLint i = 0; i < max_uni; ++i)
5931 {
5932 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Uniform, i);
5933 }
5934
5935 for (GLint i = 0; i < max_xfb; ++i)
5936 {
5937 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Transform_feedback, i);
5938 }
5939 }
5940
5941 /** Get template of shader for given stage
5942 *
5943 * @param stage Stage
5944 *
5945 * @return Template of shader source
5946 **/
5947 std::string BufferTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
5948 {
5949 static const GLchar* compute_shader_template = "#version 430 core\n"
5950 "#extension GL_ARB_enhanced_layouts : require\n"
5951 "\n"
5952 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
5953 "\n"
5954 "writeonly uniform uimage2D uni_image;\n"
5955 "\n"
5956 "INTERFACE"
5957 "\n"
5958 "void main()\n"
5959 "{\n"
5960 "CALCULATIONS"
5961 "\n"
5962 "ASSIGNMENTS"
5963 "}\n"
5964 "\n";
5965
5966 static const GLchar* fragment_shader_template = "#version 430 core\n"
5967 "#extension GL_ARB_enhanced_layouts : require\n"
5968 "\n"
5969 "INTERFACE"
5970 "\n"
5971 "void main()\n"
5972 "{\n"
5973 "CALCULATIONS"
5974 "\n"
5975 "ASSIGNMENTS"
5976 "}\n"
5977 "\n";
5978
5979 // max_vertices is set to 3 for the test case "xfb_vertex_streams" declares 3 streams in geometry shader,
5980 // according to spec, max_vertices should be no less than 3 if there are 3 streams in GS.
5981 static const GLchar* geometry_shader_template = "#version 430 core\n"
5982 "#extension GL_ARB_enhanced_layouts : require\n"
5983 "\n"
5984 "layout(points) in;\n"
5985 "layout(points, max_vertices = 3) out;\n"
5986 "\n"
5987 "INTERFACE"
5988 "\n"
5989 "void main()\n"
5990 "{\n"
5991 "CALCULATIONS"
5992 "\n"
5993 "\n"
5994 "ASSIGNMENTS"
5995 " gl_Position = vec4(0, 0, 0, 1);\n"
5996 " EmitVertex();\n"
5997 "}\n"
5998 "\n";
5999
6000 static const GLchar* tess_ctrl_shader_template = "#version 430 core\n"
6001 "#extension GL_ARB_enhanced_layouts : require\n"
6002 "\n"
6003 "layout(vertices = 1) out;\n"
6004 "\n"
6005 "INTERFACE"
6006 "\n"
6007 "void main()\n"
6008 "{\n"
6009 "CALCULATIONS"
6010 "\n"
6011 "ASSIGNMENTS"
6012 "\n"
6013 " gl_TessLevelOuter[0] = 1.0;\n"
6014 " gl_TessLevelOuter[1] = 1.0;\n"
6015 " gl_TessLevelOuter[2] = 1.0;\n"
6016 " gl_TessLevelOuter[3] = 1.0;\n"
6017 " gl_TessLevelInner[0] = 1.0;\n"
6018 " gl_TessLevelInner[1] = 1.0;\n"
6019 "}\n"
6020 "\n";
6021
6022 static const GLchar* tess_eval_shader_template = "#version 430 core\n"
6023 "#extension GL_ARB_enhanced_layouts : require\n"
6024 "\n"
6025 "layout(isolines, point_mode) in;\n"
6026 "\n"
6027 "INTERFACE"
6028 "\n"
6029 "void main()\n"
6030 "{\n"
6031 "CALCULATIONS"
6032 "\n"
6033 "ASSIGNMENTS"
6034 "}\n"
6035 "\n";
6036
6037 static const GLchar* vertex_shader_template = "#version 430 core\n"
6038 "#extension GL_ARB_enhanced_layouts : require\n"
6039 "\n"
6040 "INTERFACE"
6041 "\n"
6042 "void main()\n"
6043 "{\n"
6044 "CALCULATIONS"
6045 "\n"
6046 "ASSIGNMENTS"
6047 "}\n"
6048 "\n";
6049
6050 const GLchar* result = 0;
6051
6052 switch (stage)
6053 {
6054 case Utils::Shader::COMPUTE:
6055 result = compute_shader_template;
6056 break;
6057 case Utils::Shader::FRAGMENT:
6058 result = fragment_shader_template;
6059 break;
6060 case Utils::Shader::GEOMETRY:
6061 result = geometry_shader_template;
6062 break;
6063 case Utils::Shader::TESS_CTRL:
6064 result = tess_ctrl_shader_template;
6065 break;
6066 case Utils::Shader::TESS_EVAL:
6067 result = tess_eval_shader_template;
6068 break;
6069 case Utils::Shader::VERTEX:
6070 result = vertex_shader_template;
6071 break;
6072 default:
6073 TCU_FAIL("Invalid enum");
6074 }
6075
6076 return result;
6077 }
6078
6079 /** Prepare buffer according to descriptor
6080 *
6081 * @param buffer Buffer to prepare
6082 * @param desc Descriptor
6083 **/
6084 void BufferTestBase::prepareBuffer(Utils::Buffer& buffer, bufferDescriptor& desc)
6085 {
6086 GLsizeiptr size = 0;
6087 GLvoid* data = 0;
6088
6089 if (false == desc.m_initial_data.empty())
6090 {
6091 size = desc.m_initial_data.size();
6092 data = &desc.m_initial_data[0];
6093 }
6094 else if (false == desc.m_expected_data.empty())
6095 {
6096 size = desc.m_expected_data.size();
6097 }
6098
6099 buffer.Init(desc.m_target, Utils::Buffer::StaticDraw, size, data);
6100
6101 if (bufferDescriptor::m_non_indexed != desc.m_index)
6102 {
6103 buffer.BindBase(desc.m_index);
6104 }
6105 else
6106 {
6107 buffer.Bind();
6108 }
6109 }
6110
6111 /** Prepare collection of buffer
6112 *
6113 * @param descriptors Collection of descriptors
6114 * @param out_buffers Collection of buffers
6115 **/
6116 void BufferTestBase::prepareBuffers(bufferDescriptor::Vector& descriptors, bufferCollection& out_buffers)
6117 {
6118 for (bufferDescriptor::Vector::iterator it = descriptors.begin(), end = descriptors.end(); end != it; ++it)
6119 {
6120 bufferCollection::pair pair;
6121
6122 pair.m_buffer = new Utils::Buffer(m_context);
6123 if (0 == pair.m_buffer)
6124 {
6125 TCU_FAIL("Memory allocation failed");
6126 }
6127
6128 pair.m_descriptor = &(*it);
6129
6130 prepareBuffer(*pair.m_buffer, *pair.m_descriptor);
6131
6132 out_buffers.m_vector.push_back(pair);
6133 }
6134 }
6135
6136 /** Destructor
6137 *
6138 **/
6139 BufferTestBase::bufferCollection::~bufferCollection()
6140 {
6141 for (Vector::iterator it = m_vector.begin(), end = m_vector.end(); end != it; ++it)
6142 {
6143 if (0 != it->m_buffer)
6144 {
6145 delete it->m_buffer;
6146 it->m_buffer = 0;
6147 }
6148 }
6149 }
6150
6151 /** Constructor
6152 *
6153 * @param context Test context
6154 * @param test_name Name of test
6155 * @param test_description Description of test
6156 **/
6157 NegativeTestBase::NegativeTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6158 : TestBase(context, test_name, test_description)
6159 {
6160 }
6161
6162 /** Selects if "compute" stage is relevant for test
6163 *
6164 * @param ignored
6165 *
6166 * @return true
6167 **/
6168 bool NegativeTestBase::isComputeRelevant(GLuint /* test_case_index */)
6169 {
6170 return true;
6171 }
6172
6173 /** Selects if compilation failure is expected result
6174 *
6175 * @param ignored
6176 *
6177 * @return true
6178 **/
6179 bool NegativeTestBase::isFailureExpected(GLuint /* test_case_index */)
6180 {
6181 return true;
6182 }
6183
6184 /** Selects if the test case should use a separable program
6185 *
6186 * @param ignored
6187 *
6188 * @return false
6189 **/
6190 bool NegativeTestBase::isSeparable(const GLuint /* test_case_index */)
6191 {
6192 return false;
6193 }
6194
6195 /** Runs test case
6196 *
6197 * @param test_case_index Id of test case
6198 *
6199 * @return true if test case pass, false otherwise
6200 **/
6201 bool NegativeTestBase::testCase(GLuint test_case_index)
6202 {
6203 bool test_case_result = true;
6204
6205 /* Compute */
6206 if (true == isComputeRelevant(test_case_index))
6207 {
6208 const std::string& cs_source = getShaderSource(test_case_index, Utils::Shader::COMPUTE);
6209 bool is_build_error = false;
6210 const bool is_failure_expected = isFailureExpected(test_case_index);
6211 Utils::Program program(m_context);
6212
6213 try
6214 {
6215 program.Init(cs_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */,
6216 false /* separable */);
6217 }
6218 catch (Utils::Shader::InvalidSourceException& exc)
6219 {
6220 if (false == is_failure_expected)
6221 {
6222 m_context.getTestContext().getLog()
6223 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6224 exc.log(m_context);
6225 }
6226
6227 #if DEBUG_NEG_LOG_ERROR
6228
6229 else
6230 {
6231 m_context.getTestContext().getLog()
6232 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6233 << tcu::TestLog::EndMessage;
6234 exc.log(m_context);
6235 }
6236
6237 #endif /* DEBUG_NEG_LOG_ERROR */
6238
6239 is_build_error = true;
6240 }
6241 catch (Utils::Program::BuildException& exc)
6242 {
6243 if (false == is_failure_expected)
6244 {
6245 m_context.getTestContext().getLog()
6246 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6247 exc.log(m_context);
6248 }
6249
6250 #if DEBUG_NEG_LOG_ERROR
6251
6252 else
6253 {
6254 m_context.getTestContext().getLog()
6255 << tcu::TestLog::Message
6256 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6257 exc.log(m_context);
6258 }
6259
6260 #endif /* DEBUG_NEG_LOG_ERROR */
6261
6262 is_build_error = true;
6263 }
6264
6265 if (is_build_error != is_failure_expected)
6266 {
6267 if (!is_build_error)
6268 {
6269 m_context.getTestContext().getLog()
6270 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6271 Utils::Shader::LogSource(m_context, cs_source, Utils::Shader::COMPUTE);
6272 }
6273 test_case_result = false;
6274 }
6275 }
6276 else /* Draw */
6277 {
6278 const std::string& fs_source = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
6279 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
6280 bool is_build_error = false;
6281 const bool is_failure_expected = isFailureExpected(test_case_index);
6282 Utils::Program program(m_context);
6283 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
6284 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
6285 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
6286
6287 try
6288 {
6289 if (isSeparable(test_case_index))
6290 {
6291 program.Init("" /*cs*/, fs_source, "" /*gs_source*/, "" /*tcs_source*/, "" /*tes_source*/,
6292 "" /*vs_source*/, true /* separable */);
6293 program.Init("" /*cs*/, "" /*fs_source*/, gs_source, "" /*tcs_source*/, "" /*tes_source*/,
6294 "" /*vs_source*/, true /* separable */);
6295 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, tcs_source, "" /*tes_source*/,
6296 "" /*vs_source*/, true /* separable */);
6297 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, "" /*tcs_source*/, tes_source,
6298 "" /*vs_source*/, true /* separable */);
6299 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, "" /*tcs_source*/, "" /*tes_source*/,
6300 vs_source, true /* separable */);
6301 }
6302 else
6303 {
6304 program.Init("" /* cs */, fs_source, gs_source, tcs_source, tes_source, vs_source,
6305 false /* separable */);
6306 }
6307 }
6308 catch (Utils::Shader::InvalidSourceException& exc)
6309 {
6310 if (false == is_failure_expected)
6311 {
6312 m_context.getTestContext().getLog()
6313 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6314 exc.log(m_context);
6315 }
6316
6317 #if DEBUG_NEG_LOG_ERROR
6318
6319 else
6320 {
6321 m_context.getTestContext().getLog()
6322 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6323 << tcu::TestLog::EndMessage;
6324 exc.log(m_context);
6325 }
6326
6327 #endif /* DEBUG_NEG_LOG_ERROR */
6328
6329 is_build_error = true;
6330 }
6331 catch (Utils::Program::BuildException& exc)
6332 {
6333 if (false == is_failure_expected)
6334 {
6335 m_context.getTestContext().getLog()
6336 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6337 exc.log(m_context);
6338 }
6339
6340 #if DEBUG_NEG_LOG_ERROR
6341
6342 else
6343 {
6344 m_context.getTestContext().getLog()
6345 << tcu::TestLog::Message
6346 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6347 exc.log(m_context);
6348 }
6349
6350 #endif /* DEBUG_NEG_LOG_ERROR */
6351
6352 is_build_error = true;
6353 }
6354
6355 if (is_build_error != is_failure_expected)
6356 {
6357 if (!is_build_error)
6358 {
6359 m_context.getTestContext().getLog()
6360 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6361 Utils::Shader::LogSource(m_context, vs_source, Utils::Shader::VERTEX);
6362 Utils::Shader::LogSource(m_context, tcs_source, Utils::Shader::TESS_CTRL);
6363 Utils::Shader::LogSource(m_context, tes_source, Utils::Shader::TESS_EVAL);
6364 Utils::Shader::LogSource(m_context, gs_source, Utils::Shader::GEOMETRY);
6365 Utils::Shader::LogSource(m_context, fs_source, Utils::Shader::FRAGMENT);
6366 }
6367 test_case_result = false;
6368 }
6369 }
6370
6371 return test_case_result;
6372 }
6373
6374 /* Constants used by TextureTestBase */
6375 const glw::GLuint TextureTestBase::m_width = 16;
6376 const glw::GLuint TextureTestBase::m_height = 16;
6377
6378 /** Constructor
6379 *
6380 * @param context Test context
6381 * @param test_name Name of test
6382 * @param test_description Description of test
6383 **/
6384 TextureTestBase::TextureTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6385 : TestBase(context, test_name, test_description)
6386 {
6387 }
6388
6389 /** Get locations for all inputs with automatic_location
6390 *
6391 * @param program Program object
6392 * @param program_interface Interface of program
6393 **/
6394 void TextureTestBase::prepareAttribLocation(Utils::Program& program, Utils::ProgramInterface& program_interface)
6395 {
6396 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6397
6398 Utils::Variable::PtrVector& inputs = si.m_inputs;
6399
6400 for (Utils::Variable::PtrVector::iterator it = inputs.begin(); inputs.end() != it; ++it)
6401 {
6402 /* Test does not specify location, query value and set */
6403 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6404 {
6405 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_INPUT);
6406 GLint location = 0;
6407
6408 program.GetResource(GL_PROGRAM_INPUT, index, GL_LOCATION, 1 /* size */, &location);
6409
6410 (*it)->m_descriptor.m_expected_location = location;
6411 }
6412 }
6413 }
6414
6415 /** Verifies contents of drawn image
6416 *
6417 * @param ignored
6418 * @param color_0 Verified image
6419 *
6420 * @return true if image is filled with 1, false otherwise
6421 **/
6422 bool TextureTestBase::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& color_0)
6423 {
6424 static const GLuint size = m_width * m_height;
6425 static const GLuint expected_color = 1;
6426
6427 std::vector<GLuint> data;
6428 data.resize(size);
6429
6430 color_0.Get(GL_RED_INTEGER, GL_UNSIGNED_INT, &data[0]);
6431
6432 for (GLuint i = 0; i < size; ++i)
6433 {
6434 const GLuint color = data[i];
6435
6436 if (expected_color != color)
6437 {
6438 m_context.getTestContext().getLog() << tcu::TestLog::Message << "R32UI[" << i << "]:" << color
6439 << tcu::TestLog::EndMessage;
6440 return false;
6441 }
6442 }
6443
6444 return true;
6445 }
6446
6447 /** Execute dispatch compute for 16x16x1
6448 *
6449 * @param ignored
6450 **/
6451 void TextureTestBase::executeDispatchCall(GLuint /* test_case_index */)
6452 {
6453 const Functions& gl = m_context.getRenderContext().getFunctions();
6454
6455 gl.dispatchCompute(16 /* x */, 16 /* y */, 1 /* z */);
6456 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
6457 }
6458
6459 /** Execute drawArrays for single vertex
6460 *
6461 * @param ignored
6462 **/
6463 void TextureTestBase::executeDrawCall(GLuint /* test_case_index */)
6464 {
6465 const Functions& gl = m_context.getRenderContext().getFunctions();
6466
6467 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
6468 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6469 }
6470
6471 /** Prepare code snippet that will pass in variables to out variables
6472 *
6473 * @param ignored
6474 * @param varying_passthrough Collection of connections between in and out variables
6475 * @param stage Shader stage
6476 *
6477 * @return Code that pass in variables to next stage
6478 **/
6479 std::string TextureTestBase::getPassSnippet(GLuint /* test_case_index */,
6480 Utils::VaryingPassthrough& varying_passthrough, Utils::Shader::STAGES stage)
6481 {
6482 static const GLchar* separator = "\n ";
6483
6484 /* Skip for compute shader */
6485 if (Utils::Shader::COMPUTE == stage)
6486 {
6487 return "";
6488 }
6489
6490 Utils::VaryingConnection::Vector& vector = varying_passthrough.Get(stage);
6491
6492 std::string result = Utils::g_list;
6493 size_t position = 0;
6494
6495 for (GLuint i = 0; i < vector.size(); ++i)
6496 {
6497
6498 Utils::VaryingConnection& connection = vector[i];
6499
6500 Utils::Variable* in = connection.m_in;
6501 Utils::Variable* out = connection.m_out;
6502
6503 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6504 Utils::Variable::FLAVOUR out_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::OUTPUT);
6505
6506 const std::string passthrough =
6507 getVariablePassthrough("", in->m_descriptor, in_flavour, "", out->m_descriptor, out_flavour);
6508
6509 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6510 }
6511
6512 Utils::endList("", position, result);
6513
6514 return result;
6515 }
6516
6517 /** Basic implementation of method getProgramInterface
6518 *
6519 * @param ignored
6520 * @param ignored
6521 * @param ignored
6522 **/
6523 void TextureTestBase::getProgramInterface(GLuint /* test_case_index */,
6524 Utils::ProgramInterface& /* program_interface */,
6525 Utils::VaryingPassthrough& /* varying_passthrough */)
6526 {
6527 }
6528
6529 /** Prepare code snippet that will verify in and uniform variables
6530 *
6531 * @param ignored
6532 * @param program_interface Interface of program
6533 * @param stage Shader stage
6534 *
6535 * @return Code that verify variables
6536 **/
6537 std::string TextureTestBase::getVerificationSnippet(GLuint /* test_case_index */,
6538 Utils::ProgramInterface& program_interface,
6539 Utils::Shader::STAGES stage)
6540 {
6541 static const GLchar* separator = " ||\n ";
6542
6543 std::string verification = "if (LIST)\n"
6544 " {\n"
6545 " result = 0u;\n"
6546 " }\n";
6547
6548 /* Get flavour of in and out variables */
6549 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6550
6551 /* Get interface for shader stage */
6552 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
6553
6554 /* There are no varialbes to verify */
6555 if ((0 == si.m_inputs.size()) && (0 == si.m_uniforms.size()) && (0 == si.m_ssb_blocks.size()))
6556 {
6557 return "";
6558 }
6559
6560 /* For each in variable insert verification code */
6561 size_t position = 0;
6562
6563 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6564 {
6565 const Utils::Variable& var = *si.m_inputs[i];
6566 const std::string& var_verification = getVariableVerification("", var.m_data, var.m_descriptor, in_flavour);
6567
6568 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6569 }
6570
6571 /* For each unifrom variable insert verification code */
6572 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
6573 {
6574 const Utils::Variable& var = *si.m_uniforms[i];
6575 const std::string& var_verification =
6576 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6577
6578 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6579 }
6580
6581 /* For each ssb variable insert verification code */
6582 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
6583 {
6584 const Utils::Variable& var = *si.m_ssb_blocks[i];
6585 const std::string& var_verification =
6586 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6587
6588 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6589 }
6590
6591 Utils::endList("", position, verification);
6592
6593 #if DEBUG_TTB_VERIFICATION_SNIPPET_STAGE
6594
6595 {
6596 GLchar buffer[16];
6597 sprintf(buffer, "%d", stage + 10);
6598 Utils::replaceToken("0u", position, buffer, verification);
6599 }
6600
6601 #elif DEBUG_TTB_VERIFICATION_SNIPPET_VARIABLE
6602
6603 if (Utils::Shader::VERTEX == stage)
6604 {
6605 Utils::replaceToken("0u", position, "in_vs_first.x", verification);
6606 }
6607 else
6608 {
6609 Utils::replaceToken("0u", position, "31u", verification);
6610 }
6611
6612 #endif
6613
6614 /* Done */
6615 return verification;
6616 }
6617
6618 /** Selects if "compute" stage is relevant for test
6619 *
6620 * @param ignored
6621 *
6622 * @return true
6623 **/
6624 bool TextureTestBase::isComputeRelevant(GLuint /* test_case_index */)
6625 {
6626 return true;
6627 }
6628
6629 /** Selects if "draw" stages are relevant for test
6630 *
6631 * @param ignored
6632 *
6633 * @return true
6634 **/
6635 bool TextureTestBase::isDrawRelevant(GLuint /* test_case_index */)
6636 {
6637 return true;
6638 }
6639
6640 /** Prepare code that will do assignment of single in to single out
6641 *
6642 * @param in_parent_name Name of parent in variable
6643 * @param in_variable Descriptor of in variable
6644 * @param in_flavour Flavoud of in variable
6645 * @param out_parent_name Name of parent out variable
6646 * @param out_variable Descriptor of out variable
6647 * @param out_flavour Flavoud of out variable
6648 *
6649 * @return Code that does OUT = IN
6650 **/
6651 std::string TextureTestBase::getVariablePassthrough(const std::string& in_parent_name,
6652 const Utils::Variable::Descriptor& in_variable,
6653 Utils::Variable::FLAVOUR in_flavour,
6654 const std::string& out_parent_name,
6655 const Utils::Variable::Descriptor& out_variable,
6656 Utils::Variable::FLAVOUR out_flavour)
6657 {
6658 bool done = false;
6659 GLuint index = 0;
6660 GLuint member_index = 0;
6661 size_t position = 0;
6662 std::string result = Utils::g_list;
6663 static const GLchar* separator = ";\n ";
6664
6665 /* For each member of each array element */
6666 do
6667 {
6668 const std::string in_name = Utils::Variable::GetReference(in_parent_name, in_variable, in_flavour, index);
6669 const std::string out_name = Utils::Variable::GetReference(out_parent_name, out_variable, out_flavour, index);
6670 std::string passthrough;
6671
6672 /* Prepare verification */
6673 if (Utils::Variable::BUILTIN == in_variable.m_type)
6674 {
6675 size_t pass_position = 0;
6676
6677 passthrough = "OUT = IN;";
6678
6679 Utils::replaceToken("OUT", pass_position, out_name.c_str(), passthrough);
6680 Utils::replaceToken("IN", pass_position, in_name.c_str(), passthrough);
6681
6682 /* Increment index */
6683 ++index;
6684 }
6685 else
6686 {
6687 const Utils::Interface* in_interface = in_variable.m_interface;
6688 const Utils::Interface* out_interface = out_variable.m_interface;
6689
6690 if ((0 == in_interface) || (0 == out_interface))
6691 {
6692 TCU_FAIL("Nullptr");
6693 }
6694
6695 const Utils::Variable::Descriptor& in_member = in_interface->m_members[member_index];
6696 const Utils::Variable::Descriptor& out_member = out_interface->m_members[member_index];
6697
6698 passthrough = getVariablePassthrough(in_name, in_member, Utils::Variable::BASIC, out_name, out_member,
6699 Utils::Variable::BASIC);
6700
6701 /* Increment member_index */
6702 ++member_index;
6703
6704 /* Increment index and reset member_index if all members were processed */
6705 if (in_interface->m_members.size() == member_index)
6706 {
6707 ++index;
6708 member_index = 0;
6709 }
6710 }
6711
6712 /* Check if loop should end */
6713 if ((index >= in_variable.m_n_array_elements) && (0 == member_index))
6714 {
6715 done = true;
6716 }
6717
6718 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6719
6720 } while (true != done);
6721
6722 Utils::endList("", position, result);
6723
6724 /* Done */
6725 return result;
6726 }
6727
6728 /** Get verification of single variable
6729 *
6730 * @param parent_name Name of parent variable
6731 * @param data Data that should be used as EXPECTED
6732 * @param variable Descriptor of variable
6733 * @param flavour Flavour of variable
6734 *
6735 * @return Code that does (EXPECTED != VALUE) ||
6736 **/
6737 std::string TextureTestBase::getVariableVerification(const std::string& parent_name, const GLvoid* data,
6738 const Utils::Variable::Descriptor& variable,
6739 Utils::Variable::FLAVOUR flavour)
6740 {
6741 static const GLchar* logic_op = " ||\n ";
6742 const GLuint n_elements = (0 == variable.m_n_array_elements) ? 1 : variable.m_n_array_elements;
6743 size_t position = 0;
6744 std::string result = Utils::g_list;
6745 GLint stride = variable.m_expected_stride_of_element;
6746
6747 /* For each each array element */
6748 for (GLuint element = 0; element < n_elements; ++element)
6749 {
6750 const std::string name = Utils::Variable::GetReference(parent_name, variable, flavour, element);
6751
6752 /* Calculate data pointer */
6753 GLvoid* data_ptr = (GLvoid*)((GLubyte*)data + element * stride);
6754
6755 /* Prepare verification */
6756 if (Utils::Variable::BUILTIN == variable.m_type)
6757 {
6758 const std::string& expected = variable.m_builtin.GetGLSLConstructor(data_ptr);
6759 std::string verification;
6760 size_t verification_position = 0;
6761
6762 verification = "(EXPECTED != NAME)";
6763
6764 Utils::replaceToken("EXPECTED", verification_position, expected.c_str(), verification);
6765 Utils::replaceToken("NAME", verification_position, name.c_str(), verification);
6766
6767 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6768 }
6769 else
6770 {
6771 const Utils::Interface* interface = variable.m_interface;
6772
6773 if (0 == interface)
6774 {
6775 TCU_FAIL("Nullptr");
6776 }
6777
6778 const GLuint n_members = static_cast<GLuint>(interface->m_members.size());
6779
6780 /* for each member */
6781 for (GLuint member_index = 0; member_index < n_members; ++member_index)
6782 {
6783 const Utils::Variable::Descriptor& member = interface->m_members[member_index];
6784
6785 /* Get verification of member */
6786 const std::string& verification =
6787 getVariableVerification(name, (GLubyte*)data_ptr + member.m_offset, member, Utils::Variable::BASIC);
6788
6789 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6790 }
6791 }
6792 }
6793
6794 Utils::endList("", position, result);
6795
6796 return result;
6797 }
6798
6799 /** Prepare attributes, vertex array object and array buffer
6800 *
6801 * @param test_case_index Index of test case
6802 * @param program_interface Interface of program
6803 * @param buffer Array buffer
6804 * @param vao Vertex array object
6805 **/
6806 void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramInterface& program_interface,
6807 Utils::Buffer& buffer, Utils::VertexArray& vao)
6808 {
6809 const bool use_component_qualifier = useComponentQualifier(test_case_index);
6810
6811 /* Get shader interface */
6812 const Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6813
6814 /* Bind vao and buffer */
6815 vao.Bind();
6816 buffer.Bind();
6817
6818 /* Skip if there are no input variables in vertex shader */
6819 if (0 == si.m_inputs.size())
6820 {
6821 return;
6822 }
6823
6824 const Functions& gl = m_context.getRenderContext().getFunctions();
6825
6826 /* Calculate vertex stride and check */
6827 GLint max_inputs;
6828 gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_inputs);
6829 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
6830
6831 /* dvec3/4 vertex inputs use a single location but require 2x16B slots */
6832 const GLuint max_slots = max_inputs * 2;
6833
6834 /* Compute used slots */
6835 std::vector<GLuint> slot_sizes(max_slots, 0);
6836 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6837 {
6838 const Utils::Variable& variable = *si.m_inputs[i];
6839
6840 const GLuint variable_size = static_cast<GLuint>(variable.m_data_size);
6841
6842 const GLuint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6843 const GLuint ends_at = variable.m_descriptor.m_offset % 16 + variable_size;
6844
6845 const GLuint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6846 for (GLuint loc = 0; loc < array_length; loc++)
6847 {
6848 const GLuint slot = base_slot + loc;
6849 slot_sizes[slot] = std::max(slot_sizes[slot], ends_at);
6850 }
6851 }
6852
6853 /* Compute the offsets where we need to put vertex buffer data for each slot */
6854 std::vector<GLint> slot_offsets(max_slots, -1);
6855 GLuint buffer_size = 0;
6856 for (GLuint i = 0; i < max_slots; i++)
6857 {
6858 if (slot_sizes[i] == 0)
6859 continue;
6860 slot_offsets[i] = buffer_size;
6861 buffer_size += slot_sizes[i];
6862 }
6863
6864 /* Prepare buffer data and set up vao */
6865 std::vector<GLubyte> buffer_data(buffer_size);
6866
6867 GLubyte* ptr = &buffer_data[0];
6868
6869 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6870 {
6871 const Utils::Variable& variable = *si.m_inputs[i];
6872
6873 const GLuint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6874 const GLuint variable_offset = variable.m_descriptor.m_offset % 16;
6875 const GLuint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6876 for (GLuint loc = 0; loc < array_length; loc++)
6877 {
6878 const GLuint slot = base_slot + loc;
6879 memcpy(ptr + slot_offsets[slot] + variable_offset, variable.m_data, variable.m_data_size);
6880 }
6881
6882 if (!use_component_qualifier)
6883 {
6884 vao.Attribute(variable.m_descriptor.m_expected_location, variable.m_descriptor.m_builtin,
6885 variable.m_descriptor.m_n_array_elements, variable.m_descriptor.m_normalized,
6886 variable.GetStride(), (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6887 }
6888 else if (0 == variable.m_descriptor.m_expected_component)
6889 {
6890 /* Components can only be applied to types not surpassing
6891 * the bounds of a single slot. Therefore, we calculate
6892 * the amount of used components in the varying based on
6893 * the calculated slot sizes.
6894 */
6895 const GLuint n_component_size = Utils::Type::Double == variable.m_descriptor.m_builtin.m_basic_type ? 8 : 4;
6896 const GLuint n_rows = slot_sizes[base_slot] / n_component_size;
6897
6898 const Utils::Type& type = Utils::Type::GetType(variable.m_descriptor.m_builtin.m_basic_type,
6899 1 /* n_columns */, n_rows /* n_rows */);
6900
6901 vao.Attribute(variable.m_descriptor.m_expected_location, type, variable.m_descriptor.m_n_array_elements,
6902 variable.m_descriptor.m_normalized, variable.GetStride(),
6903 (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6904 }
6905 }
6906
6907 /* Update buffer */
6908 buffer.Data(Utils::Buffer::StaticDraw, buffer_size, ptr);
6909 }
6910
6911 /** Get locations for all outputs with automatic_location
6912 *
6913 * @param program Program object
6914 * @param program_interface Interface of program
6915 **/
6916 void TextureTestBase::prepareFragmentDataLoc(Utils::Program& program, Utils::ProgramInterface& program_interface)
6917 {
6918 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
6919 Utils::Variable::PtrVector& outputs = si.m_outputs;
6920
6921 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
6922 {
6923 /* Test does not specify location, query value and set */
6924 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6925 {
6926 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_OUTPUT);
6927 GLint location = 0;
6928
6929 program.GetResource(GL_PROGRAM_OUTPUT, index, GL_LOCATION, 1 /* size */, &location);
6930
6931 (*it)->m_descriptor.m_expected_location = location;
6932 }
6933 }
6934 }
6935
6936 /** Prepare framebuffer with single texture as color attachment
6937 *
6938 * @param framebuffer Framebuffer
6939 * @param color_0_texture Texture that will used as color attachment
6940 **/
6941 void TextureTestBase::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
6942 {
6943 /* Prepare data */
6944 std::vector<GLuint> texture_data;
6945 texture_data.resize(m_width * m_height);
6946
6947 for (GLuint i = 0; i < texture_data.size(); ++i)
6948 {
6949 texture_data[i] = 0x20406080;
6950 }
6951
6952 /* Prepare texture */
6953 color_0_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6954 &texture_data[0]);
6955
6956 /* Prepare framebuffer */
6957 framebuffer.Init();
6958 framebuffer.Bind();
6959 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0, color_0_texture.m_id, m_width, m_height);
6960
6961 framebuffer.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6962 framebuffer.Clear(GL_COLOR_BUFFER_BIT);
6963 }
6964
6965 /** Prepare iamge unit for compute shader
6966 *
6967 * @param location Uniform location
6968 * @param image_texture Texture that will used as color attachment
6969 **/
6970 void TextureTestBase::prepareImage(GLint location, Utils::Texture& image_texture) const
6971 {
6972 static const GLuint image_unit = 0;
6973
6974 std::vector<GLuint> texture_data;
6975 texture_data.resize(m_width * m_height);
6976
6977 for (GLuint i = 0; i < texture_data.size(); ++i)
6978 {
6979 texture_data[i] = 0x20406080;
6980 }
6981
6982 image_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6983 &texture_data[0]);
6984
6985 const Functions& gl = m_context.getRenderContext().getFunctions();
6986
6987 gl.bindImageTexture(image_unit, image_texture.m_id, 0 /* level */, GL_FALSE /* layered */, 0 /* Layer */,
6988 GL_WRITE_ONLY, GL_R32UI);
6989 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6990
6991 Utils::Program::Uniform(gl, Utils::Type::_int, 1 /* count */, location, &image_unit);
6992 }
6993
6994 /** Basic implementation
6995 *
6996 * @param ignored
6997 * @param si Shader interface
6998 * @param program Program
6999 * @param cs_buffer Buffer for ssb blocks
7000 **/
7001 void TextureTestBase::prepareSSBs(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
7002 Utils::Buffer& buffer)
7003 {
7004 /* Skip if there are no input variables in vertex shader */
7005 if (0 == si.m_ssb_blocks.size())
7006 {
7007 return;
7008 }
7009
7010 /* Calculate vertex stride */
7011 GLint ssbs_stride = 0;
7012
7013 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
7014 {
7015 Utils::Variable& variable = *si.m_ssb_blocks[i];
7016
7017 if (false == variable.IsBlock())
7018 {
7019 continue;
7020 }
7021
7022 GLint variable_stride = variable.GetStride();
7023
7024 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
7025
7026 ssbs_stride = std::max(ssbs_stride, ends_at);
7027 }
7028
7029 /* Set active program */
7030 program.Use();
7031
7032 /* Allocate */
7033 buffer.Bind();
7034 buffer.Data(Utils::Buffer::StaticDraw, ssbs_stride, 0);
7035
7036 /* Set up uniforms */
7037 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
7038 {
7039 Utils::Variable& variable = *si.m_ssb_blocks[i];
7040
7041 /* prepareUnifor should work fine for ssb blocks */
7042 prepareUniform(program, variable, buffer);
7043 }
7044 }
7045
7046 /** Basic implementation
7047 *
7048 * @param test_case_index Test case index
7049 * @param program_interface Program interface
7050 * @param program Program
7051 * @param cs_buffer Buffer for compute shader stage
7052 **/
7053 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7054 Utils::Program& program, Utils::Buffer& cs_buffer)
7055 {
7056 cs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7057
7058 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
7059
7060 prepareSSBs(test_case_index, cs, program, cs_buffer);
7061
7062 cs_buffer.BindBase(Utils::Shader::COMPUTE);
7063 }
7064
7065 /** Basic implementation
7066 *
7067 * @param test_case_index Test case index
7068 * @param program_interface Program interface
7069 * @param program Program
7070 * @param fs_buffer Buffer for fragment shader stage
7071 * @param gs_buffer Buffer for geometry shader stage
7072 * @param tcs_buffer Buffer for tessellation control shader stage
7073 * @param tes_buffer Buffer for tessellation evaluation shader stage
7074 * @param vs_buffer Buffer for vertex shader stage
7075 **/
7076 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7077 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7078 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7079 {
7080 fs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7081 gs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7082 tcs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7083 tes_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7084 vs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7085
7086 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7087 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7088 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7089 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7090 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7091
7092 prepareSSBs(test_case_index, fs, program, fs_buffer);
7093 prepareSSBs(test_case_index, gs, program, gs_buffer);
7094 prepareSSBs(test_case_index, tcs, program, tcs_buffer);
7095 prepareSSBs(test_case_index, tes, program, tes_buffer);
7096 prepareSSBs(test_case_index, vs, program, vs_buffer);
7097
7098 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7099 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7100 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7101 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7102 vs_buffer.BindBase(Utils::Shader::VERTEX);
7103 }
7104
7105 /** Updates buffer data with variable
7106 *
7107 * @param program Program object
7108 * @param variable Variable
7109 * @param buffer Buffer
7110 **/
7111 void TextureTestBase::prepareUniform(Utils::Program& program, Utils::Variable& variable, Utils::Buffer& buffer)
7112 {
7113 const Functions& gl = m_context.getRenderContext().getFunctions();
7114
7115 GLsizei count = variable.m_descriptor.m_n_array_elements;
7116 if (0 == count)
7117 {
7118 count = 1;
7119 }
7120
7121 if (Utils::Variable::BUILTIN == variable.m_descriptor.m_type)
7122 {
7123 program.Uniform(gl, variable.m_descriptor.m_builtin, count, variable.m_descriptor.m_expected_location,
7124 variable.m_data);
7125 }
7126 else
7127 {
7128 const bool is_block = variable.IsBlock();
7129
7130 if (false == is_block)
7131 {
7132 TCU_FAIL("Not implemented");
7133 }
7134 else
7135 {
7136 buffer.SubData(variable.m_descriptor.m_offset, variable.m_descriptor.m_expected_stride_of_element * count,
7137 variable.m_data);
7138 }
7139 }
7140 }
7141
7142 /** Basic implementation
7143 *
7144 * @param ignored
7145 * @param si Shader interface
7146 * @param program Program
7147 * @param cs_buffer Buffer for uniform blocks
7148 **/
7149 void TextureTestBase::prepareUniforms(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
7150 Utils::Buffer& buffer)
7151 {
7152 /* Skip if there are no input variables in vertex shader */
7153 if (0 == si.m_uniforms.size())
7154 {
7155 return;
7156 }
7157
7158 /* Calculate vertex stride */
7159 GLint uniforms_stride = 0;
7160
7161 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7162 {
7163 Utils::Variable& variable = *si.m_uniforms[i];
7164
7165 if (false == variable.IsBlock())
7166 {
7167 continue;
7168 }
7169
7170 GLint variable_stride = variable.GetStride();
7171
7172 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
7173
7174 uniforms_stride = std::max(uniforms_stride, ends_at);
7175 }
7176
7177 /* Set active program */
7178 program.Use();
7179
7180 /* Allocate */
7181 buffer.Bind();
7182 buffer.Data(Utils::Buffer::StaticDraw, uniforms_stride, 0);
7183
7184 /* Set up uniforms */
7185 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7186 {
7187 Utils::Variable& variable = *si.m_uniforms[i];
7188
7189 prepareUniform(program, variable, buffer);
7190 }
7191 }
7192
7193 /** Basic implementation
7194 *
7195 * @param test_case_index Test case index
7196 * @param program_interface Program interface
7197 * @param program Program
7198 * @param cs_buffer Buffer for compute shader stage
7199 **/
7200 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7201 Utils::Program& program, Utils::Buffer& cs_buffer)
7202 {
7203 cs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7204
7205 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
7206
7207 prepareUniforms(test_case_index, cs, program, cs_buffer);
7208
7209 cs_buffer.BindBase(Utils::Shader::COMPUTE);
7210 }
7211
7212 /** Basic implementation
7213 *
7214 * @param test_case_index Test case index
7215 * @param program_interface Program interface
7216 * @param program Program
7217 * @param fs_buffer Buffer for fragment shader stage
7218 * @param gs_buffer Buffer for geometry shader stage
7219 * @param tcs_buffer Buffer for tessellation control shader stage
7220 * @param tes_buffer Buffer for tessellation evaluation shader stage
7221 * @param vs_buffer Buffer for vertex shader stage
7222 **/
7223 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7224 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7225 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7226 {
7227 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7228 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7229 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7230 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7231 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7232
7233 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7234 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7235 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7236 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7237 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7238
7239 prepareUniforms(test_case_index, fs, program, fs_buffer);
7240 prepareUniforms(test_case_index, gs, program, gs_buffer);
7241 prepareUniforms(test_case_index, tcs, program, tcs_buffer);
7242 prepareUniforms(test_case_index, tes, program, tes_buffer);
7243 prepareUniforms(test_case_index, vs, program, vs_buffer);
7244
7245 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7246 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7247 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7248 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7249 vs_buffer.BindBase(Utils::Shader::VERTEX);
7250 }
7251
7252 /** Basic implementation
7253 *
7254 * @param test_case_index Test case index
7255 * @param program_interface Program interface
7256 * @param program Program
7257 * @param fs_buffer Buffer for fragment shader stage
7258 * @param gs_buffer Buffer for geometry shader stage
7259 * @param tcs_buffer Buffer for tessellation control shader stage
7260 * @param tes_buffer Buffer for tessellation evaluation shader stage
7261 * @param vs_buffer Buffer for vertex shader stage
7262 **/
7263 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7264 Utils::Program& fs_program, Utils::Program& gs_program,
7265 Utils::Program& tcs_program, Utils::Program& tes_program,
7266 Utils::Program& vs_program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7267 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7268 {
7269 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7270 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7271 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7272 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7273 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7274
7275 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7276 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7277 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7278 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7279 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7280
7281 prepareUniforms(test_case_index, fs, fs_program, fs_buffer);
7282 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7283
7284 prepareUniforms(test_case_index, gs, gs_program, gs_buffer);
7285 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7286
7287 prepareUniforms(test_case_index, tcs, tcs_program, tcs_buffer);
7288 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7289
7290 prepareUniforms(test_case_index, tes, tes_program, tes_buffer);
7291 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7292
7293 prepareUniforms(test_case_index, vs, vs_program, vs_buffer);
7294 vs_buffer.BindBase(Utils::Shader::VERTEX);
7295 }
7296
7297 /** Prepare source for shader
7298 *
7299 * @param test_case_index Index of test case
7300 * @param program_interface Interface of program
7301 * @param varying_passthrough Collection of connection between in and out variables
7302 * @param stage Shader stage
7303 *
7304 * @return Source of shader
7305 **/
7306 std::string TextureTestBase::getShaderSource(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7307 Utils::VaryingPassthrough& varying_passthrough,
7308 Utils::Shader::STAGES stage)
7309 {
7310 /* Get strings */
7311 const GLchar* shader_template = getShaderTemplate(stage);
7312 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
7313 const char* shader_version = glu::getGLSLVersionDeclaration(glslVersion);
7314 const std::string& shader_interface = program_interface.GetInterfaceForStage(stage);
7315 const std::string& verification = getVerificationSnippet(test_case_index, program_interface, stage);
7316 const std::string& passthrough = getPassSnippet(test_case_index, varying_passthrough, stage);
7317
7318 const GLchar* per_vertex = "";
7319
7320 std::string source = shader_template;
7321 size_t position = 0;
7322
7323 Utils::replaceToken("VERSION", position, shader_version, source);
7324
7325 /* Replace tokens in template */
7326 if (Utils::Shader::GEOMETRY == stage)
7327 {
7328 if (false == useMonolithicProgram(test_case_index))
7329 {
7330 per_vertex = "out gl_PerVertex {\n"
7331 "vec4 gl_Position;\n"
7332 "};\n"
7333 "\n";
7334 }
7335
7336 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
7337 }
7338
7339 Utils::replaceToken("INTERFACE", position, shader_interface.c_str(), source);
7340 Utils::replaceToken("VERIFICATION", position, verification.c_str(), source);
7341
7342 if (false == verification.empty())
7343 {
7344 Utils::replaceAllTokens("ELSE", " else ", source);
7345 }
7346 else
7347 {
7348 Utils::replaceAllTokens("ELSE", "", source);
7349 }
7350
7351 Utils::replaceAllTokens("PASSTHROUGH", passthrough.c_str(), source);
7352
7353 /* Done */
7354 return source;
7355 }
7356
7357 /** Returns template of shader for given stage
7358 *
7359 * @param stage Shade stage
7360 *
7361 * @return Proper template
7362 **/
7363 const GLchar* TextureTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
7364 {
7365
7366 static const GLchar* compute_shader_template =
7367 "VERSION\n"
7368 "#extension GL_ARB_enhanced_layouts : require\n"
7369 "\n"
7370 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
7371 "\n"
7372 "writeonly uniform uimage2D uni_image;\n"
7373 "\n"
7374 "INTERFACE"
7375 "\n"
7376 "void main()\n"
7377 "{\n"
7378 " uint result = 1u;\n"
7379 "\n"
7380 " VERIFICATION"
7381 "\n"
7382 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
7383 "}\n"
7384 "\n";
7385
7386 static const GLchar* fragment_shader_template = "VERSION\n"
7387 "#extension GL_ARB_enhanced_layouts : require\n"
7388 "\n"
7389 "flat in uint gs_fs_result;\n"
7390 " out uint fs_out_result;\n"
7391 "\n"
7392 "INTERFACE"
7393 "\n"
7394 "void main()\n"
7395 "{\n"
7396 " uint result = 1u;\n"
7397 "\n"
7398 " if (1u != gs_fs_result)\n"
7399 " {\n"
7400 " result = gs_fs_result;\n"
7401 " }\n"
7402 "ELSEVERIFICATION"
7403 "\n"
7404 " fs_out_result = result;\n"
7405 " PASSTHROUGH\n"
7406 "}\n"
7407 "\n";
7408
7409 static const GLchar* geometry_shader_template =
7410 "VERSION\n"
7411 "#extension GL_ARB_enhanced_layouts : require\n"
7412 "\n"
7413 "layout(points) in;\n"
7414 "layout(triangle_strip, max_vertices = 4) out;\n"
7415 "\n"
7416 " in uint tes_gs_result[];\n"
7417 " flat out uint gs_fs_result;\n"
7418 "\n"
7419 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
7420 "INTERFACE"
7421 "\n"
7422 "void main()\n"
7423 "{\n"
7424 " uint result = 1u;\n"
7425 "\n"
7426 " if (1u != tes_gs_result[0])\n"
7427 " {\n"
7428 " result = tes_gs_result[0];\n"
7429 " }\n"
7430 "ELSEVERIFICATION"
7431 "\n"
7432 " gs_fs_result = result;\n"
7433 " PASSTHROUGH\n"
7434 " gl_Position = vec4(-1, -1, 0, 1);\n"
7435 " EmitVertex();\n"
7436 " gs_fs_result = result;\n"
7437 " PASSTHROUGH\n"
7438 " gl_Position = vec4(-1, 1, 0, 1);\n"
7439 " EmitVertex();\n"
7440 " gs_fs_result = result;\n"
7441 " PASSTHROUGH\n"
7442 " gl_Position = vec4(1, -1, 0, 1);\n"
7443 " EmitVertex();\n"
7444 " gs_fs_result = result;\n"
7445 " PASSTHROUGH\n"
7446 " gl_Position = vec4(1, 1, 0, 1);\n"
7447 " EmitVertex();\n"
7448 "}\n"
7449 "\n";
7450
7451 static const GLchar* tess_ctrl_shader_template = "VERSION\n"
7452 "#extension GL_ARB_enhanced_layouts : require\n"
7453 "\n"
7454 "layout(vertices = 1) out;\n"
7455 "\n"
7456 "in uint vs_tcs_result[];\n"
7457 "out uint tcs_tes_result[];\n"
7458 "\n"
7459 "INTERFACE"
7460 "\n"
7461 "void main()\n"
7462 "{\n"
7463 " uint result = 1u;\n"
7464 "\n"
7465 " if (1u != vs_tcs_result[gl_InvocationID])\n"
7466 " {\n"
7467 " result = vs_tcs_result[gl_InvocationID];\n"
7468 " }\n"
7469 "ELSEVERIFICATION"
7470 "\n"
7471 " tcs_tes_result[gl_InvocationID] = result;\n"
7472 "\n"
7473 " PASSTHROUGH\n"
7474 "\n"
7475 " gl_TessLevelOuter[0] = 1.0;\n"
7476 " gl_TessLevelOuter[1] = 1.0;\n"
7477 " gl_TessLevelOuter[2] = 1.0;\n"
7478 " gl_TessLevelOuter[3] = 1.0;\n"
7479 " gl_TessLevelInner[0] = 1.0;\n"
7480 " gl_TessLevelInner[1] = 1.0;\n"
7481 "}\n"
7482 "\n";
7483
7484 static const GLchar* tess_eval_shader_template = "VERSION\n"
7485 "#extension GL_ARB_enhanced_layouts : require\n"
7486 "\n"
7487 "layout(isolines, point_mode) in;\n"
7488 "\n"
7489 "in uint tcs_tes_result[];\n"
7490 "out uint tes_gs_result;\n"
7491 "\n"
7492 "INTERFACE"
7493 "\n"
7494 "void main()\n"
7495 "{\n"
7496 " uint result = 1u;\n"
7497 "\n"
7498 " if (1u != tcs_tes_result[0])\n"
7499 " {\n"
7500 " result = tcs_tes_result[0];\n"
7501 " }\n"
7502 "ELSEVERIFICATION"
7503 "\n"
7504 " tes_gs_result = result;\n"
7505 "\n"
7506 " PASSTHROUGH\n"
7507 "}\n"
7508 "\n";
7509
7510 static const GLchar* vertex_shader_template = "VERSION\n"
7511 "#extension GL_ARB_enhanced_layouts : require\n"
7512 "\n"
7513 "out uint vs_tcs_result;\n"
7514 "\n"
7515 "INTERFACE"
7516 "\n"
7517 "void main()\n"
7518 "{\n"
7519 " uint result = 1u;\n"
7520 "\n"
7521 " VERIFICATION\n"
7522 "\n"
7523 " vs_tcs_result = result;\n"
7524 "\n"
7525 " PASSTHROUGH\n"
7526 "}\n"
7527 "\n";
7528
7529 const GLchar* result = 0;
7530
7531 switch (stage)
7532 {
7533 case Utils::Shader::COMPUTE:
7534 result = compute_shader_template;
7535 break;
7536 case Utils::Shader::FRAGMENT:
7537 result = fragment_shader_template;
7538 break;
7539 case Utils::Shader::GEOMETRY:
7540 result = geometry_shader_template;
7541 break;
7542 case Utils::Shader::TESS_CTRL:
7543 result = tess_ctrl_shader_template;
7544 break;
7545 case Utils::Shader::TESS_EVAL:
7546 result = tess_eval_shader_template;
7547 break;
7548 case Utils::Shader::VERTEX:
7549 result = vertex_shader_template;
7550 break;
7551 default:
7552 TCU_FAIL("Invalid enum");
7553 }
7554
7555 return result;
7556 }
7557
7558 /** Runs test case
7559 *
7560 * @param test_case_index Id of test case
7561 *
7562 * @return true if test case pass, false otherwise
7563 **/
7564 bool TextureTestBase::testCase(GLuint test_case_index)
7565 {
7566 try
7567 {
7568 if (true == useMonolithicProgram(test_case_index))
7569 {
7570 return testMonolithic(test_case_index);
7571 }
7572 else
7573 {
7574 return testSeparable(test_case_index);
7575 }
7576 }
7577 catch (Utils::Shader::InvalidSourceException& exc)
7578 {
7579 exc.log(m_context);
7580 TCU_FAIL(exc.what());
7581 }
7582 catch (Utils::Program::BuildException& exc)
7583 {
7584 exc.log(m_context);
7585 TCU_FAIL(exc.what());
7586 }
7587 }
7588
7589 /** Runs "draw" test with monolithic program
7590 *
7591 * @param test_case_index Id of test case
7592 **/
7593 bool TextureTestBase::testMonolithic(GLuint test_case_index)
7594 {
7595 Utils::ProgramInterface program_interface;
7596 Utils::VaryingPassthrough varying_passthrough;
7597
7598 /* */
7599 const std::string& test_name = getTestCaseName(test_case_index);
7600
7601 /* */
7602 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7603
7604 bool result = true;
7605 /* Draw */
7606 if (true == isDrawRelevant(test_case_index))
7607 {
7608 Utils::Buffer buffer_attr(m_context);
7609 Utils::Buffer buffer_ssb_fs(m_context);
7610 Utils::Buffer buffer_ssb_gs(m_context);
7611 Utils::Buffer buffer_ssb_tcs(m_context);
7612 Utils::Buffer buffer_ssb_tes(m_context);
7613 Utils::Buffer buffer_ssb_vs(m_context);
7614 Utils::Buffer buffer_u_fs(m_context);
7615 Utils::Buffer buffer_u_gs(m_context);
7616 Utils::Buffer buffer_u_tcs(m_context);
7617 Utils::Buffer buffer_u_tes(m_context);
7618 Utils::Buffer buffer_u_vs(m_context);
7619 Utils::Framebuffer framebuffer(m_context);
7620 Utils::Program program(m_context);
7621 Utils::Texture texture_fb(m_context);
7622 Utils::VertexArray vao(m_context);
7623
7624 /* */
7625 const std::string& fragment_shader =
7626 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7627 const std::string& geometry_shader =
7628 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7629 const std::string& tess_ctrl_shader =
7630 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7631 const std::string& tess_eval_shader =
7632 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7633 const std::string& vertex_shader =
7634 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7635
7636 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
7637 vertex_shader, false /* is_separable */);
7638
7639 /* */
7640 prepareAttribLocation(program, program_interface);
7641 prepareFragmentDataLoc(program, program_interface);
7642
7643 /* */
7644 std::stringstream stream;
7645 if (false == Utils::checkMonolithicDrawProgramInterface(program, program_interface, stream))
7646 {
7647 m_context.getTestContext().getLog()
7648 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7649 << ". Inspection of draw program interface failed:\n"
7650 << stream.str() << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7651 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7652 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7653
7654 return false;
7655 }
7656
7657 /* */
7658 program.Use();
7659
7660 /* */
7661 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7662 vao.Init();
7663 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7664
7665 /* */
7666 prepareUniforms(test_case_index, program_interface, program, buffer_u_fs, buffer_u_gs, buffer_u_tcs,
7667 buffer_u_tes, buffer_u_vs);
7668
7669 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_fs, buffer_ssb_gs, buffer_ssb_tcs,
7670 buffer_ssb_tes, buffer_ssb_vs);
7671
7672 /* */
7673 prepareFramebuffer(framebuffer, texture_fb);
7674
7675 /* Draw */
7676 executeDrawCall(test_case_index);
7677
7678 #if USE_NSIGHT
7679 m_context.getRenderContext().postIterate();
7680 #endif
7681
7682 /* Check results */
7683 if (false == checkResults(test_case_index, texture_fb))
7684 {
7685 m_context.getTestContext().getLog()
7686 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7687 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7688 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7689 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7690
7691 result = false;
7692 }
7693 }
7694
7695 /* Compute */
7696 if (true == isComputeRelevant(test_case_index))
7697 {
7698 Utils::Buffer buffer_ssb_cs(m_context);
7699 Utils::Buffer buffer_u_cs(m_context);
7700 Utils::Program program(m_context);
7701 Utils::Texture texture_im(m_context);
7702 Utils::VertexArray vao(m_context);
7703
7704 /* */
7705 const std::string& compute_shader =
7706 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7707
7708 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7709 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7710
7711 /* */
7712 {
7713 std::stringstream stream;
7714
7715 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7716 {
7717 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7718 << ". Inspection of compute program interface failed:\n"
7719 << stream.str() << tcu::TestLog::EndMessage;
7720
7721 return false;
7722 }
7723 }
7724
7725 /* */
7726 program.Use();
7727
7728 /* */
7729 vao.Init();
7730 vao.Bind();
7731
7732 /* */
7733 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7734
7735 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_cs);
7736
7737 /* */
7738 GLint image_location = program.GetUniformLocation("uni_image");
7739 prepareImage(image_location, texture_im);
7740
7741 /* Draw */
7742 executeDispatchCall(test_case_index);
7743
7744 #if USE_NSIGHT
7745 m_context.getRenderContext().postIterate();
7746 #endif
7747
7748 /* Check results */
7749 if (false == checkResults(test_case_index, texture_im))
7750 {
7751 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7752 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7753 << tcu::TestLog::KernelSource(compute_shader);
7754
7755 result = false;
7756 }
7757 }
7758
7759 return result;
7760 }
7761
7762 /** Runs "draw" test with separable program
7763 *
7764 * @param test_case_index Id of test case
7765 **/
7766 bool TextureTestBase::testSeparable(GLuint test_case_index)
7767 {
7768 Utils::ProgramInterface program_interface;
7769 Utils::VaryingPassthrough varying_passthrough;
7770
7771 /* */
7772 const std::string& test_name = getTestCaseName(test_case_index);
7773
7774 /* */
7775 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7776
7777 bool result = true;
7778 /* Draw */
7779 if (true == isDrawRelevant(test_case_index))
7780 {
7781 Utils::Buffer buffer_attr(m_context);
7782 Utils::Buffer buffer_u_fs(m_context);
7783 Utils::Buffer buffer_u_gs(m_context);
7784 Utils::Buffer buffer_u_tcs(m_context);
7785 Utils::Buffer buffer_u_tes(m_context);
7786 Utils::Buffer buffer_u_vs(m_context);
7787 Utils::Framebuffer framebuffer(m_context);
7788 Utils::Pipeline pipeline(m_context);
7789 Utils::Program program_fs(m_context);
7790 Utils::Program program_gs(m_context);
7791 Utils::Program program_tcs(m_context);
7792 Utils::Program program_tes(m_context);
7793 Utils::Program program_vs(m_context);
7794 Utils::Texture texture_fb(m_context);
7795 Utils::VertexArray vao(m_context);
7796
7797 /* */
7798 const std::string& fs =
7799 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7800 const std::string& gs =
7801 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7802 const std::string& tcs =
7803 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7804 const std::string& tes =
7805 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7806 const std::string& vs =
7807 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7808
7809 program_fs.Init("" /*cs*/, fs, "" /*gs*/, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7810 program_gs.Init("" /*cs*/, "" /*fs*/, gs, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7811 program_tcs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, tcs, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7812 program_tes.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, tes, "" /*vs*/, true /* is_separable */);
7813 program_vs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, "" /*tes*/, vs, true /* is_separable */);
7814
7815 /* */
7816 prepareAttribLocation(program_vs, program_interface);
7817 prepareFragmentDataLoc(program_vs, program_interface);
7818
7819 /* */
7820 std::stringstream stream;
7821 if ((false ==
7822 Utils::checkSeparableDrawProgramInterface(program_vs, program_interface, Utils::Shader::VERTEX, stream)) ||
7823 (false == Utils::checkSeparableDrawProgramInterface(program_fs, program_interface, Utils::Shader::FRAGMENT,
7824 stream)) ||
7825 (false == Utils::checkSeparableDrawProgramInterface(program_gs, program_interface, Utils::Shader::GEOMETRY,
7826 stream)) ||
7827 (false == Utils::checkSeparableDrawProgramInterface(program_tcs, program_interface,
7828 Utils::Shader::TESS_CTRL, stream)) ||
7829 (false == Utils::checkSeparableDrawProgramInterface(program_tes, program_interface,
7830 Utils::Shader::TESS_EVAL, stream)))
7831 {
7832 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7833 << ". Inspection of separable draw program interface failed:\n"
7834 << stream.str() << tcu::TestLog::EndMessage
7835 << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7836 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs)
7837 << tcu::TestLog::KernelSource(fs);
7838
7839 return false;
7840 }
7841
7842 /* */
7843 pipeline.Init();
7844 pipeline.UseProgramStages(program_fs.m_id, GL_FRAGMENT_SHADER_BIT);
7845 pipeline.UseProgramStages(program_gs.m_id, GL_GEOMETRY_SHADER_BIT);
7846 pipeline.UseProgramStages(program_tcs.m_id, GL_TESS_CONTROL_SHADER_BIT);
7847 pipeline.UseProgramStages(program_tes.m_id, GL_TESS_EVALUATION_SHADER_BIT);
7848 pipeline.UseProgramStages(program_vs.m_id, GL_VERTEX_SHADER_BIT);
7849 pipeline.Bind();
7850
7851 /* */
7852
7853 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7854 vao.Init();
7855 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7856
7857 /* */
7858 prepareUniforms(test_case_index, program_interface, program_fs, program_gs, program_tcs, program_tes,
7859 program_vs, buffer_u_fs, buffer_u_gs, buffer_u_tcs, buffer_u_tes, buffer_u_vs);
7860
7861 Utils::Program::Use(m_context.getRenderContext().getFunctions(), Utils::Program::m_invalid_id);
7862
7863 /* */
7864 prepareFramebuffer(framebuffer, texture_fb);
7865
7866 /* Draw */
7867 executeDrawCall(test_case_index);
7868
7869 #if USE_NSIGHT
7870 m_context.getRenderContext().postIterate();
7871 #endif
7872
7873 /* Check results */
7874 if (false == checkResults(test_case_index, texture_fb))
7875 {
7876 m_context.getTestContext().getLog()
7877 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7878 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7879 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs) << tcu::TestLog::KernelSource(fs);
7880
7881 result = false;
7882 }
7883 else
7884 {
7885 m_context.getTestContext().getLog()
7886 << tcu::TestLog::Message << "Success." << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vs)
7887 << tcu::TestLog::KernelSource(tcs) << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs)
7888 << tcu::TestLog::KernelSource(fs);
7889 }
7890 }
7891
7892 /* Compute */
7893 if (true == isComputeRelevant(test_case_index))
7894 {
7895 Utils::Buffer buffer_u_cs(m_context);
7896 Utils::Program program(m_context);
7897 Utils::Texture texture_im(m_context);
7898 Utils::VertexArray vao(m_context);
7899
7900 /* */
7901 const std::string& compute_shader =
7902 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7903
7904 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7905 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7906
7907 /* */
7908 {
7909 std::stringstream stream;
7910
7911 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7912 {
7913 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7914 << ". Inspection of compute program interface failed:\n"
7915 << stream.str() << tcu::TestLog::EndMessage;
7916
7917 return false;
7918 }
7919 }
7920
7921 /* */
7922 program.Use();
7923
7924 /* */
7925 vao.Init();
7926 vao.Bind();
7927
7928 /* */
7929 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7930
7931 /* */
7932 GLint image_location = program.GetUniformLocation("uni_image");
7933 prepareImage(image_location, texture_im);
7934
7935 /* Draw */
7936 executeDispatchCall(test_case_index);
7937
7938 #if USE_NSIGHT
7939 m_context.getRenderContext().postIterate();
7940 #endif
7941
7942 /* Check results */
7943 if (false == checkResults(test_case_index, texture_im))
7944 {
7945 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7946 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7947 << tcu::TestLog::KernelSource(compute_shader);
7948
7949 result = false;
7950 }
7951 }
7952
7953 return result;
7954 }
7955
7956 /** Basic implementation
7957 *
7958 * @param ignored
7959 *
7960 * @return false
7961 **/
7962 bool TextureTestBase::useComponentQualifier(glw::GLuint /* test_case_index */)
7963 {
7964 return false;
7965 }
7966
7967 /** Basic implementation
7968 *
7969 * @param ignored
7970 *
7971 * @return true
7972 **/
7973 bool TextureTestBase::useMonolithicProgram(GLuint /* test_case_index */)
7974 {
7975 return true;
7976 }
7977
7978 /** Constructor
7979 *
7980 * @param context Test framework context
7981 **/
7982 APIConstantValuesTest::APIConstantValuesTest(deqp::Context& context)
7983 : TestCase(context, "api_constant_values", "Test verifies values of api constants")
7984 {
7985 /* Nothing to be done here */
7986 }
7987
7988 /** Execute test
7989 *
7990 * @return tcu::TestNode::STOP otherwise
7991 **/
7992 tcu::TestNode::IterateResult APIConstantValuesTest::iterate()
7993 {
7994 static const GLuint expected_comp = 64;
7995 static const GLuint expected_xfb = 4;
7996 static const GLuint expected_sep = 4;
7997 GLint max_comp = 0;
7998 GLint max_xfb = 0;
7999 GLint max_sep = 0;
8000 bool test_result = true;
8001
8002 const Functions& gl = m_context.getRenderContext().getFunctions();
8003
8004 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
8005 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8006 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_comp);
8007 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8008 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_sep);
8009 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8010
8011 if (expected_xfb > (GLuint)max_xfb)
8012 {
8013 m_context.getTestContext().getLog() << tcu::TestLog::Message
8014 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_BUFFERS. Got " << max_xfb
8015 << " Expected at least " << expected_xfb << tcu::TestLog::EndMessage;
8016
8017 test_result = false;
8018 }
8019
8020 if (expected_comp > (GLuint)max_comp)
8021 {
8022 m_context.getTestContext().getLog()
8023 << tcu::TestLog::Message << "Invalid GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. Got " << max_comp
8024 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
8025
8026 test_result = false;
8027 }
8028
8029 if (expected_sep > (GLuint)max_sep)
8030 {
8031 m_context.getTestContext().getLog() << tcu::TestLog::Message
8032 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS. Got " << max_comp
8033 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
8034
8035 test_result = false;
8036 }
8037
8038 /* Set result */
8039 if (true == test_result)
8040 {
8041 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
8042 }
8043 else
8044 {
8045 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8046 }
8047
8048 /* Done */
8049 return tcu::TestNode::STOP;
8050 }
8051
8052 /** Constructor
8053 *
8054 * @param context Test framework context
8055 **/
8056 APIErrorsTest::APIErrorsTest(deqp::Context& context)
8057 : TestCase(context, "api_errors", "Test verifies errors reeturned by api")
8058 {
8059 /* Nothing to be done here */
8060 }
8061
8062 /** Execute test
8063 *
8064 * @return tcu::TestNode::STOP otherwise
8065 **/
8066 tcu::TestNode::IterateResult APIErrorsTest::iterate()
8067 {
8068 GLint length = 0;
8069 GLchar name[64];
8070 GLint param = 0;
8071 Utils::Program program(m_context);
8072 bool test_result = true;
8073
8074 const Functions& gl = m_context.getRenderContext().getFunctions();
8075
8076 try
8077 {
8078 program.Init("" /* cs */, "#version 430 core\n"
8079 "#extension GL_ARB_enhanced_layouts : require\n"
8080 "\n"
8081 "in vec4 vs_fs;\n"
8082 "out vec4 fs_out;\n"
8083 "\n"
8084 "void main()\n"
8085 "{\n"
8086 " fs_out = vs_fs;\n"
8087 "}\n"
8088 "\n" /* fs */,
8089 "" /* gs */, "" /* tcs */, "" /* tes */, "#version 430 core\n"
8090 "#extension GL_ARB_enhanced_layouts : require\n"
8091 "\n"
8092 "in vec4 in_vs;\n"
8093 "layout (xfb_offset = 16) out vec4 vs_fs;\n"
8094 "\n"
8095 "void main()\n"
8096 "{\n"
8097 " vs_fs = in_vs;\n"
8098 "}\n"
8099 "\n" /* vs */,
8100 false /* separable */);
8101 }
8102 catch (Utils::Shader::InvalidSourceException& exc)
8103 {
8104 exc.log(m_context);
8105 TCU_FAIL(exc.what());
8106 }
8107 catch (Utils::Program::BuildException& exc)
8108 {
8109 TCU_FAIL(exc.what());
8110 }
8111
8112 /*
8113 * - GetProgramInterfaceiv should generate INVALID_OPERATION when
8114 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER and <pname> is one of the
8115 * following:
8116 * * MAX_NAME_LENGTH,
8117 * * MAX_NUM_ACTIVE_VARIABLES;
8118 */
8119 gl.getProgramInterfaceiv(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH, ¶m);
8120 checkError(GL_INVALID_OPERATION, "GetProgramInterfaceiv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH)",
8121 test_result);
8122
8123 /*
8124 * - GetProgramResourceIndex should generate INVALID_ENUM when
8125 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8126 */
8127 gl.getProgramResourceIndex(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, "0");
8128 checkError(GL_INVALID_ENUM, "GetProgramResourceIndex(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8129 /*
8130 * - GetProgramResourceName should generate INVALID_ENUM when
8131 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8132 */
8133 gl.getProgramResourceName(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 64 /* bufSize */, &length,
8134 name);
8135 checkError(GL_INVALID_ENUM, "GetProgramResourceName(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8136
8137 /* Set result */
8138 if (true == test_result)
8139 {
8140 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
8141 }
8142 else
8143 {
8144 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8145 }
8146
8147 /* Done */
8148 return tcu::TestNode::STOP;
8149 }
8150
8151 /** Check if error is the expected one.
8152 *
8153 * @param expected_error Expected error
8154 * @param message Message to log in case of error
8155 * @param test_result Test result, set to false in case of invalid error
8156 **/
8157 void APIErrorsTest::checkError(GLenum expected_error, const GLchar* message, bool& test_result)
8158 {
8159 const Functions& gl = m_context.getRenderContext().getFunctions();
8160
8161 GLenum error = gl.getError();
8162
8163 if (error != expected_error)
8164 {
8165 m_context.getTestContext().getLog()
8166 << tcu::TestLog::Message << "Failure. Invalid error. Got " << glu::getErrorStr(error) << " expected "
8167 << glu::getErrorStr(expected_error) << " Msg: " << message << tcu::TestLog::EndMessage;
8168
8169 test_result = false;
8170 }
8171 }
8172
8173 /** Constructor
8174 *
8175 * @param context Test framework context
8176 **/
8177 GLSLContantImmutablityTest::GLSLContantImmutablityTest(deqp::Context& context)
8178 : NegativeTestBase(context, "glsl_contant_immutablity", "Test verifies that glsl constants cannot be modified")
8179 {
8180 /* Nothing to be done here */
8181 }
8182
8183 /** Source for given test case and stage
8184 *
8185 * @param test_case_index Index of test case
8186 * @param stage Shader stage
8187 *
8188 * @return Shader source
8189 **/
8190 std::string GLSLContantImmutablityTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
8191 {
8192 static const GLchar* cs = "#version 430 core\n"
8193 "#extension GL_ARB_enhanced_layouts : require\n"
8194 "\n"
8195 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8196 "\n"
8197 "writeonly uniform uimage2D uni_image;\n"
8198 "\n"
8199 "void main()\n"
8200 "{\n"
8201 " uint result = 1u;\n"
8202 " CONSTANT = 3;\n"
8203 "\n"
8204 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
8205 "}\n"
8206 "\n";
8207 static const GLchar* fs = "#version 430 core\n"
8208 "#extension GL_ARB_enhanced_layouts : require\n"
8209 "\n"
8210 "in vec4 gs_fs;\n"
8211 "out vec4 fs_out;\n"
8212 "\n"
8213 "void main()\n"
8214 "{\n"
8215 "ASSIGNMENT"
8216 " fs_out = gs_fs;\n"
8217 "}\n"
8218 "\n";
8219 static const GLchar* gs = "#version 430 core\n"
8220 "#extension GL_ARB_enhanced_layouts : require\n"
8221 "\n"
8222 "layout(points) in;\n"
8223 "layout(triangle_strip, max_vertices = 4) out;\n"
8224 "\n"
8225 "in vec4 tes_gs[];\n"
8226 "out vec4 gs_fs;\n"
8227 "\n"
8228 "void main()\n"
8229 "{\n"
8230 "ASSIGNMENT"
8231 " gs_fs = tes_gs[0];\n"
8232 " gl_Position = vec4(-1, -1, 0, 1);\n"
8233 " EmitVertex();\n"
8234 " gs_fs = tes_gs[0];\n"
8235 " gl_Position = vec4(-1, 1, 0, 1);\n"
8236 " EmitVertex();\n"
8237 " gs_fs = tes_gs[0];\n"
8238 " gl_Position = vec4(1, -1, 0, 1);\n"
8239 " EmitVertex();\n"
8240 " gs_fs = tes_gs[0];\n"
8241 " gl_Position = vec4(1, 1, 0, 1);\n"
8242 " EmitVertex();\n"
8243 "}\n"
8244 "\n";
8245 static const GLchar* tcs = "#version 430 core\n"
8246 "#extension GL_ARB_enhanced_layouts : require\n"
8247 "\n"
8248 "layout(vertices = 1) out;\n"
8249 "\n"
8250 "in vec4 vs_tcs[];\n"
8251 "out vec4 tcs_tes[];\n"
8252 "\n"
8253 "void main()\n"
8254 "{\n"
8255 "\n"
8256 "ASSIGNMENT"
8257 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
8258 "\n"
8259 " gl_TessLevelOuter[0] = 1.0;\n"
8260 " gl_TessLevelOuter[1] = 1.0;\n"
8261 " gl_TessLevelOuter[2] = 1.0;\n"
8262 " gl_TessLevelOuter[3] = 1.0;\n"
8263 " gl_TessLevelInner[0] = 1.0;\n"
8264 " gl_TessLevelInner[1] = 1.0;\n"
8265 "}\n"
8266 "\n";
8267 static const GLchar* tes = "#version 430 core\n"
8268 "#extension GL_ARB_enhanced_layouts : require\n"
8269 "\n"
8270 "layout(isolines, point_mode) in;\n"
8271 "\n"
8272 "in vec4 tcs_tes[];\n"
8273 "out vec4 tes_gs;\n"
8274 "\n"
8275 "void main()\n"
8276 "{\n"
8277 "ASSIGNMENT"
8278 " tes_gs = tcs_tes[0];\n"
8279 "}\n"
8280 "\n";
8281 static const GLchar* vs = "#version 430 core\n"
8282 "#extension GL_ARB_enhanced_layouts : require\n"
8283 "\n"
8284 "in vec4 in_vs;\n"
8285 "out vec4 vs_tcs;\n"
8286 "\n"
8287 "void main()\n"
8288 "{\n"
8289 "ASSIGNMENT"
8290 " vs_tcs = in_vs;\n"
8291 "}\n"
8292 "\n";
8293
8294 std::string source;
8295 testCase& test_case = m_test_cases[test_case_index];
8296
8297 if (Utils::Shader::COMPUTE == test_case.m_stage)
8298 {
8299 size_t position = 0;
8300
8301 source = cs;
8302
8303 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), source);
8304 }
8305 else
8306 {
8307 std::string assignment = " CONSTANT = 3;\n";
8308 size_t position = 0;
8309
8310 switch (stage)
8311 {
8312 case Utils::Shader::FRAGMENT:
8313 source = fs;
8314 break;
8315 case Utils::Shader::GEOMETRY:
8316 source = gs;
8317 break;
8318 case Utils::Shader::TESS_CTRL:
8319 source = tcs;
8320 break;
8321 case Utils::Shader::TESS_EVAL:
8322 source = tes;
8323 break;
8324 case Utils::Shader::VERTEX:
8325 source = vs;
8326 break;
8327 default:
8328 TCU_FAIL("Invalid enum");
8329 }
8330
8331 if (test_case.m_stage == stage)
8332 {
8333 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), assignment);
8334 }
8335 else
8336 {
8337 assignment = "";
8338 }
8339
8340 position = 0;
8341 Utils::replaceToken("ASSIGNMENT", position, assignment.c_str(), source);
8342 }
8343
8344 return source;
8345 }
8346
8347 /** Get description of test case
8348 *
8349 * @param test_case_index Index of test case
8350 *
8351 * @return Constant name
8352 **/
8353 std::string GLSLContantImmutablityTest::getTestCaseName(GLuint test_case_index)
8354 {
8355 std::string result = getConstantName(m_test_cases[test_case_index].m_constant);
8356
8357 return result;
8358 }
8359
8360 /** Get number of test cases
8361 *
8362 * @return Number of test cases
8363 **/
8364 GLuint GLSLContantImmutablityTest::getTestCaseNumber()
8365 {
8366 return static_cast<GLuint>(m_test_cases.size());
8367 }
8368
8369 /** Selects if "compute" stage is relevant for test
8370 *
8371 * @param test_case_index Index of test case
8372 *
8373 * @return true when tested stage is compute
8374 **/
8375 bool GLSLContantImmutablityTest::isComputeRelevant(GLuint test_case_index)
8376 {
8377 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
8378 }
8379
8380 /** Prepare all test cases
8381 *
8382 **/
8383 void GLSLContantImmutablityTest::testInit()
8384 {
8385 for (GLuint constant = 0; constant < CONSTANTS_MAX; ++constant)
8386 {
8387 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
8388 {
8389 testCase test_case = { (CONSTANTS)constant, (Utils::Shader::STAGES)stage };
8390
8391 m_test_cases.push_back(test_case);
8392 }
8393 }
8394 }
8395
8396 /** Get name of glsl constant
8397 *
8398 * @param Constant id
8399 *
8400 * @return Name of constant used in GLSL
8401 **/
8402 const GLchar* GLSLContantImmutablityTest::getConstantName(CONSTANTS constant)
8403 {
8404 const GLchar* name = "";
8405
8406 switch (constant)
8407 {
8408 case GL_ARB_ENHANCED_LAYOUTS:
8409 name = "GL_ARB_enhanced_layouts";
8410 break;
8411 case GL_MAX_XFB:
8412 name = "gl_MaxTransformFeedbackBuffers";
8413 break;
8414 case GL_MAX_XFB_INT_COMP:
8415 name = "gl_MaxTransformFeedbackInterleavedComponents";
8416 break;
8417 default:
8418 TCU_FAIL("Invalid enum");
8419 }
8420
8421 return name;
8422 }
8423
8424 /** Constructor
8425 *
8426 * @param context Test framework context
8427 **/
8428 GLSLContantValuesTest::GLSLContantValuesTest(deqp::Context& context)
8429 : TextureTestBase(context, "glsl_contant_values", "Test verifies values of constant symbols")
8430 {
8431 }
8432
8433 /** Selects if "compute" stage is relevant for test
8434 *
8435 * @param ignored
8436 *
8437 * @return false
8438 **/
8439 bool GLSLContantValuesTest::isComputeRelevant(GLuint /* test_case_index */)
8440 {
8441 return false;
8442 }
8443
8444 /** Prepare code snippet that will verify in and uniform variables
8445 *
8446 * @param ignored
8447 * @param ignored
8448 * @param stage Shader stage
8449 *
8450 * @return Code that verify variables
8451 **/
8452 std::string GLSLContantValuesTest::getVerificationSnippet(GLuint /* test_case_index */,
8453 Utils::ProgramInterface& /* program_interface */,
8454 Utils::Shader::STAGES stage)
8455 {
8456 /* Get constants */
8457 const Functions& gl = m_context.getRenderContext().getFunctions();
8458
8459 GLint max_transform_feedback_buffers = 0;
8460 GLint max_transform_feedback_interleaved_components = 0;
8461
8462 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8463 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8464 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8465 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8466
8467 std::string verification;
8468
8469 if (Utils::Shader::VERTEX == stage)
8470 {
8471 verification = "if (1 != GL_ARB_enhanced_layouts)\n"
8472 " {\n"
8473 " result = 0;\n"
8474 " }\n"
8475 " else if (MAX_TRANSFORM_FEEDBACK_BUFFERS\n"
8476 " != gl_MaxTransformFeedbackBuffers)\n"
8477 " {\n"
8478 " result = 0;\n"
8479 " }\n"
8480 " else if (MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS \n"
8481 " != gl_MaxTransformFeedbackInterleavedComponents)\n"
8482 " {\n"
8483 " result = 0;\n"
8484 " }\n";
8485
8486 size_t position = 0;
8487 GLchar buffer[16];
8488
8489 sprintf(buffer, "%d", max_transform_feedback_buffers);
8490 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_BUFFERS", position, buffer, verification);
8491
8492 sprintf(buffer, "%d", max_transform_feedback_interleaved_components);
8493 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", position, buffer, verification);
8494 }
8495 else
8496 {
8497 verification = "";
8498 }
8499
8500 return verification;
8501 }
8502
8503 /** Constructor
8504 *
8505 * @param context Test framework context
8506 **/
8507 GLSLConstantIntegralExpressionTest::GLSLConstantIntegralExpressionTest(deqp::Context& context)
8508 : TextureTestBase(context, "glsl_constant_integral_expression",
8509 "Test verifies that symbols can be used as constant integral expressions")
8510 {
8511 }
8512
8513 /** Get interface of program
8514 *
8515 * @param ignored
8516 * @param program_interface Interface of program
8517 * @param ignored
8518 **/
8519 void GLSLConstantIntegralExpressionTest::getProgramInterface(GLuint /* test_case_index */,
8520 Utils::ProgramInterface& program_interface,
8521 Utils::VaryingPassthrough& /* varying_passthrough */)
8522 {
8523 /* Get constants */
8524 const Functions& gl = m_context.getRenderContext().getFunctions();
8525
8526 GLint max_transform_feedback_buffers = 0;
8527 GLint max_transform_feedback_interleaved_components = 0;
8528
8529 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8530 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8531 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8532 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8533
8534 GLuint gohan_div = std::max(1, max_transform_feedback_buffers / 16);
8535 GLuint goten_div = std::max(1, max_transform_feedback_interleaved_components / 16);
8536
8537 m_gohan_length = max_transform_feedback_buffers / gohan_div;
8538 m_goten_length = max_transform_feedback_interleaved_components / goten_div;
8539
8540 /* Globals */
8541 std::string globals = "uniform uint goku [GL_ARB_enhanced_layouts / 1];\n"
8542 "uniform uint gohan[gl_MaxTransformFeedbackBuffers / GOHAN_DIV];\n"
8543 "uniform uint goten[gl_MaxTransformFeedbackInterleavedComponents / GOTEN_DIV];\n";
8544
8545 size_t position = 0;
8546 GLchar buffer[16];
8547
8548 sprintf(buffer, "%d", gohan_div);
8549 Utils::replaceToken("GOHAN_DIV", position, buffer, globals);
8550
8551 sprintf(buffer, "%d", goten_div);
8552 Utils::replaceToken("GOTEN_DIV", position, buffer, globals);
8553
8554 program_interface.m_vertex.m_globals = globals;
8555 program_interface.m_tess_ctrl.m_globals = globals;
8556 program_interface.m_tess_eval.m_globals = globals;
8557 program_interface.m_geometry.m_globals = globals;
8558 program_interface.m_fragment.m_globals = globals;
8559 program_interface.m_compute.m_globals = globals;
8560 }
8561
8562 /** Prepare code snippet that will verify in and uniform variables
8563 *
8564 * @param ignored
8565 * @param ignored
8566 * @param ignored
8567 *
8568 * @return Code that verify variables
8569 **/
8570 std::string GLSLConstantIntegralExpressionTest::getVerificationSnippet(GLuint /* test_case_index */,
8571 Utils::ProgramInterface& /* program_interface */,
8572 Utils::Shader::STAGES /* stage */)
8573 {
8574 std::string verification = "{\n"
8575 " uint goku_sum = 0;\n"
8576 " uint gohan_sum = 0;\n"
8577 " uint goten_sum = 0;\n"
8578 "\n"
8579 " for (uint i = 0u; i < goku.length(); ++i)\n"
8580 " {\n"
8581 " goku_sum += goku[i];\n"
8582 " }\n"
8583 "\n"
8584 " for (uint i = 0u; i < gohan.length(); ++i)\n"
8585 " {\n"
8586 " gohan_sum += gohan[i];\n"
8587 " }\n"
8588 "\n"
8589 " for (uint i = 0u; i < goten.length(); ++i)\n"
8590 " {\n"
8591 " goten_sum += goten[i];\n"
8592 " }\n"
8593 "\n"
8594 " if ( (1u != goku_sum) &&\n"
8595 " (EXPECTED_GOHAN_SUMu != gohan_sum) ||\n"
8596 " (EXPECTED_GOTEN_SUMu != goten_sum) )\n"
8597 " {\n"
8598 " result = 0u;\n"
8599 " }\n"
8600 " }\n";
8601
8602 size_t position = 0;
8603 GLchar buffer[16];
8604
8605 sprintf(buffer, "%d", m_gohan_length);
8606 Utils::replaceToken("EXPECTED_GOHAN_SUM", position, buffer, verification);
8607
8608 sprintf(buffer, "%d", m_goten_length);
8609 Utils::replaceToken("EXPECTED_GOTEN_SUM", position, buffer, verification);
8610
8611 return verification;
8612 }
8613
8614 /** Prepare unifroms
8615 *
8616 * @param ignored
8617 * @param ignored
8618 * @param program Program object
8619 * @param ignored
8620 **/
8621 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint /* test_case_index */,
8622 Utils::ProgramInterface& /* program_interface */,
8623 Utils::Program& program, Utils::Buffer& /* cs_buffer */)
8624 {
8625 static const GLuint uniform_data[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
8626
8627 const Functions& gl = m_context.getRenderContext().getFunctions();
8628
8629 GLint goku_location = program.GetUniformLocation("goku");
8630 GLint gohan_location = program.GetUniformLocation("gohan");
8631 GLint goten_location = program.GetUniformLocation("goten");
8632
8633 program.Uniform(gl, Utils::Type::uint, 1 /* count */, goku_location, uniform_data);
8634 program.Uniform(gl, Utils::Type::uint, m_gohan_length, gohan_location, uniform_data);
8635 program.Uniform(gl, Utils::Type::uint, m_goten_length, goten_location, uniform_data);
8636 }
8637
8638 /** Prepare unifroms
8639 *
8640 * @param test_case_index Pass as param to first implemetnation
8641 * @param program_interface Pass as param to first implemetnation
8642 * @param program Pass as param to first implemetnation
8643 * @param ignored
8644 * @param ignored
8645 * @param ignored
8646 * @param ignored
8647 * @param vs_buffer Pass as param to first implemetnation
8648 **/
8649 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint test_case_index,
8650 Utils::ProgramInterface& program_interface,
8651 Utils::Program& program, Utils::Buffer& /* fs_buffer */,
8652 Utils::Buffer& /* gs_buffer */,
8653 Utils::Buffer& /* tcs_buffer */,
8654 Utils::Buffer& /* tes_buffer */, Utils::Buffer& vs_buffer)
8655 {
8656 /* Call first implementation */
8657 prepareUniforms(test_case_index, program_interface, program, vs_buffer);
8658 }
8659
8660 /** Constructor
8661 *
8662 * @param context Test framework context
8663 **/
8664 UniformBlockMemberOffsetAndAlignTest::UniformBlockMemberOffsetAndAlignTest(deqp::Context& context)
8665 : TextureTestBase(context, "uniform_block_member_offset_and_align",
8666 "Test verifies offsets and alignment of uniform buffer members")
8667 {
8668 }
8669
8670 /** Get interface of program
8671 *
8672 * @param test_case_index Test case index
8673 * @param program_interface Interface of program
8674 * @param varying_passthrough Collection of connections between in and out variables
8675 **/
8676 void UniformBlockMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
8677 Utils::ProgramInterface& program_interface,
8678 Utils::VaryingPassthrough& varying_passthrough)
8679 {
8680 std::string globals = "const int basic_size = BASIC_SIZE;\n"
8681 "const int type_align = TYPE_ALIGN;\n"
8682 "const int type_size = TYPE_SIZE;\n";
8683
8684 Utils::Type type = getType(test_case_index);
8685 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
8686 const GLuint base_align = type.GetBaseAlignment(false);
8687 const GLuint array_align = type.GetBaseAlignment(true);
8688 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
8689 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
8690
8691 /* Calculate offsets */
8692 const GLuint first_offset = 0;
8693 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
8694
8695 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
8696
8697 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
8698 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
8699 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8700 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8701 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8702 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
8703
8704 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8705
8706 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
8707 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
8708 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8709 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8710 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8711 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
8712
8713 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8714
8715 /* Prepare data */
8716 const std::vector<GLubyte>& first = type.GenerateData();
8717 const std::vector<GLubyte>& second = type.GenerateData();
8718 const std::vector<GLubyte>& third = type.GenerateData();
8719 const std::vector<GLubyte>& fourth = type.GenerateData();
8720
8721 m_data.resize(eigth_offset + base_stride);
8722 GLubyte* ptr = &m_data[0];
8723 memcpy(ptr + first_offset, &first[0], first.size());
8724 memcpy(ptr + second_offset, &second[0], second.size());
8725 memcpy(ptr + third_offset, &third[0], third.size());
8726 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
8727 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
8728 memcpy(ptr + sixth_offset, &third[0], third.size());
8729 memcpy(ptr + seventh_offset, &second[0], second.size());
8730 memcpy(ptr + eigth_offset, &first[0], first.size());
8731
8732 /* Prepare globals */
8733 size_t position = 0;
8734 GLchar buffer[16];
8735
8736 sprintf(buffer, "%d", basic_size);
8737 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
8738
8739 sprintf(buffer, "%d", type_align);
8740 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
8741
8742 sprintf(buffer, "%d", base_stride);
8743 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
8744
8745 /* Prepare Block */
8746 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
8747
8748 vs_uni_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
8749 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8750 first_offset);
8751
8752 vs_uni_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
8753 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
8754 0 /* n_array_elements */, base_stride, second_offset);
8755
8756 vs_uni_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
8757 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8758 third_offset);
8759
8760 vs_uni_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
8761 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8762 fourth_offset);
8763
8764 vs_uni_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8765 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
8766
8767 vs_uni_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8768 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
8769
8770 vs_uni_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
8771 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8772 eigth_offset);
8773
8774 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
8775
8776 /* Add globals */
8777 vs_si.m_globals = globals;
8778
8779 /* Add uniform BLOCK */
8780 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
8781 static_cast<glw::GLint>(m_data.size()), 0, &m_data[0], m_data.size());
8782
8783 /* */
8784 program_interface.CloneVertexInterface(varying_passthrough);
8785 }
8786
8787 /** Get type name
8788 *
8789 * @param test_case_index Index of test case
8790 *
8791 * @return Name of type test in test_case_index
8792 **/
8793 std::string UniformBlockMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
8794 {
8795 return getTypeName(test_case_index);
8796 }
8797
8798 /** Returns number of types to test
8799 *
8800 * @return Number of types, 34
8801 **/
8802 glw::GLuint UniformBlockMemberOffsetAndAlignTest::getTestCaseNumber()
8803 {
8804 return getTypesNumber();
8805 }
8806
8807 /** Prepare code snippet that will verify in and uniform variables
8808 *
8809 * @param ignored
8810 * @param ignored
8811 * @param stage Shader stage
8812 *
8813 * @return Code that verify variables
8814 **/
8815 std::string UniformBlockMemberOffsetAndAlignTest::getVerificationSnippet(
8816 GLuint /* test_case_index */, Utils::ProgramInterface& /* program_interface */, Utils::Shader::STAGES stage)
8817 {
8818 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
8819 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
8820 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
8821 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
8822 " {\n"
8823 " result = 0;\n"
8824 " }";
8825
8826 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::UNIFORM);
8827
8828 Utils::replaceAllTokens("PREFIX", prefix, verification);
8829
8830 return verification;
8831 }
8832
8833 /** Constructor
8834 *
8835 * @param context Test framework context
8836 **/
8837 UniformBlockLayoutQualifierConflictTest::UniformBlockLayoutQualifierConflictTest(deqp::Context& context)
8838 : NegativeTestBase(
8839 context, "uniform_block_layout_qualifier_conflict",
8840 "Test verifies that std140 is required when offset and/or align qualifiers are used with uniform block")
8841 {
8842 /* Nothing to be done here */
8843 }
8844
8845 /** Source for given test case and stage
8846 *
8847 * @param test_case_index Index of test case
8848 * @param stage Shader stage
8849 *
8850 * @return Shader source
8851 **/
8852 std::string UniformBlockLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index,
8853 Utils::Shader::STAGES stage)
8854 {
8855 static const GLchar* cs = "#version 430 core\n"
8856 "#extension GL_ARB_enhanced_layouts : require\n"
8857 "\n"
8858 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8859 "\n"
8860 "LAYOUTuniform Block {\n"
8861 " layout(offset = 16) vec4 b;\n"
8862 " layout(align = 64) vec4 a;\n"
8863 "} uni_block;\n"
8864 "\n"
8865 "writeonly uniform image2D uni_image;\n"
8866 "\n"
8867 "void main()\n"
8868 "{\n"
8869 " vec4 result = uni_block.b + uni_block.a;\n"
8870 "\n"
8871 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
8872 "}\n"
8873 "\n";
8874 static const GLchar* fs = "#version 430 core\n"
8875 "#extension GL_ARB_enhanced_layouts : require\n"
8876 "\n"
8877 "LAYOUTuniform Block {\n"
8878 " layout(offset = 16) vec4 b;\n"
8879 " layout(align = 64) vec4 a;\n"
8880 "} uni_block;\n"
8881 "\n"
8882 "in vec4 gs_fs;\n"
8883 "out vec4 fs_out;\n"
8884 "\n"
8885 "void main()\n"
8886 "{\n"
8887 " fs_out = gs_fs + uni_block.b + uni_block.a;\n"
8888 "}\n"
8889 "\n";
8890 static const GLchar* gs = "#version 430 core\n"
8891 "#extension GL_ARB_enhanced_layouts : require\n"
8892 "\n"
8893 "layout(points) in;\n"
8894 "layout(triangle_strip, max_vertices = 4) out;\n"
8895 "\n"
8896 "LAYOUTuniform Block {\n"
8897 " layout(offset = 16) vec4 b;\n"
8898 " layout(align = 64) vec4 a;\n"
8899 "} uni_block;\n"
8900 "\n"
8901 "in vec4 tes_gs[];\n"
8902 "out vec4 gs_fs;\n"
8903 "\n"
8904 "void main()\n"
8905 "{\n"
8906 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
8907 " gl_Position = vec4(-1, -1, 0, 1);\n"
8908 " EmitVertex();\n"
8909 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
8910 " gl_Position = vec4(-1, 1, 0, 1);\n"
8911 " EmitVertex();\n"
8912 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
8913 " gl_Position = vec4(1, -1, 0, 1);\n"
8914 " EmitVertex();\n"
8915 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
8916 " gl_Position = vec4(1, 1, 0, 1);\n"
8917 " EmitVertex();\n"
8918 "}\n"
8919 "\n";
8920 static const GLchar* tcs =
8921 "#version 430 core\n"
8922 "#extension GL_ARB_enhanced_layouts : require\n"
8923 "\n"
8924 "layout(vertices = 1) out;\n"
8925 "\n"
8926 "LAYOUTuniform Block {\n"
8927 " layout(offset = 16) vec4 b;\n"
8928 " layout(align = 64) vec4 a;\n"
8929 "} uni_block;\n"
8930 "\n"
8931 "in vec4 vs_tcs[];\n"
8932 "out vec4 tcs_tes[];\n"
8933 "\n"
8934 "void main()\n"
8935 "{\n"
8936 "\n"
8937 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.b + uni_block.a;\n"
8938 "\n"
8939 " gl_TessLevelOuter[0] = 1.0;\n"
8940 " gl_TessLevelOuter[1] = 1.0;\n"
8941 " gl_TessLevelOuter[2] = 1.0;\n"
8942 " gl_TessLevelOuter[3] = 1.0;\n"
8943 " gl_TessLevelInner[0] = 1.0;\n"
8944 " gl_TessLevelInner[1] = 1.0;\n"
8945 "}\n"
8946 "\n";
8947 static const GLchar* tes = "#version 430 core\n"
8948 "#extension GL_ARB_enhanced_layouts : require\n"
8949 "\n"
8950 "layout(isolines, point_mode) in;\n"
8951 "\n"
8952 "LAYOUTuniform Block {\n"
8953 " layout(offset = 16) vec4 b;\n"
8954 " layout(align = 64) vec4 a;\n"
8955 "} uni_block;\n"
8956 "\n"
8957 "in vec4 tcs_tes[];\n"
8958 "out vec4 tes_gs;\n"
8959 "\n"
8960 "void main()\n"
8961 "{\n"
8962 " tes_gs = tcs_tes[0] + uni_block.b + uni_block.a;\n"
8963 "}\n"
8964 "\n";
8965 static const GLchar* vs = "#version 430 core\n"
8966 "#extension GL_ARB_enhanced_layouts : require\n"
8967 "\n"
8968 "LAYOUTuniform Block {\n"
8969 " layout(offset = 16) vec4 b;\n"
8970 " layout(align = 64) vec4 a;\n"
8971 "} uni_block;\n"
8972 "\n"
8973 "in vec4 in_vs;\n"
8974 "out vec4 vs_tcs;\n"
8975 "\n"
8976 "void main()\n"
8977 "{\n"
8978 " vs_tcs = in_vs + uni_block.b + uni_block.a;\n"
8979 "}\n"
8980 "\n";
8981
8982 std::string layout = "";
8983 size_t position = 0;
8984 testCase& test_case = m_test_cases[test_case_index];
8985 const GLchar* qualifier = getQualifierName(test_case.m_qualifier);
8986 std::string source;
8987
8988 if (0 != qualifier[0])
8989 {
8990 size_t layout_position = 0;
8991
8992 layout = "layout (QUALIFIER) ";
8993
8994 Utils::replaceToken("QUALIFIER", layout_position, qualifier, layout);
8995 }
8996
8997 switch (stage)
8998 {
8999 case Utils::Shader::COMPUTE:
9000 source = cs;
9001 break;
9002 case Utils::Shader::FRAGMENT:
9003 source = fs;
9004 break;
9005 case Utils::Shader::GEOMETRY:
9006 source = gs;
9007 break;
9008 case Utils::Shader::TESS_CTRL:
9009 source = tcs;
9010 break;
9011 case Utils::Shader::TESS_EVAL:
9012 source = tes;
9013 break;
9014 case Utils::Shader::VERTEX:
9015 source = vs;
9016 break;
9017 default:
9018 TCU_FAIL("Invalid enum");
9019 }
9020
9021 if (test_case.m_stage == stage)
9022 {
9023 Utils::replaceToken("LAYOUT", position, layout.c_str(), source);
9024 }
9025 else
9026 {
9027 Utils::replaceToken("LAYOUT", position, "layout (std140) ", source);
9028 }
9029
9030 return source;
9031 }
9032
9033 /** Get description of test case
9034 *
9035 * @param test_case_index Index of test case
9036 *
9037 * @return Qualifier name
9038 **/
9039 std::string UniformBlockLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
9040 {
9041 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
9042
9043 return result;
9044 }
9045
9046 /** Get number of test cases
9047 *
9048 * @return Number of test cases
9049 **/
9050 GLuint UniformBlockLayoutQualifierConflictTest::getTestCaseNumber()
9051 {
9052 return static_cast<GLuint>(m_test_cases.size());
9053 }
9054
9055 /** Selects if "compute" stage is relevant for test
9056 *
9057 * @param test_case_index Index of test case
9058 *
9059 * @return true when tested stage is compute
9060 **/
9061 bool UniformBlockLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
9062 {
9063 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9064 }
9065
9066 /** Selects if compilation failure is expected result
9067 *
9068 * @param test_case_index Index of test case
9069 *
9070 * @return false for STD140 cases, true otherwise
9071 **/
9072 bool UniformBlockLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
9073 {
9074 return (STD140 != m_test_cases[test_case_index].m_qualifier);
9075 }
9076
9077 /** Prepare all test cases
9078 *
9079 **/
9080 void UniformBlockLayoutQualifierConflictTest::testInit()
9081 {
9082 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
9083 {
9084 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9085 {
9086 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
9087
9088 m_test_cases.push_back(test_case);
9089 }
9090 }
9091 }
9092
9093 /** Get name of glsl constant
9094 *
9095 * @param Constant id
9096 *
9097 * @return Name of constant used in GLSL
9098 **/
9099 const GLchar* UniformBlockLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
9100 {
9101 const GLchar* name = "";
9102
9103 switch (qualifier)
9104 {
9105 case DEFAULT:
9106 name = "";
9107 break;
9108 case STD140:
9109 name = "std140";
9110 break;
9111 case SHARED:
9112 name = "shared";
9113 break;
9114 case PACKED:
9115 name = "packed";
9116 break;
9117 default:
9118 TCU_FAIL("Invalid enum");
9119 }
9120
9121 return name;
9122 }
9123
9124 /** Constructor
9125 *
9126 * @param context Test framework context
9127 **/
9128 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(deqp::Context& context)
9129 : NegativeTestBase(context, "uniform_block_member_invalid_offset_alignment",
9130 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
9131 {
9132 /* Nothing to be done here */
9133 }
9134
9135 /** Constructor
9136 *
9137 * @param context Test framework context
9138 * @param name Test name
9139 * @param description Test description
9140 **/
9141 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(
9142 deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
9143 : NegativeTestBase(context, name, description)
9144 {
9145 /* Nothing to be done here */
9146 }
9147
9148 /** Source for given test case and stage
9149 *
9150 * @param test_case_index Index of test case
9151 * @param stage Shader stage
9152 *
9153 * @return Shader source
9154 **/
9155 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index,
9156 Utils::Shader::STAGES stage)
9157 {
9158 static const GLchar* cs = "#version 430 core\n"
9159 "#extension GL_ARB_enhanced_layouts : require\n"
9160 "\n"
9161 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9162 "\n"
9163 "layout (std140) uniform Block {\n"
9164 " layout (offset = OFFSET) TYPE member;\n"
9165 "} block;\n"
9166 "\n"
9167 "writeonly uniform image2D uni_image;\n"
9168 "\n"
9169 "void main()\n"
9170 "{\n"
9171 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9172 "\n"
9173 " if (TYPE(1) == block.member)\n"
9174 " {\n"
9175 " result = vec4(1, 1, 1, 1);\n"
9176 " }\n"
9177 "\n"
9178 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9179 "}\n"
9180 "\n";
9181 static const GLchar* fs = "#version 430 core\n"
9182 "#extension GL_ARB_enhanced_layouts : require\n"
9183 "\n"
9184 "in vec4 gs_fs;\n"
9185 "out vec4 fs_out;\n"
9186 "\n"
9187 "void main()\n"
9188 "{\n"
9189 " fs_out = gs_fs;\n"
9190 "}\n"
9191 "\n";
9192 static const GLchar* fs_tested = "#version 430 core\n"
9193 "#extension GL_ARB_enhanced_layouts : require\n"
9194 "\n"
9195 "layout (std140) uniform Block {\n"
9196 " layout (offset = OFFSET) TYPE member;\n"
9197 "} block;\n"
9198 "\n"
9199 "in vec4 gs_fs;\n"
9200 "out vec4 fs_out;\n"
9201 "\n"
9202 "void main()\n"
9203 "{\n"
9204 " if (TYPE(1) == block.member)\n"
9205 " {\n"
9206 " fs_out = vec4(1, 1, 1, 1);\n"
9207 " }\n"
9208 "\n"
9209 " fs_out += gs_fs;\n"
9210 "}\n"
9211 "\n";
9212 static const GLchar* gs = "#version 430 core\n"
9213 "#extension GL_ARB_enhanced_layouts : require\n"
9214 "\n"
9215 "layout(points) in;\n"
9216 "layout(triangle_strip, max_vertices = 4) out;\n"
9217 "\n"
9218 "in vec4 tes_gs[];\n"
9219 "out vec4 gs_fs;\n"
9220 "\n"
9221 "void main()\n"
9222 "{\n"
9223 " gs_fs = tes_gs[0];\n"
9224 " gl_Position = vec4(-1, -1, 0, 1);\n"
9225 " EmitVertex();\n"
9226 " gs_fs = tes_gs[0];\n"
9227 " gl_Position = vec4(-1, 1, 0, 1);\n"
9228 " EmitVertex();\n"
9229 " gs_fs = tes_gs[0];\n"
9230 " gl_Position = vec4(1, -1, 0, 1);\n"
9231 " EmitVertex();\n"
9232 " gs_fs = tes_gs[0];\n"
9233 " gl_Position = vec4(1, 1, 0, 1);\n"
9234 " EmitVertex();\n"
9235 "}\n"
9236 "\n";
9237 static const GLchar* gs_tested = "#version 430 core\n"
9238 "#extension GL_ARB_enhanced_layouts : require\n"
9239 "\n"
9240 "layout(points) in;\n"
9241 "layout(triangle_strip, max_vertices = 4) out;\n"
9242 "\n"
9243 "layout (std140) uniform Block {\n"
9244 " layout (offset = OFFSET) TYPE member;\n"
9245 "} block;\n"
9246 "\n"
9247 "in vec4 tes_gs[];\n"
9248 "out vec4 gs_fs;\n"
9249 "\n"
9250 "void main()\n"
9251 "{\n"
9252 " if (TYPE(1) == block.member)\n"
9253 " {\n"
9254 " gs_fs = vec4(1, 1, 1, 1);\n"
9255 " }\n"
9256 "\n"
9257 " gs_fs += tes_gs[0];\n"
9258 " gl_Position = vec4(-1, -1, 0, 1);\n"
9259 " EmitVertex();\n"
9260 " gs_fs += tes_gs[0];\n"
9261 " gl_Position = vec4(-1, 1, 0, 1);\n"
9262 " EmitVertex();\n"
9263 " gs_fs += tes_gs[0];\n"
9264 " gl_Position = vec4(1, -1, 0, 1);\n"
9265 " EmitVertex();\n"
9266 " gs_fs += tes_gs[0];\n"
9267 " gl_Position = vec4(1, 1, 0, 1);\n"
9268 " EmitVertex();\n"
9269 "}\n"
9270 "\n";
9271 static const GLchar* tcs = "#version 430 core\n"
9272 "#extension GL_ARB_enhanced_layouts : require\n"
9273 "\n"
9274 "layout(vertices = 1) out;\n"
9275 "\n"
9276 "in vec4 vs_tcs[];\n"
9277 "out vec4 tcs_tes[];\n"
9278 "\n"
9279 "void main()\n"
9280 "{\n"
9281 "\n"
9282 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9283 "\n"
9284 " gl_TessLevelOuter[0] = 1.0;\n"
9285 " gl_TessLevelOuter[1] = 1.0;\n"
9286 " gl_TessLevelOuter[2] = 1.0;\n"
9287 " gl_TessLevelOuter[3] = 1.0;\n"
9288 " gl_TessLevelInner[0] = 1.0;\n"
9289 " gl_TessLevelInner[1] = 1.0;\n"
9290 "}\n"
9291 "\n";
9292 static const GLchar* tcs_tested = "#version 430 core\n"
9293 "#extension GL_ARB_enhanced_layouts : require\n"
9294 "\n"
9295 "layout(vertices = 1) out;\n"
9296 "\n"
9297 "layout (std140) uniform Block {\n"
9298 " layout (offset = OFFSET) TYPE member;\n"
9299 "} block;\n"
9300 "\n"
9301 "in vec4 vs_tcs[];\n"
9302 "out vec4 tcs_tes[];\n"
9303 "\n"
9304 "void main()\n"
9305 "{\n"
9306 " if (TYPE(1) == block.member)\n"
9307 " {\n"
9308 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9309 " }\n"
9310 "\n"
9311 "\n"
9312 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9313 "\n"
9314 " gl_TessLevelOuter[0] = 1.0;\n"
9315 " gl_TessLevelOuter[1] = 1.0;\n"
9316 " gl_TessLevelOuter[2] = 1.0;\n"
9317 " gl_TessLevelOuter[3] = 1.0;\n"
9318 " gl_TessLevelInner[0] = 1.0;\n"
9319 " gl_TessLevelInner[1] = 1.0;\n"
9320 "}\n"
9321 "\n";
9322 static const GLchar* tes = "#version 430 core\n"
9323 "#extension GL_ARB_enhanced_layouts : require\n"
9324 "\n"
9325 "layout(isolines, point_mode) in;\n"
9326 "\n"
9327 "in vec4 tcs_tes[];\n"
9328 "out vec4 tes_gs;\n"
9329 "\n"
9330 "void main()\n"
9331 "{\n"
9332 " tes_gs = tcs_tes[0];\n"
9333 "}\n"
9334 "\n";
9335 static const GLchar* tes_tested = "#version 430 core\n"
9336 "#extension GL_ARB_enhanced_layouts : require\n"
9337 "\n"
9338 "layout(isolines, point_mode) in;\n"
9339 "\n"
9340 "layout (std140) uniform Block {\n"
9341 " layout (offset = OFFSET) TYPE member;\n"
9342 "} block;\n"
9343 "\n"
9344 "in vec4 tcs_tes[];\n"
9345 "out vec4 tes_gs;\n"
9346 "\n"
9347 "void main()\n"
9348 "{\n"
9349 " if (TYPE(1) == block.member)\n"
9350 " {\n"
9351 " tes_gs = vec4(1, 1, 1, 1);\n"
9352 " }\n"
9353 "\n"
9354 " tes_gs += tcs_tes[0];\n"
9355 "}\n"
9356 "\n";
9357 static const GLchar* vs = "#version 430 core\n"
9358 "#extension GL_ARB_enhanced_layouts : require\n"
9359 "\n"
9360 "in vec4 in_vs;\n"
9361 "out vec4 vs_tcs;\n"
9362 "\n"
9363 "void main()\n"
9364 "{\n"
9365 " vs_tcs = in_vs;\n"
9366 "}\n"
9367 "\n";
9368 static const GLchar* vs_tested = "#version 430 core\n"
9369 "#extension GL_ARB_enhanced_layouts : require\n"
9370 "\n"
9371 "layout (std140) uniform Block {\n"
9372 " layout (offset = OFFSET) TYPE member;\n"
9373 "} block;\n"
9374 "\n"
9375 "in vec4 in_vs;\n"
9376 "out vec4 vs_tcs;\n"
9377 "\n"
9378 "void main()\n"
9379 "{\n"
9380 " if (TYPE(1) == block.member)\n"
9381 " {\n"
9382 " vs_tcs = vec4(1, 1, 1, 1);\n"
9383 " }\n"
9384 "\n"
9385 " vs_tcs += in_vs;\n"
9386 "}\n"
9387 "\n";
9388
9389 std::string source;
9390 testCase& test_case = m_test_cases[test_case_index];
9391
9392 if (test_case.m_stage == stage)
9393 {
9394 GLchar buffer[16];
9395 const GLuint offset = test_case.m_offset;
9396 size_t position = 0;
9397 const Utils::Type& type = test_case.m_type;
9398 const GLchar* type_name = type.GetGLSLTypeName();
9399
9400 sprintf(buffer, "%d", offset);
9401
9402 switch (stage)
9403 {
9404 case Utils::Shader::COMPUTE:
9405 source = cs;
9406 break;
9407 case Utils::Shader::FRAGMENT:
9408 source = fs_tested;
9409 break;
9410 case Utils::Shader::GEOMETRY:
9411 source = gs_tested;
9412 break;
9413 case Utils::Shader::TESS_CTRL:
9414 source = tcs_tested;
9415 break;
9416 case Utils::Shader::TESS_EVAL:
9417 source = tes_tested;
9418 break;
9419 case Utils::Shader::VERTEX:
9420 source = vs_tested;
9421 break;
9422 default:
9423 TCU_FAIL("Invalid enum");
9424 }
9425
9426 Utils::replaceToken("OFFSET", position, buffer, source);
9427 Utils::replaceToken("TYPE", position, type_name, source);
9428 Utils::replaceToken("TYPE", position, type_name, source);
9429 }
9430 else
9431 {
9432 switch (stage)
9433 {
9434 case Utils::Shader::FRAGMENT:
9435 source = fs;
9436 break;
9437 case Utils::Shader::GEOMETRY:
9438 source = gs;
9439 break;
9440 case Utils::Shader::TESS_CTRL:
9441 source = tcs;
9442 break;
9443 case Utils::Shader::TESS_EVAL:
9444 source = tes;
9445 break;
9446 case Utils::Shader::VERTEX:
9447 source = vs;
9448 break;
9449 default:
9450 TCU_FAIL("Invalid enum");
9451 }
9452 }
9453
9454 return source;
9455 }
9456
9457 /** Get description of test case
9458 *
9459 * @param test_case_index Index of test case
9460 *
9461 * @return Type name and offset
9462 **/
9463 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
9464 {
9465 std::stringstream stream;
9466 testCase& test_case = m_test_cases[test_case_index];
9467
9468 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
9469
9470 return stream.str();
9471 }
9472
9473 /** Get number of test cases
9474 *
9475 * @return Number of test cases
9476 **/
9477 GLuint UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseNumber()
9478 {
9479 return static_cast<GLuint>(m_test_cases.size());
9480 }
9481
9482 /** Get the maximum size for an uniform block
9483 *
9484 * @return The maximum size in basic machine units of a uniform block.
9485 **/
9486 GLint UniformBlockMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
9487 {
9488 const Functions& gl = m_context.getRenderContext().getFunctions();
9489 GLint max_size = 0;
9490
9491 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size);
9492 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
9493
9494 return max_size;
9495 }
9496
9497 /** Selects if "compute" stage is relevant for test
9498 *
9499 * @param test_case_index Index of test case
9500 *
9501 * @return true when tested stage is compute
9502 **/
9503 bool UniformBlockMemberInvalidOffsetAlignmentTest::isComputeRelevant(GLuint test_case_index)
9504 {
9505 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9506 }
9507
9508 /** Selects if compilation failure is expected result
9509 *
9510 * @param test_case_index Index of test case
9511 *
9512 * @return should_fail field from testCase
9513 **/
9514 bool UniformBlockMemberInvalidOffsetAlignmentTest::isFailureExpected(GLuint test_case_index)
9515 {
9516 return m_test_cases[test_case_index].m_should_fail;
9517 }
9518
9519 /** Checks if stage is supported
9520 *
9521 * @param stage ignored
9522 *
9523 * @return true
9524 **/
9525 bool UniformBlockMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9526 {
9527 return true;
9528 }
9529
9530 /** Prepare all test cases
9531 *
9532 **/
9533 void UniformBlockMemberInvalidOffsetAlignmentTest::testInit()
9534 {
9535 const GLuint n_types = getTypesNumber();
9536 bool stage_support[Utils::Shader::STAGE_MAX];
9537
9538 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9539 {
9540 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9541 }
9542
9543 for (GLuint i = 0; i < n_types; ++i)
9544 {
9545 const Utils::Type& type = getType(i);
9546 const GLuint alignment = type.GetBaseAlignment(false);
9547 const GLuint type_size = type.GetSize(true);
9548 const GLuint sec_to_end = getMaxBlockSize() - 2 * type_size;
9549
9550 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9551 {
9552 if (false == stage_support[stage])
9553 {
9554 continue;
9555 }
9556
9557 for (GLuint offset = 0; offset <= type_size; ++offset)
9558 {
9559 const GLuint modulo = offset % alignment;
9560 const bool is_aligned = (0 == modulo) ? true : false;
9561 const bool should_fail = !is_aligned;
9562
9563 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9564
9565 m_test_cases.push_back(test_case);
9566 }
9567
9568 for (GLuint offset = sec_to_end; offset <= sec_to_end + type_size; ++offset)
9569 {
9570 const GLuint modulo = offset % alignment;
9571 const bool is_aligned = (0 == modulo) ? true : false;
9572 const bool should_fail = !is_aligned;
9573
9574 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9575
9576 m_test_cases.push_back(test_case);
9577 }
9578 }
9579 }
9580 }
9581
9582 /** Constructor
9583 *
9584 * @param context Test framework context
9585 **/
9586 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context)
9587 : NegativeTestBase(context, "uniform_block_member_overlapping_offsets",
9588 "Test verifies that overlapping offsets qualifiers cause compilation failure")
9589 {
9590 /* Nothing to be done here */
9591 }
9592
9593 /** Constructor
9594 *
9595 * @param context Test framework context
9596 * @param name Test name
9597 * @param description Test description
9598 **/
9599 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context,
9600 const glw::GLchar* name,
9601 const glw::GLchar* description)
9602 : NegativeTestBase(context, name, description)
9603 {
9604 /* Nothing to be done here */
9605 }
9606
9607 /** Source for given test case and stage
9608 *
9609 * @param test_case_index Index of test case
9610 * @param stage Shader stage
9611 *
9612 * @return Shader source
9613 **/
9614 std::string UniformBlockMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index,
9615 Utils::Shader::STAGES stage)
9616 {
9617 static const GLchar* cs = "#version 430 core\n"
9618 "#extension GL_ARB_enhanced_layouts : require\n"
9619 "\n"
9620 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9621 "\n"
9622 "layout (std140) uniform Block {\n"
9623 " layout (offset = B_OFFSET) B_TYPE b;\n"
9624 " layout (offset = A_OFFSET) A_TYPE a;\n"
9625 "} block;\n"
9626 "\n"
9627 "writeonly uniform image2D uni_image;\n"
9628 "\n"
9629 "void main()\n"
9630 "{\n"
9631 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9632 "\n"
9633 " if ((B_TYPE(1) == block.b) ||\n"
9634 " (A_TYPE(0) == block.a) )\n"
9635 " {\n"
9636 " result = vec4(1, 1, 1, 1);\n"
9637 " }\n"
9638 "\n"
9639 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9640 "}\n"
9641 "\n";
9642 static const GLchar* fs = "#version 430 core\n"
9643 "#extension GL_ARB_enhanced_layouts : require\n"
9644 "\n"
9645 "in vec4 gs_fs;\n"
9646 "out vec4 fs_out;\n"
9647 "\n"
9648 "void main()\n"
9649 "{\n"
9650 " fs_out = gs_fs;\n"
9651 "}\n"
9652 "\n";
9653 static const GLchar* fs_tested = "#version 430 core\n"
9654 "#extension GL_ARB_enhanced_layouts : require\n"
9655 "\n"
9656 "layout (std140) uniform Block {\n"
9657 " layout (offset = B_OFFSET) B_TYPE b;\n"
9658 " layout (offset = A_OFFSET) A_TYPE a;\n"
9659 "} block;\n"
9660 "\n"
9661 "in vec4 gs_fs;\n"
9662 "out vec4 fs_out;\n"
9663 "\n"
9664 "void main()\n"
9665 "{\n"
9666 " if ((B_TYPE(1) == block.b) ||\n"
9667 " (A_TYPE(0) == block.a) )\n"
9668 " {\n"
9669 " fs_out = vec4(1, 1, 1, 1);\n"
9670 " }\n"
9671 "\n"
9672 " fs_out += gs_fs;\n"
9673 "}\n"
9674 "\n";
9675 static const GLchar* gs = "#version 430 core\n"
9676 "#extension GL_ARB_enhanced_layouts : require\n"
9677 "\n"
9678 "layout(points) in;\n"
9679 "layout(triangle_strip, max_vertices = 4) out;\n"
9680 "\n"
9681 "in vec4 tes_gs[];\n"
9682 "out vec4 gs_fs;\n"
9683 "\n"
9684 "void main()\n"
9685 "{\n"
9686 " gs_fs = tes_gs[0];\n"
9687 " gl_Position = vec4(-1, -1, 0, 1);\n"
9688 " EmitVertex();\n"
9689 " gs_fs = tes_gs[0];\n"
9690 " gl_Position = vec4(-1, 1, 0, 1);\n"
9691 " EmitVertex();\n"
9692 " gs_fs = tes_gs[0];\n"
9693 " gl_Position = vec4(1, -1, 0, 1);\n"
9694 " EmitVertex();\n"
9695 " gs_fs = tes_gs[0];\n"
9696 " gl_Position = vec4(1, 1, 0, 1);\n"
9697 " EmitVertex();\n"
9698 "}\n"
9699 "\n";
9700 static const GLchar* gs_tested = "#version 430 core\n"
9701 "#extension GL_ARB_enhanced_layouts : require\n"
9702 "\n"
9703 "layout(points) in;\n"
9704 "layout(triangle_strip, max_vertices = 4) out;\n"
9705 "\n"
9706 "layout (std140) uniform Block {\n"
9707 " layout (offset = B_OFFSET) B_TYPE b;\n"
9708 " layout (offset = A_OFFSET) A_TYPE a;\n"
9709 "} block;\n"
9710 "\n"
9711 "in vec4 tes_gs[];\n"
9712 "out vec4 gs_fs;\n"
9713 "\n"
9714 "void main()\n"
9715 "{\n"
9716 " if ((B_TYPE(1) == block.b) ||\n"
9717 " (A_TYPE(0) == block.a) )\n"
9718 " {\n"
9719 " gs_fs = vec4(1, 1, 1, 1);\n"
9720 " }\n"
9721 "\n"
9722 " gs_fs += tes_gs[0];\n"
9723 " gl_Position = vec4(-1, -1, 0, 1);\n"
9724 " EmitVertex();\n"
9725 " gs_fs += tes_gs[0];\n"
9726 " gl_Position = vec4(-1, 1, 0, 1);\n"
9727 " EmitVertex();\n"
9728 " gs_fs += tes_gs[0];\n"
9729 " gl_Position = vec4(1, -1, 0, 1);\n"
9730 " EmitVertex();\n"
9731 " gs_fs += tes_gs[0];\n"
9732 " gl_Position = vec4(1, 1, 0, 1);\n"
9733 " EmitVertex();\n"
9734 "}\n"
9735 "\n";
9736 static const GLchar* tcs = "#version 430 core\n"
9737 "#extension GL_ARB_enhanced_layouts : require\n"
9738 "\n"
9739 "layout(vertices = 1) out;\n"
9740 "\n"
9741 "in vec4 vs_tcs[];\n"
9742 "out vec4 tcs_tes[];\n"
9743 "\n"
9744 "void main()\n"
9745 "{\n"
9746 "\n"
9747 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9748 "\n"
9749 " gl_TessLevelOuter[0] = 1.0;\n"
9750 " gl_TessLevelOuter[1] = 1.0;\n"
9751 " gl_TessLevelOuter[2] = 1.0;\n"
9752 " gl_TessLevelOuter[3] = 1.0;\n"
9753 " gl_TessLevelInner[0] = 1.0;\n"
9754 " gl_TessLevelInner[1] = 1.0;\n"
9755 "}\n"
9756 "\n";
9757 static const GLchar* tcs_tested = "#version 430 core\n"
9758 "#extension GL_ARB_enhanced_layouts : require\n"
9759 "\n"
9760 "layout(vertices = 1) out;\n"
9761 "\n"
9762 "layout (std140) uniform Block {\n"
9763 " layout (offset = B_OFFSET) B_TYPE b;\n"
9764 " layout (offset = A_OFFSET) A_TYPE a;\n"
9765 "} block;\n"
9766 "\n"
9767 "in vec4 vs_tcs[];\n"
9768 "out vec4 tcs_tes[];\n"
9769 "\n"
9770 "void main()\n"
9771 "{\n"
9772 " if ((B_TYPE(1) == block.b) ||\n"
9773 " (A_TYPE(0) == block.a) )\n"
9774 " {\n"
9775 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9776 " }\n"
9777 "\n"
9778 "\n"
9779 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9780 "\n"
9781 " gl_TessLevelOuter[0] = 1.0;\n"
9782 " gl_TessLevelOuter[1] = 1.0;\n"
9783 " gl_TessLevelOuter[2] = 1.0;\n"
9784 " gl_TessLevelOuter[3] = 1.0;\n"
9785 " gl_TessLevelInner[0] = 1.0;\n"
9786 " gl_TessLevelInner[1] = 1.0;\n"
9787 "}\n"
9788 "\n";
9789 static const GLchar* tes = "#version 430 core\n"
9790 "#extension GL_ARB_enhanced_layouts : require\n"
9791 "\n"
9792 "layout(isolines, point_mode) in;\n"
9793 "\n"
9794 "in vec4 tcs_tes[];\n"
9795 "out vec4 tes_gs;\n"
9796 "\n"
9797 "void main()\n"
9798 "{\n"
9799 " tes_gs = tcs_tes[0];\n"
9800 "}\n"
9801 "\n";
9802 static const GLchar* tes_tested = "#version 430 core\n"
9803 "#extension GL_ARB_enhanced_layouts : require\n"
9804 "\n"
9805 "layout(isolines, point_mode) in;\n"
9806 "\n"
9807 "layout (std140) uniform Block {\n"
9808 " layout (offset = B_OFFSET) B_TYPE b;\n"
9809 " layout (offset = A_OFFSET) A_TYPE a;\n"
9810 "} block;\n"
9811 "\n"
9812 "in vec4 tcs_tes[];\n"
9813 "out vec4 tes_gs;\n"
9814 "\n"
9815 "void main()\n"
9816 "{\n"
9817 " if ((B_TYPE(1) == block.b) ||\n"
9818 " (A_TYPE(0) == block.a) )\n"
9819 " {\n"
9820 " tes_gs = vec4(1, 1, 1, 1);\n"
9821 " }\n"
9822 "\n"
9823 " tes_gs += tcs_tes[0];\n"
9824 "}\n"
9825 "\n";
9826 static const GLchar* vs = "#version 430 core\n"
9827 "#extension GL_ARB_enhanced_layouts : require\n"
9828 "\n"
9829 "in vec4 in_vs;\n"
9830 "out vec4 vs_tcs;\n"
9831 "\n"
9832 "void main()\n"
9833 "{\n"
9834 " vs_tcs = in_vs;\n"
9835 "}\n"
9836 "\n";
9837 static const GLchar* vs_tested = "#version 430 core\n"
9838 "#extension GL_ARB_enhanced_layouts : require\n"
9839 "\n"
9840 "layout (std140) uniform Block {\n"
9841 " layout (offset = B_OFFSET) B_TYPE b;\n"
9842 " layout (offset = A_OFFSET) A_TYPE a;\n"
9843 "} block;\n"
9844 "\n"
9845 "in vec4 in_vs;\n"
9846 "out vec4 vs_tcs;\n"
9847 "\n"
9848 "void main()\n"
9849 "{\n"
9850 " if ((B_TYPE(1) == block.b) ||\n"
9851 " (A_TYPE(0) == block.a) )\n"
9852 " {\n"
9853 " vs_tcs = vec4(1, 1, 1, 1);\n"
9854 " }\n"
9855 "\n"
9856 " vs_tcs += in_vs;\n"
9857 "}\n"
9858 "\n";
9859
9860 std::string source;
9861 testCase& test_case = m_test_cases[test_case_index];
9862
9863 if (test_case.m_stage == stage)
9864 {
9865 GLchar buffer[16];
9866 const GLuint b_offset = test_case.m_b_offset;
9867 const Utils::Type& b_type = test_case.m_b_type;
9868 const GLchar* b_type_name = b_type.GetGLSLTypeName();
9869 const GLuint a_offset = test_case.m_a_offset;
9870 const Utils::Type& a_type = test_case.m_a_type;
9871 const GLchar* a_type_name = a_type.GetGLSLTypeName();
9872 size_t position = 0;
9873
9874 switch (stage)
9875 {
9876 case Utils::Shader::COMPUTE:
9877 source = cs;
9878 break;
9879 case Utils::Shader::FRAGMENT:
9880 source = fs_tested;
9881 break;
9882 case Utils::Shader::GEOMETRY:
9883 source = gs_tested;
9884 break;
9885 case Utils::Shader::TESS_CTRL:
9886 source = tcs_tested;
9887 break;
9888 case Utils::Shader::TESS_EVAL:
9889 source = tes_tested;
9890 break;
9891 case Utils::Shader::VERTEX:
9892 source = vs_tested;
9893 break;
9894 default:
9895 TCU_FAIL("Invalid enum");
9896 }
9897
9898 sprintf(buffer, "%d", b_offset);
9899 Utils::replaceToken("B_OFFSET", position, buffer, source);
9900 Utils::replaceToken("B_TYPE", position, b_type_name, source);
9901 sprintf(buffer, "%d", a_offset);
9902 Utils::replaceToken("A_OFFSET", position, buffer, source);
9903 Utils::replaceToken("A_TYPE", position, a_type_name, source);
9904 Utils::replaceToken("B_TYPE", position, b_type_name, source);
9905 Utils::replaceToken("A_TYPE", position, a_type_name, source);
9906 }
9907 else
9908 {
9909 switch (stage)
9910 {
9911 case Utils::Shader::FRAGMENT:
9912 source = fs;
9913 break;
9914 case Utils::Shader::GEOMETRY:
9915 source = gs;
9916 break;
9917 case Utils::Shader::TESS_CTRL:
9918 source = tcs;
9919 break;
9920 case Utils::Shader::TESS_EVAL:
9921 source = tes;
9922 break;
9923 case Utils::Shader::VERTEX:
9924 source = vs;
9925 break;
9926 default:
9927 TCU_FAIL("Invalid enum");
9928 }
9929 }
9930
9931 return source;
9932 }
9933
9934 /** Get description of test case
9935 *
9936 * @param test_case_index Index of test case
9937 *
9938 * @return Type name and offset
9939 **/
9940 std::string UniformBlockMemberOverlappingOffsetsTest::getTestCaseName(GLuint test_case_index)
9941 {
9942 std::stringstream stream;
9943 testCase& test_case = m_test_cases[test_case_index];
9944
9945 stream << "Type: " << test_case.m_b_type.GetGLSLTypeName() << ", offset: " << test_case.m_b_offset
9946 << ". Type: " << test_case.m_a_type.GetGLSLTypeName() << ", offset: " << test_case.m_a_offset;
9947
9948 return stream.str();
9949 }
9950
9951 /** Get number of test cases
9952 *
9953 * @return Number of test cases
9954 **/
9955 GLuint UniformBlockMemberOverlappingOffsetsTest::getTestCaseNumber()
9956 {
9957 return static_cast<GLuint>(m_test_cases.size());
9958 }
9959
9960 /** Selects if "compute" stage is relevant for test
9961 *
9962 * @param test_case_index Index of test case
9963 *
9964 * @return true when tested stage is compute
9965 **/
9966 bool UniformBlockMemberOverlappingOffsetsTest::isComputeRelevant(GLuint test_case_index)
9967 {
9968 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9969 }
9970
9971 /** Checks if stage is supported
9972 *
9973 * @param stage ignored
9974 *
9975 * @return true
9976 **/
9977 bool UniformBlockMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9978 {
9979 return true;
9980 }
9981
9982 /** Prepare all test cases
9983 *
9984 **/
9985 void UniformBlockMemberOverlappingOffsetsTest::testInit()
9986 {
9987 const GLuint n_types = getTypesNumber();
9988 bool stage_support[Utils::Shader::STAGE_MAX];
9989
9990 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9991 {
9992 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9993 }
9994
9995 for (GLuint i = 0; i < n_types; ++i)
9996 {
9997 const Utils::Type& b_type = getType(i);
9998 const GLuint b_size = b_type.GetActualAlignment(1 /* align */, false /* is_array*/);
9999
10000 for (GLuint j = 0; j < n_types; ++j)
10001 {
10002 const Utils::Type& a_type = getType(j);
10003 const GLuint a_align = a_type.GetBaseAlignment(false);
10004 const GLuint a_size = a_type.GetActualAlignment(1 /* align */, false /* is_array*/);
10005
10006 const GLuint b_offset = lcm(b_size, a_size);
10007 const GLuint a_after_start = b_offset + 1;
10008 const GLuint a_after_off = a_type.GetActualOffset(a_after_start, a_size);
10009 const GLuint a_before_start = b_offset - a_align;
10010 const GLuint a_before_off = a_type.GetActualOffset(a_before_start, a_size);
10011
10012 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10013 {
10014 if (false == stage_support[stage])
10015 {
10016 continue;
10017 }
10018
10019 if ((b_offset > a_before_off) && (b_offset < a_before_off + a_size))
10020 {
10021 testCase test_case = { b_offset, b_type, a_before_off, a_type,
10022 (Utils::Shader::STAGES)stage };
10023
10024 m_test_cases.push_back(test_case);
10025 }
10026
10027 if ((b_offset < a_after_off) && (b_offset + b_size > a_after_off))
10028 {
10029 testCase test_case = { b_offset, b_type, a_after_off, a_type,
10030 (Utils::Shader::STAGES)stage };
10031
10032 m_test_cases.push_back(test_case);
10033 }
10034
10035 /* b offset, should be fine for both types */
10036 testCase test_case = { b_offset, b_type, b_offset, a_type, (Utils::Shader::STAGES)stage };
10037
10038 m_test_cases.push_back(test_case);
10039 }
10040 }
10041 }
10042 }
10043
10044 /** Find greatest common divisor for a and b
10045 *
10046 * @param a A argument
10047 * @param b B argument
10048 *
10049 * @return Found gcd value
10050 **/
10051 GLuint UniformBlockMemberOverlappingOffsetsTest::gcd(GLuint a, GLuint b)
10052 {
10053 if ((0 != a) && (0 == b))
10054 {
10055 return a;
10056 }
10057 else
10058 {
10059 GLuint greater = std::max(a, b);
10060 GLuint lesser = std::min(a, b);
10061
10062 return gcd(lesser, greater % lesser);
10063 }
10064 }
10065
10066 /** Find lowest common multiple for a and b
10067 *
10068 * @param a A argument
10069 * @param b B argument
10070 *
10071 * @return Found gcd value
10072 **/
10073 GLuint UniformBlockMemberOverlappingOffsetsTest::lcm(GLuint a, GLuint b)
10074 {
10075 return (a * b) / gcd(a, b);
10076 }
10077
10078 /** Constructor
10079 *
10080 * @param context Test framework context
10081 **/
10082 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context)
10083 : NegativeTestBase(context, "uniform_block_member_align_non_power_of_2",
10084 "Test verifies that align qualifier requires value that is a power of 2")
10085 {
10086 /* Nothing to be done here */
10087 }
10088
10089 /** Constructor
10090 *
10091 * @param context Test framework context
10092 * @param name Test name
10093 * @param description Test description
10094 **/
10095 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context,
10096 const glw::GLchar* name,
10097 const glw::GLchar* description)
10098 : NegativeTestBase(context, name, description)
10099 {
10100 /* Nothing to be done here */
10101 }
10102
10103 /** Source for given test case and stage
10104 *
10105 * @param test_case_index Index of test case
10106 * @param stage Shader stage
10107 *
10108 * @return Shader source
10109 **/
10110 std::string UniformBlockMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10111 {
10112 static const GLchar* cs = "#version 430 core\n"
10113 "#extension GL_ARB_enhanced_layouts : require\n"
10114 "\n"
10115 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10116 "\n"
10117 "layout (std140) uniform Block {\n"
10118 " vec4 b;\n"
10119 " layout (align = ALIGN) TYPE a;\n"
10120 "} block;\n"
10121 "\n"
10122 "writeonly uniform image2D uni_image;\n"
10123 "\n"
10124 "void main()\n"
10125 "{\n"
10126 " vec4 result = vec4(1, 0, 0.5, 1);\n"
10127 "\n"
10128 " if (TYPE(0) == block.a)\n"
10129 " {\n"
10130 " result = vec4(1, 1, 1, 1) - block.b;\n"
10131 " }\n"
10132 "\n"
10133 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10134 "}\n"
10135 "\n";
10136 static const GLchar* fs = "#version 430 core\n"
10137 "#extension GL_ARB_enhanced_layouts : require\n"
10138 "\n"
10139 "in vec4 gs_fs;\n"
10140 "out vec4 fs_out;\n"
10141 "\n"
10142 "void main()\n"
10143 "{\n"
10144 " fs_out = gs_fs;\n"
10145 "}\n"
10146 "\n";
10147 static const GLchar* fs_tested = "#version 430 core\n"
10148 "#extension GL_ARB_enhanced_layouts : require\n"
10149 "\n"
10150 "layout (std140) uniform Block {\n"
10151 " vec4 b;\n"
10152 " layout (align = ALIGN) TYPE a;\n"
10153 "} block;\n"
10154 "\n"
10155 "in vec4 gs_fs;\n"
10156 "out vec4 fs_out;\n"
10157 "\n"
10158 "void main()\n"
10159 "{\n"
10160 " if (TYPE(0) == block.a)\n"
10161 " {\n"
10162 " fs_out = block.b;\n"
10163 " }\n"
10164 "\n"
10165 " fs_out += gs_fs;\n"
10166 "}\n"
10167 "\n";
10168 static const GLchar* gs = "#version 430 core\n"
10169 "#extension GL_ARB_enhanced_layouts : require\n"
10170 "\n"
10171 "layout(points) in;\n"
10172 "layout(triangle_strip, max_vertices = 4) out;\n"
10173 "\n"
10174 "in vec4 tes_gs[];\n"
10175 "out vec4 gs_fs;\n"
10176 "\n"
10177 "void main()\n"
10178 "{\n"
10179 " gs_fs = tes_gs[0];\n"
10180 " gl_Position = vec4(-1, -1, 0, 1);\n"
10181 " EmitVertex();\n"
10182 " gs_fs = tes_gs[0];\n"
10183 " gl_Position = vec4(-1, 1, 0, 1);\n"
10184 " EmitVertex();\n"
10185 " gs_fs = tes_gs[0];\n"
10186 " gl_Position = vec4(1, -1, 0, 1);\n"
10187 " EmitVertex();\n"
10188 " gs_fs = tes_gs[0];\n"
10189 " gl_Position = vec4(1, 1, 0, 1);\n"
10190 " EmitVertex();\n"
10191 "}\n"
10192 "\n";
10193 static const GLchar* gs_tested = "#version 430 core\n"
10194 "#extension GL_ARB_enhanced_layouts : require\n"
10195 "\n"
10196 "layout(points) in;\n"
10197 "layout(triangle_strip, max_vertices = 4) out;\n"
10198 "\n"
10199 "layout (std140) uniform Block {\n"
10200 " vec4 b;\n"
10201 " layout (align = ALIGN) TYPE a;\n"
10202 "} block;\n"
10203 "\n"
10204 "in vec4 tes_gs[];\n"
10205 "out vec4 gs_fs;\n"
10206 "\n"
10207 "void main()\n"
10208 "{\n"
10209 " if (TYPE(0) == block.a)\n"
10210 " {\n"
10211 " gs_fs = block.b;\n"
10212 " }\n"
10213 "\n"
10214 " gs_fs += tes_gs[0];\n"
10215 " gl_Position = vec4(-1, -1, 0, 1);\n"
10216 " EmitVertex();\n"
10217 " gs_fs += tes_gs[0];\n"
10218 " gl_Position = vec4(-1, 1, 0, 1);\n"
10219 " EmitVertex();\n"
10220 " gs_fs += tes_gs[0];\n"
10221 " gl_Position = vec4(1, -1, 0, 1);\n"
10222 " EmitVertex();\n"
10223 " gs_fs += tes_gs[0];\n"
10224 " gl_Position = vec4(1, 1, 0, 1);\n"
10225 " EmitVertex();\n"
10226 "}\n"
10227 "\n";
10228 static const GLchar* tcs = "#version 430 core\n"
10229 "#extension GL_ARB_enhanced_layouts : require\n"
10230 "\n"
10231 "layout(vertices = 1) out;\n"
10232 "\n"
10233 "in vec4 vs_tcs[];\n"
10234 "out vec4 tcs_tes[];\n"
10235 "\n"
10236 "void main()\n"
10237 "{\n"
10238 "\n"
10239 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
10240 "\n"
10241 " gl_TessLevelOuter[0] = 1.0;\n"
10242 " gl_TessLevelOuter[1] = 1.0;\n"
10243 " gl_TessLevelOuter[2] = 1.0;\n"
10244 " gl_TessLevelOuter[3] = 1.0;\n"
10245 " gl_TessLevelInner[0] = 1.0;\n"
10246 " gl_TessLevelInner[1] = 1.0;\n"
10247 "}\n"
10248 "\n";
10249 static const GLchar* tcs_tested = "#version 430 core\n"
10250 "#extension GL_ARB_enhanced_layouts : require\n"
10251 "\n"
10252 "layout(vertices = 1) out;\n"
10253 "\n"
10254 "layout (std140) uniform Block {\n"
10255 " vec4 b;\n"
10256 " layout (align = ALIGN) TYPE a;\n"
10257 "} block;\n"
10258 "\n"
10259 "in vec4 vs_tcs[];\n"
10260 "out vec4 tcs_tes[];\n"
10261 "\n"
10262 "void main()\n"
10263 "{\n"
10264 " if (TYPE(0) == block.a)\n"
10265 " {\n"
10266 " tcs_tes[gl_InvocationID] = block.b;\n"
10267 " }\n"
10268 "\n"
10269 "\n"
10270 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
10271 "\n"
10272 " gl_TessLevelOuter[0] = 1.0;\n"
10273 " gl_TessLevelOuter[1] = 1.0;\n"
10274 " gl_TessLevelOuter[2] = 1.0;\n"
10275 " gl_TessLevelOuter[3] = 1.0;\n"
10276 " gl_TessLevelInner[0] = 1.0;\n"
10277 " gl_TessLevelInner[1] = 1.0;\n"
10278 "}\n"
10279 "\n";
10280 static const GLchar* tes = "#version 430 core\n"
10281 "#extension GL_ARB_enhanced_layouts : require\n"
10282 "\n"
10283 "layout(isolines, point_mode) in;\n"
10284 "\n"
10285 "in vec4 tcs_tes[];\n"
10286 "out vec4 tes_gs;\n"
10287 "\n"
10288 "void main()\n"
10289 "{\n"
10290 " tes_gs = tcs_tes[0];\n"
10291 "}\n"
10292 "\n";
10293 static const GLchar* tes_tested = "#version 430 core\n"
10294 "#extension GL_ARB_enhanced_layouts : require\n"
10295 "\n"
10296 "layout(isolines, point_mode) in;\n"
10297 "\n"
10298 "layout (std140) uniform Block {\n"
10299 " vec4 b;\n"
10300 " layout (align = ALIGN) TYPE a;\n"
10301 "} block;\n"
10302 "\n"
10303 "in vec4 tcs_tes[];\n"
10304 "out vec4 tes_gs;\n"
10305 "\n"
10306 "void main()\n"
10307 "{\n"
10308 " if (TYPE(0) == block.a)\n"
10309 " {\n"
10310 " tes_gs = block.b;\n"
10311 " }\n"
10312 "\n"
10313 " tes_gs += tcs_tes[0];\n"
10314 "}\n"
10315 "\n";
10316 static const GLchar* vs = "#version 430 core\n"
10317 "#extension GL_ARB_enhanced_layouts : require\n"
10318 "\n"
10319 "in vec4 in_vs;\n"
10320 "out vec4 vs_tcs;\n"
10321 "\n"
10322 "void main()\n"
10323 "{\n"
10324 " vs_tcs = in_vs;\n"
10325 "}\n"
10326 "\n";
10327 static const GLchar* vs_tested = "#version 430 core\n"
10328 "#extension GL_ARB_enhanced_layouts : require\n"
10329 "\n"
10330 "layout (std140) uniform Block {\n"
10331 " vec4 b;\n"
10332 " layout (align = ALIGN) TYPE a;\n"
10333 "} block;\n"
10334 "\n"
10335 "in vec4 in_vs;\n"
10336 "out vec4 vs_tcs;\n"
10337 "\n"
10338 "void main()\n"
10339 "{\n"
10340 " if (TYPE(0) == block.a)\n"
10341 " {\n"
10342 " vs_tcs = block.b;\n"
10343 " }\n"
10344 "\n"
10345 " vs_tcs += in_vs;\n"
10346 "}\n"
10347 "\n";
10348
10349 std::string source;
10350 testCase& test_case = m_test_cases[test_case_index];
10351
10352 if (test_case.m_stage == stage)
10353 {
10354 GLchar buffer[16];
10355 const GLuint alignment = test_case.m_alignment;
10356 const Utils::Type& type = test_case.m_type;
10357 const GLchar* type_name = type.GetGLSLTypeName();
10358 size_t position = 0;
10359
10360 switch (stage)
10361 {
10362 case Utils::Shader::COMPUTE:
10363 source = cs;
10364 break;
10365 case Utils::Shader::FRAGMENT:
10366 source = fs_tested;
10367 break;
10368 case Utils::Shader::GEOMETRY:
10369 source = gs_tested;
10370 break;
10371 case Utils::Shader::TESS_CTRL:
10372 source = tcs_tested;
10373 break;
10374 case Utils::Shader::TESS_EVAL:
10375 source = tes_tested;
10376 break;
10377 case Utils::Shader::VERTEX:
10378 source = vs_tested;
10379 break;
10380 default:
10381 TCU_FAIL("Invalid enum");
10382 }
10383
10384 sprintf(buffer, "%d", alignment);
10385 Utils::replaceToken("ALIGN", position, buffer, source);
10386 Utils::replaceToken("TYPE", position, type_name, source);
10387 Utils::replaceToken("TYPE", position, type_name, source);
10388 }
10389 else
10390 {
10391 switch (stage)
10392 {
10393 case Utils::Shader::FRAGMENT:
10394 source = fs;
10395 break;
10396 case Utils::Shader::GEOMETRY:
10397 source = gs;
10398 break;
10399 case Utils::Shader::TESS_CTRL:
10400 source = tcs;
10401 break;
10402 case Utils::Shader::TESS_EVAL:
10403 source = tes;
10404 break;
10405 case Utils::Shader::VERTEX:
10406 source = vs;
10407 break;
10408 default:
10409 TCU_FAIL("Invalid enum");
10410 }
10411 }
10412
10413 return source;
10414 }
10415
10416 /** Get description of test case
10417 *
10418 * @param test_case_index Index of test case
10419 *
10420 * @return Type name and offset
10421 **/
10422 std::string UniformBlockMemberAlignNonPowerOf2Test::getTestCaseName(GLuint test_case_index)
10423 {
10424 std::stringstream stream;
10425 testCase& test_case = m_test_cases[test_case_index];
10426
10427 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", align: " << test_case.m_alignment;
10428
10429 return stream.str();
10430 }
10431
10432 /** Get number of test cases
10433 *
10434 * @return Number of test cases
10435 **/
10436 GLuint UniformBlockMemberAlignNonPowerOf2Test::getTestCaseNumber()
10437 {
10438 return static_cast<GLuint>(m_test_cases.size());
10439 }
10440
10441 /** Selects if "compute" stage is relevant for test
10442 *
10443 * @param test_case_index Index of test case
10444 *
10445 * @return true when tested stage is compute
10446 **/
10447 bool UniformBlockMemberAlignNonPowerOf2Test::isComputeRelevant(GLuint test_case_index)
10448 {
10449 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
10450 }
10451
10452 /** Checks if stage is supported
10453 *
10454 * @param ignored
10455 *
10456 * @return true
10457 **/
10458 bool UniformBlockMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES /* stage */)
10459 {
10460 return true;
10461 }
10462
10463 /** Selects if compilation failure is expected result
10464 *
10465 * @param test_case_index Index of test case
10466 *
10467 * @return should_fail field from testCase
10468 **/
10469 bool UniformBlockMemberAlignNonPowerOf2Test::isFailureExpected(GLuint test_case_index)
10470 {
10471 return m_test_cases[test_case_index].m_should_fail;
10472 }
10473
10474 /** Prepare all test cases
10475 *
10476 **/
10477 void UniformBlockMemberAlignNonPowerOf2Test::testInit()
10478 {
10479 static const GLuint dmat4_size = 128;
10480 const GLuint n_types = getTypesNumber();
10481 bool stage_support[Utils::Shader::STAGE_MAX];
10482
10483 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10484 {
10485 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
10486 }
10487
10488 for (GLuint j = 0; j < n_types; ++j)
10489 {
10490 const Utils::Type& type = getType(j);
10491
10492 for (GLuint align = 0; align <= dmat4_size; ++align)
10493 {
10494
10495 #if WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST
10496
10497 const bool should_fail = (0 == align) ? false : !isPowerOf2(align);
10498
10499 #else /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10500
10501 const bool should_fail = !isPowerOf2(align);
10502
10503 #endif /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10504
10505 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10506 {
10507 if (false == stage_support[stage])
10508 {
10509 continue;
10510 }
10511
10512 testCase test_case = { align, type, should_fail, (Utils::Shader::STAGES)stage };
10513
10514 m_test_cases.push_back(test_case);
10515 }
10516 }
10517 }
10518 }
10519
10520 /** Check if value is power of 2
10521 *
10522 * @param val Tested value
10523 *
10524 * @return true if val is power of 2, false otherwise
10525 **/
10526 bool UniformBlockMemberAlignNonPowerOf2Test::isPowerOf2(GLuint val)
10527 {
10528 if (0 == val)
10529 {
10530 return false;
10531 }
10532
10533 return (0 == (val & (val - 1)));
10534 }
10535
10536 /** Constructor
10537 *
10538 * @param context Test framework context
10539 **/
10540 UniformBlockAlignmentTest::UniformBlockAlignmentTest(deqp::Context& context)
10541 : TextureTestBase(context, "uniform_block_alignment", "Test verifies offset and alignment of uniform buffer")
10542 {
10543 }
10544
10545 /** Get interface of program
10546 *
10547 * @param ignored
10548 * @param program_interface Interface of program
10549 * @param varying_passthrough Collection of connections between in and out variables
10550 **/
10551 void UniformBlockAlignmentTest::getProgramInterface(GLuint /* test_case_index */,
10552 Utils::ProgramInterface& program_interface,
10553 Utils::VaryingPassthrough& varying_passthrough)
10554 {
10555 static const Utils::Type vec4 = Utils::Type::vec4;
10556
10557 #if WRKARD_UNIFORMBLOCKALIGNMENT
10558
10559 static const GLuint block_align = 16;
10560
10561 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10562
10563 static const GLuint block_align = 64;
10564
10565 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10566
10567 static const GLuint vec4_stride = 16;
10568 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
10569
10570 /*Fixed a test issue, the fifth_offset should be calculated by block_align, instead of fifth_align, according to spec, the actual
10571 alignment of a member will be the greater of the specified alignment and the base aligment for the member type
10572 */
10573 const GLuint first_offset = 0; /* vec4 at 0 */
10574 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
10575 const GLuint third_offset =
10576 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
10577 const GLuint fourth_offset =
10578 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
10579 const GLuint fifth_offset =
10580 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, block_align); /* vec4[2] at 160 */
10581 const GLuint sixth_offset =
10582 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
10583
10584 Utils::Interface* structure = program_interface.Structure("Data");
10585
10586 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10587 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
10588
10589 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
10590 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
10591 Utils::Type::vec4.GetSize() /* offset */);
10592
10593 /* Prepare Block */
10594 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
10595
10596 vs_uni_block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10597 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
10598
10599 vs_uni_block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10600 0 /* n_array_elements */, data_stride, second_offset);
10601
10602 vs_uni_block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10603 2 /* n_array_elements */, data_stride, third_offset);
10604
10605 vs_uni_block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
10606 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
10607
10608 vs_uni_block->Member("fifth", "layout(align = 64)", 0 /* expected_component */, 0 /* expected_location */, vec4,
10609 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
10610
10611 vs_uni_block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10612 0 /* n_array_elements */, data_stride, sixth_offset);
10613
10614 const GLuint stride = calculateStride(*vs_uni_block);
10615 m_data.resize(stride);
10616 generateData(*vs_uni_block, 0, m_data);
10617
10618 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10619
10620 /* Add uniform BLOCK */
10621 #if WRKARD_UNIFORMBLOCKALIGNMENT
10622 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
10623 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10624 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10625 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_uni_block, 0,
10626 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10627 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10628
10629 program_interface.CloneVertexInterface(varying_passthrough);
10630 }
10631
10632 /** Constructor
10633 *
10634 * @param context Test framework context
10635 **/
10636 SSBMemberOffsetAndAlignTest::SSBMemberOffsetAndAlignTest(deqp::Context& context)
10637 : TextureTestBase(context, "ssb_member_offset_and_align",
10638 "Test verifies offsets and alignment of storage buffer members")
10639 {
10640 }
10641
10642 /** Get interface of program
10643 *
10644 * @param test_case_index Test case index
10645 * @param program_interface Interface of program
10646 * @param varying_passthrough Collection of connections between in and out variables
10647 **/
10648 void SSBMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
10649 Utils::ProgramInterface& program_interface,
10650 Utils::VaryingPassthrough& varying_passthrough)
10651 {
10652 std::string globals = "const int basic_size = BASIC_SIZE;\n"
10653 "const int type_align = TYPE_ALIGN;\n"
10654 "const int type_size = TYPE_SIZE;\n";
10655
10656 Utils::Type type = getType(test_case_index);
10657 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
10658 const GLuint base_align = type.GetBaseAlignment(false);
10659 const GLuint array_align = type.GetBaseAlignment(true);
10660 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
10661 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
10662
10663 /* Calculate offsets */
10664 const GLuint first_offset = 0;
10665 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
10666
10667 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
10668
10669 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
10670 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
10671 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10672 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10673 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10674 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
10675
10676 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10677
10678 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
10679 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
10680 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10681 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10682 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10683 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
10684
10685 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10686
10687 /* Prepare data */
10688 const std::vector<GLubyte>& first = type.GenerateData();
10689 const std::vector<GLubyte>& second = type.GenerateData();
10690 const std::vector<GLubyte>& third = type.GenerateData();
10691 const std::vector<GLubyte>& fourth = type.GenerateData();
10692
10693 m_data.resize(eigth_offset + base_stride);
10694 GLubyte* ptr = &m_data[0];
10695 memcpy(ptr + first_offset, &first[0], first.size());
10696 memcpy(ptr + second_offset, &second[0], second.size());
10697 memcpy(ptr + third_offset, &third[0], third.size());
10698 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
10699 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
10700 memcpy(ptr + sixth_offset, &third[0], third.size());
10701 memcpy(ptr + seventh_offset, &second[0], second.size());
10702 memcpy(ptr + eigth_offset, &first[0], first.size());
10703
10704 /* Prepare globals */
10705 size_t position = 0;
10706 GLchar buffer[16];
10707
10708 sprintf(buffer, "%d", basic_size);
10709 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
10710
10711 sprintf(buffer, "%d", type_align);
10712 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
10713
10714 sprintf(buffer, "%d", base_stride);
10715 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
10716
10717 /* Prepare Block */
10718 Utils::Interface* vs_buf_block = program_interface.Block("vs_buf_Block");
10719
10720 vs_buf_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
10721 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10722 first_offset);
10723
10724 vs_buf_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
10725 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
10726 0 /* n_array_elements */, base_stride, second_offset);
10727
10728 vs_buf_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
10729 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10730 third_offset);
10731
10732 vs_buf_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
10733 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10734 fourth_offset);
10735
10736 vs_buf_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10737 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
10738
10739 vs_buf_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10740 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
10741
10742 vs_buf_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
10743 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10744 eigth_offset);
10745
10746 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10747
10748 /* Add globals */
10749 vs_si.m_globals = globals;
10750
10751 /* Add uniform BLOCK */
10752 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_block, 0,
10753 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10754
10755 /* */
10756 program_interface.CloneVertexInterface(varying_passthrough);
10757 }
10758
10759 /** Get type name
10760 *
10761 * @param test_case_index Index of test case
10762 *
10763 * @return Name of type test in test_case_index
10764 **/
10765 std::string SSBMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
10766 {
10767 return getTypeName(test_case_index);
10768 }
10769
10770 /** Returns number of types to test
10771 *
10772 * @return Number of types, 34
10773 **/
10774 glw::GLuint SSBMemberOffsetAndAlignTest::getTestCaseNumber()
10775 {
10776 return getTypesNumber();
10777 }
10778
10779 /** Prepare code snippet that will verify in and uniform variables
10780 *
10781 * @param ignored
10782 * @param ignored
10783 * @param stage Shader stage
10784 *
10785 * @return Code that verify variables
10786 **/
10787 std::string SSBMemberOffsetAndAlignTest::getVerificationSnippet(GLuint /* test_case_index */,
10788 Utils::ProgramInterface& /* program_interface */,
10789 Utils::Shader::STAGES stage)
10790 {
10791 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
10792 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
10793 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
10794 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
10795 " {\n"
10796 " result = 0;\n"
10797 " }";
10798
10799 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::SSB);
10800
10801 Utils::replaceAllTokens("PREFIX", prefix, verification);
10802
10803 return verification;
10804 }
10805
10806 /** Selects if "draw" stages are relevant for test
10807 *
10808 * @param ignored
10809 *
10810 * @return true if all stages support shader storage buffers, false otherwise
10811 **/
10812 bool SSBMemberOffsetAndAlignTest::isDrawRelevant(GLuint /* test_case_index */)
10813 {
10814 const Functions& gl = m_context.getRenderContext().getFunctions();
10815 GLint gs_supported_buffers = 0;
10816 GLint tcs_supported_buffers = 0;
10817 GLint tes_supported_buffers = 0;
10818 GLint vs_supported_buffers = 0;
10819
10820 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
10821 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
10822 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
10823 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
10824
10825 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
10826
10827 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
10828 (1 <= vs_supported_buffers));
10829 }
10830
10831 /** Constructor
10832 *
10833 * @param context Test framework context
10834 **/
10835 SSBLayoutQualifierConflictTest::SSBLayoutQualifierConflictTest(deqp::Context& context)
10836 : NegativeTestBase(context, "ssb_layout_qualifier_conflict", "Test verifies that std140 or std430 is required when "
10837 "offset and/or align qualifiers are used with storage "
10838 "block")
10839 {
10840 /* Nothing to be done here */
10841 }
10842
10843 /** Source for given test case and stage
10844 *
10845 * @param test_case_index Index of test case
10846 * @param stage Shader stage
10847 *
10848 * @return Shader source
10849 **/
10850 std::string SSBLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10851 {
10852 static const GLchar* cs = "#version 430 core\n"
10853 "#extension GL_ARB_enhanced_layouts : require\n"
10854 "\n"
10855 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10856 "\n"
10857 "layout (QUALIFIERbinding = BINDING) buffer cs_Block {\n"
10858 " layout(offset = 16) vec4 b;\n"
10859 " layout(align = 64) vec4 a;\n"
10860 "} uni_block;\n"
10861 "\n"
10862 "writeonly uniform image2D uni_image;\n"
10863 "\n"
10864 "void main()\n"
10865 "{\n"
10866 " vec4 result = uni_block.b + uni_block.a;\n"
10867 "\n"
10868 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10869 "}\n"
10870 "\n";
10871 static const GLchar* fs = "#version 430 core\n"
10872 "#extension GL_ARB_enhanced_layouts : require\n"
10873 "\n"
10874 "layout (QUALIFIERbinding = BINDING) buffer Block {\n"
10875 " layout(offset = 16) vec4 b;\n"
10876 " layout(align = 64) vec4 a;\n"
10877 "} uni_block;\n"
10878 "\n"
10879 "in vec4 gs_fs;\n"
10880 "out vec4 fs_out;\n"
10881 "\n"
10882 "void main()\n"
10883 "{\n"
10884 " fs_out = gs_fs + uni_block.b + uni_block.a;\n"
10885 "}\n"
10886 "\n";
10887 static const GLchar* gs = "#version 430 core\n"
10888 "#extension GL_ARB_enhanced_layouts : require\n"
10889 "\n"
10890 "layout(points) in;\n"
10891 "layout(triangle_strip, max_vertices = 4) out;\n"
10892 "\n"
10893 "layout (QUALIFIERbinding = BINDING) buffer gs_Block {\n"
10894 " layout(offset = 16) vec4 b;\n"
10895 " layout(align = 64) vec4 a;\n"
10896 "} uni_block;\n"
10897 "\n"
10898 "in vec4 tes_gs[];\n"
10899 "out vec4 gs_fs;\n"
10900 "\n"
10901 "void main()\n"
10902 "{\n"
10903 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
10904 " gl_Position = vec4(-1, -1, 0, 1);\n"
10905 " EmitVertex();\n"
10906 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
10907 " gl_Position = vec4(-1, 1, 0, 1);\n"
10908 " EmitVertex();\n"
10909 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
10910 " gl_Position = vec4(1, -1, 0, 1);\n"
10911 " EmitVertex();\n"
10912 " gs_fs = tes_gs[0] + uni_block.b + uni_block.a;\n"
10913 " gl_Position = vec4(1, 1, 0, 1);\n"
10914 " EmitVertex();\n"
10915 "}\n"
10916 "\n";
10917 static const GLchar* tcs =
10918 "#version 430 core\n"
10919 "#extension GL_ARB_enhanced_layouts : require\n"
10920 "\n"
10921 "layout(vertices = 1) out;\n"
10922 "\n"
10923 "layout (QUALIFIERbinding = BINDING) buffer tcs_Block {\n"
10924 " layout(offset = 16) vec4 b;\n"
10925 " layout(align = 64) vec4 a;\n"
10926 "} uni_block;\n"
10927 "\n"
10928 "in vec4 vs_tcs[];\n"
10929 "out vec4 tcs_tes[];\n"
10930 "\n"
10931 "void main()\n"
10932 "{\n"
10933 "\n"
10934 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.b + uni_block.a;\n"
10935 "\n"
10936 " gl_TessLevelOuter[0] = 1.0;\n"
10937 " gl_TessLevelOuter[1] = 1.0;\n"
10938 " gl_TessLevelOuter[2] = 1.0;\n"
10939 " gl_TessLevelOuter[3] = 1.0;\n"
10940 " gl_TessLevelInner[0] = 1.0;\n"
10941 " gl_TessLevelInner[1] = 1.0;\n"
10942 "}\n"
10943 "\n";
10944 static const GLchar* tes = "#version 430 core\n"
10945 "#extension GL_ARB_enhanced_layouts : require\n"
10946 "\n"
10947 "layout(isolines, point_mode) in;\n"
10948 "\n"
10949 "layout (QUALIFIERbinding = BINDING) buffer tes_Block {\n"
10950 " layout(offset = 16) vec4 b;\n"
10951 " layout(align = 64) vec4 a;\n"
10952 "} uni_block;\n"
10953 "\n"
10954 "in vec4 tcs_tes[];\n"
10955 "out vec4 tes_gs;\n"
10956 "\n"
10957 "void main()\n"
10958 "{\n"
10959 " tes_gs = tcs_tes[0] + uni_block.b + uni_block.a;\n"
10960 "}\n"
10961 "\n";
10962 static const GLchar* vs = "#version 430 core\n"
10963 "#extension GL_ARB_enhanced_layouts : require\n"
10964 "\n"
10965 "layout (QUALIFIERbinding = BINDING) buffer vs_Block {\n"
10966 " layout(offset = 16) vec4 b;\n"
10967 " layout(align = 64) vec4 a;\n"
10968 "} uni_block;\n"
10969 "\n"
10970 "in vec4 in_vs;\n"
10971 "out vec4 vs_tcs;\n"
10972 "\n"
10973 "void main()\n"
10974 "{\n"
10975 " vs_tcs = in_vs + uni_block.b + uni_block.a;\n"
10976 "}\n"
10977 "\n";
10978
10979 GLchar buffer[16];
10980 size_t position = 0;
10981 std::string source;
10982 testCase& test_case = m_test_cases[test_case_index];
10983 std::string qualifier = getQualifierName(test_case.m_qualifier);
10984
10985 if (false == qualifier.empty())
10986 {
10987 qualifier.append(", ");
10988 }
10989
10990 sprintf(buffer, "%d", stage);
10991
10992 switch (stage)
10993 {
10994 case Utils::Shader::COMPUTE:
10995 source = cs;
10996 break;
10997 case Utils::Shader::FRAGMENT:
10998 source = fs;
10999 break;
11000 case Utils::Shader::GEOMETRY:
11001 source = gs;
11002 break;
11003 case Utils::Shader::TESS_CTRL:
11004 source = tcs;
11005 break;
11006 case Utils::Shader::TESS_EVAL:
11007 source = tes;
11008 break;
11009 case Utils::Shader::VERTEX:
11010 source = vs;
11011 break;
11012 default:
11013 TCU_FAIL("Invalid enum");
11014 }
11015
11016 if (test_case.m_stage == stage)
11017 {
11018 Utils::replaceToken("QUALIFIER", position, qualifier.c_str(), source);
11019 }
11020 else
11021 {
11022 Utils::replaceToken("QUALIFIER", position, "std140, ", source);
11023 }
11024
11025 Utils::replaceToken("BINDING", position, buffer, source);
11026
11027 return source;
11028 }
11029
11030 /** Get description of test case
11031 *
11032 * @param test_case_index Index of test case
11033 *
11034 * @return Qualifier name
11035 **/
11036 std::string SSBLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
11037 {
11038 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
11039
11040 return result;
11041 }
11042
11043 /** Get number of test cases
11044 *
11045 * @return Number of test cases
11046 **/
11047 GLuint SSBLayoutQualifierConflictTest::getTestCaseNumber()
11048 {
11049 return static_cast<GLuint>(m_test_cases.size());
11050 }
11051
11052 /** Selects if "compute" stage is relevant for test
11053 *
11054 * @param test_case_index Index of test case
11055 *
11056 * @return true when tested stage is compute
11057 **/
11058 bool SSBLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
11059 {
11060 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
11061 }
11062
11063 /** Selects if compilation failure is expected result
11064 *
11065 * @param test_case_index Index of test case
11066 *
11067 * @return false for STD140 and STD430 cases, true otherwise
11068 **/
11069 bool SSBLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
11070 {
11071 const QUALIFIERS qualifier = m_test_cases[test_case_index].m_qualifier;
11072
11073 return !((STD140 == qualifier) || (STD430 == qualifier));
11074 }
11075
11076 /** Checks if stage is supported
11077 *
11078 * @param stage Shader stage
11079 *
11080 * @return true if supported, false otherwise
11081 **/
11082 bool SSBLayoutQualifierConflictTest::isStageSupported(Utils::Shader::STAGES stage)
11083 {
11084 const Functions& gl = m_context.getRenderContext().getFunctions();
11085 GLint max_supported_buffers = 0;
11086 GLenum pname = 0;
11087
11088 switch (stage)
11089 {
11090 case Utils::Shader::COMPUTE:
11091 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11092 break;
11093 case Utils::Shader::FRAGMENT:
11094 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11095 break;
11096 case Utils::Shader::GEOMETRY:
11097 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11098 break;
11099 case Utils::Shader::TESS_CTRL:
11100 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11101 break;
11102 case Utils::Shader::TESS_EVAL:
11103 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11104 break;
11105 case Utils::Shader::VERTEX:
11106 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11107 break;
11108 default:
11109 TCU_FAIL("Invalid enum");
11110 }
11111
11112 gl.getIntegerv(pname, &max_supported_buffers);
11113 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11114
11115 return 1 <= max_supported_buffers;
11116 }
11117
11118 /** Prepare all test cases
11119 *
11120 **/
11121 void SSBLayoutQualifierConflictTest::testInit()
11122 {
11123 bool stage_support[Utils::Shader::STAGE_MAX];
11124
11125 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11126 {
11127 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
11128 }
11129
11130 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
11131 {
11132 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11133 {
11134 if (false == stage_support[stage])
11135 {
11136 continue;
11137 }
11138
11139 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
11140
11141 m_test_cases.push_back(test_case);
11142 }
11143 }
11144 }
11145
11146 /** Get name of glsl constant
11147 *
11148 * @param Constant id
11149 *
11150 * @return Name of constant used in GLSL
11151 **/
11152 const GLchar* SSBLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
11153 {
11154 const GLchar* name = "";
11155
11156 switch (qualifier)
11157 {
11158 case DEFAULT:
11159 name = "";
11160 break;
11161 case STD140:
11162 name = "std140";
11163 break;
11164 case STD430:
11165 name = "std430";
11166 break;
11167 case SHARED:
11168 name = "shared";
11169 break;
11170 case PACKED:
11171 name = "packed";
11172 break;
11173 default:
11174 TCU_FAIL("Invalid enum");
11175 }
11176
11177 return name;
11178 }
11179
11180 /** Constructor
11181 *
11182 * @param context Test framework context
11183 **/
11184 SSBMemberInvalidOffsetAlignmentTest::SSBMemberInvalidOffsetAlignmentTest(deqp::Context& context)
11185 : UniformBlockMemberInvalidOffsetAlignmentTest(
11186 context, "ssb_member_invalid_offset_alignment",
11187 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
11188 {
11189 /* Nothing to be done here */
11190 }
11191
11192 /** Get the maximum size for a shader storage block
11193 *
11194 * @return The maximum size in basic machine units of a shader storage block.
11195 **/
11196 GLint SSBMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
11197 {
11198 const Functions& gl = m_context.getRenderContext().getFunctions();
11199 GLint max_size = 0;
11200
11201 gl.getIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_size);
11202 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11203
11204 return max_size;
11205 }
11206
11207 /** Source for given test case and stage
11208 *
11209 * @param test_case_index Index of test case
11210 * @param stage Shader stage
11211 *
11212 * @return Shader source
11213 **/
11214 std::string SSBMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11215 {
11216 static const GLchar* cs = "#version 430 core\n"
11217 "#extension GL_ARB_enhanced_layouts : require\n"
11218 "\n"
11219 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11220 "\n"
11221 "layout (std140) buffer Block {\n"
11222 " layout (offset = OFFSET) TYPE member;\n"
11223 "} block;\n"
11224 "\n"
11225 "writeonly uniform image2D uni_image;\n"
11226 "\n"
11227 "void main()\n"
11228 "{\n"
11229 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11230 "\n"
11231 " if (TYPE(1) == block.member)\n"
11232 " {\n"
11233 " result = vec4(1, 1, 1, 1);\n"
11234 " }\n"
11235 "\n"
11236 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11237 "}\n"
11238 "\n";
11239 static const GLchar* fs = "#version 430 core\n"
11240 "#extension GL_ARB_enhanced_layouts : require\n"
11241 "\n"
11242 "in vec4 gs_fs;\n"
11243 "out vec4 fs_out;\n"
11244 "\n"
11245 "void main()\n"
11246 "{\n"
11247 " fs_out = gs_fs;\n"
11248 "}\n"
11249 "\n";
11250 static const GLchar* fs_tested = "#version 430 core\n"
11251 "#extension GL_ARB_enhanced_layouts : require\n"
11252 "\n"
11253 "layout (std140) buffer Block {\n"
11254 " layout (offset = OFFSET) TYPE member;\n"
11255 "} block;\n"
11256 "\n"
11257 "in vec4 gs_fs;\n"
11258 "out vec4 fs_out;\n"
11259 "\n"
11260 "void main()\n"
11261 "{\n"
11262 " if (TYPE(1) == block.member)\n"
11263 " {\n"
11264 " fs_out = vec4(1, 1, 1, 1);\n"
11265 " }\n"
11266 "\n"
11267 " fs_out += gs_fs;\n"
11268 "}\n"
11269 "\n";
11270 static const GLchar* gs = "#version 430 core\n"
11271 "#extension GL_ARB_enhanced_layouts : require\n"
11272 "\n"
11273 "layout(points) in;\n"
11274 "layout(triangle_strip, max_vertices = 4) out;\n"
11275 "\n"
11276 "in vec4 tes_gs[];\n"
11277 "out vec4 gs_fs;\n"
11278 "\n"
11279 "void main()\n"
11280 "{\n"
11281 " gs_fs = tes_gs[0];\n"
11282 " gl_Position = vec4(-1, -1, 0, 1);\n"
11283 " EmitVertex();\n"
11284 " gs_fs = tes_gs[0];\n"
11285 " gl_Position = vec4(-1, 1, 0, 1);\n"
11286 " EmitVertex();\n"
11287 " gs_fs = tes_gs[0];\n"
11288 " gl_Position = vec4(1, -1, 0, 1);\n"
11289 " EmitVertex();\n"
11290 " gs_fs = tes_gs[0];\n"
11291 " gl_Position = vec4(1, 1, 0, 1);\n"
11292 " EmitVertex();\n"
11293 "}\n"
11294 "\n";
11295 static const GLchar* gs_tested = "#version 430 core\n"
11296 "#extension GL_ARB_enhanced_layouts : require\n"
11297 "\n"
11298 "layout(points) in;\n"
11299 "layout(triangle_strip, max_vertices = 4) out;\n"
11300 "\n"
11301 "layout (std140) buffer Block {\n"
11302 " layout (offset = OFFSET) TYPE member;\n"
11303 "} block;\n"
11304 "\n"
11305 "in vec4 tes_gs[];\n"
11306 "out vec4 gs_fs;\n"
11307 "\n"
11308 "void main()\n"
11309 "{\n"
11310 " if (TYPE(1) == block.member)\n"
11311 " {\n"
11312 " gs_fs = vec4(1, 1, 1, 1);\n"
11313 " }\n"
11314 "\n"
11315 " gs_fs += tes_gs[0];\n"
11316 " gl_Position = vec4(-1, -1, 0, 1);\n"
11317 " EmitVertex();\n"
11318 " gs_fs += tes_gs[0];\n"
11319 " gl_Position = vec4(-1, 1, 0, 1);\n"
11320 " EmitVertex();\n"
11321 " gs_fs += tes_gs[0];\n"
11322 " gl_Position = vec4(1, -1, 0, 1);\n"
11323 " EmitVertex();\n"
11324 " gs_fs += tes_gs[0];\n"
11325 " gl_Position = vec4(1, 1, 0, 1);\n"
11326 " EmitVertex();\n"
11327 "}\n"
11328 "\n";
11329 static const GLchar* tcs = "#version 430 core\n"
11330 "#extension GL_ARB_enhanced_layouts : require\n"
11331 "\n"
11332 "layout(vertices = 1) out;\n"
11333 "\n"
11334 "in vec4 vs_tcs[];\n"
11335 "out vec4 tcs_tes[];\n"
11336 "\n"
11337 "void main()\n"
11338 "{\n"
11339 "\n"
11340 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11341 "\n"
11342 " gl_TessLevelOuter[0] = 1.0;\n"
11343 " gl_TessLevelOuter[1] = 1.0;\n"
11344 " gl_TessLevelOuter[2] = 1.0;\n"
11345 " gl_TessLevelOuter[3] = 1.0;\n"
11346 " gl_TessLevelInner[0] = 1.0;\n"
11347 " gl_TessLevelInner[1] = 1.0;\n"
11348 "}\n"
11349 "\n";
11350 static const GLchar* tcs_tested = "#version 430 core\n"
11351 "#extension GL_ARB_enhanced_layouts : require\n"
11352 "\n"
11353 "layout(vertices = 1) out;\n"
11354 "\n"
11355 "layout (std140) buffer Block {\n"
11356 " layout (offset = OFFSET) TYPE member;\n"
11357 "} block;\n"
11358 "\n"
11359 "in vec4 vs_tcs[];\n"
11360 "out vec4 tcs_tes[];\n"
11361 "\n"
11362 "void main()\n"
11363 "{\n"
11364 " if (TYPE(1) == block.member)\n"
11365 " {\n"
11366 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11367 " }\n"
11368 "\n"
11369 "\n"
11370 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11371 "\n"
11372 " gl_TessLevelOuter[0] = 1.0;\n"
11373 " gl_TessLevelOuter[1] = 1.0;\n"
11374 " gl_TessLevelOuter[2] = 1.0;\n"
11375 " gl_TessLevelOuter[3] = 1.0;\n"
11376 " gl_TessLevelInner[0] = 1.0;\n"
11377 " gl_TessLevelInner[1] = 1.0;\n"
11378 "}\n"
11379 "\n";
11380 static const GLchar* tes = "#version 430 core\n"
11381 "#extension GL_ARB_enhanced_layouts : require\n"
11382 "\n"
11383 "layout(isolines, point_mode) in;\n"
11384 "\n"
11385 "in vec4 tcs_tes[];\n"
11386 "out vec4 tes_gs;\n"
11387 "\n"
11388 "void main()\n"
11389 "{\n"
11390 " tes_gs = tcs_tes[0];\n"
11391 "}\n"
11392 "\n";
11393 static const GLchar* tes_tested = "#version 430 core\n"
11394 "#extension GL_ARB_enhanced_layouts : require\n"
11395 "\n"
11396 "layout(isolines, point_mode) in;\n"
11397 "\n"
11398 "layout (std140) buffer Block {\n"
11399 " layout (offset = OFFSET) TYPE member;\n"
11400 "} block;\n"
11401 "\n"
11402 "in vec4 tcs_tes[];\n"
11403 "out vec4 tes_gs;\n"
11404 "\n"
11405 "void main()\n"
11406 "{\n"
11407 " if (TYPE(1) == block.member)\n"
11408 " {\n"
11409 " tes_gs = vec4(1, 1, 1, 1);\n"
11410 " }\n"
11411 "\n"
11412 " tes_gs += tcs_tes[0];\n"
11413 "}\n"
11414 "\n";
11415 static const GLchar* vs = "#version 430 core\n"
11416 "#extension GL_ARB_enhanced_layouts : require\n"
11417 "\n"
11418 "in vec4 in_vs;\n"
11419 "out vec4 vs_tcs;\n"
11420 "\n"
11421 "void main()\n"
11422 "{\n"
11423 " vs_tcs = in_vs;\n"
11424 "}\n"
11425 "\n";
11426 static const GLchar* vs_tested = "#version 430 core\n"
11427 "#extension GL_ARB_enhanced_layouts : require\n"
11428 "\n"
11429 "layout (std140) buffer Block {\n"
11430 " layout (offset = OFFSET) TYPE member;\n"
11431 "} block;\n"
11432 "\n"
11433 "in vec4 in_vs;\n"
11434 "out vec4 vs_tcs;\n"
11435 "\n"
11436 "void main()\n"
11437 "{\n"
11438 " if (TYPE(1) == block.member)\n"
11439 " {\n"
11440 " vs_tcs = vec4(1, 1, 1, 1);\n"
11441 " }\n"
11442 "\n"
11443 " vs_tcs += in_vs;\n"
11444 "}\n"
11445 "\n";
11446
11447 std::string source;
11448 testCase& test_case = m_test_cases[test_case_index];
11449
11450 if (test_case.m_stage == stage)
11451 {
11452 GLchar buffer[16];
11453 const GLuint offset = test_case.m_offset;
11454 size_t position = 0;
11455 const Utils::Type& type = test_case.m_type;
11456 const GLchar* type_name = type.GetGLSLTypeName();
11457
11458 sprintf(buffer, "%d", offset);
11459
11460 switch (stage)
11461 {
11462 case Utils::Shader::COMPUTE:
11463 source = cs;
11464 break;
11465 case Utils::Shader::FRAGMENT:
11466 source = fs_tested;
11467 break;
11468 case Utils::Shader::GEOMETRY:
11469 source = gs_tested;
11470 break;
11471 case Utils::Shader::TESS_CTRL:
11472 source = tcs_tested;
11473 break;
11474 case Utils::Shader::TESS_EVAL:
11475 source = tes_tested;
11476 break;
11477 case Utils::Shader::VERTEX:
11478 source = vs_tested;
11479 break;
11480 default:
11481 TCU_FAIL("Invalid enum");
11482 }
11483
11484 Utils::replaceToken("OFFSET", position, buffer, source);
11485 Utils::replaceToken("TYPE", position, type_name, source);
11486 Utils::replaceToken("TYPE", position, type_name, source);
11487 }
11488 else
11489 {
11490 switch (stage)
11491 {
11492 case Utils::Shader::FRAGMENT:
11493 source = fs;
11494 break;
11495 case Utils::Shader::GEOMETRY:
11496 source = gs;
11497 break;
11498 case Utils::Shader::TESS_CTRL:
11499 source = tcs;
11500 break;
11501 case Utils::Shader::TESS_EVAL:
11502 source = tes;
11503 break;
11504 case Utils::Shader::VERTEX:
11505 source = vs;
11506 break;
11507 default:
11508 TCU_FAIL("Invalid enum");
11509 }
11510 }
11511
11512 return source;
11513 }
11514
11515 /** Checks if stage is supported
11516 *
11517 * @param stage Shader stage
11518 *
11519 * @return true if supported, false otherwise
11520 **/
11521 bool SSBMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES stage)
11522 {
11523 const Functions& gl = m_context.getRenderContext().getFunctions();
11524 GLint max_supported_buffers = 0;
11525 GLenum pname = 0;
11526
11527 switch (stage)
11528 {
11529 case Utils::Shader::COMPUTE:
11530 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11531 break;
11532 case Utils::Shader::FRAGMENT:
11533 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11534 break;
11535 case Utils::Shader::GEOMETRY:
11536 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11537 break;
11538 case Utils::Shader::TESS_CTRL:
11539 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11540 break;
11541 case Utils::Shader::TESS_EVAL:
11542 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11543 break;
11544 case Utils::Shader::VERTEX:
11545 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11546 break;
11547 default:
11548 TCU_FAIL("Invalid enum");
11549 }
11550
11551 gl.getIntegerv(pname, &max_supported_buffers);
11552 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11553
11554 return 1 <= max_supported_buffers;
11555 }
11556
11557 /** Constructor
11558 *
11559 * @param context Test framework context
11560 **/
11561 SSBMemberOverlappingOffsetsTest::SSBMemberOverlappingOffsetsTest(deqp::Context& context)
11562 : UniformBlockMemberOverlappingOffsetsTest(
11563 context, "ssb_member_overlapping_offsets",
11564 "Test verifies that overlapping offsets qualifiers cause compilation failure")
11565 {
11566 /* Nothing to be done here */
11567 }
11568
11569 /** Source for given test case and stage
11570 *
11571 * @param test_case_index Index of test case
11572 * @param stage Shader stage
11573 *
11574 * @return Shader source
11575 **/
11576 std::string SSBMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11577 {
11578 static const GLchar* cs = "#version 430 core\n"
11579 "#extension GL_ARB_enhanced_layouts : require\n"
11580 "\n"
11581 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11582 "\n"
11583 "layout (std140) buffer Block {\n"
11584 " layout (offset = B_OFFSET) B_TYPE b;\n"
11585 " layout (offset = A_OFFSET) A_TYPE a;\n"
11586 "} block;\n"
11587 "\n"
11588 "writeonly uniform image2D uni_image;\n"
11589 "\n"
11590 "void main()\n"
11591 "{\n"
11592 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11593 "\n"
11594 " if ((B_TYPE(1) == block.b) ||\n"
11595 " (A_TYPE(0) == block.a) )\n"
11596 " {\n"
11597 " result = vec4(1, 1, 1, 1);\n"
11598 " }\n"
11599 "\n"
11600 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11601 "}\n"
11602 "\n";
11603 static const GLchar* fs = "#version 430 core\n"
11604 "#extension GL_ARB_enhanced_layouts : require\n"
11605 "\n"
11606 "in vec4 gs_fs;\n"
11607 "out vec4 fs_out;\n"
11608 "\n"
11609 "void main()\n"
11610 "{\n"
11611 " fs_out = gs_fs;\n"
11612 "}\n"
11613 "\n";
11614 static const GLchar* fs_tested = "#version 430 core\n"
11615 "#extension GL_ARB_enhanced_layouts : require\n"
11616 "\n"
11617 "layout (std140) buffer Block {\n"
11618 " layout (offset = B_OFFSET) B_TYPE b;\n"
11619 " layout (offset = A_OFFSET) A_TYPE a;\n"
11620 "} block;\n"
11621 "\n"
11622 "in vec4 gs_fs;\n"
11623 "out vec4 fs_out;\n"
11624 "\n"
11625 "void main()\n"
11626 "{\n"
11627 " if ((B_TYPE(1) == block.b) ||\n"
11628 " (A_TYPE(0) == block.a) )\n"
11629 " {\n"
11630 " fs_out = vec4(1, 1, 1, 1);\n"
11631 " }\n"
11632 "\n"
11633 " fs_out += gs_fs;\n"
11634 "}\n"
11635 "\n";
11636 static const GLchar* gs = "#version 430 core\n"
11637 "#extension GL_ARB_enhanced_layouts : require\n"
11638 "\n"
11639 "layout(points) in;\n"
11640 "layout(triangle_strip, max_vertices = 4) out;\n"
11641 "\n"
11642 "in vec4 tes_gs[];\n"
11643 "out vec4 gs_fs;\n"
11644 "\n"
11645 "void main()\n"
11646 "{\n"
11647 " gs_fs = tes_gs[0];\n"
11648 " gl_Position = vec4(-1, -1, 0, 1);\n"
11649 " EmitVertex();\n"
11650 " gs_fs = tes_gs[0];\n"
11651 " gl_Position = vec4(-1, 1, 0, 1);\n"
11652 " EmitVertex();\n"
11653 " gs_fs = tes_gs[0];\n"
11654 " gl_Position = vec4(1, -1, 0, 1);\n"
11655 " EmitVertex();\n"
11656 " gs_fs = tes_gs[0];\n"
11657 " gl_Position = vec4(1, 1, 0, 1);\n"
11658 " EmitVertex();\n"
11659 "}\n"
11660 "\n";
11661 static const GLchar* gs_tested = "#version 430 core\n"
11662 "#extension GL_ARB_enhanced_layouts : require\n"
11663 "\n"
11664 "layout(points) in;\n"
11665 "layout(triangle_strip, max_vertices = 4) out;\n"
11666 "\n"
11667 "layout (std140) buffer Block {\n"
11668 " layout (offset = B_OFFSET) B_TYPE b;\n"
11669 " layout (offset = A_OFFSET) A_TYPE a;\n"
11670 "} block;\n"
11671 "\n"
11672 "in vec4 tes_gs[];\n"
11673 "out vec4 gs_fs;\n"
11674 "\n"
11675 "void main()\n"
11676 "{\n"
11677 " if ((B_TYPE(1) == block.b) ||\n"
11678 " (A_TYPE(0) == block.a) )\n"
11679 " {\n"
11680 " gs_fs = vec4(1, 1, 1, 1);\n"
11681 " }\n"
11682 "\n"
11683 " gs_fs += tes_gs[0];\n"
11684 " gl_Position = vec4(-1, -1, 0, 1);\n"
11685 " EmitVertex();\n"
11686 " gs_fs += tes_gs[0];\n"
11687 " gl_Position = vec4(-1, 1, 0, 1);\n"
11688 " EmitVertex();\n"
11689 " gs_fs += tes_gs[0];\n"
11690 " gl_Position = vec4(1, -1, 0, 1);\n"
11691 " EmitVertex();\n"
11692 " gs_fs += tes_gs[0];\n"
11693 " gl_Position = vec4(1, 1, 0, 1);\n"
11694 " EmitVertex();\n"
11695 "}\n"
11696 "\n";
11697 static const GLchar* tcs = "#version 430 core\n"
11698 "#extension GL_ARB_enhanced_layouts : require\n"
11699 "\n"
11700 "layout(vertices = 1) out;\n"
11701 "\n"
11702 "in vec4 vs_tcs[];\n"
11703 "out vec4 tcs_tes[];\n"
11704 "\n"
11705 "void main()\n"
11706 "{\n"
11707 "\n"
11708 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11709 "\n"
11710 " gl_TessLevelOuter[0] = 1.0;\n"
11711 " gl_TessLevelOuter[1] = 1.0;\n"
11712 " gl_TessLevelOuter[2] = 1.0;\n"
11713 " gl_TessLevelOuter[3] = 1.0;\n"
11714 " gl_TessLevelInner[0] = 1.0;\n"
11715 " gl_TessLevelInner[1] = 1.0;\n"
11716 "}\n"
11717 "\n";
11718 static const GLchar* tcs_tested = "#version 430 core\n"
11719 "#extension GL_ARB_enhanced_layouts : require\n"
11720 "\n"
11721 "layout(vertices = 1) out;\n"
11722 "\n"
11723 "layout (std140) buffer Block {\n"
11724 " layout (offset = B_OFFSET) B_TYPE b;\n"
11725 " layout (offset = A_OFFSET) A_TYPE a;\n"
11726 "} block;\n"
11727 "\n"
11728 "in vec4 vs_tcs[];\n"
11729 "out vec4 tcs_tes[];\n"
11730 "\n"
11731 "void main()\n"
11732 "{\n"
11733 " if ((B_TYPE(1) == block.b) ||\n"
11734 " (A_TYPE(0) == block.a) )\n"
11735 " {\n"
11736 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11737 " }\n"
11738 "\n"
11739 "\n"
11740 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11741 "\n"
11742 " gl_TessLevelOuter[0] = 1.0;\n"
11743 " gl_TessLevelOuter[1] = 1.0;\n"
11744 " gl_TessLevelOuter[2] = 1.0;\n"
11745 " gl_TessLevelOuter[3] = 1.0;\n"
11746 " gl_TessLevelInner[0] = 1.0;\n"
11747 " gl_TessLevelInner[1] = 1.0;\n"
11748 "}\n"
11749 "\n";
11750 static const GLchar* tes = "#version 430 core\n"
11751 "#extension GL_ARB_enhanced_layouts : require\n"
11752 "\n"
11753 "layout(isolines, point_mode) in;\n"
11754 "\n"
11755 "in vec4 tcs_tes[];\n"
11756 "out vec4 tes_gs;\n"
11757 "\n"
11758 "void main()\n"
11759 "{\n"
11760 " tes_gs = tcs_tes[0];\n"
11761 "}\n"
11762 "\n";
11763 static const GLchar* tes_tested = "#version 430 core\n"
11764 "#extension GL_ARB_enhanced_layouts : require\n"
11765 "\n"
11766 "layout(isolines, point_mode) in;\n"
11767 "\n"
11768 "layout (std140) buffer Block {\n"
11769 " layout (offset = B_OFFSET) B_TYPE b;\n"
11770 " layout (offset = A_OFFSET) A_TYPE a;\n"
11771 "} block;\n"
11772 "\n"
11773 "in vec4 tcs_tes[];\n"
11774 "out vec4 tes_gs;\n"
11775 "\n"
11776 "void main()\n"
11777 "{\n"
11778 " if ((B_TYPE(1) == block.b) ||\n"
11779 " (A_TYPE(0) == block.a) )\n"
11780 " {\n"
11781 " tes_gs = vec4(1, 1, 1, 1);\n"
11782 " }\n"
11783 "\n"
11784 " tes_gs += tcs_tes[0];\n"
11785 "}\n"
11786 "\n";
11787 static const GLchar* vs = "#version 430 core\n"
11788 "#extension GL_ARB_enhanced_layouts : require\n"
11789 "\n"
11790 "in vec4 in_vs;\n"
11791 "out vec4 vs_tcs;\n"
11792 "\n"
11793 "void main()\n"
11794 "{\n"
11795 " vs_tcs = in_vs;\n"
11796 "}\n"
11797 "\n";
11798 static const GLchar* vs_tested = "#version 430 core\n"
11799 "#extension GL_ARB_enhanced_layouts : require\n"
11800 "\n"
11801 "layout (std140) buffer Block {\n"
11802 " layout (offset = B_OFFSET) B_TYPE b;\n"
11803 " layout (offset = A_OFFSET) A_TYPE a;\n"
11804 "} block;\n"
11805 "\n"
11806 "in vec4 in_vs;\n"
11807 "out vec4 vs_tcs;\n"
11808 "\n"
11809 "void main()\n"
11810 "{\n"
11811 " if ((B_TYPE(1) == block.b) ||\n"
11812 " (A_TYPE(0) == block.a) )\n"
11813 " {\n"
11814 " vs_tcs = vec4(1, 1, 1, 1);\n"
11815 " }\n"
11816 "\n"
11817 " vs_tcs += in_vs;\n"
11818 "}\n"
11819 "\n";
11820
11821 std::string source;
11822 testCase& test_case = m_test_cases[test_case_index];
11823
11824 if (test_case.m_stage == stage)
11825 {
11826 GLchar buffer[16];
11827 const GLuint b_offset = test_case.m_b_offset;
11828 const Utils::Type& b_type = test_case.m_b_type;
11829 const GLchar* b_type_name = b_type.GetGLSLTypeName();
11830 const GLuint a_offset = test_case.m_a_offset;
11831 const Utils::Type& a_type = test_case.m_a_type;
11832 const GLchar* a_type_name = a_type.GetGLSLTypeName();
11833 size_t position = 0;
11834
11835 switch (stage)
11836 {
11837 case Utils::Shader::COMPUTE:
11838 source = cs;
11839 break;
11840 case Utils::Shader::FRAGMENT:
11841 source = fs_tested;
11842 break;
11843 case Utils::Shader::GEOMETRY:
11844 source = gs_tested;
11845 break;
11846 case Utils::Shader::TESS_CTRL:
11847 source = tcs_tested;
11848 break;
11849 case Utils::Shader::TESS_EVAL:
11850 source = tes_tested;
11851 break;
11852 case Utils::Shader::VERTEX:
11853 source = vs_tested;
11854 break;
11855 default:
11856 TCU_FAIL("Invalid enum");
11857 }
11858
11859 sprintf(buffer, "%d", b_offset);
11860 Utils::replaceToken("B_OFFSET", position, buffer, source);
11861 Utils::replaceToken("B_TYPE", position, b_type_name, source);
11862 sprintf(buffer, "%d", a_offset);
11863 Utils::replaceToken("A_OFFSET", position, buffer, source);
11864 Utils::replaceToken("A_TYPE", position, a_type_name, source);
11865 Utils::replaceToken("B_TYPE", position, b_type_name, source);
11866 Utils::replaceToken("A_TYPE", position, a_type_name, source);
11867 }
11868 else
11869 {
11870 switch (stage)
11871 {
11872 case Utils::Shader::FRAGMENT:
11873 source = fs;
11874 break;
11875 case Utils::Shader::GEOMETRY:
11876 source = gs;
11877 break;
11878 case Utils::Shader::TESS_CTRL:
11879 source = tcs;
11880 break;
11881 case Utils::Shader::TESS_EVAL:
11882 source = tes;
11883 break;
11884 case Utils::Shader::VERTEX:
11885 source = vs;
11886 break;
11887 default:
11888 TCU_FAIL("Invalid enum");
11889 }
11890 }
11891
11892 return source;
11893 }
11894
11895 /** Checks if stage is supported
11896 *
11897 * @param stage Shader stage
11898 *
11899 * @return true if supported, false otherwise
11900 **/
11901 bool SSBMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES stage)
11902 {
11903 const Functions& gl = m_context.getRenderContext().getFunctions();
11904 GLint max_supported_buffers = 0;
11905 GLenum pname = 0;
11906
11907 switch (stage)
11908 {
11909 case Utils::Shader::COMPUTE:
11910 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11911 break;
11912 case Utils::Shader::FRAGMENT:
11913 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11914 break;
11915 case Utils::Shader::GEOMETRY:
11916 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11917 break;
11918 case Utils::Shader::TESS_CTRL:
11919 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11920 break;
11921 case Utils::Shader::TESS_EVAL:
11922 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11923 break;
11924 case Utils::Shader::VERTEX:
11925 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11926 break;
11927 default:
11928 TCU_FAIL("Invalid enum");
11929 }
11930
11931 gl.getIntegerv(pname, &max_supported_buffers);
11932 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11933
11934 return 1 <= max_supported_buffers;
11935 }
11936
11937 /** Constructor
11938 *
11939 * @param context Test framework context
11940 **/
11941 SSBMemberAlignNonPowerOf2Test::SSBMemberAlignNonPowerOf2Test(deqp::Context& context)
11942 : UniformBlockMemberAlignNonPowerOf2Test(context, "ssb_member_align_non_power_of_2",
11943 "Test verifies that align qualifier requires value that is a power of 2")
11944 {
11945 /* Nothing to be done here */
11946 }
11947
11948 /** Source for given test case and stage
11949 *
11950 * @param test_case_index Index of test case
11951 * @param stage Shader stage
11952 *
11953 * @return Shader source
11954 **/
11955 std::string SSBMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11956 {
11957 static const GLchar* cs = "#version 430 core\n"
11958 "#extension GL_ARB_enhanced_layouts : require\n"
11959 "\n"
11960 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11961 "\n"
11962 "layout (std140) buffer Block {\n"
11963 " vec4 b;\n"
11964 " layout (align = ALIGN) TYPE a;\n"
11965 "} block;\n"
11966 "\n"
11967 "writeonly uniform image2D uni_image;\n"
11968 "\n"
11969 "void main()\n"
11970 "{\n"
11971 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11972 "\n"
11973 " if (TYPE(0) == block.a)\n"
11974 " {\n"
11975 " result = vec4(1, 1, 1, 1) - block.b;\n"
11976 " }\n"
11977 "\n"
11978 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11979 "}\n"
11980 "\n";
11981 static const GLchar* fs = "#version 430 core\n"
11982 "#extension GL_ARB_enhanced_layouts : require\n"
11983 "\n"
11984 "in vec4 gs_fs;\n"
11985 "out vec4 fs_out;\n"
11986 "\n"
11987 "void main()\n"
11988 "{\n"
11989 " fs_out = gs_fs;\n"
11990 "}\n"
11991 "\n";
11992 static const GLchar* fs_tested = "#version 430 core\n"
11993 "#extension GL_ARB_enhanced_layouts : require\n"
11994 "\n"
11995 "layout (std140) buffer Block {\n"
11996 " vec4 b;\n"
11997 " layout (align = ALIGN) TYPE a;\n"
11998 "} block;\n"
11999 "\n"
12000 "in vec4 gs_fs;\n"
12001 "out vec4 fs_out;\n"
12002 "\n"
12003 "void main()\n"
12004 "{\n"
12005 " if (TYPE(0) == block.a)\n"
12006 " {\n"
12007 " fs_out = block.b;\n"
12008 " }\n"
12009 "\n"
12010 " fs_out += gs_fs;\n"
12011 "}\n"
12012 "\n";
12013 static const GLchar* gs = "#version 430 core\n"
12014 "#extension GL_ARB_enhanced_layouts : require\n"
12015 "\n"
12016 "layout(points) in;\n"
12017 "layout(triangle_strip, max_vertices = 4) out;\n"
12018 "\n"
12019 "in vec4 tes_gs[];\n"
12020 "out vec4 gs_fs;\n"
12021 "\n"
12022 "void main()\n"
12023 "{\n"
12024 " gs_fs = tes_gs[0];\n"
12025 " gl_Position = vec4(-1, -1, 0, 1);\n"
12026 " EmitVertex();\n"
12027 " gs_fs = tes_gs[0];\n"
12028 " gl_Position = vec4(-1, 1, 0, 1);\n"
12029 " EmitVertex();\n"
12030 " gs_fs = tes_gs[0];\n"
12031 " gl_Position = vec4(1, -1, 0, 1);\n"
12032 " EmitVertex();\n"
12033 " gs_fs = tes_gs[0];\n"
12034 " gl_Position = vec4(1, 1, 0, 1);\n"
12035 " EmitVertex();\n"
12036 "}\n"
12037 "\n";
12038 static const GLchar* gs_tested = "#version 430 core\n"
12039 "#extension GL_ARB_enhanced_layouts : require\n"
12040 "\n"
12041 "layout(points) in;\n"
12042 "layout(triangle_strip, max_vertices = 4) out;\n"
12043 "\n"
12044 "layout (std140) buffer Block {\n"
12045 " vec4 b;\n"
12046 " layout (align = ALIGN) TYPE a;\n"
12047 "} block;\n"
12048 "\n"
12049 "in vec4 tes_gs[];\n"
12050 "out vec4 gs_fs;\n"
12051 "\n"
12052 "void main()\n"
12053 "{\n"
12054 " if (TYPE(0) == block.a)\n"
12055 " {\n"
12056 " gs_fs = block.b;\n"
12057 " }\n"
12058 "\n"
12059 " gs_fs += tes_gs[0];\n"
12060 " gl_Position = vec4(-1, -1, 0, 1);\n"
12061 " EmitVertex();\n"
12062 " gs_fs += tes_gs[0];\n"
12063 " gl_Position = vec4(-1, 1, 0, 1);\n"
12064 " EmitVertex();\n"
12065 " gs_fs += tes_gs[0];\n"
12066 " gl_Position = vec4(1, -1, 0, 1);\n"
12067 " EmitVertex();\n"
12068 " gs_fs += tes_gs[0];\n"
12069 " gl_Position = vec4(1, 1, 0, 1);\n"
12070 " EmitVertex();\n"
12071 "}\n"
12072 "\n";
12073 static const GLchar* tcs = "#version 430 core\n"
12074 "#extension GL_ARB_enhanced_layouts : require\n"
12075 "\n"
12076 "layout(vertices = 1) out;\n"
12077 "\n"
12078 "in vec4 vs_tcs[];\n"
12079 "out vec4 tcs_tes[];\n"
12080 "\n"
12081 "void main()\n"
12082 "{\n"
12083 "\n"
12084 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
12085 "\n"
12086 " gl_TessLevelOuter[0] = 1.0;\n"
12087 " gl_TessLevelOuter[1] = 1.0;\n"
12088 " gl_TessLevelOuter[2] = 1.0;\n"
12089 " gl_TessLevelOuter[3] = 1.0;\n"
12090 " gl_TessLevelInner[0] = 1.0;\n"
12091 " gl_TessLevelInner[1] = 1.0;\n"
12092 "}\n"
12093 "\n";
12094 static const GLchar* tcs_tested = "#version 430 core\n"
12095 "#extension GL_ARB_enhanced_layouts : require\n"
12096 "\n"
12097 "layout(vertices = 1) out;\n"
12098 "\n"
12099 "layout (std140) buffer Block {\n"
12100 " vec4 b;\n"
12101 " layout (align = ALIGN) TYPE a;\n"
12102 "} block;\n"
12103 "\n"
12104 "in vec4 vs_tcs[];\n"
12105 "out vec4 tcs_tes[];\n"
12106 "\n"
12107 "void main()\n"
12108 "{\n"
12109 " if (TYPE(0) == block.a)\n"
12110 " {\n"
12111 " tcs_tes[gl_InvocationID] = block.b;\n"
12112 " }\n"
12113 "\n"
12114 "\n"
12115 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
12116 "\n"
12117 " gl_TessLevelOuter[0] = 1.0;\n"
12118 " gl_TessLevelOuter[1] = 1.0;\n"
12119 " gl_TessLevelOuter[2] = 1.0;\n"
12120 " gl_TessLevelOuter[3] = 1.0;\n"
12121 " gl_TessLevelInner[0] = 1.0;\n"
12122 " gl_TessLevelInner[1] = 1.0;\n"
12123 "}\n"
12124 "\n";
12125 static const GLchar* tes = "#version 430 core\n"
12126 "#extension GL_ARB_enhanced_layouts : require\n"
12127 "\n"
12128 "layout(isolines, point_mode) in;\n"
12129 "\n"
12130 "in vec4 tcs_tes[];\n"
12131 "out vec4 tes_gs;\n"
12132 "\n"
12133 "void main()\n"
12134 "{\n"
12135 " tes_gs = tcs_tes[0];\n"
12136 "}\n"
12137 "\n";
12138 static const GLchar* tes_tested = "#version 430 core\n"
12139 "#extension GL_ARB_enhanced_layouts : require\n"
12140 "\n"
12141 "layout(isolines, point_mode) in;\n"
12142 "\n"
12143 "layout (std140) buffer Block {\n"
12144 " vec4 b;\n"
12145 " layout (align = ALIGN) TYPE a;\n"
12146 "} block;\n"
12147 "\n"
12148 "in vec4 tcs_tes[];\n"
12149 "out vec4 tes_gs;\n"
12150 "\n"
12151 "void main()\n"
12152 "{\n"
12153 " if (TYPE(0) == block.a)\n"
12154 " {\n"
12155 " tes_gs = block.b;\n"
12156 " }\n"
12157 "\n"
12158 " tes_gs += tcs_tes[0];\n"
12159 "}\n"
12160 "\n";
12161 static const GLchar* vs = "#version 430 core\n"
12162 "#extension GL_ARB_enhanced_layouts : require\n"
12163 "\n"
12164 "in vec4 in_vs;\n"
12165 "out vec4 vs_tcs;\n"
12166 "\n"
12167 "void main()\n"
12168 "{\n"
12169 " vs_tcs = in_vs;\n"
12170 "}\n"
12171 "\n";
12172 static const GLchar* vs_tested = "#version 430 core\n"
12173 "#extension GL_ARB_enhanced_layouts : require\n"
12174 "\n"
12175 "layout (std140) buffer Block {\n"
12176 " vec4 b;\n"
12177 " layout (align = ALIGN) TYPE a;\n"
12178 "} block;\n"
12179 "\n"
12180 "in vec4 in_vs;\n"
12181 "out vec4 vs_tcs;\n"
12182 "\n"
12183 "void main()\n"
12184 "{\n"
12185 " if (TYPE(0) == block.a)\n"
12186 " {\n"
12187 " vs_tcs = block.b;\n"
12188 " }\n"
12189 "\n"
12190 " vs_tcs += in_vs;\n"
12191 "}\n"
12192 "\n";
12193
12194 std::string source;
12195 testCase& test_case = m_test_cases[test_case_index];
12196
12197 if (test_case.m_stage == stage)
12198 {
12199 GLchar buffer[16];
12200 const GLuint alignment = test_case.m_alignment;
12201 const Utils::Type& type = test_case.m_type;
12202 const GLchar* type_name = type.GetGLSLTypeName();
12203 size_t position = 0;
12204
12205 switch (stage)
12206 {
12207 case Utils::Shader::COMPUTE:
12208 source = cs;
12209 break;
12210 case Utils::Shader::FRAGMENT:
12211 source = fs_tested;
12212 break;
12213 case Utils::Shader::GEOMETRY:
12214 source = gs_tested;
12215 break;
12216 case Utils::Shader::TESS_CTRL:
12217 source = tcs_tested;
12218 break;
12219 case Utils::Shader::TESS_EVAL:
12220 source = tes_tested;
12221 break;
12222 case Utils::Shader::VERTEX:
12223 source = vs_tested;
12224 break;
12225 default:
12226 TCU_FAIL("Invalid enum");
12227 }
12228
12229 sprintf(buffer, "%d", alignment);
12230 Utils::replaceToken("ALIGN", position, buffer, source);
12231 Utils::replaceToken("TYPE", position, type_name, source);
12232 Utils::replaceToken("TYPE", position, type_name, source);
12233 }
12234 else
12235 {
12236 switch (stage)
12237 {
12238 case Utils::Shader::FRAGMENT:
12239 source = fs;
12240 break;
12241 case Utils::Shader::GEOMETRY:
12242 source = gs;
12243 break;
12244 case Utils::Shader::TESS_CTRL:
12245 source = tcs;
12246 break;
12247 case Utils::Shader::TESS_EVAL:
12248 source = tes;
12249 break;
12250 case Utils::Shader::VERTEX:
12251 source = vs;
12252 break;
12253 default:
12254 TCU_FAIL("Invalid enum");
12255 }
12256 }
12257
12258 return source;
12259 }
12260
12261 /** Checks if stage is supported
12262 *
12263 * @param stage Shader stage
12264 *
12265 * @return true if supported, false otherwise
12266 **/
12267 bool SSBMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES stage)
12268 {
12269 const Functions& gl = m_context.getRenderContext().getFunctions();
12270 GLint max_supported_buffers = 0;
12271 GLenum pname = 0;
12272
12273 switch (stage)
12274 {
12275 case Utils::Shader::COMPUTE:
12276 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
12277 break;
12278 case Utils::Shader::FRAGMENT:
12279 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
12280 break;
12281 case Utils::Shader::GEOMETRY:
12282 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
12283 break;
12284 case Utils::Shader::TESS_CTRL:
12285 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
12286 break;
12287 case Utils::Shader::TESS_EVAL:
12288 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
12289 break;
12290 case Utils::Shader::VERTEX:
12291 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
12292 break;
12293 default:
12294 TCU_FAIL("Invalid enum");
12295 }
12296
12297 gl.getIntegerv(pname, &max_supported_buffers);
12298 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12299
12300 return 1 <= max_supported_buffers;
12301 }
12302
12303 /** Constructor
12304 *
12305 * @param context Test framework context
12306 **/
12307 SSBAlignmentTest::SSBAlignmentTest(deqp::Context& context)
12308 : TextureTestBase(context, "ssb_alignment", "Test verifies offset and alignment of ssb buffer")
12309 {
12310 }
12311
12312 /** Get interface of program
12313 *
12314 * @param ignored
12315 * @param program_interface Interface of program
12316 * @param varying_passthrough Collection of connections between in and out variables
12317 **/
12318 void SSBAlignmentTest::getProgramInterface(GLuint /* test_case_index */, Utils::ProgramInterface& program_interface,
12319 Utils::VaryingPassthrough& varying_passthrough)
12320 {
12321 static const Utils::Type vec4 = Utils::Type::vec4;
12322
12323 #if WRKARD_UNIFORMBLOCKALIGNMENT
12324
12325 static const GLuint block_align = 16;
12326
12327 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12328
12329 static const GLuint block_align = 64;
12330
12331 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12332
12333 static const GLuint fifth_align = 16;
12334 static const GLuint vec4_stride = 16;
12335 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
12336
12337 const GLuint first_offset = 0; /* vec4 at 0 */
12338 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
12339 const GLuint third_offset =
12340 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
12341 const GLuint fourth_offset =
12342 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
12343 const GLuint fifth_offset =
12344 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, fifth_align); /* vec4[2] at 160 */
12345 const GLuint sixth_offset =
12346 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
12347
12348 Utils::Interface* structure = program_interface.Structure("Data");
12349
12350 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12351 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
12352
12353 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
12354 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
12355 Utils::Type::vec4.GetSize() /* offset */);
12356
12357 /* Prepare Block */
12358 Utils::Interface* vs_buf_Block = program_interface.Block("vs_buf_Block");
12359
12360 vs_buf_Block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12361 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
12362
12363 vs_buf_Block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12364 0 /* n_array_elements */, data_stride, second_offset);
12365
12366 vs_buf_Block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12367 2 /* n_array_elements */, data_stride, third_offset);
12368
12369 vs_buf_Block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
12370 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
12371
12372 vs_buf_Block->Member("fifth", "layout(align = 16)", 0 /* expected_component */, 0 /* expected_location */, vec4,
12373 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
12374
12375 vs_buf_Block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12376 0 /* n_array_elements */, data_stride, sixth_offset);
12377
12378 const GLuint stride = calculateStride(*vs_buf_Block);
12379 m_data.resize(stride);
12380 generateData(*vs_buf_Block, 0, m_data);
12381
12382 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12383
12384 /* Add uniform BLOCK */
12385 #if WRKARD_UNIFORMBLOCKALIGNMENT
12386 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_Block, 0,
12387 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12388 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12389 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_buf_Block, 0,
12390 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12391 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12392
12393 program_interface.CloneVertexInterface(varying_passthrough);
12394 }
12395
12396 /** Selects if "draw" stages are relevant for test
12397 *
12398 * @param ignored
12399 *
12400 * @return true if all stages support shader storage buffers, false otherwise
12401 **/
12402 bool SSBAlignmentTest::isDrawRelevant(GLuint /* test_case_index */)
12403 {
12404 const Functions& gl = m_context.getRenderContext().getFunctions();
12405 GLint gs_supported_buffers = 0;
12406 GLint tcs_supported_buffers = 0;
12407 GLint tes_supported_buffers = 0;
12408 GLint vs_supported_buffers = 0;
12409
12410 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
12411 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
12412 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
12413 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
12414
12415 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12416
12417 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
12418 (1 <= vs_supported_buffers));
12419 }
12420
12421 /** Constructor
12422 *
12423 * @param context Test framework context
12424 **/
12425 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context)
12426 : TextureTestBase(context, "varying_locations", "Test verifies that input and output locations are respected")
12427 {
12428 }
12429
12430 /** Constructor
12431 *
12432 * @param context Test context
12433 * @param test_name Name of test
12434 * @param test_description Description of test
12435 **/
12436 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context, const glw::GLchar* test_name,
12437 const glw::GLchar* test_description)
12438 : TextureTestBase(context, test_name, test_description)
12439 {
12440 }
12441
12442 /** Get interface of program
12443 *
12444 * @param test_case_index Test case
12445 * @param program_interface Interface of program
12446 * @param varying_passthrough Collection of connections between in and out variables
12447 **/
12448 void VaryingLocationsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
12449 Utils::VaryingPassthrough& varying_passthrough)
12450 {
12451 const Utils::Type type = getType(test_case_index);
12452
12453 m_first_data = type.GenerateDataPacked();
12454 m_last_data = type.GenerateDataPacked();
12455
12456 prepareShaderStage(Utils::Shader::FRAGMENT, type, program_interface, varying_passthrough);
12457 prepareShaderStage(Utils::Shader::GEOMETRY, type, program_interface, varying_passthrough);
12458 prepareShaderStage(Utils::Shader::TESS_CTRL, type, program_interface, varying_passthrough);
12459 prepareShaderStage(Utils::Shader::TESS_EVAL, type, program_interface, varying_passthrough);
12460 prepareShaderStage(Utils::Shader::VERTEX, type, program_interface, varying_passthrough);
12461 }
12462
12463 /** Get type name
12464 *
12465 * @param test_case_index Index of test case
12466 *
12467 * @return Name of type test in test_case_index
12468 **/
12469 std::string VaryingLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12470 {
12471 return getTypeName(test_case_index);
12472 }
12473
12474 /** Returns number of types to test
12475 *
12476 * @return Number of types, 34
12477 **/
12478 glw::GLuint VaryingLocationsTest::getTestCaseNumber()
12479 {
12480 return getTypesNumber();
12481 }
12482
12483 /** Selects if "compute" stage is relevant for test
12484 *
12485 * @param ignored
12486 *
12487 * @return false
12488 **/
12489 bool VaryingLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12490 {
12491 return false;
12492 }
12493
12494 /**
12495 *
12496 *
12497 **/
12498 std::string VaryingLocationsTest::prepareGlobals(GLint last_in_loc, GLint last_out_loc)
12499 {
12500 GLchar buffer[16];
12501 std::string globals = "const uint first_input_location = 0u;\n"
12502 "const uint first_output_location = 0u;\n"
12503 "const uint last_input_location = LAST_INPUTu;\n"
12504 "const uint last_output_location = LAST_OUTPUTu;\n";
12505 size_t position = 100; /* Skip first part */
12506
12507 sprintf(buffer, "%d", last_in_loc);
12508 Utils::replaceToken("LAST_INPUT", position, buffer, globals);
12509
12510 sprintf(buffer, "%d", last_out_loc);
12511 Utils::replaceToken("LAST_OUTPUT", position, buffer, globals);
12512
12513 return globals;
12514 }
12515
12516 /**
12517 *
12518 **/
12519 void VaryingLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12520 Utils::ProgramInterface& program_interface,
12521 Utils::VaryingPassthrough& varying_passthrough)
12522 {
12523 const GLuint array_length = 1;
12524 const GLuint first_in_loc = 0;
12525 const GLuint first_out_loc = 0;
12526 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12527 size_t position = 0;
12528
12529 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12530
12531 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12532
12533 const GLchar* qual_first_in = "layout (location = first_input_location)";
12534 const GLchar* qual_first_out = "layout (location = first_output_location)";
12535 const GLchar* qual_last_in = "layout (location = last_input_location)";
12536 const GLchar* qual_last_out = "layout (location = last_output_location)";
12537
12538 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12539 const GLuint type_size = type.GetSize();
12540
12541 std::string first_in_name = "PREFIXfirst";
12542 std::string first_out_name = "PREFIXfirst";
12543 std::string last_in_name = "PREFIXlast";
12544 std::string last_out_name = "PREFIXlast";
12545
12546 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12547 position = 0;
12548 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12549 position = 0;
12550 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12551 position = 0;
12552 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12553
12554 if (Utils::Shader::FRAGMENT == stage)
12555 {
12556 qual_first_in = "layout (location = first_input_location) flat";
12557 qual_last_in = "layout (location = last_input_location) flat";
12558 }
12559 if (Utils::Shader::GEOMETRY == stage)
12560 {
12561 qual_first_out = "layout (location = first_output_location) flat";
12562 qual_last_out = "layout (location = last_output_location) flat";
12563 }
12564
12565 Utils::Variable* first_in = si.Input(
12566 first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12567 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12568 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12569
12570 Utils::Variable* last_in =
12571 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12572 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12573 0u /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12574 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12575
12576 if (Utils::Shader::FRAGMENT != stage)
12577 {
12578 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12579
12580 Utils::Variable* first_out =
12581 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12582 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12583 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */,
12584 m_first_data.size() /* data_size */);
12585
12586 Utils::Variable* last_out = si.Output(
12587 last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12588 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12589 0u /* stride */, 0u /* offset */, (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12590
12591 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12592
12593 varying_passthrough.Add(stage, first_in, first_out);
12594 varying_passthrough.Add(stage, last_in, last_out);
12595 }
12596 else
12597 {
12598 /* No outputs for fragment shader, so last_output_location can be 0 */
12599 si.m_globals = prepareGlobals(last_in_loc, 0);
12600 }
12601 }
12602
12603 /** This test should be run with separable programs
12604 *
12605 * @param ignored
12606 *
12607 * @return true
12608 **/
12609 bool VaryingLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12610 {
12611 return false;
12612 }
12613
12614 /* Constants used by VertexAttribLocationsTest */
12615 const GLuint VertexAttribLocationsTest::m_base_vertex = 4;
12616 const GLuint VertexAttribLocationsTest::m_base_instance = 2;
12617 const GLuint VertexAttribLocationsTest::m_loc_vertex = 2;
12618 const GLuint VertexAttribLocationsTest::m_loc_instance = 5;
12619 const GLuint VertexAttribLocationsTest::m_n_instances = 4;
12620
12621 /** Constructor
12622 *
12623 * @param context Test framework context
12624 **/
12625 VertexAttribLocationsTest::VertexAttribLocationsTest(deqp::Context& context)
12626 : TextureTestBase(context, "vertex_attrib_locations",
12627 "Test verifies that attribute locations are respected by drawing operations")
12628 {
12629 }
12630
12631 /** Execute proper draw command for test case
12632 *
12633 * @param test_case_index Index of test case
12634 **/
12635 void VertexAttribLocationsTest::executeDrawCall(GLuint test_case_index)
12636 {
12637 const Functions& gl = m_context.getRenderContext().getFunctions();
12638
12639 switch (test_case_index)
12640 {
12641 case DRAWARRAYS:
12642 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
12643 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
12644 break;
12645 case DRAWARRAYSINSTANCED:
12646 gl.drawArraysInstanced(GL_PATCHES, 0 /* first */, 1 /* count */, m_n_instances);
12647 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArraysInstanced");
12648 break;
12649 case DRAWELEMENTS:
12650 gl.drawElements(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL);
12651 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
12652 break;
12653 case DRAWELEMENTSBASEVERTEX:
12654 gl.drawElementsBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_base_vertex);
12655 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsBaseVertex");
12656 break;
12657 case DRAWELEMENTSINSTANCED:
12658 gl.drawElementsInstanced(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances);
12659 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstanced");
12660 break;
12661 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12662 gl.drawElementsInstancedBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12663 m_base_instance);
12664 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseInstance");
12665 break;
12666 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12667 gl.drawElementsInstancedBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12668 m_base_vertex);
12669 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertex");
12670 break;
12671 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12672 gl.drawElementsInstancedBaseVertexBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL,
12673 m_n_instances, m_base_vertex, m_base_instance);
12674 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertexBaseInstance");
12675 break;
12676 default:
12677 TCU_FAIL("Invalid enum");
12678 }
12679 }
12680
12681 /** Get interface of program
12682 *
12683 * @param ignored
12684 * @param program_interface Interface of program
12685 * @param ignored
12686 **/
12687 void VertexAttribLocationsTest::getProgramInterface(GLuint /* test_case_index */,
12688 Utils::ProgramInterface& program_interface,
12689 Utils::VaryingPassthrough& /* varying_passthrough */)
12690 {
12691 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12692
12693 /* Globals */
12694 si.m_globals = "const uint vertex_index_location = 2;\n"
12695 "const uint instance_index_location = 5;\n";
12696
12697 /* Attributes */
12698 si.Input("vertex_index" /* name */, "layout (location = vertex_index_location)" /* qualifiers */,
12699 0 /* expected_componenet */, m_loc_vertex /* expected_location */, Utils::Type::uint /* type */,
12700 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 0u /* offset */,
12701 (GLvoid*)0 /* data */, 0 /* data_size */);
12702 si.Input("instance_index" /* name */, "layout (location = instance_index_location)" /* qualifiers */,
12703 0 /* expected_componenet */, m_loc_instance /* expected_location */, Utils::Type::uint /* type */,
12704 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 16u /* offset */,
12705 (GLvoid*)0 /* data */, 0 /* data_size */);
12706 }
12707
12708 /** Get name of test case
12709 *
12710 * @param test_case_index Index of test case
12711 *
12712 * @return Name of test case
12713 **/
12714 std::string VertexAttribLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12715 {
12716 std::string result;
12717
12718 switch (test_case_index)
12719 {
12720 case DRAWARRAYS:
12721 result = "DrawArrays";
12722 break;
12723 case DRAWARRAYSINSTANCED:
12724 result = "DrawArraysInstanced";
12725 break;
12726 case DRAWELEMENTS:
12727 result = "DrawElements";
12728 break;
12729 case DRAWELEMENTSBASEVERTEX:
12730 result = "DrawElementsBaseVertex";
12731 break;
12732 case DRAWELEMENTSINSTANCED:
12733 result = "DrawElementsInstanced";
12734 break;
12735 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12736 result = "DrawElementsInstancedBaseInstance";
12737 break;
12738 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12739 result = "DrawElementsInstancedBaseVertex";
12740 break;
12741 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12742 result = "DrawElementsInstancedBaseVertexBaseInstance";
12743 break;
12744 default:
12745 TCU_FAIL("Invalid enum");
12746 }
12747
12748 return result;
12749 }
12750
12751 /** Get number of test cases
12752 *
12753 * @return Number of test cases
12754 **/
12755 GLuint VertexAttribLocationsTest::getTestCaseNumber()
12756 {
12757 return TESTCASES_MAX;
12758 }
12759
12760 /** Prepare code snippet that will verify in and uniform variables
12761 *
12762 * @param ignored
12763 * @param ignored
12764 * @param stage Shader stage
12765 *
12766 * @return Code that verify variables
12767 **/
12768 std::string VertexAttribLocationsTest::getVerificationSnippet(GLuint /* test_case_index */,
12769 Utils::ProgramInterface& /* program_interface */,
12770 Utils::Shader::STAGES stage)
12771 {
12772 std::string verification;
12773
12774 if (Utils::Shader::VERTEX == stage)
12775 {
12776
12777 #if DEBUG_VERTEX_ATTRIB_LOCATIONS_TEST_VARIABLE
12778
12779 verification = "if (gl_InstanceID != instance_index)\n"
12780 " {\n"
12781 " result = 12u;\n"
12782 " }\n"
12783 " else if (gl_VertexID != vertex_index)\n"
12784 " {\n"
12785 " result = 11u;\n"
12786 " }\n";
12787
12788 #else
12789
12790 verification = "if ((gl_VertexID != vertex_index) ||\n"
12791 " (gl_InstanceID != instance_index) )\n"
12792 " {\n"
12793 " result = 0u;\n"
12794 " }\n";
12795
12796 #endif
12797 }
12798 else
12799 {
12800 verification = "";
12801 }
12802
12803 return verification;
12804 }
12805
12806 /** Selects if "compute" stage is relevant for test
12807 *
12808 * @param ignored
12809 *
12810 * @return false
12811 **/
12812 bool VertexAttribLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12813 {
12814 return false;
12815 }
12816
12817 /** Prepare attributes, vertex array object and array buffer
12818 *
12819 * @param ignored
12820 * @param ignored Interface of program
12821 * @param buffer Array buffer
12822 * @param vao Vertex array object
12823 **/
12824 void VertexAttribLocationsTest::prepareAttributes(GLuint test_case_index /* test_case_index */,
12825 Utils::ProgramInterface& /* program_interface */,
12826 Utils::Buffer& buffer, Utils::VertexArray& vao)
12827 {
12828 static const GLuint vertex_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12829 static const GLuint instance_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12830
12831 std::vector<GLuint> buffer_data;
12832 buffer_data.resize(8 + 8); /* vertex_index_data + instance_index_data */
12833
12834 GLubyte* ptr = (GLubyte*)&buffer_data[0];
12835
12836 /*
12837 When case index >=2, the test calls glDrawElement*(), such as glDrawElementsBaseVertex(), glDrawElementsInstanced(), glDrawElementsInstancedBaseInstance() and so on,
12838 So we need to change the buffer type as GL_ELEMENT_ARRAY_BUFFER
12839 */
12840 if (test_case_index >= 2)
12841 {
12842 buffer.m_buffer = Utils::Buffer::Element;
12843 }
12844 vao.Bind();
12845 buffer.Bind();
12846
12847 vao.Attribute(m_loc_vertex /* vertex_index */, Utils::Type::uint, 0 /* array_elements */, false /* normalized */,
12848 0 /* stride */, 0 /* offset */);
12849
12850 vao.Attribute(m_loc_instance /* instance_index */, Utils::Type::uint, 0 /* array_elements */,
12851 false /* normalized */, 0 /* stride */, (GLvoid*)sizeof(vertex_index_data) /* offset */);
12852 // when test_case_index is 5 or 7, the draw call is glDrawElementsInstancedBaseInstance, glDrawElementsInstancedBaseVertexBaseInstance
12853 // the instancecount is 4, the baseinstance is 2, the divisor should be set 2
12854 bool isBaseInstanced = (test_case_index == DRAWELEMENTSINSTANCEDBASEINSTANCE ||
12855 test_case_index == DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE);
12856 vao.Divisor(m_context.getRenderContext().getFunctions() /* gl */, m_loc_instance /* instance_index */,
12857 isBaseInstanced ? 2 : 1 /* divisor. 1 - advance once per instance */);
12858
12859 memcpy(ptr + 0, vertex_index_data, sizeof(vertex_index_data));
12860 memcpy(ptr + sizeof(vertex_index_data), instance_index_data, sizeof(instance_index_data));
12861
12862 buffer.Data(Utils::Buffer::StaticDraw, buffer_data.size() * sizeof(GLuint), ptr);
12863 }
12864
12865 /** This test should be run with separable programs
12866 *
12867 * @param ignored
12868 *
12869 * @return true
12870 **/
12871 bool VertexAttribLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12872 {
12873 return false;
12874 }
12875
12876 /** Constructor
12877 *
12878 * @param context Test framework context
12879 **/
12880 VaryingArrayLocationsTest::VaryingArrayLocationsTest(deqp::Context& context)
12881 : VaryingLocationsTest(context, "varying_array_locations",
12882 "Test verifies that input and output locations are respected for arrays")
12883 {
12884 }
12885
12886 /**
12887 *
12888 **/
12889 void VaryingArrayLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12890 Utils::ProgramInterface& program_interface,
12891 Utils::VaryingPassthrough& varying_passthrough)
12892 {
12893 const GLuint array_length = 1u;
12894 const GLuint first_in_loc = 0;
12895 const GLuint first_out_loc = 0;
12896 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12897 size_t position = 0;
12898
12899 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12900
12901 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12902
12903 const GLchar* qual_first_in = "layout (location = first_input_location)";
12904 const GLchar* qual_first_out = "layout (location = first_output_location)";
12905 const GLchar* qual_last_in = "layout (location = last_input_location)";
12906 const GLchar* qual_last_out = "layout (location = last_output_location)";
12907
12908 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12909 const GLuint type_size = type.GetSize();
12910
12911 std::string first_in_name = "PREFIXfirst";
12912 std::string first_out_name = "PREFIXfirst";
12913 std::string last_in_name = "PREFIXlast";
12914 std::string last_out_name = "PREFIXlast";
12915
12916 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12917 position = 0;
12918 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12919 position = 0;
12920 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12921 position = 0;
12922 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12923
12924 if (Utils::Shader::FRAGMENT == stage)
12925 {
12926 qual_first_in = "layout (location = first_input_location) flat";
12927 qual_last_in = "layout (location = last_input_location) flat";
12928 }
12929 if (Utils::Shader::GEOMETRY == stage)
12930 {
12931 qual_first_out = "layout (location = first_output_location) flat";
12932 qual_last_out = "layout (location = last_output_location) flat";
12933 }
12934
12935 Utils::Variable* first_in =
12936 si.Input(first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12937 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12938 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12939 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12940
12941 Utils::Variable* last_in =
12942 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12943 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12944 array_length /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12945 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12946
12947 if (Utils::Shader::FRAGMENT != stage)
12948 {
12949 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12950
12951 Utils::Variable* first_out =
12952 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12953 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12954 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12955 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12956
12957 Utils::Variable* last_out =
12958 si.Output(last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12959 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12960 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12961 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12962
12963 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12964
12965 varying_passthrough.Add(stage, first_in, first_out);
12966 varying_passthrough.Add(stage, last_in, last_out);
12967 }
12968 else
12969 {
12970 /* No outputs for fragment shader, so last_output_location can be 0 */
12971 si.m_globals = prepareGlobals(last_in_loc, 0);
12972 }
12973 }
12974
12975 /** Constructor
12976 *
12977 * @param context Test framework context
12978 **/
12979 VaryingStructureLocationsTest::VaryingStructureLocationsTest(deqp::Context& context)
12980 : TextureTestBase(context, "varying_structure_locations",
12981 "Test verifies that locations are respected when structures are used as in and out ")
12982 {
12983 }
12984
12985 /** Prepare code snippet that will pass in variables to out variables
12986 *
12987 * @param ignored
12988 * @param varying_passthrough Collection of connections between in and out variables
12989 * @param stage Shader stage
12990 *
12991 * @return Code that pass in variables to next stage
12992 **/
12993 std::string VaryingStructureLocationsTest::getPassSnippet(GLuint /* test_case_index */,
12994 Utils::VaryingPassthrough& varying_passthrough,
12995 Utils::Shader::STAGES stage)
12996 {
12997 std::string result;
12998
12999 if (Utils::Shader::VERTEX != stage)
13000 {
13001 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
13002 }
13003 else
13004 {
13005 result = " vs_tcs_output[0].single = vs_in_single[0];\n"
13006 " vs_tcs_output[0].array[0] = vs_in_array[0];\n";
13007 }
13008
13009 return result;
13010 }
13011
13012 /** Get interface of program
13013 *
13014 * @param test_case_index Test case
13015 * @param program_interface Interface of program
13016 * @param varying_passthrough Collection of connections between in and out variables
13017 **/
13018 void VaryingStructureLocationsTest::getProgramInterface(GLuint test_case_index,
13019 Utils::ProgramInterface& program_interface,
13020 Utils::VaryingPassthrough& varying_passthrough)
13021 {
13022 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
13023 const Utils::Type type = getType(test_case_index);
13024
13025 /* Prepare data */
13026 // We should call GenerateDataPacked() to generate data, which can make sure the data in shader is correct
13027 m_single_data = type.GenerateDataPacked();
13028 m_array_data = type.GenerateDataPacked();
13029
13030 m_data.resize(m_single_data.size() + m_array_data.size());
13031 GLubyte* ptr = (GLubyte*)&m_data[0];
13032 memcpy(ptr, &m_single_data[0], m_single_data.size());
13033 memcpy(ptr + m_single_data.size(), &m_array_data[0], m_array_data.size());
13034
13035 Utils::Interface* structure = program_interface.Structure("Data");
13036
13037 structure->Member("single", "" /* qualifiers */, 0 /* component */, 0 /* location */, type, false /* normalized */,
13038 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */);
13039
13040 // the second struct member 's location should not be 0, it is based on by how many the locations the first struct member consumed.
13041 structure->Member("array", "" /* qualifiers */, 0 /* component */, type.GetLocations() /* location */, type,
13042 false /* normalized */, 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */);
13043
13044 si.Input("vs_in_single", "layout (location = 0)", 0 /* component */, 0 /* location */, type, false /* normalized */,
13045 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_single_data[0] /* data */,
13046 m_single_data.size() /* data_size */);
13047
13048 si.Input("vs_in_array", "layout (location = 8)", 0 /* component */, 8 /* location */, type, false /* normalized */,
13049 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */,
13050 (GLvoid*)&m_array_data[0] /* data */, m_array_data.size() /* data_size */);
13051
13052 si.Output("vs_tcs_output", "layout (location = 0)", 0 /* component */, 0 /* location */, structure,
13053 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
13054 m_data.size() /* data_size */);
13055
13056 program_interface.CloneVertexInterface(varying_passthrough);
13057 }
13058
13059 /** Get type name
13060 *
13061 * @param test_case_index Index of test case
13062 *
13063 * @return Name of type test in test_case_index
13064 **/
13065 std::string VaryingStructureLocationsTest::getTestCaseName(glw::GLuint test_case_index)
13066 {
13067 return getTypeName(test_case_index);
13068 }
13069
13070 /** Returns number of types to test
13071 *
13072 * @return Number of types, 34
13073 **/
13074 glw::GLuint VaryingStructureLocationsTest::getTestCaseNumber()
13075 {
13076 return getTypesNumber();
13077 }
13078
13079 /** Selects if "compute" stage is relevant for test
13080 *
13081 * @param ignored
13082 *
13083 * @return false
13084 **/
13085 bool VaryingStructureLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13086 {
13087 return false;
13088 }
13089
13090 /** This test should be run with separable programs
13091 *
13092 * @param ignored
13093 *
13094 * @return true
13095 **/
13096 bool VaryingStructureLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13097 {
13098 return false;
13099 }
13100
13101 /** Constructor
13102 *
13103 * @param context Test context
13104 * @param test_name Name of test
13105 * @param test_description Description of test
13106 **/
13107 VaryingStructureMemberLocationTest::VaryingStructureMemberLocationTest(deqp::Context& context)
13108 : NegativeTestBase(context, "varying_structure_member_location",
13109 "Test verifies that compiler does not allow location qualifier on member of structure")
13110 {
13111 }
13112
13113 /** Source for given test case and stage
13114 *
13115 * @param test_case_index Index of test case
13116 * @param stage Shader stage
13117 *
13118 * @return Shader source
13119 **/
13120 std::string VaryingStructureMemberLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13121 {
13122 static const GLchar* struct_definition = "struct Data {\n"
13123 " vec4 gohan;\n"
13124 #if DEBUG_NEG_REMOVE_ERROR
13125 " /* layout (location = 4) */ vec4 goten;\n"
13126 #else
13127 " layout (location = 4) vec4 goten;\n"
13128 #endif /* DEBUG_NEG_REMOVE_ERROR */
13129 "};\n";
13130 static const GLchar* input_use = " result += data.gohan + data.goten;\n";
13131 static const GLchar* input_var = "in Data dataARRAY;\n";
13132 static const GLchar* output_var = "out Data dataARRAY;\n";
13133 static const GLchar* output_use = " dataINDEX.gohan = result / 2;\n"
13134 " dataINDEX.goten = result / 4 - dataINDEX.gohan;\n";
13135 static const GLchar* fs = "#version 430 core\n"
13136 "#extension GL_ARB_enhanced_layouts : require\n"
13137 "\n"
13138 "in vec4 gs_fs;\n"
13139 "out vec4 fs_out;\n"
13140 "\n"
13141 "void main()\n"
13142 "{\n"
13143 " fs_out = gs_fs;\n"
13144 "}\n"
13145 "\n";
13146 static const GLchar* fs_tested = "#version 430 core\n"
13147 "#extension GL_ARB_enhanced_layouts : require\n"
13148 "\n"
13149 "STRUCT_DEFINITION"
13150 "\n"
13151 "VARIABLE_DEFINITION"
13152 "\n"
13153 "in vec4 gs_fs;\n"
13154 "out vec4 fs_out;\n"
13155 "\n"
13156 "void main()\n"
13157 "{\n"
13158 " vec4 result = gs_fs;\n"
13159 "\n"
13160 "VARIABLE_USE"
13161 "\n"
13162 " fs_out += result;\n"
13163 "}\n"
13164 "\n";
13165 static const GLchar* gs = "#version 430 core\n"
13166 "#extension GL_ARB_enhanced_layouts : require\n"
13167 "\n"
13168 "layout(points) in;\n"
13169 "layout(triangle_strip, max_vertices = 4) out;\n"
13170 "\n"
13171 "in vec4 tes_gs[];\n"
13172 "out vec4 gs_fs;\n"
13173 "\n"
13174 "void main()\n"
13175 "{\n"
13176 " gs_fs = tes_gs[0];\n"
13177 " gl_Position = vec4(-1, -1, 0, 1);\n"
13178 " EmitVertex();\n"
13179 " gs_fs = tes_gs[0];\n"
13180 " gl_Position = vec4(-1, 1, 0, 1);\n"
13181 " EmitVertex();\n"
13182 " gs_fs = tes_gs[0];\n"
13183 " gl_Position = vec4(1, -1, 0, 1);\n"
13184 " EmitVertex();\n"
13185 " gs_fs = tes_gs[0];\n"
13186 " gl_Position = vec4(1, 1, 0, 1);\n"
13187 " EmitVertex();\n"
13188 "}\n"
13189 "\n";
13190 static const GLchar* gs_tested = "#version 430 core\n"
13191 "#extension GL_ARB_enhanced_layouts : require\n"
13192 "\n"
13193 "layout(points) in;\n"
13194 "layout(triangle_strip, max_vertices = 4) out;\n"
13195 "\n"
13196 "STRUCT_DEFINITION"
13197 "\n"
13198 "VARIABLE_DEFINITION"
13199 "\n"
13200 "in vec4 tes_gs[];\n"
13201 "out vec4 gs_fs;\n"
13202 "\n"
13203 "void main()\n"
13204 "{\n"
13205 " vec4 result = tes_gs[0];\n"
13206 "\n"
13207 "VARIABLE_USE"
13208 "\n"
13209 " gs_fs = result;\n"
13210 " gl_Position = vec4(-1, -1, 0, 1);\n"
13211 " EmitVertex();\n"
13212 " gs_fs = result;\n"
13213 " gl_Position = vec4(-1, 1, 0, 1);\n"
13214 " EmitVertex();\n"
13215 " gs_fs = result;\n"
13216 " gl_Position = vec4(1, -1, 0, 1);\n"
13217 " EmitVertex();\n"
13218 " gs_fs = result;\n"
13219 " gl_Position = vec4(1, 1, 0, 1);\n"
13220 " EmitVertex();\n"
13221 "}\n"
13222 "\n";
13223 static const GLchar* tcs = "#version 430 core\n"
13224 "#extension GL_ARB_enhanced_layouts : require\n"
13225 "\n"
13226 "layout(vertices = 1) out;\n"
13227 "\n"
13228 "in vec4 vs_tcs[];\n"
13229 "out vec4 tcs_tes[];\n"
13230 "\n"
13231 "void main()\n"
13232 "{\n"
13233 "\n"
13234 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13235 "\n"
13236 " gl_TessLevelOuter[0] = 1.0;\n"
13237 " gl_TessLevelOuter[1] = 1.0;\n"
13238 " gl_TessLevelOuter[2] = 1.0;\n"
13239 " gl_TessLevelOuter[3] = 1.0;\n"
13240 " gl_TessLevelInner[0] = 1.0;\n"
13241 " gl_TessLevelInner[1] = 1.0;\n"
13242 "}\n"
13243 "\n";
13244 static const GLchar* tcs_tested = "#version 430 core\n"
13245 "#extension GL_ARB_enhanced_layouts : require\n"
13246 "\n"
13247 "layout(vertices = 1) out;\n"
13248 "\n"
13249 "STRUCT_DEFINITION"
13250 "\n"
13251 "VARIABLE_DEFINITION"
13252 "\n"
13253 "in vec4 vs_tcs[];\n"
13254 "out vec4 tcs_tes[];\n"
13255 "\n"
13256 "void main()\n"
13257 "{\n"
13258 " vec4 result = vs_tcs[gl_InvocationID];\n"
13259 "\n"
13260 "VARIABLE_USE"
13261 "\n"
13262 " tcs_tes[gl_InvocationID] = result;\n"
13263 "\n"
13264 " gl_TessLevelOuter[0] = 1.0;\n"
13265 " gl_TessLevelOuter[1] = 1.0;\n"
13266 " gl_TessLevelOuter[2] = 1.0;\n"
13267 " gl_TessLevelOuter[3] = 1.0;\n"
13268 " gl_TessLevelInner[0] = 1.0;\n"
13269 " gl_TessLevelInner[1] = 1.0;\n"
13270 "}\n"
13271 "\n";
13272 static const GLchar* tes = "#version 430 core\n"
13273 "#extension GL_ARB_enhanced_layouts : require\n"
13274 "\n"
13275 "layout(isolines, point_mode) in;\n"
13276 "\n"
13277 "in vec4 tcs_tes[];\n"
13278 "out vec4 tes_gs;\n"
13279 "\n"
13280 "void main()\n"
13281 "{\n"
13282 " tes_gs = tcs_tes[0];\n"
13283 "}\n"
13284 "\n";
13285 static const GLchar* tes_tested = "#version 430 core\n"
13286 "#extension GL_ARB_enhanced_layouts : require\n"
13287 "\n"
13288 "layout(isolines, point_mode) in;\n"
13289 "\n"
13290 "STRUCT_DEFINITION"
13291 "\n"
13292 "VARIABLE_DEFINITION"
13293 "\n"
13294 "in vec4 tcs_tes[];\n"
13295 "out vec4 tes_gs;\n"
13296 "\n"
13297 "void main()\n"
13298 "{\n"
13299 " vec4 result = tcs_tes[0];\n"
13300 "\n"
13301 "VARIABLE_USE"
13302 "\n"
13303 " tes_gs += result;\n"
13304 "}\n"
13305 "\n";
13306 static const GLchar* vs = "#version 430 core\n"
13307 "#extension GL_ARB_enhanced_layouts : require\n"
13308 "\n"
13309 "in vec4 in_vs;\n"
13310 "out vec4 vs_tcs;\n"
13311 "\n"
13312 "void main()\n"
13313 "{\n"
13314 " vs_tcs = in_vs;\n"
13315 "}\n"
13316 "\n";
13317 static const GLchar* vs_tested = "#version 430 core\n"
13318 "#extension GL_ARB_enhanced_layouts : require\n"
13319 "\n"
13320 "STRUCT_DEFINITION"
13321 "\n"
13322 "VARIABLE_DEFINITION"
13323 "\n"
13324 "in vec4 in_vs;\n"
13325 "out vec4 vs_tcs;\n"
13326 "\n"
13327 "void main()\n"
13328 "{\n"
13329 " vec4 result = in_vs;\n"
13330 "\n"
13331 "VARIABLE_USE"
13332 "\n"
13333 " vs_tcs += result;\n"
13334 "}\n"
13335 "\n";
13336
13337 std::string source;
13338 testCase& test_case = m_test_cases[test_case_index];
13339 const GLchar* var_definition = input_var;
13340 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
13341 const GLchar* array = "";
13342 const GLchar* index = "";
13343
13344 if (!test_case.m_is_input)
13345 {
13346 var_definition = output_var;
13347 var_use = output_use;
13348 }
13349
13350 if (test_case.m_stage == stage)
13351 {
13352 size_t position = 0;
13353 size_t temp = 0;
13354
13355 switch (stage)
13356 {
13357 case Utils::Shader::FRAGMENT:
13358 source = fs_tested;
13359 break;
13360 case Utils::Shader::GEOMETRY:
13361 source = gs_tested;
13362 array = test_case.m_is_input ? "[]" : "";
13363 index = test_case.m_is_input ? "[0]" : "";
13364 break;
13365 case Utils::Shader::TESS_CTRL:
13366 source = tcs_tested;
13367 array = "[]";
13368 index = "[gl_InvocationID]";
13369 break;
13370 case Utils::Shader::TESS_EVAL:
13371 source = tes_tested;
13372 array = test_case.m_is_input ? "[]" : "";
13373 index = test_case.m_is_input ? "[0]" : "";
13374 break;
13375 case Utils::Shader::VERTEX:
13376 source = vs_tested;
13377 break;
13378 default:
13379 TCU_FAIL("Invalid enum");
13380 }
13381
13382 Utils::replaceToken("STRUCT_DEFINITION", position, struct_definition, source);
13383 temp = position;
13384 Utils::replaceToken("VARIABLE_DEFINITION", position, var_definition, source);
13385 position = temp;
13386 Utils::replaceToken("ARRAY", position, array, source);
13387 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13388
13389 Utils::replaceAllTokens("INDEX", index, source);
13390 }
13391 else
13392 {
13393 switch (stage)
13394 {
13395 case Utils::Shader::FRAGMENT:
13396 source = fs;
13397 break;
13398 case Utils::Shader::GEOMETRY:
13399 source = gs;
13400 break;
13401 case Utils::Shader::TESS_CTRL:
13402 source = tcs;
13403 break;
13404 case Utils::Shader::TESS_EVAL:
13405 source = tes;
13406 break;
13407 case Utils::Shader::VERTEX:
13408 source = vs;
13409 break;
13410 default:
13411 TCU_FAIL("Invalid enum");
13412 }
13413 }
13414
13415 return source;
13416 }
13417
13418 /** Get description of test case
13419 *
13420 * @param test_case_index Index of test case
13421 *
13422 * @return Test case description
13423 **/
13424 std::string VaryingStructureMemberLocationTest::getTestCaseName(GLuint test_case_index)
13425 {
13426 std::stringstream stream;
13427 testCase& test_case = m_test_cases[test_case_index];
13428
13429 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13430
13431 if (true == test_case.m_is_input)
13432 {
13433 stream << "input";
13434 }
13435 else
13436 {
13437 stream << "output";
13438 }
13439
13440 return stream.str();
13441 }
13442
13443 /** Get number of test cases
13444 *
13445 * @return Number of test cases
13446 **/
13447 GLuint VaryingStructureMemberLocationTest::getTestCaseNumber()
13448 {
13449 return static_cast<GLuint>(m_test_cases.size());
13450 }
13451
13452 /** Selects if "compute" stage is relevant for test
13453 *
13454 * @param ignored
13455 *
13456 * @return false
13457 **/
13458 bool VaryingStructureMemberLocationTest::isComputeRelevant(GLuint /* test_case_index */)
13459 {
13460 return false;
13461 }
13462
13463 /** Prepare all test cases
13464 *
13465 **/
13466 void VaryingStructureMemberLocationTest::testInit()
13467 {
13468 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13469 {
13470 if (Utils::Shader::COMPUTE == stage)
13471 {
13472 continue;
13473 }
13474
13475 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
13476 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
13477
13478 /* It is a compile-time error to declare a struct as a VS input */
13479 if (Utils::Shader::VERTEX != stage)
13480 {
13481 m_test_cases.push_back(test_case_in);
13482 }
13483
13484 if (Utils::Shader::FRAGMENT != stage)
13485 {
13486 m_test_cases.push_back(test_case_out);
13487 }
13488 }
13489 }
13490
13491 /** Constructor
13492 *
13493 * @param context Test framework context
13494 **/
13495 VaryingBlockLocationsTest::VaryingBlockLocationsTest(deqp::Context& context)
13496 : TextureTestBase(context, "varying_block_locations",
13497 "Test verifies that locations are respected when blocks are used as in and out ")
13498 {
13499 }
13500
13501 /** Prepare code snippet that will pass in variables to out variables
13502 *
13503 * @param ignored
13504 * @param varying_passthrough Collection of connections between in and out variables
13505 * @param stage Shader stage
13506 *
13507 * @return Code that pass in variables to next stage
13508 **/
13509 std::string VaryingBlockLocationsTest::getPassSnippet(GLuint /* test_case_index */,
13510 Utils::VaryingPassthrough& varying_passthrough,
13511 Utils::Shader::STAGES stage)
13512 {
13513 std::string result;
13514
13515 if (Utils::Shader::VERTEX != stage)
13516 {
13517 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
13518 }
13519 else
13520 {
13521 result = "vs_tcs_block.third = vs_in_third;\n"
13522 " vs_tcs_block.fourth = vs_in_fourth;\n"
13523 " vs_tcs_block.fifth = vs_in_fifth;\n";
13524 }
13525
13526 return result;
13527 }
13528
13529 /** Get interface of program
13530 *
13531 * @param ignored
13532 * @param program_interface Interface of program
13533 * @param varying_passthrough Collection of connections between in and out variables
13534 **/
13535 void VaryingBlockLocationsTest::getProgramInterface(GLuint /* test_case_index */,
13536 Utils::ProgramInterface& program_interface,
13537 Utils::VaryingPassthrough& varying_passthrough)
13538 {
13539 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
13540 const Utils::Type vec4 = Utils::Type::vec4;
13541
13542 /* Prepare data */
13543 m_third_data = vec4.GenerateData();
13544 m_fourth_data = vec4.GenerateData();
13545 m_fifth_data = vec4.GenerateData();
13546
13547 /* Memory layout is different from location layout */
13548 const GLuint fifth_offset = 0u;
13549 const GLuint third_offset = static_cast<GLuint>(fifth_offset + m_fifth_data.size());
13550 const GLuint fourth_offset = static_cast<GLuint>(third_offset + m_fourth_data.size());
13551
13552 m_data.resize(fourth_offset + m_fourth_data.size());
13553 GLubyte* ptr = (GLubyte*)&m_data[0];
13554 memcpy(ptr + third_offset, &m_third_data[0], m_third_data.size());
13555 memcpy(ptr + fourth_offset, &m_fourth_data[0], m_fourth_data.size());
13556 memcpy(ptr + fifth_offset, &m_fifth_data[0], m_fifth_data.size());
13557
13558 Utils::Interface* block = program_interface.Block("vs_tcs_Block");
13559
13560 block->Member("fifth", "" /* qualifiers */, 0 /* component */, 4 /* location */, vec4, false /* normalized */,
13561 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */);
13562
13563 block->Member("third", "layout (location = 2)" /* qualifiers */, 0 /* component */, 2 /* location */, vec4,
13564 false /* normalized */, 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */);
13565
13566 block->Member("fourth", "" /* qualifiers */, 0 /* component */, 3 /* location */, vec4, false /* normalized */,
13567 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */);
13568
13569 si.Output("vs_tcs_block", "layout (location = 4)", 0 /* component */, 4 /* location */, block,
13570 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
13571 m_data.size() /* data_size */);
13572
13573 si.Input("vs_in_third", "layout (location = 0)", 0 /* component */, 0 /* location */, vec4, false /* normalized */,
13574 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */,
13575 (GLvoid*)&m_third_data[0] /* data */, m_third_data.size() /* data_size */);
13576
13577 si.Input("vs_in_fourth", "layout (location = 1)", 0 /* component */, 1 /* location */, vec4, false /* normalized */,
13578 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */,
13579 (GLvoid*)&m_fourth_data[0] /* data */, m_fourth_data.size() /* data_size */);
13580
13581 si.Input("vs_in_fifth", "layout (location = 2)", 0 /* component */, 2 /* location */, vec4, false /* normalized */,
13582 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */,
13583 (GLvoid*)&m_fifth_data[0] /* data */, m_fifth_data.size() /* data_size */);
13584
13585 program_interface.CloneVertexInterface(varying_passthrough);
13586 }
13587
13588 /** Selects if "compute" stage is relevant for test
13589 *
13590 * @param ignored
13591 *
13592 * @return false
13593 **/
13594 bool VaryingBlockLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13595 {
13596 return false;
13597 }
13598
13599 /** This test should be run with separable programs
13600 *
13601 * @param ignored
13602 *
13603 * @return true
13604 **/
13605 bool VaryingBlockLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13606 {
13607 return false;
13608 }
13609
13610 /** Constructor
13611 *
13612 * @param context Test framework context
13613 **/
13614 VaryingBlockMemberLocationsTest::VaryingBlockMemberLocationsTest(deqp::Context& context)
13615 : NegativeTestBase(
13616 context, "varying_block_member_locations",
13617 "Test verifies that compilation error is reported when not all members of block are qualified with location")
13618 {
13619 }
13620
13621 /** Source for given test case and stage
13622 *
13623 * @param test_case_index Index of test case
13624 * @param stage Shader stage
13625 *
13626 * @return Shader source
13627 **/
13628 std::string VaryingBlockMemberLocationsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13629 {
13630 static const GLchar* block_definition_all = "Goku {\n"
13631 " layout (location = 2) vec4 gohan;\n"
13632 " layout (location = 4) vec4 goten;\n"
13633 " layout (location = 6) vec4 chichi;\n"
13634 "} gokuARRAY;\n";
13635 static const GLchar* block_definition_one = "Goku {\n"
13636 " vec4 gohan;\n"
13637 #if DEBUG_NEG_REMOVE_ERROR
13638 " /* layout (location = 4) */ vec4 goten;\n"
13639 #else
13640 " layout (location = 4) vec4 goten;\n"
13641 #endif /* DEBUG_NEG_REMOVE_ERROR */
13642 " vec4 chichi;\n"
13643 "} gokuARRAY;\n";
13644 static const GLchar* input_use = " result += gokuINDEX.gohan + gokuINDEX.goten + gokuINDEX.chichi;\n";
13645 static const GLchar* output_use = " gokuINDEX.gohan = result / 2;\n"
13646 " gokuINDEX.goten = result / 4 - gokuINDEX.gohan;\n"
13647 " gokuINDEX.chichi = result / 8 - gokuINDEX.goten;\n";
13648 static const GLchar* fs = "#version 430 core\n"
13649 "#extension GL_ARB_enhanced_layouts : require\n"
13650 "\n"
13651 "in vec4 gs_fs;\n"
13652 "out vec4 fs_out;\n"
13653 "\n"
13654 "void main()\n"
13655 "{\n"
13656 " fs_out = gs_fs;\n"
13657 "}\n"
13658 "\n";
13659 static const GLchar* fs_tested = "#version 430 core\n"
13660 "#extension GL_ARB_enhanced_layouts : require\n"
13661 "\n"
13662 "DIRECTION BLOCK_DEFINITION"
13663 "\n"
13664 "in vec4 gs_fs;\n"
13665 "out vec4 fs_out;\n"
13666 "\n"
13667 "void main()\n"
13668 "{\n"
13669 " vec4 result = gs_fs;\n"
13670 "\n"
13671 "VARIABLE_USE"
13672 "\n"
13673 " fs_out = result;\n"
13674 "}\n"
13675 "\n";
13676 static const GLchar* gs = "#version 430 core\n"
13677 "#extension GL_ARB_enhanced_layouts : require\n"
13678 "\n"
13679 "layout(points) in;\n"
13680 "layout(triangle_strip, max_vertices = 4) out;\n"
13681 "\n"
13682 "in vec4 tes_gs[];\n"
13683 "out vec4 gs_fs;\n"
13684 "\n"
13685 "void main()\n"
13686 "{\n"
13687 " gs_fs = tes_gs[0];\n"
13688 " gl_Position = vec4(-1, -1, 0, 1);\n"
13689 " EmitVertex();\n"
13690 " gs_fs = tes_gs[0];\n"
13691 " gl_Position = vec4(-1, 1, 0, 1);\n"
13692 " EmitVertex();\n"
13693 " gs_fs = tes_gs[0];\n"
13694 " gl_Position = vec4(1, -1, 0, 1);\n"
13695 " EmitVertex();\n"
13696 " gs_fs = tes_gs[0];\n"
13697 " gl_Position = vec4(1, 1, 0, 1);\n"
13698 " EmitVertex();\n"
13699 "}\n"
13700 "\n";
13701 static const GLchar* gs_tested = "#version 430 core\n"
13702 "#extension GL_ARB_enhanced_layouts : require\n"
13703 "\n"
13704 "layout(points) in;\n"
13705 "layout(triangle_strip, max_vertices = 4) out;\n"
13706 "\n"
13707 "DIRECTION BLOCK_DEFINITION"
13708 "\n"
13709 "in vec4 tes_gs[];\n"
13710 "out vec4 gs_fs;\n"
13711 "\n"
13712 "void main()\n"
13713 "{\n"
13714 " vec4 result = tes_gs[0];\n"
13715 "\n"
13716 "VARIABLE_USE"
13717 "\n"
13718 " gs_fs = result;\n"
13719 " gl_Position = vec4(-1, -1, 0, 1);\n"
13720 " EmitVertex();\n"
13721 " gs_fs = result;\n"
13722 " gl_Position = vec4(-1, 1, 0, 1);\n"
13723 " EmitVertex();\n"
13724 " gs_fs = result;\n"
13725 " gl_Position = vec4(1, -1, 0, 1);\n"
13726 " EmitVertex();\n"
13727 " gs_fs = result;\n"
13728 " gl_Position = vec4(1, 1, 0, 1);\n"
13729 " EmitVertex();\n"
13730 "}\n"
13731 "\n";
13732 static const GLchar* tcs = "#version 430 core\n"
13733 "#extension GL_ARB_enhanced_layouts : require\n"
13734 "\n"
13735 "layout(vertices = 1) out;\n"
13736 "\n"
13737 "in vec4 vs_tcs[];\n"
13738 "out vec4 tcs_tes[];\n"
13739 "\n"
13740 "void main()\n"
13741 "{\n"
13742 "\n"
13743 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13744 "\n"
13745 " gl_TessLevelOuter[0] = 1.0;\n"
13746 " gl_TessLevelOuter[1] = 1.0;\n"
13747 " gl_TessLevelOuter[2] = 1.0;\n"
13748 " gl_TessLevelOuter[3] = 1.0;\n"
13749 " gl_TessLevelInner[0] = 1.0;\n"
13750 " gl_TessLevelInner[1] = 1.0;\n"
13751 "}\n"
13752 "\n";
13753 static const GLchar* tcs_tested = "#version 430 core\n"
13754 "#extension GL_ARB_enhanced_layouts : require\n"
13755 "\n"
13756 "layout(vertices = 1) out;\n"
13757 "\n"
13758 "DIRECTION BLOCK_DEFINITION"
13759 "\n"
13760 "in vec4 vs_tcs[];\n"
13761 "out vec4 tcs_tes[];\n"
13762 "\n"
13763 "void main()\n"
13764 "{\n"
13765 " vec4 result = vs_tcs[gl_InvocationID];\n"
13766 "\n"
13767 "VARIABLE_USE"
13768 "\n"
13769 " tcs_tes[gl_InvocationID] = result;\n"
13770 "\n"
13771 " gl_TessLevelOuter[0] = 1.0;\n"
13772 " gl_TessLevelOuter[1] = 1.0;\n"
13773 " gl_TessLevelOuter[2] = 1.0;\n"
13774 " gl_TessLevelOuter[3] = 1.0;\n"
13775 " gl_TessLevelInner[0] = 1.0;\n"
13776 " gl_TessLevelInner[1] = 1.0;\n"
13777 "}\n"
13778 "\n";
13779 static const GLchar* tes = "#version 430 core\n"
13780 "#extension GL_ARB_enhanced_layouts : require\n"
13781 "\n"
13782 "layout(isolines, point_mode) in;\n"
13783 "\n"
13784 "in vec4 tcs_tes[];\n"
13785 "out vec4 tes_gs;\n"
13786 "\n"
13787 "void main()\n"
13788 "{\n"
13789 " tes_gs = tcs_tes[0];\n"
13790 "}\n"
13791 "\n";
13792 static const GLchar* tes_tested = "#version 430 core\n"
13793 "#extension GL_ARB_enhanced_layouts : require\n"
13794 "\n"
13795 "layout(isolines, point_mode) in;\n"
13796 "\n"
13797 "DIRECTION BLOCK_DEFINITION"
13798 "\n"
13799 "in vec4 tcs_tes[];\n"
13800 "out vec4 tes_gs;\n"
13801 "\n"
13802 "void main()\n"
13803 "{\n"
13804 " vec4 result = tcs_tes[0];\n"
13805 "\n"
13806 "VARIABLE_USE"
13807 "\n"
13808 " tes_gs = result;\n"
13809 "}\n"
13810 "\n";
13811 static const GLchar* vs = "#version 430 core\n"
13812 "#extension GL_ARB_enhanced_layouts : require\n"
13813 "\n"
13814 "in vec4 in_vs;\n"
13815 "out vec4 vs_tcs;\n"
13816 "\n"
13817 "void main()\n"
13818 "{\n"
13819 " vs_tcs = in_vs;\n"
13820 "}\n"
13821 "\n";
13822 static const GLchar* vs_tested = "#version 430 core\n"
13823 "#extension GL_ARB_enhanced_layouts : require\n"
13824 "\n"
13825 "DIRECTION BLOCK_DEFINITION"
13826 "\n"
13827 "in vec4 in_vs;\n"
13828 "out vec4 vs_tcs;\n"
13829 "\n"
13830 "void main()\n"
13831 "{\n"
13832 " vec4 result = in_vs;\n"
13833 "\n"
13834 "VARIABLE_USE"
13835 "\n"
13836 " vs_tcs = result;\n"
13837 "}\n"
13838 "\n";
13839
13840 const GLchar* array = "";
13841 const GLchar* direction = "in";
13842 const GLchar* index = "";
13843 std::string source;
13844 testCase& test_case = m_test_cases[test_case_index];
13845 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
13846 const GLchar* definition = test_case.m_qualify_all ? block_definition_all : block_definition_one;
13847
13848 if (!test_case.m_is_input)
13849 {
13850 direction = "out";
13851 var_use = output_use;
13852 }
13853
13854 if (test_case.m_stage == stage)
13855 {
13856 size_t position = 0;
13857 size_t temp = 0;
13858
13859 switch (stage)
13860 {
13861 case Utils::Shader::FRAGMENT:
13862 source = fs_tested;
13863 break;
13864 case Utils::Shader::GEOMETRY:
13865 source = gs_tested;
13866 array = test_case.m_is_input ? "[]" : "";
13867 index = test_case.m_is_input ? "[0]" : "";
13868 break;
13869 case Utils::Shader::TESS_CTRL:
13870 source = tcs_tested;
13871 array = "[]";
13872 index = "[gl_InvocationID]";
13873 break;
13874 case Utils::Shader::TESS_EVAL:
13875 source = tes_tested;
13876 array = test_case.m_is_input ? "[]" : "";
13877 index = test_case.m_is_input ? "[0]" : "";
13878 break;
13879 case Utils::Shader::VERTEX:
13880 source = vs_tested;
13881 break;
13882 default:
13883 TCU_FAIL("Invalid enum");
13884 }
13885
13886 Utils::replaceToken("DIRECTION", position, direction, source);
13887 temp = position;
13888 Utils::replaceToken("BLOCK_DEFINITION", position, definition, source);
13889 position = temp;
13890 Utils::replaceToken("ARRAY", position, array, source);
13891 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13892
13893 Utils::replaceAllTokens("INDEX", index, source);
13894 }
13895 else
13896 {
13897 switch (stage)
13898 {
13899 case Utils::Shader::FRAGMENT:
13900 source = fs;
13901 break;
13902 case Utils::Shader::GEOMETRY:
13903 source = gs;
13904 break;
13905 case Utils::Shader::TESS_CTRL:
13906 source = tcs;
13907 break;
13908 case Utils::Shader::TESS_EVAL:
13909 source = tes;
13910 break;
13911 case Utils::Shader::VERTEX:
13912 source = vs;
13913 break;
13914 default:
13915 TCU_FAIL("Invalid enum");
13916 }
13917 }
13918
13919 return source;
13920 }
13921
13922 /** Get description of test case
13923 *
13924 * @param test_case_index Index of test case
13925 *
13926 * @return Test case description
13927 **/
13928 std::string VaryingBlockMemberLocationsTest::getTestCaseName(GLuint test_case_index)
13929 {
13930 std::stringstream stream;
13931 testCase& test_case = m_test_cases[test_case_index];
13932
13933 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13934
13935 if (true == test_case.m_is_input)
13936 {
13937 stream << "input";
13938 }
13939 else
13940 {
13941 stream << "output";
13942 }
13943
13944 if (true == test_case.m_qualify_all)
13945 {
13946 stream << ", all members qualified";
13947 }
13948 else
13949 {
13950 stream << ", not all members qualified";
13951 }
13952
13953 return stream.str();
13954 }
13955
13956 /** Get number of test cases
13957 *
13958 * @return Number of test cases
13959 **/
13960 GLuint VaryingBlockMemberLocationsTest::getTestCaseNumber()
13961 {
13962 return static_cast<GLuint>(m_test_cases.size());
13963 }
13964
13965 /** Selects if "compute" stage is relevant for test
13966 *
13967 * @param ignored
13968 *
13969 * @return false
13970 **/
13971 bool VaryingBlockMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13972 {
13973 return false;
13974 }
13975
13976 /** Selects if compilation failure is expected result
13977 *
13978 * @param test_case_index Index of test case
13979 *
13980 * @return false when all members are qualified, true otherwise
13981 **/
13982 bool VaryingBlockMemberLocationsTest::isFailureExpected(GLuint test_case_index)
13983 {
13984 return (true != m_test_cases[test_case_index].m_qualify_all);
13985 }
13986
13987 /** Prepare all test cases
13988 *
13989 **/
13990 void VaryingBlockMemberLocationsTest::testInit()
13991 {
13992 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13993 {
13994 if (Utils::Shader::COMPUTE == stage)
13995 {
13996 continue;
13997 }
13998
13999 testCase test_case_in_all = { true, true, (Utils::Shader::STAGES)stage };
14000 testCase test_case_in_one = { true, false, (Utils::Shader::STAGES)stage };
14001 testCase test_case_out_all = { false, true, (Utils::Shader::STAGES)stage };
14002 testCase test_case_out_one = { false, false, (Utils::Shader::STAGES)stage };
14003
14004 if (Utils::Shader::VERTEX != stage)
14005 {
14006 m_test_cases.push_back(test_case_in_all);
14007 m_test_cases.push_back(test_case_in_one);
14008 }
14009
14010 if (Utils::Shader::FRAGMENT != stage)
14011 {
14012 m_test_cases.push_back(test_case_out_all);
14013 m_test_cases.push_back(test_case_out_one);
14014 }
14015 }
14016 }
14017
14018 /** Constructor
14019 *
14020 * @param context Test framework context
14021 **/
14022 VaryingBlockAutomaticMemberLocationsTest::VaryingBlockAutomaticMemberLocationsTest(deqp::Context& context)
14023 : NegativeTestBase(
14024 context, "varying_block_automatic_member_locations",
14025 "Test verifies that compiler assigns subsequent locations to block members, even if this causes errors")
14026 {
14027 }
14028
14029 /** Source for given test case and stage
14030 *
14031 * @param test_case_index Index of test case
14032 * @param stage Shader stage
14033 *
14034 * @return Shader source
14035 **/
14036 std::string VaryingBlockAutomaticMemberLocationsTest::getShaderSource(GLuint test_case_index,
14037 Utils::Shader::STAGES stage)
14038 {
14039 static const GLchar* block_definition = "layout (location = 2) DIRECTION DBZ {\n"
14040 " vec4 goku;\n"
14041 " vec4 gohan[4];\n"
14042 " vec4 goten;\n"
14043 #if DEBUG_NEG_REMOVE_ERROR
14044 " /* layout (location = 1) */ vec4 chichi;\n"
14045 #else
14046 " layout (location = 1) vec4 chichi;\n"
14047 #endif /* DEBUG_NEG_REMOVE_ERROR */
14048 " vec4 pan;\n"
14049 "} dbzARRAY;\n";
14050 static const GLchar* input_use = " result += dbzINDEX.goku + dbzINDEX.gohan[0] + dbzINDEX.gohan[1] + "
14051 "dbzINDEX.gohan[3] + dbzINDEX.gohan[2] + dbzINDEX.goten + dbzINDEX.chichi + "
14052 "dbzINDEX.pan;\n";
14053 static const GLchar* output_use = " dbzINDEX.goku = result;\n"
14054 " dbzINDEX.gohan[0] = result / 2;\n"
14055 " dbzINDEX.gohan[1] = result / 2.25;\n"
14056 " dbzINDEX.gohan[2] = result / 2.5;\n"
14057 " dbzINDEX.gohan[3] = result / 2.75;\n"
14058 " dbzINDEX.goten = result / 4 - dbzINDEX.gohan[0] - dbzINDEX.gohan[1] - "
14059 "dbzINDEX.gohan[2] - dbzINDEX.gohan[3];\n"
14060 " dbzINDEX.chichi = result / 8 - dbzINDEX.goten;\n"
14061 " dbzINDEX.pan = result / 16 - dbzINDEX.chichi;\n";
14062 static const GLchar* fs = "#version 430 core\n"
14063 "#extension GL_ARB_enhanced_layouts : require\n"
14064 "\n"
14065 "in vec4 gs_fs;\n"
14066 "out vec4 fs_out;\n"
14067 "\n"
14068 "void main()\n"
14069 "{\n"
14070 " fs_out = gs_fs;\n"
14071 "}\n"
14072 "\n";
14073 static const GLchar* fs_tested = "#version 430 core\n"
14074 "#extension GL_ARB_enhanced_layouts : require\n"
14075 "\n"
14076 "BLOCK_DEFINITION"
14077 "\n"
14078 "in vec4 gs_fs;\n"
14079 "out vec4 fs_out;\n"
14080 "\n"
14081 "void main()\n"
14082 "{\n"
14083 " vec4 result = gs_fs;\n"
14084 "\n"
14085 "VARIABLE_USE"
14086 "\n"
14087 " fs_out += result;\n"
14088 "}\n"
14089 "\n";
14090 static const GLchar* gs = "#version 430 core\n"
14091 "#extension GL_ARB_enhanced_layouts : require\n"
14092 "\n"
14093 "layout(points) in;\n"
14094 "layout(triangle_strip, max_vertices = 4) out;\n"
14095 "\n"
14096 "in vec4 tes_gs[];\n"
14097 "out vec4 gs_fs;\n"
14098 "\n"
14099 "void main()\n"
14100 "{\n"
14101 " gs_fs = tes_gs[0];\n"
14102 " gl_Position = vec4(-1, -1, 0, 1);\n"
14103 " EmitVertex();\n"
14104 " gs_fs = tes_gs[0];\n"
14105 " gl_Position = vec4(-1, 1, 0, 1);\n"
14106 " EmitVertex();\n"
14107 " gs_fs = tes_gs[0];\n"
14108 " gl_Position = vec4(1, -1, 0, 1);\n"
14109 " EmitVertex();\n"
14110 " gs_fs = tes_gs[0];\n"
14111 " gl_Position = vec4(1, 1, 0, 1);\n"
14112 " EmitVertex();\n"
14113 "}\n"
14114 "\n";
14115 static const GLchar* gs_tested = "#version 430 core\n"
14116 "#extension GL_ARB_enhanced_layouts : require\n"
14117 "\n"
14118 "layout(points) in;\n"
14119 "layout(triangle_strip, max_vertices = 4) out;\n"
14120 "\n"
14121 "BLOCK_DEFINITION"
14122 "\n"
14123 "in vec4 tes_gs[];\n"
14124 "out vec4 gs_fs;\n"
14125 "\n"
14126 "void main()\n"
14127 "{\n"
14128 " vec4 result = tes_gs[0];\n"
14129 "\n"
14130 "VARIABLE_USE"
14131 "\n"
14132 " gs_fs = result;\n"
14133 " gl_Position = vec4(-1, -1, 0, 1);\n"
14134 " EmitVertex();\n"
14135 " gs_fs = result;\n"
14136 " gl_Position = vec4(-1, 1, 0, 1);\n"
14137 " EmitVertex();\n"
14138 " gs_fs = result;\n"
14139 " gl_Position = vec4(1, -1, 0, 1);\n"
14140 " EmitVertex();\n"
14141 " gs_fs = result;\n"
14142 " gl_Position = vec4(1, 1, 0, 1);\n"
14143 " EmitVertex();\n"
14144 "}\n"
14145 "\n";
14146 static const GLchar* tcs = "#version 430 core\n"
14147 "#extension GL_ARB_enhanced_layouts : require\n"
14148 "\n"
14149 "layout(vertices = 1) out;\n"
14150 "\n"
14151 "in vec4 vs_tcs[];\n"
14152 "out vec4 tcs_tes[];\n"
14153 "\n"
14154 "void main()\n"
14155 "{\n"
14156 "\n"
14157 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14158 "\n"
14159 " gl_TessLevelOuter[0] = 1.0;\n"
14160 " gl_TessLevelOuter[1] = 1.0;\n"
14161 " gl_TessLevelOuter[2] = 1.0;\n"
14162 " gl_TessLevelOuter[3] = 1.0;\n"
14163 " gl_TessLevelInner[0] = 1.0;\n"
14164 " gl_TessLevelInner[1] = 1.0;\n"
14165 "}\n"
14166 "\n";
14167 static const GLchar* tcs_tested = "#version 430 core\n"
14168 "#extension GL_ARB_enhanced_layouts : require\n"
14169 "\n"
14170 "layout(vertices = 1) out;\n"
14171 "\n"
14172 "BLOCK_DEFINITION"
14173 "\n"
14174 "in vec4 vs_tcs[];\n"
14175 "out vec4 tcs_tes[];\n"
14176 "\n"
14177 "void main()\n"
14178 "{\n"
14179 " vec4 result = vs_tcs[gl_InvocationID];\n"
14180 "\n"
14181 "VARIABLE_USE"
14182 "\n"
14183 " tcs_tes[gl_InvocationID] = result;\n"
14184 "\n"
14185 " gl_TessLevelOuter[0] = 1.0;\n"
14186 " gl_TessLevelOuter[1] = 1.0;\n"
14187 " gl_TessLevelOuter[2] = 1.0;\n"
14188 " gl_TessLevelOuter[3] = 1.0;\n"
14189 " gl_TessLevelInner[0] = 1.0;\n"
14190 " gl_TessLevelInner[1] = 1.0;\n"
14191 "}\n"
14192 "\n";
14193 static const GLchar* tes = "#version 430 core\n"
14194 "#extension GL_ARB_enhanced_layouts : require\n"
14195 "\n"
14196 "layout(isolines, point_mode) in;\n"
14197 "\n"
14198 "in vec4 tcs_tes[];\n"
14199 "out vec4 tes_gs;\n"
14200 "\n"
14201 "void main()\n"
14202 "{\n"
14203 " tes_gs = tcs_tes[0];\n"
14204 "}\n"
14205 "\n";
14206 static const GLchar* tes_tested = "#version 430 core\n"
14207 "#extension GL_ARB_enhanced_layouts : require\n"
14208 "\n"
14209 "layout(isolines, point_mode) in;\n"
14210 "\n"
14211 "BLOCK_DEFINITION"
14212 "\n"
14213 "in vec4 tcs_tes[];\n"
14214 "out vec4 tes_gs;\n"
14215 "\n"
14216 "void main()\n"
14217 "{\n"
14218 " vec4 result = tcs_tes[0];\n"
14219 "\n"
14220 "VARIABLE_USE"
14221 "\n"
14222 " tes_gs += result;\n"
14223 "}\n"
14224 "\n";
14225 static const GLchar* vs = "#version 430 core\n"
14226 "#extension GL_ARB_enhanced_layouts : require\n"
14227 "\n"
14228 "in vec4 in_vs;\n"
14229 "out vec4 vs_tcs;\n"
14230 "\n"
14231 "void main()\n"
14232 "{\n"
14233 " vs_tcs = in_vs;\n"
14234 "}\n"
14235 "\n";
14236 static const GLchar* vs_tested = "#version 430 core\n"
14237 "#extension GL_ARB_enhanced_layouts : require\n"
14238 "\n"
14239 "BLOCK_DEFINITION"
14240 "\n"
14241 "in vec4 in_vs;\n"
14242 "out vec4 vs_tcs;\n"
14243 "\n"
14244 "void main()\n"
14245 "{\n"
14246 " vec4 result = in_vs;\n"
14247 "\n"
14248 "VARIABLE_USE"
14249 "\n"
14250 " vs_tcs += result;\n"
14251 "}\n"
14252 "\n";
14253
14254 const GLchar* array = "";
14255 const GLchar* direction = "in";
14256 const GLchar* index = "";
14257 std::string source;
14258 testCase& test_case = m_test_cases[test_case_index];
14259 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
14260
14261 if (!test_case.m_is_input)
14262 {
14263 direction = "out";
14264 var_use = output_use;
14265 }
14266
14267 if (test_case.m_stage == stage)
14268 {
14269 size_t position = 0;
14270
14271 switch (stage)
14272 {
14273 case Utils::Shader::FRAGMENT:
14274 source = fs_tested;
14275 break;
14276 case Utils::Shader::GEOMETRY:
14277 source = gs_tested;
14278 array = test_case.m_is_input ? "[]" : "";
14279 index = test_case.m_is_input ? "[0]" : "";
14280 break;
14281 case Utils::Shader::TESS_CTRL:
14282 source = tcs_tested;
14283 array = "[]";
14284 index = "[gl_InvocationID]";
14285 break;
14286 case Utils::Shader::TESS_EVAL:
14287 source = tes_tested;
14288 array = test_case.m_is_input ? "[]" : "";
14289 index = test_case.m_is_input ? "[0]" : "";
14290 break;
14291 case Utils::Shader::VERTEX:
14292 source = vs_tested;
14293 break;
14294 default:
14295 TCU_FAIL("Invalid enum");
14296 }
14297
14298 Utils::replaceToken("BLOCK_DEFINITION", position, block_definition, source);
14299 position = 0;
14300 Utils::replaceToken("DIRECTION", position, direction, source);
14301 Utils::replaceToken("ARRAY", position, array, source);
14302 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14303
14304 Utils::replaceAllTokens("INDEX", index, source);
14305 }
14306 else
14307 {
14308 switch (stage)
14309 {
14310 case Utils::Shader::FRAGMENT:
14311 source = fs;
14312 break;
14313 case Utils::Shader::GEOMETRY:
14314 source = gs;
14315 break;
14316 case Utils::Shader::TESS_CTRL:
14317 source = tcs;
14318 break;
14319 case Utils::Shader::TESS_EVAL:
14320 source = tes;
14321 break;
14322 case Utils::Shader::VERTEX:
14323 source = vs;
14324 break;
14325 default:
14326 TCU_FAIL("Invalid enum");
14327 }
14328 }
14329
14330 return source;
14331 }
14332
14333 /** Get description of test case
14334 *
14335 * @param test_case_index Index of test case
14336 *
14337 * @return Test case description
14338 **/
14339 std::string VaryingBlockAutomaticMemberLocationsTest::getTestCaseName(GLuint test_case_index)
14340 {
14341 std::stringstream stream;
14342 testCase& test_case = m_test_cases[test_case_index];
14343
14344 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
14345
14346 if (true == test_case.m_is_input)
14347 {
14348 stream << "input";
14349 }
14350 else
14351 {
14352 stream << "output";
14353 }
14354
14355 return stream.str();
14356 }
14357
14358 /** Get number of test cases
14359 *
14360 * @return Number of test cases
14361 **/
14362 GLuint VaryingBlockAutomaticMemberLocationsTest::getTestCaseNumber()
14363 {
14364 return static_cast<GLuint>(m_test_cases.size());
14365 }
14366
14367 /** Selects if "compute" stage is relevant for test
14368 *
14369 * @param ignored
14370 *
14371 * @return false
14372 **/
14373 bool VaryingBlockAutomaticMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
14374 {
14375 return false;
14376 }
14377
14378 /** Prepare all test cases
14379 *
14380 **/
14381 void VaryingBlockAutomaticMemberLocationsTest::testInit()
14382 {
14383 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14384 {
14385 if (Utils::Shader::COMPUTE == stage)
14386 {
14387 continue;
14388 }
14389
14390 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
14391 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
14392
14393 if (Utils::Shader::VERTEX != stage)
14394 {
14395 m_test_cases.push_back(test_case_in);
14396 }
14397
14398 if (Utils::Shader::FRAGMENT != stage)
14399 {
14400 m_test_cases.push_back(test_case_out);
14401 }
14402 }
14403 }
14404
14405 /** Constructor
14406 *
14407 * @param context Test framework context
14408 **/
14409 VaryingLocationLimitTest::VaryingLocationLimitTest(deqp::Context& context)
14410 : NegativeTestBase(context, "varying_location_limit",
14411 "Test verifies that compiler reports error when location qualifier exceeds limits")
14412 {
14413 }
14414
14415 /** Source for given test case and stage
14416 *
14417 * @param test_case_index Index of test case
14418 * @param stage Shader stage
14419 *
14420 * @return Shader source
14421 **/
14422 std::string VaryingLocationLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
14423 {
14424 #if DEBUG_NEG_REMOVE_ERROR
14425 static const GLchar* var_definition = "layout (location = LAST /* + 1 */) FLAT DIRECTION TYPE gokuARRAY;\n";
14426 #else
14427 static const GLchar* var_definition = "layout (location = LAST + 1) FLAT DIRECTION TYPE gokuARRAY;\n";
14428 #endif /* DEBUG_NEG_REMOVE_ERROR */
14429 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
14430 " {\n"
14431 " result += vec4(1, 0.5, 0.25, 0.125);\n"
14432 " }\n";
14433 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
14434 " if (vec4(0) == result)\n"
14435 " {\n"
14436 " gokuINDEX = TYPE(1);\n"
14437 " }\n";
14438 static const GLchar* fs = "#version 430 core\n"
14439 "#extension GL_ARB_enhanced_layouts : require\n"
14440 "\n"
14441 "in vec4 gs_fs;\n"
14442 "out vec4 fs_out;\n"
14443 "\n"
14444 "void main()\n"
14445 "{\n"
14446 " fs_out = gs_fs;\n"
14447 "}\n"
14448 "\n";
14449 static const GLchar* fs_tested = "#version 430 core\n"
14450 "#extension GL_ARB_enhanced_layouts : require\n"
14451 "\n"
14452 "VAR_DEFINITION"
14453 "\n"
14454 "in vec4 gs_fs;\n"
14455 "out vec4 fs_out;\n"
14456 "\n"
14457 "void main()\n"
14458 "{\n"
14459 " vec4 result = gs_fs;\n"
14460 "\n"
14461 "VARIABLE_USE"
14462 "\n"
14463 " fs_out += result;\n"
14464 "}\n"
14465 "\n";
14466 static const GLchar* gs = "#version 430 core\n"
14467 "#extension GL_ARB_enhanced_layouts : require\n"
14468 "\n"
14469 "layout(points) in;\n"
14470 "layout(triangle_strip, max_vertices = 4) out;\n"
14471 "\n"
14472 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
14473 "in vec4 tes_gs[];\n"
14474 "out vec4 gs_fs;\n"
14475 "\n"
14476 "void main()\n"
14477 "{\n"
14478 " gs_fs = tes_gs[0];\n"
14479 " gl_Position = vec4(-1, -1, 0, 1);\n"
14480 " EmitVertex();\n"
14481 " gs_fs = tes_gs[0];\n"
14482 " gl_Position = vec4(-1, 1, 0, 1);\n"
14483 " EmitVertex();\n"
14484 " gs_fs = tes_gs[0];\n"
14485 " gl_Position = vec4(1, -1, 0, 1);\n"
14486 " EmitVertex();\n"
14487 " gs_fs = tes_gs[0];\n"
14488 " gl_Position = vec4(1, 1, 0, 1);\n"
14489 " EmitVertex();\n"
14490 "}\n"
14491 "\n";
14492 static const GLchar* gs_tested = "#version 430 core\n"
14493 "#extension GL_ARB_enhanced_layouts : require\n"
14494 "\n"
14495 "layout(points) in;\n"
14496 "layout(triangle_strip, max_vertices = 4) out;\n"
14497 "\n"
14498 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
14499 "VAR_DEFINITION"
14500 "\n"
14501 "in vec4 tes_gs[];\n"
14502 "out vec4 gs_fs;\n"
14503 "\n"
14504 "void main()\n"
14505 "{\n"
14506 " vec4 result = tes_gs[0];\n"
14507 "\n"
14508 "VARIABLE_USE"
14509 "\n"
14510 " gs_fs = result;\n"
14511 " gl_Position = vec4(-1, -1, 0, 1);\n"
14512 " EmitVertex();\n"
14513 " gs_fs = result;\n"
14514 " gl_Position = vec4(-1, 1, 0, 1);\n"
14515 " EmitVertex();\n"
14516 " gs_fs = result;\n"
14517 " gl_Position = vec4(1, -1, 0, 1);\n"
14518 " EmitVertex();\n"
14519 " gs_fs = result;\n"
14520 " gl_Position = vec4(1, 1, 0, 1);\n"
14521 " EmitVertex();\n"
14522 "}\n"
14523 "\n";
14524 static const GLchar* tcs = "#version 430 core\n"
14525 "#extension GL_ARB_enhanced_layouts : require\n"
14526 "\n"
14527 "layout(vertices = 1) out;\n"
14528 "\n"
14529 "in vec4 vs_tcs[];\n"
14530 "out vec4 tcs_tes[];\n"
14531 "\n"
14532 "void main()\n"
14533 "{\n"
14534 "\n"
14535 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14536 "\n"
14537 " gl_TessLevelOuter[0] = 1.0;\n"
14538 " gl_TessLevelOuter[1] = 1.0;\n"
14539 " gl_TessLevelOuter[2] = 1.0;\n"
14540 " gl_TessLevelOuter[3] = 1.0;\n"
14541 " gl_TessLevelInner[0] = 1.0;\n"
14542 " gl_TessLevelInner[1] = 1.0;\n"
14543 "}\n"
14544 "\n";
14545 static const GLchar* tcs_tested = "#version 430 core\n"
14546 "#extension GL_ARB_enhanced_layouts : require\n"
14547 "\n"
14548 "layout(vertices = 1) out;\n"
14549 "\n"
14550 "VAR_DEFINITION"
14551 "\n"
14552 "in vec4 vs_tcs[];\n"
14553 "out vec4 tcs_tes[];\n"
14554 "\n"
14555 "void main()\n"
14556 "{\n"
14557 " vec4 result = vs_tcs[gl_InvocationID];\n"
14558 "\n"
14559 "VARIABLE_USE"
14560 "\n"
14561 " tcs_tes[gl_InvocationID] = result;\n"
14562 "\n"
14563 " gl_TessLevelOuter[0] = 1.0;\n"
14564 " gl_TessLevelOuter[1] = 1.0;\n"
14565 " gl_TessLevelOuter[2] = 1.0;\n"
14566 " gl_TessLevelOuter[3] = 1.0;\n"
14567 " gl_TessLevelInner[0] = 1.0;\n"
14568 " gl_TessLevelInner[1] = 1.0;\n"
14569 "}\n"
14570 "\n";
14571 static const GLchar* tes = "#version 430 core\n"
14572 "#extension GL_ARB_enhanced_layouts : require\n"
14573 "\n"
14574 "layout(isolines, point_mode) in;\n"
14575 "\n"
14576 "in vec4 tcs_tes[];\n"
14577 "out vec4 tes_gs;\n"
14578 "\n"
14579 "void main()\n"
14580 "{\n"
14581 " tes_gs = tcs_tes[0];\n"
14582 "}\n"
14583 "\n";
14584 static const GLchar* tes_tested = "#version 430 core\n"
14585 "#extension GL_ARB_enhanced_layouts : require\n"
14586 "\n"
14587 "layout(isolines, point_mode) in;\n"
14588 "\n"
14589 "VAR_DEFINITION"
14590 "\n"
14591 "in vec4 tcs_tes[];\n"
14592 "out vec4 tes_gs;\n"
14593 "\n"
14594 "void main()\n"
14595 "{\n"
14596 " vec4 result = tcs_tes[0];\n"
14597 "\n"
14598 "VARIABLE_USE"
14599 "\n"
14600 " tes_gs += result;\n"
14601 "}\n"
14602 "\n";
14603 static const GLchar* vs = "#version 430 core\n"
14604 "#extension GL_ARB_enhanced_layouts : require\n"
14605 "\n"
14606 "in vec4 in_vs;\n"
14607 "out vec4 vs_tcs;\n"
14608 "\n"
14609 "void main()\n"
14610 "{\n"
14611 " vs_tcs = in_vs;\n"
14612 "}\n"
14613 "\n";
14614 static const GLchar* vs_tested = "#version 430 core\n"
14615 "#extension GL_ARB_enhanced_layouts : require\n"
14616 "\n"
14617 "VAR_DEFINITION"
14618 "\n"
14619 "in vec4 in_vs;\n"
14620 "out vec4 vs_tcs;\n"
14621 "\n"
14622 "void main()\n"
14623 "{\n"
14624 " vec4 result = in_vs;\n"
14625 "\n"
14626 "VARIABLE_USE"
14627 "\n"
14628 " vs_tcs += result;\n"
14629 "}\n"
14630 "\n";
14631
14632 std::string source;
14633 testCase& test_case = m_test_cases[test_case_index];
14634 size_t position = 0;
14635 const GLchar* per_vertex = !isSeparable(test_case_index) ? "" : "out gl_PerVertex {\n"
14636 "vec4 gl_Position;\n"
14637 "};\n"
14638 "\n";
14639
14640 if (test_case.m_stage == stage)
14641 {
14642 const GLchar* array = "";
14643 GLchar buffer[16];
14644 const GLchar* direction = "in ";
14645 const GLchar* flat = "";
14646 const GLchar* index = "";
14647 GLuint last = getLastInputLocation(stage, test_case.m_type, 0, true);
14648 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
14649 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
14650 const GLchar* var_use = input_use;
14651
14652 if (false == test_case.m_is_input)
14653 {
14654 direction = "out";
14655 last = getLastOutputLocation(stage, test_case.m_type, 0, true);
14656 storage = Utils::Variable::VARYING_OUTPUT;
14657 var_use = output_use;
14658 }
14659
14660 if (isFlatRequired(stage, test_case.m_type, storage))
14661 {
14662 flat = "flat";
14663 }
14664
14665 sprintf(buffer, "%d", last);
14666
14667 switch (stage)
14668 {
14669 case Utils::Shader::FRAGMENT:
14670 source = fs_tested;
14671 break;
14672 case Utils::Shader::GEOMETRY:
14673 source = gs_tested;
14674 array = test_case.m_is_input ? "[]" : "";
14675 index = test_case.m_is_input ? "[0]" : "";
14676 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
14677 break;
14678 case Utils::Shader::TESS_CTRL:
14679 source = tcs_tested;
14680 array = "[]";
14681 index = "[gl_InvocationID]";
14682 break;
14683 case Utils::Shader::TESS_EVAL:
14684 source = tes_tested;
14685 array = test_case.m_is_input ? "[]" : "";
14686 index = test_case.m_is_input ? "[0]" : "";
14687 break;
14688 case Utils::Shader::VERTEX:
14689 source = vs_tested;
14690 break;
14691 default:
14692 TCU_FAIL("Invalid enum");
14693 }
14694
14695 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
14696 position = 0;
14697 Utils::replaceToken("LAST", position, buffer, source);
14698 Utils::replaceToken("FLAT", position, flat, source);
14699 Utils::replaceToken("DIRECTION", position, direction, source);
14700 Utils::replaceToken("ARRAY", position, array, source);
14701 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14702
14703 Utils::replaceAllTokens("TYPE", type_name, source);
14704 Utils::replaceAllTokens("INDEX", index, source);
14705 }
14706 else
14707 {
14708 switch (stage)
14709 {
14710 case Utils::Shader::FRAGMENT:
14711 source = fs;
14712 break;
14713 case Utils::Shader::GEOMETRY:
14714 source = gs;
14715 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
14716 break;
14717 case Utils::Shader::TESS_CTRL:
14718 source = tcs;
14719 break;
14720 case Utils::Shader::TESS_EVAL:
14721 source = tes;
14722 break;
14723 case Utils::Shader::VERTEX:
14724 source = vs;
14725 break;
14726 default:
14727 TCU_FAIL("Invalid enum");
14728 }
14729 }
14730
14731 return source;
14732 }
14733
14734 /** Get description of test case
14735 *
14736 * @param test_case_index Index of test case
14737 *
14738 * @return Test case description
14739 **/
14740 std::string VaryingLocationLimitTest::getTestCaseName(GLuint test_case_index)
14741 {
14742 std::stringstream stream;
14743 testCase& test_case = m_test_cases[test_case_index];
14744
14745 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
14746 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
14747
14748 if (true == test_case.m_is_input)
14749 {
14750 stream << "input";
14751 }
14752 else
14753 {
14754 stream << "output";
14755 }
14756
14757 return stream.str();
14758 }
14759
14760 /** Get number of test cases
14761 *
14762 * @return Number of test cases
14763 **/
14764 GLuint VaryingLocationLimitTest::getTestCaseNumber()
14765 {
14766 return static_cast<GLuint>(m_test_cases.size());
14767 }
14768
14769 /** Selects if "compute" stage is relevant for test
14770 *
14771 * @param ignored
14772 *
14773 * @return false
14774 **/
14775 bool VaryingLocationLimitTest::isComputeRelevant(GLuint /* test_case_index */)
14776 {
14777 return false;
14778 }
14779
14780 /** Selects if the test case should use a separable program
14781 *
14782 * @param test_case_index Id of test case
14783 *
14784 * @return whether the test should use separable programs or not
14785 **/
14786 bool VaryingLocationLimitTest::isSeparable(const GLuint test_case_index)
14787 {
14788 const testCase& test_case = m_test_cases[test_case_index];
14789
14790 return test_case.m_is_input && test_case.m_stage != Utils::Shader::VERTEX;
14791 }
14792
14793 /** Prepare all test cases
14794 *
14795 **/
14796 void VaryingLocationLimitTest::testInit()
14797 {
14798 const GLuint n_types = getTypesNumber();
14799
14800 for (GLuint i = 0; i < n_types; ++i)
14801 {
14802 const Utils::Type& type = getType(i);
14803
14804 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14805 {
14806 if (Utils::Shader::COMPUTE == stage)
14807 {
14808 continue;
14809 }
14810
14811 testCase test_case_in = { true, type, (Utils::Shader::STAGES)stage };
14812 testCase test_case_out = { false, type, (Utils::Shader::STAGES)stage };
14813
14814 m_test_cases.push_back(test_case_in);
14815
14816 if (Utils::Shader::FRAGMENT != stage)
14817 {
14818 m_test_cases.push_back(test_case_out);
14819 }
14820 }
14821 }
14822 }
14823
14824 /** Constructor
14825 *
14826 * @param context Test framework context
14827 **/
14828 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context)
14829 : VaryingLocationsTest(context, "varying_components",
14830 "Test verifies that input and output components are respected")
14831 {
14832 }
14833
14834 /** Constructor
14835 *
14836 * @param context Test framework context
14837 * @param test_name Name of test
14838 * @param test_description Description of test
14839 **/
14840 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context, const glw::GLchar* test_name,
14841 const glw::GLchar* test_description)
14842 : VaryingLocationsTest(context, test_name, test_description)
14843 {
14844 }
14845
14846 /** Get interface of program
14847 *
14848 * @param test_case_index Test case
14849 * @param program_interface Interface of program
14850 * @param varying_passthrough Collection of connections between in and out variables
14851 **/
14852 void VaryingComponentsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
14853 Utils::VaryingPassthrough& varying_passthrough)
14854 {
14855 GLuint array_length = getArrayLength();
14856 const testCase& test_case = m_test_cases[test_case_index];
14857 const Utils::Type vector_type = Utils::Type::GetType(test_case.m_type, 1, 4);
14858 Utils::ShaderInterface si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
14859
14860 /* Zero means no array, however we still need at least 1 slot of data */
14861 if (0 == array_length)
14862 {
14863 array_length += 1;
14864 }
14865
14866 /* Generate data */
14867 const std::vector<GLubyte>& data = vector_type.GenerateDataPacked();
14868 const size_t data_size = data.size();
14869
14870 /* Prepare data for variables */
14871 m_data.resize(array_length * data_size);
14872
14873 GLubyte* dst = &m_data[0];
14874 const GLubyte* src = &data[0];
14875
14876 for (GLuint i = 0; i < array_length; ++i)
14877 {
14878 memcpy(dst + data_size * i, src, data_size);
14879 }
14880
14881 /* Prepare interface for each stage */
14882 prepareShaderStage(Utils::Shader::FRAGMENT, vector_type, program_interface, test_case, varying_passthrough);
14883 prepareShaderStage(Utils::Shader::GEOMETRY, vector_type, program_interface, test_case, varying_passthrough);
14884 prepareShaderStage(Utils::Shader::TESS_CTRL, vector_type, program_interface, test_case, varying_passthrough);
14885 prepareShaderStage(Utils::Shader::TESS_EVAL, vector_type, program_interface, test_case, varying_passthrough);
14886 prepareShaderStage(Utils::Shader::VERTEX, vector_type, program_interface, test_case, varying_passthrough);
14887 }
14888
14889 /** Get type name
14890 *
14891 * @param test_case_index Index of test case
14892 *
14893 * @return Name of type test in test_case_index
14894 **/
14895 std::string VaryingComponentsTest::getTestCaseName(glw::GLuint test_case_index)
14896 {
14897 std::string name;
14898
14899 const testCase& test_case = m_test_cases[test_case_index];
14900
14901 name = "Type: ";
14902
14903 switch (test_case.m_type)
14904 {
14905 case Utils::Type::Double:
14906 name.append(Utils::Type::_double.GetGLSLTypeName());
14907 break;
14908 case Utils::Type::Float:
14909 name.append(Utils::Type::_float.GetGLSLTypeName());
14910 break;
14911 case Utils::Type::Int:
14912 name.append(Utils::Type::_int.GetGLSLTypeName());
14913 break;
14914 case Utils::Type::Uint:
14915 name.append(Utils::Type::uint.GetGLSLTypeName());
14916 break;
14917 }
14918
14919 name.append(", layout: ");
14920
14921 switch (test_case.m_layout)
14922 {
14923 case G64VEC2:
14924 name.append("G64VEC2");
14925 break;
14926 case G64SCALAR_G64SCALAR:
14927 name.append("G64SCALAR_G64SCALAR");
14928 break;
14929 case GVEC4:
14930 name.append("GVEC4");
14931 break;
14932 case SCALAR_GVEC3:
14933 name.append("SCALAR_GVEC3");
14934 break;
14935 case GVEC3_SCALAR:
14936 name.append("GVEC3_SCALAR");
14937 break;
14938 case GVEC2_GVEC2:
14939 name.append("GVEC2_GVEC2");
14940 break;
14941 case GVEC2_SCALAR_SCALAR:
14942 name.append("GVEC2_SCALAR_SCALAR");
14943 break;
14944 case SCALAR_GVEC2_SCALAR:
14945 name.append("SCALAR_GVEC2_SCALAR");
14946 break;
14947 case SCALAR_SCALAR_GVEC2:
14948 name.append("SCALAR_SCALAR_GVEC2");
14949 break;
14950 case SCALAR_SCALAR_SCALAR_SCALAR:
14951 name.append("SCALAR_SCALAR_SCALAR_SCALAR");
14952 break;
14953 }
14954
14955 return name;
14956 }
14957
14958 /** Returns number of types to test
14959 *
14960 * @return Number of types
14961 **/
14962 glw::GLuint VaryingComponentsTest::getTestCaseNumber()
14963 {
14964 return static_cast<GLuint>(m_test_cases.size());
14965 }
14966
14967 /* Prepare test cases */
14968 void VaryingComponentsTest::testInit()
14969 {
14970 m_test_cases.push_back(testCase(G64VEC2, Utils::Type::Double));
14971 m_test_cases.push_back(testCase(G64SCALAR_G64SCALAR, Utils::Type::Double));
14972
14973 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Float));
14974 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Float));
14975 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Float));
14976 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Float));
14977 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Float));
14978 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Float));
14979 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Float));
14980 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Float));
14981
14982 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Int));
14983 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Int));
14984 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Int));
14985 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Int));
14986 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Int));
14987 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Int));
14988 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Int));
14989 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Int));
14990
14991 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Uint));
14992 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Uint));
14993 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Uint));
14994 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Uint));
14995 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Uint));
14996 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Uint));
14997 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Uint));
14998 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Uint));
14999 }
15000
15001 /** Inform that test use components
15002 *
15003 * @param ignored
15004 *
15005 * @return true
15006 **/
15007 bool VaryingComponentsTest::useComponentQualifier(glw::GLuint /* test_case_index */)
15008 {
15009 return true;
15010 }
15011
15012 /** Get length of arrays that should be used during test
15013 *
15014 * @return 0u - no array at all
15015 **/
15016 GLuint VaryingComponentsTest::getArrayLength()
15017 {
15018 return 0;
15019 }
15020
15021 std::string VaryingComponentsTest::prepareGlobals(GLuint last_in_location, GLuint last_out_location)
15022 {
15023 std::string globals = VaryingLocationsTest::prepareGlobals(last_in_location, last_out_location);
15024
15025 globals.append("const uint comp_x = 0u;\n"
15026 "const uint comp_y = 1u;\n"
15027 "const uint comp_z = 2u;\n"
15028 "const uint comp_w = 3u;\n");
15029
15030 return globals;
15031 }
15032
15033 /**
15034 *
15035 **/
15036 std::string VaryingComponentsTest::prepareName(const glw::GLchar* name, glw::GLint location, glw::GLint component,
15037 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
15038 {
15039 GLchar buffer[16];
15040 std::string result = "PREFIXNAME_lLOCATION_cCOMPONENT";
15041 size_t position = 0;
15042 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, storage);
15043
15044 Utils::replaceToken("PREFIX", position, prefix, result);
15045 Utils::replaceToken("NAME", position, name, result);
15046
15047 sprintf(buffer, "%d", location);
15048 Utils::replaceToken("LOCATION", position, buffer, result);
15049
15050 sprintf(buffer, "%d", component);
15051 Utils::replaceToken("COMPONENT", position, buffer, result);
15052
15053 return result;
15054 }
15055
15056 std::string VaryingComponentsTest::prepareQualifiers(const glw::GLchar* location, const glw::GLchar* component,
15057 const glw::GLchar* interpolation)
15058 {
15059 size_t position = 0;
15060 std::string qualifiers = "layout (location = LOCATION, component = COMPONENT) INTERPOLATION";
15061
15062 Utils::replaceToken("LOCATION", position, location, qualifiers);
15063 Utils::replaceToken("COMPONENT", position, component, qualifiers);
15064 Utils::replaceToken("INTERPOLATION", position, interpolation, qualifiers);
15065
15066 return qualifiers;
15067 }
15068
15069 /**
15070 *
15071 **/
15072 void VaryingComponentsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& vector_type,
15073 Utils::ProgramInterface& program_interface, const testCase& test_case,
15074 Utils::VaryingPassthrough& varying_passthrough)
15075 {
15076 const GLuint array_length = getArrayLength();
15077 const Utils::Type& basic_type = Utils::Type::GetType(vector_type.m_basic_type, 1 /* n_cols */, 1 /* n_rows */);
15078 descriptor desc_in[8];
15079 descriptor desc_out[8];
15080 const GLuint first_in_loc = 0;
15081 const GLuint first_out_loc = 0;
15082 const GLchar* interpolation = "";
15083 const GLuint last_in_loc = getLastInputLocation(stage, vector_type, array_length, false);
15084 GLuint last_out_loc = 0;
15085 GLuint n_desc = 0;
15086 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
15087
15088 /* Select interpolation */
15089 if ((Utils::Shader::FRAGMENT == stage) || (Utils::Shader::GEOMETRY == stage))
15090 {
15091 interpolation = " flat";
15092 }
15093
15094 if (Utils::Shader::FRAGMENT != stage)
15095 {
15096 last_out_loc = getLastOutputLocation(stage, vector_type, array_length, false);
15097 }
15098
15099 switch (test_case.m_layout)
15100 {
15101 case G64VEC2:
15102 n_desc = 2;
15103 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "g64vec2");
15104 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "g64vec2");
15105
15106 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "g64vec2");
15107 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "g64vec2");
15108 break;
15109
15110 case G64SCALAR_G64SCALAR:
15111 n_desc = 4;
15112 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "g64scalar");
15113 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "g64scalar");
15114 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "g64scalar");
15115 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "g64scalar");
15116
15117 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "g64scalar");
15118 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "g64scalar");
15119 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "g64scalar");
15120 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "g64scalar");
15121 break;
15122 case GVEC4:
15123 n_desc = 2;
15124 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 4, "gvec4");
15125 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 4, "gvec4");
15126
15127 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 4, "gvec4");
15128 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 4, "gvec4");
15129 break;
15130 case SCALAR_GVEC3:
15131 n_desc = 4;
15132 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15133 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15134 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 3, "gvec3");
15135 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 3, "gvec3");
15136
15137 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15138 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15139 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 3, "gvec3");
15140 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 3, "gvec3");
15141 break;
15142 case GVEC3_SCALAR:
15143 n_desc = 4;
15144 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 3, "gvec3");
15145 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 3, "gvec3");
15146 desc_in[2].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15147 desc_in[3].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15148
15149 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 3, "gvec3");
15150 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 3, "gvec3");
15151 desc_out[2].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15152 desc_out[3].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15153 break;
15154 case GVEC2_GVEC2:
15155 n_desc = 4;
15156 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15157 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15158 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15159 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15160
15161 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15162 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15163 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15164 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15165 break;
15166 case GVEC2_SCALAR_SCALAR:
15167 n_desc = 6;
15168 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15169 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15170 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15171 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15172 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15173 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15174
15175 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15176 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15177 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15178 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15179 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15180 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15181 break;
15182 case SCALAR_GVEC2_SCALAR:
15183 n_desc = 6;
15184 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15185 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15186 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 2, "gvec2");
15187 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 2, "gvec2");
15188 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15189 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15190
15191 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15192 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15193 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 2, "gvec2");
15194 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 2, "gvec2");
15195 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15196 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15197 break;
15198 case SCALAR_SCALAR_GVEC2:
15199 n_desc = 6;
15200 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15201 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15202 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15203 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15204 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15205 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15206
15207 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15208 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15209 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15210 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15211 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15212 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15213 break;
15214 case SCALAR_SCALAR_SCALAR_SCALAR:
15215 n_desc = 8;
15216 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15217 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15218 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15219 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15220 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15221 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15222 desc_in[6].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15223 desc_in[7].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15224
15225 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15226 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15227 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15228 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15229 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15230 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15231 desc_out[6].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15232 desc_out[7].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15233 break;
15234 }
15235
15236 for (GLuint i = 0; i < n_desc; ++i)
15237 {
15238 const descriptor& in_desc = desc_in[i];
15239
15240 Utils::Variable* in =
15241 prepareVarying(basic_type, in_desc, interpolation, si, stage, Utils::Variable::VARYING_INPUT);
15242
15243 if (Utils::Shader::FRAGMENT != stage)
15244 {
15245 const descriptor& out_desc = desc_out[i];
15246
15247 Utils::Variable* out =
15248 prepareVarying(basic_type, out_desc, interpolation, si, stage, Utils::Variable::VARYING_OUTPUT);
15249
15250 varying_passthrough.Add(stage, in, out);
15251 }
15252 }
15253
15254 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
15255 }
15256
15257 /**
15258 *
15259 **/
15260 Utils::Variable* VaryingComponentsTest::prepareVarying(const Utils::Type& basic_type, const descriptor& desc,
15261 const GLchar* interpolation, Utils::ShaderInterface& si,
15262 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
15263 {
15264 const GLuint array_length = getArrayLength();
15265 const GLuint component_size = Utils::Type::_float.GetSize();
15266 const std::string& name = prepareName(desc.m_name, desc.m_location, desc.m_component, stage, storage);
15267 const GLuint offset = desc.m_component * component_size;
15268 const std::string& qual = prepareQualifiers(desc.m_location_str, desc.m_component_str, interpolation);
15269 const GLuint size = desc.m_n_rows * basic_type.GetSize();
15270 const Utils::Type& type = Utils::Type::GetType(basic_type.m_basic_type, 1 /* n_columns */, desc.m_n_rows);
15271 Utils::Variable* var = 0;
15272
15273 if (Utils::Variable::VARYING_INPUT == storage)
15274 {
15275 var = si.Input(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15276 desc.m_location /* expected_location */, type, /* built_in_type */
15277 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15278 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15279 }
15280 else
15281 {
15282 var = si.Output(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15283 desc.m_location /* expected_location */, type, /* built_in_type */
15284 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15285 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15286 }
15287
15288 return var;
15289 }
15290
15291 void VaryingComponentsTest::descriptor::assign(glw::GLint component, const glw::GLchar* component_str,
15292 glw::GLint location, const glw::GLchar* location_str, glw::GLuint n_rows,
15293 const glw::GLchar* name)
15294 {
15295 m_component = component;
15296 m_component_str = component_str;
15297 m_location = location;
15298 m_location_str = location_str;
15299 m_n_rows = n_rows;
15300 m_name = name;
15301 }
15302
15303 VaryingComponentsTest::testCase::testCase(COMPONENTS_LAYOUT layout, Utils::Type::TYPES type)
15304 : m_layout(layout), m_type(type)
15305 {
15306 }
15307
15308 /** Constructor
15309 *
15310 * @param context Test framework context
15311 **/
15312 VaryingArrayComponentsTest::VaryingArrayComponentsTest(deqp::Context& context)
15313 : VaryingComponentsTest(context, "varying_array_components",
15314 "Test verifies that input and output components are respected for arrays")
15315 {
15316 }
15317
15318 /** Get length of arrays that should be used during test
15319 *
15320 * @return 4u
15321 **/
15322 GLuint VaryingArrayComponentsTest::getArrayLength()
15323 {
15324 return 4u;
15325 }
15326
15327 /** Constructor
15328 *
15329 * @param context Test framework context
15330 **/
15331 VaryingInvalidValueComponentTest::VaryingInvalidValueComponentTest(deqp::Context& context)
15332 : NegativeTestBase(context, "varying_invalid_value_component", "Test verifies that compiler reports error when "
15333 "using an invalid value in the component "
15334 "qualification for a specific type")
15335 {
15336 }
15337
15338 /** Source for given test case and stage
15339 *
15340 * @param test_case_index Index of test case
15341 * @param stage Shader stage
15342 *
15343 * @return Shader source
15344 **/
15345 std::string VaryingInvalidValueComponentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15346 {
15347 #if DEBUG_NEG_REMOVE_ERROR
15348 static const GLchar* var_definition_arr =
15349 "layout (location = 1 /*, component = COMPONENT */) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15350 static const GLchar* var_definition_one =
15351 "layout (location = 1 /*, component = COMPONENT */) FLAT DIRECTION TYPE gokuARRAY;\n";
15352 #else
15353 static const GLchar* var_definition_arr =
15354 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15355 static const GLchar* var_definition_one =
15356 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
15357 #endif /* DEBUG_NEG_REMOVE_ERROR */
15358 static const GLchar* input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
15359 " {\n"
15360 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15361 " }\n";
15362 static const GLchar* input_use_one = " if (TYPE(0) == gokuINDEX)\n"
15363 " {\n"
15364 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15365 " }\n";
15366 static const GLchar* output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
15367 " if (vec4(0) == result)\n"
15368 " {\n"
15369 " gokuINDEX[0] = TYPE(1);\n"
15370 " }\n";
15371 static const GLchar* output_use_one = " gokuINDEX = TYPE(0);\n"
15372 " if (vec4(0) == result)\n"
15373 " {\n"
15374 " gokuINDEX = TYPE(1);\n"
15375 " }\n";
15376 static const GLchar* fs = "#version 430 core\n"
15377 "#extension GL_ARB_enhanced_layouts : require\n"
15378 "\n"
15379 "in vec4 gs_fs;\n"
15380 "out vec4 fs_out;\n"
15381 "\n"
15382 "void main()\n"
15383 "{\n"
15384 " fs_out = gs_fs;\n"
15385 "}\n"
15386 "\n";
15387 static const GLchar* fs_tested = "#version 430 core\n"
15388 "#extension GL_ARB_enhanced_layouts : require\n"
15389 "\n"
15390 "VAR_DEFINITION"
15391 "\n"
15392 "in vec4 gs_fs;\n"
15393 "out vec4 fs_out;\n"
15394 "\n"
15395 "void main()\n"
15396 "{\n"
15397 " vec4 result = gs_fs;\n"
15398 "\n"
15399 "VARIABLE_USE"
15400 "\n"
15401 " fs_out += result;\n"
15402 "}\n"
15403 "\n";
15404 static const GLchar* gs = "#version 430 core\n"
15405 "#extension GL_ARB_enhanced_layouts : require\n"
15406 "\n"
15407 "layout(points) in;\n"
15408 "layout(triangle_strip, max_vertices = 4) out;\n"
15409 "\n"
15410 "in vec4 tes_gs[];\n"
15411 "out vec4 gs_fs;\n"
15412 "\n"
15413 "void main()\n"
15414 "{\n"
15415 " gs_fs = tes_gs[0];\n"
15416 " gl_Position = vec4(-1, -1, 0, 1);\n"
15417 " EmitVertex();\n"
15418 " gs_fs = tes_gs[0];\n"
15419 " gl_Position = vec4(-1, 1, 0, 1);\n"
15420 " EmitVertex();\n"
15421 " gs_fs = tes_gs[0];\n"
15422 " gl_Position = vec4(1, -1, 0, 1);\n"
15423 " EmitVertex();\n"
15424 " gs_fs = tes_gs[0];\n"
15425 " gl_Position = vec4(1, 1, 0, 1);\n"
15426 " EmitVertex();\n"
15427 "}\n"
15428 "\n";
15429 static const GLchar* gs_tested = "#version 430 core\n"
15430 "#extension GL_ARB_enhanced_layouts : require\n"
15431 "\n"
15432 "layout(points) in;\n"
15433 "layout(triangle_strip, max_vertices = 4) out;\n"
15434 "\n"
15435 "VAR_DEFINITION"
15436 "\n"
15437 "in vec4 tes_gs[];\n"
15438 "out vec4 gs_fs;\n"
15439 "\n"
15440 "void main()\n"
15441 "{\n"
15442 " vec4 result = tes_gs[0];\n"
15443 "\n"
15444 "VARIABLE_USE"
15445 "\n"
15446 " gs_fs = result;\n"
15447 " gl_Position = vec4(-1, -1, 0, 1);\n"
15448 " EmitVertex();\n"
15449 " gs_fs = result;\n"
15450 " gl_Position = vec4(-1, 1, 0, 1);\n"
15451 " EmitVertex();\n"
15452 " gs_fs = result;\n"
15453 " gl_Position = vec4(1, -1, 0, 1);\n"
15454 " EmitVertex();\n"
15455 " gs_fs = result;\n"
15456 " gl_Position = vec4(1, 1, 0, 1);\n"
15457 " EmitVertex();\n"
15458 "}\n"
15459 "\n";
15460 static const GLchar* tcs = "#version 430 core\n"
15461 "#extension GL_ARB_enhanced_layouts : require\n"
15462 "\n"
15463 "layout(vertices = 1) out;\n"
15464 "\n"
15465 "in vec4 vs_tcs[];\n"
15466 "out vec4 tcs_tes[];\n"
15467 "\n"
15468 "void main()\n"
15469 "{\n"
15470 "\n"
15471 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15472 "\n"
15473 " gl_TessLevelOuter[0] = 1.0;\n"
15474 " gl_TessLevelOuter[1] = 1.0;\n"
15475 " gl_TessLevelOuter[2] = 1.0;\n"
15476 " gl_TessLevelOuter[3] = 1.0;\n"
15477 " gl_TessLevelInner[0] = 1.0;\n"
15478 " gl_TessLevelInner[1] = 1.0;\n"
15479 "}\n"
15480 "\n";
15481 static const GLchar* tcs_tested = "#version 430 core\n"
15482 "#extension GL_ARB_enhanced_layouts : require\n"
15483 "\n"
15484 "layout(vertices = 1) out;\n"
15485 "\n"
15486 "VAR_DEFINITION"
15487 "\n"
15488 "in vec4 vs_tcs[];\n"
15489 "out vec4 tcs_tes[];\n"
15490 "\n"
15491 "void main()\n"
15492 "{\n"
15493 " vec4 result = vs_tcs[gl_InvocationID];\n"
15494 "\n"
15495 "VARIABLE_USE"
15496 "\n"
15497 " tcs_tes[gl_InvocationID] = result;\n"
15498 "\n"
15499 " gl_TessLevelOuter[0] = 1.0;\n"
15500 " gl_TessLevelOuter[1] = 1.0;\n"
15501 " gl_TessLevelOuter[2] = 1.0;\n"
15502 " gl_TessLevelOuter[3] = 1.0;\n"
15503 " gl_TessLevelInner[0] = 1.0;\n"
15504 " gl_TessLevelInner[1] = 1.0;\n"
15505 "}\n"
15506 "\n";
15507 static const GLchar* tes = "#version 430 core\n"
15508 "#extension GL_ARB_enhanced_layouts : require\n"
15509 "\n"
15510 "layout(isolines, point_mode) in;\n"
15511 "\n"
15512 "in vec4 tcs_tes[];\n"
15513 "out vec4 tes_gs;\n"
15514 "\n"
15515 "void main()\n"
15516 "{\n"
15517 " tes_gs = tcs_tes[0];\n"
15518 "}\n"
15519 "\n";
15520 static const GLchar* tes_tested = "#version 430 core\n"
15521 "#extension GL_ARB_enhanced_layouts : require\n"
15522 "\n"
15523 "layout(isolines, point_mode) in;\n"
15524 "\n"
15525 "VAR_DEFINITION"
15526 "\n"
15527 "in vec4 tcs_tes[];\n"
15528 "out vec4 tes_gs;\n"
15529 "\n"
15530 "void main()\n"
15531 "{\n"
15532 " vec4 result = tcs_tes[0];\n"
15533 "\n"
15534 "VARIABLE_USE"
15535 "\n"
15536 " tes_gs += result;\n"
15537 "}\n"
15538 "\n";
15539 static const GLchar* vs = "#version 430 core\n"
15540 "#extension GL_ARB_enhanced_layouts : require\n"
15541 "\n"
15542 "in vec4 in_vs;\n"
15543 "out vec4 vs_tcs;\n"
15544 "\n"
15545 "void main()\n"
15546 "{\n"
15547 " vs_tcs = in_vs;\n"
15548 "}\n"
15549 "\n";
15550 static const GLchar* vs_tested = "#version 430 core\n"
15551 "#extension GL_ARB_enhanced_layouts : require\n"
15552 "\n"
15553 "VAR_DEFINITION"
15554 "\n"
15555 "in vec4 in_vs;\n"
15556 "out vec4 vs_tcs;\n"
15557 "\n"
15558 "void main()\n"
15559 "{\n"
15560 " vec4 result = in_vs;\n"
15561 "\n"
15562 "VARIABLE_USE"
15563 "\n"
15564 " vs_tcs += result;\n"
15565 "}\n"
15566 "\n";
15567
15568 std::string source;
15569 testCase& test_case = m_test_cases[test_case_index];
15570
15571 if (test_case.m_stage == stage)
15572 {
15573 const GLchar* array = "";
15574 GLchar buffer[16];
15575 const GLchar* var_definition = 0;
15576 const GLchar* direction = "in";
15577 const GLchar* index = "";
15578 size_t position = 0;
15579 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
15580 const GLchar* var_use = 0;
15581 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
15582 const GLchar* flat = "";
15583
15584 if (false == test_case.m_is_input)
15585 {
15586 direction = "out";
15587 storage = Utils::Variable::VARYING_OUTPUT;
15588
15589 if (false == test_case.m_is_array)
15590 {
15591 var_definition = var_definition_one;
15592 var_use = output_use_one;
15593 }
15594 else
15595 {
15596 var_definition = var_definition_arr;
15597 var_use = output_use_arr;
15598 }
15599 }
15600 else
15601 {
15602 if (false == test_case.m_is_array)
15603 {
15604 var_definition = var_definition_one;
15605 var_use = Utils::Shader::VERTEX == stage ? input_use_one : "\n";
15606 }
15607 else
15608 {
15609 var_definition = var_definition_arr;
15610 var_use = Utils::Shader::VERTEX == stage ? input_use_arr : "\n";
15611 }
15612 }
15613
15614 if (isFlatRequired(stage, test_case.m_type, storage, true))
15615 {
15616 flat = "flat";
15617 }
15618
15619 sprintf(buffer, "%d", test_case.m_component);
15620
15621 switch (stage)
15622 {
15623 case Utils::Shader::FRAGMENT:
15624 source = fs_tested;
15625 break;
15626 case Utils::Shader::GEOMETRY:
15627 source = gs_tested;
15628 array = test_case.m_is_input ? "[]" : "";
15629 index = test_case.m_is_input ? "[0]" : "";
15630 break;
15631 case Utils::Shader::TESS_CTRL:
15632 source = tcs_tested;
15633 array = "[]";
15634 index = "[gl_InvocationID]";
15635 break;
15636 case Utils::Shader::TESS_EVAL:
15637 source = tes_tested;
15638 array = test_case.m_is_input ? "[]" : "";
15639 index = test_case.m_is_input ? "[0]" : "";
15640 break;
15641 case Utils::Shader::VERTEX:
15642 source = vs_tested;
15643 break;
15644 default:
15645 TCU_FAIL("Invalid enum");
15646 }
15647
15648 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
15649 position = 0;
15650 Utils::replaceToken("COMPONENT", position, buffer, source);
15651 Utils::replaceToken("FLAT", position, flat, source);
15652 Utils::replaceToken("DIRECTION", position, direction, source);
15653 Utils::replaceToken("ARRAY", position, array, source);
15654 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
15655
15656 Utils::replaceAllTokens("TYPE", type_name, source);
15657 Utils::replaceAllTokens("INDEX", index, source);
15658 }
15659 else
15660 {
15661 switch (stage)
15662 {
15663 case Utils::Shader::FRAGMENT:
15664 source = fs;
15665 break;
15666 case Utils::Shader::GEOMETRY:
15667 source = gs;
15668 break;
15669 case Utils::Shader::TESS_CTRL:
15670 source = tcs;
15671 break;
15672 case Utils::Shader::TESS_EVAL:
15673 source = tes;
15674 break;
15675 case Utils::Shader::VERTEX:
15676 source = vs;
15677 break;
15678 default:
15679 TCU_FAIL("Invalid enum");
15680 }
15681 }
15682
15683 return source;
15684 }
15685
15686 /** Get description of test case
15687 *
15688 * @param test_case_index Index of test case
15689 *
15690 * @return Test case description
15691 **/
15692 std::string VaryingInvalidValueComponentTest::getTestCaseName(GLuint test_case_index)
15693 {
15694 std::stringstream stream;
15695 testCase& test_case = m_test_cases[test_case_index];
15696
15697 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
15698 << " type: " << test_case.m_type.GetGLSLTypeName();
15699
15700 if (true == test_case.m_is_array)
15701 {
15702 stream << "[1]";
15703 }
15704
15705 stream << ", direction: ";
15706
15707 if (true == test_case.m_is_input)
15708 {
15709 stream << "input";
15710 }
15711 else
15712 {
15713 stream << "output";
15714 }
15715
15716 stream << ", component: " << test_case.m_component;
15717
15718 return stream.str();
15719 }
15720
15721 /** Get number of test cases
15722 *
15723 * @return Number of test cases
15724 **/
15725 GLuint VaryingInvalidValueComponentTest::getTestCaseNumber()
15726 {
15727 return static_cast<GLuint>(m_test_cases.size());
15728 }
15729
15730 /** Selects if "compute" stage is relevant for test
15731 *
15732 * @param ignored
15733 *
15734 * @return false
15735 **/
15736 bool VaryingInvalidValueComponentTest::isComputeRelevant(GLuint /* test_case_index */)
15737 {
15738 return false;
15739 }
15740
15741 /** Prepare all test cases
15742 *
15743 **/
15744 void VaryingInvalidValueComponentTest::testInit()
15745 {
15746 const GLuint n_types = getTypesNumber();
15747
15748 for (GLuint i = 0; i < n_types; ++i)
15749 {
15750 const Utils::Type& type = getType(i);
15751 const std::vector<GLuint>& valid_components = type.GetValidComponents();
15752
15753 if (valid_components.empty())
15754 {
15755 continue;
15756 }
15757
15758 std::vector<GLuint> every_component(4, 0);
15759 every_component[1] = 1;
15760 every_component[2] = 2;
15761 every_component[3] = 3;
15762 std::vector<GLuint> invalid_components;
15763
15764 std::set_symmetric_difference(every_component.begin(), every_component.end(), valid_components.begin(),
15765 valid_components.end(), back_inserter(invalid_components));
15766
15767 for (std::vector<GLuint>::const_iterator it_invalid_components = invalid_components.begin();
15768 it_invalid_components != invalid_components.end(); ++it_invalid_components)
15769 {
15770 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
15771 {
15772 if (Utils::Shader::COMPUTE == stage)
15773 {
15774 continue;
15775 }
15776
15777 testCase test_case_in_arr = { *it_invalid_components, true, true, (Utils::Shader::STAGES)stage, type };
15778 testCase test_case_in_one = { *it_invalid_components, true, false, (Utils::Shader::STAGES)stage, type };
15779 testCase test_case_out_arr = { *it_invalid_components, false, true, (Utils::Shader::STAGES)stage,
15780 type };
15781 testCase test_case_out_one = { *it_invalid_components, false, false, (Utils::Shader::STAGES)stage,
15782 type };
15783
15784 m_test_cases.push_back(test_case_in_arr);
15785 m_test_cases.push_back(test_case_in_one);
15786
15787 if (Utils::Shader::FRAGMENT != stage)
15788 {
15789 m_test_cases.push_back(test_case_out_arr);
15790 m_test_cases.push_back(test_case_out_one);
15791 }
15792 }
15793 }
15794 }
15795 }
15796
15797 /** Constructor
15798 *
15799 * @param context Test framework context
15800 **/
15801 VaryingExceedingComponentsTest::VaryingExceedingComponentsTest(deqp::Context& context)
15802 : NegativeTestBase(context, "varying_exceeding_components",
15803 "Test verifies that compiler reports error when component qualifier exceeds limits")
15804 {
15805 }
15806
15807 /** Source for given test case and stage
15808 *
15809 * @param test_case_index Index of test case
15810 * @param stage Shader stage
15811 *
15812 * @return Shader source
15813 **/
15814 std::string VaryingExceedingComponentsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15815 {
15816 #if DEBUG_NEG_REMOVE_ERROR
15817 static const GLchar* var_definition_arr =
15818 "layout (location = 1 /*, component = 4 */) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15819 static const GLchar* var_definition_one =
15820 "layout (location = 1 /*, component = 4 */) FLAT DIRECTION TYPE gokuARRAY;\n";
15821 #else
15822 static const GLchar* var_definition_arr =
15823 "layout (location = 1, component = 4) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15824 static const GLchar* var_definition_one = "layout (location = 1, component = 4) FLAT DIRECTION TYPE gokuARRAY;\n";
15825 #endif /* DEBUG_NEG_REMOVE_ERROR */
15826 static const GLchar* input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
15827 " {\n"
15828 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15829 " }\n";
15830 static const GLchar* input_use_one = " if (TYPE(0) == gokuINDEX)\n"
15831 " {\n"
15832 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15833 " }\n";
15834 static const GLchar* output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
15835 " if (vec4(0) == result)\n"
15836 " {\n"
15837 " gokuINDEX[0] = TYPE(1);\n"
15838 " }\n";
15839 static const GLchar* output_use_one = " gokuINDEX = TYPE(0);\n"
15840 " if (vec4(0) == result)\n"
15841 " {\n"
15842 " gokuINDEX = TYPE(1);\n"
15843 " }\n";
15844 static const GLchar* fs = "#version 430 core\n"
15845 "#extension GL_ARB_enhanced_layouts : require\n"
15846 "\n"
15847 "in vec4 gs_fs;\n"
15848 "out vec4 fs_out;\n"
15849 "\n"
15850 "void main()\n"
15851 "{\n"
15852 " fs_out = gs_fs;\n"
15853 "}\n"
15854 "\n";
15855 static const GLchar* fs_tested = "#version 430 core\n"
15856 "#extension GL_ARB_enhanced_layouts : require\n"
15857 "\n"
15858 "VAR_DEFINITION"
15859 "\n"
15860 "in vec4 gs_fs;\n"
15861 "out vec4 fs_out;\n"
15862 "\n"
15863 "void main()\n"
15864 "{\n"
15865 " vec4 result = gs_fs;\n"
15866 "\n"
15867 "VARIABLE_USE"
15868 "\n"
15869 " fs_out += result;\n"
15870 "}\n"
15871 "\n";
15872 static const GLchar* gs = "#version 430 core\n"
15873 "#extension GL_ARB_enhanced_layouts : require\n"
15874 "\n"
15875 "layout(points) in;\n"
15876 "layout(triangle_strip, max_vertices = 4) out;\n"
15877 "\n"
15878 "in vec4 tes_gs[];\n"
15879 "out vec4 gs_fs;\n"
15880 "\n"
15881 "void main()\n"
15882 "{\n"
15883 " gs_fs = tes_gs[0];\n"
15884 " gl_Position = vec4(-1, -1, 0, 1);\n"
15885 " EmitVertex();\n"
15886 " gs_fs = tes_gs[0];\n"
15887 " gl_Position = vec4(-1, 1, 0, 1);\n"
15888 " EmitVertex();\n"
15889 " gs_fs = tes_gs[0];\n"
15890 " gl_Position = vec4(1, -1, 0, 1);\n"
15891 " EmitVertex();\n"
15892 " gs_fs = tes_gs[0];\n"
15893 " gl_Position = vec4(1, 1, 0, 1);\n"
15894 " EmitVertex();\n"
15895 "}\n"
15896 "\n";
15897 static const GLchar* gs_tested = "#version 430 core\n"
15898 "#extension GL_ARB_enhanced_layouts : require\n"
15899 "\n"
15900 "layout(points) in;\n"
15901 "layout(triangle_strip, max_vertices = 4) out;\n"
15902 "\n"
15903 "VAR_DEFINITION"
15904 "\n"
15905 "in vec4 tes_gs[];\n"
15906 "out vec4 gs_fs;\n"
15907 "\n"
15908 "void main()\n"
15909 "{\n"
15910 " vec4 result = tes_gs[0];\n"
15911 "\n"
15912 "VARIABLE_USE"
15913 "\n"
15914 " gs_fs = result;\n"
15915 " gl_Position = vec4(-1, -1, 0, 1);\n"
15916 " EmitVertex();\n"
15917 " gs_fs = result;\n"
15918 " gl_Position = vec4(-1, 1, 0, 1);\n"
15919 " EmitVertex();\n"
15920 " gs_fs = result;\n"
15921 " gl_Position = vec4(1, -1, 0, 1);\n"
15922 " EmitVertex();\n"
15923 " gs_fs = result;\n"
15924 " gl_Position = vec4(1, 1, 0, 1);\n"
15925 " EmitVertex();\n"
15926 "}\n"
15927 "\n";
15928 static const GLchar* tcs = "#version 430 core\n"
15929 "#extension GL_ARB_enhanced_layouts : require\n"
15930 "\n"
15931 "layout(vertices = 1) out;\n"
15932 "\n"
15933 "in vec4 vs_tcs[];\n"
15934 "out vec4 tcs_tes[];\n"
15935 "\n"
15936 "void main()\n"
15937 "{\n"
15938 "\n"
15939 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15940 "\n"
15941 " gl_TessLevelOuter[0] = 1.0;\n"
15942 " gl_TessLevelOuter[1] = 1.0;\n"
15943 " gl_TessLevelOuter[2] = 1.0;\n"
15944 " gl_TessLevelOuter[3] = 1.0;\n"
15945 " gl_TessLevelInner[0] = 1.0;\n"
15946 " gl_TessLevelInner[1] = 1.0;\n"
15947 "}\n"
15948 "\n";
15949 static const GLchar* tcs_tested = "#version 430 core\n"
15950 "#extension GL_ARB_enhanced_layouts : require\n"
15951 "\n"
15952 "layout(vertices = 1) out;\n"
15953 "\n"
15954 "VAR_DEFINITION"
15955 "\n"
15956 "in vec4 vs_tcs[];\n"
15957 "out vec4 tcs_tes[];\n"
15958 "\n"
15959 "void main()\n"
15960 "{\n"
15961 " vec4 result = vs_tcs[gl_InvocationID];\n"
15962 "\n"
15963 "VARIABLE_USE"
15964 "\n"
15965 " tcs_tes[gl_InvocationID] = result;\n"
15966 "\n"
15967 " gl_TessLevelOuter[0] = 1.0;\n"
15968 " gl_TessLevelOuter[1] = 1.0;\n"
15969 " gl_TessLevelOuter[2] = 1.0;\n"
15970 " gl_TessLevelOuter[3] = 1.0;\n"
15971 " gl_TessLevelInner[0] = 1.0;\n"
15972 " gl_TessLevelInner[1] = 1.0;\n"
15973 "}\n"
15974 "\n";
15975 static const GLchar* tes = "#version 430 core\n"
15976 "#extension GL_ARB_enhanced_layouts : require\n"
15977 "\n"
15978 "layout(isolines, point_mode) in;\n"
15979 "\n"
15980 "in vec4 tcs_tes[];\n"
15981 "out vec4 tes_gs;\n"
15982 "\n"
15983 "void main()\n"
15984 "{\n"
15985 " tes_gs = tcs_tes[0];\n"
15986 "}\n"
15987 "\n";
15988 static const GLchar* tes_tested = "#version 430 core\n"
15989 "#extension GL_ARB_enhanced_layouts : require\n"
15990 "\n"
15991 "layout(isolines, point_mode) in;\n"
15992 "\n"
15993 "VAR_DEFINITION"
15994 "\n"
15995 "in vec4 tcs_tes[];\n"
15996 "out vec4 tes_gs;\n"
15997 "\n"
15998 "void main()\n"
15999 "{\n"
16000 " vec4 result = tcs_tes[0];\n"
16001 "\n"
16002 "VARIABLE_USE"
16003 "\n"
16004 " tes_gs += result;\n"
16005 "}\n"
16006 "\n";
16007 static const GLchar* vs = "#version 430 core\n"
16008 "#extension GL_ARB_enhanced_layouts : require\n"
16009 "\n"
16010 "in vec4 in_vs;\n"
16011 "out vec4 vs_tcs;\n"
16012 "\n"
16013 "void main()\n"
16014 "{\n"
16015 " vs_tcs = in_vs;\n"
16016 "}\n"
16017 "\n";
16018 static const GLchar* vs_tested = "#version 430 core\n"
16019 "#extension GL_ARB_enhanced_layouts : require\n"
16020 "\n"
16021 "VAR_DEFINITION"
16022 "\n"
16023 "in vec4 in_vs;\n"
16024 "out vec4 vs_tcs;\n"
16025 "\n"
16026 "void main()\n"
16027 "{\n"
16028 " vec4 result = in_vs;\n"
16029 "\n"
16030 "VARIABLE_USE"
16031 "\n"
16032 " vs_tcs += result;\n"
16033 "}\n"
16034 "\n";
16035
16036 std::string source;
16037 testCase& test_case = m_test_cases[test_case_index];
16038
16039 if (test_case.m_stage == stage)
16040 {
16041 const GLchar* array = "";
16042 const GLchar* var_definition = 0;
16043 const GLchar* direction = "in";
16044 const GLchar* index = "";
16045 size_t position = 0;
16046 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16047 const GLchar* var_use = 0;
16048 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16049 const GLchar* flat = "";
16050
16051 if (false == test_case.m_is_input)
16052 {
16053 direction = "out";
16054 storage = Utils::Variable::VARYING_OUTPUT;
16055
16056 if (false == test_case.m_is_array)
16057 {
16058 var_definition = var_definition_one;
16059 var_use = output_use_one;
16060 }
16061 else
16062 {
16063 var_definition = var_definition_arr;
16064 var_use = output_use_arr;
16065 }
16066 }
16067 else
16068 {
16069 if (false == test_case.m_is_array)
16070 {
16071 var_definition = var_definition_one;
16072 var_use = Utils::Shader::VERTEX == stage ? input_use_one : "\n";
16073 }
16074 else
16075 {
16076 var_definition = var_definition_arr;
16077 var_use = Utils::Shader::VERTEX == stage ? input_use_arr : "\n";
16078 }
16079 }
16080
16081 if (isFlatRequired(stage, test_case.m_type, storage, true))
16082 {
16083 flat = "flat";
16084 }
16085
16086 switch (stage)
16087 {
16088 case Utils::Shader::FRAGMENT:
16089 source = fs_tested;
16090 break;
16091 case Utils::Shader::GEOMETRY:
16092 source = gs_tested;
16093 array = test_case.m_is_input ? "[]" : "";
16094 index = test_case.m_is_input ? "[0]" : "";
16095 break;
16096 case Utils::Shader::TESS_CTRL:
16097 source = tcs_tested;
16098 array = "[]";
16099 index = "[gl_InvocationID]";
16100 break;
16101 case Utils::Shader::TESS_EVAL:
16102 source = tes_tested;
16103 array = test_case.m_is_input ? "[]" : "";
16104 index = test_case.m_is_input ? "[0]" : "";
16105 break;
16106 case Utils::Shader::VERTEX:
16107 source = vs_tested;
16108 break;
16109 default:
16110 TCU_FAIL("Invalid enum");
16111 }
16112
16113 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16114 position = 0;
16115 Utils::replaceToken("FLAT", position, flat, source);
16116 Utils::replaceToken("DIRECTION", position, direction, source);
16117 Utils::replaceToken("ARRAY", position, array, source);
16118 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16119
16120 Utils::replaceAllTokens("TYPE", type_name, source);
16121 Utils::replaceAllTokens("INDEX", index, source);
16122 }
16123 else
16124 {
16125 switch (stage)
16126 {
16127 case Utils::Shader::FRAGMENT:
16128 source = fs;
16129 break;
16130 case Utils::Shader::GEOMETRY:
16131 source = gs;
16132 break;
16133 case Utils::Shader::TESS_CTRL:
16134 source = tcs;
16135 break;
16136 case Utils::Shader::TESS_EVAL:
16137 source = tes;
16138 break;
16139 case Utils::Shader::VERTEX:
16140 source = vs;
16141 break;
16142 default:
16143 TCU_FAIL("Invalid enum");
16144 }
16145 }
16146
16147 return source;
16148 }
16149
16150 /** Get description of test case
16151 *
16152 * @param test_case_index Index of test case
16153 *
16154 * @return Test case description
16155 **/
16156 std::string VaryingExceedingComponentsTest::getTestCaseName(GLuint test_case_index)
16157 {
16158 std::stringstream stream;
16159 testCase& test_case = m_test_cases[test_case_index];
16160
16161 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16162 << " type: " << test_case.m_type.GetGLSLTypeName();
16163
16164 if (true == test_case.m_is_array)
16165 {
16166 stream << "[1]";
16167 }
16168
16169 stream << ", direction: ";
16170
16171 if (true == test_case.m_is_input)
16172 {
16173 stream << "input";
16174 }
16175 else
16176 {
16177 stream << "output";
16178 }
16179
16180 return stream.str();
16181 }
16182
16183 /** Get number of test cases
16184 *
16185 * @return Number of test cases
16186 **/
16187 GLuint VaryingExceedingComponentsTest::getTestCaseNumber()
16188 {
16189 return static_cast<GLuint>(m_test_cases.size());
16190 }
16191
16192 /** Selects if "compute" stage is relevant for test
16193 *
16194 * @param ignored
16195 *
16196 * @return false
16197 **/
16198 bool VaryingExceedingComponentsTest::isComputeRelevant(GLuint /* test_case_index */)
16199 {
16200 return false;
16201 }
16202
16203 /** Prepare all test cases
16204 *
16205 **/
16206 void VaryingExceedingComponentsTest::testInit()
16207 {
16208 const GLuint n_types = getTypesNumber();
16209
16210 for (GLuint i = 0; i < n_types; ++i)
16211 {
16212 const Utils::Type& type = getType(i);
16213 const std::vector<GLuint>& valid_components = type.GetValidComponents();
16214
16215 if (valid_components.empty())
16216 {
16217 continue;
16218 }
16219
16220 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16221 {
16222 if (Utils::Shader::COMPUTE == stage)
16223 {
16224 continue;
16225 }
16226
16227 testCase test_case_in_arr = { true, true, (Utils::Shader::STAGES)stage, type };
16228 testCase test_case_in_one = { true, false, (Utils::Shader::STAGES)stage, type };
16229 testCase test_case_out_arr = { false, true, (Utils::Shader::STAGES)stage, type };
16230 testCase test_case_out_one = { false, false, (Utils::Shader::STAGES)stage, type };
16231
16232 m_test_cases.push_back(test_case_in_arr);
16233 m_test_cases.push_back(test_case_in_one);
16234
16235 if (Utils::Shader::FRAGMENT != stage)
16236 {
16237 m_test_cases.push_back(test_case_out_arr);
16238 m_test_cases.push_back(test_case_out_one);
16239 }
16240 }
16241 }
16242 }
16243
16244 /** Constructor
16245 *
16246 * @param context Test framework context
16247 **/
16248 VaryingComponentWithoutLocationTest::VaryingComponentWithoutLocationTest(deqp::Context& context)
16249 : NegativeTestBase(context, "varying_component_without_location",
16250 "Test verifies that compiler reports error when component qualifier is used without location")
16251 {
16252 }
16253
16254 /** Source for given test case and stage
16255 *
16256 * @param test_case_index Index of test case
16257 * @param stage Shader stage
16258 *
16259 * @return Shader source
16260 **/
16261 std::string VaryingComponentWithoutLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16262 {
16263 #if DEBUG_NEG_REMOVE_ERROR
16264 static const GLchar* var_definition = "/* layout (component = COMPONENT) */ FLAT DIRECTION TYPE gokuARRAY;\n";
16265 #else
16266 static const GLchar* var_definition = "layout (component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
16267 #endif /* DEBUG_NEG_REMOVE_ERROR */
16268 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
16269 " {\n"
16270 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16271 " }\n";
16272 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
16273 " if (vec4(0) == result)\n"
16274 " {\n"
16275 " gokuINDEX = TYPE(1);\n"
16276 " }\n";
16277 static const GLchar* fs = "#version 430 core\n"
16278 "#extension GL_ARB_enhanced_layouts : require\n"
16279 "\n"
16280 "in vec4 gs_fs;\n"
16281 "out vec4 fs_out;\n"
16282 "\n"
16283 "void main()\n"
16284 "{\n"
16285 " fs_out = gs_fs;\n"
16286 "}\n"
16287 "\n";
16288 static const GLchar* fs_tested = "#version 430 core\n"
16289 "#extension GL_ARB_enhanced_layouts : require\n"
16290 "\n"
16291 "VAR_DEFINITION"
16292 "\n"
16293 "in vec4 gs_fs;\n"
16294 "out vec4 fs_out;\n"
16295 "\n"
16296 "void main()\n"
16297 "{\n"
16298 " vec4 result = gs_fs;\n"
16299 "\n"
16300 "VARIABLE_USE"
16301 "\n"
16302 " fs_out = result;\n"
16303 "}\n"
16304 "\n";
16305 static const GLchar* gs = "#version 430 core\n"
16306 "#extension GL_ARB_enhanced_layouts : require\n"
16307 "\n"
16308 "layout(points) in;\n"
16309 "layout(triangle_strip, max_vertices = 4) out;\n"
16310 "\n"
16311 "in vec4 tes_gs[];\n"
16312 "out vec4 gs_fs;\n"
16313 "\n"
16314 "void main()\n"
16315 "{\n"
16316 " gs_fs = tes_gs[0];\n"
16317 " gl_Position = vec4(-1, -1, 0, 1);\n"
16318 " EmitVertex();\n"
16319 " gs_fs = tes_gs[0];\n"
16320 " gl_Position = vec4(-1, 1, 0, 1);\n"
16321 " EmitVertex();\n"
16322 " gs_fs = tes_gs[0];\n"
16323 " gl_Position = vec4(1, -1, 0, 1);\n"
16324 " EmitVertex();\n"
16325 " gs_fs = tes_gs[0];\n"
16326 " gl_Position = vec4(1, 1, 0, 1);\n"
16327 " EmitVertex();\n"
16328 "}\n"
16329 "\n";
16330 static const GLchar* gs_tested = "#version 430 core\n"
16331 "#extension GL_ARB_enhanced_layouts : require\n"
16332 "\n"
16333 "layout(points) in;\n"
16334 "layout(triangle_strip, max_vertices = 4) out;\n"
16335 "\n"
16336 "VAR_DEFINITION"
16337 "\n"
16338 "in vec4 tes_gs[];\n"
16339 "out vec4 gs_fs;\n"
16340 "\n"
16341 "void main()\n"
16342 "{\n"
16343 " vec4 result = tes_gs[0];\n"
16344 "\n"
16345 "VARIABLE_USE"
16346 "\n"
16347 " gs_fs = result;\n"
16348 " gl_Position = vec4(-1, -1, 0, 1);\n"
16349 " EmitVertex();\n"
16350 " gs_fs = result;\n"
16351 " gl_Position = vec4(-1, 1, 0, 1);\n"
16352 " EmitVertex();\n"
16353 " gs_fs = result;\n"
16354 " gl_Position = vec4(1, -1, 0, 1);\n"
16355 " EmitVertex();\n"
16356 " gs_fs = result;\n"
16357 " gl_Position = vec4(1, 1, 0, 1);\n"
16358 " EmitVertex();\n"
16359 "}\n"
16360 "\n";
16361 static const GLchar* tcs = "#version 430 core\n"
16362 "#extension GL_ARB_enhanced_layouts : require\n"
16363 "\n"
16364 "layout(vertices = 1) out;\n"
16365 "\n"
16366 "in vec4 vs_tcs[];\n"
16367 "out vec4 tcs_tes[];\n"
16368 "\n"
16369 "void main()\n"
16370 "{\n"
16371 "\n"
16372 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16373 "\n"
16374 " gl_TessLevelOuter[0] = 1.0;\n"
16375 " gl_TessLevelOuter[1] = 1.0;\n"
16376 " gl_TessLevelOuter[2] = 1.0;\n"
16377 " gl_TessLevelOuter[3] = 1.0;\n"
16378 " gl_TessLevelInner[0] = 1.0;\n"
16379 " gl_TessLevelInner[1] = 1.0;\n"
16380 "}\n"
16381 "\n";
16382 static const GLchar* tcs_tested = "#version 430 core\n"
16383 "#extension GL_ARB_enhanced_layouts : require\n"
16384 "\n"
16385 "layout(vertices = 1) out;\n"
16386 "\n"
16387 "VAR_DEFINITION"
16388 "\n"
16389 "in vec4 vs_tcs[];\n"
16390 "out vec4 tcs_tes[];\n"
16391 "\n"
16392 "void main()\n"
16393 "{\n"
16394 " vec4 result = vs_tcs[gl_InvocationID];\n"
16395 "\n"
16396 "VARIABLE_USE"
16397 "\n"
16398 " tcs_tes[gl_InvocationID] = result;\n"
16399 "\n"
16400 " gl_TessLevelOuter[0] = 1.0;\n"
16401 " gl_TessLevelOuter[1] = 1.0;\n"
16402 " gl_TessLevelOuter[2] = 1.0;\n"
16403 " gl_TessLevelOuter[3] = 1.0;\n"
16404 " gl_TessLevelInner[0] = 1.0;\n"
16405 " gl_TessLevelInner[1] = 1.0;\n"
16406 "}\n"
16407 "\n";
16408 static const GLchar* tes = "#version 430 core\n"
16409 "#extension GL_ARB_enhanced_layouts : require\n"
16410 "\n"
16411 "layout(isolines, point_mode) in;\n"
16412 "\n"
16413 "in vec4 tcs_tes[];\n"
16414 "out vec4 tes_gs;\n"
16415 "\n"
16416 "void main()\n"
16417 "{\n"
16418 " tes_gs = tcs_tes[0];\n"
16419 "}\n"
16420 "\n";
16421 static const GLchar* tes_tested = "#version 430 core\n"
16422 "#extension GL_ARB_enhanced_layouts : require\n"
16423 "\n"
16424 "layout(isolines, point_mode) in;\n"
16425 "\n"
16426 "VAR_DEFINITION"
16427 "\n"
16428 "in vec4 tcs_tes[];\n"
16429 "out vec4 tes_gs;\n"
16430 "\n"
16431 "void main()\n"
16432 "{\n"
16433 " vec4 result = tcs_tes[0];\n"
16434 "\n"
16435 "VARIABLE_USE"
16436 "\n"
16437 " tes_gs = result;\n"
16438 "}\n"
16439 "\n";
16440 static const GLchar* vs = "#version 430 core\n"
16441 "#extension GL_ARB_enhanced_layouts : require\n"
16442 "\n"
16443 "in vec4 in_vs;\n"
16444 "out vec4 vs_tcs;\n"
16445 "\n"
16446 "void main()\n"
16447 "{\n"
16448 " vs_tcs = in_vs;\n"
16449 "}\n"
16450 "\n";
16451 static const GLchar* vs_tested = "#version 430 core\n"
16452 "#extension GL_ARB_enhanced_layouts : require\n"
16453 "\n"
16454 "VAR_DEFINITION"
16455 "\n"
16456 "in vec4 in_vs;\n"
16457 "out vec4 vs_tcs;\n"
16458 "\n"
16459 "void main()\n"
16460 "{\n"
16461 " vec4 result = in_vs;\n"
16462 "\n"
16463 "VARIABLE_USE"
16464 "\n"
16465 " vs_tcs = result;\n"
16466 "}\n"
16467 "\n";
16468
16469 std::string source;
16470 testCase& test_case = m_test_cases[test_case_index];
16471
16472 if (test_case.m_stage == stage)
16473 {
16474 const GLchar* array = "";
16475 GLchar buffer[16];
16476 const GLchar* direction = "in";
16477 const GLchar* index = "";
16478 size_t position = 0;
16479 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16480 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
16481 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16482 const GLchar* flat = "";
16483
16484 if (false == test_case.m_is_input)
16485 {
16486 direction = "out";
16487 storage = Utils::Variable::VARYING_OUTPUT;
16488 var_use = output_use;
16489 }
16490
16491 if (isFlatRequired(stage, test_case.m_type, storage, true))
16492 {
16493 flat = "flat";
16494 }
16495
16496 sprintf(buffer, "%d", test_case.m_component);
16497
16498 switch (stage)
16499 {
16500 case Utils::Shader::FRAGMENT:
16501 source = fs_tested;
16502 break;
16503 case Utils::Shader::GEOMETRY:
16504 source = gs_tested;
16505 array = test_case.m_is_input ? "[]" : "";
16506 index = test_case.m_is_input ? "[0]" : "";
16507 break;
16508 case Utils::Shader::TESS_CTRL:
16509 source = tcs_tested;
16510 array = "[]";
16511 index = "[gl_InvocationID]";
16512 break;
16513 case Utils::Shader::TESS_EVAL:
16514 source = tes_tested;
16515 array = test_case.m_is_input ? "[]" : "";
16516 index = test_case.m_is_input ? "[0]" : "";
16517 break;
16518 case Utils::Shader::VERTEX:
16519 source = vs_tested;
16520 break;
16521 default:
16522 TCU_FAIL("Invalid enum");
16523 }
16524
16525 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16526 position = 0;
16527 Utils::replaceToken("COMPONENT", position, buffer, source);
16528 Utils::replaceToken("FLAT", position, flat, source);
16529 Utils::replaceToken("DIRECTION", position, direction, source);
16530 Utils::replaceToken("ARRAY", position, array, source);
16531 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16532
16533 Utils::replaceAllTokens("TYPE", type_name, source);
16534 Utils::replaceAllTokens("INDEX", index, source);
16535 }
16536 else
16537 {
16538 switch (stage)
16539 {
16540 case Utils::Shader::FRAGMENT:
16541 source = fs;
16542 break;
16543 case Utils::Shader::GEOMETRY:
16544 source = gs;
16545 break;
16546 case Utils::Shader::TESS_CTRL:
16547 source = tcs;
16548 break;
16549 case Utils::Shader::TESS_EVAL:
16550 source = tes;
16551 break;
16552 case Utils::Shader::VERTEX:
16553 source = vs;
16554 break;
16555 default:
16556 TCU_FAIL("Invalid enum");
16557 }
16558 }
16559
16560 return source;
16561 }
16562
16563 /** Get description of test case
16564 *
16565 * @param test_case_index Index of test case
16566 *
16567 * @return Test case description
16568 **/
16569 std::string VaryingComponentWithoutLocationTest::getTestCaseName(GLuint test_case_index)
16570 {
16571 std::stringstream stream;
16572 testCase& test_case = m_test_cases[test_case_index];
16573
16574 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16575 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
16576
16577 if (true == test_case.m_is_input)
16578 {
16579 stream << "input";
16580 }
16581 else
16582 {
16583 stream << "output";
16584 }
16585
16586 stream << ", component: " << test_case.m_component;
16587
16588 return stream.str();
16589 }
16590
16591 /** Get number of test cases
16592 *
16593 * @return Number of test cases
16594 **/
16595 GLuint VaryingComponentWithoutLocationTest::getTestCaseNumber()
16596 {
16597 return static_cast<GLuint>(m_test_cases.size());
16598 }
16599
16600 /** Selects if "compute" stage is relevant for test
16601 *
16602 * @param ignored
16603 *
16604 * @return false
16605 **/
16606 bool VaryingComponentWithoutLocationTest::isComputeRelevant(GLuint /* test_case_index */)
16607 {
16608 return false;
16609 }
16610
16611 /** Prepare all test cases
16612 *
16613 **/
16614 void VaryingComponentWithoutLocationTest::testInit()
16615 {
16616 const GLuint n_types = getTypesNumber();
16617
16618 for (GLuint i = 0; i < n_types; ++i)
16619 {
16620 const Utils::Type& type = getType(i);
16621 const std::vector<GLuint>& valid_components = type.GetValidComponents();
16622
16623 if (valid_components.empty())
16624 {
16625 continue;
16626 }
16627
16628 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16629 {
16630 if (Utils::Shader::COMPUTE == stage)
16631 {
16632 continue;
16633 }
16634
16635 testCase test_case_in = { valid_components.back(), true, (Utils::Shader::STAGES)stage, type };
16636 testCase test_case_out = { valid_components.back(), false, (Utils::Shader::STAGES)stage, type };
16637
16638 m_test_cases.push_back(test_case_in);
16639
16640 if (Utils::Shader::FRAGMENT != stage)
16641 {
16642 m_test_cases.push_back(test_case_out);
16643 }
16644 }
16645 }
16646 }
16647
16648 /** Constructor
16649 *
16650 * @param context Test framework context
16651 **/
16652 VaryingComponentOfInvalidTypeTest::VaryingComponentOfInvalidTypeTest(deqp::Context& context)
16653 : NegativeTestBase(context, "varying_component_of_invalid_type",
16654 "Test verifies that compiler reports error when component qualifier is used for invalid type")
16655 {
16656 }
16657
16658 /** Source for given test case and stage
16659 *
16660 * @param test_case_index Index of test case
16661 * @param stage Shader stage
16662 *
16663 * @return Shader source
16664 **/
16665 std::string VaryingComponentOfInvalidTypeTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16666 {
16667 static const GLchar* block_definition_arr = "layout (location = 1COMPONENT) DIRECTION Goku {\n"
16668 " FLAT TYPE member;\n"
16669 "} gokuARRAY[1];\n";
16670 static const GLchar* block_definition_one = "layout (location = 1COMPONENT) DIRECTION Goku {\n"
16671 " FLAT TYPE member;\n"
16672 "} gokuARRAY;\n";
16673 static const GLchar* matrix_dvec3_dvec4_definition_arr =
16674 "layout (location = 1COMPONENT) FLAT DIRECTION TYPE gokuARRAY[1];\n";
16675 static const GLchar* matrix_dvec3_dvec4_definition_one =
16676 "layout (location = 1COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
16677 static const GLchar* struct_definition_arr = "struct Goku {\n"
16678 " TYPE member;\n"
16679 "};\n"
16680 "\n"
16681 "layout (location = 1COMPONENT) FLAT DIRECTION Goku gokuARRAY[1];\n";
16682 static const GLchar* struct_definition_one = "struct Goku {\n"
16683 " TYPE member;\n"
16684 "};\n"
16685 "\n"
16686 "layout (location = 1COMPONENT) FLAT DIRECTION Goku gokuARRAY;\n";
16687 static const GLchar* matrix_dvec3_dvec4_input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
16688 " {\n"
16689 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16690 " }\n";
16691 static const GLchar* matrix_dvec3_dvec4_input_use_one = " if (TYPE(0) == gokuINDEX)\n"
16692 " {\n"
16693 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16694 " }\n";
16695 static const GLchar* matrix_dvec3_dvec4_output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
16696 " if (vec4(0) == result)\n"
16697 " {\n"
16698 " gokuINDEX[0] = TYPE(1);\n"
16699 " }\n";
16700 static const GLchar* matrix_dvec3_dvec4_output_use_one = " gokuINDEX = TYPE(0);\n"
16701 " if (vec4(0) == result)\n"
16702 " {\n"
16703 " gokuINDEX = TYPE(1);\n"
16704 " }\n";
16705 static const GLchar* member_input_use_arr = " if (TYPE(0) == gokuINDEX[0].member)\n"
16706 " {\n"
16707 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16708 " }\n";
16709 static const GLchar* member_input_use_one = " if (TYPE(0) == gokuINDEX.member)\n"
16710 " {\n"
16711 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16712 " }\n";
16713 static const GLchar* member_output_use_arr = " gokuINDEX[0].member = TYPE(0);\n"
16714 " if (vec4(0) == result)\n"
16715 " {\n"
16716 " gokuINDEX[0].member = TYPE(1);\n"
16717 " }\n";
16718 static const GLchar* member_output_use_one = " gokuINDEX.member = TYPE(0);\n"
16719 " if (vec4(0) == result)\n"
16720 " {\n"
16721 " gokuINDEX.member = TYPE(1);\n"
16722 " }\n";
16723 static const GLchar* fs = "#version 430 core\n"
16724 "#extension GL_ARB_enhanced_layouts : require\n"
16725 "\n"
16726 "in vec4 gs_fs;\n"
16727 "out vec4 fs_out;\n"
16728 "\n"
16729 "void main()\n"
16730 "{\n"
16731 " fs_out = gs_fs;\n"
16732 "}\n"
16733 "\n";
16734 static const GLchar* fs_tested = "#version 430 core\n"
16735 "#extension GL_ARB_enhanced_layouts : require\n"
16736 "\n"
16737 "VAR_DEFINITION"
16738 "\n"
16739 "in vec4 gs_fs;\n"
16740 "out vec4 fs_out;\n"
16741 "\n"
16742 "void main()\n"
16743 "{\n"
16744 " vec4 result = gs_fs;\n"
16745 "\n"
16746 "VARIABLE_USE"
16747 "\n"
16748 " fs_out += result;\n"
16749 "}\n"
16750 "\n";
16751 static const GLchar* gs = "#version 430 core\n"
16752 "#extension GL_ARB_enhanced_layouts : require\n"
16753 "\n"
16754 "layout(points) in;\n"
16755 "layout(triangle_strip, max_vertices = 4) out;\n"
16756 "\n"
16757 "in vec4 tes_gs[];\n"
16758 "out vec4 gs_fs;\n"
16759 "\n"
16760 "void main()\n"
16761 "{\n"
16762 " gs_fs = tes_gs[0];\n"
16763 " gl_Position = vec4(-1, -1, 0, 1);\n"
16764 " EmitVertex();\n"
16765 " gs_fs = tes_gs[0];\n"
16766 " gl_Position = vec4(-1, 1, 0, 1);\n"
16767 " EmitVertex();\n"
16768 " gs_fs = tes_gs[0];\n"
16769 " gl_Position = vec4(1, -1, 0, 1);\n"
16770 " EmitVertex();\n"
16771 " gs_fs = tes_gs[0];\n"
16772 " gl_Position = vec4(1, 1, 0, 1);\n"
16773 " EmitVertex();\n"
16774 "}\n"
16775 "\n";
16776 static const GLchar* gs_tested = "#version 430 core\n"
16777 "#extension GL_ARB_enhanced_layouts : require\n"
16778 "\n"
16779 "layout(points) in;\n"
16780 "layout(triangle_strip, max_vertices = 4) out;\n"
16781 "\n"
16782 "VAR_DEFINITION"
16783 "\n"
16784 "in vec4 tes_gs[];\n"
16785 "out vec4 gs_fs;\n"
16786 "\n"
16787 "void main()\n"
16788 "{\n"
16789 " vec4 result = tes_gs[0];\n"
16790 "\n"
16791 "VARIABLE_USE"
16792 "\n"
16793 " gs_fs = result;\n"
16794 " gl_Position = vec4(-1, -1, 0, 1);\n"
16795 " EmitVertex();\n"
16796 " gs_fs = result;\n"
16797 " gl_Position = vec4(-1, 1, 0, 1);\n"
16798 " EmitVertex();\n"
16799 " gs_fs = result;\n"
16800 " gl_Position = vec4(1, -1, 0, 1);\n"
16801 " EmitVertex();\n"
16802 " gs_fs = result;\n"
16803 " gl_Position = vec4(1, 1, 0, 1);\n"
16804 " EmitVertex();\n"
16805 "}\n"
16806 "\n";
16807 static const GLchar* tcs = "#version 430 core\n"
16808 "#extension GL_ARB_enhanced_layouts : require\n"
16809 "\n"
16810 "layout(vertices = 1) out;\n"
16811 "\n"
16812 "in vec4 vs_tcs[];\n"
16813 "out vec4 tcs_tes[];\n"
16814 "\n"
16815 "void main()\n"
16816 "{\n"
16817 "\n"
16818 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16819 "\n"
16820 " gl_TessLevelOuter[0] = 1.0;\n"
16821 " gl_TessLevelOuter[1] = 1.0;\n"
16822 " gl_TessLevelOuter[2] = 1.0;\n"
16823 " gl_TessLevelOuter[3] = 1.0;\n"
16824 " gl_TessLevelInner[0] = 1.0;\n"
16825 " gl_TessLevelInner[1] = 1.0;\n"
16826 "}\n"
16827 "\n";
16828 static const GLchar* tcs_tested = "#version 430 core\n"
16829 "#extension GL_ARB_enhanced_layouts : require\n"
16830 "\n"
16831 "layout(vertices = 1) out;\n"
16832 "\n"
16833 "VAR_DEFINITION"
16834 "\n"
16835 "in vec4 vs_tcs[];\n"
16836 "out vec4 tcs_tes[];\n"
16837 "\n"
16838 "void main()\n"
16839 "{\n"
16840 " vec4 result = vs_tcs[gl_InvocationID];\n"
16841 "\n"
16842 "VARIABLE_USE"
16843 "\n"
16844 " tcs_tes[gl_InvocationID] = result;\n"
16845 "\n"
16846 " gl_TessLevelOuter[0] = 1.0;\n"
16847 " gl_TessLevelOuter[1] = 1.0;\n"
16848 " gl_TessLevelOuter[2] = 1.0;\n"
16849 " gl_TessLevelOuter[3] = 1.0;\n"
16850 " gl_TessLevelInner[0] = 1.0;\n"
16851 " gl_TessLevelInner[1] = 1.0;\n"
16852 "}\n"
16853 "\n";
16854 static const GLchar* tes = "#version 430 core\n"
16855 "#extension GL_ARB_enhanced_layouts : require\n"
16856 "\n"
16857 "layout(isolines, point_mode) in;\n"
16858 "\n"
16859 "in vec4 tcs_tes[];\n"
16860 "out vec4 tes_gs;\n"
16861 "\n"
16862 "void main()\n"
16863 "{\n"
16864 " tes_gs = tcs_tes[0];\n"
16865 "}\n"
16866 "\n";
16867 static const GLchar* tes_tested = "#version 430 core\n"
16868 "#extension GL_ARB_enhanced_layouts : require\n"
16869 "\n"
16870 "layout(isolines, point_mode) in;\n"
16871 "\n"
16872 "VAR_DEFINITION"
16873 "\n"
16874 "in vec4 tcs_tes[];\n"
16875 "out vec4 tes_gs;\n"
16876 "\n"
16877 "void main()\n"
16878 "{\n"
16879 " vec4 result = tcs_tes[0];\n"
16880 "\n"
16881 "VARIABLE_USE"
16882 "\n"
16883 " tes_gs += result;\n"
16884 "}\n"
16885 "\n";
16886 static const GLchar* vs = "#version 430 core\n"
16887 "#extension GL_ARB_enhanced_layouts : require\n"
16888 "\n"
16889 "in vec4 in_vs;\n"
16890 "out vec4 vs_tcs;\n"
16891 "\n"
16892 "void main()\n"
16893 "{\n"
16894 " vs_tcs = in_vs;\n"
16895 "}\n"
16896 "\n";
16897 static const GLchar* vs_tested = "#version 430 core\n"
16898 "#extension GL_ARB_enhanced_layouts : require\n"
16899 "\n"
16900 "VAR_DEFINITION"
16901 "\n"
16902 "in vec4 in_vs;\n"
16903 "out vec4 vs_tcs;\n"
16904 "\n"
16905 "void main()\n"
16906 "{\n"
16907 " vec4 result = in_vs;\n"
16908 "\n"
16909 "VARIABLE_USE"
16910 "\n"
16911 " vs_tcs += result;\n"
16912 "}\n"
16913 "\n";
16914
16915 std::string source;
16916 testCase& test_case = m_test_cases[test_case_index];
16917
16918 if (test_case.m_stage == stage)
16919 {
16920 const GLchar* array = "";
16921 GLchar buffer[32];
16922 const GLchar* var_definition = 0;
16923 const GLchar* direction = "in ";
16924 const GLchar* index = "";
16925 size_t position = 0;
16926 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16927 const GLchar* var_use = 0;
16928 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16929 const GLchar* flat = "";
16930
16931 if (false == test_case.m_is_input)
16932 {
16933 direction = "out";
16934 storage = Utils::Variable::VARYING_OUTPUT;
16935
16936 if (false == test_case.m_is_array)
16937 {
16938 switch (test_case.m_case)
16939 {
16940 case BLOCK:
16941 var_definition = block_definition_one;
16942 var_use = member_output_use_one;
16943 break;
16944 case MATRIX:
16945 case DVEC3_DVEC4:
16946 var_definition = matrix_dvec3_dvec4_definition_one;
16947 var_use = matrix_dvec3_dvec4_output_use_one;
16948 break;
16949 case STRUCT:
16950 var_definition = struct_definition_one;
16951 var_use = member_output_use_one;
16952 break;
16953 default:
16954 TCU_FAIL("Invalid enum");
16955 }
16956 }
16957 else
16958 {
16959 switch (test_case.m_case)
16960 {
16961 case BLOCK:
16962 var_definition = block_definition_arr;
16963 var_use = member_output_use_arr;
16964 break;
16965 case MATRIX:
16966 case DVEC3_DVEC4:
16967 var_definition = matrix_dvec3_dvec4_definition_arr;
16968 var_use = matrix_dvec3_dvec4_output_use_arr;
16969 break;
16970 case STRUCT:
16971 var_definition = struct_definition_arr;
16972 var_use = member_output_use_arr;
16973 break;
16974 default:
16975 TCU_FAIL("Invalid enum");
16976 }
16977 }
16978 }
16979 else
16980 {
16981 if (false == test_case.m_is_array)
16982 {
16983 switch (test_case.m_case)
16984 {
16985 case BLOCK:
16986 var_definition = block_definition_one;
16987 var_use = Utils::Shader::VERTEX == stage ? member_input_use_one : "\n";
16988 break;
16989 case MATRIX:
16990 case DVEC3_DVEC4:
16991 var_definition = matrix_dvec3_dvec4_definition_one;
16992 var_use = Utils::Shader::VERTEX == stage ? matrix_dvec3_dvec4_input_use_one : "\n";
16993 break;
16994 case STRUCT:
16995 var_definition = struct_definition_one;
16996 var_use = Utils::Shader::VERTEX == stage ? member_input_use_one : "\n";
16997 break;
16998 default:
16999 TCU_FAIL("Invalid enum");
17000 }
17001 }
17002 else
17003 {
17004 switch (test_case.m_case)
17005 {
17006 case BLOCK:
17007 var_definition = block_definition_arr;
17008 var_use = Utils::Shader::VERTEX == stage ? member_input_use_arr : "\n";
17009 break;
17010 case MATRIX:
17011 case DVEC3_DVEC4:
17012 var_definition = matrix_dvec3_dvec4_definition_arr;
17013 var_use = Utils::Shader::VERTEX == stage ? matrix_dvec3_dvec4_input_use_arr : "\n";
17014 break;
17015 case STRUCT:
17016 var_definition = struct_definition_arr;
17017 var_use = Utils::Shader::VERTEX == stage ? member_input_use_arr : "\n";
17018 break;
17019 default:
17020 TCU_FAIL("Invalid enum");
17021 }
17022 }
17023 }
17024
17025 if (isFlatRequired(stage, test_case.m_type, storage))
17026 {
17027 flat = "flat";
17028 }
17029
17030 #if DEBUG_NEG_REMOVE_ERROR
17031 sprintf(buffer, " /* , component = %d */", test_case.m_component);
17032 #else
17033 sprintf(buffer, ", component = %d", test_case.m_component);
17034 #endif /* DEBUG_NEG_REMOVE_ERROR */
17035
17036 switch (stage)
17037 {
17038 case Utils::Shader::FRAGMENT:
17039 source = fs_tested;
17040 break;
17041 case Utils::Shader::GEOMETRY:
17042 source = gs_tested;
17043 array = test_case.m_is_input ? "[]" : "";
17044 index = test_case.m_is_input ? "[0]" : "";
17045 break;
17046 case Utils::Shader::TESS_CTRL:
17047 source = tcs_tested;
17048 array = "[]";
17049 index = "[gl_InvocationID]";
17050 break;
17051 case Utils::Shader::TESS_EVAL:
17052 source = tes_tested;
17053 array = test_case.m_is_input ? "[]" : "";
17054 index = test_case.m_is_input ? "[0]" : "";
17055 break;
17056 case Utils::Shader::VERTEX:
17057 source = vs_tested;
17058 break;
17059 default:
17060 TCU_FAIL("Invalid enum");
17061 }
17062
17063 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17064 position = 0;
17065 Utils::replaceToken("COMPONENT", position, buffer, source);
17066 Utils::replaceToken("DIRECTION", position, direction, source);
17067 Utils::replaceToken("ARRAY", position, array, source);
17068 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
17069
17070 Utils::replaceAllTokens("FLAT", flat, source);
17071 Utils::replaceAllTokens("TYPE", type_name, source);
17072 Utils::replaceAllTokens("INDEX", index, source);
17073 }
17074 else
17075 {
17076 switch (stage)
17077 {
17078 case Utils::Shader::FRAGMENT:
17079 source = fs;
17080 break;
17081 case Utils::Shader::GEOMETRY:
17082 source = gs;
17083 break;
17084 case Utils::Shader::TESS_CTRL:
17085 source = tcs;
17086 break;
17087 case Utils::Shader::TESS_EVAL:
17088 source = tes;
17089 break;
17090 case Utils::Shader::VERTEX:
17091 source = vs;
17092 break;
17093 default:
17094 TCU_FAIL("Invalid enum");
17095 }
17096 }
17097
17098 return source;
17099 }
17100
17101 /** Get description of test case
17102 *
17103 * @param test_case_index Index of test case
17104 *
17105 * @return Test case description
17106 **/
17107 std::string VaryingComponentOfInvalidTypeTest::getTestCaseName(GLuint test_case_index)
17108 {
17109 std::stringstream stream;
17110 testCase& test_case = m_test_cases[test_case_index];
17111
17112 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17113 << " type: " << test_case.m_type.GetGLSLTypeName();
17114
17115 if (true == test_case.m_is_array)
17116 {
17117 stream << "[1]";
17118 }
17119
17120 stream << ", direction: ";
17121
17122 if (true == test_case.m_is_input)
17123 {
17124 stream << "input";
17125 }
17126 else
17127 {
17128 stream << "output";
17129 }
17130
17131 stream << ", component: " << test_case.m_component;
17132
17133 return stream.str();
17134 }
17135
17136 /** Get number of test cases
17137 *
17138 * @return Number of test cases
17139 **/
17140 GLuint VaryingComponentOfInvalidTypeTest::getTestCaseNumber()
17141 {
17142 return static_cast<GLuint>(m_test_cases.size());
17143 }
17144
17145 /** Selects if "compute" stage is relevant for test
17146 *
17147 * @param ignored
17148 *
17149 * @return false
17150 **/
17151 bool VaryingComponentOfInvalidTypeTest::isComputeRelevant(GLuint /* test_case_index */)
17152 {
17153 return false;
17154 }
17155
17156 /** Prepare all test cases
17157 *
17158 **/
17159 void VaryingComponentOfInvalidTypeTest::testInit()
17160 {
17161 const GLuint n_types = getTypesNumber();
17162
17163 for (GLuint i = 0; i < n_types; ++i)
17164 {
17165 const Utils::Type& type = getType(i);
17166 const std::vector<GLuint>& valid_components = type.GetValidComponents();
17167
17168 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17169 {
17170 if (Utils::Shader::COMPUTE == stage)
17171 {
17172 continue;
17173 }
17174
17175 /* matrices */
17176 if (1 != type.m_n_columns)
17177 {
17178 testCase test_case_in_arr = { MATRIX, 0, true, true, (Utils::Shader::STAGES)stage, type };
17179 testCase test_case_in_one = { MATRIX, 0, false, true, (Utils::Shader::STAGES)stage, type };
17180 testCase test_case_out_arr = { MATRIX, 0, true, false, (Utils::Shader::STAGES)stage, type };
17181 testCase test_case_out_one = { MATRIX, 0, false, false, (Utils::Shader::STAGES)stage, type };
17182
17183 m_test_cases.push_back(test_case_in_arr);
17184 m_test_cases.push_back(test_case_in_one);
17185
17186 if (Utils::Shader::FRAGMENT != stage)
17187 {
17188 m_test_cases.push_back(test_case_out_arr);
17189 m_test_cases.push_back(test_case_out_one);
17190 }
17191 }
17192 else if (Utils::Type::Double == type.m_basic_type && 2 < type.m_n_rows) /* dvec3 and dvec4 */
17193 {
17194 testCase test_case_in_arr = { DVEC3_DVEC4, 0, true, true, (Utils::Shader::STAGES)stage, type };
17195 testCase test_case_in_one = { DVEC3_DVEC4, 0, false, true, (Utils::Shader::STAGES)stage, type };
17196 testCase test_case_out_arr = { DVEC3_DVEC4, 0, true, false, (Utils::Shader::STAGES)stage, type };
17197 testCase test_case_out_one = { DVEC3_DVEC4, 0, false, false, (Utils::Shader::STAGES)stage, type };
17198
17199 m_test_cases.push_back(test_case_in_arr);
17200 m_test_cases.push_back(test_case_in_one);
17201
17202 if (Utils::Shader::FRAGMENT != stage)
17203 {
17204 m_test_cases.push_back(test_case_out_arr);
17205 m_test_cases.push_back(test_case_out_one);
17206 }
17207 }
17208 else
17209 {
17210 if (valid_components.empty())
17211 {
17212 TCU_FAIL("Unhandled type");
17213 }
17214
17215 for (GLuint c = BLOCK; c < MAX_CASES; ++c)
17216 {
17217 testCase test_case_in_arr = { (CASES)c, valid_components.back(), true,
17218 true, (Utils::Shader::STAGES)stage, type };
17219 testCase test_case_in_one = { (CASES)c, valid_components.back(), false,
17220 true, (Utils::Shader::STAGES)stage, type };
17221 testCase test_case_out_arr = { (CASES)c, valid_components.back(), true,
17222 false, (Utils::Shader::STAGES)stage, type };
17223 testCase test_case_out_one = { (CASES)c, valid_components.back(), false,
17224 false, (Utils::Shader::STAGES)stage, type };
17225
17226 if (Utils::Shader::VERTEX != stage)
17227 {
17228 m_test_cases.push_back(test_case_in_arr);
17229 m_test_cases.push_back(test_case_in_one);
17230 }
17231
17232 if (Utils::Shader::FRAGMENT != stage)
17233 {
17234 m_test_cases.push_back(test_case_out_arr);
17235 m_test_cases.push_back(test_case_out_one);
17236 }
17237 }
17238 }
17239 }
17240 }
17241 }
17242
17243 /** Constructor
17244 *
17245 * @param context Test framework context
17246 **/
17247 InputComponentAliasingTest::InputComponentAliasingTest(deqp::Context& context)
17248 : NegativeTestBase(context, "input_component_aliasing",
17249 "Test verifies that compiler reports component aliasing as error")
17250 {
17251 }
17252
17253 /** Source for given test case and stage
17254 *
17255 * @param test_case_index Index of test case
17256 * @param stage Shader stage
17257 *
17258 * @return Shader source
17259 **/
17260 std::string InputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
17261 {
17262 static const GLchar* var_definition =
17263 "layout (location = 1, component = COMPONENT) FLAT in TYPE gohanARRAY;\n"
17264 #if DEBUG_NEG_REMOVE_ERROR
17265 "/* layout (location = 1, component = COMPONENT) */ FLAT in TYPE gotenARRAY;\n";
17266 #else
17267 "layout (location = 1, component = COMPONENT) FLAT in TYPE gotenARRAY;\n";
17268 #endif /* DEBUG_NEG_REMOVE_ERROR */
17269 static const GLchar* test_one = " if (TYPE(0) == gohanINDEX)\n"
17270 " {\n"
17271 " result += vec4(1, 0.5, 0.25, 0.125);\n"
17272 " }\n";
17273 static const GLchar* fs = "#version 430 core\n"
17274 "#extension GL_ARB_enhanced_layouts : require\n"
17275 "\n"
17276 "in vec4 gs_fs;\n"
17277 "out vec4 fs_out;\n"
17278 "\n"
17279 "void main()\n"
17280 "{\n"
17281 " fs_out = gs_fs;\n"
17282 "}\n"
17283 "\n";
17284 static const GLchar* fs_tested = "#version 430 core\n"
17285 "#extension GL_ARB_enhanced_layouts : require\n"
17286 "\n"
17287 "VAR_DEFINITION"
17288 "\n"
17289 "in vec4 gs_fs;\n"
17290 "out vec4 fs_out;\n"
17291 "\n"
17292 "void main()\n"
17293 "{\n"
17294 " vec4 result = gs_fs;\n"
17295 "\n"
17296 "VARIABLE_USE"
17297 "\n"
17298 " fs_out += result;\n"
17299 "}\n"
17300 "\n";
17301 static const GLchar* gs = "#version 430 core\n"
17302 "#extension GL_ARB_enhanced_layouts : require\n"
17303 "\n"
17304 "layout(points) in;\n"
17305 "layout(triangle_strip, max_vertices = 4) out;\n"
17306 "\n"
17307 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17308 "\n"
17309 "in vec4 tes_gs[];\n"
17310 "out vec4 gs_fs;\n"
17311 "\n"
17312 "void main()\n"
17313 "{\n"
17314 " gohan = TYPE(1);\n"
17315 "\n"
17316 " gs_fs = tes_gs[0];\n"
17317 " gl_Position = vec4(-1, -1, 0, 1);\n"
17318 " EmitVertex();\n"
17319 " gs_fs = tes_gs[0];\n"
17320 " gl_Position = vec4(-1, 1, 0, 1);\n"
17321 " EmitVertex();\n"
17322 " gs_fs = tes_gs[0];\n"
17323 " gl_Position = vec4(1, -1, 0, 1);\n"
17324 " EmitVertex();\n"
17325 " gs_fs = tes_gs[0];\n"
17326 " gl_Position = vec4(1, 1, 0, 1);\n"
17327 " EmitVertex();\n"
17328 "}\n"
17329 "\n";
17330 static const GLchar* gs_tested = "#version 430 core\n"
17331 "#extension GL_ARB_enhanced_layouts : require\n"
17332 "\n"
17333 "layout(points) in;\n"
17334 "layout(triangle_strip, max_vertices = 4) out;\n"
17335 "\n"
17336 "VAR_DEFINITION"
17337 "\n"
17338 "in vec4 tes_gs[];\n"
17339 "out vec4 gs_fs;\n"
17340 "\n"
17341 "void main()\n"
17342 "{\n"
17343 " vec4 result = tes_gs[0];\n"
17344 "\n"
17345 "VARIABLE_USE"
17346 "\n"
17347 " gs_fs = result;\n"
17348 " gl_Position = vec4(-1, -1, 0, 1);\n"
17349 " EmitVertex();\n"
17350 " gs_fs = result;\n"
17351 " gl_Position = vec4(-1, 1, 0, 1);\n"
17352 " EmitVertex();\n"
17353 " gs_fs = result;\n"
17354 " gl_Position = vec4(1, -1, 0, 1);\n"
17355 " EmitVertex();\n"
17356 " gs_fs = result;\n"
17357 " gl_Position = vec4(1, 1, 0, 1);\n"
17358 " EmitVertex();\n"
17359 "}\n"
17360 "\n";
17361 static const GLchar* tcs = "#version 430 core\n"
17362 "#extension GL_ARB_enhanced_layouts : require\n"
17363 "\n"
17364 "layout(vertices = 1) out;\n"
17365 "\n"
17366 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan[];\n"
17367 "\n"
17368 "in vec4 vs_tcs[];\n"
17369 "out vec4 tcs_tes[];\n"
17370 "\n"
17371 "void main()\n"
17372 "{\n"
17373 " gohan[gl_InvocationID] = TYPE(1);\n"
17374 "\n"
17375 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17376 "\n"
17377 " gl_TessLevelOuter[0] = 1.0;\n"
17378 " gl_TessLevelOuter[1] = 1.0;\n"
17379 " gl_TessLevelOuter[2] = 1.0;\n"
17380 " gl_TessLevelOuter[3] = 1.0;\n"
17381 " gl_TessLevelInner[0] = 1.0;\n"
17382 " gl_TessLevelInner[1] = 1.0;\n"
17383 "}\n"
17384 "\n";
17385 static const GLchar* tcs_tested = "#version 430 core\n"
17386 "#extension GL_ARB_enhanced_layouts : require\n"
17387 "\n"
17388 "layout(vertices = 1) out;\n"
17389 "\n"
17390 "VAR_DEFINITION"
17391 "\n"
17392 "in vec4 vs_tcs[];\n"
17393 "out vec4 tcs_tes[];\n"
17394 "\n"
17395 "void main()\n"
17396 "{\n"
17397 " vec4 result = vs_tcs[gl_InvocationID];\n"
17398 "\n"
17399 "VARIABLE_USE"
17400 "\n"
17401 " tcs_tes[gl_InvocationID] = result;\n"
17402 "\n"
17403 " gl_TessLevelOuter[0] = 1.0;\n"
17404 " gl_TessLevelOuter[1] = 1.0;\n"
17405 " gl_TessLevelOuter[2] = 1.0;\n"
17406 " gl_TessLevelOuter[3] = 1.0;\n"
17407 " gl_TessLevelInner[0] = 1.0;\n"
17408 " gl_TessLevelInner[1] = 1.0;\n"
17409 "}\n"
17410 "\n";
17411 static const GLchar* tes = "#version 430 core\n"
17412 "#extension GL_ARB_enhanced_layouts : require\n"
17413 "\n"
17414 "layout(isolines, point_mode) in;\n"
17415 "\n"
17416 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17417 "\n"
17418 "in vec4 tcs_tes[];\n"
17419 "out vec4 tes_gs;\n"
17420 "\n"
17421 "void main()\n"
17422 "{\n"
17423 " gohan = TYPE(1);\n"
17424 "\n"
17425 " tes_gs = tcs_tes[0];\n"
17426 "}\n"
17427 "\n";
17428 static const GLchar* tes_tested = "#version 430 core\n"
17429 "#extension GL_ARB_enhanced_layouts : require\n"
17430 "\n"
17431 "layout(isolines, point_mode) in;\n"
17432 "\n"
17433 "VAR_DEFINITION"
17434 "\n"
17435 "in vec4 tcs_tes[];\n"
17436 "out vec4 tes_gs;\n"
17437 "\n"
17438 "void main()\n"
17439 "{\n"
17440 " vec4 result = tcs_tes[0];\n"
17441 "\n"
17442 "VARIABLE_USE"
17443 "\n"
17444 " tes_gs += result;\n"
17445 "}\n"
17446 "\n";
17447 static const GLchar* vs = "#version 430 core\n"
17448 "#extension GL_ARB_enhanced_layouts : require\n"
17449 "\n"
17450 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17451 "\n"
17452 "in vec4 in_vs;\n"
17453 "out vec4 vs_tcs;\n"
17454 "\n"
17455 "void main()\n"
17456 "{\n"
17457 " gohan = TYPE(1);\n"
17458 "\n"
17459 " vs_tcs = in_vs;\n"
17460 "}\n"
17461 "\n";
17462 static const GLchar* vs_tested = "#version 430 core\n"
17463 "#extension GL_ARB_enhanced_layouts : require\n"
17464 "\n"
17465 "VAR_DEFINITION"
17466 "\n"
17467 "in vec4 in_vs;\n"
17468 "out vec4 vs_tcs;\n"
17469 "\n"
17470 "void main()\n"
17471 "{\n"
17472 " vec4 result = in_vs;\n"
17473 "\n"
17474 "VARIABLE_USE"
17475 "\n"
17476 " vs_tcs += result;\n"
17477 "}\n"
17478 "\n";
17479
17480 std::string source;
17481 testCase& test_case = m_test_cases[test_case_index];
17482 GLchar buffer_gohan[16];
17483 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
17484
17485 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17486
17487 if (test_case.m_stage == stage)
17488 {
17489 const GLchar* array = "";
17490 GLchar buffer_goten[16];
17491 const GLchar* flat = "";
17492 const GLchar* index = "";
17493 size_t position = 0;
17494 const GLchar* var_use = test_one;
17495
17496 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_INPUT, true))
17497 {
17498 flat = "flat";
17499 }
17500
17501 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17502
17503 switch (stage)
17504 {
17505 case Utils::Shader::FRAGMENT:
17506 source = fs_tested;
17507 break;
17508 case Utils::Shader::GEOMETRY:
17509 source = gs_tested;
17510 array = "[]";
17511 index = "[0]";
17512 break;
17513 case Utils::Shader::TESS_CTRL:
17514 source = tcs_tested;
17515 array = "[]";
17516 index = "[gl_InvocationID]";
17517 break;
17518 case Utils::Shader::TESS_EVAL:
17519 source = tes_tested;
17520 array = "[]";
17521 index = "[0]";
17522 break;
17523 case Utils::Shader::VERTEX:
17524 source = vs_tested;
17525 break;
17526 default:
17527 TCU_FAIL("Invalid enum");
17528 }
17529
17530 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17531 position = 0;
17532 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17533 Utils::replaceToken("ARRAY", position, array, source);
17534 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17535 Utils::replaceToken("ARRAY", position, array, source);
17536 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
17537
17538 Utils::replaceAllTokens("FLAT", flat, source);
17539 Utils::replaceAllTokens("TYPE", type_name, source);
17540 Utils::replaceAllTokens("INDEX", index, source);
17541 }
17542 else
17543 {
17544 const GLchar* flat = "";
17545
17546 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_OUTPUT, true))
17547 {
17548 flat = "flat";
17549 }
17550
17551 switch (stage)
17552 {
17553 case Utils::Shader::FRAGMENT:
17554 source = fs;
17555 break;
17556 case Utils::Shader::GEOMETRY:
17557 source = gs;
17558 break;
17559 case Utils::Shader::TESS_CTRL:
17560 source = tcs;
17561 break;
17562 case Utils::Shader::TESS_EVAL:
17563 source = tes;
17564 break;
17565 case Utils::Shader::VERTEX:
17566 source = vs;
17567 break;
17568 default:
17569 TCU_FAIL("Invalid enum");
17570 }
17571
17572 Utils::replaceAllTokens("FLAT", flat, source);
17573 Utils::replaceAllTokens("COMPONENT", buffer_gohan, source);
17574 Utils::replaceAllTokens("TYPE", type_name, source);
17575 }
17576
17577 return source;
17578 }
17579
17580 /** Get description of test case
17581 *
17582 * @param test_case_index Index of test case
17583 *
17584 * @return Test case description
17585 **/
17586 std::string InputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
17587 {
17588 std::stringstream stream;
17589 testCase& test_case = m_test_cases[test_case_index];
17590
17591 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17592 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
17593 << " & " << test_case.m_component_goten;
17594
17595 return stream.str();
17596 }
17597
17598 /** Get number of test cases
17599 *
17600 * @return Number of test cases
17601 **/
17602 GLuint InputComponentAliasingTest::getTestCaseNumber()
17603 {
17604 return static_cast<GLuint>(m_test_cases.size());
17605 }
17606
17607 /** Selects if "compute" stage is relevant for test
17608 *
17609 * @param ignored
17610 *
17611 * @return false
17612 **/
17613 bool InputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
17614 {
17615 return false;
17616 }
17617
17618 /** Selects if compilation failure is expected result
17619 *
17620 * @param test_case_index Index of test case
17621 *
17622 * @return false for VS that use only single variable, true otherwise
17623 **/
17624 bool InputComponentAliasingTest::isFailureExpected(GLuint test_case_index)
17625 {
17626 testCase& test_case = m_test_cases[test_case_index];
17627
17628 return (Utils::Shader::VERTEX != test_case.m_stage);
17629 }
17630
17631 /** Prepare all test cases
17632 *
17633 **/
17634 void InputComponentAliasingTest::testInit()
17635 {
17636 const GLuint n_types = getTypesNumber();
17637
17638 for (GLuint i = 0; i < n_types; ++i)
17639 {
17640 const Utils::Type& type = getType(i);
17641 const std::vector<GLuint>& valid_components = type.GetValidComponents();
17642
17643 if (valid_components.empty())
17644 {
17645 continue;
17646 }
17647
17648 for (std::vector<GLuint>::const_iterator it_gohan = valid_components.begin();
17649 it_gohan != valid_components.end(); ++it_gohan)
17650 {
17651 const GLuint max_component = *it_gohan + type.GetNumComponents();
17652 for (std::vector<GLuint>::const_iterator it_goten = it_gohan;
17653 it_goten != valid_components.end() && max_component > *it_goten; ++it_goten)
17654 {
17655 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17656 {
17657 /* Skip compute shader */
17658 if (Utils::Shader::COMPUTE == stage)
17659 {
17660 continue;
17661 }
17662
17663 testCase test_case = { *it_gohan, *it_goten, (Utils::Shader::STAGES)stage, type };
17664
17665 m_test_cases.push_back(test_case);
17666 }
17667 }
17668 }
17669 }
17670 }
17671
17672 /** Constructor
17673 *
17674 * @param context Test framework context
17675 **/
17676 OutputComponentAliasingTest::OutputComponentAliasingTest(deqp::Context& context)
17677 : NegativeTestBase(context, "output_component_aliasing",
17678 "Test verifies that compiler reports component aliasing as error")
17679 {
17680 }
17681
17682 /** Source for given test case and stage
17683 *
17684 * @param test_case_index Index of test case
17685 * @param stage Shader stage
17686 *
17687 * @return Shader source
17688 **/
17689 std::string OutputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
17690 {
17691 static const GLchar* var_definition =
17692 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohanARRAY;\n"
17693 #if DEBUG_NEG_REMOVE_ERROR
17694 "/* layout (location = 1, component = COMPONENT) */ FLAT out TYPE gotenARRAY;\n";
17695 #else
17696 "layout (location = 1, component = COMPONENT) FLAT out TYPE gotenARRAY;\n";
17697 #endif /* DEBUG_NEG_REMOVE_ERROR */
17698 static const GLchar* l_test = " gohanINDEX = TYPE(1);\n"
17699 " gotenINDEX = TYPE(0);\n";
17700 static const GLchar* fs = "#version 430 core\n"
17701 "#extension GL_ARB_enhanced_layouts : require\n"
17702 "\n"
17703 "in vec4 gs_fs;\n"
17704 "out vec4 fs_out;\n"
17705 "\n"
17706 "void main()\n"
17707 "{\n"
17708 " fs_out = gs_fs;\n"
17709 "}\n"
17710 "\n";
17711 static const GLchar* fs_tested = "#version 430 core\n"
17712 "#extension GL_ARB_enhanced_layouts : require\n"
17713 "\n"
17714 "VAR_DEFINITION"
17715 "\n"
17716 "in vec4 gs_fs;\n"
17717 "out vec4 fs_out;\n"
17718 "\n"
17719 "void main()\n"
17720 "{\n"
17721 " vec4 result = gs_fs;\n"
17722 "\n"
17723 "VARIABLE_USE"
17724 "\n"
17725 " fs_out += result;\n"
17726 "}\n"
17727 "\n";
17728 static const GLchar* gs = "#version 430 core\n"
17729 "#extension GL_ARB_enhanced_layouts : require\n"
17730 "\n"
17731 "layout(points) in;\n"
17732 "layout(triangle_strip, max_vertices = 4) out;\n"
17733 "\n"
17734 "in vec4 tes_gs[];\n"
17735 "out vec4 gs_fs;\n"
17736 "\n"
17737 "void main()\n"
17738 "{\n"
17739 " gs_fs = tes_gs[0];\n"
17740 " gl_Position = vec4(-1, -1, 0, 1);\n"
17741 " EmitVertex();\n"
17742 " gs_fs = tes_gs[0];\n"
17743 " gl_Position = vec4(-1, 1, 0, 1);\n"
17744 " EmitVertex();\n"
17745 " gs_fs = tes_gs[0];\n"
17746 " gl_Position = vec4(1, -1, 0, 1);\n"
17747 " EmitVertex();\n"
17748 " gs_fs = tes_gs[0];\n"
17749 " gl_Position = vec4(1, 1, 0, 1);\n"
17750 " EmitVertex();\n"
17751 "}\n"
17752 "\n";
17753 static const GLchar* gs_tested = "#version 430 core\n"
17754 "#extension GL_ARB_enhanced_layouts : require\n"
17755 "\n"
17756 "layout(points) in;\n"
17757 "layout(triangle_strip, max_vertices = 4) out;\n"
17758 "\n"
17759 "VAR_DEFINITION"
17760 "\n"
17761 "in vec4 tes_gs[];\n"
17762 "out vec4 gs_fs;\n"
17763 "\n"
17764 "void main()\n"
17765 "{\n"
17766 " vec4 result = tes_gs[0];\n"
17767 "\n"
17768 "VARIABLE_USE"
17769 "\n"
17770 " gs_fs = result;\n"
17771 " gl_Position = vec4(-1, -1, 0, 1);\n"
17772 " EmitVertex();\n"
17773 " gs_fs = result;\n"
17774 " gl_Position = vec4(-1, 1, 0, 1);\n"
17775 " EmitVertex();\n"
17776 " gs_fs = result;\n"
17777 " gl_Position = vec4(1, -1, 0, 1);\n"
17778 " EmitVertex();\n"
17779 " gs_fs = result;\n"
17780 " gl_Position = vec4(1, 1, 0, 1);\n"
17781 " EmitVertex();\n"
17782 "}\n"
17783 "\n";
17784 static const GLchar* tcs = "#version 430 core\n"
17785 "#extension GL_ARB_enhanced_layouts : require\n"
17786 "\n"
17787 "layout(vertices = 1) out;\n"
17788 "\n"
17789 "in vec4 vs_tcs[];\n"
17790 "out vec4 tcs_tes[];\n"
17791 "\n"
17792 "void main()\n"
17793 "{\n"
17794 "\n"
17795 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17796 "\n"
17797 " gl_TessLevelOuter[0] = 1.0;\n"
17798 " gl_TessLevelOuter[1] = 1.0;\n"
17799 " gl_TessLevelOuter[2] = 1.0;\n"
17800 " gl_TessLevelOuter[3] = 1.0;\n"
17801 " gl_TessLevelInner[0] = 1.0;\n"
17802 " gl_TessLevelInner[1] = 1.0;\n"
17803 "}\n"
17804 "\n";
17805 static const GLchar* tcs_tested = "#version 430 core\n"
17806 "#extension GL_ARB_enhanced_layouts : require\n"
17807 "\n"
17808 "layout(vertices = 1) out;\n"
17809 "\n"
17810 "VAR_DEFINITION"
17811 "\n"
17812 "in vec4 vs_tcs[];\n"
17813 "out vec4 tcs_tes[];\n"
17814 "\n"
17815 "void main()\n"
17816 "{\n"
17817 " vec4 result = vs_tcs[gl_InvocationID];\n"
17818 "\n"
17819 "VARIABLE_USE"
17820 "\n"
17821 " tcs_tes[gl_InvocationID] = result;\n"
17822 "\n"
17823 " gl_TessLevelOuter[0] = 1.0;\n"
17824 " gl_TessLevelOuter[1] = 1.0;\n"
17825 " gl_TessLevelOuter[2] = 1.0;\n"
17826 " gl_TessLevelOuter[3] = 1.0;\n"
17827 " gl_TessLevelInner[0] = 1.0;\n"
17828 " gl_TessLevelInner[1] = 1.0;\n"
17829 "}\n"
17830 "\n";
17831 static const GLchar* tes = "#version 430 core\n"
17832 "#extension GL_ARB_enhanced_layouts : require\n"
17833 "\n"
17834 "layout(isolines, point_mode) in;\n"
17835 "\n"
17836 "in vec4 tcs_tes[];\n"
17837 "out vec4 tes_gs;\n"
17838 "\n"
17839 "void main()\n"
17840 "{\n"
17841 " tes_gs = tcs_tes[0];\n"
17842 "}\n"
17843 "\n";
17844 static const GLchar* tes_tested = "#version 430 core\n"
17845 "#extension GL_ARB_enhanced_layouts : require\n"
17846 "\n"
17847 "layout(isolines, point_mode) in;\n"
17848 "\n"
17849 "VAR_DEFINITION"
17850 "\n"
17851 "in vec4 tcs_tes[];\n"
17852 "out vec4 tes_gs;\n"
17853 "\n"
17854 "void main()\n"
17855 "{\n"
17856 " vec4 result = tcs_tes[0];\n"
17857 "\n"
17858 "VARIABLE_USE"
17859 "\n"
17860 " tes_gs += result;\n"
17861 "}\n"
17862 "\n";
17863 static const GLchar* vs = "#version 430 core\n"
17864 "#extension GL_ARB_enhanced_layouts : require\n"
17865 "\n"
17866 "in vec4 in_vs;\n"
17867 "out vec4 vs_tcs;\n"
17868 "\n"
17869 "void main()\n"
17870 "{\n"
17871 " vs_tcs = in_vs;\n"
17872 "}\n"
17873 "\n";
17874 static const GLchar* vs_tested = "#version 430 core\n"
17875 "#extension GL_ARB_enhanced_layouts : require\n"
17876 "\n"
17877 "VAR_DEFINITION"
17878 "\n"
17879 "in vec4 in_vs;\n"
17880 "out vec4 vs_tcs;\n"
17881 "\n"
17882 "void main()\n"
17883 "{\n"
17884 " vec4 result = in_vs;\n"
17885 "\n"
17886 "VARIABLE_USE"
17887 "\n"
17888 " vs_tcs += result;\n"
17889 "}\n"
17890 "\n";
17891
17892 std::string source;
17893 testCase& test_case = m_test_cases[test_case_index];
17894
17895 if (test_case.m_stage == stage)
17896 {
17897 const GLchar* array = "";
17898 GLchar buffer_gohan[16];
17899 GLchar buffer_goten[16];
17900 const GLchar* flat = "";
17901 const GLchar* index = "";
17902 size_t position = 0;
17903 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
17904
17905 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_OUTPUT))
17906 {
17907 flat = "flat";
17908 }
17909
17910 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17911 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17912
17913 switch (stage)
17914 {
17915 case Utils::Shader::FRAGMENT:
17916 source = fs_tested;
17917 break;
17918 case Utils::Shader::GEOMETRY:
17919 source = gs_tested;
17920 break;
17921 case Utils::Shader::TESS_CTRL:
17922 source = tcs_tested;
17923 array = "[]";
17924 index = "[gl_InvocationID]";
17925 break;
17926 case Utils::Shader::TESS_EVAL:
17927 source = tes_tested;
17928 break;
17929 case Utils::Shader::VERTEX:
17930 source = vs_tested;
17931 break;
17932 default:
17933 TCU_FAIL("Invalid enum");
17934 }
17935
17936 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17937 position = 0;
17938 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17939 Utils::replaceToken("FLAT", position, flat, source);
17940 Utils::replaceToken("ARRAY", position, array, source);
17941 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17942 Utils::replaceToken("FLAT", position, flat, source);
17943 Utils::replaceToken("ARRAY", position, array, source);
17944 Utils::replaceToken("VARIABLE_USE", position, l_test, source);
17945
17946 Utils::replaceAllTokens("TYPE", type_name, source);
17947 Utils::replaceAllTokens("INDEX", index, source);
17948 }
17949 else
17950 {
17951 switch (stage)
17952 {
17953 case Utils::Shader::FRAGMENT:
17954 source = fs;
17955 break;
17956 case Utils::Shader::GEOMETRY:
17957 source = gs;
17958 break;
17959 case Utils::Shader::TESS_CTRL:
17960 source = tcs;
17961 break;
17962 case Utils::Shader::TESS_EVAL:
17963 source = tes;
17964 break;
17965 case Utils::Shader::VERTEX:
17966 source = vs;
17967 break;
17968 default:
17969 TCU_FAIL("Invalid enum");
17970 }
17971 }
17972
17973 return source;
17974 }
17975
17976 /** Get description of test case
17977 *
17978 * @param test_case_index Index of test case
17979 *
17980 * @return Test case description
17981 **/
17982 std::string OutputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
17983 {
17984 std::stringstream stream;
17985 testCase& test_case = m_test_cases[test_case_index];
17986
17987 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17988 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
17989 << " & " << test_case.m_component_goten;
17990
17991 return stream.str();
17992 }
17993
17994 /** Get number of test cases
17995 *
17996 * @return Number of test cases
17997 **/
17998 GLuint OutputComponentAliasingTest::getTestCaseNumber()
17999 {
18000 return static_cast<GLuint>(m_test_cases.size());
18001 }
18002
18003 /** Selects if "compute" stage is relevant for test
18004 *
18005 * @param ignored
18006 *
18007 * @return false
18008 **/
18009 bool OutputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
18010 {
18011 return false;
18012 }
18013
18014 /** Prepare all test cases
18015 *
18016 **/
18017 void OutputComponentAliasingTest::testInit()
18018 {
18019 const GLuint n_types = getTypesNumber();
18020
18021 for (GLuint i = 0; i < n_types; ++i)
18022 {
18023 const Utils::Type& type = getType(i);
18024 const std::vector<GLuint>& valid_components = type.GetValidComponents();
18025
18026 if (valid_components.empty())
18027 {
18028 continue;
18029 }
18030
18031 for (std::vector<GLuint>::const_iterator it_gohan = valid_components.begin();
18032 it_gohan != valid_components.end(); ++it_gohan)
18033 {
18034 const GLuint max_component = *it_gohan + type.GetNumComponents();
18035 for (std::vector<GLuint>::const_iterator it_goten = it_gohan;
18036 it_goten != valid_components.end() && max_component > *it_goten; ++it_goten)
18037 {
18038 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18039 {
18040 /* Skip compute shader */
18041 if (Utils::Shader::COMPUTE == stage)
18042 {
18043 continue;
18044 }
18045
18046 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Type::Double == type.m_basic_type))
18047 {
18048 continue;
18049 }
18050
18051 testCase test_case = { *it_gohan, *it_goten, (Utils::Shader::STAGES)stage, type };
18052
18053 m_test_cases.push_back(test_case);
18054 }
18055 }
18056 }
18057 }
18058 }
18059
18060 /** Constructor
18061 *
18062 * @param context Test framework context
18063 **/
18064 VaryingLocationAliasingWithMixedTypesTest::VaryingLocationAliasingWithMixedTypesTest(deqp::Context& context)
18065 : NegativeTestBase(context, "varying_location_aliasing_with_mixed_types",
18066 "Test verifies that compiler reports error when float/int types are mixed at one location")
18067 {
18068 }
18069
18070 /** Source for given test case and stage
18071 *
18072 * @param test_case_index Index of test case
18073 * @param stage Shader stage
18074 *
18075 * @return Shader source
18076 **/
18077 std::string VaryingLocationAliasingWithMixedTypesTest::getShaderSource(GLuint test_case_index,
18078 Utils::Shader::STAGES stage)
18079 {
18080 static const GLchar* var_definition =
18081 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gohanARRAY;\n"
18082 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gotenARRAY;\n";
18083 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
18084 " (TYPE(1) == gotenINDEX) )\n"
18085 " {\n"
18086 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18087 " }\n";
18088 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
18089 " gotenINDEX = TYPE(1);\n"
18090 " if (vec4(0) == result)\n"
18091 " {\n"
18092 " gohanINDEX = TYPE(1);\n"
18093 " gotenINDEX = TYPE(0);\n"
18094 " }\n";
18095 static const GLchar* fs = "#version 430 core\n"
18096 "#extension GL_ARB_enhanced_layouts : require\n"
18097 "\n"
18098 "in vec4 gs_fs;\n"
18099 "out vec4 fs_out;\n"
18100 "\n"
18101 "void main()\n"
18102 "{\n"
18103 " fs_out = gs_fs;\n"
18104 "}\n"
18105 "\n";
18106 static const GLchar* fs_tested = "#version 430 core\n"
18107 "#extension GL_ARB_enhanced_layouts : require\n"
18108 "\n"
18109 "VAR_DEFINITION"
18110 "\n"
18111 "in vec4 gs_fs;\n"
18112 "out vec4 fs_out;\n"
18113 "\n"
18114 "void main()\n"
18115 "{\n"
18116 " vec4 result = gs_fs;\n"
18117 "\n"
18118 "VARIABLE_USE"
18119 "\n"
18120 " fs_out += result;\n"
18121 "}\n"
18122 "\n";
18123 static const GLchar* gs = "#version 430 core\n"
18124 "#extension GL_ARB_enhanced_layouts : require\n"
18125 "\n"
18126 "layout(points) in;\n"
18127 "layout(triangle_strip, max_vertices = 4) out;\n"
18128 "\n"
18129 "in vec4 tes_gs[];\n"
18130 "out vec4 gs_fs;\n"
18131 "\n"
18132 "void main()\n"
18133 "{\n"
18134 " gs_fs = tes_gs[0];\n"
18135 " gl_Position = vec4(-1, -1, 0, 1);\n"
18136 " EmitVertex();\n"
18137 " gs_fs = tes_gs[0];\n"
18138 " gl_Position = vec4(-1, 1, 0, 1);\n"
18139 " EmitVertex();\n"
18140 " gs_fs = tes_gs[0];\n"
18141 " gl_Position = vec4(1, -1, 0, 1);\n"
18142 " EmitVertex();\n"
18143 " gs_fs = tes_gs[0];\n"
18144 " gl_Position = vec4(1, 1, 0, 1);\n"
18145 " EmitVertex();\n"
18146 "}\n"
18147 "\n";
18148 static const GLchar* gs_tested = "#version 430 core\n"
18149 "#extension GL_ARB_enhanced_layouts : require\n"
18150 "\n"
18151 "layout(points) in;\n"
18152 "layout(triangle_strip, max_vertices = 4) out;\n"
18153 "\n"
18154 "VAR_DEFINITION"
18155 "\n"
18156 "in vec4 tes_gs[];\n"
18157 "out vec4 gs_fs;\n"
18158 "\n"
18159 "void main()\n"
18160 "{\n"
18161 " vec4 result = tes_gs[0];\n"
18162 "\n"
18163 "VARIABLE_USE"
18164 "\n"
18165 " gs_fs = result;\n"
18166 " gl_Position = vec4(-1, -1, 0, 1);\n"
18167 " EmitVertex();\n"
18168 " gs_fs = result;\n"
18169 " gl_Position = vec4(-1, 1, 0, 1);\n"
18170 " EmitVertex();\n"
18171 " gs_fs = result;\n"
18172 " gl_Position = vec4(1, -1, 0, 1);\n"
18173 " EmitVertex();\n"
18174 " gs_fs = result;\n"
18175 " gl_Position = vec4(1, 1, 0, 1);\n"
18176 " EmitVertex();\n"
18177 "}\n"
18178 "\n";
18179 static const GLchar* tcs = "#version 430 core\n"
18180 "#extension GL_ARB_enhanced_layouts : require\n"
18181 "\n"
18182 "layout(vertices = 1) out;\n"
18183 "\n"
18184 "in vec4 vs_tcs[];\n"
18185 "out vec4 tcs_tes[];\n"
18186 "\n"
18187 "void main()\n"
18188 "{\n"
18189 "\n"
18190 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18191 "\n"
18192 " gl_TessLevelOuter[0] = 1.0;\n"
18193 " gl_TessLevelOuter[1] = 1.0;\n"
18194 " gl_TessLevelOuter[2] = 1.0;\n"
18195 " gl_TessLevelOuter[3] = 1.0;\n"
18196 " gl_TessLevelInner[0] = 1.0;\n"
18197 " gl_TessLevelInner[1] = 1.0;\n"
18198 "}\n"
18199 "\n";
18200 static const GLchar* tcs_tested = "#version 430 core\n"
18201 "#extension GL_ARB_enhanced_layouts : require\n"
18202 "\n"
18203 "layout(vertices = 1) out;\n"
18204 "\n"
18205 "VAR_DEFINITION"
18206 "\n"
18207 "in vec4 vs_tcs[];\n"
18208 "out vec4 tcs_tes[];\n"
18209 "\n"
18210 "void main()\n"
18211 "{\n"
18212 " vec4 result = vs_tcs[gl_InvocationID];\n"
18213 "\n"
18214 "VARIABLE_USE"
18215 "\n"
18216 " tcs_tes[gl_InvocationID] = result;\n"
18217 "\n"
18218 " gl_TessLevelOuter[0] = 1.0;\n"
18219 " gl_TessLevelOuter[1] = 1.0;\n"
18220 " gl_TessLevelOuter[2] = 1.0;\n"
18221 " gl_TessLevelOuter[3] = 1.0;\n"
18222 " gl_TessLevelInner[0] = 1.0;\n"
18223 " gl_TessLevelInner[1] = 1.0;\n"
18224 "}\n"
18225 "\n";
18226 static const GLchar* tes = "#version 430 core\n"
18227 "#extension GL_ARB_enhanced_layouts : require\n"
18228 "\n"
18229 "layout(isolines, point_mode) in;\n"
18230 "\n"
18231 "in vec4 tcs_tes[];\n"
18232 "out vec4 tes_gs;\n"
18233 "\n"
18234 "void main()\n"
18235 "{\n"
18236 " tes_gs = tcs_tes[0];\n"
18237 "}\n"
18238 "\n";
18239 static const GLchar* tes_tested = "#version 430 core\n"
18240 "#extension GL_ARB_enhanced_layouts : require\n"
18241 "\n"
18242 "layout(isolines, point_mode) in;\n"
18243 "\n"
18244 "VAR_DEFINITION"
18245 "\n"
18246 "in vec4 tcs_tes[];\n"
18247 "out vec4 tes_gs;\n"
18248 "\n"
18249 "void main()\n"
18250 "{\n"
18251 " vec4 result = tcs_tes[0];\n"
18252 "\n"
18253 "VARIABLE_USE"
18254 "\n"
18255 " tes_gs += result;\n"
18256 "}\n"
18257 "\n";
18258 static const GLchar* vs = "#version 430 core\n"
18259 "#extension GL_ARB_enhanced_layouts : require\n"
18260 "\n"
18261 "in vec4 in_vs;\n"
18262 "out vec4 vs_tcs;\n"
18263 "\n"
18264 "void main()\n"
18265 "{\n"
18266 " vs_tcs = in_vs;\n"
18267 "}\n"
18268 "\n";
18269 static const GLchar* vs_tested = "#version 430 core\n"
18270 "#extension GL_ARB_enhanced_layouts : require\n"
18271 "\n"
18272 "VAR_DEFINITION"
18273 "\n"
18274 "in vec4 in_vs;\n"
18275 "out vec4 vs_tcs;\n"
18276 "\n"
18277 "void main()\n"
18278 "{\n"
18279 " vec4 result = in_vs;\n"
18280 "\n"
18281 "VARIABLE_USE"
18282 "\n"
18283 " vs_tcs += result;\n"
18284 "}\n"
18285 "\n";
18286
18287 std::string source;
18288 testCase& test_case = m_test_cases[test_case_index];
18289
18290 if (test_case.m_stage == stage)
18291 {
18292 const GLchar* array = "";
18293 GLchar buffer_gohan[16];
18294 GLchar buffer_goten[16];
18295 const GLchar* direction = "in ";
18296 const GLchar* flat_gohan = "";
18297 const GLchar* flat_goten = "";
18298 const GLchar* index = "";
18299 size_t position = 0;
18300 size_t temp;
18301 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18302 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18303 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
18304 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
18305
18306 if (false == test_case.m_is_input)
18307 {
18308 direction = "out";
18309 storage = Utils::Variable::VARYING_OUTPUT;
18310 var_use = output_use;
18311 }
18312
18313 /* If the interpolation qualifier would be different, the test
18314 * would fail and we are testing here mixed types, not mixed
18315 * interpolation qualifiers.
18316 */
18317 if (isFlatRequired(stage, test_case.m_type_gohan, storage) ||
18318 isFlatRequired(stage, test_case.m_type_goten, storage))
18319 {
18320 flat_gohan = "flat";
18321 flat_goten = "flat";
18322 }
18323
18324 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18325 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18326
18327 #if DEBUG_NEG_REMOVE_ERROR
18328 type_goten_name = Utils::Type::GetType(test_case.m_type_gohan.m_basic_type, 1, 1).GetGLSLTypeName();
18329 if (Utils::Type::Double == test_case.m_type_gohan.m_basic_type)
18330 {
18331 sprintf(buffer_goten, "%d", 0 == test_case.m_component_gohan ? 2 : 0);
18332 }
18333 #endif /* DEBUG_NEG_REMOVE_ERROR */
18334
18335 switch (stage)
18336 {
18337 case Utils::Shader::FRAGMENT:
18338 source = fs_tested;
18339 break;
18340 case Utils::Shader::GEOMETRY:
18341 source = gs_tested;
18342 array = test_case.m_is_input ? "[]" : "";
18343 index = test_case.m_is_input ? "[0]" : "";
18344 break;
18345 case Utils::Shader::TESS_CTRL:
18346 source = tcs_tested;
18347 array = "[]";
18348 index = "[gl_InvocationID]";
18349 break;
18350 case Utils::Shader::TESS_EVAL:
18351 source = tes_tested;
18352 array = test_case.m_is_input ? "[]" : "";
18353 index = test_case.m_is_input ? "[0]" : "";
18354 break;
18355 case Utils::Shader::VERTEX:
18356 source = vs_tested;
18357 break;
18358 default:
18359 TCU_FAIL("Invalid enum");
18360 }
18361
18362 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18363 position = 0;
18364 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18365 Utils::replaceToken("FLAT", position, flat_gohan, source);
18366 Utils::replaceToken("DIRECTION", position, direction, source);
18367 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18368 Utils::replaceToken("ARRAY", position, array, source);
18369 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18370 Utils::replaceToken("FLAT", position, flat_goten, source);
18371 Utils::replaceToken("DIRECTION", position, direction, source);
18372 Utils::replaceToken("TYPE", position, type_goten_name, source);
18373 Utils::replaceToken("ARRAY", position, array, source);
18374
18375 temp = position;
18376 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18377 position = temp;
18378 if (!test_case.m_is_input)
18379 {
18380 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18381 Utils::replaceToken("TYPE", position, type_goten_name, source);
18382 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18383 Utils::replaceToken("TYPE", position, type_goten_name, source);
18384 }
18385 else if (Utils::Shader::VERTEX == stage)
18386 {
18387 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18388 Utils::replaceToken("TYPE", position, type_goten_name, source);
18389 }
18390
18391 Utils::replaceAllTokens("INDEX", index, source);
18392 }
18393 else
18394 {
18395 switch (stage)
18396 {
18397 case Utils::Shader::FRAGMENT:
18398 source = fs;
18399 break;
18400 case Utils::Shader::GEOMETRY:
18401 source = gs;
18402 break;
18403 case Utils::Shader::TESS_CTRL:
18404 source = tcs;
18405 break;
18406 case Utils::Shader::TESS_EVAL:
18407 source = tes;
18408 break;
18409 case Utils::Shader::VERTEX:
18410 source = vs;
18411 break;
18412 default:
18413 TCU_FAIL("Invalid enum");
18414 }
18415 }
18416
18417 return source;
18418 }
18419
18420 /** Get description of test case
18421 *
18422 * @param test_case_index Index of test case
18423 *
18424 * @return Test case description
18425 **/
18426 std::string VaryingLocationAliasingWithMixedTypesTest::getTestCaseName(GLuint test_case_index)
18427 {
18428 std::stringstream stream;
18429 testCase& test_case = m_test_cases[test_case_index];
18430
18431 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18432 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
18433 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18434
18435 if (true == test_case.m_is_input)
18436 {
18437 stream << "input";
18438 }
18439 else
18440 {
18441 stream << "output";
18442 }
18443
18444 return stream.str();
18445 }
18446
18447 /** Get number of test cases
18448 *
18449 * @return Number of test cases
18450 **/
18451 GLuint VaryingLocationAliasingWithMixedTypesTest::getTestCaseNumber()
18452 {
18453 return static_cast<GLuint>(m_test_cases.size());
18454 }
18455
18456 /** Selects if "compute" stage is relevant for test
18457 *
18458 * @param ignored
18459 *
18460 * @return false
18461 **/
18462 bool VaryingLocationAliasingWithMixedTypesTest::isComputeRelevant(GLuint /* test_case_index */)
18463 {
18464 return false;
18465 }
18466
18467 /** Prepare all test cases
18468 *
18469 **/
18470 void VaryingLocationAliasingWithMixedTypesTest::testInit()
18471 {
18472 const GLuint n_types = getTypesNumber();
18473
18474 for (GLuint i = 0; i < n_types; ++i)
18475 {
18476 const Utils::Type& type_gohan = getType(i);
18477 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
18478
18479 if (valid_components_gohan.empty())
18480 {
18481 continue;
18482 }
18483
18484 for (GLuint j = 0; j < n_types; ++j)
18485 {
18486 const Utils::Type& type_goten = getType(j);
18487 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
18488
18489 if (valid_components_goten.empty())
18490 {
18491 continue;
18492 }
18493
18494 /* Skip valid combinations */
18495 if (Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
18496 {
18497 continue;
18498 }
18499
18500 for (std::vector<GLuint>::const_iterator it_gohan = valid_components_gohan.begin();
18501 it_gohan != valid_components_gohan.end(); ++it_gohan)
18502 {
18503 const GLuint min_component = *it_gohan + type_gohan.GetNumComponents();
18504 for (std::vector<GLuint>::const_iterator it_goten = valid_components_goten.begin();
18505 it_goten != valid_components_goten.end(); ++it_goten)
18506 {
18507
18508 if (min_component > *it_goten)
18509 {
18510 continue;
18511 }
18512
18513 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18514 {
18515 /* Skip compute shader */
18516 if (Utils::Shader::COMPUTE == stage)
18517 {
18518 continue;
18519 }
18520
18521 if (Utils::Shader::VERTEX != stage)
18522 {
18523 testCase test_case_in = { *it_gohan, *it_goten, true, (Utils::Shader::STAGES)stage,
18524 type_gohan, type_goten };
18525
18526 m_test_cases.push_back(test_case_in);
18527 }
18528
18529 /* Skip double outputs in fragment shader */
18530 if ((Utils::Shader::FRAGMENT != stage) || ((Utils::Type::Double != type_gohan.m_basic_type) &&
18531 (Utils::Type::Double != type_goten.m_basic_type)))
18532 {
18533 testCase test_case_out = { *it_gohan, *it_goten, false, (Utils::Shader::STAGES)stage,
18534 type_gohan, type_goten };
18535
18536 m_test_cases.push_back(test_case_out);
18537 }
18538 }
18539 }
18540 }
18541 }
18542 }
18543 }
18544
18545 /** Constructor
18546 *
18547 * @param context Test framework context
18548 **/
18549 VaryingLocationAliasingWithMixedInterpolationTest::VaryingLocationAliasingWithMixedInterpolationTest(
18550 deqp::Context& context)
18551 : NegativeTestBase(
18552 context, "varying_location_aliasing_with_mixed_interpolation",
18553 "Test verifies that compiler reports error when interpolation qualifiers are mixed at one location")
18554 {
18555 }
18556
18557 /** Source for given test case and stage
18558 *
18559 * @param test_case_index Index of test case
18560 * @param stage Shader stage
18561 *
18562 * @return Shader source
18563 **/
18564 std::string VaryingLocationAliasingWithMixedInterpolationTest::getShaderSource(GLuint test_case_index,
18565 Utils::Shader::STAGES stage)
18566 {
18567 static const GLchar* var_definition =
18568 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
18569 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
18570 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
18571 " (TYPE(1) == gotenINDEX) )\n"
18572 " {\n"
18573 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18574 " }\n";
18575 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
18576 " gotenINDEX = TYPE(1);\n"
18577 " if (vec4(0) == result)\n"
18578 " {\n"
18579 " gohanINDEX = TYPE(1);\n"
18580 " gotenINDEX = TYPE(0);\n"
18581 " }\n";
18582 static const GLchar* fs = "#version 430 core\n"
18583 "#extension GL_ARB_enhanced_layouts : require\n"
18584 "\n"
18585 "in vec4 gs_fs;\n"
18586 "out vec4 fs_out;\n"
18587 "\n"
18588 "void main()\n"
18589 "{\n"
18590 " fs_out = gs_fs;\n"
18591 "}\n"
18592 "\n";
18593 static const GLchar* fs_tested = "#version 430 core\n"
18594 "#extension GL_ARB_enhanced_layouts : require\n"
18595 "\n"
18596 "VAR_DEFINITION"
18597 "\n"
18598 "in vec4 gs_fs;\n"
18599 "out vec4 fs_out;\n"
18600 "\n"
18601 "void main()\n"
18602 "{\n"
18603 " vec4 result = gs_fs;\n"
18604 "\n"
18605 "VARIABLE_USE"
18606 "\n"
18607 " fs_out = result;\n"
18608 "}\n"
18609 "\n";
18610 static const GLchar* gs = "#version 430 core\n"
18611 "#extension GL_ARB_enhanced_layouts : require\n"
18612 "\n"
18613 "layout(points) in;\n"
18614 "layout(triangle_strip, max_vertices = 4) out;\n"
18615 "\n"
18616 "in vec4 tes_gs[];\n"
18617 "out vec4 gs_fs;\n"
18618 "\n"
18619 "void main()\n"
18620 "{\n"
18621 " gs_fs = tes_gs[0];\n"
18622 " gl_Position = vec4(-1, -1, 0, 1);\n"
18623 " EmitVertex();\n"
18624 " gs_fs = tes_gs[0];\n"
18625 " gl_Position = vec4(-1, 1, 0, 1);\n"
18626 " EmitVertex();\n"
18627 " gs_fs = tes_gs[0];\n"
18628 " gl_Position = vec4(1, -1, 0, 1);\n"
18629 " EmitVertex();\n"
18630 " gs_fs = tes_gs[0];\n"
18631 " gl_Position = vec4(1, 1, 0, 1);\n"
18632 " EmitVertex();\n"
18633 "}\n"
18634 "\n";
18635 static const GLchar* gs_tested = "#version 430 core\n"
18636 "#extension GL_ARB_enhanced_layouts : require\n"
18637 "\n"
18638 "layout(points) in;\n"
18639 "layout(triangle_strip, max_vertices = 4) out;\n"
18640 "\n"
18641 "VAR_DEFINITION"
18642 "\n"
18643 "in vec4 tes_gs[];\n"
18644 "out vec4 gs_fs;\n"
18645 "\n"
18646 "void main()\n"
18647 "{\n"
18648 " vec4 result = tes_gs[0];\n"
18649 "\n"
18650 "VARIABLE_USE"
18651 "\n"
18652 " gs_fs = result;\n"
18653 " gl_Position = vec4(-1, -1, 0, 1);\n"
18654 " EmitVertex();\n"
18655 " gs_fs = result;\n"
18656 " gl_Position = vec4(-1, 1, 0, 1);\n"
18657 " EmitVertex();\n"
18658 " gs_fs = result;\n"
18659 " gl_Position = vec4(1, -1, 0, 1);\n"
18660 " EmitVertex();\n"
18661 " gs_fs = result;\n"
18662 " gl_Position = vec4(1, 1, 0, 1);\n"
18663 " EmitVertex();\n"
18664 "}\n"
18665 "\n";
18666 static const GLchar* tcs = "#version 430 core\n"
18667 "#extension GL_ARB_enhanced_layouts : require\n"
18668 "\n"
18669 "layout(vertices = 1) out;\n"
18670 "\n"
18671 "in vec4 vs_tcs[];\n"
18672 "out vec4 tcs_tes[];\n"
18673 "\n"
18674 "void main()\n"
18675 "{\n"
18676 "\n"
18677 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18678 "\n"
18679 " gl_TessLevelOuter[0] = 1.0;\n"
18680 " gl_TessLevelOuter[1] = 1.0;\n"
18681 " gl_TessLevelOuter[2] = 1.0;\n"
18682 " gl_TessLevelOuter[3] = 1.0;\n"
18683 " gl_TessLevelInner[0] = 1.0;\n"
18684 " gl_TessLevelInner[1] = 1.0;\n"
18685 "}\n"
18686 "\n";
18687 static const GLchar* tcs_tested = "#version 430 core\n"
18688 "#extension GL_ARB_enhanced_layouts : require\n"
18689 "\n"
18690 "layout(vertices = 1) out;\n"
18691 "\n"
18692 "VAR_DEFINITION"
18693 "\n"
18694 "in vec4 vs_tcs[];\n"
18695 "out vec4 tcs_tes[];\n"
18696 "\n"
18697 "void main()\n"
18698 "{\n"
18699 " vec4 result = vs_tcs[gl_InvocationID];\n"
18700 "\n"
18701 "VARIABLE_USE"
18702 "\n"
18703 " tcs_tes[gl_InvocationID] = result;\n"
18704 "\n"
18705 " gl_TessLevelOuter[0] = 1.0;\n"
18706 " gl_TessLevelOuter[1] = 1.0;\n"
18707 " gl_TessLevelOuter[2] = 1.0;\n"
18708 " gl_TessLevelOuter[3] = 1.0;\n"
18709 " gl_TessLevelInner[0] = 1.0;\n"
18710 " gl_TessLevelInner[1] = 1.0;\n"
18711 "}\n"
18712 "\n";
18713 static const GLchar* tes = "#version 430 core\n"
18714 "#extension GL_ARB_enhanced_layouts : require\n"
18715 "\n"
18716 "layout(isolines, point_mode) in;\n"
18717 "\n"
18718 "in vec4 tcs_tes[];\n"
18719 "out vec4 tes_gs;\n"
18720 "\n"
18721 "void main()\n"
18722 "{\n"
18723 " tes_gs = tcs_tes[0];\n"
18724 "}\n"
18725 "\n";
18726 static const GLchar* tes_tested = "#version 430 core\n"
18727 "#extension GL_ARB_enhanced_layouts : require\n"
18728 "\n"
18729 "layout(isolines, point_mode) in;\n"
18730 "\n"
18731 "VAR_DEFINITION"
18732 "\n"
18733 "in vec4 tcs_tes[];\n"
18734 "out vec4 tes_gs;\n"
18735 "\n"
18736 "void main()\n"
18737 "{\n"
18738 " vec4 result = tcs_tes[0];\n"
18739 "\n"
18740 "VARIABLE_USE"
18741 "\n"
18742 " tes_gs += result;\n"
18743 "}\n"
18744 "\n";
18745 static const GLchar* vs = "#version 430 core\n"
18746 "#extension GL_ARB_enhanced_layouts : require\n"
18747 "\n"
18748 "in vec4 in_vs;\n"
18749 "out vec4 vs_tcs;\n"
18750 "\n"
18751 "void main()\n"
18752 "{\n"
18753 " vs_tcs = in_vs;\n"
18754 "}\n"
18755 "\n";
18756 static const GLchar* vs_tested = "#version 430 core\n"
18757 "#extension GL_ARB_enhanced_layouts : require\n"
18758 "\n"
18759 "VAR_DEFINITION"
18760 "\n"
18761 "in vec4 in_vs;\n"
18762 "out vec4 vs_tcs;\n"
18763 "\n"
18764 "void main()\n"
18765 "{\n"
18766 " vec4 result = in_vs;\n"
18767 "\n"
18768 "VARIABLE_USE"
18769 "\n"
18770 " vs_tcs += result;\n"
18771 "}\n"
18772 "\n";
18773
18774 std::string source;
18775 testCase& test_case = m_test_cases[test_case_index];
18776
18777 if (test_case.m_stage == stage)
18778 {
18779 const GLchar* array = "";
18780 GLchar buffer_gohan[16];
18781 GLchar buffer_goten[16];
18782 const GLchar* direction = "in ";
18783 const GLchar* index = "";
18784 const GLchar* int_gohan = getInterpolationQualifier(test_case.m_interpolation_gohan);
18785 const GLchar* int_goten = getInterpolationQualifier(test_case.m_interpolation_goten);
18786 #if DEBUG_NEG_REMOVE_ERROR
18787 if (FLAT == test_case.m_interpolation_goten)
18788 {
18789 int_gohan = int_goten;
18790 }
18791 else
18792 {
18793 int_goten = int_gohan;
18794 }
18795 #endif /* DEBUG_NEG_REMOVE_ERROR */
18796 size_t position = 0;
18797 size_t temp;
18798 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18799 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18800 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
18801
18802 if (false == test_case.m_is_input)
18803 {
18804 direction = "out";
18805
18806 var_use = output_use;
18807 }
18808
18809 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18810 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18811
18812 switch (stage)
18813 {
18814 case Utils::Shader::FRAGMENT:
18815 source = fs_tested;
18816 break;
18817 case Utils::Shader::GEOMETRY:
18818 source = gs_tested;
18819 array = test_case.m_is_input ? "[]" : "";
18820 index = test_case.m_is_input ? "[0]" : "";
18821 break;
18822 case Utils::Shader::TESS_CTRL:
18823 source = tcs_tested;
18824 array = "[]";
18825 index = "[gl_InvocationID]";
18826 break;
18827 case Utils::Shader::TESS_EVAL:
18828 source = tes_tested;
18829 array = test_case.m_is_input ? "[]" : "";
18830 index = test_case.m_is_input ? "[0]" : "";
18831 break;
18832 case Utils::Shader::VERTEX:
18833 source = vs_tested;
18834 break;
18835 default:
18836 TCU_FAIL("Invalid enum");
18837 }
18838
18839 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18840 position = 0;
18841 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18842 Utils::replaceToken("INTERPOLATION", position, int_gohan, source);
18843 Utils::replaceToken("DIRECTION", position, direction, source);
18844 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18845 Utils::replaceToken("ARRAY", position, array, source);
18846 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18847 Utils::replaceToken("INTERPOLATION", position, int_goten, source);
18848 Utils::replaceToken("DIRECTION", position, direction, source);
18849 Utils::replaceToken("TYPE", position, type_goten_name, source);
18850 Utils::replaceToken("ARRAY", position, array, source);
18851
18852 temp = position;
18853 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18854 position = temp;
18855 if (!test_case.m_is_input)
18856 {
18857 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18858 Utils::replaceToken("TYPE", position, type_goten_name, source);
18859 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18860 Utils::replaceToken("TYPE", position, type_goten_name, source);
18861 }
18862 else if (Utils::Shader::VERTEX == stage)
18863 {
18864 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18865 Utils::replaceToken("TYPE", position, type_goten_name, source);
18866 }
18867
18868 Utils::replaceAllTokens("INDEX", index, source);
18869 }
18870 else
18871 {
18872 switch (stage)
18873 {
18874 case Utils::Shader::FRAGMENT:
18875 source = fs;
18876 break;
18877 case Utils::Shader::GEOMETRY:
18878 source = gs;
18879 break;
18880 case Utils::Shader::TESS_CTRL:
18881 source = tcs;
18882 break;
18883 case Utils::Shader::TESS_EVAL:
18884 source = tes;
18885 break;
18886 case Utils::Shader::VERTEX:
18887 source = vs;
18888 break;
18889 default:
18890 TCU_FAIL("Invalid enum");
18891 }
18892 }
18893
18894 return source;
18895 }
18896
18897 /** Get description of test case
18898 *
18899 * @param test_case_index Index of test case
18900 *
18901 * @return Test case description
18902 **/
18903 std::string VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseName(GLuint test_case_index)
18904 {
18905 std::stringstream stream;
18906 testCase& test_case = m_test_cases[test_case_index];
18907
18908 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18909 << getInterpolationQualifier(test_case.m_interpolation_gohan) << " "
18910 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
18911 << getInterpolationQualifier(test_case.m_interpolation_goten) << " "
18912 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18913
18914 if (true == test_case.m_is_input)
18915 {
18916 stream << "input";
18917 }
18918 else
18919 {
18920 stream << "output";
18921 }
18922
18923 return stream.str();
18924 }
18925
18926 /** Get number of test cases
18927 *
18928 * @return Number of test cases
18929 **/
18930 GLuint VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseNumber()
18931 {
18932 return static_cast<GLuint>(m_test_cases.size());
18933 }
18934
18935 /** Selects if "compute" stage is relevant for test
18936 *
18937 * @param ignored
18938 *
18939 * @return false
18940 **/
18941 bool VaryingLocationAliasingWithMixedInterpolationTest::isComputeRelevant(GLuint /* test_case_index */)
18942 {
18943 return false;
18944 }
18945
18946 /** Prepare all test cases
18947 *
18948 **/
18949 void VaryingLocationAliasingWithMixedInterpolationTest::testInit()
18950 {
18951 const GLuint n_types = getTypesNumber();
18952
18953 for (GLuint i = 0; i < n_types; ++i)
18954 {
18955 const Utils::Type& type_gohan = getType(i);
18956 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
18957
18958 if (valid_components_gohan.empty())
18959 {
18960 continue;
18961 }
18962
18963 const GLuint gohan = valid_components_gohan.front();
18964
18965 for (GLuint j = 0; j < n_types; ++j)
18966 {
18967 const Utils::Type& type_goten = getType(j);
18968 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
18969
18970 if (valid_components_goten.empty())
18971 {
18972 continue;
18973 }
18974
18975 /* Just get the highest valid component for goten and
18976 * check if we can use it.
18977 */
18978 const GLuint min_component = gohan + type_gohan.GetNumComponents();
18979 const GLuint goten = valid_components_goten.back();
18980
18981 if (min_component > goten)
18982 {
18983 continue;
18984 }
18985
18986 /* Skip invalid combinations */
18987 if (!Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
18988 {
18989 continue;
18990 }
18991
18992 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18993 {
18994 /* Skip compute shader */
18995 if (Utils::Shader::COMPUTE == stage)
18996 {
18997 continue;
18998 }
18999
19000 for (GLuint int_gohan = 0; int_gohan < INTERPOLATION_MAX; ++int_gohan)
19001 {
19002 for (GLuint int_goten = 0; int_goten < INTERPOLATION_MAX; ++int_goten)
19003 {
19004 /* Skip when both are the same */
19005 if (int_gohan == int_goten)
19006 {
19007 continue;
19008 }
19009
19010 /* Skip inputs in: vertex shader and whenever
19011 * flat is mandatory and is not the chosen
19012 * one.
19013 */
19014 bool skip_inputs = Utils::Shader::VERTEX == stage;
19015 skip_inputs |=
19016 (FLAT != int_gohan && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_gohan,
19017 Utils::Variable::VARYING_INPUT));
19018 skip_inputs |=
19019 (FLAT != int_goten && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_goten,
19020 Utils::Variable::VARYING_INPUT));
19021
19022 if (!skip_inputs)
19023 {
19024 testCase test_case_in = { gohan,
19025 goten,
19026 static_cast<INTERPOLATIONS>(int_gohan),
19027 static_cast<INTERPOLATIONS>(int_goten),
19028 true,
19029 static_cast<Utils::Shader::STAGES>(stage),
19030 type_gohan,
19031 type_goten };
19032 m_test_cases.push_back(test_case_in);
19033 }
19034
19035 /* Skip outputs in fragment shader and
19036 * whenever flat is mandatory and is not the
19037 * chosen one.
19038 */
19039 bool skip_outputs = Utils::Shader::FRAGMENT == stage;
19040 skip_outputs |=
19041 (FLAT != int_gohan && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_gohan,
19042 Utils::Variable::VARYING_OUTPUT));
19043 skip_outputs |=
19044 (FLAT != int_goten && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_goten,
19045 Utils::Variable::VARYING_OUTPUT));
19046
19047 if (!skip_outputs)
19048 {
19049 testCase test_case_out = { gohan,
19050 goten,
19051 static_cast<INTERPOLATIONS>(int_gohan),
19052 static_cast<INTERPOLATIONS>(int_goten),
19053 false,
19054 static_cast<Utils::Shader::STAGES>(stage),
19055 type_gohan,
19056 type_goten };
19057 m_test_cases.push_back(test_case_out);
19058 }
19059 }
19060 }
19061 }
19062 }
19063 }
19064 }
19065
19066 /** Get interpolation qualifier
19067 *
19068 * @param interpolation Enumeration
19069 *
19070 * @return GLSL qualifier
19071 **/
19072 const GLchar* VaryingLocationAliasingWithMixedInterpolationTest::getInterpolationQualifier(INTERPOLATIONS interpolation)
19073 {
19074 const GLchar* result = 0;
19075
19076 switch (interpolation)
19077 {
19078 case SMOOTH:
19079 result = "smooth";
19080 break;
19081 case FLAT:
19082 result = "flat";
19083 break;
19084 case NO_PERSPECTIVE:
19085 result = "noperspective";
19086 break;
19087 default:
19088 TCU_FAIL("Invalid enum");
19089 }
19090
19091 return result;
19092 }
19093
19094 /** Constructor
19095 *
19096 * @param context Test framework context
19097 **/
19098 VaryingLocationAliasingWithMixedAuxiliaryStorageTest::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(
19099 deqp::Context& context)
19100 : NegativeTestBase(
19101 context, "varying_location_aliasing_with_mixed_auxiliary_storage",
19102 "Test verifies that compiler reports error when auxiliary storage qualifiers are mixed at one location")
19103 {
19104 }
19105
19106 /** Source for given test case and stage
19107 *
19108 * @param test_case_index Index of test case
19109 * @param stage Shader stage
19110 *
19111 * @return Shader source
19112 **/
19113 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getShaderSource(GLuint test_case_index,
19114 Utils::Shader::STAGES stage)
19115 {
19116 static const GLchar* var_definition =
19117 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
19118 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
19119 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX_GOHAN) &&\n"
19120 " (TYPE(1) == gotenINDEX_GOTEN) )\n"
19121 " {\n"
19122 " result += vec4(1, 0.5, 0.25, 0.125);\n"
19123 " }\n";
19124 static const GLchar* output_use = " gohanINDEX_GOHAN = TYPE(0);\n"
19125 " gotenINDEX_GOTEN = TYPE(1);\n"
19126 " if (vec4(0) == result)\n"
19127 " {\n"
19128 " gohanINDEX_GOHAN = TYPE(1);\n"
19129 " gotenINDEX_GOTEN = TYPE(0);\n"
19130 " }\n";
19131 static const GLchar* fs = "#version 430 core\n"
19132 "#extension GL_ARB_enhanced_layouts : require\n"
19133 "\n"
19134 "in vec4 gs_fs;\n"
19135 "out vec4 fs_out;\n"
19136 "\n"
19137 "void main()\n"
19138 "{\n"
19139 " fs_out = gs_fs;\n"
19140 "}\n"
19141 "\n";
19142 static const GLchar* fs_tested = "#version 430 core\n"
19143 "#extension GL_ARB_enhanced_layouts : require\n"
19144 "\n"
19145 "VAR_DEFINITION"
19146 "\n"
19147 "in vec4 gs_fs;\n"
19148 "out vec4 fs_out;\n"
19149 "\n"
19150 "void main()\n"
19151 "{\n"
19152 " vec4 result = gs_fs;\n"
19153 "\n"
19154 "VARIABLE_USE"
19155 "\n"
19156 " fs_out = result;\n"
19157 "}\n"
19158 "\n";
19159 static const GLchar* gs = "#version 430 core\n"
19160 "#extension GL_ARB_enhanced_layouts : require\n"
19161 "\n"
19162 "layout(points) in;\n"
19163 "layout(triangle_strip, max_vertices = 4) out;\n"
19164 "\n"
19165 "in vec4 tes_gs[];\n"
19166 "out vec4 gs_fs;\n"
19167 "\n"
19168 "void main()\n"
19169 "{\n"
19170 " gs_fs = tes_gs[0];\n"
19171 " gl_Position = vec4(-1, -1, 0, 1);\n"
19172 " EmitVertex();\n"
19173 " gs_fs = tes_gs[0];\n"
19174 " gl_Position = vec4(-1, 1, 0, 1);\n"
19175 " EmitVertex();\n"
19176 " gs_fs = tes_gs[0];\n"
19177 " gl_Position = vec4(1, -1, 0, 1);\n"
19178 " EmitVertex();\n"
19179 " gs_fs = tes_gs[0];\n"
19180 " gl_Position = vec4(1, 1, 0, 1);\n"
19181 " EmitVertex();\n"
19182 "}\n"
19183 "\n";
19184 static const GLchar* gs_tested = "#version 430 core\n"
19185 "#extension GL_ARB_enhanced_layouts : require\n"
19186 "\n"
19187 "layout(points) in;\n"
19188 "layout(triangle_strip, max_vertices = 4) out;\n"
19189 "\n"
19190 "VAR_DEFINITION"
19191 "\n"
19192 "in vec4 tes_gs[];\n"
19193 "out vec4 gs_fs;\n"
19194 "\n"
19195 "void main()\n"
19196 "{\n"
19197 " vec4 result = tes_gs[0];\n"
19198 "\n"
19199 "VARIABLE_USE"
19200 "\n"
19201 " gs_fs = result;\n"
19202 " gl_Position = vec4(-1, -1, 0, 1);\n"
19203 " EmitVertex();\n"
19204 " gs_fs = result;\n"
19205 " gl_Position = vec4(-1, 1, 0, 1);\n"
19206 " EmitVertex();\n"
19207 " gs_fs = result;\n"
19208 " gl_Position = vec4(1, -1, 0, 1);\n"
19209 " EmitVertex();\n"
19210 " gs_fs = result;\n"
19211 " gl_Position = vec4(1, 1, 0, 1);\n"
19212 " EmitVertex();\n"
19213 "}\n"
19214 "\n";
19215 static const GLchar* tcs = "#version 430 core\n"
19216 "#extension GL_ARB_enhanced_layouts : require\n"
19217 "\n"
19218 "layout(vertices = 1) out;\n"
19219 "\n"
19220 "in vec4 vs_tcs[];\n"
19221 "out vec4 tcs_tes[];\n"
19222 "\n"
19223 "void main()\n"
19224 "{\n"
19225 "\n"
19226 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
19227 "\n"
19228 " gl_TessLevelOuter[0] = 1.0;\n"
19229 " gl_TessLevelOuter[1] = 1.0;\n"
19230 " gl_TessLevelOuter[2] = 1.0;\n"
19231 " gl_TessLevelOuter[3] = 1.0;\n"
19232 " gl_TessLevelInner[0] = 1.0;\n"
19233 " gl_TessLevelInner[1] = 1.0;\n"
19234 "}\n"
19235 "\n";
19236 static const GLchar* tcs_tested = "#version 430 core\n"
19237 "#extension GL_ARB_enhanced_layouts : require\n"
19238 "\n"
19239 "layout(vertices = 1) out;\n"
19240 "\n"
19241 "VAR_DEFINITION"
19242 "\n"
19243 "in vec4 vs_tcs[];\n"
19244 "out vec4 tcs_tes[];\n"
19245 "\n"
19246 "void main()\n"
19247 "{\n"
19248 " vec4 result = vs_tcs[gl_InvocationID];\n"
19249 "\n"
19250 "VARIABLE_USE"
19251 "\n"
19252 " tcs_tes[gl_InvocationID] = result;\n"
19253 "\n"
19254 " gl_TessLevelOuter[0] = 1.0;\n"
19255 " gl_TessLevelOuter[1] = 1.0;\n"
19256 " gl_TessLevelOuter[2] = 1.0;\n"
19257 " gl_TessLevelOuter[3] = 1.0;\n"
19258 " gl_TessLevelInner[0] = 1.0;\n"
19259 " gl_TessLevelInner[1] = 1.0;\n"
19260 "}\n"
19261 "\n";
19262 static const GLchar* tes = "#version 430 core\n"
19263 "#extension GL_ARB_enhanced_layouts : require\n"
19264 "\n"
19265 "layout(isolines, point_mode) in;\n"
19266 "\n"
19267 "in vec4 tcs_tes[];\n"
19268 "out vec4 tes_gs;\n"
19269 "\n"
19270 "void main()\n"
19271 "{\n"
19272 " tes_gs = tcs_tes[0];\n"
19273 "}\n"
19274 "\n";
19275 static const GLchar* tes_tested = "#version 430 core\n"
19276 "#extension GL_ARB_enhanced_layouts : require\n"
19277 "\n"
19278 "layout(isolines, point_mode) in;\n"
19279 "\n"
19280 "VAR_DEFINITION"
19281 "\n"
19282 "in vec4 tcs_tes[];\n"
19283 "out vec4 tes_gs;\n"
19284 "\n"
19285 "void main()\n"
19286 "{\n"
19287 " vec4 result = tcs_tes[0];\n"
19288 "\n"
19289 "VARIABLE_USE"
19290 "\n"
19291 " tes_gs += result;\n"
19292 "}\n"
19293 "\n";
19294 static const GLchar* vs = "#version 430 core\n"
19295 "#extension GL_ARB_enhanced_layouts : require\n"
19296 "\n"
19297 "in vec4 in_vs;\n"
19298 "out vec4 vs_tcs;\n"
19299 "\n"
19300 "void main()\n"
19301 "{\n"
19302 " vs_tcs = in_vs;\n"
19303 "}\n"
19304 "\n";
19305 static const GLchar* vs_tested = "#version 430 core\n"
19306 "#extension GL_ARB_enhanced_layouts : require\n"
19307 "\n"
19308 "VAR_DEFINITION"
19309 "\n"
19310 "in vec4 in_vs;\n"
19311 "out vec4 vs_tcs;\n"
19312 "\n"
19313 "void main()\n"
19314 "{\n"
19315 " vec4 result = in_vs;\n"
19316 "\n"
19317 "VARIABLE_USE"
19318 "\n"
19319 " vs_tcs += result;\n"
19320 "}\n"
19321 "\n";
19322
19323 std::string source;
19324 testCase& test_case = m_test_cases[test_case_index];
19325
19326 if (test_case.m_stage == stage)
19327 {
19328 const GLchar* array_gohan = "";
19329 const GLchar* array_goten = "";
19330 const GLchar* aux_gohan = getAuxiliaryQualifier(test_case.m_aux_gohan);
19331 #if DEBUG_NEG_REMOVE_ERROR
19332 const GLchar* aux_goten = aux_gohan;
19333 #else
19334 const GLchar* aux_goten = getAuxiliaryQualifier(test_case.m_aux_goten);
19335 #endif /* DEBUG_NEG_REMOVE_ERROR */
19336 GLchar buffer_gohan[16];
19337 GLchar buffer_goten[16];
19338 const GLchar* direction = "in";
19339 const GLchar* index_gohan = "";
19340 const GLchar* index_goten = "";
19341 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
19342 const GLchar* interpolation = "";
19343 size_t position = 0;
19344 size_t temp;
19345 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
19346 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
19347 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
19348
19349 if (false == test_case.m_is_input)
19350 {
19351 direction = "out";
19352 storage = Utils::Variable::VARYING_OUTPUT;
19353 var_use = output_use;
19354 }
19355
19356 if (isFlatRequired(stage, test_case.m_type_gohan, storage) ||
19357 isFlatRequired(stage, test_case.m_type_goten, storage))
19358 {
19359 interpolation = "flat";
19360 }
19361
19362 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
19363 sprintf(buffer_goten, "%d", test_case.m_component_goten);
19364
19365 switch (stage)
19366 {
19367 case Utils::Shader::FRAGMENT:
19368 source = fs_tested;
19369 break;
19370 case Utils::Shader::GEOMETRY:
19371 source = gs_tested;
19372 array_gohan = test_case.m_is_input ? "[]" : "";
19373 index_gohan = test_case.m_is_input ? "[0]" : "";
19374 array_goten = test_case.m_is_input ? "[]" : "";
19375 index_goten = test_case.m_is_input ? "[0]" : "";
19376 break;
19377 case Utils::Shader::TESS_CTRL:
19378 source = tcs_tested;
19379 if (PATCH != test_case.m_aux_gohan)
19380 {
19381 array_gohan = "[]";
19382 index_gohan = "[gl_InvocationID]";
19383 }
19384 #if DEBUG_NEG_REMOVE_ERROR
19385 array_goten = array_gohan;
19386 index_goten = index_gohan;
19387 #else
19388 if (PATCH != test_case.m_aux_goten)
19389 {
19390 array_goten = "[]";
19391 index_goten = "[gl_InvocationID]";
19392 }
19393 #endif /* DEBUG_NEG_REMOVE_ERROR */
19394 break;
19395 case Utils::Shader::TESS_EVAL:
19396 source = tes_tested;
19397 if (PATCH != test_case.m_aux_gohan)
19398 {
19399 array_gohan = test_case.m_is_input ? "[]" : "";
19400 index_gohan = test_case.m_is_input ? "[0]" : "";
19401 }
19402 #if DEBUG_NEG_REMOVE_ERROR
19403 array_goten = array_gohan;
19404 index_goten = index_gohan;
19405 #else
19406 if (PATCH != test_case.m_aux_goten)
19407 {
19408 array_goten = test_case.m_is_input ? "[]" : "";
19409 index_goten = test_case.m_is_input ? "[0]" : "";
19410 }
19411 #endif /* DEBUG_NEG_REMOVE_ERROR */
19412 break;
19413 case Utils::Shader::VERTEX:
19414 source = vs_tested;
19415 break;
19416 default:
19417 TCU_FAIL("Invalid enum");
19418 }
19419
19420 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
19421 position = 0;
19422 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
19423 Utils::replaceToken("AUX", position, aux_gohan, source);
19424 Utils::replaceToken("INTERPOLATION", position, interpolation, source);
19425 Utils::replaceToken("DIRECTION", position, direction, source);
19426 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19427 Utils::replaceToken("ARRAY", position, array_gohan, source);
19428 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
19429 Utils::replaceToken("AUX", position, aux_goten, source);
19430 Utils::replaceToken("INTERPOLATION", position, interpolation, source);
19431 Utils::replaceToken("DIRECTION", position, direction, source);
19432 Utils::replaceToken("TYPE", position, type_goten_name, source);
19433 Utils::replaceToken("ARRAY", position, array_goten, source);
19434
19435 temp = position;
19436 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
19437 position = temp;
19438 if (!test_case.m_is_input)
19439 {
19440 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19441 Utils::replaceToken("TYPE", position, type_goten_name, source);
19442 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19443 Utils::replaceToken("TYPE", position, type_goten_name, source);
19444 }
19445 else if (Utils::Shader::VERTEX == stage)
19446 {
19447 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19448 Utils::replaceToken("TYPE", position, type_goten_name, source);
19449 }
19450
19451 Utils::replaceAllTokens("INDEX_GOHAN", index_gohan, source);
19452 Utils::replaceAllTokens("INDEX_GOTEN", index_goten, source);
19453 }
19454 else
19455 {
19456 switch (stage)
19457 {
19458 case Utils::Shader::FRAGMENT:
19459 source = fs;
19460 break;
19461 case Utils::Shader::GEOMETRY:
19462 source = gs;
19463 break;
19464 case Utils::Shader::TESS_CTRL:
19465 source = tcs;
19466 break;
19467 case Utils::Shader::TESS_EVAL:
19468 source = tes;
19469 break;
19470 case Utils::Shader::VERTEX:
19471 source = vs;
19472 break;
19473 default:
19474 TCU_FAIL("Invalid enum");
19475 }
19476 }
19477
19478 return source;
19479 }
19480
19481 /** Get description of test case
19482 *
19483 * @param test_case_index Index of test case
19484 *
19485 * @return Test case description
19486 **/
19487 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseName(GLuint test_case_index)
19488 {
19489 std::stringstream stream;
19490 testCase& test_case = m_test_cases[test_case_index];
19491
19492 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
19493 << getAuxiliaryQualifier(test_case.m_aux_gohan) << " " << test_case.m_type_gohan.GetGLSLTypeName() << " at "
19494 << test_case.m_component_gohan << ", " << getAuxiliaryQualifier(test_case.m_aux_goten) << " "
19495 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
19496
19497 if (true == test_case.m_is_input)
19498 {
19499 stream << "input";
19500 }
19501 else
19502 {
19503 stream << "output";
19504 }
19505
19506 return stream.str();
19507 }
19508
19509 /** Get number of test cases
19510 *
19511 * @return Number of test cases
19512 **/
19513 GLuint VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseNumber()
19514 {
19515 return static_cast<GLuint>(m_test_cases.size());
19516 }
19517
19518 /** Selects if "compute" stage is relevant for test
19519 *
19520 * @param ignored
19521 *
19522 * @return false
19523 **/
19524 bool VaryingLocationAliasingWithMixedAuxiliaryStorageTest::isComputeRelevant(GLuint /* test_case_index */)
19525 {
19526 return false;
19527 }
19528
19529 /** Prepare all test cases
19530 *
19531 **/
19532 void VaryingLocationAliasingWithMixedAuxiliaryStorageTest::testInit()
19533 {
19534 const GLuint n_types = getTypesNumber();
19535
19536 for (GLuint i = 0; i < n_types; ++i)
19537 {
19538 const Utils::Type& type_gohan = getType(i);
19539 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
19540
19541 if (valid_components_gohan.empty())
19542 {
19543 continue;
19544 }
19545
19546 const GLuint gohan = valid_components_gohan.front();
19547
19548 for (GLuint j = 0; j < n_types; ++j)
19549 {
19550 const Utils::Type& type_goten = getType(j);
19551 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
19552
19553 if (valid_components_goten.empty())
19554 {
19555 continue;
19556 }
19557
19558 /* Just get the highest valid component for goten and
19559 * check if we can use it.
19560 */
19561 const GLuint min_component = gohan + type_gohan.GetNumComponents();
19562 const GLuint goten = valid_components_goten.back();
19563
19564 if (min_component > goten)
19565 {
19566 continue;
19567 }
19568
19569 /* Skip invalid combinations */
19570 if (!Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
19571 {
19572 continue;
19573 }
19574
19575 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
19576 {
19577 /* Skip compute shader */
19578 if (Utils::Shader::COMPUTE == stage)
19579 {
19580 continue;
19581 }
19582
19583 for (GLuint aux = 0; aux < AUXILIARY_MAX; ++aux)
19584 {
19585 Utils::Shader::STAGES const shader_stage = static_cast<Utils::Shader::STAGES>(stage);
19586 AUXILIARIES const auxiliary = static_cast<AUXILIARIES>(aux);
19587
19588 if (PATCH == auxiliary)
19589 {
19590 if (Utils::Shader::TESS_CTRL == shader_stage || Utils::Shader::TESS_EVAL == shader_stage)
19591 {
19592 bool direction = Utils::Shader::TESS_EVAL == shader_stage;
19593 testCase test_case_patch_gohan = { gohan, goten, auxiliary, NONE,
19594 direction, shader_stage, type_gohan, type_goten };
19595 testCase test_case_patch_goten = { gohan, goten, NONE, auxiliary,
19596 direction, shader_stage, type_gohan, type_goten };
19597
19598 m_test_cases.push_back(test_case_patch_gohan);
19599 m_test_cases.push_back(test_case_patch_goten);
19600 }
19601 continue;
19602 }
19603
19604 for (GLuint second_aux = 0; second_aux < AUXILIARY_MAX; ++second_aux)
19605 {
19606 AUXILIARIES const second_auxiliary = static_cast<AUXILIARIES>(second_aux);
19607
19608 if (PATCH == second_auxiliary || auxiliary == second_auxiliary)
19609 {
19610 continue;
19611 }
19612
19613 if (Utils::Shader::FRAGMENT != shader_stage)
19614 {
19615 testCase test_case_out = { gohan, goten, auxiliary, second_auxiliary,
19616 false, shader_stage, type_gohan, type_goten };
19617
19618 m_test_cases.push_back(test_case_out);
19619 }
19620
19621 if (Utils::Shader::VERTEX != shader_stage)
19622 {
19623 testCase test_case_in = { gohan, goten, auxiliary, second_auxiliary,
19624 true, shader_stage, type_gohan, type_goten };
19625
19626 m_test_cases.push_back(test_case_in);
19627 }
19628 }
19629 }
19630 }
19631 }
19632 }
19633 }
19634
19635 /** Get auxiliary storage qualifier
19636 *
19637 * @param aux Enumeration
19638 *
19639 * @return GLSL qualifier
19640 **/
19641 const GLchar* VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getAuxiliaryQualifier(AUXILIARIES aux)
19642 {
19643 const GLchar* result = 0;
19644
19645 switch (aux)
19646 {
19647 case NONE:
19648 result = "";
19649 break;
19650 case PATCH:
19651 result = "patch";
19652 break;
19653 case CENTROID:
19654 result = "centroid";
19655 break;
19656 case SAMPLE:
19657 result = "sample";
19658 break;
19659 default:
19660 TCU_FAIL("Invalid enum");
19661 }
19662
19663 return result;
19664 }
19665
19666 /* Constants used by VertexAttribLocationAPITest */
19667 const GLuint VertexAttribLocationAPITest::m_goten_location = 6;
19668
19669 /** Constructor
19670 *
19671 * @param context Test framework context
19672 **/
19673 VertexAttribLocationAPITest::VertexAttribLocationAPITest(deqp::Context& context)
19674 : TextureTestBase(context, "vertex_attrib_location_api",
19675 "Test verifies that attribute locations API works as expected")
19676 {
19677 }
19678
19679 /** Does BindAttribLocation for "goten" and relink program
19680 *
19681 * @param program Program object
19682 * @param program_interface Interface of program
19683 **/
19684 void VertexAttribLocationAPITest::prepareAttribLocation(Utils::Program& program,
19685 Utils::ProgramInterface& program_interface)
19686 {
19687 const Functions& gl = m_context.getRenderContext().getFunctions();
19688
19689 gl.bindAttribLocation(program.m_id, m_goten_location, "goten");
19690 GLU_EXPECT_NO_ERROR(gl.getError(), "BindAttribLocation");
19691
19692 program.Link(gl, program.m_id);
19693
19694 /* We still need to get locations for gohan and chichi */
19695 TextureTestBase::prepareAttribLocation(program, program_interface);
19696 }
19697
19698 /** Get interface of program
19699 *
19700 * @param ignored
19701 * @param program_interface Interface of program
19702 * @param ignored
19703 **/
19704 void VertexAttribLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19705 Utils::ProgramInterface& program_interface,
19706 Utils::VaryingPassthrough& /* varying_passthrough */)
19707 {
19708 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
19709 const Utils::Type& type = Utils::Type::vec4;
19710 const GLuint type_size = type.GetSize();
19711
19712 /* Offsets */
19713 const GLuint chichi_offset = 0;
19714 const GLuint goten_offset = chichi_offset + type_size;
19715 const GLuint gohan_offset = goten_offset + type_size;
19716 const GLuint goku_offset = gohan_offset + type_size;
19717
19718 /* Locations */
19719 const GLuint goku_location = 2;
19720 const GLuint goten_location = m_goten_location;
19721
19722 /* Generate data */
19723 m_goku_data = type.GenerateDataPacked();
19724 m_gohan_data = type.GenerateDataPacked();
19725 m_goten_data = type.GenerateDataPacked();
19726 m_chichi_data = type.GenerateDataPacked();
19727
19728 /* Globals */
19729 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19730
19731 /* Attributes */
19732 si.Input("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19733 goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19734 0u /* n_array_elements */, 0u /* stride */, goku_offset /* offset */, (GLvoid*)&m_goku_data[0] /* data */,
19735 m_goku_data.size() /* data_size */);
19736
19737 si.Input("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19738 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19739 0u /* n_array_elements */, 0u /* stride */, gohan_offset /* offset */,
19740 (GLvoid*)&m_gohan_data[0] /* data */, m_gohan_data.size() /* data_size */);
19741
19742 si.Input("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19743 goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19744 0u /* n_array_elements */, 0u /* stride */, goten_offset /* offset */,
19745 (GLvoid*)&m_goten_data[0] /* data */, m_goten_data.size() /* data_size */);
19746
19747 si.Input("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19748 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19749 0u /* n_array_elements */, 0u /* stride */, chichi_offset /* offset */,
19750 (GLvoid*)&m_chichi_data[0] /* data */, m_chichi_data.size() /* data_size */);
19751 }
19752
19753 /** Selects if "compute" stage is relevant for test
19754 *
19755 * @param ignored
19756 *
19757 * @return false
19758 **/
19759 bool VertexAttribLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19760 {
19761 return false;
19762 }
19763
19764 /* Constants used by FragmentDataLocationAPITest */
19765 const GLuint FragmentDataLocationAPITest::m_goten_location = 6;
19766
19767 /** Constructor
19768 *
19769 * @param context Test framework context
19770 **/
19771 FragmentDataLocationAPITest::FragmentDataLocationAPITest(deqp::Context& context)
19772 : TextureTestBase(context, "fragment_data_location_api",
19773 "Test verifies that fragment data locations API works as expected")
19774 , m_goku(context)
19775 , m_gohan(context)
19776 , m_goten(context)
19777 , m_chichi(context)
19778 , m_goku_location(0)
19779 , m_gohan_location(0)
19780 , m_chichi_location(0)
19781 {
19782 }
19783
19784 /** Verifies contents of drawn images
19785 *
19786 * @param ignored
19787 * @param ignored
19788 *
19789 * @return true if images are filled with expected values, false otherwise
19790 **/
19791 bool FragmentDataLocationAPITest::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& /* color_0 */)
19792 {
19793 static const GLuint size = m_width * m_height;
19794 static const GLuint expected_goku = 0xff000000;
19795 static const GLuint expected_gohan = 0xff0000ff;
19796 static const GLuint expected_goten = 0xff00ff00;
19797 static const GLuint expected_chichi = 0xffff0000;
19798
19799 std::vector<GLuint> data;
19800 data.resize(size);
19801
19802 m_goku.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19803
19804 for (GLuint i = 0; i < size; ++i)
19805 {
19806 const GLuint color = data[i];
19807
19808 if (expected_goku != color)
19809 {
19810 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19811 << tcu::TestLog::EndMessage;
19812 return false;
19813 }
19814 }
19815
19816 m_gohan.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19817
19818 for (GLuint i = 0; i < size; ++i)
19819 {
19820 const GLuint color = data[i];
19821
19822 if (expected_gohan != color)
19823 {
19824 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19825 << tcu::TestLog::EndMessage;
19826 return false;
19827 }
19828 }
19829
19830 m_goten.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19831
19832 for (GLuint i = 0; i < size; ++i)
19833 {
19834 const GLuint color = data[i];
19835
19836 if (expected_goten != color)
19837 {
19838 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19839 << tcu::TestLog::EndMessage;
19840 return false;
19841 }
19842 }
19843
19844 m_chichi.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19845
19846 for (GLuint i = 0; i < size; ++i)
19847 {
19848 const GLuint color = data[i];
19849
19850 if (expected_chichi != color)
19851 {
19852 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19853 << tcu::TestLog::EndMessage;
19854 return false;
19855 }
19856 }
19857
19858 return true;
19859 }
19860
19861 /** Prepare code snippet that will set out variables
19862 *
19863 * @param ignored
19864 * @param ignored
19865 * @param stage Shader stage
19866 *
19867 * @return Code that pass in variables to next stage
19868 **/
19869 std::string FragmentDataLocationAPITest::getPassSnippet(GLuint /* test_case_index */,
19870 Utils::VaryingPassthrough& /* varying_passthrough */,
19871 Utils::Shader::STAGES stage)
19872 {
19873 std::string result;
19874
19875 /* Skip for compute shader */
19876 if (Utils::Shader::FRAGMENT != stage)
19877 {
19878 result = "";
19879 }
19880 else
19881 {
19882 result = "chichi = vec4(0, 0, 1, 1);\n"
19883 " goku = vec4(0, 0, 0, 1);\n"
19884 " goten = vec4(0, 1, 0, 1);\n"
19885 " gohan = vec4(1, 0, 0, 1);\n";
19886 }
19887
19888 return result;
19889 }
19890
19891 /** Get interface of program
19892 *
19893 * @param ignored
19894 * @param program_interface Interface of program
19895 * @param ignored
19896 **/
19897 void FragmentDataLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19898 Utils::ProgramInterface& program_interface,
19899 Utils::VaryingPassthrough& /* varying_passthrough */)
19900 {
19901 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19902 const Utils::Type& type = Utils::Type::vec4;
19903
19904 /* Locations */
19905 m_goku_location = 2;
19906
19907 /* Globals */
19908 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19909
19910 /* Attributes */
19911 si.Output("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19912 m_goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19913 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19914
19915 si.Output("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19916 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19917 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19918
19919 si.Output("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19920 m_goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19921 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19922
19923 si.Output("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19924 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19925 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19926 }
19927
19928 /** Selects if "compute" stage is relevant for test
19929 *
19930 * @param ignored
19931 *
19932 * @return false
19933 **/
19934 bool FragmentDataLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19935 {
19936 return false;
19937 }
19938
19939 /** Get locations for all outputs with automatic_location
19940 *
19941 * @param program Program object
19942 * @param program_interface Interface of program
19943 **/
19944 void FragmentDataLocationAPITest::prepareFragmentDataLoc(Utils::Program& program,
19945 Utils::ProgramInterface& program_interface)
19946 {
19947 /* Bind location of goten */
19948 const Functions& gl = m_context.getRenderContext().getFunctions();
19949
19950 gl.bindFragDataLocation(program.m_id, m_goten_location, "goten");
19951 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFragDataLocation");
19952
19953 program.Link(gl, program.m_id);
19954
19955 /* Prepare locations for gohan and chichi */
19956 TextureTestBase::prepareFragmentDataLoc(program, program_interface);
19957
19958 /* Get all locations */
19959 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19960
19961 Utils::Variable::PtrVector& outputs = si.m_outputs;
19962
19963 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
19964 {
19965 const Utils::Variable::Descriptor& desc = (*it)->m_descriptor;
19966
19967 if (0 == desc.m_name.compare("gohan"))
19968 {
19969 m_gohan_location = desc.m_expected_location;
19970 }
19971 else if (0 == desc.m_name.compare("chichi"))
19972 {
19973 m_chichi_location = desc.m_expected_location;
19974 }
19975
19976 /* Locations of goku and goten are fixed */
19977 }
19978 }
19979
19980 /** Prepare framebuffer with single texture as color attachment
19981 *
19982 * @param framebuffer Framebuffer
19983 * @param color_0_texture Texture that will used as color attachment
19984 **/
19985 void FragmentDataLocationAPITest::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
19986 {
19987 /* Let parent prepare its stuff */
19988 TextureTestBase::prepareFramebuffer(framebuffer, color_0_texture);
19989
19990 /* Prepare data */
19991 std::vector<GLuint> texture_data;
19992 texture_data.resize(m_width * m_height);
19993
19994 for (GLuint i = 0; i < texture_data.size(); ++i)
19995 {
19996 texture_data[i] = 0x20406080;
19997 }
19998
19999 /* Prepare textures */
20000 m_goku.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20001
20002 m_gohan.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20003
20004 m_goten.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20005
20006 m_chichi.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20007
20008 /* Attach textures to framebuffer */
20009 framebuffer.Bind();
20010 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goku_location, m_goku.m_id, m_width, m_height);
20011 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_gohan_location, m_gohan.m_id, m_width, m_height);
20012 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goten_location, m_goten.m_id, m_width, m_height);
20013 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_chichi_location, m_chichi.m_id, m_width, m_height);
20014
20015 /* Set up drawbuffers */
20016 const Functions& gl = m_context.getRenderContext().getFunctions();
20017 // The fragment shader can have more than 4 color outputs, but it only care about 4 (goku, gohan, goten, chichi).
20018 // We will first initialize all draw buffers to NONE and then set the real value for the 4 outputs we care about
20019 GLint maxDrawBuffers = 0;
20020 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
20021
20022 std::vector<GLenum> buffers(maxDrawBuffers, GL_NONE);
20023 buffers[m_chichi_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_chichi_location);
20024 buffers[m_goten_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goten_location);
20025 buffers[m_goku_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goku_location);
20026 buffers[m_gohan_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_gohan_location);
20027
20028 gl.drawBuffers(maxDrawBuffers, buffers.data());
20029 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers");
20030 }
20031
20032 /** Constructor
20033 *
20034 * @param context Test framework context
20035 **/
20036 XFBInputTest::XFBInputTest(deqp::Context& context)
20037 : NegativeTestBase(context, "xfb_input",
20038 "Test verifies that compiler reports error when xfb qualifiers are used with input")
20039 {
20040 }
20041
20042 /** Source for given test case and stage
20043 *
20044 * @param test_case_index Index of test case
20045 * @param stage Shader stage
20046 *
20047 * @return Shader source
20048 **/
20049 std::string XFBInputTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
20050 {
20051 #if DEBUG_NEG_REMOVE_ERROR
20052 static const GLchar* buffer_var_definition = "/* layout (xfb_buffer = 2) */ in vec4 gohanARRAY;\n";
20053 static const GLchar* offset_var_definition = "/* layout (xfb_offset = 16) */ in vec4 gohanARRAY;\n";
20054 static const GLchar* stride_var_definition = "/* layout (xfb_stride = 32) */ in vec4 gohanARRAY;\n";
20055 #else
20056 static const GLchar* buffer_var_definition = "layout (xfb_buffer = 2) in vec4 gohanARRAY;\n";
20057 static const GLchar* offset_var_definition = "layout (xfb_offset = 16) in vec4 gohanARRAY;\n";
20058 static const GLchar* stride_var_definition = "layout (xfb_stride = 32) in vec4 gohanARRAY;\n";
20059 #endif /* DEBUG_NEG_REMOVE_ERROR */
20060 static const GLchar* fs = "#version 430 core\n"
20061 "#extension GL_ARB_enhanced_layouts : require\n"
20062 "\n"
20063 "in vec4 gs_fs;\n"
20064 "out vec4 fs_out;\n"
20065 "\n"
20066 "void main()\n"
20067 "{\n"
20068 " fs_out = gs_fs;\n"
20069 "}\n"
20070 "\n";
20071 static const GLchar* fs_tested = "#version 430 core\n"
20072 "#extension GL_ARB_enhanced_layouts : require\n"
20073 "\n"
20074 "VAR_DEFINITION"
20075 "\n"
20076 "in vec4 gs_fs;\n"
20077 "out vec4 fs_out;\n"
20078 "\n"
20079 "void main()\n"
20080 "{\n"
20081 " vec4 result = gs_fs;\n"
20082 "\n"
20083 " fs_out = result;\n"
20084 "}\n"
20085 "\n";
20086 static const GLchar* gs = "#version 430 core\n"
20087 "#extension GL_ARB_enhanced_layouts : require\n"
20088 "\n"
20089 "layout(points) in;\n"
20090 "layout(triangle_strip, max_vertices = 4) out;\n"
20091 "\n"
20092 "in vec4 tes_gs[];\n"
20093 "out vec4 gs_fs;\n"
20094 "\n"
20095 "void main()\n"
20096 "{\n"
20097 " gs_fs = tes_gs[0];\n"
20098 " gl_Position = vec4(-1, -1, 0, 1);\n"
20099 " EmitVertex();\n"
20100 " gs_fs = tes_gs[0];\n"
20101 " gl_Position = vec4(-1, 1, 0, 1);\n"
20102 " EmitVertex();\n"
20103 " gs_fs = tes_gs[0];\n"
20104 " gl_Position = vec4(1, -1, 0, 1);\n"
20105 " EmitVertex();\n"
20106 " gs_fs = tes_gs[0];\n"
20107 " gl_Position = vec4(1, 1, 0, 1);\n"
20108 " EmitVertex();\n"
20109 "}\n"
20110 "\n";
20111 static const GLchar* gs_tested = "#version 430 core\n"
20112 "#extension GL_ARB_enhanced_layouts : require\n"
20113 "\n"
20114 "layout(points) in;\n"
20115 "layout(triangle_strip, max_vertices = 4) out;\n"
20116 "\n"
20117 "VAR_DEFINITION"
20118 "\n"
20119 "in vec4 tes_gs[];\n"
20120 "out vec4 gs_fs;\n"
20121 "\n"
20122 "void main()\n"
20123 "{\n"
20124 " vec4 result = tes_gs[0];\n"
20125 "\n"
20126 " gs_fs = result;\n"
20127 " gl_Position = vec4(-1, -1, 0, 1);\n"
20128 " EmitVertex();\n"
20129 " gs_fs = result;\n"
20130 " gl_Position = vec4(-1, 1, 0, 1);\n"
20131 " EmitVertex();\n"
20132 " gs_fs = result;\n"
20133 " gl_Position = vec4(1, -1, 0, 1);\n"
20134 " EmitVertex();\n"
20135 " gs_fs = result;\n"
20136 " gl_Position = vec4(1, 1, 0, 1);\n"
20137 " EmitVertex();\n"
20138 "}\n"
20139 "\n";
20140 static const GLchar* tcs = "#version 430 core\n"
20141 "#extension GL_ARB_enhanced_layouts : require\n"
20142 "\n"
20143 "layout(vertices = 1) out;\n"
20144 "\n"
20145 "in vec4 vs_tcs[];\n"
20146 "out vec4 tcs_tes[];\n"
20147 "\n"
20148 "void main()\n"
20149 "{\n"
20150 "\n"
20151 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
20152 "\n"
20153 " gl_TessLevelOuter[0] = 1.0;\n"
20154 " gl_TessLevelOuter[1] = 1.0;\n"
20155 " gl_TessLevelOuter[2] = 1.0;\n"
20156 " gl_TessLevelOuter[3] = 1.0;\n"
20157 " gl_TessLevelInner[0] = 1.0;\n"
20158 " gl_TessLevelInner[1] = 1.0;\n"
20159 "}\n"
20160 "\n";
20161 static const GLchar* tcs_tested = "#version 430 core\n"
20162 "#extension GL_ARB_enhanced_layouts : require\n"
20163 "\n"
20164 "layout(vertices = 1) out;\n"
20165 "\n"
20166 "VAR_DEFINITION"
20167 "\n"
20168 "in vec4 vs_tcs[];\n"
20169 "out vec4 tcs_tes[];\n"
20170 "\n"
20171 "void main()\n"
20172 "{\n"
20173 " vec4 result = vs_tcs[gl_InvocationID];\n"
20174 "\n"
20175 " tcs_tes[gl_InvocationID] = result;\n"
20176 "\n"
20177 " gl_TessLevelOuter[0] = 1.0;\n"
20178 " gl_TessLevelOuter[1] = 1.0;\n"
20179 " gl_TessLevelOuter[2] = 1.0;\n"
20180 " gl_TessLevelOuter[3] = 1.0;\n"
20181 " gl_TessLevelInner[0] = 1.0;\n"
20182 " gl_TessLevelInner[1] = 1.0;\n"
20183 "}\n"
20184 "\n";
20185 static const GLchar* tes = "#version 430 core\n"
20186 "#extension GL_ARB_enhanced_layouts : require\n"
20187 "\n"
20188 "layout(isolines, point_mode) in;\n"
20189 "\n"
20190 "in vec4 tcs_tes[];\n"
20191 "out vec4 tes_gs;\n"
20192 "\n"
20193 "void main()\n"
20194 "{\n"
20195 " tes_gs = tcs_tes[0];\n"
20196 "}\n"
20197 "\n";
20198 static const GLchar* tes_tested = "#version 430 core\n"
20199 "#extension GL_ARB_enhanced_layouts : require\n"
20200 "\n"
20201 "layout(isolines, point_mode) in;\n"
20202 "\n"
20203 "VAR_DEFINITION"
20204 "\n"
20205 "in vec4 tcs_tes[];\n"
20206 "out vec4 tes_gs;\n"
20207 "\n"
20208 "void main()\n"
20209 "{\n"
20210 " vec4 result = tcs_tes[0];\n"
20211 "\n"
20212 " tes_gs += result;\n"
20213 "}\n"
20214 "\n";
20215 static const GLchar* vs = "#version 430 core\n"
20216 "#extension GL_ARB_enhanced_layouts : require\n"
20217 "\n"
20218 "in vec4 in_vs;\n"
20219 "out vec4 vs_tcs;\n"
20220 "\n"
20221 "void main()\n"
20222 "{\n"
20223 " vs_tcs = in_vs;\n"
20224 "}\n"
20225 "\n";
20226 static const GLchar* vs_tested = "#version 430 core\n"
20227 "#extension GL_ARB_enhanced_layouts : require\n"
20228 "\n"
20229 "VAR_DEFINITION"
20230 "\n"
20231 "in vec4 in_vs;\n"
20232 "out vec4 vs_tcs;\n"
20233 "\n"
20234 "void main()\n"
20235 "{\n"
20236 " vec4 result = in_vs;\n"
20237 "\n"
20238 " vs_tcs += result;\n"
20239 "}\n"
20240 "\n";
20241
20242 std::string source;
20243 testCase& test_case = m_test_cases[test_case_index];
20244
20245 if (test_case.m_stage == stage)
20246 {
20247 const GLchar* array = "";
20248 size_t position = 0;
20249 const GLchar* var_definition = 0;
20250
20251 switch (test_case.m_qualifier)
20252 {
20253 case BUFFER:
20254 var_definition = buffer_var_definition;
20255 break;
20256 case OFFSET:
20257 var_definition = offset_var_definition;
20258 break;
20259 case STRIDE:
20260 var_definition = stride_var_definition;
20261 break;
20262 default:
20263 TCU_FAIL("Invalid enum");
20264 }
20265
20266 switch (stage)
20267 {
20268 case Utils::Shader::FRAGMENT:
20269 source = fs_tested;
20270 break;
20271 case Utils::Shader::GEOMETRY:
20272 source = gs_tested;
20273 array = "[]";
20274 break;
20275 case Utils::Shader::TESS_CTRL:
20276 source = tcs_tested;
20277 array = "[]";
20278 break;
20279 case Utils::Shader::TESS_EVAL:
20280 source = tes_tested;
20281 array = "[]";
20282 break;
20283 case Utils::Shader::VERTEX:
20284 source = vs_tested;
20285 break;
20286 default:
20287 TCU_FAIL("Invalid enum");
20288 }
20289
20290 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
20291 position = 0;
20292 Utils::replaceToken("ARRAY", position, array, source);
20293 }
20294 else
20295 {
20296 switch (stage)
20297 {
20298 case Utils::Shader::FRAGMENT:
20299 source = fs;
20300 break;
20301 case Utils::Shader::GEOMETRY:
20302 source = gs;
20303 break;
20304 case Utils::Shader::TESS_CTRL:
20305 source = tcs;
20306 break;
20307 case Utils::Shader::TESS_EVAL:
20308 source = tes;
20309 break;
20310 case Utils::Shader::VERTEX:
20311 source = vs;
20312 break;
20313 default:
20314 TCU_FAIL("Invalid enum");
20315 }
20316 }
20317
20318 return source;
20319 }
20320
20321 /** Get description of test case
20322 *
20323 * @param test_case_index Index of test case
20324 *
20325 * @return Test case description
20326 **/
20327 std::string XFBInputTest::getTestCaseName(GLuint test_case_index)
20328 {
20329 std::stringstream stream;
20330 testCase& test_case = m_test_cases[test_case_index];
20331
20332 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", qualifier: ";
20333
20334 switch (test_case.m_qualifier)
20335 {
20336 case BUFFER:
20337 stream << "xfb_buffer";
20338 break;
20339 case OFFSET:
20340 stream << "xfb_offset";
20341 break;
20342 case STRIDE:
20343 stream << "xfb_stride";
20344 break;
20345 default:
20346 TCU_FAIL("Invalid enum");
20347 }
20348
20349 return stream.str();
20350 }
20351
20352 /** Get number of test cases
20353 *
20354 * @return Number of test cases
20355 **/
20356 GLuint XFBInputTest::getTestCaseNumber()
20357 {
20358 return static_cast<GLuint>(m_test_cases.size());
20359 }
20360
20361 /** Selects if "compute" stage is relevant for test
20362 *
20363 * @param ignored
20364 *
20365 * @return false
20366 **/
20367 bool XFBInputTest::isComputeRelevant(GLuint /* test_case_index */)
20368 {
20369 return false;
20370 }
20371
20372 /** Prepare all test cases
20373 *
20374 **/
20375 void XFBInputTest::testInit()
20376 {
20377 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
20378 {
20379 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
20380 {
20381 if (Utils::Shader::COMPUTE == stage)
20382 {
20383 continue;
20384 }
20385
20386 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
20387
20388 m_test_cases.push_back(test_case);
20389 }
20390 }
20391 }
20392
20393 /* Constants used by XFBAllStagesTest */
20394 const GLuint XFBAllStagesTest::m_gs_index = 3;
20395
20396 /** Constructor
20397 *
20398 * @param context Test context
20399 **/
20400 XFBAllStagesTest::XFBAllStagesTest(deqp::Context& context)
20401 : BufferTestBase(context, "xfb_all_stages",
20402 "Test verifies that only last stage in vertex processing can output to transform feedback")
20403 {
20404 /* Nothing to be done here */
20405 }
20406
20407 /** Get descriptors of buffers necessary for test
20408 *
20409 * @param ignored
20410 * @param out_descriptors Descriptors of buffers used by test
20411 **/
20412 void XFBAllStagesTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
20413 bufferDescriptor::Vector& out_descriptors)
20414 {
20415 static const GLuint n_stages = 4;
20416 const Utils::Type& vec4 = Utils::Type::vec4;
20417
20418 /* Data */
20419 tcu::Vec4 sum;
20420
20421 /* Test uses single uniform and xfb per stage + uniform for fragment shader */
20422 out_descriptors.resize(n_stages * 2 + 1);
20423
20424 /* */
20425 for (GLuint i = 0; i < n_stages; ++i)
20426 {
20427 /* Get references */
20428 bufferDescriptor& uniform = out_descriptors[i + 0];
20429 bufferDescriptor& xfb = out_descriptors[i + n_stages];
20430
20431 /* Index */
20432 uniform.m_index = i;
20433 xfb.m_index = i;
20434
20435 /* Target */
20436 uniform.m_target = Utils::Buffer::Uniform;
20437 xfb.m_target = Utils::Buffer::Transform_feedback;
20438
20439 /* Data */
20440 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
20441
20442 sum += var;
20443
20444 uniform.m_initial_data.resize(vec4.GetSize());
20445 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
20446
20447 xfb.m_initial_data = vec4.GenerateDataPacked();
20448
20449 if (m_gs_index != i)
20450 {
20451 xfb.m_expected_data = xfb.m_initial_data;
20452 }
20453 else
20454 {
20455 xfb.m_expected_data.resize(vec4.GetSize());
20456 memcpy(&xfb.m_expected_data[0], sum.getPtr(), vec4.GetSize());
20457 }
20458 }
20459
20460 /* FS */
20461 {
20462 /* Get reference */
20463 bufferDescriptor& uniform = out_descriptors[n_stages * 2];
20464
20465 /* Index */
20466 uniform.m_index = n_stages;
20467
20468 /* Target */
20469 uniform.m_target = Utils::Buffer::Uniform;
20470
20471 /* Data */
20472 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
20473
20474 uniform.m_initial_data.resize(vec4.GetSize());
20475 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
20476 }
20477 }
20478
20479 /** Get body of main function for given shader stage
20480 *
20481 * @param ignored
20482 * @param stage Shader stage
20483 * @param out_assignments Set to empty
20484 * @param out_calculations Set to empty
20485 **/
20486 void XFBAllStagesTest::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20487 std::string& out_assignments, std::string& out_calculations)
20488 {
20489 out_calculations = "";
20490
20491 static const GLchar* vs = " vs_tcs = uni_vs;\n";
20492 static const GLchar* tcs = " tcs_tes[gl_InvocationID] = uni_tcs + vs_tcs[gl_InvocationID];\n";
20493 static const GLchar* tes = " tes_gs = uni_tes + tcs_tes[0];\n";
20494 static const GLchar* gs = " gs_fs = uni_gs + tes_gs[0];\n";
20495 static const GLchar* fs = " fs_out = uni_fs + gs_fs;\n";
20496
20497 const GLchar* assignments = 0;
20498 switch (stage)
20499 {
20500 case Utils::Shader::FRAGMENT:
20501 assignments = fs;
20502 break;
20503 case Utils::Shader::GEOMETRY:
20504 assignments = gs;
20505 break;
20506 case Utils::Shader::TESS_CTRL:
20507 assignments = tcs;
20508 break;
20509 case Utils::Shader::TESS_EVAL:
20510 assignments = tes;
20511 break;
20512 case Utils::Shader::VERTEX:
20513 assignments = vs;
20514 break;
20515 default:
20516 TCU_FAIL("Invalid enum");
20517 }
20518
20519 out_assignments = assignments;
20520 }
20521
20522 /** Get interface of shader
20523 *
20524 * @param ignored
20525 * @param stage Shader stage
20526 * @param out_interface Set to ""
20527 **/
20528 void XFBAllStagesTest::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20529 std::string& out_interface)
20530 {
20531 static const GLchar* vs = "layout(xfb_buffer = 0, xfb_offset = 0) out vec4 vs_tcs;\n"
20532 "layout(binding = 0) uniform vs_block {\n"
20533 " vec4 uni_vs;\n"
20534 "};\n";
20535 static const GLchar* tcs = " in vec4 vs_tcs[];\n"
20536 "layout(xfb_buffer = 1, xfb_offset = 0) out vec4 tcs_tes[1];\n"
20537 "layout(binding = 1) uniform tcs_block {\n"
20538 " vec4 uni_tcs;\n"
20539 "};\n";
20540 static const GLchar* tes = " in vec4 tcs_tes[];\n"
20541 "layout(xfb_buffer = 2, xfb_offset = 0) out vec4 tes_gs;\n"
20542 "layout(binding = 2) uniform tes_block {\n"
20543 " vec4 uni_tes;\n"
20544 "};\n";
20545 static const GLchar* gs = " in vec4 tes_gs[];\n"
20546 "layout(xfb_buffer = 3, xfb_offset = 0) out vec4 gs_fs;\n"
20547 "layout(binding = 3) uniform gs_block {\n"
20548 " vec4 uni_gs;\n"
20549 "};\n";
20550 static const GLchar* fs = " in vec4 gs_fs;\n"
20551 " out vec4 fs_out;\n"
20552 "layout(binding = 4) uniform fs_block {\n"
20553 " vec4 uni_fs;\n"
20554 "};\n";
20555
20556 const GLchar* interface = 0;
20557 switch (stage)
20558 {
20559 case Utils::Shader::FRAGMENT:
20560 interface = fs;
20561 break;
20562 case Utils::Shader::GEOMETRY:
20563 interface = gs;
20564 break;
20565 case Utils::Shader::TESS_CTRL:
20566 interface = tcs;
20567 break;
20568 case Utils::Shader::TESS_EVAL:
20569 interface = tes;
20570 break;
20571 case Utils::Shader::VERTEX:
20572 interface = vs;
20573 break;
20574 default:
20575 TCU_FAIL("Invalid enum");
20576 }
20577
20578 out_interface = interface;
20579 }
20580
20581 /* Constants used by XFBStrideOfEmptyListTest */
20582 const GLuint XFBStrideOfEmptyListTest::m_stride = 64;
20583
20584 /** Constructor
20585 *
20586 * @param context Test context
20587 **/
20588 XFBStrideOfEmptyListTest::XFBStrideOfEmptyListTest(deqp::Context& context)
20589 : BufferTestBase(
20590 context, "xfb_stride_of_empty_list",
20591 "Test verifies correct behavior when xfb_stride qualifier is specified but no xfb_offset is specified")
20592 {
20593 /* Nothing to be done here */
20594 }
20595
20596 /** Execute drawArrays for single vertex
20597 *
20598 * @param test_case_index Index of test case
20599 *
20600 * @return true if proper error is reported
20601 **/
20602 bool XFBStrideOfEmptyListTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20603 {
20604 const Functions& gl = m_context.getRenderContext().getFunctions();
20605 bool result = true;
20606
20607 /* Draw */
20608 gl.disable(GL_RASTERIZER_DISCARD);
20609 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20610
20611 gl.beginTransformFeedback(GL_POINTS);
20612 GLenum error = gl.getError();
20613 switch (test_case_index)
20614 {
20615 case VALID:
20616 if (GL_NO_ERROR != error)
20617 {
20618 gl.endTransformFeedback();
20619 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20620 }
20621
20622 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20623 error = gl.getError();
20624
20625 gl.endTransformFeedback();
20626 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20627 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20628
20629 break;
20630
20631 case FIRST_MISSING:
20632 if (GL_NO_ERROR == error)
20633 {
20634 gl.endTransformFeedback();
20635 }
20636
20637 if (GL_INVALID_OPERATION != error)
20638 {
20639 m_context.getTestContext().getLog()
20640 << tcu::TestLog::Message << "XFB at index 0, that is written by GS, is missing. It was expected that "
20641 "INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20642 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20643
20644 result = false;
20645 }
20646
20647 break;
20648
20649 case SECOND_MISSING:
20650 if (GL_NO_ERROR != error)
20651 {
20652 gl.endTransformFeedback();
20653 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20654 }
20655
20656 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20657 error = gl.getError();
20658
20659 gl.endTransformFeedback();
20660 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20661 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20662
20663 break;
20664 }
20665
20666 /* Done */
20667 return result;
20668 }
20669
20670 /** Get descriptors of buffers necessary for test
20671 *
20672 * @param test_case_index Index of test case
20673 * @param out_descriptors Descriptors of buffers used by test
20674 **/
20675 void XFBStrideOfEmptyListTest::getBufferDescriptors(glw::GLuint test_case_index,
20676 bufferDescriptor::Vector& out_descriptors)
20677 {
20678 switch (test_case_index)
20679 {
20680 case VALID:
20681 {
20682 /* Test needs single uniform and two xfbs */
20683 out_descriptors.resize(3);
20684
20685 /* Get references */
20686 bufferDescriptor& uniform = out_descriptors[0];
20687 bufferDescriptor& xfb_0 = out_descriptors[1];
20688 bufferDescriptor& xfb_1 = out_descriptors[2];
20689
20690 /* Index */
20691 uniform.m_index = 0;
20692 xfb_0.m_index = 0;
20693 xfb_1.m_index = 1;
20694
20695 /* Target */
20696 uniform.m_target = Utils::Buffer::Uniform;
20697 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20698 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20699
20700 /* Data */
20701 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20702
20703 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20704 xfb_0.m_expected_data = uniform.m_initial_data;
20705
20706 /* Data, contents are the same as no modification is expected */
20707 xfb_1.m_initial_data.resize(m_stride);
20708 xfb_1.m_expected_data.resize(m_stride);
20709
20710 for (GLuint i = 0; i < m_stride; ++i)
20711 {
20712 xfb_1.m_initial_data[0] = (glw::GLubyte)i;
20713 xfb_1.m_expected_data[0] = (glw::GLubyte)i;
20714 }
20715 }
20716
20717 break;
20718
20719 case FIRST_MISSING:
20720 {
20721 /* Test needs single uniform and two xfbs */
20722 out_descriptors.resize(2);
20723
20724 /* Get references */
20725 bufferDescriptor& uniform = out_descriptors[0];
20726 bufferDescriptor& xfb_1 = out_descriptors[1];
20727
20728 /* Index */
20729 uniform.m_index = 0;
20730 xfb_1.m_index = 1;
20731
20732 /* Target */
20733 uniform.m_target = Utils::Buffer::Uniform;
20734 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20735
20736 /* Data */
20737 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20738
20739 /* Draw call will not be executed, contents does not matter */
20740 xfb_1.m_initial_data.resize(m_stride);
20741 }
20742
20743 break;
20744
20745 case SECOND_MISSING:
20746 {
20747 /* Test needs single uniform and two xfbs */
20748 out_descriptors.resize(2);
20749
20750 /* Get references */
20751 bufferDescriptor& uniform = out_descriptors[0];
20752 bufferDescriptor& xfb_0 = out_descriptors[1];
20753
20754 /* Index */
20755 uniform.m_index = 0;
20756 xfb_0.m_index = 0;
20757
20758 /* Target */
20759 uniform.m_target = Utils::Buffer::Uniform;
20760 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20761
20762 /* Data */
20763 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20764
20765 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20766 xfb_0.m_expected_data = uniform.m_initial_data;
20767 }
20768
20769 break;
20770 }
20771 }
20772
20773 /** Get body of main function for given shader stage
20774 *
20775 * @param ignored
20776 * @param stage Shader stage
20777 * @param out_assignments Set to empty
20778 * @param out_calculations Set to empty
20779 **/
20780 void XFBStrideOfEmptyListTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20781 std::string& out_assignments, std::string& out_calculations)
20782 {
20783 out_calculations = "";
20784
20785 static const GLchar* gs = " gs_fs = uni_gs;\n";
20786 static const GLchar* fs = " fs_out = vec4(gs_fs);\n";
20787
20788 const GLchar* assignments = "";
20789 switch (stage)
20790 {
20791 case Utils::Shader::FRAGMENT:
20792 assignments = fs;
20793 break;
20794 case Utils::Shader::GEOMETRY:
20795 assignments = gs;
20796 break;
20797 default:
20798 break;
20799 }
20800
20801 out_assignments = assignments;
20802 }
20803
20804 /** Get interface of shader
20805 *
20806 * @param ignored
20807 * @param stage Shader stage
20808 * @param out_interface Set to ""
20809 **/
20810 void XFBStrideOfEmptyListTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20811 std::string& out_interface)
20812 {
20813 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out vec4 gs_fs;\n"
20814 "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
20815 "\n"
20816 "layout (binding = 0) uniform gs_block {\n"
20817 " vec4 uni_gs;\n"
20818 "};\n";
20819 static const GLchar* fs = "in vec4 gs_fs;\n"
20820 "out vec4 fs_out;\n";
20821
20822 switch (stage)
20823 {
20824 case Utils::Shader::FRAGMENT:
20825 out_interface = fs;
20826 break;
20827 case Utils::Shader::GEOMETRY:
20828 out_interface = gs;
20829 break;
20830 default:
20831 out_interface = "";
20832 return;
20833 }
20834 }
20835
20836 /** Returns buffer details in human readable form.
20837 *
20838 * @param test_case_index Index of test case
20839 *
20840 * @return Case description
20841 **/
20842 std::string XFBStrideOfEmptyListTest::getTestCaseName(GLuint test_case_index)
20843 {
20844 std::string result;
20845
20846 switch (test_case_index)
20847 {
20848 case VALID:
20849 result = "Valid case";
20850 break;
20851 case FIRST_MISSING:
20852 result = "Missing xfb at index 0";
20853 break;
20854 case SECOND_MISSING:
20855 result = "Missing xfb at index 1";
20856 break;
20857 default:
20858 TCU_FAIL("Invalid enum");
20859 }
20860
20861 return result;
20862 }
20863
20864 /** Get number of test cases
20865 *
20866 * @return 3
20867 **/
20868 GLuint XFBStrideOfEmptyListTest::getTestCaseNumber()
20869 {
20870 return 3;
20871 }
20872
20873 /* Constants used by XFBStrideOfEmptyListTest */
20874 const GLuint XFBStrideOfEmptyListAndAPITest::m_stride = 64;
20875
20876 /** Constructor
20877 *
20878 * @param context Test context
20879 **/
20880 XFBStrideOfEmptyListAndAPITest::XFBStrideOfEmptyListAndAPITest(deqp::Context& context)
20881 : BufferTestBase(context, "xfb_stride_of_empty_list_and_api",
20882 "Test verifies that xfb_stride qualifier is not overriden by API")
20883 {
20884 /* Nothing to be done here */
20885 }
20886
20887 /** Execute drawArrays for single vertex
20888 *
20889 * @param test_case_index Index of test case
20890 *
20891 * @return true if proper error is reported
20892 **/
20893 bool XFBStrideOfEmptyListAndAPITest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20894 {
20895 const Functions& gl = m_context.getRenderContext().getFunctions();
20896 bool result = true;
20897
20898 /* Draw */
20899 gl.disable(GL_RASTERIZER_DISCARD);
20900 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20901
20902 gl.beginTransformFeedback(GL_POINTS);
20903 GLenum error = gl.getError();
20904 switch (test_case_index)
20905 {
20906 case VALID:
20907 if (GL_NO_ERROR != error)
20908 {
20909 gl.endTransformFeedback();
20910 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20911 }
20912
20913 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20914 error = gl.getError();
20915
20916 gl.endTransformFeedback();
20917 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20918 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20919
20920 break;
20921
20922 case FIRST_MISSING:
20923 if (GL_NO_ERROR != error)
20924 {
20925 gl.endTransformFeedback();
20926 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20927 }
20928
20929 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20930 error = gl.getError();
20931
20932 gl.endTransformFeedback();
20933 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20934 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20935
20936 break;
20937
20938 case SECOND_MISSING:
20939 if (GL_NO_ERROR == error)
20940 {
20941 gl.endTransformFeedback();
20942 }
20943
20944 if (GL_INVALID_OPERATION != error)
20945 {
20946 m_context.getTestContext().getLog()
20947 << tcu::TestLog::Message << "XFB at index 1, that is declared as empty, is missing. It was expected "
20948 "that INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20949 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20950
20951 result = false;
20952 }
20953
20954 break;
20955 }
20956
20957 /* Done */
20958 return result;
20959 }
20960
20961 /** Get descriptors of buffers necessary for test
20962 *
20963 * @param test_case_index Index of test case
20964 * @param out_descriptors Descriptors of buffers used by test
20965 **/
20966 void XFBStrideOfEmptyListAndAPITest::getBufferDescriptors(glw::GLuint test_case_index,
20967 bufferDescriptor::Vector& out_descriptors)
20968 {
20969 switch (test_case_index)
20970 {
20971 case VALID:
20972 {
20973 /* Test needs single uniform and two xfbs */
20974 out_descriptors.resize(3);
20975
20976 /* Get references */
20977 bufferDescriptor& uniform = out_descriptors[0];
20978 bufferDescriptor& xfb_0 = out_descriptors[1];
20979 bufferDescriptor& xfb_1 = out_descriptors[2];
20980
20981 /* Index */
20982 uniform.m_index = 0;
20983 xfb_0.m_index = 0;
20984 xfb_1.m_index = 1;
20985
20986 /* Target */
20987 uniform.m_target = Utils::Buffer::Uniform;
20988 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20989 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20990
20991 /* Data */
20992 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20993
20994 /* Data, contents are the same as no modification is expected */
20995 xfb_0.m_initial_data.resize(m_stride);
20996 xfb_0.m_expected_data.resize(m_stride);
20997
20998 for (GLuint i = 0; i < m_stride; ++i)
20999 {
21000 xfb_0.m_initial_data[0] = (glw::GLubyte)i;
21001 xfb_0.m_expected_data[0] = (glw::GLubyte)i;
21002 }
21003
21004 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21005 xfb_1.m_expected_data = uniform.m_initial_data;
21006 }
21007
21008 break;
21009
21010 case FIRST_MISSING:
21011 {
21012 /* Test needs single uniform and two xfbs */
21013 out_descriptors.resize(2);
21014
21015 /* Get references */
21016 bufferDescriptor& uniform = out_descriptors[0];
21017 bufferDescriptor& xfb_1 = out_descriptors[1];
21018
21019 /* Index */
21020 uniform.m_index = 0;
21021 xfb_1.m_index = 1;
21022
21023 /* Target */
21024 uniform.m_target = Utils::Buffer::Uniform;
21025 xfb_1.m_target = Utils::Buffer::Transform_feedback;
21026
21027 /* Data */
21028 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21029
21030 /* Data, contents are the same as no modification is expected */
21031 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21032 xfb_1.m_expected_data = uniform.m_initial_data;
21033 }
21034
21035 break;
21036
21037 case SECOND_MISSING:
21038 {
21039 /* Test needs single uniform and two xfbs */
21040 out_descriptors.resize(2);
21041
21042 /* Get references */
21043 bufferDescriptor& uniform = out_descriptors[0];
21044 bufferDescriptor& xfb_0 = out_descriptors[1];
21045
21046 /* Index */
21047 uniform.m_index = 0;
21048 xfb_0.m_index = 0;
21049
21050 /* Target */
21051 uniform.m_target = Utils::Buffer::Uniform;
21052 xfb_0.m_target = Utils::Buffer::Transform_feedback;
21053
21054 /* Data */
21055 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21056
21057 /* Draw call will not be executed, contents does not matter */
21058 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21059 }
21060
21061 break;
21062 }
21063 }
21064
21065 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
21066 *
21067 * @param ignored
21068 * @param captured_varyings Vector of varying names to be captured
21069 **/
21070 void XFBStrideOfEmptyListAndAPITest::getCapturedVaryings(glw::GLuint /* test_case_index */,
21071 Utils::Program::NameVector& captured_varyings,
21072 GLint* xfb_components)
21073 {
21074 captured_varyings.push_back("gs_fs1");
21075 captured_varyings.push_back("gs_fs2");
21076 *xfb_components = 4;
21077 }
21078
21079 /** Get body of main function for given shader stage
21080 *
21081 * @param ignored
21082 * @param stage Shader stage
21083 * @param out_assignments Set to empty
21084 * @param out_calculations Set to empty
21085 **/
21086 void XFBStrideOfEmptyListAndAPITest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21087 std::string& out_assignments, std::string& out_calculations)
21088 {
21089 out_calculations = "";
21090
21091 static const GLchar* gs = " gs_fs1 = -uni_gs;\n"
21092 " gs_fs2 = uni_gs;\n";
21093 static const GLchar* fs = " fs_out = vec4(gs_fs2);\n";
21094
21095 const GLchar* assignments = "";
21096 switch (stage)
21097 {
21098 case Utils::Shader::FRAGMENT:
21099 assignments = fs;
21100 break;
21101 case Utils::Shader::GEOMETRY:
21102 assignments = gs;
21103 break;
21104 default:
21105 break;
21106 }
21107
21108 out_assignments = assignments;
21109 }
21110
21111 /** Get interface of shader
21112 *
21113 * @param ignored
21114 * @param stage Shader stage
21115 * @param out_interface Set to ""
21116 **/
21117 void XFBStrideOfEmptyListAndAPITest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21118 std::string& out_interface)
21119 {
21120 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_stride = 64) out vec4 gs_fs1;\n"
21121 "layout (xfb_buffer = 1, xfb_offset = 0) out vec4 gs_fs2;\n"
21122 "\n"
21123 "layout(binding = 0) uniform gs_block {\n"
21124 " vec4 uni_gs;\n"
21125 "};\n";
21126 static const GLchar* fs = "in vec4 gs_fs2;\n"
21127 "out vec4 fs_out;\n";
21128
21129 switch (stage)
21130 {
21131 case Utils::Shader::FRAGMENT:
21132 out_interface = fs;
21133 break;
21134 case Utils::Shader::GEOMETRY:
21135 out_interface = gs;
21136 break;
21137 default:
21138 out_interface = "";
21139 return;
21140 }
21141 }
21142
21143 /** Returns buffer details in human readable form.
21144 *
21145 * @param test_case_index Index of test case
21146 *
21147 * @return Case description
21148 **/
21149 std::string XFBStrideOfEmptyListAndAPITest::getTestCaseName(GLuint test_case_index)
21150 {
21151 std::string result;
21152
21153 switch (test_case_index)
21154 {
21155 case VALID:
21156 result = "Valid case";
21157 break;
21158 case FIRST_MISSING:
21159 result = "Missing xfb at index 0";
21160 break;
21161 case SECOND_MISSING:
21162 result = "Missing xfb at index 1";
21163 break;
21164 default:
21165 TCU_FAIL("Invalid enum");
21166 }
21167
21168 return result;
21169 }
21170
21171 /** Get number of test cases
21172 *
21173 * @return 2
21174 **/
21175 GLuint XFBStrideOfEmptyListAndAPITest::getTestCaseNumber()
21176 {
21177 return 3;
21178 }
21179
21180 /** Constructor
21181 *
21182 * @param context Test framework context
21183 **/
21184 XFBTooSmallStrideTest::XFBTooSmallStrideTest(deqp::Context& context)
21185 : NegativeTestBase(context, "xfb_too_small_stride",
21186 "Test verifies that compiler reports error when xfb_stride sets not enough space")
21187 {
21188 }
21189
21190 /** Source for given test case and stage
21191 *
21192 * @param test_case_index Index of test case
21193 * @param stage Shader stage
21194 *
21195 * @return Shader source
21196 **/
21197 std::string XFBTooSmallStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21198 {
21199 #if DEBUG_NEG_REMOVE_ERROR
21200 static const GLchar* array_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 32 */ ) out;\n"
21201 #else
21202 static const GLchar* array_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
21203 #endif /* DEBUG_NEG_REMOVE_ERROR */
21204 "\n"
21205 "layout (xfb_offset = 16) out vec4 gohan[4];\n";
21206 #if DEBUG_NEG_REMOVE_ERROR
21207 static const GLchar* block_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 32 */ ) out;\n"
21208 #else
21209 static const GLchar* block_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
21210 #endif /* DEBUG_NEG_REMOVE_ERROR */
21211 "\n"
21212 "layout (xfb_offset = 0) out Goku {\n"
21213 " vec4 gohan;\n"
21214 " vec4 goten;\n"
21215 " vec4 chichi;\n"
21216 "} goku;\n";
21217 #if DEBUG_NEG_REMOVE_ERROR
21218 static const GLchar* offset_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 40 */ ) out;\n"
21219 #else
21220 static const GLchar* offset_var_definition = "layout (xfb_buffer = 0, xfb_stride = 40) out;\n"
21221 #endif /* DEBUG_NEG_REMOVE_ERROR */
21222 "\n"
21223 "layout (xfb_offset = 32) out vec4 gohan;\n";
21224 // 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;"
21225 // To make the shader failed to compile, change xfb_stride to a value that is smaller than 32
21226 #if DEBUG_NEG_REMOVE_ERROR
21227 static const GLchar* stride_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 28 */ ) out;\n"
21228 "\n"
21229 "layout (xfb_offset = 16 /*, xfb_stride = 28 */ ) out vec4 gohan;\n";
21230 #else
21231 static const GLchar* stride_var_definition = "layout (xfb_buffer = 0, xfb_stride = 28) out;\n"
21232 "\n"
21233 "layout (xfb_offset = 16, xfb_stride = 28) out vec4 gohan;\n";
21234 #endif /* DEBUG_NEG_REMOVE_ERROR */
21235 static const GLchar* array_use = " gohan[0] = result / 2;\n"
21236 " gohan[1] = result / 4;\n"
21237 " gohan[2] = result / 6;\n"
21238 " gohan[3] = result / 8;\n";
21239 static const GLchar* block_use = " goku.gohan = result / 2;\n"
21240 " goku.goten = result / 4;\n"
21241 " goku.chichi = result / 6;\n";
21242 static const GLchar* output_use = "gohan = result / 4;\n";
21243 static const GLchar* fs = "#version 430 core\n"
21244 "#extension GL_ARB_enhanced_layouts : require\n"
21245 "\n"
21246 "in vec4 any_fs;\n"
21247 "out vec4 fs_out;\n"
21248 "\n"
21249 "void main()\n"
21250 "{\n"
21251 " fs_out = any_fs;\n"
21252 "}\n"
21253 "\n";
21254 static const GLchar* gs_tested = "#version 430 core\n"
21255 "#extension GL_ARB_enhanced_layouts : require\n"
21256 "\n"
21257 "layout(points) in;\n"
21258 "layout(triangle_strip, max_vertices = 4) out;\n"
21259 "\n"
21260 "VAR_DEFINITION"
21261 "\n"
21262 "in vec4 vs_any[];\n"
21263 "out vec4 any_fs;\n"
21264 "\n"
21265 "void main()\n"
21266 "{\n"
21267 " vec4 result = vs_any[0];\n"
21268 "\n"
21269 "VARIABLE_USE"
21270 "\n"
21271 " any_fs = result;\n"
21272 " gl_Position = vec4(-1, -1, 0, 1);\n"
21273 " EmitVertex();\n"
21274 " any_fs = result;\n"
21275 " gl_Position = vec4(-1, 1, 0, 1);\n"
21276 " EmitVertex();\n"
21277 " any_fs = result;\n"
21278 " gl_Position = vec4(1, -1, 0, 1);\n"
21279 " EmitVertex();\n"
21280 " any_fs = result;\n"
21281 " gl_Position = vec4(1, 1, 0, 1);\n"
21282 " EmitVertex();\n"
21283 "}\n"
21284 "\n";
21285 static const GLchar* tcs = "#version 430 core\n"
21286 "#extension GL_ARB_enhanced_layouts : require\n"
21287 "\n"
21288 "layout(vertices = 1) out;\n"
21289 "\n"
21290 "in vec4 vs_any[];\n"
21291 "out vec4 tcs_tes[];\n"
21292 "\n"
21293 "void main()\n"
21294 "{\n"
21295 "\n"
21296 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
21297 "\n"
21298 " gl_TessLevelOuter[0] = 1.0;\n"
21299 " gl_TessLevelOuter[1] = 1.0;\n"
21300 " gl_TessLevelOuter[2] = 1.0;\n"
21301 " gl_TessLevelOuter[3] = 1.0;\n"
21302 " gl_TessLevelInner[0] = 1.0;\n"
21303 " gl_TessLevelInner[1] = 1.0;\n"
21304 "}\n"
21305 "\n";
21306 static const GLchar* tes_tested = "#version 430 core\n"
21307 "#extension GL_ARB_enhanced_layouts : require\n"
21308 "\n"
21309 "layout(isolines, point_mode) in;\n"
21310 "\n"
21311 "VAR_DEFINITION"
21312 "\n"
21313 "in vec4 tcs_tes[];\n"
21314 "out vec4 any_fs;\n"
21315 "\n"
21316 "void main()\n"
21317 "{\n"
21318 " vec4 result = tcs_tes[0];\n"
21319 "\n"
21320 "VARIABLE_USE"
21321 "\n"
21322 " any_fs += result;\n"
21323 "}\n"
21324 "\n";
21325 static const GLchar* vs = "#version 430 core\n"
21326 "#extension GL_ARB_enhanced_layouts : require\n"
21327 "\n"
21328 "in vec4 in_vs;\n"
21329 "out vec4 vs_any;\n"
21330 "\n"
21331 "void main()\n"
21332 "{\n"
21333 " vs_any = in_vs;\n"
21334 "}\n"
21335 "\n";
21336 static const GLchar* vs_tested = "#version 430 core\n"
21337 "#extension GL_ARB_enhanced_layouts : require\n"
21338 "\n"
21339 "VAR_DEFINITION"
21340 "\n"
21341 "in vec4 in_vs;\n"
21342 "out vec4 any_fs;\n"
21343 "\n"
21344 "void main()\n"
21345 "{\n"
21346 " vec4 result = in_vs;\n"
21347 "\n"
21348 "VARIABLE_USE"
21349 "\n"
21350 " any_fs += result;\n"
21351 "}\n"
21352 "\n";
21353
21354 std::string source;
21355 testCase& test_case = m_test_cases[test_case_index];
21356
21357 if (test_case.m_stage == stage)
21358 {
21359 size_t position = 0;
21360 const GLchar* var_definition = 0;
21361 const GLchar* var_use = 0;
21362
21363 switch (test_case.m_case)
21364 {
21365 case OFFSET:
21366 var_definition = offset_var_definition;
21367 var_use = output_use;
21368 break;
21369 case STRIDE:
21370 var_definition = stride_var_definition;
21371 var_use = output_use;
21372 break;
21373 case BLOCK:
21374 var_definition = block_var_definition;
21375 var_use = block_use;
21376 break;
21377 case ARRAY:
21378 var_definition = array_var_definition;
21379 var_use = array_use;
21380 break;
21381 default:
21382 TCU_FAIL("Invalid enum");
21383 }
21384
21385 switch (stage)
21386 {
21387 case Utils::Shader::GEOMETRY:
21388 source = gs_tested;
21389 break;
21390 case Utils::Shader::TESS_EVAL:
21391 source = tes_tested;
21392 break;
21393 case Utils::Shader::VERTEX:
21394 source = vs_tested;
21395 break;
21396 default:
21397 TCU_FAIL("Invalid enum");
21398 }
21399
21400 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21401 position = 0;
21402 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21403 }
21404 else
21405 {
21406 switch (test_case.m_stage)
21407 {
21408 case Utils::Shader::GEOMETRY:
21409 switch (stage)
21410 {
21411 case Utils::Shader::FRAGMENT:
21412 source = fs;
21413 break;
21414 case Utils::Shader::VERTEX:
21415 source = vs;
21416 break;
21417 default:
21418 source = "";
21419 }
21420 break;
21421 case Utils::Shader::TESS_EVAL:
21422 switch (stage)
21423 {
21424 case Utils::Shader::FRAGMENT:
21425 source = fs;
21426 break;
21427 case Utils::Shader::TESS_CTRL:
21428 source = tcs;
21429 break;
21430 case Utils::Shader::VERTEX:
21431 source = vs;
21432 break;
21433 default:
21434 source = "";
21435 }
21436 break;
21437 case Utils::Shader::VERTEX:
21438 switch (stage)
21439 {
21440 case Utils::Shader::FRAGMENT:
21441 source = fs;
21442 break;
21443 default:
21444 source = "";
21445 }
21446 break;
21447 default:
21448 TCU_FAIL("Invalid enum");
21449 }
21450 }
21451
21452 return source;
21453 }
21454
21455 /** Get description of test case
21456 *
21457 * @param test_case_index Index of test case
21458 *
21459 * @return Test case description
21460 **/
21461 std::string XFBTooSmallStrideTest::getTestCaseName(GLuint test_case_index)
21462 {
21463 std::stringstream stream;
21464 testCase& test_case = m_test_cases[test_case_index];
21465
21466 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
21467
21468 switch (test_case.m_case)
21469 {
21470 case OFFSET:
21471 stream << "buffer stride: 40, vec4 offset: 32";
21472 break;
21473 case STRIDE:
21474 stream << "buffer stride: 32, vec4 off 16 stride: 32";
21475 break;
21476 case BLOCK:
21477 stream << "buffer stride: 32, block 3xvec4 offset 0";
21478 break;
21479 case ARRAY:
21480 stream << "buffer stride: 32, vec4[4] offset 16";
21481 break;
21482 default:
21483 TCU_FAIL("Invalid enum");
21484 }
21485
21486 return stream.str();
21487 }
21488
21489 /** Get number of test cases
21490 *
21491 * @return Number of test cases
21492 **/
21493 GLuint XFBTooSmallStrideTest::getTestCaseNumber()
21494 {
21495 return static_cast<GLuint>(m_test_cases.size());
21496 }
21497
21498 /** Selects if "compute" stage is relevant for test
21499 *
21500 * @param ignored
21501 *
21502 * @return false
21503 **/
21504 bool XFBTooSmallStrideTest::isComputeRelevant(GLuint /* test_case_index */)
21505 {
21506 return false;
21507 }
21508
21509 /** Prepare all test cases
21510 *
21511 **/
21512 void XFBTooSmallStrideTest::testInit()
21513 {
21514 for (GLuint c = 0; c < CASE_MAX; ++c)
21515 {
21516 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21517 {
21518 /*
21519 It is invalid to define transform feedback output in TCS, according to spec:
21520 The data captured in transform feedback mode depends on the active programs on each of the shader stages.
21521 If a program is active for the geometry shader stage, transform feedback captures the vertices of each
21522 primitive emitted by the geometry shader. Otherwise, if a program is active for the tessellation evaluation
21523 shader stage, transform feedback captures each primitive produced by the tessellation primitive generator,
21524 whose vertices are processed by the tessellation evaluation shader. Otherwise, transform feedback captures
21525 each primitive processed by the vertex shader.
21526 */
21527 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21528 (Utils::Shader::FRAGMENT == stage))
21529 {
21530 continue;
21531 }
21532
21533 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
21534
21535 m_test_cases.push_back(test_case);
21536 }
21537 }
21538 }
21539
21540 /** Constructor
21541 *
21542 * @param context Test framework context
21543 **/
21544 XFBVariableStrideTest::XFBVariableStrideTest(deqp::Context& context)
21545 : NegativeTestBase(context, "xfb_variable_stride", "Test verifies that stride qualifier is respected")
21546 {
21547 }
21548
21549 /** Source for given test case and stage
21550 *
21551 * @param test_case_index Index of test case
21552 * @param stage Shader stage
21553 *
21554 * @return Shader source
21555 **/
21556 std::string XFBVariableStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21557 {
21558 static const GLchar* invalid_var_definition = "const uint type_size = SIZE;\n"
21559 "\n"
21560 #if DEBUG_NEG_REMOVE_ERROR
21561 "layout (xfb_stride = 2 * type_size) out;\n"
21562 #else
21563 "layout (xfb_stride = type_size) out;\n"
21564 #endif /* DEBUG_NEG_REMOVE_ERROR */
21565 "\n"
21566 "layout (xfb_offset = 0) out TYPE goku;\n"
21567 "layout (xfb_offset = type_size) out TYPE vegeta;\n";
21568 static const GLchar* valid_var_definition = "const uint type_size = SIZE;\n"
21569 "\n"
21570 "layout (xfb_stride = type_size) out;\n"
21571 "\n"
21572 "layout (xfb_offset = 0) out TYPE goku;\n";
21573 static const GLchar* invalid_use = " goku = TYPE(1);\n"
21574 " vegeta = TYPE(0);\n"
21575 " if (vec4(0) == result)\n"
21576 " {\n"
21577 " goku = TYPE(0);\n"
21578 " vegeta = TYPE(1);\n"
21579 " }\n";
21580 static const GLchar* valid_use = " goku = TYPE(1);\n"
21581 " if (vec4(0) == result)\n"
21582 " {\n"
21583 " goku = TYPE(0);\n"
21584 " }\n";
21585 static const GLchar* fs = "#version 430 core\n"
21586 "#extension GL_ARB_enhanced_layouts : require\n"
21587 "\n"
21588 "in vec4 any_fs;\n"
21589 "out vec4 fs_out;\n"
21590 "\n"
21591 "void main()\n"
21592 "{\n"
21593 " fs_out = any_fs;\n"
21594 "}\n"
21595 "\n";
21596 static const GLchar* gs_tested = "#version 430 core\n"
21597 "#extension GL_ARB_enhanced_layouts : require\n"
21598 "\n"
21599 "layout(points) in;\n"
21600 "layout(triangle_strip, max_vertices = 4) out;\n"
21601 "\n"
21602 "VAR_DEFINITION"
21603 "\n"
21604 "in vec4 vs_any[];\n"
21605 "out vec4 any_fs;\n"
21606 "\n"
21607 "void main()\n"
21608 "{\n"
21609 " vec4 result = vs_any[0];\n"
21610 "\n"
21611 "VARIABLE_USE"
21612 "\n"
21613 " any_fs = result;\n"
21614 " gl_Position = vec4(-1, -1, 0, 1);\n"
21615 " EmitVertex();\n"
21616 " any_fs = result;\n"
21617 " gl_Position = vec4(-1, 1, 0, 1);\n"
21618 " EmitVertex();\n"
21619 " any_fs = result;\n"
21620 " gl_Position = vec4(1, -1, 0, 1);\n"
21621 " EmitVertex();\n"
21622 " any_fs = result;\n"
21623 " gl_Position = vec4(1, 1, 0, 1);\n"
21624 " EmitVertex();\n"
21625 "}\n"
21626 "\n";
21627 static const GLchar* tcs = "#version 430 core\n"
21628 "#extension GL_ARB_enhanced_layouts : require\n"
21629 "\n"
21630 "layout(vertices = 1) out;\n"
21631 "\n"
21632 "in vec4 vs_any[];\n"
21633 "out vec4 tcs_tes[];\n"
21634 "\n"
21635 "void main()\n"
21636 "{\n"
21637 "\n"
21638 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
21639 "\n"
21640 " gl_TessLevelOuter[0] = 1.0;\n"
21641 " gl_TessLevelOuter[1] = 1.0;\n"
21642 " gl_TessLevelOuter[2] = 1.0;\n"
21643 " gl_TessLevelOuter[3] = 1.0;\n"
21644 " gl_TessLevelInner[0] = 1.0;\n"
21645 " gl_TessLevelInner[1] = 1.0;\n"
21646 "}\n"
21647 "\n";
21648 static const GLchar* tes_tested = "#version 430 core\n"
21649 "#extension GL_ARB_enhanced_layouts : require\n"
21650 "\n"
21651 "layout(isolines, point_mode) in;\n"
21652 "\n"
21653 "VAR_DEFINITION"
21654 "\n"
21655 "in vec4 tcs_tes[];\n"
21656 "out vec4 any_fs;\n"
21657 "\n"
21658 "void main()\n"
21659 "{\n"
21660 " vec4 result = tcs_tes[0];\n"
21661 "\n"
21662 "VARIABLE_USE"
21663 "\n"
21664 " any_fs = result;\n"
21665 "}\n"
21666 "\n";
21667 static const GLchar* vs = "#version 430 core\n"
21668 "#extension GL_ARB_enhanced_layouts : require\n"
21669 "\n"
21670 "in vec4 in_vs;\n"
21671 "out vec4 vs_any;\n"
21672 "\n"
21673 "void main()\n"
21674 "{\n"
21675 " vs_any = in_vs;\n"
21676 "}\n"
21677 "\n";
21678 static const GLchar* vs_tested = "#version 430 core\n"
21679 "#extension GL_ARB_enhanced_layouts : require\n"
21680 "\n"
21681 "VAR_DEFINITION"
21682 "\n"
21683 "in vec4 in_vs;\n"
21684 "out vec4 any_fs;\n"
21685 "\n"
21686 "void main()\n"
21687 "{\n"
21688 " vec4 result = in_vs;\n"
21689 "\n"
21690 "VARIABLE_USE"
21691 "\n"
21692 " any_fs = result;\n"
21693 "}\n"
21694 "\n";
21695
21696 std::string source;
21697 testCase& test_case = m_test_cases[test_case_index];
21698
21699 if (test_case.m_stage == stage)
21700 {
21701 GLchar buffer[16];
21702 size_t position = 0;
21703 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
21704 const GLchar* var_definition = 0;
21705 const GLchar* var_use = 0;
21706
21707 sprintf(buffer, "%d", test_case.m_type.GetSize());
21708
21709 switch (test_case.m_case)
21710 {
21711 case VALID:
21712 var_definition = valid_var_definition;
21713 var_use = valid_use;
21714 break;
21715 case INVALID:
21716 var_definition = invalid_var_definition;
21717 var_use = invalid_use;
21718 break;
21719 default:
21720 TCU_FAIL("Invalid enum");
21721 }
21722
21723 switch (stage)
21724 {
21725 case Utils::Shader::GEOMETRY:
21726 source = gs_tested;
21727 break;
21728 case Utils::Shader::TESS_EVAL:
21729 source = tes_tested;
21730 break;
21731 case Utils::Shader::VERTEX:
21732 source = vs_tested;
21733 break;
21734 default:
21735 TCU_FAIL("Invalid enum");
21736 }
21737
21738 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21739 position = 0;
21740 Utils::replaceToken("SIZE", position, buffer, source);
21741 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21742
21743 Utils::replaceAllTokens("TYPE", type_name, source);
21744 }
21745 else
21746 {
21747 switch (test_case.m_stage)
21748 {
21749 case Utils::Shader::GEOMETRY:
21750 switch (stage)
21751 {
21752 case Utils::Shader::FRAGMENT:
21753 source = fs;
21754 break;
21755 case Utils::Shader::VERTEX:
21756 source = vs;
21757 break;
21758 default:
21759 source = "";
21760 }
21761 break;
21762 case Utils::Shader::TESS_EVAL:
21763 switch (stage)
21764 {
21765 case Utils::Shader::FRAGMENT:
21766 source = fs;
21767 break;
21768 case Utils::Shader::TESS_CTRL:
21769 source = tcs;
21770 break;
21771 case Utils::Shader::VERTEX:
21772 source = vs;
21773 break;
21774 default:
21775 source = "";
21776 }
21777 break;
21778 case Utils::Shader::VERTEX:
21779 switch (stage)
21780 {
21781 case Utils::Shader::FRAGMENT:
21782 source = fs;
21783 break;
21784 default:
21785 source = "";
21786 }
21787 break;
21788 default:
21789 TCU_FAIL("Invalid enum");
21790 }
21791 }
21792
21793 return source;
21794 }
21795
21796 /** Get description of test case
21797 *
21798 * @param test_case_index Index of test case
21799 *
21800 * @return Test case description
21801 **/
21802 std::string XFBVariableStrideTest::getTestCaseName(GLuint test_case_index)
21803 {
21804 std::stringstream stream;
21805 testCase& test_case = m_test_cases[test_case_index];
21806
21807 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
21808 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
21809
21810 switch (test_case.m_case)
21811 {
21812 case VALID:
21813 stream << "valid";
21814 break;
21815 case INVALID:
21816 stream << "invalid";
21817 break;
21818 default:
21819 TCU_FAIL("Invalid enum");
21820 }
21821
21822 return stream.str();
21823 }
21824
21825 /** Get number of test cases
21826 *
21827 * @return Number of test cases
21828 **/
21829 GLuint XFBVariableStrideTest::getTestCaseNumber()
21830 {
21831 return static_cast<GLuint>(m_test_cases.size());
21832 }
21833
21834 /** Selects if "compute" stage is relevant for test
21835 *
21836 * @param ignored
21837 *
21838 * @return false
21839 **/
21840 bool XFBVariableStrideTest::isComputeRelevant(GLuint /* test_case_index */)
21841 {
21842 return false;
21843 }
21844
21845 /** Selects if compilation failure is expected result
21846 *
21847 * @param test_case_index Index of test case
21848 *
21849 * @return true
21850 **/
21851 bool XFBVariableStrideTest::isFailureExpected(GLuint test_case_index)
21852 {
21853 testCase& test_case = m_test_cases[test_case_index];
21854
21855 return (INVALID == test_case.m_case);
21856 }
21857
21858 /** Prepare all test cases
21859 *
21860 **/
21861 void XFBVariableStrideTest::testInit()
21862 {
21863 const GLuint n_types = getTypesNumber();
21864
21865 for (GLuint i = 0; i < n_types; ++i)
21866 {
21867 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21868 {
21869 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21870 (Utils::Shader::FRAGMENT == stage))
21871 {
21872 continue;
21873 }
21874
21875 const Utils::Type& type = getType(i);
21876 for (GLuint c = 0; c < CASE_MAX; ++c)
21877 {
21878 testCase test_case = { static_cast<CASES>(c), static_cast<Utils::Shader::STAGES>(stage), type };
21879
21880 m_test_cases.push_back(test_case);
21881 }
21882 }
21883 }
21884 }
21885
21886 /** Constructor
21887 *
21888 * @param context Test framework context
21889 **/
21890 XFBBlockStrideTest::XFBBlockStrideTest(deqp::Context& context)
21891 : TestBase(context, "xfb_block_stride", "Test verifies that stride qualifier is respected for blocks")
21892 {
21893 }
21894
21895 /** Source for given test case and stage
21896 *
21897 * @param test_case_index Index of test case
21898 * @param stage Shader stage
21899 *
21900 * @return Shader source
21901 **/
21902 std::string XFBBlockStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21903 {
21904 static const GLchar* var_definition = "layout (xfb_offset = 0, xfb_stride = 128) out Goku {\n"
21905 " vec4 gohan;\n"
21906 " vec4 goten;\n"
21907 " vec4 chichi;\n"
21908 "} gokuARRAY;\n";
21909 static const GLchar* var_use = " gokuINDEX.gohan = vec4(1, 0, 0, 0);\n"
21910 " gokuINDEX.goten = vec4(0, 0, 1, 0);\n"
21911 " gokuINDEX.chichi = vec4(0, 1, 0, 0);\n"
21912 " if (vec4(0) == result)\n"
21913 " {\n"
21914 " gokuINDEX.gohan = vec4(0, 1, 1, 1);\n"
21915 " gokuINDEX.goten = vec4(1, 1, 0, 1);\n"
21916 " gokuINDEX.chichi = vec4(1, 0, 1, 1);\n"
21917 " }\n";
21918 static const GLchar* gs_tested =
21919 "#version 430 core\n"
21920 "#extension GL_ARB_enhanced_layouts : require\n"
21921 "\n"
21922 "layout(points) in;\n"
21923 "layout(triangle_strip, max_vertices = 4) out;\n"
21924 "\n"
21925 "VAR_DEFINITION"
21926 "\n"
21927 "out gl_PerVertex \n"
21928 "{ \n"
21929 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
21930 "}; \n"
21931 "in vec4 tes_gs[];\n"
21932 "out vec4 gs_fs;\n"
21933 "\n"
21934 "void main()\n"
21935 "{\n"
21936 " vec4 result = tes_gs[0];\n"
21937 "\n"
21938 "VARIABLE_USE"
21939 "\n"
21940 " gs_fs = result;\n"
21941 " gl_Position = vec4(-1, -1, 0, 1);\n"
21942 " EmitVertex();\n"
21943 " gs_fs = result;\n"
21944 " gl_Position = vec4(-1, 1, 0, 1);\n"
21945 " EmitVertex();\n"
21946 " gs_fs = result;\n"
21947 " gl_Position = vec4(1, -1, 0, 1);\n"
21948 " EmitVertex();\n"
21949 " gs_fs = result;\n"
21950 " gl_Position = vec4(1, 1, 0, 1);\n"
21951 " EmitVertex();\n"
21952 "}\n"
21953 "\n";
21954 static const GLchar* tcs = "#version 430 core\n"
21955 "#extension GL_ARB_enhanced_layouts : require\n"
21956 "\n"
21957 "layout(vertices = 1) out;\n"
21958 "\n"
21959 "in vec4 vs_tcs[];\n"
21960 "out vec4 tcs_tes[];\n"
21961 "\n"
21962 "void main()\n"
21963 "{\n"
21964 "\n"
21965 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
21966 "\n"
21967 " gl_TessLevelOuter[0] = 1.0;\n"
21968 " gl_TessLevelOuter[1] = 1.0;\n"
21969 " gl_TessLevelOuter[2] = 1.0;\n"
21970 " gl_TessLevelOuter[3] = 1.0;\n"
21971 " gl_TessLevelInner[0] = 1.0;\n"
21972 " gl_TessLevelInner[1] = 1.0;\n"
21973 "}\n"
21974 "\n";
21975 #if 0
21976 static const GLchar* tcs_tested =
21977 "#version 430 core\n"
21978 "#extension GL_ARB_enhanced_layouts : require\n"
21979 "\n"
21980 "layout(vertices = 1) out;\n"
21981 "\n"
21982 "VAR_DEFINITION"
21983 "\n"
21984 "in vec4 vs_tcs[];\n"
21985 "out vec4 tcs_tes[];\n"
21986 "\n"
21987 "void main()\n"
21988 "{\n"
21989 " vec4 result = vs_tcs[gl_InvocationID];\n"
21990 "\n"
21991 "VARIABLE_USE"
21992 "\n"
21993 " tcs_tes[gl_InvocationID] = result;\n"
21994 "\n"
21995 " gl_TessLevelOuter[0] = 1.0;\n"
21996 " gl_TessLevelOuter[1] = 1.0;\n"
21997 " gl_TessLevelOuter[2] = 1.0;\n"
21998 " gl_TessLevelOuter[3] = 1.0;\n"
21999 " gl_TessLevelInner[0] = 1.0;\n"
22000 " gl_TessLevelInner[1] = 1.0;\n"
22001 "}\n"
22002 "\n";
22003 #endif
22004 static const GLchar* tes_tested = "#version 430 core\n"
22005 "#extension GL_ARB_enhanced_layouts : require\n"
22006 "\n"
22007 "layout(isolines, point_mode) in;\n"
22008 "\n"
22009 "VAR_DEFINITION"
22010 "\n"
22011 "in vec4 tcs_tes[];\n"
22012 "out vec4 tes_gs;\n"
22013 "\n"
22014 "void main()\n"
22015 "{\n"
22016 " vec4 result = tcs_tes[0];\n"
22017 "\n"
22018 "VARIABLE_USE"
22019 "\n"
22020 " tes_gs += result;\n"
22021 "}\n"
22022 "\n";
22023 static const GLchar* vs = "#version 430 core\n"
22024 "#extension GL_ARB_enhanced_layouts : require\n"
22025 "\n"
22026 "in vec4 in_vs;\n"
22027 "out vec4 vs_tcs;\n"
22028 "out vec4 tes_gs;\n"
22029 "\n"
22030 "void main()\n"
22031 "{\n"
22032 " vs_tcs = tes_gs = in_vs;\n"
22033 "}\n"
22034 "\n";
22035 static const GLchar* vs_tested = "#version 430 core\n"
22036 "#extension GL_ARB_enhanced_layouts : require\n"
22037 "\n"
22038 "VAR_DEFINITION"
22039 "\n"
22040 "in vec4 in_vs;\n"
22041 "out vec4 vs_tcs;\n"
22042 "\n"
22043 "void main()\n"
22044 "{\n"
22045 " vec4 result = in_vs;\n"
22046 "\n"
22047 "VARIABLE_USE"
22048 "\n"
22049 " vs_tcs += result;\n"
22050 "}\n"
22051 "\n";
22052
22053 std::string source;
22054 Utils::Shader::STAGES test_case = m_test_cases[test_case_index];
22055
22056 if (test_case == stage)
22057 {
22058 const GLchar* array = "";
22059 const GLchar* index = "";
22060 size_t position = 0;
22061 size_t temp;
22062 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
22063 // change array = "[]" to "[1]"
22064 switch (stage)
22065 {
22066 case Utils::Shader::GEOMETRY:
22067 source = gs_tested;
22068 array = "[1]";
22069 index = "[0]";
22070 break;
22071 /*
22072 It is invalid to define transform feedback output in HS
22073 */
22074 #if 0
22075 case Utils::Shader::TESS_CTRL:
22076 source = tcs_tested;
22077 array = "[]";
22078 index = "[gl_InvocationID]";
22079 break;
22080 #endif
22081 case Utils::Shader::TESS_EVAL:
22082 source = tes_tested;
22083 array = "[1]";
22084 index = "[0]";
22085 break;
22086 case Utils::Shader::VERTEX:
22087 source = vs_tested;
22088 break;
22089 default:
22090 TCU_FAIL("Invalid enum");
22091 }
22092
22093 temp = position;
22094 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22095 position = temp;
22096 Utils::replaceToken("ARRAY", position, array, source);
22097 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22098
22099 Utils::replaceAllTokens("INDEX", index, source);
22100 }
22101 else
22102 {
22103 switch (test_case)
22104 {
22105 case Utils::Shader::GEOMETRY:
22106 switch (stage)
22107 {
22108 case Utils::Shader::VERTEX:
22109 source = vs;
22110 break;
22111 default:
22112 source = "";
22113 }
22114 break;
22115 case Utils::Shader::TESS_CTRL:
22116 switch (stage)
22117 {
22118 case Utils::Shader::VERTEX:
22119 source = vs;
22120 break;
22121 default:
22122 source = "";
22123 }
22124 break;
22125 case Utils::Shader::TESS_EVAL:
22126 switch (stage)
22127 {
22128 case Utils::Shader::TESS_CTRL:
22129 source = tcs;
22130 break;
22131 case Utils::Shader::VERTEX:
22132 source = vs;
22133 break;
22134 default:
22135 source = "";
22136 }
22137 break;
22138 case Utils::Shader::VERTEX:
22139 source = "";
22140 break;
22141 default:
22142 TCU_FAIL("Invalid enum");
22143 }
22144 }
22145
22146 return source;
22147 }
22148
22149 /** Get description of test case
22150 *
22151 * @param test_case_index Index of test case
22152 *
22153 * @return Test case description
22154 **/
22155 std::string XFBBlockStrideTest::getTestCaseName(GLuint test_case_index)
22156 {
22157 std::stringstream stream;
22158
22159 stream << "Stage: " << Utils::Shader::GetStageName(m_test_cases[test_case_index]);
22160
22161 return stream.str();
22162 }
22163
22164 /** Get number of test cases
22165 *
22166 * @return Number of test cases
22167 **/
22168 GLuint XFBBlockStrideTest::getTestCaseNumber()
22169 {
22170 return static_cast<GLuint>(m_test_cases.size());
22171 }
22172
22173 /** Inspects program for xfb stride
22174 *
22175 * @param program Program to query
22176 *
22177 * @return true if query results match expected values, false otherwise
22178 **/
22179 bool XFBBlockStrideTest::inspectProgram(Utils::Program& program)
22180 {
22181 GLint stride = 0;
22182
22183 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
22184 1 /* buf_size */, &stride);
22185
22186 return (128 == stride);
22187 }
22188
22189 /** Runs test case
22190 *
22191 * @param test_case_index Id of test case
22192 *
22193 * @return true if test case pass, false otherwise
22194 **/
22195 bool XFBBlockStrideTest::testCase(GLuint test_case_index)
22196 {
22197 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
22198 Utils::Program program(m_context);
22199 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
22200 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
22201 bool test_case_result = true;
22202 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
22203
22204 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
22205
22206 test_case_result = inspectProgram(program);
22207
22208 return test_case_result;
22209 }
22210
22211 /** Prepare all test cases
22212 *
22213 **/
22214 void XFBBlockStrideTest::testInit()
22215 {
22216 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22217 {
22218 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22219 (Utils::Shader::FRAGMENT == stage))
22220 {
22221 continue;
22222 }
22223
22224 m_test_cases.push_back((Utils::Shader::STAGES)stage);
22225 }
22226 }
22227
22228 /** Constructor
22229 *
22230 * @param context Test context
22231 **/
22232 XFBBlockMemberStrideTest::XFBBlockMemberStrideTest(deqp::Context& context)
22233 : BufferTestBase(context, "xfb_block_member_stride",
22234 "Test verifies that xfb_stride qualifier is respected for block member")
22235 {
22236 /* Nothing to be done here */
22237 }
22238
22239 /** Get descriptors of buffers necessary for test
22240 *
22241 * @param ignored
22242 * @param out_descriptors Descriptors of buffers used by test
22243 **/
22244 void XFBBlockMemberStrideTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
22245 bufferDescriptor::Vector& out_descriptors)
22246 {
22247 const Utils::Type& vec4 = Utils::Type::vec4;
22248
22249 /* Test needs single uniform and xfb */
22250 out_descriptors.resize(2);
22251
22252 /* Get references */
22253 bufferDescriptor& uniform = out_descriptors[0];
22254 bufferDescriptor& xfb = out_descriptors[1];
22255
22256 /* Index */
22257 uniform.m_index = 0;
22258 xfb.m_index = 0;
22259
22260 /* Target */
22261 uniform.m_target = Utils::Buffer::Uniform;
22262 xfb.m_target = Utils::Buffer::Transform_feedback;
22263
22264 /* Data */
22265 static const GLuint vec4_size = 16;
22266 const std::vector<GLubyte>& gohan_data = vec4.GenerateDataPacked();
22267 const std::vector<GLubyte>& goten_data = vec4.GenerateDataPacked();
22268 const std::vector<GLubyte>& chichi_data = vec4.GenerateDataPacked();
22269
22270 /* Uniform data */
22271 uniform.m_initial_data.resize(3 * vec4_size);
22272 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], vec4_size);
22273 memcpy(&uniform.m_initial_data[0] + vec4_size, &goten_data[0], vec4_size);
22274 memcpy(&uniform.m_initial_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
22275
22276 /* XFB data */
22277 xfb.m_initial_data.resize(4 * vec4_size);
22278 xfb.m_expected_data.resize(4 * vec4_size);
22279
22280 for (GLuint i = 0; i < 4 * vec4_size; ++i)
22281 {
22282 xfb.m_initial_data[i] = (glw::GLubyte)i;
22283 xfb.m_expected_data[i] = (glw::GLubyte)i;
22284 }
22285
22286 // the xfb_offset of "chichi" should be 32
22287 memcpy(&xfb.m_expected_data[0] + 0, &gohan_data[0], vec4_size);
22288 memcpy(&xfb.m_expected_data[0] + vec4_size, &goten_data[0], vec4_size);
22289 memcpy(&xfb.m_expected_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
22290 }
22291
22292 /** Get body of main function for given shader stage
22293 *
22294 * @param ignored
22295 * @param stage Shader stage
22296 * @param out_assignments Set to empty
22297 * @param out_calculations Set to empty
22298 **/
22299 void XFBBlockMemberStrideTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
22300 std::string& out_assignments, std::string& out_calculations)
22301 {
22302 out_calculations = "";
22303
22304 static const GLchar* gs = " gohan = uni_gohan;\n"
22305 " goten = uni_goten;\n"
22306 " chichi = uni_chichi;\n";
22307 static const GLchar* fs = " fs_out = gohan + goten + chichi;\n";
22308
22309 const GLchar* assignments = "";
22310 switch (stage)
22311 {
22312 case Utils::Shader::FRAGMENT:
22313 assignments = fs;
22314 break;
22315 case Utils::Shader::GEOMETRY:
22316 assignments = gs;
22317 break;
22318 default:
22319 break;
22320 }
22321
22322 out_assignments = assignments;
22323 }
22324
22325 /** Get interface of shader
22326 *
22327 * @param ignored
22328 * @param stage Shader stage
22329 * @param out_interface Set to ""
22330 **/
22331 void XFBBlockMemberStrideTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
22332 std::string& out_interface)
22333 {
22334 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
22335 " vec4 gohan;\n"
22336 " layout (xfb_stride = 48) vec4 goten;\n"
22337 " vec4 chichi;\n"
22338 "};\n"
22339 "layout(binding = 0) uniform gs_block {\n"
22340 " vec4 uni_gohan;\n"
22341 " vec4 uni_goten;\n"
22342 " vec4 uni_chichi;\n"
22343 "};\n";
22344 static const GLchar* fs = "in Goku {\n"
22345 " vec4 gohan;\n"
22346 " vec4 goten;\n"
22347 " vec4 chichi;\n"
22348 "};\n"
22349 "out vec4 fs_out;\n";
22350
22351 switch (stage)
22352 {
22353 case Utils::Shader::FRAGMENT:
22354 out_interface = fs;
22355 break;
22356 case Utils::Shader::GEOMETRY:
22357 out_interface = gs;
22358 break;
22359 default:
22360 out_interface = "";
22361 return;
22362 }
22363 }
22364
22365 /** Inspects program to check if all resources are as expected
22366 *
22367 * @param ignored
22368 * @param program Program instance
22369 * @param out_stream Error message
22370 *
22371 * @return true if everything is ok, false otherwise
22372 **/
22373 bool XFBBlockMemberStrideTest::inspectProgram(GLuint /* test_case_index*/, Utils::Program& program,
22374 std::stringstream& out_stream)
22375 {
22376 const GLuint gohan_id = program.GetResourceIndex("gohan", GL_TRANSFORM_FEEDBACK_VARYING);
22377 const GLuint goten_id = program.GetResourceIndex("goten", GL_TRANSFORM_FEEDBACK_VARYING);
22378 const GLuint chichi_id = program.GetResourceIndex("chichi", GL_TRANSFORM_FEEDBACK_VARYING);
22379
22380 GLint gohan_offset = 0;
22381 GLint goten_offset = 0;
22382 GLint chichi_offset = 0;
22383
22384 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, gohan_id, GL_OFFSET, 1, &gohan_offset);
22385 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, goten_id, GL_OFFSET, 1, &goten_offset);
22386 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, chichi_id, GL_OFFSET, 1, &chichi_offset);
22387
22388 // the xfb_offset of "chichi" should be 32
22389 if ((0 != gohan_offset) || (16 != goten_offset) || (32 != chichi_offset))
22390 {
22391 out_stream << "Got wrong offset: [" << gohan_offset << ", " << goten_offset << ", " << chichi_offset
22392 << "] expected: [0, 16, 32]";
22393 return false;
22394 }
22395
22396 return true;
22397 }
22398
22399 /** Constructor
22400 *
22401 * @param context Test framework context
22402 **/
22403 XFBDuplicatedStrideTest::XFBDuplicatedStrideTest(deqp::Context& context)
22404 : NegativeTestBase(context, "xfb_duplicated_stride",
22405 "Test verifies that compiler reports error when conflicting stride qualifiers are used")
22406 {
22407 }
22408
22409 /** Source for given test case and stage
22410 *
22411 * @param test_case_index Index of test case
22412 * @param stage Shader stage
22413 *
22414 * @return Shader source
22415 **/
22416 std::string XFBDuplicatedStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
22417 {
22418 static const GLchar* invalid_var_definition = "const uint valid_stride = 64;\n"
22419 #if DEBUG_NEG_REMOVE_ERROR
22420 "const uint conflicting_stride = 64;\n"
22421 #else
22422 "const uint conflicting_stride = 128;\n"
22423 #endif /* DEBUG_NEG_REMOVE_ERROR */
22424 "\n"
22425 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
22426 "layout (xfb_buffer = 0, xfb_stride = conflicting_stride) out;\n";
22427 static const GLchar* valid_var_definition = "const uint valid_stride = 64;\n"
22428 "\n"
22429 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
22430 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n";
22431 static const GLchar* fs = "#version 430 core\n"
22432 "#extension GL_ARB_enhanced_layouts : require\n"
22433 "\n"
22434 "in vec4 any_fs;\n"
22435 "out vec4 fs_out;\n"
22436 "\n"
22437 "void main()\n"
22438 "{\n"
22439 " fs_out = any_fs;\n"
22440 "}\n"
22441 "\n";
22442 static const GLchar* gs_tested = "#version 430 core\n"
22443 "#extension GL_ARB_enhanced_layouts : require\n"
22444 "\n"
22445 "layout(points) in;\n"
22446 "layout(triangle_strip, max_vertices = 4) out;\n"
22447 "\n"
22448 "VAR_DEFINITION"
22449 "\n"
22450 "in vec4 vs_any[];\n"
22451 "out vec4 any_fs;\n"
22452 "\n"
22453 "void main()\n"
22454 "{\n"
22455 " vec4 result = vs_any[0];\n"
22456 "\n"
22457 " any_fs = result;\n"
22458 " gl_Position = vec4(-1, -1, 0, 1);\n"
22459 " EmitVertex();\n"
22460 " any_fs = result;\n"
22461 " gl_Position = vec4(-1, 1, 0, 1);\n"
22462 " EmitVertex();\n"
22463 " any_fs = result;\n"
22464 " gl_Position = vec4(1, -1, 0, 1);\n"
22465 " EmitVertex();\n"
22466 " any_fs = result;\n"
22467 " gl_Position = vec4(1, 1, 0, 1);\n"
22468 " EmitVertex();\n"
22469 "}\n"
22470 "\n";
22471 static const GLchar* tcs = "#version 430 core\n"
22472 "#extension GL_ARB_enhanced_layouts : require\n"
22473 "\n"
22474 "layout(vertices = 1) out;\n"
22475 "\n"
22476 "in vec4 vs_any[];\n"
22477 "out vec4 tcs_tes[];\n"
22478 "\n"
22479 "void main()\n"
22480 "{\n"
22481 "\n"
22482 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
22483 "\n"
22484 " gl_TessLevelOuter[0] = 1.0;\n"
22485 " gl_TessLevelOuter[1] = 1.0;\n"
22486 " gl_TessLevelOuter[2] = 1.0;\n"
22487 " gl_TessLevelOuter[3] = 1.0;\n"
22488 " gl_TessLevelInner[0] = 1.0;\n"
22489 " gl_TessLevelInner[1] = 1.0;\n"
22490 "}\n"
22491 "\n";
22492 static const GLchar* tes_tested = "#version 430 core\n"
22493 "#extension GL_ARB_enhanced_layouts : require\n"
22494 "\n"
22495 "layout(isolines, point_mode) in;\n"
22496 "\n"
22497 "VAR_DEFINITION"
22498 "\n"
22499 "in vec4 tcs_tes[];\n"
22500 "out vec4 any_fs;\n"
22501 "\n"
22502 "void main()\n"
22503 "{\n"
22504 " vec4 result = tcs_tes[0];\n"
22505 "\n"
22506 " any_fs = result;\n"
22507 "}\n"
22508 "\n";
22509 static const GLchar* vs = "#version 430 core\n"
22510 "#extension GL_ARB_enhanced_layouts : require\n"
22511 "\n"
22512 "in vec4 in_vs;\n"
22513 "out vec4 vs_any;\n"
22514 "\n"
22515 "void main()\n"
22516 "{\n"
22517 " vs_any = in_vs;\n"
22518 "}\n"
22519 "\n";
22520 static const GLchar* vs_tested = "#version 430 core\n"
22521 "#extension GL_ARB_enhanced_layouts : require\n"
22522 "\n"
22523 "VAR_DEFINITION"
22524 "\n"
22525 "in vec4 in_vs;\n"
22526 "out vec4 any_fs;\n"
22527 "\n"
22528 "void main()\n"
22529 "{\n"
22530 " vec4 result = in_vs;\n"
22531 "\n"
22532 " any_fs += result;\n"
22533 "}\n"
22534 "\n";
22535
22536 std::string source;
22537 testCase& test_case = m_test_cases[test_case_index];
22538
22539 if (test_case.m_stage == stage)
22540 {
22541 size_t position = 0;
22542 const GLchar* var_definition = 0;
22543
22544 switch (test_case.m_case)
22545 {
22546 case VALID:
22547 var_definition = valid_var_definition;
22548 break;
22549 case INVALID:
22550 var_definition = invalid_var_definition;
22551 break;
22552 default:
22553 TCU_FAIL("Invalid enum");
22554 }
22555
22556 switch (stage)
22557 {
22558 case Utils::Shader::GEOMETRY:
22559 source = gs_tested;
22560 break;
22561 case Utils::Shader::TESS_EVAL:
22562 source = tes_tested;
22563 break;
22564 case Utils::Shader::VERTEX:
22565 source = vs_tested;
22566 break;
22567 default:
22568 TCU_FAIL("Invalid enum");
22569 }
22570
22571 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22572 }
22573 else
22574 {
22575 switch (test_case.m_stage)
22576 {
22577 case Utils::Shader::GEOMETRY:
22578 switch (stage)
22579 {
22580 case Utils::Shader::FRAGMENT:
22581 source = fs;
22582 break;
22583 case Utils::Shader::VERTEX:
22584 source = vs;
22585 break;
22586 default:
22587 source = "";
22588 }
22589 break;
22590 case Utils::Shader::TESS_EVAL:
22591 switch (stage)
22592 {
22593 case Utils::Shader::FRAGMENT:
22594 source = fs;
22595 break;
22596 case Utils::Shader::TESS_CTRL:
22597 source = tcs;
22598 break;
22599 case Utils::Shader::VERTEX:
22600 source = vs;
22601 break;
22602 default:
22603 source = "";
22604 }
22605 break;
22606 case Utils::Shader::VERTEX:
22607 switch (stage)
22608 {
22609 case Utils::Shader::FRAGMENT:
22610 source = fs;
22611 break;
22612 default:
22613 source = "";
22614 }
22615 break;
22616 default:
22617 TCU_FAIL("Invalid enum");
22618 }
22619 }
22620
22621 return source;
22622 }
22623
22624 /** Get description of test case
22625 *
22626 * @param test_case_index Index of test case
22627 *
22628 * @return Test case description
22629 **/
22630 std::string XFBDuplicatedStrideTest::getTestCaseName(GLuint test_case_index)
22631 {
22632 std::stringstream stream;
22633 testCase& test_case = m_test_cases[test_case_index];
22634
22635 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
22636
22637 switch (test_case.m_case)
22638 {
22639 case VALID:
22640 stream << "valid";
22641 break;
22642 case INVALID:
22643 stream << "invalid";
22644 break;
22645 default:
22646 TCU_FAIL("Invalid enum");
22647 }
22648
22649 return stream.str();
22650 }
22651
22652 /** Get number of test cases
22653 *
22654 * @return Number of test cases
22655 **/
22656 GLuint XFBDuplicatedStrideTest::getTestCaseNumber()
22657 {
22658 return static_cast<GLuint>(m_test_cases.size());
22659 }
22660
22661 /** Selects if "compute" stage is relevant for test
22662 *
22663 * @param ignored
22664 *
22665 * @return false
22666 **/
22667 bool XFBDuplicatedStrideTest::isComputeRelevant(GLuint /* test_case_index */)
22668 {
22669 return false;
22670 }
22671
22672 /** Selects if compilation failure is expected result
22673 *
22674 * @param test_case_index Index of test case
22675 *
22676 * @return true
22677 **/
22678 bool XFBDuplicatedStrideTest::isFailureExpected(GLuint test_case_index)
22679 {
22680 testCase& test_case = m_test_cases[test_case_index];
22681
22682 return (INVALID == test_case.m_case);
22683 }
22684
22685 /** Prepare all test cases
22686 *
22687 **/
22688 void XFBDuplicatedStrideTest::testInit()
22689 {
22690 for (GLuint c = 0; c < CASE_MAX; ++c)
22691 {
22692 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22693 {
22694 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22695 (Utils::Shader::FRAGMENT == stage))
22696 {
22697 continue;
22698 }
22699
22700 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
22701
22702 m_test_cases.push_back(test_case);
22703 }
22704 }
22705 }
22706
22707 /** Constructor
22708 *
22709 * @param context Test framework context
22710 **/
22711 XFBGetProgramResourceAPITest::XFBGetProgramResourceAPITest(deqp::Context& context)
22712 : TestBase(context, "xfb_get_program_resource_api",
22713 "Test verifies that get program resource reports correct results for XFB")
22714 {
22715 }
22716
22717 /** Source for given test case and stage
22718 *
22719 * @param test_case_index Index of test case
22720 * @param stage Shader stage
22721 *
22722 * @return Shader source
22723 **/
22724 std::string XFBGetProgramResourceAPITest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
22725 {
22726 static const GLchar* api_var_definition = "out TYPE b0_v1ARRAY;\n"
22727 "out TYPE b1_v1ARRAY;\n"
22728 "out TYPE b0_v3ARRAY;\n"
22729 "out TYPE b0_v0ARRAY;\n";
22730 static const GLchar* xfb_var_definition =
22731 "const uint type_size = SIZE;\n"
22732 "\n"
22733 "layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;\n"
22734 "\n"
22735 "layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out TYPE b0_v1ARRAY;\n"
22736 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out TYPE b1_v1ARRAY;\n"
22737 "layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out TYPE b0_v3ARRAY;\n"
22738 "layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out TYPE b0_v0ARRAY;\n";
22739 static const GLchar* var_use = " b0_v1INDEX = TYPE(0);\n"
22740 " b1_v1INDEX = TYPE(1);\n"
22741 " b0_v3INDEX = TYPE(0);\n"
22742 " b0_v0INDEX = TYPE(1);\n"
22743 " if (vec4(0) == result)\n"
22744 " {\n"
22745 " b0_v1INDEX = TYPE(1);\n"
22746 " b1_v1INDEX = TYPE(0);\n"
22747 " b0_v3INDEX = TYPE(1);\n"
22748 " b0_v0INDEX = TYPE(0);\n"
22749 " }\n";
22750 static const GLchar* gs_tested =
22751 "#version 430 core\n"
22752 "#extension GL_ARB_enhanced_layouts : require\n"
22753 "\n"
22754 "layout(points) in;\n"
22755 "layout(triangle_strip, max_vertices = 4) out;\n"
22756 "\n"
22757 "VAR_DEFINITION"
22758 "\n"
22759 "out gl_PerVertex \n"
22760 "{ \n"
22761 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
22762 "}; \n"
22763 "in vec4 tes_gs[];\n"
22764 "out vec4 gs_fs;\n"
22765 "\n"
22766 "void main()\n"
22767 "{\n"
22768 " vec4 result = tes_gs[0];\n"
22769 "\n"
22770 "VARIABLE_USE"
22771 "\n"
22772 " gs_fs = result;\n"
22773 " gl_Position = vec4(-1, -1, 0, 1);\n"
22774 " EmitVertex();\n"
22775 " gs_fs = result;\n"
22776 " gl_Position = vec4(-1, 1, 0, 1);\n"
22777 " EmitVertex();\n"
22778 " gs_fs = result;\n"
22779 " gl_Position = vec4(1, -1, 0, 1);\n"
22780 " EmitVertex();\n"
22781 " gs_fs = result;\n"
22782 " gl_Position = vec4(1, 1, 0, 1);\n"
22783 " EmitVertex();\n"
22784 "}\n"
22785 "\n";
22786 #if 0
22787 static const GLchar* tcs_tested =
22788 "#version 430 core\n"
22789 "#extension GL_ARB_enhanced_layouts : require\n"
22790 "\n"
22791 "layout(vertices = 1) out;\n"
22792 "\n"
22793 "VAR_DEFINITION"
22794 "\n"
22795 "in vec4 vs_tcs[];\n"
22796 "out vec4 tcs_tes[];\n"
22797 "\n"
22798 "void main()\n"
22799 "{\n"
22800 " vec4 result = vs_tcs[gl_InvocationID];\n"
22801 "\n"
22802 "VARIABLE_USE"
22803 "\n"
22804 " tcs_tes[gl_InvocationID] = result;\n"
22805 "\n"
22806 " gl_TessLevelOuter[0] = 1.0;\n"
22807 " gl_TessLevelOuter[1] = 1.0;\n"
22808 " gl_TessLevelOuter[2] = 1.0;\n"
22809 " gl_TessLevelOuter[3] = 1.0;\n"
22810 " gl_TessLevelInner[0] = 1.0;\n"
22811 " gl_TessLevelInner[1] = 1.0;\n"
22812 "}\n"
22813 "\n";
22814 #endif
22815 static const GLchar* tes_tested = "#version 430 core\n"
22816 "#extension GL_ARB_enhanced_layouts : require\n"
22817 "\n"
22818 "layout(isolines, point_mode) in;\n"
22819 "\n"
22820 "VAR_DEFINITION"
22821 "\n"
22822 "in vec4 tcs_tes[];\n"
22823 "out vec4 tes_gs;\n"
22824 "\n"
22825 "void main()\n"
22826 "{\n"
22827 " vec4 result = tcs_tes[0];\n"
22828 "\n"
22829 "VARIABLE_USE"
22830 "\n"
22831 " tes_gs = result;\n"
22832 "}\n"
22833 "\n";
22834 static const GLchar* vs_tested = "#version 430 core\n"
22835 "#extension GL_ARB_enhanced_layouts : require\n"
22836 "\n"
22837 "VAR_DEFINITION"
22838 "\n"
22839 "in vec4 in_vs;\n"
22840 "out vec4 vs_tcs;\n"
22841 "\n"
22842 "void main()\n"
22843 "{\n"
22844 " vec4 result = in_vs;\n"
22845 "\n"
22846 "VARIABLE_USE"
22847 "\n"
22848 " vs_tcs = result;\n"
22849 "}\n"
22850 "\n";
22851
22852 std::string source;
22853 const test_Case& test_case = m_test_cases[test_case_index];
22854
22855 if (test_case.m_stage == stage)
22856 {
22857 const GLchar* array = "";
22858 GLchar buffer[16];
22859 const GLchar* index = "";
22860 size_t position = 0;
22861 size_t temp;
22862 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
22863 const GLchar* var_definition = 0;
22864
22865 sprintf(buffer, "%d", test_case.m_type.GetSize());
22866
22867 if (XFB == test_case.m_case)
22868 {
22869 var_definition = xfb_var_definition;
22870 }
22871 else
22872 {
22873 var_definition = api_var_definition;
22874 }
22875
22876 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
22877 // change array = "[]" to "[1]"
22878 switch (stage)
22879 {
22880 case Utils::Shader::GEOMETRY:
22881 source = gs_tested;
22882 array = "[1]";
22883 index = "[0]";
22884 break;
22885 // It is invalid to output transform feedback varyings in tessellation control shader
22886 #if 0
22887 case Utils::Shader::TESS_CTRL:
22888 source = tcs_tested;
22889 array = "[]";
22890 index = "[gl_InvocationID]";
22891 break;
22892 #endif
22893 case Utils::Shader::TESS_EVAL:
22894 source = tes_tested;
22895 array = "[1]";
22896 index = "[0]";
22897 break;
22898 case Utils::Shader::VERTEX:
22899 source = vs_tested;
22900 break;
22901 default:
22902 TCU_FAIL("Invalid enum");
22903 }
22904
22905 temp = position;
22906 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22907 if (XFB == test_case.m_case)
22908 {
22909 position = temp;
22910 Utils::replaceToken("SIZE", position, buffer, source);
22911 }
22912 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22913
22914 Utils::replaceAllTokens("ARRAY", array, source);
22915 Utils::replaceAllTokens("INDEX", index, source);
22916 Utils::replaceAllTokens("TYPE", type_name, source);
22917 }
22918 else
22919 {
22920 source = "";
22921 }
22922
22923 return source;
22924 }
22925
22926 /** Get description of test case
22927 *
22928 * @param test_case_index Index of test case
22929 *
22930 * @return Test case description
22931 **/
22932 std::string XFBGetProgramResourceAPITest::getTestCaseName(GLuint test_case_index)
22933 {
22934 std::stringstream stream;
22935 const test_Case& test_case = m_test_cases[test_case_index];
22936
22937 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
22938 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
22939
22940 switch (test_case.m_case)
22941 {
22942 case INTERLEAVED:
22943 stream << "interleaved";
22944 break;
22945 case SEPARATED:
22946 stream << "separated";
22947 break;
22948 case XFB:
22949 stream << "xfb";
22950 break;
22951 default:
22952 TCU_FAIL("Invalid enum");
22953 }
22954
22955 return stream.str();
22956 }
22957
22958 /** Get number of test cases
22959 *
22960 * @return Number of test cases
22961 **/
22962 GLuint XFBGetProgramResourceAPITest::getTestCaseNumber()
22963 {
22964 return static_cast<GLuint>(m_test_cases.size());
22965 }
22966
22967 /** Inspects program for offset, buffer index, buffer stride and type
22968 *
22969 * @param test_case_index Index of test case
22970 * @param program Program to query
22971 *
22972 * @return true if query results match expected values, false otherwise
22973 **/
22974 bool XFBGetProgramResourceAPITest::inspectProgram(glw::GLuint test_case_index, Utils::Program& program)
22975 {
22976 GLint b0_stride = 0;
22977 GLint b1_stride = 0;
22978 GLint b0_v0_buf = 0;
22979 GLint b0_v0_offset = 0;
22980 GLint b0_v0_type = 0;
22981 GLint b0_v1_buf = 0;
22982 GLint b0_v1_offset = 0;
22983 GLint b0_v1_type = 0;
22984 GLint b0_v3_buf = 0;
22985 GLint b0_v3_offset = 0;
22986 GLint b0_v3_type = 0;
22987 GLint b1_v1_buf = 0;
22988 GLint b1_v1_offset = 0;
22989 GLint b1_v1_type = 0;
22990 const test_Case& test_case = m_test_cases[test_case_index];
22991 const GLenum type_enum = test_case.m_type.GetTypeGLenum();
22992 const GLint type_size = test_case.m_type.GetSize();
22993
22994 GLuint b0_v0_index = program.GetResourceIndex("b0_v0", GL_TRANSFORM_FEEDBACK_VARYING);
22995 GLuint b0_v1_index = program.GetResourceIndex("b0_v1", GL_TRANSFORM_FEEDBACK_VARYING);
22996 GLuint b0_v3_index = program.GetResourceIndex("b0_v3", GL_TRANSFORM_FEEDBACK_VARYING);
22997 GLuint b1_v1_index = program.GetResourceIndex("b1_v1", GL_TRANSFORM_FEEDBACK_VARYING);
22998
22999 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_OFFSET, 1 /* buf_size */, &b0_v0_offset);
23000 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_OFFSET, 1 /* buf_size */, &b0_v1_offset);
23001 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_OFFSET, 1 /* buf_size */, &b0_v3_offset);
23002 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_OFFSET, 1 /* buf_size */, &b1_v1_offset);
23003
23004 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TYPE, 1 /* buf_size */, &b0_v0_type);
23005 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TYPE, 1 /* buf_size */, &b0_v1_type);
23006 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TYPE, 1 /* buf_size */, &b0_v3_type);
23007 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TYPE, 1 /* buf_size */, &b1_v1_type);
23008
23009 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23010 1 /* buf_size */, &b0_v0_buf);
23011 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23012 1 /* buf_size */, &b0_v1_buf);
23013 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23014 1 /* buf_size */, &b0_v3_buf);
23015 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23016 1 /* buf_size */, &b1_v1_buf);
23017
23018 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b0_v0_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
23019 &b0_stride);
23020 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b1_v1_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
23021 &b1_stride);
23022
23023 if (SEPARATED != test_case.m_case)
23024 {
23025 return (((GLint)(4 * type_size) == b0_stride) && ((GLint)(4 * type_size) == b1_stride) &&
23026 ((GLint)(0) == b0_v0_buf) && ((GLint)(0 * type_size) == b0_v0_offset) &&
23027 ((GLint)(type_enum) == b0_v0_type) && ((GLint)(0) == b0_v1_buf) &&
23028 ((GLint)(1 * type_size) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
23029 ((GLint)(0) == b0_v3_buf) && ((GLint)(3 * type_size) == b0_v3_offset) &&
23030 ((GLint)(type_enum) == b0_v3_type) && ((GLint)(1) == b1_v1_buf) &&
23031 ((GLint)(1 * type_size) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
23032 }
23033 else
23034 {
23035 return (((GLint)(1 * type_size) == b0_stride) && ((GLint)(1 * type_size) == b1_stride) &&
23036 ((GLint)(0) == b0_v0_buf) && ((GLint)(0) == b0_v0_offset) && ((GLint)(type_enum) == b0_v0_type) &&
23037 ((GLint)(1) == b0_v1_buf) && ((GLint)(0) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
23038 ((GLint)(2) == b0_v3_buf) && ((GLint)(0) == b0_v3_offset) && ((GLint)(type_enum) == b0_v3_type) &&
23039 ((GLint)(3) == b1_v1_buf) && ((GLint)(0) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
23040 }
23041 }
23042
23043 /** Insert gl_SkipComponents
23044 *
23045 * @param num_components How many gl_SkipComponents1 need to be inserted
23046 * @param varyings The transform feedback varyings string vector
23047 *
23048 **/
23049 void XFBGetProgramResourceAPITest::insertSkipComponents(int num_components, Utils::Program::NameVector& varyings)
23050 {
23051 int num_component_4 = num_components / 4;
23052 int num_component_1 = num_components % 4;
23053 for (int i = 0; i < num_component_4; i++)
23054 {
23055 varyings.push_back("gl_SkipComponents4");
23056 }
23057 switch (num_component_1)
23058 {
23059 case 1:
23060 varyings.push_back("gl_SkipComponents1");
23061 break;
23062 case 2:
23063 varyings.push_back("gl_SkipComponents2");
23064 break;
23065 case 3:
23066 varyings.push_back("gl_SkipComponents3");
23067 break;
23068 default:
23069 break;
23070 }
23071 }
23072
23073 /** Runs test case
23074 *
23075 * @param test_case_index Id of test case
23076 *
23077 * @return true if test case pass, false otherwise
23078 **/
23079 bool XFBGetProgramResourceAPITest::testCase(GLuint test_case_index)
23080 {
23081 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
23082 Utils::Program program(m_context);
23083 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
23084 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
23085 const test_Case& test_case = m_test_cases[test_case_index];
23086 bool test_case_result = true;
23087 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
23088
23089 // According to spec: gl_SkipComponents1 ~ gl_SkipComponents4 is treated as specifying a one- to four-component floating point output variables with undefined values.
23090 // 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.
23091
23092 if (INTERLEAVED == test_case.m_case)
23093 {
23094 /*
23095 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
23096 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
23097 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
23098 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
23099
23100 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,
23101 we need to calculate how many "gl_SkipComponents" need to be inserted.
23102 */
23103 Utils::Program::NameVector captured_varyings;
23104 captured_varyings.push_back("b0_v0");
23105 captured_varyings.push_back("b0_v1");
23106 // Compute how many gl_SkipComponents to be inserted
23107 int numComponents = test_case.m_type.GetSize() / 4;
23108 insertSkipComponents(numComponents, captured_varyings);
23109 captured_varyings.push_back("b0_v3");
23110 captured_varyings.push_back("gl_NextBuffer");
23111 insertSkipComponents(numComponents, captured_varyings);
23112 captured_varyings.push_back("b1_v1");
23113 insertSkipComponents(numComponents * 2, captured_varyings);
23114
23115 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, true,
23116 true /* separable */);
23117 }
23118 else if (SEPARATED == test_case.m_case)
23119 {
23120 Utils::Program::NameVector captured_varyings;
23121
23122 captured_varyings.push_back("b0_v0");
23123 captured_varyings.push_back("b0_v1");
23124 captured_varyings.push_back("b0_v3");
23125 captured_varyings.push_back("b1_v1");
23126
23127 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, false,
23128 true /* separable */);
23129 }
23130 else
23131 {
23132
23133 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
23134 }
23135
23136 test_case_result = inspectProgram(test_case_index, program);
23137
23138 return test_case_result;
23139 }
23140
23141 /** Prepare all test cases
23142 *
23143 **/
23144 void XFBGetProgramResourceAPITest::testInit()
23145 {
23146 const Functions& gl = m_context.getRenderContext().getFunctions();
23147 const GLuint n_types = getTypesNumber();
23148 GLint max_xfb_int;
23149 GLint max_xfb_sep;
23150
23151 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_int);
23152 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23153
23154 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_xfb_sep);
23155 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23156
23157 GLint max_varyings;
23158 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings);
23159
23160 for (GLuint i = 0; i < n_types; ++i)
23161 {
23162 // 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,
23163 // 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
23164 // shader valid, we can either skip the dmat4, dmat4x3 or query the implementation-dependent value MAX_VARYING_COMPONENTS before generating the shader
23165 // to guarantee the number of varying not exceeded.
23166 /*
23167 layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;
23168 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
23169 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
23170 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
23171 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
23172 in vec4 in_vs;
23173 out vec4 vs_tcs;
23174 */
23175 if (i == 7 || i == 9)
23176 continue;
23177 const Utils::Type& type = getType(i);
23178 if (4 * type.GetNumComponents() + 4 > (GLuint)max_varyings)
23179 {
23180 continue;
23181 }
23182 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
23183 {
23184 /*
23185 It is invalid to define transform feedback output in HS
23186 */
23187 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
23188 (Utils::Shader::FRAGMENT == stage))
23189 {
23190 continue;
23191 }
23192
23193 test_Case test_case_int = { INTERLEAVED, (Utils::Shader::STAGES)stage, type };
23194 test_Case test_case_sep = { SEPARATED, (Utils::Shader::STAGES)stage, type };
23195 test_Case test_case_xfb = { XFB, (Utils::Shader::STAGES)stage, type };
23196
23197 if ((int)type.GetSize() <= max_xfb_int)
23198 {
23199 m_test_cases.push_back(test_case_xfb);
23200 m_test_cases.push_back(test_case_int);
23201 }
23202
23203 if ((int)type.GetSize() <= max_xfb_sep)
23204 {
23205 m_test_cases.push_back(test_case_sep);
23206 }
23207 }
23208 }
23209 }
23210
23211 /** Constructor
23212 *
23213 * @param context Test context
23214 **/
23215 XFBOverrideQualifiersWithAPITest::XFBOverrideQualifiersWithAPITest(deqp::Context& context)
23216 : BufferTestBase(context, "xfb_override_qualifiers_with_api",
23217 "Test verifies that xfb_offset qualifier is not overriden with API")
23218 {
23219 /* Nothing to be done here */
23220 }
23221
23222 /** Get descriptors of buffers necessary for test
23223 *
23224 * @param test_case_index Index of test case
23225 * @param out_descriptors Descriptors of buffers used by test
23226 **/
23227 void XFBOverrideQualifiersWithAPITest::getBufferDescriptors(glw::GLuint test_case_index,
23228 bufferDescriptor::Vector& out_descriptors)
23229 {
23230 const Utils::Type& type = getType(test_case_index);
23231
23232 /* Test needs single uniform and xfb */
23233 out_descriptors.resize(2);
23234
23235 /* Get references */
23236 bufferDescriptor& uniform = out_descriptors[0];
23237 bufferDescriptor& xfb = out_descriptors[1];
23238
23239 /* Index */
23240 uniform.m_index = 0;
23241 xfb.m_index = 0;
23242
23243 /* Target */
23244 uniform.m_target = Utils::Buffer::Uniform;
23245 xfb.m_target = Utils::Buffer::Transform_feedback;
23246
23247 /* Data */
23248 const GLuint gen_start = Utils::s_rand;
23249 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
23250 const std::vector<GLubyte>& trunks_data = type.GenerateData();
23251 const std::vector<GLubyte>& goku_data = type.GenerateData();
23252
23253 Utils::s_rand = gen_start;
23254 const std::vector<GLubyte>& vegeta_data_pck = type.GenerateDataPacked();
23255 type.GenerateDataPacked(); // generate the data for trunks
23256 const std::vector<GLubyte>& goku_data_pck = type.GenerateDataPacked();
23257
23258 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
23259 const GLuint padded_type_size = type.GetBaseAlignment(false) * type.m_n_columns;
23260 const GLuint type_size_pck = static_cast<GLuint>(vegeta_data_pck.size());
23261
23262 /* Uniform data */
23263 uniform.m_initial_data.resize(3 * padded_type_size);
23264 memcpy(&uniform.m_initial_data[0] + 0, &vegeta_data[0], type_size);
23265 memcpy(&uniform.m_initial_data[0] + padded_type_size, &trunks_data[0], type_size);
23266 memcpy(&uniform.m_initial_data[0] + 2 * padded_type_size, &goku_data[0], type_size);
23267
23268 /* XFB data */
23269 xfb.m_initial_data.resize(3 * type_size_pck);
23270 xfb.m_expected_data.resize(3 * type_size_pck);
23271
23272 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
23273 {
23274 xfb.m_initial_data[i] = (glw::GLubyte)i;
23275 xfb.m_expected_data[i] = (glw::GLubyte)i;
23276 }
23277
23278 memcpy(&xfb.m_expected_data[0] + 0, &goku_data_pck[0], type_size_pck);
23279 memcpy(&xfb.m_expected_data[0] + 2 * type_size_pck, &vegeta_data_pck[0], type_size_pck);
23280 }
23281
23282 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
23283 *
23284 * @param ignored
23285 * @param captured_varyings List of names
23286 **/
23287 void XFBOverrideQualifiersWithAPITest::getCapturedVaryings(glw::GLuint test_case_index,
23288 Utils::Program::NameVector& captured_varyings,
23289 GLint* xfb_components)
23290 {
23291 captured_varyings.resize(1);
23292
23293 captured_varyings[0] = "trunks";
23294
23295 /* The test captures 3 varyings of type 'type' */
23296 Utils::Type type = getType(test_case_index);
23297 GLint type_size = type.GetSize(false);
23298 *xfb_components = 3 * type_size / 4;
23299 }
23300
23301 /** Get body of main function for given shader stage
23302 *
23303 * @param test_case_index Index of test case
23304 * @param stage Shader stage
23305 * @param out_assignments Set to empty
23306 * @param out_calculations Set to empty
23307 **/
23308 void XFBOverrideQualifiersWithAPITest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
23309 std::string& out_assignments, std::string& out_calculations)
23310 {
23311 out_calculations = "";
23312
23313 static const GLchar* gs = " vegeta = uni_vegeta;\n"
23314 " trunks = uni_trunks;\n"
23315 " goku = uni_goku;\n";
23316 static const GLchar* fs = " fs_out = vec4(0);\n"
23317 " if (TYPE(1) == goku + trunks + vegeta)\n"
23318 " {\n"
23319 " fs_out = vec4(1);\n"
23320 " }\n";
23321
23322 const GLchar* assignments = "";
23323 switch (stage)
23324 {
23325 case Utils::Shader::FRAGMENT:
23326 assignments = fs;
23327 break;
23328 case Utils::Shader::GEOMETRY:
23329 assignments = gs;
23330 break;
23331 default:
23332 break;
23333 }
23334
23335 out_assignments = assignments;
23336
23337 if (Utils::Shader::FRAGMENT == stage)
23338 {
23339 const Utils::Type& type = getType(test_case_index);
23340
23341 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_assignments);
23342 }
23343 }
23344
23345 /** Get interface of shader
23346 *
23347 * @param test_case_index Index of test case
23348 * @param stage Shader stage
23349 * @param out_interface Set to ""
23350 **/
23351 void XFBOverrideQualifiersWithAPITest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
23352 std::string& out_interface)
23353 {
23354 static const GLchar* gs = "const uint sizeof_type = SIZE;\n"
23355 "\n"
23356 "layout (xfb_offset = 2 * sizeof_type) flat out TYPE vegeta;\n"
23357 " flat out TYPE trunks;\n"
23358 "layout (xfb_offset = 0) flat out TYPE goku;\n"
23359 "\n"
23360 /*
23361 There is no packing qualifier for uniform block gs_block, according to spec, it should be "shared" by default,
23362 the definition equals to "layout(binding=0, shared)", if the block is declared as shared, each block member will
23363 not be packed, and each block member's layout in memory is implementation dependent, so we can't use the API
23364 glBufferData() to update the UBO directly, we need to query each block member's offset first, then upload the
23365 data to the corresponding offset, otherwise we can't get the correct data from UBO; to make the test passed,
23366 we need to add the qualifier std140, and change the declaration as layout(binding=0, std140), which can make
23367 sure all the block members are packed and the application can upload the data by glBufferData() directly.
23368 */
23369 "layout(binding = 0, std140) uniform gs_block {\n"
23370 " TYPE uni_vegeta;\n"
23371 " TYPE uni_trunks;\n"
23372 " TYPE uni_goku;\n"
23373 "};\n";
23374 static const GLchar* fs = "flat in TYPE vegeta;\n"
23375 "flat in TYPE trunks;\n"
23376 "flat in TYPE goku;\n"
23377 "\n"
23378 "out vec4 fs_out;\n";
23379
23380 const Utils::Type& type = getType(test_case_index);
23381
23382 switch (stage)
23383 {
23384 case Utils::Shader::FRAGMENT:
23385 out_interface = fs;
23386 break;
23387 case Utils::Shader::GEOMETRY:
23388 out_interface = gs;
23389 break;
23390 default:
23391 out_interface = "";
23392 return;
23393 }
23394
23395 if (Utils::Shader::GEOMETRY == stage)
23396 {
23397 GLchar buffer[16];
23398 size_t position = 0;
23399 const GLuint type_size = type.GetSize();
23400
23401 sprintf(buffer, "%d", type_size);
23402
23403 Utils::replaceToken("SIZE", position, buffer, out_interface);
23404 }
23405
23406 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_interface);
23407 }
23408
23409 /** Get type name
23410 *
23411 * @param test_case_index Index of test case
23412 *
23413 * @return Name of type test in test_case_index
23414 **/
23415 std::string XFBOverrideQualifiersWithAPITest::getTestCaseName(glw::GLuint test_case_index)
23416 {
23417 return getTypeName(test_case_index);
23418 }
23419
23420 /** Returns number of types to test
23421 *
23422 * @return Number of types, 34
23423 **/
23424 glw::GLuint XFBOverrideQualifiersWithAPITest::getTestCaseNumber()
23425 {
23426 return getTypesNumber();
23427 }
23428
23429 /** Inspects program to check if all resources are as expected
23430 *
23431 * @param test_case_index Index of test case
23432 * @param program Program instance
23433 * @param out_stream Error message
23434 *
23435 * @return true if everything is ok, false otherwise
23436 **/
23437 bool XFBOverrideQualifiersWithAPITest::inspectProgram(GLuint test_case_index, Utils::Program& program,
23438 std::stringstream& out_stream)
23439 {
23440 GLint stride = 0;
23441 const Utils::Type& type = getType(test_case_index);
23442 const GLuint type_size = type.GetSize(false);
23443
23444 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
23445 1 /* buf_size */, &stride);
23446
23447 if ((GLint)(3 * type_size) != stride)
23448 {
23449 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
23450
23451 return false;
23452 }
23453
23454 return true;
23455 }
23456
23457 /** Constructor
23458 *
23459 * @param context Test context
23460 **/
23461 XFBVertexStreamsTest::XFBVertexStreamsTest(deqp::Context& context)
23462 : BufferTestBase(context, "xfb_vertex_streams",
23463 "Test verifies that xfb qualifier works with multiple output streams")
23464 {
23465 /* Nothing to be done here */
23466 }
23467
23468 /** Get descriptors of buffers necessary for test
23469 *
23470 * @param ignored
23471 * @param out_descriptors Descriptors of buffers used by test
23472 **/
23473 void XFBVertexStreamsTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
23474 bufferDescriptor::Vector& out_descriptors)
23475 {
23476 const Utils::Type& type = Utils::Type::vec4;
23477
23478 /* Test needs single uniform and three xfbs */
23479 out_descriptors.resize(4);
23480
23481 /* Get references */
23482 bufferDescriptor& uniform = out_descriptors[0];
23483 bufferDescriptor& xfb_1 = out_descriptors[1];
23484 bufferDescriptor& xfb_2 = out_descriptors[2];
23485 bufferDescriptor& xfb_3 = out_descriptors[3];
23486
23487 /* Index */
23488 uniform.m_index = 0;
23489 xfb_1.m_index = 1;
23490 xfb_2.m_index = 2;
23491 xfb_3.m_index = 3;
23492
23493 /* Target */
23494 uniform.m_target = Utils::Buffer::Uniform;
23495 xfb_1.m_target = Utils::Buffer::Transform_feedback;
23496 xfb_2.m_target = Utils::Buffer::Transform_feedback;
23497 xfb_3.m_target = Utils::Buffer::Transform_feedback;
23498
23499 /* Data */
23500 const std::vector<GLubyte>& goku_data = type.GenerateData();
23501 const std::vector<GLubyte>& gohan_data = type.GenerateData();
23502 const std::vector<GLubyte>& goten_data = type.GenerateData();
23503 const std::vector<GLubyte>& picolo_data = type.GenerateData();
23504 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
23505 const std::vector<GLubyte>& bulma_data = type.GenerateData();
23506
23507 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
23508
23509 /* Uniform data */
23510 uniform.m_initial_data.resize(6 * type_size);
23511 memcpy(&uniform.m_initial_data[0] + 0, &goku_data[0], type_size);
23512 memcpy(&uniform.m_initial_data[0] + type_size, &gohan_data[0], type_size);
23513 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
23514 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &picolo_data[0], type_size);
23515 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
23516 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &bulma_data[0], type_size);
23517
23518 /* XFB data */
23519 static const GLuint xfb_stride = 64;
23520 xfb_1.m_initial_data.resize(xfb_stride);
23521 xfb_1.m_expected_data.resize(xfb_stride);
23522 xfb_2.m_initial_data.resize(xfb_stride);
23523 xfb_2.m_expected_data.resize(xfb_stride);
23524 xfb_3.m_initial_data.resize(xfb_stride);
23525 xfb_3.m_expected_data.resize(xfb_stride);
23526
23527 for (GLuint i = 0; i < xfb_stride; ++i)
23528 {
23529 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
23530 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
23531 xfb_2.m_initial_data[i] = (glw::GLubyte)i;
23532 xfb_2.m_expected_data[i] = (glw::GLubyte)i;
23533 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
23534 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
23535 }
23536
23537 memcpy(&xfb_1.m_expected_data[0] + 48, &goku_data[0], type_size);
23538 memcpy(&xfb_1.m_expected_data[0] + 32, &gohan_data[0], type_size);
23539 memcpy(&xfb_1.m_expected_data[0] + 16, &goten_data[0], type_size);
23540 memcpy(&xfb_3.m_expected_data[0] + 48, &picolo_data[0], type_size);
23541 memcpy(&xfb_3.m_expected_data[0] + 32, &vegeta_data[0], type_size);
23542 memcpy(&xfb_2.m_expected_data[0] + 32, &bulma_data[0], type_size);
23543 }
23544
23545 /** Get body of main function for given shader stage
23546 *
23547 * @param ignored
23548 * @param stage Shader stage
23549 * @param out_assignments Set to empty
23550 * @param out_calculations Set to empty
23551 **/
23552 void XFBVertexStreamsTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23553 std::string& out_assignments, std::string& out_calculations)
23554 {
23555 out_calculations = "";
23556
23557 // the shader declares the output variables with different "stream" qualifier, to make the data can export to
23558 // each stream, we must call the function EmitStreamVertex() and EndStreamPrimitive() to make each vertex emitted
23559 // by the GS is assigned to specific stream.
23560 static const GLchar* gs = " goku = uni_goku;\n"
23561 " gohan = uni_gohan;\n"
23562 " goten = uni_goten;\n"
23563 " EmitStreamVertex(0);\n"
23564 " EndStreamPrimitive(0);\n"
23565 " picolo = uni_picolo;\n"
23566 " vegeta = uni_vegeta;\n"
23567 " EmitStreamVertex(1);\n"
23568 " EndStreamPrimitive(1);\n"
23569 " bulma = uni_bulma;\n"
23570 " EmitStreamVertex(2);\n"
23571 " EndStreamPrimitive(2);\n";
23572
23573 static const GLchar* fs = " fs_out = gohan + goku + goten;\n";
23574
23575 const GLchar* assignments = "";
23576 switch (stage)
23577 {
23578 case Utils::Shader::FRAGMENT:
23579 assignments = fs;
23580 break;
23581 case Utils::Shader::GEOMETRY:
23582 assignments = gs;
23583 break;
23584 default:
23585 break;
23586 }
23587
23588 out_assignments = assignments;
23589 }
23590
23591 /** Get interface of shader
23592 *
23593 * @param ignored
23594 * @param stage Shader stage
23595 * @param out_interface Set to ""
23596 **/
23597 void XFBVertexStreamsTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23598 std::string& out_interface)
23599 {
23600 static const GLchar* gs = "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
23601 "layout (xfb_buffer = 2, xfb_stride = 64) out;\n"
23602 "layout (xfb_buffer = 3, xfb_stride = 64) out;\n"
23603 "\n"
23604 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23605 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23606 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n"
23607 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 48) out vec4 picolo;\n"
23608 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 32) out vec4 vegeta;\n"
23609 "layout (stream = 2, xfb_buffer = 2, xfb_offset = 32) out vec4 bulma;\n"
23610 "\n"
23611 "layout(binding = 0) uniform gs_block {\n"
23612 " vec4 uni_goku;\n"
23613 " vec4 uni_gohan;\n"
23614 " vec4 uni_goten;\n"
23615 " vec4 uni_picolo;\n"
23616 " vec4 uni_vegeta;\n"
23617 " vec4 uni_bulma;\n"
23618 "};\n";
23619 /*
23620 Fixed incorrect usage of in/out qualifier, the following variable should be input symbols for fragment shader
23621 */
23622 static const GLchar* fs = "in vec4 goku;\n"
23623 "in vec4 gohan;\n"
23624 "in vec4 goten;\n"
23625 "\n"
23626 "out vec4 fs_out;\n";
23627
23628 switch (stage)
23629 {
23630 case Utils::Shader::FRAGMENT:
23631 out_interface = fs;
23632 break;
23633 case Utils::Shader::GEOMETRY:
23634 out_interface = gs;
23635 break;
23636 default:
23637 out_interface = "";
23638 return;
23639 }
23640 }
23641
23642 /** Constructor
23643 *
23644 * @param context Test framework context
23645 **/
23646 XFBMultipleVertexStreamsTest::XFBMultipleVertexStreamsTest(deqp::Context& context)
23647 : NegativeTestBase(
23648 context, "xfb_multiple_vertex_streams",
23649 "Test verifies that compiler reports error when multiple streams are captured with same xfb_buffer")
23650 {
23651 }
23652
23653 /** Source for given test case and stage
23654 *
23655 * @param ignored
23656 * @param stage Shader stage
23657 *
23658 * @return Shader source
23659 **/
23660 std::string XFBMultipleVertexStreamsTest::getShaderSource(GLuint /* test_case_index */, Utils::Shader::STAGES stage)
23661 {
23662 static const GLchar* var_definition = "const uint valid_stride = 64;\n"
23663 "\n"
23664 "layout (xfb_buffer = 1, xfb_stride = valid_stride) out;\n"
23665 "layout (xfb_buffer = 3, xfb_stride = valid_stride) out;\n"
23666 "\n"
23667 "\n"
23668 #if DEBUG_NEG_REMOVE_ERROR
23669 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23670 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 32) out vec4 gohan;\n"
23671 "layout (stream = 2, xfb_buffer = 2, xfb_offset = 16) out vec4 goten;\n";
23672 #else
23673 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23674 "layout (stream = 1, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23675 "layout (stream = 2, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n";
23676 #endif /* DEBUG_NEG_REMOVE_ERROR */
23677 static const GLchar* var_use = " goku = result / 2;\n"
23678 " gohan = result / 4;\n"
23679 " goten = result / 6;\n";
23680 static const GLchar* fs = "#version 430 core\n"
23681 "#extension GL_ARB_enhanced_layouts : require\n"
23682 "\n"
23683 "in vec4 gs_fs;\n"
23684 "in vec4 goku;\n"
23685 "out vec4 fs_out;\n"
23686 "\n"
23687 "void main()\n"
23688 "{\n"
23689 " fs_out = gs_fs + goku;\n"
23690 "}\n"
23691 "\n";
23692 static const GLchar* gs = "#version 430 core\n"
23693 "#extension GL_ARB_enhanced_layouts : require\n"
23694 "\n"
23695 "layout(points) in;\n"
23696 "layout(triangle_strip, max_vertices = 4) out;\n"
23697 "\n"
23698 "VAR_DEFINITION"
23699 "\n"
23700 "in vec4 vs_gs[];\n"
23701 "out vec4 gs_fs;\n"
23702 "\n"
23703 "void main()\n"
23704 "{\n"
23705 " vec4 result = vs_gs[0];\n"
23706 "\n"
23707 "VARIABLE_USE"
23708 "\n"
23709 " gs_fs = result;\n"
23710 " gl_Position = vec4(-1, -1, 0, 1);\n"
23711 " EmitVertex();\n"
23712 " gs_fs = result;\n"
23713 " gl_Position = vec4(-1, 1, 0, 1);\n"
23714 " EmitVertex();\n"
23715 " gs_fs = result;\n"
23716 " gl_Position = vec4(1, -1, 0, 1);\n"
23717 " EmitVertex();\n"
23718 " gs_fs = result;\n"
23719 " gl_Position = vec4(1, 1, 0, 1);\n"
23720 " EmitVertex();\n"
23721 "}\n"
23722 "\n";
23723 static const GLchar* vs = "#version 430 core\n"
23724 "#extension GL_ARB_enhanced_layouts : require\n"
23725 "\n"
23726 "in vec4 in_vs;\n"
23727 "out vec4 vs_gs;\n"
23728 "\n"
23729 "void main()\n"
23730 "{\n"
23731 " vs_gs = in_vs;\n"
23732 "}\n"
23733 "\n";
23734
23735 std::string source;
23736
23737 if (Utils::Shader::GEOMETRY == stage)
23738 {
23739 size_t position = 0;
23740
23741 source = gs;
23742
23743 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23744 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23745 }
23746 else
23747 {
23748 switch (stage)
23749 {
23750 case Utils::Shader::FRAGMENT:
23751 source = fs;
23752 break;
23753 case Utils::Shader::VERTEX:
23754 source = vs;
23755 break;
23756 default:
23757 source = "";
23758 }
23759 }
23760
23761 return source;
23762 }
23763
23764 /** Selects if "compute" stage is relevant for test
23765 *
23766 * @param ignored
23767 *
23768 * @return false
23769 **/
23770 bool XFBMultipleVertexStreamsTest::isComputeRelevant(GLuint /* test_case_index */)
23771 {
23772 return false;
23773 }
23774
23775 /** Constructor
23776 *
23777 * @param context Test framework context
23778 **/
23779 XFBExceedBufferLimitTest::XFBExceedBufferLimitTest(deqp::Context& context)
23780 : NegativeTestBase(context, "xfb_exceed_buffer_limit",
23781 "Test verifies that compiler reports error when xfb_buffer qualifier exceeds limit")
23782 {
23783 }
23784
23785 /** Source for given test case and stage
23786 *
23787 * @param test_case_index Index of test case
23788 * @param stage Shader stage
23789 *
23790 * @return Shader source
23791 **/
23792 std::string XFBExceedBufferLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
23793 {
23794 static const GLchar* block_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23795 "\n"
23796 #if DEBUG_NEG_REMOVE_ERROR
23797 "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
23798 #else
23799 "layout (xfb_buffer = buffer_index, xfb_offset = 0) out Goku {\n"
23800 #endif /* DEBUG_NEG_REMOVE_ERROR */
23801 " vec4 member;\n"
23802 "} goku;\n";
23803 static const GLchar* global_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23804 "\n"
23805 #if DEBUG_NEG_REMOVE_ERROR
23806 "layout (xfb_buffer = 0) out;\n";
23807 #else
23808 "layout (xfb_buffer = buffer_index) out;\n";
23809 #endif /* DEBUG_NEG_REMOVE_ERROR */
23810 static const GLchar* vector_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23811 "\n"
23812 #if DEBUG_NEG_REMOVE_ERROR
23813 "layout (xfb_buffer = 0) out vec4 goku;\n";
23814 #else
23815 "layout (xfb_buffer = buffer_index) out vec4 goku;\n";
23816 #endif /* DEBUG_NEG_REMOVE_ERROR */
23817 static const GLchar* block_use = " goku.member = result / 2;\n";
23818 static const GLchar* global_use = "";
23819 static const GLchar* vector_use = " goku = result / 2;\n";
23820 static const GLchar* fs = "#version 430 core\n"
23821 "#extension GL_ARB_enhanced_layouts : require\n"
23822 "\n"
23823 "in vec4 any_fs;\n"
23824 "out vec4 fs_out;\n"
23825 "\n"
23826 "void main()\n"
23827 "{\n"
23828 " fs_out = any_fs;\n"
23829 "}\n"
23830 "\n";
23831 static const GLchar* gs_tested = "#version 430 core\n"
23832 "#extension GL_ARB_enhanced_layouts : require\n"
23833 "\n"
23834 "layout(points) in;\n"
23835 "layout(triangle_strip, max_vertices = 4) out;\n"
23836 "\n"
23837 "VAR_DEFINITION"
23838 "\n"
23839 "in vec4 vs_any[];\n"
23840 "out vec4 any_fs;\n"
23841 "\n"
23842 "void main()\n"
23843 "{\n"
23844 " vec4 result = vs_any[0];\n"
23845 "\n"
23846 "VARIABLE_USE"
23847 "\n"
23848 " any_fs = result;\n"
23849 " gl_Position = vec4(-1, -1, 0, 1);\n"
23850 " EmitVertex();\n"
23851 " any_fs = result;\n"
23852 " gl_Position = vec4(-1, 1, 0, 1);\n"
23853 " EmitVertex();\n"
23854 " any_fs = result;\n"
23855 " gl_Position = vec4(1, -1, 0, 1);\n"
23856 " EmitVertex();\n"
23857 " any_fs = result;\n"
23858 " gl_Position = vec4(1, 1, 0, 1);\n"
23859 " EmitVertex();\n"
23860 "}\n"
23861 "\n";
23862 static const GLchar* tcs = "#version 430 core\n"
23863 "#extension GL_ARB_enhanced_layouts : require\n"
23864 "\n"
23865 "layout(vertices = 1) out;\n"
23866 "\n"
23867 "in vec4 vs_any[];\n"
23868 "out vec4 tcs_tes[];\n"
23869 "\n"
23870 "void main()\n"
23871 "{\n"
23872 "\n"
23873 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
23874 "\n"
23875 " gl_TessLevelOuter[0] = 1.0;\n"
23876 " gl_TessLevelOuter[1] = 1.0;\n"
23877 " gl_TessLevelOuter[2] = 1.0;\n"
23878 " gl_TessLevelOuter[3] = 1.0;\n"
23879 " gl_TessLevelInner[0] = 1.0;\n"
23880 " gl_TessLevelInner[1] = 1.0;\n"
23881 "}\n"
23882 "\n";
23883 static const GLchar* tes_tested = "#version 430 core\n"
23884 "#extension GL_ARB_enhanced_layouts : require\n"
23885 "\n"
23886 "layout(isolines, point_mode) in;\n"
23887 "\n"
23888 "VAR_DEFINITION"
23889 "\n"
23890 "in vec4 tcs_tes[];\n"
23891 "out vec4 any_fs;\n"
23892 "\n"
23893 "void main()\n"
23894 "{\n"
23895 " vec4 result = tcs_tes[0];\n"
23896 "\n"
23897 "VARIABLE_USE"
23898 "\n"
23899 " any_fs += result;\n"
23900 "}\n"
23901 "\n";
23902 static const GLchar* vs = "#version 430 core\n"
23903 "#extension GL_ARB_enhanced_layouts : require\n"
23904 "\n"
23905 "in vec4 in_vs;\n"
23906 "out vec4 vs_any;\n"
23907 "\n"
23908 "void main()\n"
23909 "{\n"
23910 " vs_any = in_vs;\n"
23911 "}\n"
23912 "\n";
23913 static const GLchar* vs_tested = "#version 430 core\n"
23914 "#extension GL_ARB_enhanced_layouts : require\n"
23915 "\n"
23916 "VAR_DEFINITION"
23917 "\n"
23918 "in vec4 in_vs;\n"
23919 "out vec4 any_fs;\n"
23920 "\n"
23921 "void main()\n"
23922 "{\n"
23923 " vec4 result = in_vs;\n"
23924 "\n"
23925 "VARIABLE_USE"
23926 "\n"
23927 " any_fs = result;\n"
23928 "}\n"
23929 "\n";
23930
23931 std::string source;
23932 testCase& test_case = m_test_cases[test_case_index];
23933
23934 if (test_case.m_stage == stage)
23935 {
23936 GLchar buffer[16];
23937 const Functions& gl = m_context.getRenderContext().getFunctions();
23938 GLint max_n_xfb = 0;
23939 size_t position = 0;
23940 const GLchar* var_definition = 0;
23941 const GLchar* var_use = 0;
23942
23943 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_n_xfb);
23944 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23945
23946 sprintf(buffer, "%d", max_n_xfb);
23947
23948 switch (test_case.m_case)
23949 {
23950 case BLOCK:
23951 var_definition = block_var_definition;
23952 var_use = block_use;
23953 break;
23954 case GLOBAL:
23955 var_definition = global_var_definition;
23956 var_use = global_use;
23957 break;
23958 case VECTOR:
23959 var_definition = vector_var_definition;
23960 var_use = vector_use;
23961 break;
23962 default:
23963 TCU_FAIL("Invalid enum");
23964 }
23965
23966 switch (stage)
23967 {
23968 case Utils::Shader::GEOMETRY:
23969 source = gs_tested;
23970 break;
23971 case Utils::Shader::TESS_EVAL:
23972 source = tes_tested;
23973 break;
23974 case Utils::Shader::VERTEX:
23975 source = vs_tested;
23976 break;
23977 default:
23978 TCU_FAIL("Invalid enum");
23979 }
23980
23981 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23982 position = 0;
23983 Utils::replaceToken("MAX_BUFFER", position, buffer, source);
23984 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23985 }
23986 else
23987 {
23988 switch (test_case.m_stage)
23989 {
23990 case Utils::Shader::GEOMETRY:
23991 switch (stage)
23992 {
23993 case Utils::Shader::FRAGMENT:
23994 source = fs;
23995 break;
23996 case Utils::Shader::VERTEX:
23997 source = vs;
23998 break;
23999 default:
24000 source = "";
24001 }
24002 break;
24003 case Utils::Shader::TESS_EVAL:
24004 switch (stage)
24005 {
24006 case Utils::Shader::FRAGMENT:
24007 source = fs;
24008 break;
24009 case Utils::Shader::TESS_CTRL:
24010 source = tcs;
24011 break;
24012 case Utils::Shader::VERTEX:
24013 source = vs;
24014 break;
24015 default:
24016 source = "";
24017 }
24018 break;
24019 case Utils::Shader::VERTEX:
24020 switch (stage)
24021 {
24022 case Utils::Shader::FRAGMENT:
24023 source = fs;
24024 break;
24025 default:
24026 source = "";
24027 }
24028 break;
24029 default:
24030 TCU_FAIL("Invalid enum");
24031 }
24032 }
24033
24034 return source;
24035 }
24036
24037 /** Get description of test case
24038 *
24039 * @param test_case_index Index of test case
24040 *
24041 * @return Test case description
24042 **/
24043 std::string XFBExceedBufferLimitTest::getTestCaseName(GLuint test_case_index)
24044 {
24045 std::stringstream stream;
24046 testCase& test_case = m_test_cases[test_case_index];
24047
24048 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
24049
24050 switch (test_case.m_case)
24051 {
24052 case BLOCK:
24053 stream << "BLOCK";
24054 break;
24055 case GLOBAL:
24056 stream << "GLOBAL";
24057 break;
24058 case VECTOR:
24059 stream << "VECTOR";
24060 break;
24061 default:
24062 TCU_FAIL("Invalid enum");
24063 }
24064
24065 return stream.str();
24066 }
24067
24068 /** Get number of test cases
24069 *
24070 * @return Number of test cases
24071 **/
24072 GLuint XFBExceedBufferLimitTest::getTestCaseNumber()
24073 {
24074 return static_cast<GLuint>(m_test_cases.size());
24075 }
24076
24077 /** Selects if "compute" stage is relevant for test
24078 *
24079 * @param ignored
24080 *
24081 * @return false
24082 **/
24083 bool XFBExceedBufferLimitTest::isComputeRelevant(GLuint /* test_case_index */)
24084 {
24085 return false;
24086 }
24087
24088 /** Prepare all test cases
24089 *
24090 **/
24091 void XFBExceedBufferLimitTest::testInit()
24092 {
24093 for (GLuint c = 0; c < CASE_MAX; ++c)
24094 {
24095 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24096 {
24097 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
24098 (Utils::Shader::FRAGMENT == stage))
24099 {
24100 continue;
24101 }
24102
24103 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
24104
24105 m_test_cases.push_back(test_case);
24106 }
24107 }
24108 }
24109
24110 /** Constructor
24111 *
24112 * @param context Test framework context
24113 **/
24114 XFBExceedOffsetLimitTest::XFBExceedOffsetLimitTest(deqp::Context& context)
24115 : NegativeTestBase(context, "xfb_exceed_offset_limit",
24116 "Test verifies that compiler reports error when xfb_offset qualifier exceeds limit")
24117 {
24118 }
24119
24120 /** Source for given test case and stage
24121 *
24122 * @param test_case_index Index of test case
24123 * @param stage Shader stage
24124 *
24125 * @return Shader source
24126 **/
24127 std::string XFBExceedOffsetLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24128 {
24129 static const GLchar* block_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24130 "\n"
24131 #if DEBUG_NEG_REMOVE_ERROR
24132 "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
24133 #else
24134 "layout (xfb_buffer = 0, xfb_offset = overflow_offset + 16) out Goku "
24135 "{\n"
24136 #endif /* DEBUG_NEG_REMOVE_ERROR */
24137 " vec4 member;\n"
24138 "} goku;\n";
24139 static const GLchar* global_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24140 "\n"
24141 #if DEBUG_NEG_REMOVE_ERROR
24142 "layout (xfb_buffer = 0, xfb_stride = 0) out;\n";
24143 #else
24144 "layout (xfb_buffer = 0, xfb_stride = overflow_offset) out;\n";
24145 #endif /* DEBUG_NEG_REMOVE_ERROR */
24146 static const GLchar* vector_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24147 "\n"
24148 #if DEBUG_NEG_REMOVE_ERROR
24149 "layout (xfb_buffer = 0, xfb_offset = 0) out vec4 goku;\n";
24150 #else
24151 "layout (xfb_buffer = 0, xfb_offset = overflow_offset) out vec4 "
24152 "goku;\n";
24153 #endif /* DEBUG_NEG_REMOVE_ERROR */
24154 static const GLchar* block_use = " goku.member = result / 2;\n";
24155 static const GLchar* global_use = "";
24156 static const GLchar* vector_use = " goku = result / 2;\n";
24157 static const GLchar* fs = "#version 430 core\n"
24158 "#extension GL_ARB_enhanced_layouts : require\n"
24159 "\n"
24160 "in vec4 any_fs;\n"
24161 "out vec4 fs_out;\n"
24162 "\n"
24163 "void main()\n"
24164 "{\n"
24165 " fs_out = any_fs;\n"
24166 "}\n"
24167 "\n";
24168 static const GLchar* gs_tested = "#version 430 core\n"
24169 "#extension GL_ARB_enhanced_layouts : require\n"
24170 "\n"
24171 "layout(points) in;\n"
24172 "layout(triangle_strip, max_vertices = 4) out;\n"
24173 "\n"
24174 "VAR_DEFINITION"
24175 "\n"
24176 "in vec4 vs_any[];\n"
24177 "out vec4 any_fs;\n"
24178 "\n"
24179 "void main()\n"
24180 "{\n"
24181 " vec4 result = vs_any[0];\n"
24182 "\n"
24183 "VARIABLE_USE"
24184 "\n"
24185 " any_fs = result;\n"
24186 " gl_Position = vec4(-1, -1, 0, 1);\n"
24187 " EmitVertex();\n"
24188 " any_fs = result;\n"
24189 " gl_Position = vec4(-1, 1, 0, 1);\n"
24190 " EmitVertex();\n"
24191 " any_fs = result;\n"
24192 " gl_Position = vec4(1, -1, 0, 1);\n"
24193 " EmitVertex();\n"
24194 " any_fs = result;\n"
24195 " gl_Position = vec4(1, 1, 0, 1);\n"
24196 " EmitVertex();\n"
24197 "}\n"
24198 "\n";
24199 static const GLchar* tcs = "#version 430 core\n"
24200 "#extension GL_ARB_enhanced_layouts : require\n"
24201 "\n"
24202 "layout(vertices = 1) out;\n"
24203 "\n"
24204 "in vec4 vs_any[];\n"
24205 "out vec4 tcs_tes[];\n"
24206 "\n"
24207 "void main()\n"
24208 "{\n"
24209 "\n"
24210 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
24211 "\n"
24212 " gl_TessLevelOuter[0] = 1.0;\n"
24213 " gl_TessLevelOuter[1] = 1.0;\n"
24214 " gl_TessLevelOuter[2] = 1.0;\n"
24215 " gl_TessLevelOuter[3] = 1.0;\n"
24216 " gl_TessLevelInner[0] = 1.0;\n"
24217 " gl_TessLevelInner[1] = 1.0;\n"
24218 "}\n"
24219 "\n";
24220 static const GLchar* tes_tested = "#version 430 core\n"
24221 "#extension GL_ARB_enhanced_layouts : require\n"
24222 "\n"
24223 "layout(isolines, point_mode) in;\n"
24224 "\n"
24225 "VAR_DEFINITION"
24226 "\n"
24227 "in vec4 tcs_tes[];\n"
24228 "out vec4 any_fs;\n"
24229 "\n"
24230 "void main()\n"
24231 "{\n"
24232 " vec4 result = tcs_tes[0];\n"
24233 "\n"
24234 "VARIABLE_USE"
24235 "\n"
24236 " any_fs += result;\n"
24237 "}\n"
24238 "\n";
24239 static const GLchar* vs = "#version 430 core\n"
24240 "#extension GL_ARB_enhanced_layouts : require\n"
24241 "\n"
24242 "in vec4 in_vs;\n"
24243 "out vec4 vs_any;\n"
24244 "\n"
24245 "void main()\n"
24246 "{\n"
24247 " vs_any = in_vs;\n"
24248 "}\n"
24249 "\n";
24250 static const GLchar* vs_tested = "#version 430 core\n"
24251 "#extension GL_ARB_enhanced_layouts : require\n"
24252 "\n"
24253 "VAR_DEFINITION"
24254 "\n"
24255 "in vec4 in_vs;\n"
24256 "out vec4 any_fs;\n"
24257 "\n"
24258 "void main()\n"
24259 "{\n"
24260 " vec4 result = in_vs;\n"
24261 "\n"
24262 "VARIABLE_USE"
24263 "\n"
24264 " any_fs = result;\n"
24265 "}\n"
24266 "\n";
24267
24268 std::string source;
24269 testCase& test_case = m_test_cases[test_case_index];
24270
24271 if (test_case.m_stage == stage)
24272 {
24273 GLchar buffer[16];
24274 const Functions& gl = m_context.getRenderContext().getFunctions();
24275 GLint max_n_xfb_comp = 0;
24276 GLint max_n_xfb_bytes = 0;
24277 size_t position = 0;
24278 const GLchar* var_definition = 0;
24279 const GLchar* var_use = 0;
24280
24281 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_n_xfb_comp);
24282 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
24283
24284 max_n_xfb_bytes = max_n_xfb_comp * 4;
24285
24286 sprintf(buffer, "%d", max_n_xfb_bytes);
24287
24288 switch (test_case.m_case)
24289 {
24290 case BLOCK:
24291 var_definition = block_var_definition;
24292 var_use = block_use;
24293 break;
24294 case GLOBAL:
24295 var_definition = global_var_definition;
24296 var_use = global_use;
24297 break;
24298 case VECTOR:
24299 var_definition = vector_var_definition;
24300 var_use = vector_use;
24301 break;
24302 default:
24303 TCU_FAIL("Invalid enum");
24304 }
24305
24306 switch (stage)
24307 {
24308 case Utils::Shader::GEOMETRY:
24309 source = gs_tested;
24310 break;
24311 case Utils::Shader::TESS_EVAL:
24312 source = tes_tested;
24313 break;
24314 case Utils::Shader::VERTEX:
24315 source = vs_tested;
24316 break;
24317 default:
24318 TCU_FAIL("Invalid enum");
24319 }
24320
24321 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
24322 position = 0;
24323 Utils::replaceToken("MAX_SIZE", position, buffer, source);
24324 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
24325 }
24326 else
24327 {
24328 switch (test_case.m_stage)
24329 {
24330 case Utils::Shader::GEOMETRY:
24331 switch (stage)
24332 {
24333 case Utils::Shader::FRAGMENT:
24334 source = fs;
24335 break;
24336 case Utils::Shader::VERTEX:
24337 source = vs;
24338 break;
24339 default:
24340 source = "";
24341 }
24342 break;
24343 case Utils::Shader::TESS_EVAL:
24344 switch (stage)
24345 {
24346 case Utils::Shader::FRAGMENT:
24347 source = fs;
24348 break;
24349 case Utils::Shader::TESS_CTRL:
24350 source = tcs;
24351 break;
24352 case Utils::Shader::VERTEX:
24353 source = vs;
24354 break;
24355 default:
24356 source = "";
24357 }
24358 break;
24359 case Utils::Shader::VERTEX:
24360 switch (stage)
24361 {
24362 case Utils::Shader::FRAGMENT:
24363 source = fs;
24364 break;
24365 default:
24366 source = "";
24367 }
24368 break;
24369 default:
24370 TCU_FAIL("Invalid enum");
24371 }
24372 }
24373
24374 return source;
24375 }
24376
24377 /** Get description of test case
24378 *
24379 * @param test_case_index Index of test case
24380 *
24381 * @return Test case description
24382 **/
24383 std::string XFBExceedOffsetLimitTest::getTestCaseName(GLuint test_case_index)
24384 {
24385 std::stringstream stream;
24386 testCase& test_case = m_test_cases[test_case_index];
24387
24388 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
24389
24390 switch (test_case.m_case)
24391 {
24392 case BLOCK:
24393 stream << "BLOCK";
24394 break;
24395 case GLOBAL:
24396 stream << "GLOBAL";
24397 break;
24398 case VECTOR:
24399 stream << "VECTOR";
24400 break;
24401 default:
24402 TCU_FAIL("Invalid enum");
24403 }
24404
24405 return stream.str();
24406 }
24407
24408 /** Get number of test cases
24409 *
24410 * @return Number of test cases
24411 **/
24412 GLuint XFBExceedOffsetLimitTest::getTestCaseNumber()
24413 {
24414 return static_cast<GLuint>(m_test_cases.size());
24415 }
24416
24417 /** Selects if "compute" stage is relevant for test
24418 *
24419 * @param ignored
24420 *
24421 * @return false
24422 **/
24423 bool XFBExceedOffsetLimitTest::isComputeRelevant(GLuint /* test_case_index */)
24424 {
24425 return false;
24426 }
24427
24428 /** Prepare all test cases
24429 *
24430 **/
24431 void XFBExceedOffsetLimitTest::testInit()
24432 {
24433 for (GLuint c = 0; c < CASE_MAX; ++c)
24434 {
24435 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24436 {
24437 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
24438 (Utils::Shader::FRAGMENT == stage))
24439 {
24440 continue;
24441 }
24442
24443 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
24444
24445 m_test_cases.push_back(test_case);
24446 }
24447 }
24448 }
24449
24450 /** Constructor
24451 *
24452 * @param context Test context
24453 **/
24454 XFBGlobalBufferTest::XFBGlobalBufferTest(deqp::Context& context)
24455 : BufferTestBase(context, "xfb_global_buffer", "Test verifies that global xfb_buffer qualifier is respected")
24456 {
24457 /* Nothing to be done here */
24458 }
24459
24460 /** Get descriptors of buffers necessary for test
24461 *
24462 * @param test_case_index Index of test case
24463 * @param out_descriptors Descriptors of buffers used by test
24464 **/
24465 void XFBGlobalBufferTest::getBufferDescriptors(glw::GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24466 {
24467 // the function "getType(test_case_index)" can't return correct data type, so change code as following:
24468 const Utils::Type& type = m_test_cases[test_case_index].m_type;
24469
24470 /* Test needs single uniform and two xfbs */
24471 out_descriptors.resize(3);
24472
24473 /* Get references */
24474 bufferDescriptor& uniform = out_descriptors[0];
24475 bufferDescriptor& xfb_1 = out_descriptors[1];
24476 bufferDescriptor& xfb_3 = out_descriptors[2];
24477
24478 /* Index */
24479 uniform.m_index = 0;
24480 xfb_1.m_index = 1;
24481 xfb_3.m_index = 3;
24482
24483 /* Target */
24484 uniform.m_target = Utils::Buffer::Uniform;
24485 xfb_1.m_target = Utils::Buffer::Transform_feedback;
24486 xfb_3.m_target = Utils::Buffer::Transform_feedback;
24487
24488 /* Data */
24489 const GLuint gen_start = Utils::s_rand;
24490 const std::vector<GLubyte>& chichi_data = type.GenerateData();
24491 const std::vector<GLubyte>& bulma_data = type.GenerateData();
24492 const std::vector<GLubyte>& trunks_data = type.GenerateData();
24493 const std::vector<GLubyte>& bra_data = type.GenerateData();
24494 const std::vector<GLubyte>& gohan_data = type.GenerateData();
24495 const std::vector<GLubyte>& goten_data = type.GenerateData();
24496
24497 Utils::s_rand = gen_start;
24498 const std::vector<GLubyte>& chichi_data_pck = type.GenerateDataPacked();
24499 const std::vector<GLubyte>& bulma_data_pck = type.GenerateDataPacked();
24500 const std::vector<GLubyte>& trunks_data_pck = type.GenerateDataPacked();
24501 const std::vector<GLubyte>& bra_data_pck = type.GenerateDataPacked();
24502 const std::vector<GLubyte>& gohan_data_pck = type.GenerateDataPacked();
24503 const std::vector<GLubyte>& goten_data_pck = type.GenerateDataPacked();
24504
24505 const GLuint type_size = static_cast<GLuint>(chichi_data.size());
24506 const GLuint padded_type_size = type.GetBaseAlignment(false) * type.m_n_columns;
24507 const GLuint type_size_pck = static_cast<GLuint>(chichi_data_pck.size());
24508
24509 /* Uniform data */
24510 uniform.m_initial_data.resize(6 * padded_type_size);
24511 memcpy(&uniform.m_initial_data[0] + 0, &chichi_data[0], type_size);
24512 memcpy(&uniform.m_initial_data[0] + padded_type_size, &bulma_data[0], type_size);
24513 memcpy(&uniform.m_initial_data[0] + 2 * padded_type_size, &trunks_data[0], type_size);
24514 memcpy(&uniform.m_initial_data[0] + 3 * padded_type_size, &bra_data[0], type_size);
24515 memcpy(&uniform.m_initial_data[0] + 4 * padded_type_size, &gohan_data[0], type_size);
24516 memcpy(&uniform.m_initial_data[0] + 5 * padded_type_size, &goten_data[0], type_size);
24517
24518 /* XFB data */
24519 xfb_1.m_initial_data.resize(3 * type_size_pck);
24520 xfb_1.m_expected_data.resize(3 * type_size_pck);
24521 xfb_3.m_initial_data.resize(3 * type_size_pck);
24522 xfb_3.m_expected_data.resize(3 * type_size_pck);
24523
24524 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
24525 {
24526 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
24527 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
24528 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
24529 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
24530 }
24531
24532 memcpy(&xfb_3.m_expected_data[0] + 2 * type_size_pck, &chichi_data_pck[0], type_size_pck);
24533 memcpy(&xfb_1.m_expected_data[0] + 0 * type_size_pck, &bulma_data_pck[0], type_size_pck);
24534 memcpy(&xfb_1.m_expected_data[0] + 1 * type_size_pck, &trunks_data_pck[0], type_size_pck);
24535 memcpy(&xfb_1.m_expected_data[0] + 2 * type_size_pck, &bra_data_pck[0], type_size_pck);
24536 memcpy(&xfb_3.m_expected_data[0] + 0 * type_size_pck, &gohan_data_pck[0], type_size_pck);
24537 memcpy(&xfb_3.m_expected_data[0] + 1 * type_size_pck, &goten_data_pck[0], type_size_pck);
24538 }
24539
24540 /** Source for given test case and stage
24541 *
24542 * @param test_case_index Index of test case
24543 * @param stage Shader stage
24544 *
24545 * @return Shader source
24546 **/
24547 std::string XFBGlobalBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24548 {
24549 static const GLchar* fs =
24550 "#version 430 core\n"
24551 "#extension GL_ARB_enhanced_layouts : require\n"
24552 "\n"
24553 "flat in TYPE chichi;\n"
24554 "flat in TYPE bulma;\n"
24555 "in Vegeta {\n"
24556 " flat TYPE trunk;\n"
24557 " flat TYPE bra;\n"
24558 "} vegeta;\n"
24559 "in Goku {\n"
24560 " flat TYPE gohan;\n"
24561 " flat TYPE goten;\n"
24562 "} goku;\n"
24563 "\n"
24564 "out vec4 fs_out;\n"
24565 "\n"
24566 "void main()\n"
24567 "{\n"
24568 " fs_out = vec4(1);\n"
24569 " if (TYPE(1) != chichi + bulma + vegeta.trunk + vegeta.bra + goku.gohan + goku.goten)\n"
24570 " {\n"
24571 " fs_out = vec4(0);\n"
24572 " }\n"
24573 "}\n"
24574 "\n";
24575
24576 static const GLchar* gs = "#version 430 core\n"
24577 "#extension GL_ARB_enhanced_layouts : require\n"
24578 "\n"
24579 "layout(points) in;\n"
24580 "layout(points, max_vertices = 1) out;\n"
24581 "\n"
24582 "INTERFACE"
24583 "\n"
24584 "void main()\n"
24585 "{\n"
24586 "ASSIGNMENTS"
24587 " EmitVertex();\n"
24588 "}\n"
24589 "\n";
24590
24591 static const GLchar* tcs = "#version 430 core\n"
24592 "#extension GL_ARB_enhanced_layouts : require\n"
24593 "\n"
24594 "layout(vertices = 1) out;\n"
24595 "\n"
24596 "\n"
24597 "void main()\n"
24598 "{\n"
24599 " gl_TessLevelOuter[0] = 1.0;\n"
24600 " gl_TessLevelOuter[1] = 1.0;\n"
24601 " gl_TessLevelOuter[2] = 1.0;\n"
24602 " gl_TessLevelOuter[3] = 1.0;\n"
24603 " gl_TessLevelInner[0] = 1.0;\n"
24604 " gl_TessLevelInner[1] = 1.0;\n"
24605 "}\n"
24606 "\n";
24607
24608 static const GLchar* tes = "#version 430 core\n"
24609 "#extension GL_ARB_enhanced_layouts : require\n"
24610 "\n"
24611 "layout(isolines, point_mode) in;\n"
24612 "\n"
24613 "INTERFACE"
24614 "\n"
24615 "void main()\n"
24616 "{\n"
24617 "ASSIGNMENTS"
24618 "}\n"
24619 "\n";
24620
24621 static const GLchar* vs = "#version 430 core\n"
24622 "#extension GL_ARB_enhanced_layouts : require\n"
24623 "\n"
24624 "void main()\n"
24625 "{\n"
24626 "}\n"
24627 "\n";
24628
24629 static const GLchar* vs_tested = "#version 430 core\n"
24630 "#extension GL_ARB_enhanced_layouts : require\n"
24631 "\n"
24632 "INTERFACE"
24633 "\n"
24634 "void main()\n"
24635 "{\n"
24636 "ASSIGNMENTS"
24637 "}\n"
24638 "\n";
24639
24640 std::string source;
24641 const _testCase& test_case = m_test_cases[test_case_index];
24642 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
24643
24644 if (test_case.m_stage == stage)
24645 {
24646 std::string assignments = " chichi = uni_chichi;\n"
24647 " bulma = uni_bulma;\n"
24648 " vegeta.trunk = uni_trunk;\n"
24649 " vegeta.bra = uni_bra;\n"
24650 " goku.gohan = uni_gohan;\n"
24651 " goku.goten = uni_goten;\n";
24652
24653 std::string interface = "layout (xfb_buffer = 3) out;\n"
24654 "\n"
24655 "const uint type_size = SIZE;\n"
24656 "\n"
24657 "layout ( xfb_offset = 2 * type_size) flat out TYPE chichi;\n"
24658 "layout (xfb_buffer = 1, xfb_offset = 0) flat out TYPE bulma;\n"
24659 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out Vegeta {\n"
24660 " flat TYPE trunk;\n"
24661 " flat TYPE bra;\n"
24662 "} vegeta;\n"
24663 "layout ( xfb_offset = 0) out Goku {\n"
24664 " flat TYPE gohan;\n"
24665 " flat TYPE goten;\n"
24666 "} goku;\n"
24667 "\n"
24668 // Uniform block must be declared with std140, otherwise each block member is not packed
24669 "layout(binding = 0, std140) uniform block {\n"
24670 " TYPE uni_chichi;\n"
24671 " TYPE uni_bulma;\n"
24672 " TYPE uni_trunk;\n"
24673 " TYPE uni_bra;\n"
24674 " TYPE uni_gohan;\n"
24675 " TYPE uni_goten;\n"
24676 "};\n";
24677
24678 /* Prepare interface string */
24679 {
24680 GLchar buffer[16];
24681 size_t position = 0;
24682 const GLuint type_size = test_case.m_type.GetSize();
24683
24684 sprintf(buffer, "%d", type_size);
24685
24686 Utils::replaceToken("SIZE", position, buffer, interface);
24687 Utils::replaceAllTokens("TYPE", type_name, interface);
24688 }
24689
24690 switch (stage)
24691 {
24692 case Utils::Shader::GEOMETRY:
24693 source = gs;
24694 break;
24695 case Utils::Shader::TESS_EVAL:
24696 source = tes;
24697 break;
24698 case Utils::Shader::VERTEX:
24699 source = vs_tested;
24700 break;
24701 default:
24702 TCU_FAIL("Invalid enum");
24703 }
24704
24705 /* Replace tokens */
24706 {
24707 size_t position = 0;
24708
24709 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
24710 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
24711 }
24712 }
24713 else
24714 {
24715 switch (test_case.m_stage)
24716 {
24717 case Utils::Shader::GEOMETRY:
24718 switch (stage)
24719 {
24720 case Utils::Shader::FRAGMENT:
24721 source = fs;
24722 Utils::replaceAllTokens("TYPE", type_name, source);
24723 break;
24724 case Utils::Shader::VERTEX:
24725 source = vs;
24726 break;
24727 default:
24728 source = "";
24729 }
24730 break;
24731 case Utils::Shader::TESS_EVAL:
24732 switch (stage)
24733 {
24734 case Utils::Shader::FRAGMENT:
24735 source = fs;
24736 Utils::replaceAllTokens("TYPE", type_name, source);
24737 break;
24738 case Utils::Shader::TESS_CTRL:
24739 source = tcs;
24740 break;
24741 case Utils::Shader::VERTEX:
24742 source = vs;
24743 break;
24744 default:
24745 source = "";
24746 }
24747 break;
24748 case Utils::Shader::VERTEX:
24749 switch (stage)
24750 {
24751 case Utils::Shader::FRAGMENT:
24752 source = fs;
24753 Utils::replaceAllTokens("TYPE", type_name, source);
24754 break;
24755 default:
24756 source = "";
24757 }
24758 break;
24759 default:
24760 TCU_FAIL("Invalid enum");
24761 }
24762 }
24763
24764 return source;
24765 }
24766
24767 /** Get name of test case
24768 *
24769 * @param test_case_index Index of test case
24770 *
24771 * @return Name of case
24772 **/
24773 std::string XFBGlobalBufferTest::getTestCaseName(GLuint test_case_index)
24774 {
24775 std::string name;
24776 const _testCase& test_case = m_test_cases[test_case_index];
24777
24778 name = "Tested stage: ";
24779 name.append(Utils::Shader::GetStageName(test_case.m_stage));
24780 name.append(". Tested type: ");
24781 name.append(test_case.m_type.GetGLSLTypeName());
24782
24783 return name;
24784 }
24785
24786 /** Get number of cases
24787 *
24788 * @return Number of test cases
24789 **/
24790 GLuint XFBGlobalBufferTest::getTestCaseNumber()
24791 {
24792 return static_cast<GLuint>(m_test_cases.size());
24793 }
24794
24795 /** Prepare set of test cases
24796 *
24797 **/
24798 void XFBGlobalBufferTest::testInit()
24799 {
24800 GLuint n_types = getTypesNumber();
24801
24802 for (GLuint i = 0; i < n_types; ++i)
24803 {
24804 const Utils::Type& type = getType(i);
24805 /*
24806 When the tfx varying is the following type, the number of output exceeds the gl_MaxVaryingComponents, which will
24807 cause a link time error.
24808 */
24809 if (strcmp(type.GetGLSLTypeName(), "dmat3") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4") == 0 ||
24810 strcmp(type.GetGLSLTypeName(), "dmat3x4") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4x3") == 0)
24811 {
24812 continue;
24813 }
24814 const _testCase test_cases[] = { { Utils::Shader::VERTEX, type },
24815 { Utils::Shader::GEOMETRY, type },
24816 { Utils::Shader::TESS_EVAL, type } };
24817
24818 m_test_cases.push_back(test_cases[0]);
24819 m_test_cases.push_back(test_cases[1]);
24820 m_test_cases.push_back(test_cases[2]);
24821 }
24822 }
24823
24824 /** Constructor
24825 *
24826 * @param context Test context
24827 **/
24828 XFBStrideTest::XFBStrideTest(deqp::Context& context)
24829 : BufferTestBase(context, "xfb_stride", "Test verifies that correct stride is used for all types")
24830 {
24831 /* Nothing to be done here */
24832 }
24833
24834 /** Execute drawArrays for single vertex
24835 *
24836 * @param test_case_index
24837 *
24838 * @return true
24839 **/
24840 bool XFBStrideTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
24841 {
24842 const Functions& gl = m_context.getRenderContext().getFunctions();
24843 GLenum primitive_type = GL_PATCHES;
24844 const testCase& test_case = m_test_cases[test_case_index];
24845
24846 if (Utils::Shader::VERTEX == test_case.m_stage)
24847 {
24848 primitive_type = GL_POINTS;
24849 }
24850
24851 gl.disable(GL_RASTERIZER_DISCARD);
24852 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
24853
24854 gl.beginTransformFeedback(GL_POINTS);
24855 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
24856
24857 gl.drawArrays(primitive_type, 0 /* first */, 2 /* count */);
24858 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
24859
24860 gl.endTransformFeedback();
24861 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
24862
24863 return true;
24864 }
24865
24866 /** Get descriptors of buffers necessary for test
24867 *
24868 * @param test_case_index Index of test case
24869 * @param out_descriptors Descriptors of buffers used by test
24870 **/
24871 void XFBStrideTest::getBufferDescriptors(GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24872 {
24873 const testCase& test_case = m_test_cases[test_case_index];
24874 const Utils::Type& type = test_case.m_type;
24875
24876 /* Test needs single uniform and xfb */
24877 out_descriptors.resize(2);
24878
24879 /* Get references */
24880 bufferDescriptor& uniform = out_descriptors[0];
24881 bufferDescriptor& xfb = out_descriptors[1];
24882
24883 /* Index */
24884 uniform.m_index = 0;
24885 xfb.m_index = 0;
24886
24887 /* Target */
24888 uniform.m_target = Utils::Buffer::Uniform;
24889 xfb.m_target = Utils::Buffer::Transform_feedback;
24890
24891 /* Data */
24892 const GLuint rand_start = Utils::s_rand;
24893 const std::vector<GLubyte>& uniform_data = type.GenerateData();
24894
24895 Utils::s_rand = rand_start;
24896 const std::vector<GLubyte>& xfb_data = type.GenerateDataPacked();
24897
24898 const GLuint uni_type_size = static_cast<GLuint>(uniform_data.size());
24899 const GLuint xfb_type_size = static_cast<GLuint>(xfb_data.size());
24900 /*
24901 Note: If xfb varying output from vertex shader, the variable "goku" will only output once to transform feedback buffer,
24902 if xfb varying output from TES or GS, because the input primitive type in TES is defined as "layout(isolines, point_mode) in;",
24903 the primitive type is line which make the variable "goku" will output twice to transform feedback buffer, so for vertex shader
24904 only one valid data should be initialized in xfb.m_expected_data
24905 */
24906 const GLuint xfb_data_size = (test_case.m_stage == Utils::Shader::VERTEX) ? xfb_type_size : xfb_type_size * 2;
24907 /* Uniform data */
24908 uniform.m_initial_data.resize(uni_type_size);
24909 memcpy(&uniform.m_initial_data[0] + 0 * uni_type_size, &uniform_data[0], uni_type_size);
24910
24911 /* XFB data */
24912 xfb.m_initial_data.resize(xfb_data_size);
24913 xfb.m_expected_data.resize(xfb_data_size);
24914
24915 for (GLuint i = 0; i < xfb_data_size; ++i)
24916 {
24917 xfb.m_initial_data[i] = (glw::GLubyte)i;
24918 xfb.m_expected_data[i] = (glw::GLubyte)i;
24919 }
24920
24921 if (test_case.m_stage == Utils::Shader::VERTEX)
24922 {
24923 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24924 }
24925 else
24926 {
24927 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24928 memcpy(&xfb.m_expected_data[0] + 1 * xfb_type_size, &xfb_data[0], xfb_type_size);
24929 }
24930 }
24931
24932 /** Get body of main function for given shader stage
24933 *
24934 * @param test_case_index Index of test case
24935 * @param stage Shader stage
24936 * @param out_assignments Set to empty
24937 * @param out_calculations Set to empty
24938 **/
24939 void XFBStrideTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_assignments,
24940 std::string& out_calculations)
24941 {
24942 const testCase& test_case = m_test_cases[test_case_index];
24943
24944 out_calculations = "";
24945
24946 static const GLchar* vs_tes_gs = " goku = uni_goku;\n";
24947 static const GLchar* fs = " fs_out = vec4(1, 0.25, 0.5, 0.75);\n"
24948 " if (TYPE(0) == goku)\n"
24949 " {\n"
24950 " fs_out = vec4(1, 0.75, 0.5, 0.5);\n"
24951 " }\n";
24952
24953 const GLchar* assignments = "";
24954
24955 if (test_case.m_stage == stage)
24956 {
24957 switch (stage)
24958 {
24959 case Utils::Shader::GEOMETRY:
24960 assignments = vs_tes_gs;
24961 break;
24962 case Utils::Shader::TESS_EVAL:
24963 assignments = vs_tes_gs;
24964 break;
24965 case Utils::Shader::VERTEX:
24966 assignments = vs_tes_gs;
24967 break;
24968 default:
24969 TCU_FAIL("Invalid enum");
24970 }
24971 }
24972 else
24973 {
24974 switch (stage)
24975 {
24976 case Utils::Shader::FRAGMENT:
24977 assignments = fs;
24978 break;
24979 case Utils::Shader::GEOMETRY:
24980 case Utils::Shader::TESS_CTRL:
24981 case Utils::Shader::TESS_EVAL:
24982 case Utils::Shader::VERTEX:
24983 break;
24984 default:
24985 TCU_FAIL("Invalid enum");
24986 }
24987 }
24988
24989 out_assignments = assignments;
24990
24991 if (Utils::Shader::FRAGMENT == stage)
24992 {
24993 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_assignments);
24994 }
24995 }
24996
24997 /** Get interface of shader
24998 *
24999 * @param test_case_index Index of test case
25000 * @param stage Shader stage
25001 * @param out_interface Set to ""
25002 **/
25003 void XFBStrideTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_interface)
25004 {
25005 static const GLchar* vs_tes_gs = "layout (xfb_offset = 0) FLAT out TYPE goku;\n"
25006 "\n"
25007 "layout(std140, binding = 0) uniform Goku {\n"
25008 " TYPE uni_goku;\n"
25009 "};\n";
25010 static const GLchar* fs = "FLAT in TYPE goku;\n"
25011 "\n"
25012 "out vec4 fs_out;\n";
25013
25014 const testCase& test_case = m_test_cases[test_case_index];
25015 const GLchar* interface = "";
25016 const GLchar* flat = "";
25017
25018 if (test_case.m_stage == stage)
25019 {
25020 switch (stage)
25021 {
25022 case Utils::Shader::GEOMETRY:
25023 interface = vs_tes_gs;
25024 break;
25025 case Utils::Shader::TESS_EVAL:
25026 interface = vs_tes_gs;
25027 break;
25028 case Utils::Shader::VERTEX:
25029 interface = vs_tes_gs;
25030 break;
25031 default:
25032 TCU_FAIL("Invalid enum");
25033 }
25034 }
25035 else
25036 {
25037 switch (stage)
25038 {
25039 case Utils::Shader::FRAGMENT:
25040 interface = fs;
25041 break;
25042 case Utils::Shader::GEOMETRY:
25043 case Utils::Shader::TESS_CTRL:
25044 case Utils::Shader::TESS_EVAL:
25045 case Utils::Shader::VERTEX:
25046 break;
25047 default:
25048 TCU_FAIL("Invalid enum");
25049 }
25050 }
25051
25052 out_interface = interface;
25053
25054 if (Utils::Type::Float != test_case.m_type.m_basic_type)
25055 {
25056 flat = "flat";
25057 }
25058
25059 Utils::replaceAllTokens("FLAT", flat, out_interface);
25060 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_interface);
25061 }
25062
25063 /** Get source code of shader
25064 *
25065 * @param test_case_index Index of test case
25066 * @param stage Shader stage
25067 *
25068 * @return Source
25069 **/
25070 std::string XFBStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25071 {
25072 std::string source;
25073 const testCase& test_case = m_test_cases[test_case_index];
25074
25075 switch (test_case.m_stage)
25076 {
25077 case Utils::Shader::VERTEX:
25078 switch (stage)
25079 {
25080 case Utils::Shader::FRAGMENT:
25081 case Utils::Shader::VERTEX:
25082 source = BufferTestBase::getShaderSource(test_case_index, stage);
25083 break;
25084 default:
25085 break;
25086 }
25087 break;
25088
25089 case Utils::Shader::TESS_EVAL:
25090 switch (stage)
25091 {
25092 case Utils::Shader::FRAGMENT:
25093 case Utils::Shader::TESS_CTRL:
25094 case Utils::Shader::TESS_EVAL:
25095 case Utils::Shader::VERTEX:
25096 source = BufferTestBase::getShaderSource(test_case_index, stage);
25097 break;
25098 default:
25099 break;
25100 }
25101 break;
25102
25103 case Utils::Shader::GEOMETRY:
25104 source = BufferTestBase::getShaderSource(test_case_index, stage);
25105 break;
25106
25107 default:
25108 TCU_FAIL("Invalid enum");
25109 }
25110
25111 /* */
25112 return source;
25113 }
25114
25115 /** Get name of test case
25116 *
25117 * @param test_case_index Index of test case
25118 *
25119 * @return Name of tested stage
25120 **/
25121 std::string XFBStrideTest::getTestCaseName(glw::GLuint test_case_index)
25122 {
25123 std::stringstream stream;
25124 const testCase& test_case = m_test_cases[test_case_index];
25125
25126 stream << "Type: " << test_case.m_type.GetGLSLTypeName()
25127 << ", stage: " << Utils::Shader::GetStageName(test_case.m_stage);
25128
25129 return stream.str();
25130 }
25131
25132 /** Returns number of test cases
25133 *
25134 * @return TEST_MAX
25135 **/
25136 glw::GLuint XFBStrideTest::getTestCaseNumber()
25137 {
25138 return static_cast<GLuint>(m_test_cases.size());
25139 }
25140
25141 /** Prepare all test cases
25142 *
25143 **/
25144 void XFBStrideTest::testInit()
25145 {
25146 const GLuint n_types = getTypesNumber();
25147
25148 for (GLuint i = 0; i < n_types; ++i)
25149 {
25150 const Utils::Type& type = getType(i);
25151
25152 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25153 {
25154 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
25155 (Utils::Shader::TESS_CTRL == stage))
25156 {
25157 continue;
25158 }
25159
25160 testCase test_case = { (Utils::Shader::STAGES)stage, type };
25161
25162 m_test_cases.push_back(test_case);
25163 }
25164 }
25165 }
25166
25167 /** Constructor
25168 *
25169 * @param context Test framework context
25170 **/
25171 XFBBlockMemberBufferTest::XFBBlockMemberBufferTest(deqp::Context& context)
25172 : NegativeTestBase(
25173 context, "xfb_block_member_buffer",
25174 "Test verifies that compiler reports error when block member has different xfb_buffer qualifier than buffer")
25175 {
25176 }
25177
25178 /** Source for given test case and stage
25179 *
25180 * @param test_case_index Index of test case
25181 * @param stage Shader stage
25182 *
25183 * @return Shader source
25184 **/
25185 std::string XFBBlockMemberBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25186 {
25187 static const GLchar* var_definition = "layout (xfb_offset = 0) out Goku {\n"
25188 " vec4 gohan;\n"
25189 #if DEBUG_NEG_REMOVE_ERROR
25190 " /* layout (xfb_buffer = 1) */ vec4 goten;\n"
25191 #else
25192 " layout (xfb_buffer = 1) vec4 goten;\n"
25193 #endif /* DEBUG_NEG_REMOVE_ERROR */
25194 "} goku;\n";
25195 static const GLchar* var_use = " goku.gohan = result / 2;\n"
25196 " goku.goten = result / 4;\n";
25197 static const GLchar* fs = "#version 430 core\n"
25198 "#extension GL_ARB_enhanced_layouts : require\n"
25199 "\n"
25200 "in vec4 any_fs;\n"
25201 "out vec4 fs_out;\n"
25202 "\n"
25203 "void main()\n"
25204 "{\n"
25205 " fs_out = any_fs;\n"
25206 "}\n"
25207 "\n";
25208 static const GLchar* gs_tested = "#version 430 core\n"
25209 "#extension GL_ARB_enhanced_layouts : require\n"
25210 "\n"
25211 "layout(points) in;\n"
25212 "layout(triangle_strip, max_vertices = 4) out;\n"
25213 "\n"
25214 "VAR_DEFINITION"
25215 "\n"
25216 "in vec4 vs_any[];\n"
25217 "out vec4 any_fs;\n"
25218 "\n"
25219 "void main()\n"
25220 "{\n"
25221 " vec4 result = vs_any[0];\n"
25222 "\n"
25223 "VARIABLE_USE"
25224 "\n"
25225 " any_fs = result;\n"
25226 " gl_Position = vec4(-1, -1, 0, 1);\n"
25227 " EmitVertex();\n"
25228 " any_fs = result;\n"
25229 " gl_Position = vec4(-1, 1, 0, 1);\n"
25230 " EmitVertex();\n"
25231 " any_fs = result;\n"
25232 " gl_Position = vec4(1, -1, 0, 1);\n"
25233 " EmitVertex();\n"
25234 " any_fs = result;\n"
25235 " gl_Position = vec4(1, 1, 0, 1);\n"
25236 " EmitVertex();\n"
25237 "}\n"
25238 "\n";
25239 static const GLchar* tcs = "#version 430 core\n"
25240 "#extension GL_ARB_enhanced_layouts : require\n"
25241 "\n"
25242 "layout(vertices = 1) out;\n"
25243 "\n"
25244 "in vec4 vs_any[];\n"
25245 "out vec4 tcs_tes[];\n"
25246 "\n"
25247 "void main()\n"
25248 "{\n"
25249 "\n"
25250 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25251 "\n"
25252 " gl_TessLevelOuter[0] = 1.0;\n"
25253 " gl_TessLevelOuter[1] = 1.0;\n"
25254 " gl_TessLevelOuter[2] = 1.0;\n"
25255 " gl_TessLevelOuter[3] = 1.0;\n"
25256 " gl_TessLevelInner[0] = 1.0;\n"
25257 " gl_TessLevelInner[1] = 1.0;\n"
25258 "}\n"
25259 "\n";
25260 static const GLchar* tes_tested = "#version 430 core\n"
25261 "#extension GL_ARB_enhanced_layouts : require\n"
25262 "\n"
25263 "layout(isolines, point_mode) in;\n"
25264 "\n"
25265 "VAR_DEFINITION"
25266 "\n"
25267 "in vec4 tcs_tes[];\n"
25268 "out vec4 any_fs;\n"
25269 "\n"
25270 "void main()\n"
25271 "{\n"
25272 " vec4 result = tcs_tes[0];\n"
25273 "\n"
25274 "VARIABLE_USE"
25275 "\n"
25276 " any_fs += result;\n"
25277 "}\n"
25278 "\n";
25279 static const GLchar* vs = "#version 430 core\n"
25280 "#extension GL_ARB_enhanced_layouts : require\n"
25281 "\n"
25282 "in vec4 in_vs;\n"
25283 "out vec4 vs_any;\n"
25284 "\n"
25285 "void main()\n"
25286 "{\n"
25287 " vs_any = in_vs;\n"
25288 "}\n"
25289 "\n";
25290 static const GLchar* vs_tested = "#version 430 core\n"
25291 "#extension GL_ARB_enhanced_layouts : require\n"
25292 "\n"
25293 "VAR_DEFINITION"
25294 "\n"
25295 "in vec4 in_vs;\n"
25296 "out vec4 any_fs;\n"
25297 "\n"
25298 "void main()\n"
25299 "{\n"
25300 " vec4 result = in_vs;\n"
25301 "\n"
25302 "VARIABLE_USE"
25303 "\n"
25304 " any_fs = result;\n"
25305 "}\n"
25306 "\n";
25307
25308 std::string source;
25309 testCase& test_case = m_test_cases[test_case_index];
25310
25311 if (test_case.m_stage == stage)
25312 {
25313 size_t position = 0;
25314
25315 switch (stage)
25316 {
25317 case Utils::Shader::GEOMETRY:
25318 source = gs_tested;
25319 break;
25320 case Utils::Shader::TESS_EVAL:
25321 source = tes_tested;
25322 break;
25323 case Utils::Shader::VERTEX:
25324 source = vs_tested;
25325 break;
25326 default:
25327 TCU_FAIL("Invalid enum");
25328 }
25329
25330 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25331 position = 0;
25332 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25333 }
25334 else
25335 {
25336 switch (test_case.m_stage)
25337 {
25338 case Utils::Shader::GEOMETRY:
25339 switch (stage)
25340 {
25341 case Utils::Shader::FRAGMENT:
25342 source = fs;
25343 break;
25344 case Utils::Shader::VERTEX:
25345 source = vs;
25346 break;
25347 default:
25348 source = "";
25349 }
25350 break;
25351 case Utils::Shader::TESS_EVAL:
25352 switch (stage)
25353 {
25354 case Utils::Shader::FRAGMENT:
25355 source = fs;
25356 break;
25357 case Utils::Shader::TESS_CTRL:
25358 source = tcs;
25359 break;
25360 case Utils::Shader::VERTEX:
25361 source = vs;
25362 break;
25363 default:
25364 source = "";
25365 }
25366 break;
25367 case Utils::Shader::VERTEX:
25368 switch (stage)
25369 {
25370 case Utils::Shader::FRAGMENT:
25371 source = fs;
25372 break;
25373 default:
25374 source = "";
25375 }
25376 break;
25377 default:
25378 TCU_FAIL("Invalid enum");
25379 }
25380 }
25381
25382 return source;
25383 }
25384
25385 /** Get description of test case
25386 *
25387 * @param test_case_index Index of test case
25388 *
25389 * @return Test case description
25390 **/
25391 std::string XFBBlockMemberBufferTest::getTestCaseName(GLuint test_case_index)
25392 {
25393 std::stringstream stream;
25394 testCase& test_case = m_test_cases[test_case_index];
25395
25396 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
25397
25398 return stream.str();
25399 }
25400
25401 /** Get number of test cases
25402 *
25403 * @return Number of test cases
25404 **/
25405 GLuint XFBBlockMemberBufferTest::getTestCaseNumber()
25406 {
25407 return static_cast<GLuint>(m_test_cases.size());
25408 }
25409
25410 /** Selects if "compute" stage is relevant for test
25411 *
25412 * @param ignored
25413 *
25414 * @return false
25415 **/
25416 bool XFBBlockMemberBufferTest::isComputeRelevant(GLuint /* test_case_index */)
25417 {
25418 return false;
25419 }
25420
25421 /** Prepare all test cases
25422 *
25423 **/
25424 void XFBBlockMemberBufferTest::testInit()
25425 {
25426 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25427 {
25428 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25429 (Utils::Shader::FRAGMENT == stage))
25430 {
25431 continue;
25432 }
25433
25434 testCase test_case = { (Utils::Shader::STAGES)stage };
25435
25436 m_test_cases.push_back(test_case);
25437 }
25438 }
25439
25440 /** Constructor
25441 *
25442 * @param context Test framework context
25443 **/
25444 XFBOutputOverlappingTest::XFBOutputOverlappingTest(deqp::Context& context)
25445 : NegativeTestBase(context, "xfb_output_overlapping",
25446 "Test verifies that compiler reports error when two xfb qualified outputs overlap")
25447 {
25448 }
25449
25450 /** Source for given test case and stage
25451 *
25452 * @param test_case_index Index of test case
25453 * @param stage Shader stage
25454 *
25455 * @return Shader source
25456 **/
25457 std::string XFBOutputOverlappingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25458 {
25459 static const GLchar* var_definition = "layout (xfb_offset = 0) out TYPE gohan;\n"
25460 #if DEBUG_NEG_REMOVE_ERROR
25461 "/* layout (xfb_offset = OFFSET) */ out TYPE goten;\n";
25462 #else
25463 "layout (xfb_offset = OFFSET) out TYPE goten;\n";
25464 #endif /* DEBUG_NEG_REMOVE_ERROR */
25465 static const GLchar* var_use = " gohan = TYPE(0);\n"
25466 " goten = TYPE(1);\n"
25467 " if (vec4(0) == result)\n"
25468 " {\n"
25469 " gohan = TYPE(1);\n"
25470 " goten = TYPE(0);\n"
25471 " }\n";
25472 static const GLchar* fs = "#version 430 core\n"
25473 "#extension GL_ARB_enhanced_layouts : require\n"
25474 "\n"
25475 "in vec4 any_fs;\n"
25476 "out vec4 fs_out;\n"
25477 "\n"
25478 "void main()\n"
25479 "{\n"
25480 " fs_out = any_fs;\n"
25481 "}\n"
25482 "\n";
25483 static const GLchar* gs_tested = "#version 430 core\n"
25484 "#extension GL_ARB_enhanced_layouts : require\n"
25485 "\n"
25486 "layout(points) in;\n"
25487 "layout(triangle_strip, max_vertices = 4) out;\n"
25488 "\n"
25489 "VAR_DEFINITION"
25490 "\n"
25491 "in vec4 vs_any[];\n"
25492 "out vec4 any_fs;\n"
25493 "\n"
25494 "void main()\n"
25495 "{\n"
25496 " vec4 result = vs_any[0];\n"
25497 "\n"
25498 "VARIABLE_USE"
25499 "\n"
25500 " any_fs = result;\n"
25501 " gl_Position = vec4(-1, -1, 0, 1);\n"
25502 " EmitVertex();\n"
25503 " any_fs = result;\n"
25504 " gl_Position = vec4(-1, 1, 0, 1);\n"
25505 " EmitVertex();\n"
25506 " any_fs = result;\n"
25507 " gl_Position = vec4(1, -1, 0, 1);\n"
25508 " EmitVertex();\n"
25509 " any_fs = result;\n"
25510 " gl_Position = vec4(1, 1, 0, 1);\n"
25511 " EmitVertex();\n"
25512 "}\n"
25513 "\n";
25514 static const GLchar* tcs = "#version 430 core\n"
25515 "#extension GL_ARB_enhanced_layouts : require\n"
25516 "\n"
25517 "layout(vertices = 1) out;\n"
25518 "\n"
25519 "in vec4 vs_any[];\n"
25520 "out vec4 tcs_tes[];\n"
25521 "\n"
25522 "void main()\n"
25523 "{\n"
25524 "\n"
25525 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25526 "\n"
25527 " gl_TessLevelOuter[0] = 1.0;\n"
25528 " gl_TessLevelOuter[1] = 1.0;\n"
25529 " gl_TessLevelOuter[2] = 1.0;\n"
25530 " gl_TessLevelOuter[3] = 1.0;\n"
25531 " gl_TessLevelInner[0] = 1.0;\n"
25532 " gl_TessLevelInner[1] = 1.0;\n"
25533 "}\n"
25534 "\n";
25535 static const GLchar* tes_tested = "#version 430 core\n"
25536 "#extension GL_ARB_enhanced_layouts : require\n"
25537 "\n"
25538 "layout(isolines, point_mode) in;\n"
25539 "\n"
25540 "VAR_DEFINITION"
25541 "\n"
25542 "in vec4 tcs_tes[];\n"
25543 "out vec4 any_fs;\n"
25544 "\n"
25545 "void main()\n"
25546 "{\n"
25547 " vec4 result = tcs_tes[0];\n"
25548 "\n"
25549 "VARIABLE_USE"
25550 "\n"
25551 " any_fs += result;\n"
25552 "}\n"
25553 "\n";
25554 static const GLchar* vs = "#version 430 core\n"
25555 "#extension GL_ARB_enhanced_layouts : require\n"
25556 "\n"
25557 "in vec4 in_vs;\n"
25558 "out vec4 vs_any;\n"
25559 "\n"
25560 "void main()\n"
25561 "{\n"
25562 " vs_any = in_vs;\n"
25563 "}\n"
25564 "\n";
25565 static const GLchar* vs_tested = "#version 430 core\n"
25566 "#extension GL_ARB_enhanced_layouts : require\n"
25567 "\n"
25568 "VAR_DEFINITION"
25569 "\n"
25570 "in vec4 in_vs;\n"
25571 "out vec4 any_fs;\n"
25572 "\n"
25573 "void main()\n"
25574 "{\n"
25575 " vec4 result = in_vs;\n"
25576 "\n"
25577 "VARIABLE_USE"
25578 "\n"
25579 " any_fs = result;\n"
25580 "}\n"
25581 "\n";
25582
25583 std::string source;
25584 testCase& test_case = m_test_cases[test_case_index];
25585
25586 if (test_case.m_stage == stage)
25587 {
25588 GLchar offset[16];
25589 size_t position = 0;
25590 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25591
25592 sprintf(offset, "%d", test_case.m_offset);
25593
25594 switch (stage)
25595 {
25596 case Utils::Shader::GEOMETRY:
25597 source = gs_tested;
25598 break;
25599 case Utils::Shader::TESS_EVAL:
25600 source = tes_tested;
25601 break;
25602 case Utils::Shader::VERTEX:
25603 source = vs_tested;
25604 break;
25605 default:
25606 TCU_FAIL("Invalid enum");
25607 }
25608
25609 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25610 position = 0;
25611 Utils::replaceToken("OFFSET", position, offset, source);
25612 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25613
25614 Utils::replaceAllTokens("TYPE", type_name, source);
25615 }
25616 else
25617 {
25618 switch (test_case.m_stage)
25619 {
25620 case Utils::Shader::GEOMETRY:
25621 switch (stage)
25622 {
25623 case Utils::Shader::FRAGMENT:
25624 source = fs;
25625 break;
25626 case Utils::Shader::VERTEX:
25627 source = vs;
25628 break;
25629 default:
25630 source = "";
25631 }
25632 break;
25633 case Utils::Shader::TESS_EVAL:
25634 switch (stage)
25635 {
25636 case Utils::Shader::FRAGMENT:
25637 source = fs;
25638 break;
25639 case Utils::Shader::TESS_CTRL:
25640 source = tcs;
25641 break;
25642 case Utils::Shader::VERTEX:
25643 source = vs;
25644 break;
25645 default:
25646 source = "";
25647 }
25648 break;
25649 case Utils::Shader::VERTEX:
25650 switch (stage)
25651 {
25652 case Utils::Shader::FRAGMENT:
25653 source = fs;
25654 break;
25655 default:
25656 source = "";
25657 }
25658 break;
25659 default:
25660 TCU_FAIL("Invalid enum");
25661 }
25662 }
25663
25664 return source;
25665 }
25666
25667 /** Get description of test case
25668 *
25669 * @param test_case_index Index of test case
25670 *
25671 * @return Test case description
25672 **/
25673 std::string XFBOutputOverlappingTest::getTestCaseName(GLuint test_case_index)
25674 {
25675 std::stringstream stream;
25676 testCase& test_case = m_test_cases[test_case_index];
25677
25678 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25679 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
25680
25681 return stream.str();
25682 }
25683
25684 /** Get number of test cases
25685 *
25686 * @return Number of test cases
25687 **/
25688 GLuint XFBOutputOverlappingTest::getTestCaseNumber()
25689 {
25690 return static_cast<GLuint>(m_test_cases.size());
25691 }
25692
25693 /** Selects if "compute" stage is relevant for test
25694 *
25695 * @param ignored
25696 *
25697 * @return false
25698 **/
25699 bool XFBOutputOverlappingTest::isComputeRelevant(GLuint /* test_case_index */)
25700 {
25701 return false;
25702 }
25703
25704 /** Prepare all test cases
25705 *
25706 **/
25707 void XFBOutputOverlappingTest::testInit()
25708 {
25709 const GLuint n_types = getTypesNumber();
25710
25711 for (GLuint i = 0; i < n_types; ++i)
25712 {
25713 const Utils::Type& type = getType(i);
25714 const GLuint basic_type_size = Utils::Type::GetTypeSize(type.m_basic_type);
25715
25716 /* Skip scalars, not applicable as:
25717 *
25718 * The offset must be a multiple of the size of the first component of the first
25719 * qualified variable or block member, or a compile-time error results.
25720 */
25721 if ((1 == type.m_n_columns) && (1 == type.m_n_rows))
25722 {
25723 continue;
25724 }
25725
25726 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25727 {
25728 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25729 (Utils::Shader::FRAGMENT == stage))
25730 {
25731 continue;
25732 }
25733
25734 testCase test_case = { basic_type_size /* offset */, (Utils::Shader::STAGES)stage, type };
25735
25736 m_test_cases.push_back(test_case);
25737 }
25738 }
25739 }
25740
25741 /** Constructor
25742 *
25743 * @param context Test framework context
25744 **/
25745 XFBInvalidOffsetAlignmentTest::XFBInvalidOffsetAlignmentTest(deqp::Context& context)
25746 : NegativeTestBase(context, "xfb_invalid_offset_alignment",
25747 "Test verifies that compiler reports error when xfb_offset has invalid alignment")
25748 {
25749 }
25750
25751 /** Source for given test case and stage
25752 *
25753 * @param test_case_index Index of test case
25754 * @param stage Shader stage
25755 *
25756 * @return Shader source
25757 **/
25758 std::string XFBInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25759 {
25760 #if DEBUG_NEG_REMOVE_ERROR
25761 static const GLchar* var_definition = "/* layout (xfb_offset = OFFSET) */ out TYPE gohan;\n";
25762 #else
25763 static const GLchar* var_definition = "layout (xfb_offset = OFFSET) out TYPE gohan;\n";
25764 #endif /* DEBUG_NEG_REMOVE_ERROR */
25765 static const GLchar* var_use = " gohan = TYPE(0);\n"
25766 " if (vec4(0) == result)\n"
25767 " {\n"
25768 " gohan = TYPE(1);\n"
25769 " }\n";
25770 static const GLchar* fs = "#version 430 core\n"
25771 "#extension GL_ARB_enhanced_layouts : require\n"
25772 "\n"
25773 "in vec4 any_fs;\n"
25774 "out vec4 fs_out;\n"
25775 "\n"
25776 "void main()\n"
25777 "{\n"
25778 " fs_out = any_fs;\n"
25779 "}\n"
25780 "\n";
25781 static const GLchar* gs_tested = "#version 430 core\n"
25782 "#extension GL_ARB_enhanced_layouts : require\n"
25783 "\n"
25784 "layout(points) in;\n"
25785 "layout(triangle_strip, max_vertices = 4) out;\n"
25786 "\n"
25787 "VAR_DEFINITION"
25788 "\n"
25789 "in vec4 vs_any[];\n"
25790 "out vec4 any_fs;\n"
25791 "\n"
25792 "void main()\n"
25793 "{\n"
25794 " vec4 result = vs_any[0];\n"
25795 "\n"
25796 "VARIABLE_USE"
25797 "\n"
25798 " any_fs = result;\n"
25799 " gl_Position = vec4(-1, -1, 0, 1);\n"
25800 " EmitVertex();\n"
25801 " any_fs = result;\n"
25802 " gl_Position = vec4(-1, 1, 0, 1);\n"
25803 " EmitVertex();\n"
25804 " any_fs = result;\n"
25805 " gl_Position = vec4(1, -1, 0, 1);\n"
25806 " EmitVertex();\n"
25807 " any_fs = result;\n"
25808 " gl_Position = vec4(1, 1, 0, 1);\n"
25809 " EmitVertex();\n"
25810 "}\n"
25811 "\n";
25812 static const GLchar* tcs = "#version 430 core\n"
25813 "#extension GL_ARB_enhanced_layouts : require\n"
25814 "\n"
25815 "layout(vertices = 1) out;\n"
25816 "\n"
25817 "in vec4 vs_any[];\n"
25818 "out vec4 tcs_tes[];\n"
25819 "\n"
25820 "void main()\n"
25821 "{\n"
25822 "\n"
25823 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25824 "\n"
25825 " gl_TessLevelOuter[0] = 1.0;\n"
25826 " gl_TessLevelOuter[1] = 1.0;\n"
25827 " gl_TessLevelOuter[2] = 1.0;\n"
25828 " gl_TessLevelOuter[3] = 1.0;\n"
25829 " gl_TessLevelInner[0] = 1.0;\n"
25830 " gl_TessLevelInner[1] = 1.0;\n"
25831 "}\n"
25832 "\n";
25833 static const GLchar* tes_tested = "#version 430 core\n"
25834 "#extension GL_ARB_enhanced_layouts : require\n"
25835 "\n"
25836 "layout(isolines, point_mode) in;\n"
25837 "\n"
25838 "VAR_DEFINITION"
25839 "\n"
25840 "in vec4 tcs_tes[];\n"
25841 "out vec4 any_fs;\n"
25842 "\n"
25843 "void main()\n"
25844 "{\n"
25845 " vec4 result = tcs_tes[0];\n"
25846 "\n"
25847 "VARIABLE_USE"
25848 "\n"
25849 " any_fs += result;\n"
25850 "}\n"
25851 "\n";
25852 static const GLchar* vs = "#version 430 core\n"
25853 "#extension GL_ARB_enhanced_layouts : require\n"
25854 "\n"
25855 "in vec4 in_vs;\n"
25856 "out vec4 vs_any;\n"
25857 "\n"
25858 "void main()\n"
25859 "{\n"
25860 " vs_any = in_vs;\n"
25861 "}\n"
25862 "\n";
25863 static const GLchar* vs_tested = "#version 430 core\n"
25864 "#extension GL_ARB_enhanced_layouts : require\n"
25865 "\n"
25866 "VAR_DEFINITION"
25867 "\n"
25868 "in vec4 in_vs;\n"
25869 "out vec4 any_fs;\n"
25870 "\n"
25871 "void main()\n"
25872 "{\n"
25873 " vec4 result = in_vs;\n"
25874 "\n"
25875 "VARIABLE_USE"
25876 "\n"
25877 " any_fs = result;\n"
25878 "}\n"
25879 "\n";
25880
25881 std::string source;
25882 testCase& test_case = m_test_cases[test_case_index];
25883
25884 if (test_case.m_stage == stage)
25885 {
25886 GLchar offset[16];
25887 size_t position = 0;
25888 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25889
25890 sprintf(offset, "%d", test_case.m_offset);
25891
25892 switch (stage)
25893 {
25894 case Utils::Shader::GEOMETRY:
25895 source = gs_tested;
25896 break;
25897 case Utils::Shader::TESS_EVAL:
25898 source = tes_tested;
25899 break;
25900 case Utils::Shader::VERTEX:
25901 source = vs_tested;
25902 break;
25903 default:
25904 TCU_FAIL("Invalid enum");
25905 }
25906
25907 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25908 position = 0;
25909 Utils::replaceToken("OFFSET", position, offset, source);
25910 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25911
25912 Utils::replaceAllTokens("TYPE", type_name, source);
25913 }
25914 else
25915 {
25916 switch (test_case.m_stage)
25917 {
25918 case Utils::Shader::GEOMETRY:
25919 switch (stage)
25920 {
25921 case Utils::Shader::FRAGMENT:
25922 source = fs;
25923 break;
25924 case Utils::Shader::VERTEX:
25925 source = vs;
25926 break;
25927 default:
25928 source = "";
25929 }
25930 break;
25931 case Utils::Shader::TESS_EVAL:
25932 switch (stage)
25933 {
25934 case Utils::Shader::FRAGMENT:
25935 source = fs;
25936 break;
25937 case Utils::Shader::TESS_CTRL:
25938 source = tcs;
25939 break;
25940 case Utils::Shader::VERTEX:
25941 source = vs;
25942 break;
25943 default:
25944 source = "";
25945 }
25946 break;
25947 case Utils::Shader::VERTEX:
25948 switch (stage)
25949 {
25950 case Utils::Shader::FRAGMENT:
25951 source = fs;
25952 break;
25953 default:
25954 source = "";
25955 }
25956 break;
25957 default:
25958 TCU_FAIL("Invalid enum");
25959 }
25960 }
25961
25962 return source;
25963 }
25964
25965 /** Get description of test case
25966 *
25967 * @param test_case_index Index of test case
25968 *
25969 * @return Test case description
25970 **/
25971 std::string XFBInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
25972 {
25973 std::stringstream stream;
25974 testCase& test_case = m_test_cases[test_case_index];
25975
25976 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25977 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
25978
25979 return stream.str();
25980 }
25981
25982 /** Get number of test cases
25983 *
25984 * @return Number of test cases
25985 **/
25986 GLuint XFBInvalidOffsetAlignmentTest::getTestCaseNumber()
25987 {
25988 return static_cast<GLuint>(m_test_cases.size());
25989 }
25990
25991 /** Selects if "compute" stage is relevant for test
25992 *
25993 * @param ignored
25994 *
25995 * @return false
25996 **/
25997 bool XFBInvalidOffsetAlignmentTest::isComputeRelevant(GLuint /* test_case_index */)
25998 {
25999 return false;
26000 }
26001
26002 /** Prepare all test cases
26003 *
26004 **/
26005 void XFBInvalidOffsetAlignmentTest::testInit()
26006 {
26007 const GLuint n_types = getTypesNumber();
26008
26009 for (GLuint i = 0; i < n_types; ++i)
26010 {
26011 const Utils::Type& type = getType(i);
26012 const GLuint basic_type_size = Utils::Type::GetTypeSize(type.m_basic_type);
26013
26014 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
26015 {
26016 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
26017 (Utils::Shader::FRAGMENT == stage))
26018 {
26019 continue;
26020 }
26021
26022 for (GLuint offset = basic_type_size + 1; offset < 2 * basic_type_size; ++offset)
26023 {
26024 testCase test_case = { offset, (Utils::Shader::STAGES)stage, type };
26025
26026 m_test_cases.push_back(test_case);
26027 }
26028 }
26029 }
26030 }
26031
26032 /** Constructor
26033 *
26034 * @param context Test context
26035 **/
26036 XFBCaptureInactiveOutputVariableTest::XFBCaptureInactiveOutputVariableTest(deqp::Context& context)
26037 : BufferTestBase(context, "xfb_capture_inactive_output_variable",
26038 "Test verifies that inactive variables are captured")
26039 {
26040 /* Nothing to be done here */
26041 }
26042
26043 /** Execute drawArrays for single vertex
26044 *
26045 * @param test_case_index
26046 *
26047 * @return true
26048 **/
26049 bool XFBCaptureInactiveOutputVariableTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26050 {
26051 const Functions& gl = m_context.getRenderContext().getFunctions();
26052 GLenum primitive_type = GL_PATCHES;
26053
26054 if (TEST_VS == test_case_index)
26055 {
26056 primitive_type = GL_POINTS;
26057 }
26058
26059 gl.disable(GL_RASTERIZER_DISCARD);
26060 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26061
26062 gl.beginTransformFeedback(GL_POINTS);
26063 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26064
26065 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26066 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26067
26068 gl.endTransformFeedback();
26069 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26070
26071 return true;
26072 }
26073
26074 /** Get descriptors of buffers necessary for test
26075 *
26076 * @param ignored
26077 * @param out_descriptors Descriptors of buffers used by test
26078 **/
26079 void XFBCaptureInactiveOutputVariableTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26080 bufferDescriptor::Vector& out_descriptors)
26081 {
26082 const Utils::Type& type = Utils::Type::vec4;
26083
26084 /* Test needs single uniform and xfb */
26085 out_descriptors.resize(2);
26086
26087 /* Get references */
26088 bufferDescriptor& uniform = out_descriptors[0];
26089 bufferDescriptor& xfb = out_descriptors[1];
26090
26091 /* Index */
26092 uniform.m_index = 0;
26093 xfb.m_index = 0;
26094
26095 /* Target */
26096 uniform.m_target = Utils::Buffer::Uniform;
26097 xfb.m_target = Utils::Buffer::Transform_feedback;
26098
26099 /* Data */
26100 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26101 const std::vector<GLubyte>& goten_data = type.GenerateData();
26102
26103 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26104
26105 /* Uniform data */
26106 uniform.m_initial_data.resize(2 * type_size);
26107 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
26108 memcpy(&uniform.m_initial_data[0] + type_size, &goten_data[0], type_size);
26109
26110 /* XFB data */
26111 xfb.m_initial_data.resize(3 * type_size);
26112 xfb.m_expected_data.resize(3 * type_size);
26113
26114 for (GLuint i = 0; i < 3 * type_size; ++i)
26115 {
26116 xfb.m_initial_data[i] = (glw::GLubyte)i;
26117 xfb.m_expected_data[i] = (glw::GLubyte)i;
26118 }
26119
26120 memcpy(&xfb.m_expected_data[0] + 2 * type_size, &gohan_data[0], type_size);
26121 memcpy(&xfb.m_expected_data[0] + 0 * type_size, &goten_data[0], type_size);
26122 }
26123
26124 /** Get body of main function for given shader stage
26125 *
26126 * @param test_case_index Index of test case
26127 * @param stage Shader stage
26128 * @param out_assignments Set to empty
26129 * @param out_calculations Set to empty
26130 **/
26131 void XFBCaptureInactiveOutputVariableTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26132 std::string& out_assignments, std::string& out_calculations)
26133 {
26134 out_calculations = "";
26135
26136 static const GLchar* vs_tes_gs = " goten = uni_goten;\n"
26137 " gohan = uni_gohan;\n";
26138 static const GLchar* fs = " fs_out = goku + gohan + goten;\n";
26139
26140 const GLchar* assignments = "";
26141
26142 switch (stage)
26143 {
26144 case Utils::Shader::FRAGMENT:
26145 assignments = fs;
26146 break;
26147
26148 case Utils::Shader::GEOMETRY:
26149 if (TEST_GS == test_case_index)
26150 {
26151 assignments = vs_tes_gs;
26152 }
26153 break;
26154
26155 case Utils::Shader::TESS_CTRL:
26156 break;
26157
26158 case Utils::Shader::TESS_EVAL:
26159 if (TEST_TES == test_case_index)
26160 {
26161 assignments = vs_tes_gs;
26162 }
26163 break;
26164
26165 case Utils::Shader::VERTEX:
26166 if (TEST_VS == test_case_index)
26167 {
26168 assignments = vs_tes_gs;
26169 }
26170 break;
26171
26172 default:
26173 TCU_FAIL("Invalid enum");
26174 }
26175
26176 out_assignments = assignments;
26177 }
26178
26179 /** Get interface of shader
26180 *
26181 * @param test_case_index Index of test case
26182 * @param stage Shader stage
26183 * @param out_interface Set to ""
26184 **/
26185 void XFBCaptureInactiveOutputVariableTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26186 std::string& out_interface)
26187 {
26188 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26189 "\n"
26190 "layout (xfb_offset = 1 * sizeof_type) out vec4 goku;\n"
26191 "layout (xfb_offset = 2 * sizeof_type) out vec4 gohan;\n"
26192 "layout (xfb_offset = 0 * sizeof_type) out vec4 goten;\n"
26193 "\n"
26194 "layout(binding = 0) uniform block {\n"
26195 " vec4 uni_gohan;\n"
26196 " vec4 uni_goten;\n"
26197 "};\n";
26198 static const GLchar* fs = "in vec4 goku;\n"
26199 "in vec4 gohan;\n"
26200 "in vec4 goten;\n"
26201 "out vec4 fs_out;\n";
26202
26203 const GLchar* interface = "";
26204
26205 switch (stage)
26206 {
26207 case Utils::Shader::FRAGMENT:
26208 interface = fs;
26209 break;
26210
26211 case Utils::Shader::GEOMETRY:
26212 if (TEST_GS == test_case_index)
26213 {
26214 interface = vs_tes_gs;
26215 }
26216 break;
26217
26218 case Utils::Shader::TESS_CTRL:
26219 break;
26220
26221 case Utils::Shader::TESS_EVAL:
26222 if (TEST_TES == test_case_index)
26223 {
26224 interface = vs_tes_gs;
26225 }
26226 break;
26227
26228 case Utils::Shader::VERTEX:
26229 if (TEST_VS == test_case_index)
26230 {
26231 interface = vs_tes_gs;
26232 }
26233 break;
26234
26235 default:
26236 TCU_FAIL("Invalid enum");
26237 }
26238
26239 out_interface = interface;
26240 }
26241
26242 /** Get source code of shader
26243 *
26244 * @param test_case_index Index of test case
26245 * @param stage Shader stage
26246 *
26247 * @return Source
26248 **/
26249 std::string XFBCaptureInactiveOutputVariableTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26250 {
26251 std::string source;
26252
26253 switch (test_case_index)
26254 {
26255 case TEST_VS:
26256 switch (stage)
26257 {
26258 case Utils::Shader::FRAGMENT:
26259 case Utils::Shader::VERTEX:
26260 source = BufferTestBase::getShaderSource(test_case_index, stage);
26261 break;
26262 default:
26263 break;
26264 }
26265 break;
26266
26267 case TEST_TES:
26268 switch (stage)
26269 {
26270 case Utils::Shader::FRAGMENT:
26271 case Utils::Shader::TESS_CTRL:
26272 case Utils::Shader::TESS_EVAL:
26273 case Utils::Shader::VERTEX:
26274 source = BufferTestBase::getShaderSource(test_case_index, stage);
26275 break;
26276 default:
26277 break;
26278 }
26279 break;
26280
26281 case TEST_GS:
26282 source = BufferTestBase::getShaderSource(test_case_index, stage);
26283 break;
26284
26285 default:
26286 TCU_FAIL("Invalid enum");
26287 }
26288
26289 /* */
26290 return source;
26291 }
26292
26293 /** Get name of test case
26294 *
26295 * @param test_case_index Index of test case
26296 *
26297 * @return Name of tested stage
26298 **/
26299 std::string XFBCaptureInactiveOutputVariableTest::getTestCaseName(glw::GLuint test_case_index)
26300 {
26301 const GLchar* name = 0;
26302
26303 switch (test_case_index)
26304 {
26305 case TEST_VS:
26306 name = "vertex";
26307 break;
26308 case TEST_TES:
26309 name = "tessellation evaluation";
26310 break;
26311 case TEST_GS:
26312 name = "geometry";
26313 break;
26314 default:
26315 TCU_FAIL("Invalid enum");
26316 }
26317
26318 return name;
26319 }
26320
26321 /** Returns number of test cases
26322 *
26323 * @return TEST_MAX
26324 **/
26325 glw::GLuint XFBCaptureInactiveOutputVariableTest::getTestCaseNumber()
26326 {
26327 return TEST_MAX;
26328 }
26329
26330 /** Inspects program to check if all resources are as expected
26331 *
26332 * @param ignored
26333 * @param program Program instance
26334 * @param out_stream Error message
26335 *
26336 * @return true if everything is ok, false otherwise
26337 **/
26338 bool XFBCaptureInactiveOutputVariableTest::inspectProgram(GLuint /* test_case_index */, Utils::Program& program,
26339 std::stringstream& out_stream)
26340 {
26341 GLint stride = 0;
26342 const Utils::Type& type = Utils::Type::vec4;
26343 const GLuint type_size = type.GetSize();
26344
26345 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
26346 1 /* buf_size */, &stride);
26347
26348 if ((GLint)(3 * type_size) != stride)
26349 {
26350 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
26351
26352 return false;
26353 }
26354
26355 return true;
26356 }
26357
26358 /** Verify contents of buffers
26359 *
26360 * @param buffers Collection of buffers to be verified
26361 *
26362 * @return true if everything is as expected, false otherwise
26363 **/
26364 bool XFBCaptureInactiveOutputVariableTest::verifyBuffers(bufferCollection& buffers)
26365 {
26366 bool result = true;
26367
26368 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26369 Utils::Buffer* buffer = pair.m_buffer;
26370 bufferDescriptor* descriptor = pair.m_descriptor;
26371
26372 /* Get pointer to contents of buffer */
26373 buffer->Bind();
26374 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26375
26376 /* Get pointer to expected data */
26377 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26378
26379 /* Compare */
26380 static const GLuint vec4_size = 16;
26381
26382 int res_gohan = memcmp(buffer_data + 2 * vec4_size, expected_data + 2 * vec4_size, vec4_size);
26383 int res_goten = memcmp(buffer_data + 0 * vec4_size, expected_data + 0 * vec4_size, vec4_size);
26384
26385 if ((0 != res_gohan) || (0 != res_goten))
26386 {
26387 m_context.getTestContext().getLog()
26388 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26389 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26390
26391 result = false;
26392 }
26393
26394 /* Release buffer mapping */
26395 buffer->UnMap();
26396
26397 return result;
26398 }
26399
26400 /** Constructor
26401 *
26402 * @param context Test context
26403 **/
26404 XFBCaptureInactiveOutputComponentTest::XFBCaptureInactiveOutputComponentTest(deqp::Context& context)
26405 : BufferTestBase(context, "xfb_capture_inactive_output_component",
26406 "Test verifies that inactive components are not modified")
26407 {
26408 /* Nothing to be done here */
26409 }
26410
26411 /** Execute drawArrays for single vertex
26412 *
26413 * @param test_case_index
26414 *
26415 * @return true
26416 **/
26417 bool XFBCaptureInactiveOutputComponentTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26418 {
26419 const Functions& gl = m_context.getRenderContext().getFunctions();
26420 GLenum primitive_type = GL_PATCHES;
26421
26422 if (TEST_VS == test_case_index)
26423 {
26424 primitive_type = GL_POINTS;
26425 }
26426
26427 gl.disable(GL_RASTERIZER_DISCARD);
26428 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26429
26430 gl.beginTransformFeedback(GL_POINTS);
26431 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26432
26433 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26434 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26435
26436 gl.endTransformFeedback();
26437 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26438
26439 return true;
26440 }
26441
26442 /** Get descriptors of buffers necessary for test
26443 *
26444 * @param ignored
26445 * @param out_descriptors Descriptors of buffers used by test
26446 **/
26447 void XFBCaptureInactiveOutputComponentTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26448 bufferDescriptor::Vector& out_descriptors)
26449 {
26450 const Utils::Type& type = Utils::Type::vec4;
26451
26452 /* Test needs single uniform and xfb */
26453 out_descriptors.resize(2);
26454
26455 /* Get references */
26456 bufferDescriptor& uniform = out_descriptors[0];
26457 bufferDescriptor& xfb = out_descriptors[1];
26458
26459 /* Index */
26460 uniform.m_index = 0;
26461 xfb.m_index = 0;
26462
26463 /* Target */
26464 uniform.m_target = Utils::Buffer::Uniform;
26465 xfb.m_target = Utils::Buffer::Transform_feedback;
26466
26467 /* Data */
26468 const std::vector<GLubyte>& goku_data = type.GenerateData();
26469 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26470 const std::vector<GLubyte>& goten_data = type.GenerateData();
26471 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26472 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
26473 const std::vector<GLubyte>& trunks_data = type.GenerateData();
26474 const std::vector<GLubyte>& bra_data = type.GenerateData();
26475 const std::vector<GLubyte>& bulma_data = type.GenerateData();
26476
26477 const GLuint comp_size = Utils::Type::GetTypeSize(type.m_basic_type);
26478 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26479
26480 /* Uniform data */
26481 uniform.m_initial_data.resize(8 * type_size);
26482 memcpy(&uniform.m_initial_data[0] + 0 * type_size, &goku_data[0], type_size);
26483 memcpy(&uniform.m_initial_data[0] + 1 * type_size, &gohan_data[0], type_size);
26484 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
26485 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &chichi_data[0], type_size);
26486 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
26487 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &trunks_data[0], type_size);
26488 memcpy(&uniform.m_initial_data[0] + 6 * type_size, &bra_data[0], type_size);
26489 memcpy(&uniform.m_initial_data[0] + 7 * type_size, &bulma_data[0], type_size);
26490
26491 /* XFB data */
26492 xfb.m_initial_data.resize(8 * type_size);
26493 xfb.m_expected_data.resize(8 * type_size);
26494
26495 for (GLuint i = 0; i < 8 * type_size; ++i)
26496 {
26497 xfb.m_initial_data[i] = (glw::GLubyte)i;
26498 xfb.m_expected_data[i] = (glw::GLubyte)i;
26499 }
26500
26501 /* goku - x, z - 32 */
26502 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 0 * comp_size, &goku_data[0] + 0 * comp_size, comp_size);
26503 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 2 * comp_size, &goku_data[0] + 2 * comp_size, comp_size);
26504
26505 /* gohan - y, w - 0 */
26506 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 1 * comp_size, &gohan_data[0] + 1 * comp_size, comp_size);
26507 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 3 * comp_size, &gohan_data[0] + 3 * comp_size, comp_size);
26508
26509 /* goten - x, y - 16 */
26510 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 0 * comp_size, &goten_data[0] + 0 * comp_size, comp_size);
26511 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 1 * comp_size, &goten_data[0] + 1 * comp_size, comp_size);
26512
26513 /* chichi - z, w - 48 */
26514 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 2 * comp_size, &chichi_data[0] + 2 * comp_size, comp_size);
26515 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 3 * comp_size, &chichi_data[0] + 3 * comp_size, comp_size);
26516
26517 /* vegeta - x - 112 */
26518 memcpy(&xfb.m_expected_data[0] + 7 * type_size + 0 * comp_size, &vegeta_data[0] + 0 * comp_size, comp_size);
26519
26520 /* trunks - y - 96 */
26521 memcpy(&xfb.m_expected_data[0] + 6 * type_size + 1 * comp_size, &trunks_data[0] + 1 * comp_size, comp_size);
26522
26523 /* bra - z - 80 */
26524 memcpy(&xfb.m_expected_data[0] + 5 * type_size + 2 * comp_size, &bra_data[0] + 2 * comp_size, comp_size);
26525
26526 /* bulma - w - 64 */
26527 memcpy(&xfb.m_expected_data[0] + 4 * type_size + 3 * comp_size, &bulma_data[0] + 3 * comp_size, comp_size);
26528 }
26529
26530 /** Get body of main function for given shader stage
26531 *
26532 * @param test_case_index Index of test case
26533 * @param stage Shader stage
26534 * @param out_assignments Set to empty
26535 * @param out_calculations Set to empty
26536 **/
26537 void XFBCaptureInactiveOutputComponentTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26538 std::string& out_assignments, std::string& out_calculations)
26539 {
26540 out_calculations = "";
26541
26542 static const GLchar* vs_tes_gs = " goku.x = uni_goku.x ;\n"
26543 " goku.z = uni_goku.z ;\n"
26544 " gohan.y = uni_gohan.y ;\n"
26545 " gohan.w = uni_gohan.w ;\n"
26546 " goten.x = uni_goten.x ;\n"
26547 " goten.y = uni_goten.y ;\n"
26548 " chichi.z = uni_chichi.z ;\n"
26549 " chichi.w = uni_chichi.w ;\n"
26550 " vegeta.x = uni_vegeta.x ;\n"
26551 " trunks.y = uni_trunks.y ;\n"
26552 " bra.z = uni_bra.z ;\n"
26553 " bulma.w = uni_bulma.w ;\n";
26554 static const GLchar* fs = " fs_out = goku + gohan + goten + chichi + vegeta + trunks + bra + bulma;\n";
26555
26556 const GLchar* assignments = "";
26557
26558 switch (stage)
26559 {
26560 case Utils::Shader::FRAGMENT:
26561 assignments = fs;
26562 break;
26563
26564 case Utils::Shader::GEOMETRY:
26565 if (TEST_GS == test_case_index)
26566 {
26567 assignments = vs_tes_gs;
26568 }
26569 break;
26570
26571 case Utils::Shader::TESS_CTRL:
26572 break;
26573
26574 case Utils::Shader::TESS_EVAL:
26575 if (TEST_TES == test_case_index)
26576 {
26577 assignments = vs_tes_gs;
26578 }
26579 break;
26580
26581 case Utils::Shader::VERTEX:
26582 if (TEST_VS == test_case_index)
26583 {
26584 assignments = vs_tes_gs;
26585 }
26586 break;
26587
26588 default:
26589 TCU_FAIL("Invalid enum");
26590 }
26591
26592 out_assignments = assignments;
26593 }
26594
26595 /** Get interface of shader
26596 *
26597 * @param test_case_index Index of test case
26598 * @param stage Shader stage
26599 * @param out_interface Set to ""
26600 **/
26601 void XFBCaptureInactiveOutputComponentTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26602 std::string& out_interface)
26603 {
26604 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26605 "\n"
26606 "layout (xfb_offset = 2 * sizeof_type) out vec4 goku;\n"
26607 "layout (xfb_offset = 0 * sizeof_type) out vec4 gohan;\n"
26608 "layout (xfb_offset = 1 * sizeof_type) out vec4 goten;\n"
26609 "layout (xfb_offset = 3 * sizeof_type) out vec4 chichi;\n"
26610 "layout (xfb_offset = 7 * sizeof_type) out vec4 vegeta;\n"
26611 "layout (xfb_offset = 6 * sizeof_type) out vec4 trunks;\n"
26612 "layout (xfb_offset = 5 * sizeof_type) out vec4 bra;\n"
26613 "layout (xfb_offset = 4 * sizeof_type) out vec4 bulma;\n"
26614 "\n"
26615 "layout(binding = 0) uniform block {\n"
26616 " vec4 uni_goku;\n"
26617 " vec4 uni_gohan;\n"
26618 " vec4 uni_goten;\n"
26619 " vec4 uni_chichi;\n"
26620 " vec4 uni_vegeta;\n"
26621 " vec4 uni_trunks;\n"
26622 " vec4 uni_bra;\n"
26623 " vec4 uni_bulma;\n"
26624 "};\n";
26625 static const GLchar* fs = "in vec4 vegeta;\n"
26626 "in vec4 trunks;\n"
26627 "in vec4 bra;\n"
26628 "in vec4 bulma;\n"
26629 "in vec4 goku;\n"
26630 "in vec4 gohan;\n"
26631 "in vec4 goten;\n"
26632 "in vec4 chichi;\n"
26633 "\n"
26634 "out vec4 fs_out;\n";
26635
26636 const GLchar* interface = "";
26637
26638 switch (stage)
26639 {
26640 case Utils::Shader::FRAGMENT:
26641 interface = fs;
26642 break;
26643
26644 case Utils::Shader::GEOMETRY:
26645 if (TEST_GS == test_case_index)
26646 {
26647 interface = vs_tes_gs;
26648 }
26649 break;
26650
26651 case Utils::Shader::TESS_CTRL:
26652 break;
26653
26654 case Utils::Shader::TESS_EVAL:
26655 if (TEST_TES == test_case_index)
26656 {
26657 interface = vs_tes_gs;
26658 }
26659 break;
26660
26661 case Utils::Shader::VERTEX:
26662 if (TEST_VS == test_case_index)
26663 {
26664 interface = vs_tes_gs;
26665 }
26666 break;
26667
26668 default:
26669 TCU_FAIL("Invalid enum");
26670 }
26671
26672 out_interface = interface;
26673 }
26674
26675 /** Get source code of shader
26676 *
26677 * @param test_case_index Index of test case
26678 * @param stage Shader stage
26679 *
26680 * @return Source
26681 **/
26682 std::string XFBCaptureInactiveOutputComponentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26683 {
26684 std::string source;
26685
26686 switch (test_case_index)
26687 {
26688 case TEST_VS:
26689 switch (stage)
26690 {
26691 case Utils::Shader::FRAGMENT:
26692 case Utils::Shader::VERTEX:
26693 source = BufferTestBase::getShaderSource(test_case_index, stage);
26694 break;
26695 default:
26696 break;
26697 }
26698 break;
26699
26700 case TEST_TES:
26701 switch (stage)
26702 {
26703 case Utils::Shader::FRAGMENT:
26704 case Utils::Shader::TESS_CTRL:
26705 case Utils::Shader::TESS_EVAL:
26706 case Utils::Shader::VERTEX:
26707 source = BufferTestBase::getShaderSource(test_case_index, stage);
26708 break;
26709 default:
26710 break;
26711 }
26712 break;
26713
26714 case TEST_GS:
26715 source = BufferTestBase::getShaderSource(test_case_index, stage);
26716 break;
26717
26718 default:
26719 TCU_FAIL("Invalid enum");
26720 }
26721
26722 /* */
26723 return source;
26724 }
26725
26726 /** Get name of test case
26727 *
26728 * @param test_case_index Index of test case
26729 *
26730 * @return Name of tested stage
26731 **/
26732 std::string XFBCaptureInactiveOutputComponentTest::getTestCaseName(glw::GLuint test_case_index)
26733 {
26734 const GLchar* name = 0;
26735
26736 switch (test_case_index)
26737 {
26738 case TEST_VS:
26739 name = "vertex";
26740 break;
26741 case TEST_TES:
26742 name = "tessellation evaluation";
26743 break;
26744 case TEST_GS:
26745 name = "geometry";
26746 break;
26747 default:
26748 TCU_FAIL("Invalid enum");
26749 }
26750
26751 return name;
26752 }
26753
26754 /** Returns number of test cases
26755 *
26756 * @return TEST_MAX
26757 **/
26758 glw::GLuint XFBCaptureInactiveOutputComponentTest::getTestCaseNumber()
26759 {
26760 return TEST_MAX;
26761 }
26762
26763 /** Verify contents of buffers
26764 *
26765 * @param buffers Collection of buffers to be verified
26766 *
26767 * @return true if everything is as expected, false otherwise
26768 **/
26769 bool XFBCaptureInactiveOutputComponentTest::verifyBuffers(bufferCollection& buffers)
26770 {
26771 bool result = true;
26772
26773 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26774 Utils::Buffer* buffer = pair.m_buffer;
26775 bufferDescriptor* descriptor = pair.m_descriptor;
26776
26777 /* Get pointer to contents of buffer */
26778 buffer->Bind();
26779 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26780
26781 /* Get pointer to expected data */
26782 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26783
26784 /* Compare */
26785 static const GLuint comp_size = 4;
26786 static const GLuint vec4_size = 16;
26787
26788 int res_goku_x =
26789 memcmp(buffer_data + 2 * vec4_size + 0 * comp_size, expected_data + 2 * vec4_size + 0 * comp_size, comp_size);
26790 int res_goku_z =
26791 memcmp(buffer_data + 2 * vec4_size + 2 * comp_size, expected_data + 2 * vec4_size + 2 * comp_size, comp_size);
26792
26793 int res_gohan_y =
26794 memcmp(buffer_data + 0 * vec4_size + 1 * comp_size, expected_data + 0 * vec4_size + 1 * comp_size, comp_size);
26795 int res_gohan_w =
26796 memcmp(buffer_data + 0 * vec4_size + 3 * comp_size, expected_data + 0 * vec4_size + 3 * comp_size, comp_size);
26797
26798 int res_goten_x =
26799 memcmp(buffer_data + 1 * vec4_size + 0 * comp_size, expected_data + 1 * vec4_size + 0 * comp_size, comp_size);
26800 int res_goten_y =
26801 memcmp(buffer_data + 1 * vec4_size + 1 * comp_size, expected_data + 1 * vec4_size + 1 * comp_size, comp_size);
26802
26803 int res_chichi_z =
26804 memcmp(buffer_data + 3 * vec4_size + 2 * comp_size, expected_data + 3 * vec4_size + 2 * comp_size, comp_size);
26805 int res_chichi_w =
26806 memcmp(buffer_data + 3 * vec4_size + 3 * comp_size, expected_data + 3 * vec4_size + 3 * comp_size, comp_size);
26807
26808 int res_vegeta_x =
26809 memcmp(buffer_data + 7 * vec4_size + 0 * comp_size, expected_data + 7 * vec4_size + 0 * comp_size, comp_size);
26810
26811 int res_trunks_y =
26812 memcmp(buffer_data + 6 * vec4_size + 1 * comp_size, expected_data + 6 * vec4_size + 1 * comp_size, comp_size);
26813
26814 int res_bra_z =
26815 memcmp(buffer_data + 5 * vec4_size + 2 * comp_size, expected_data + 5 * vec4_size + 2 * comp_size, comp_size);
26816
26817 int res_bulma_w =
26818 memcmp(buffer_data + 4 * vec4_size + 3 * comp_size, expected_data + 4 * vec4_size + 3 * comp_size, comp_size);
26819
26820 if ((0 != res_goku_x) || (0 != res_goku_z) || (0 != res_gohan_y) || (0 != res_gohan_w) || (0 != res_goten_x) ||
26821 (0 != res_goten_y) || (0 != res_chichi_z) || (0 != res_chichi_w) || (0 != res_vegeta_x) ||
26822 (0 != res_trunks_y) || (0 != res_bra_z) || (0 != res_bulma_w))
26823 {
26824 m_context.getTestContext().getLog()
26825 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26826 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26827
26828 result = false;
26829 }
26830
26831 /* Release buffer mapping */
26832 buffer->UnMap();
26833
26834 return result;
26835 }
26836
26837 /** Constructor
26838 *
26839 * @param context Test context
26840 **/
26841 XFBCaptureInactiveOutputBlockMemberTest::XFBCaptureInactiveOutputBlockMemberTest(deqp::Context& context)
26842 : BufferTestBase(context, "xfb_capture_inactive_output_block_member",
26843 "Test verifies that inactive block members are captured")
26844 {
26845 /* Nothing to be done here */
26846 }
26847
26848 /** Execute drawArrays for single vertex
26849 *
26850 * @param test_case_index
26851 *
26852 * @return true
26853 **/
26854 bool XFBCaptureInactiveOutputBlockMemberTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26855 {
26856 const Functions& gl = m_context.getRenderContext().getFunctions();
26857 GLenum primitive_type = GL_PATCHES;
26858
26859 if (TEST_VS == test_case_index)
26860 {
26861 primitive_type = GL_POINTS;
26862 }
26863
26864 gl.disable(GL_RASTERIZER_DISCARD);
26865 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26866
26867 gl.beginTransformFeedback(GL_POINTS);
26868 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26869
26870 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26871 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26872
26873 gl.endTransformFeedback();
26874 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26875
26876 return true;
26877 }
26878
26879 /** Get descriptors of buffers necessary for test
26880 *
26881 * @param ignored
26882 * @param out_descriptors Descriptors of buffers used by test
26883 **/
26884 void XFBCaptureInactiveOutputBlockMemberTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26885 bufferDescriptor::Vector& out_descriptors)
26886 {
26887 const Utils::Type& type = Utils::Type::vec4;
26888
26889 /* Test needs single uniform and xfb */
26890 out_descriptors.resize(2);
26891
26892 /* Get references */
26893 bufferDescriptor& uniform = out_descriptors[0];
26894 bufferDescriptor& xfb = out_descriptors[1];
26895
26896 /* Index */
26897 uniform.m_index = 0;
26898 xfb.m_index = 0;
26899
26900 /* Target */
26901 uniform.m_target = Utils::Buffer::Uniform;
26902 xfb.m_target = Utils::Buffer::Transform_feedback;
26903
26904 /* Data */
26905 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26906 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26907
26908 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26909
26910 /* Uniform data */
26911 uniform.m_initial_data.resize(2 * type_size);
26912 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
26913 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
26914
26915 /* XFB data */
26916 xfb.m_initial_data.resize(4 * type_size);
26917 xfb.m_expected_data.resize(4 * type_size);
26918
26919 for (GLuint i = 0; i < 4 * type_size; ++i)
26920 {
26921 xfb.m_initial_data[i] = (glw::GLubyte)i;
26922 xfb.m_expected_data[i] = (glw::GLubyte)i;
26923 }
26924
26925 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
26926 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
26927 }
26928
26929 /** Get body of main function for given shader stage
26930 *
26931 * @param test_case_index Index of test case
26932 * @param stage Shader stage
26933 * @param out_assignments Set to empty
26934 * @param out_calculations Set to empty
26935 **/
26936 void XFBCaptureInactiveOutputBlockMemberTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26937 std::string& out_assignments, std::string& out_calculations)
26938 {
26939 out_calculations = "";
26940
26941 static const GLchar* vs_tes_gs = " chichi = uni_chichi;\n"
26942 " gohan = uni_gohan;\n";
26943 static const GLchar* fs = " fs_out = goten + gohan + chichi;\n";
26944
26945 const GLchar* assignments = "";
26946
26947 switch (stage)
26948 {
26949 case Utils::Shader::FRAGMENT:
26950 assignments = fs;
26951 break;
26952
26953 case Utils::Shader::GEOMETRY:
26954 if (TEST_GS == test_case_index)
26955 {
26956 assignments = vs_tes_gs;
26957 }
26958 break;
26959
26960 case Utils::Shader::TESS_CTRL:
26961 break;
26962
26963 case Utils::Shader::TESS_EVAL:
26964 if (TEST_TES == test_case_index)
26965 {
26966 assignments = vs_tes_gs;
26967 }
26968 break;
26969
26970 case Utils::Shader::VERTEX:
26971 if (TEST_VS == test_case_index)
26972 {
26973 assignments = vs_tes_gs;
26974 }
26975 break;
26976
26977 default:
26978 TCU_FAIL("Invalid enum");
26979 }
26980
26981 out_assignments = assignments;
26982 }
26983
26984 /** Get interface of shader
26985 *
26986 * @param test_case_index Index of test case
26987 * @param stage Shader stage
26988 * @param out_interface Set to ""
26989 **/
26990 void XFBCaptureInactiveOutputBlockMemberTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26991 std::string& out_interface)
26992 {
26993 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26994 "\n"
26995 "layout (xfb_offset = 1 * sizeof_type) out Goku {\n"
26996 " vec4 gohan;\n"
26997 " vec4 goten;\n"
26998 " vec4 chichi;\n"
26999 "};\n"
27000 "\n"
27001 "layout(binding = 0) uniform block {\n"
27002 " vec4 uni_gohan;\n"
27003 " vec4 uni_chichi;\n"
27004 "};\n";
27005 static const GLchar* fs = "in Goku {\n"
27006 " vec4 gohan;\n"
27007 " vec4 goten;\n"
27008 " vec4 chichi;\n"
27009 "};\n"
27010 "out vec4 fs_out;\n";
27011
27012 const GLchar* interface = "";
27013
27014 switch (stage)
27015 {
27016 case Utils::Shader::FRAGMENT:
27017 interface = fs;
27018 break;
27019
27020 case Utils::Shader::GEOMETRY:
27021 if (TEST_GS == test_case_index)
27022 {
27023 interface = vs_tes_gs;
27024 }
27025 break;
27026
27027 case Utils::Shader::TESS_CTRL:
27028 break;
27029
27030 case Utils::Shader::TESS_EVAL:
27031 if (TEST_TES == test_case_index)
27032 {
27033 interface = vs_tes_gs;
27034 }
27035 break;
27036
27037 case Utils::Shader::VERTEX:
27038 if (TEST_VS == test_case_index)
27039 {
27040 interface = vs_tes_gs;
27041 }
27042 break;
27043
27044 default:
27045 TCU_FAIL("Invalid enum");
27046 }
27047
27048 out_interface = interface;
27049 }
27050
27051 /** Get source code of shader
27052 *
27053 * @param test_case_index Index of test case
27054 * @param stage Shader stage
27055 *
27056 * @return Source
27057 **/
27058 std::string XFBCaptureInactiveOutputBlockMemberTest::getShaderSource(GLuint test_case_index,
27059 Utils::Shader::STAGES stage)
27060 {
27061 std::string source;
27062
27063 switch (test_case_index)
27064 {
27065 case TEST_VS:
27066 switch (stage)
27067 {
27068 case Utils::Shader::FRAGMENT:
27069 case Utils::Shader::VERTEX:
27070 source = BufferTestBase::getShaderSource(test_case_index, stage);
27071 break;
27072 default:
27073 break;
27074 }
27075 break;
27076
27077 case TEST_TES:
27078 switch (stage)
27079 {
27080 case Utils::Shader::FRAGMENT:
27081 case Utils::Shader::TESS_CTRL:
27082 case Utils::Shader::TESS_EVAL:
27083 case Utils::Shader::VERTEX:
27084 source = BufferTestBase::getShaderSource(test_case_index, stage);
27085 break;
27086 default:
27087 break;
27088 }
27089 break;
27090
27091 case TEST_GS:
27092 source = BufferTestBase::getShaderSource(test_case_index, stage);
27093 break;
27094
27095 default:
27096 TCU_FAIL("Invalid enum");
27097 }
27098
27099 /* */
27100 return source;
27101 }
27102
27103 /** Get name of test case
27104 *
27105 * @param test_case_index Index of test case
27106 *
27107 * @return Name of tested stage
27108 **/
27109 std::string XFBCaptureInactiveOutputBlockMemberTest::getTestCaseName(glw::GLuint test_case_index)
27110 {
27111 const GLchar* name = 0;
27112
27113 switch (test_case_index)
27114 {
27115 case TEST_VS:
27116 name = "vertex";
27117 break;
27118 case TEST_TES:
27119 name = "tessellation evaluation";
27120 break;
27121 case TEST_GS:
27122 name = "geometry";
27123 break;
27124 default:
27125 TCU_FAIL("Invalid enum");
27126 }
27127
27128 return name;
27129 }
27130
27131 /** Returns number of test cases
27132 *
27133 * @return TEST_MAX
27134 **/
27135 glw::GLuint XFBCaptureInactiveOutputBlockMemberTest::getTestCaseNumber()
27136 {
27137 return TEST_MAX;
27138 }
27139
27140 /** Verify contents of buffers
27141 *
27142 * @param buffers Collection of buffers to be verified
27143 *
27144 * @return true if everything is as expected, false otherwise
27145 **/
27146 bool XFBCaptureInactiveOutputBlockMemberTest::verifyBuffers(bufferCollection& buffers)
27147 {
27148 bool result = true;
27149
27150 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27151 Utils::Buffer* buffer = pair.m_buffer;
27152 bufferDescriptor* descriptor = pair.m_descriptor;
27153
27154 /* Get pointer to contents of buffer */
27155 buffer->Bind();
27156 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27157
27158 /* Get pointer to expected data */
27159 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27160
27161 /* Compare */
27162 static const GLuint vec4_size = 16;
27163
27164 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27165 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27166 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27167
27168 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27169 {
27170 m_context.getTestContext().getLog()
27171 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27172 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27173
27174 result = false;
27175 }
27176
27177 /* Release buffer mapping */
27178 buffer->UnMap();
27179
27180 return result;
27181 }
27182
27183 /** Constructor
27184 *
27185 * @param context Test context
27186 **/
27187 XFBCaptureStructTest::XFBCaptureStructTest(deqp::Context& context)
27188 : BufferTestBase(context, "xfb_capture_struct", "Test verifies that inactive structure members are captured")
27189 {
27190 /* Nothing to be done here */
27191 }
27192
27193 /** Execute drawArrays for single vertex
27194 *
27195 * @param test_case_index
27196 *
27197 * @return true
27198 **/
27199 bool XFBCaptureStructTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
27200 {
27201 const Functions& gl = m_context.getRenderContext().getFunctions();
27202 GLenum primitive_type = GL_PATCHES;
27203
27204 if (TEST_VS == test_case_index)
27205 {
27206 primitive_type = GL_POINTS;
27207 }
27208
27209 gl.disable(GL_RASTERIZER_DISCARD);
27210 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
27211
27212 gl.beginTransformFeedback(GL_POINTS);
27213 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
27214
27215 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
27216 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
27217
27218 gl.endTransformFeedback();
27219 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
27220
27221 return true;
27222 }
27223
27224 /** Get descriptors of buffers necessary for test
27225 *
27226 * @param ignored
27227 * @param out_descriptors Descriptors of buffers used by test
27228 **/
27229 void XFBCaptureStructTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
27230 bufferDescriptor::Vector& out_descriptors)
27231 {
27232 const Utils::Type& type = Utils::Type::vec4;
27233
27234 /* Test needs single uniform and xfb */
27235 out_descriptors.resize(2);
27236
27237 /* Get references */
27238 bufferDescriptor& uniform = out_descriptors[0];
27239 bufferDescriptor& xfb = out_descriptors[1];
27240
27241 /* Index */
27242 uniform.m_index = 0;
27243 xfb.m_index = 0;
27244
27245 /* Target */
27246 uniform.m_target = Utils::Buffer::Uniform;
27247 xfb.m_target = Utils::Buffer::Transform_feedback;
27248
27249 /* Data */
27250 const std::vector<GLubyte>& gohan_data = type.GenerateData();
27251 const std::vector<GLubyte>& chichi_data = type.GenerateData();
27252
27253 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
27254
27255 /* Uniform data */
27256 uniform.m_initial_data.resize(2 * type_size);
27257 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
27258 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
27259
27260 /* XFB data */
27261 xfb.m_initial_data.resize(4 * type_size);
27262 xfb.m_expected_data.resize(4 * type_size);
27263
27264 for (GLuint i = 0; i < 4 * type_size; ++i)
27265 {
27266 xfb.m_initial_data[i] = (glw::GLubyte)i;
27267 xfb.m_expected_data[i] = (glw::GLubyte)i;
27268 }
27269
27270 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
27271 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
27272 }
27273
27274 /** Get body of main function for given shader stage
27275 *
27276 * @param test_case_index Index of test case
27277 * @param stage Shader stage
27278 * @param out_assignments Set to empty
27279 * @param out_calculations Set to empty
27280 **/
27281 void XFBCaptureStructTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
27282 std::string& out_assignments, std::string& out_calculations)
27283 {
27284 out_calculations = "";
27285
27286 static const GLchar* vs_tes_gs = " goku.chichi = uni_chichi;\n"
27287 " goku.gohan = uni_gohan;\n";
27288 static const GLchar* fs = " fs_out = goku.goten + goku.gohan + goku.chichi;\n";
27289
27290 const GLchar* assignments = "";
27291
27292 switch (stage)
27293 {
27294 case Utils::Shader::FRAGMENT:
27295 assignments = fs;
27296 break;
27297
27298 case Utils::Shader::GEOMETRY:
27299 if (TEST_GS == test_case_index)
27300 {
27301 assignments = vs_tes_gs;
27302 }
27303 break;
27304
27305 case Utils::Shader::TESS_CTRL:
27306 break;
27307
27308 case Utils::Shader::TESS_EVAL:
27309 if (TEST_TES == test_case_index)
27310 {
27311 assignments = vs_tes_gs;
27312 }
27313 break;
27314
27315 case Utils::Shader::VERTEX:
27316 if (TEST_VS == test_case_index)
27317 {
27318 assignments = vs_tes_gs;
27319 }
27320 break;
27321
27322 default:
27323 TCU_FAIL("Invalid enum");
27324 }
27325
27326 out_assignments = assignments;
27327 }
27328
27329 /** Get interface of shader
27330 *
27331 * @param test_case_index Index of test case
27332 * @param stage Shader stage
27333 * @param out_interface Set to ""
27334 **/
27335 void XFBCaptureStructTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
27336 std::string& out_interface)
27337 {
27338 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
27339 "\n"
27340 "struct Goku {\n"
27341 " vec4 gohan;\n"
27342 " vec4 goten;\n"
27343 " vec4 chichi;\n"
27344 "};\n"
27345 "\n"
27346 "layout (xfb_offset = sizeof_type) out Goku goku;\n"
27347 "\n"
27348 "layout(binding = 0, std140) uniform block {\n"
27349 " vec4 uni_gohan;\n"
27350 " vec4 uni_chichi;\n"
27351 "};\n";
27352 static const GLchar* fs = "struct Goku {\n"
27353 " vec4 gohan;\n"
27354 " vec4 goten;\n"
27355 " vec4 chichi;\n"
27356 "};\n"
27357 "\n"
27358 "in Goku goku;\n"
27359 "\n"
27360 "out vec4 fs_out;\n";
27361
27362 const GLchar* interface = "";
27363
27364 switch (stage)
27365 {
27366 case Utils::Shader::FRAGMENT:
27367 interface = fs;
27368 break;
27369
27370 case Utils::Shader::GEOMETRY:
27371 if (TEST_GS == test_case_index)
27372 {
27373 interface = vs_tes_gs;
27374 }
27375 break;
27376
27377 case Utils::Shader::TESS_CTRL:
27378 break;
27379
27380 case Utils::Shader::TESS_EVAL:
27381 if (TEST_TES == test_case_index)
27382 {
27383 interface = vs_tes_gs;
27384 }
27385 break;
27386
27387 case Utils::Shader::VERTEX:
27388 if (TEST_VS == test_case_index)
27389 {
27390 interface = vs_tes_gs;
27391 }
27392 break;
27393
27394 default:
27395 TCU_FAIL("Invalid enum");
27396 }
27397
27398 out_interface = interface;
27399 }
27400
27401 /** Get source code of shader
27402 *
27403 * @param test_case_index Index of test case
27404 * @param stage Shader stage
27405 *
27406 * @return Source
27407 **/
27408 std::string XFBCaptureStructTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27409 {
27410 std::string source;
27411
27412 switch (test_case_index)
27413 {
27414 case TEST_VS:
27415 switch (stage)
27416 {
27417 case Utils::Shader::FRAGMENT:
27418 case Utils::Shader::VERTEX:
27419 source = BufferTestBase::getShaderSource(test_case_index, stage);
27420 break;
27421 default:
27422 break;
27423 }
27424 break;
27425
27426 case TEST_TES:
27427 switch (stage)
27428 {
27429 case Utils::Shader::FRAGMENT:
27430 case Utils::Shader::TESS_CTRL:
27431 case Utils::Shader::TESS_EVAL:
27432 case Utils::Shader::VERTEX:
27433 source = BufferTestBase::getShaderSource(test_case_index, stage);
27434 break;
27435 default:
27436 break;
27437 }
27438 break;
27439
27440 case TEST_GS:
27441 source = BufferTestBase::getShaderSource(test_case_index, stage);
27442 break;
27443
27444 default:
27445 TCU_FAIL("Invalid enum");
27446 }
27447
27448 /* */
27449 return source;
27450 }
27451
27452 /** Get name of test case
27453 *
27454 * @param test_case_index Index of test case
27455 *
27456 * @return Name of tested stage
27457 **/
27458 std::string XFBCaptureStructTest::getTestCaseName(glw::GLuint test_case_index)
27459 {
27460 const GLchar* name = 0;
27461
27462 switch (test_case_index)
27463 {
27464 case TEST_VS:
27465 name = "vertex";
27466 break;
27467 case TEST_TES:
27468 name = "tessellation evaluation";
27469 break;
27470 case TEST_GS:
27471 name = "geometry";
27472 break;
27473 default:
27474 TCU_FAIL("Invalid enum");
27475 }
27476
27477 return name;
27478 }
27479
27480 /** Returns number of test cases
27481 *
27482 * @return TEST_MAX
27483 **/
27484 glw::GLuint XFBCaptureStructTest::getTestCaseNumber()
27485 {
27486 return TEST_MAX;
27487 }
27488
27489 /** Verify contents of buffers
27490 *
27491 * @param buffers Collection of buffers to be verified
27492 *
27493 * @return true if everything is as expected, false otherwise
27494 **/
27495 bool XFBCaptureStructTest::verifyBuffers(bufferCollection& buffers)
27496 {
27497 bool result = true;
27498
27499 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27500 Utils::Buffer* buffer = pair.m_buffer;
27501 bufferDescriptor* descriptor = pair.m_descriptor;
27502
27503 /* Get pointer to contents of buffer */
27504 buffer->Bind();
27505 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27506
27507 /* Get pointer to expected data */
27508 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27509
27510 /* Compare */
27511 static const GLuint vec4_size = 16;
27512
27513 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27514 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27515 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27516
27517 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27518 {
27519 m_context.getTestContext().getLog()
27520 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27521 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27522
27523 result = false;
27524 }
27525
27526 /* Release buffer mapping */
27527 buffer->UnMap();
27528
27529 return result;
27530 }
27531
27532 /** Constructor
27533 *
27534 * @param context Test framework context
27535 **/
27536 XFBCaptureUnsizedArrayTest::XFBCaptureUnsizedArrayTest(deqp::Context& context)
27537 : NegativeTestBase(context, "xfb_capture_unsized_array",
27538 "Test verifies that compiler reports error when unsized array is qualified with xfb_offset")
27539 {
27540 }
27541
27542 /** Source for given test case and stage
27543 *
27544 * @param test_case_index Index of test case
27545 * @param stage Shader stage
27546 *
27547 * @return Shader source
27548 **/
27549 std::string XFBCaptureUnsizedArrayTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27550 {
27551 #if DEBUG_NEG_REMOVE_ERROR
27552 static const GLchar* var_definition = "/* layout (xfb_offset = 0) */ out vec4 goku[];\n";
27553 #else
27554 static const GLchar* var_definition = "layout (xfb_offset = 0) out vec4 goku[];\n";
27555 #endif /* DEBUG_NEG_REMOVE_ERROR */
27556 static const GLchar* var_use = " goku[0] = result / 2;\n";
27557 static const GLchar* fs = "#version 430 core\n"
27558 "#extension GL_ARB_enhanced_layouts : require\n"
27559 "\n"
27560 "in vec4 any_fs;\n"
27561 "out vec4 fs_out;\n"
27562 "\n"
27563 "void main()\n"
27564 "{\n"
27565 " fs_out = any_fs;\n"
27566 "}\n"
27567 "\n";
27568 static const GLchar* vs_tested = "#version 430 core\n"
27569 "#extension GL_ARB_enhanced_layouts : require\n"
27570 "\n"
27571 "VAR_DEFINITION"
27572 "\n"
27573 "in vec4 in_vs;\n"
27574 "out vec4 any_fs;\n"
27575 "\n"
27576 "void main()\n"
27577 "{\n"
27578 " vec4 result = in_vs;\n"
27579 "\n"
27580 "VARIABLE_USE"
27581 "\n"
27582 " any_fs = result;\n"
27583 "}\n"
27584 "\n";
27585
27586 std::string source;
27587 testCase& test_case = m_test_cases[test_case_index];
27588
27589 if (test_case.m_stage == stage)
27590 {
27591 size_t position = 0;
27592
27593 switch (stage)
27594 {
27595 case Utils::Shader::VERTEX:
27596 source = vs_tested;
27597 break;
27598 default:
27599 TCU_FAIL("Invalid enum");
27600 }
27601
27602 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
27603 position = 0;
27604 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
27605 }
27606 else
27607 {
27608 switch (test_case.m_stage)
27609 {
27610 case Utils::Shader::VERTEX:
27611 switch (stage)
27612 {
27613 case Utils::Shader::FRAGMENT:
27614 source = fs;
27615 break;
27616 default:
27617 source = "";
27618 }
27619 break;
27620 default:
27621 TCU_FAIL("Invalid enum");
27622 }
27623 }
27624
27625 return source;
27626 }
27627
27628 /** Get description of test case
27629 *
27630 * @param test_case_index Index of test case
27631 *
27632 * @return Test case description
27633 **/
27634 std::string XFBCaptureUnsizedArrayTest::getTestCaseName(GLuint test_case_index)
27635 {
27636 std::stringstream stream;
27637 testCase& test_case = m_test_cases[test_case_index];
27638
27639 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
27640
27641 return stream.str();
27642 }
27643
27644 /** Get number of test cases
27645 *
27646 * @return Number of test cases
27647 **/
27648 GLuint XFBCaptureUnsizedArrayTest::getTestCaseNumber()
27649 {
27650 return static_cast<GLuint>(m_test_cases.size());
27651 }
27652
27653 /** Selects if "compute" stage is relevant for test
27654 *
27655 * @param ignored
27656 *
27657 * @return false
27658 **/
27659 bool XFBCaptureUnsizedArrayTest::isComputeRelevant(GLuint /* test_case_index */)
27660 {
27661 return false;
27662 }
27663
27664 /** Prepare all test cases
27665 *
27666 **/
27667 void XFBCaptureUnsizedArrayTest::testInit()
27668 {
27669 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
27670 {
27671 /* Not aplicable for */
27672 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
27673 (Utils::Shader::FRAGMENT == stage) || (Utils::Shader::GEOMETRY == stage) ||
27674 (Utils::Shader::TESS_EVAL == stage))
27675 {
27676 continue;
27677 }
27678
27679 testCase test_case = { (Utils::Shader::STAGES)stage };
27680
27681 m_test_cases.push_back(test_case);
27682 }
27683 }
27684
27685 /** Constructor
27686 *
27687 * @param context Test context
27688 **/
27689 XFBExplicitLocationTest::XFBExplicitLocationTest(deqp::Context& context)
27690 : BufferTestBase(context, "xfb_explicit_location", "Test verifies that explicit location on matrices and arrays does not impact xfb output")
27691 {
27692 /* Nothing to be done here */
27693 }
27694
27695 /** Execute drawArrays for single vertex
27696 *
27697 * @param test_case_index
27698 *
27699 * @return true
27700 **/
27701 bool XFBExplicitLocationTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
27702 {
27703 const Functions& gl = m_context.getRenderContext().getFunctions();
27704 GLenum primitive_type = GL_PATCHES;
27705 const testCase& test_case = m_test_cases[test_case_index];
27706
27707 if (Utils::Shader::VERTEX == test_case.m_stage)
27708 {
27709 primitive_type = GL_POINTS;
27710 }
27711
27712 gl.disable(GL_RASTERIZER_DISCARD);
27713 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
27714
27715 gl.beginTransformFeedback(GL_POINTS);
27716 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
27717
27718 gl.drawArrays(primitive_type, 0 /* first */, 2 /* count */);
27719 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
27720
27721 gl.endTransformFeedback();
27722 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
27723
27724 return true;
27725 }
27726
27727 /** Get descriptors of buffers necessary for test
27728 *
27729 * @param test_case_index Index of test case
27730 * @param out_descriptors Descriptors of buffers used by test
27731 **/
27732 void XFBExplicitLocationTest::getBufferDescriptors(GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
27733 {
27734 const testCase& test_case = m_test_cases[test_case_index];
27735 const Utils::Type& type = test_case.m_type;
27736
27737 /* Test needs single uniform and xfb */
27738 out_descriptors.resize(2);
27739
27740 /* Get references */
27741 bufferDescriptor& uniform = out_descriptors[0];
27742 bufferDescriptor& xfb = out_descriptors[1];
27743
27744 /* Index */
27745 uniform.m_index = 0;
27746 xfb.m_index = 0;
27747
27748 /* Target */
27749 uniform.m_target = Utils::Buffer::Uniform;
27750 xfb.m_target = Utils::Buffer::Transform_feedback;
27751
27752 /* Data */
27753 const GLuint rand_start = Utils::s_rand;
27754 std::vector<GLubyte> uniform_data;
27755
27756 for (GLuint i = 0; i < std::max(test_case.m_array_size, 1u); i++)
27757 {
27758 const std::vector<GLubyte>& type_uniform_data = type.GenerateData();
27759 /**
27760 * Rule 4 of Section 7.6.2.2:
27761 *
27762 * If the member is an array of scalars or vectors, the base alignment and array stride
27763 * are set to match the base alignment of a single array element, according to rules (1),
27764 * (2), and (3), and rounded up to the base alignment of a vec4.
27765 */
27766 uniform_data.resize(Utils::align(uniform_data.size(), 16));
27767 uniform_data.insert(uniform_data.end(), type_uniform_data.begin(), type_uniform_data.end());
27768 }
27769
27770 Utils::s_rand = rand_start;
27771 std::vector<GLubyte> xfb_data;
27772
27773 for (GLuint i = 0; i < std::max(test_case.m_array_size, 1u); i++)
27774 {
27775 const std::vector<GLubyte>& type_xfb_data = type.GenerateDataPacked();
27776 xfb_data.insert(xfb_data.end(), type_xfb_data.begin(), type_xfb_data.end());
27777 }
27778
27779 const GLuint uni_type_size = static_cast<GLuint>(uniform_data.size());
27780 const GLuint xfb_type_size = static_cast<GLuint>(xfb_data.size());
27781 /*
27782 Note: If xfb varying output from vertex shader, the variable "goku" will only output once to transform feedback buffer,
27783 if xfb varying output from TES or GS, because the input primitive type in TES is defined as "layout(isolines, point_mode) in;",
27784 the primitive type is line which make the variable "goku" will output twice to transform feedback buffer, so for vertex shader
27785 only one valid data should be initialized in xfb.m_expected_data
27786 */
27787 const GLuint xfb_data_size = (test_case.m_stage == Utils::Shader::VERTEX) ? xfb_type_size : xfb_type_size * 2;
27788 /* Uniform data */
27789 uniform.m_initial_data.resize(uni_type_size);
27790 memcpy(&uniform.m_initial_data[0] + 0 * uni_type_size, &uniform_data[0], uni_type_size);
27791
27792 /* XFB data */
27793 xfb.m_initial_data.resize(xfb_data_size, 0);
27794 xfb.m_expected_data.resize(xfb_data_size);
27795
27796 if (test_case.m_stage == Utils::Shader::VERTEX)
27797 {
27798 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
27799 }
27800 else
27801 {
27802 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
27803 memcpy(&xfb.m_expected_data[0] + 1 * xfb_type_size, &xfb_data[0], xfb_type_size);
27804 }
27805 }
27806
27807 /** Get body of main function for given shader stage
27808 *
27809 * @param test_case_index Index of test case
27810 * @param stage Shader stage
27811 * @param out_assignments Set to empty
27812 * @param out_calculations Set to empty
27813 **/
27814 void XFBExplicitLocationTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_assignments,
27815 std::string& out_calculations)
27816 {
27817 const testCase& test_case = m_test_cases[test_case_index];
27818
27819 out_calculations = "";
27820
27821 static const GLchar* vs_tes_gs = " goku = uni_goku;\n";
27822
27823 const GLchar* assignments = "";
27824
27825 if (test_case.m_stage == stage)
27826 {
27827 switch (stage)
27828 {
27829 case Utils::Shader::GEOMETRY:
27830 assignments = vs_tes_gs;
27831 break;
27832 case Utils::Shader::TESS_EVAL:
27833 assignments = vs_tes_gs;
27834 break;
27835 case Utils::Shader::VERTEX:
27836 assignments = vs_tes_gs;
27837 break;
27838 default:
27839 TCU_FAIL("Invalid enum");
27840 }
27841 }
27842 else
27843 {
27844 switch (stage)
27845 {
27846 case Utils::Shader::FRAGMENT:
27847 assignments = "";
27848 break;
27849 case Utils::Shader::GEOMETRY:
27850 case Utils::Shader::TESS_CTRL:
27851 case Utils::Shader::TESS_EVAL:
27852 case Utils::Shader::VERTEX:
27853 break;
27854 default:
27855 TCU_FAIL("Invalid enum");
27856 }
27857 }
27858
27859 out_assignments = assignments;
27860
27861 if (Utils::Shader::FRAGMENT == stage)
27862 {
27863 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_assignments);
27864 }
27865 }
27866
27867 /** Get interface of shader
27868 *
27869 * @param test_case_index Index of test case
27870 * @param stage Shader stage
27871 * @param out_interface Set to ""
27872 **/
27873 void XFBExplicitLocationTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_interface)
27874 {
27875 static const GLchar* vs_tes_gs = "layout (location = 0, xfb_offset = 0) FLAT out TYPE gokuARRAY;\n"
27876 "\n"
27877 "layout(std140, binding = 0) uniform Goku {\n"
27878 " TYPE uni_gokuARRAY;\n"
27879 "};\n";
27880
27881 const testCase& test_case = m_test_cases[test_case_index];
27882 const GLchar* interface = "";
27883 const GLchar* flat = "";
27884
27885 if (test_case.m_stage == stage)
27886 {
27887 switch (stage)
27888 {
27889 case Utils::Shader::GEOMETRY:
27890 interface = vs_tes_gs;
27891 break;
27892 case Utils::Shader::TESS_EVAL:
27893 interface = vs_tes_gs;
27894 break;
27895 case Utils::Shader::VERTEX:
27896 interface = vs_tes_gs;
27897 break;
27898 default:
27899 TCU_FAIL("Invalid enum");
27900 }
27901 }
27902 else
27903 {
27904 switch (stage)
27905 {
27906 case Utils::Shader::FRAGMENT:
27907 interface = "";
27908 break;
27909 case Utils::Shader::GEOMETRY:
27910 case Utils::Shader::TESS_CTRL:
27911 case Utils::Shader::TESS_EVAL:
27912 case Utils::Shader::VERTEX:
27913 break;
27914 default:
27915 TCU_FAIL("Invalid enum");
27916 }
27917 }
27918
27919 out_interface = interface;
27920
27921 if (Utils::Type::Float != test_case.m_type.m_basic_type)
27922 {
27923 flat = "flat";
27924 }
27925
27926 /* Array size */
27927 if (0 == test_case.m_array_size)
27928 {
27929 Utils::replaceAllTokens("ARRAY", "", out_interface);
27930 }
27931 else
27932 {
27933 char buffer[16];
27934 sprintf(buffer, "[%d]", test_case.m_array_size);
27935
27936 Utils::replaceAllTokens("ARRAY", buffer, out_interface);
27937 }
27938
27939 Utils::replaceAllTokens("FLAT", flat, out_interface);
27940 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_interface);
27941 }
27942
27943 /** Get source code of shader
27944 *
27945 * @param test_case_index Index of test case
27946 * @param stage Shader stage
27947 *
27948 * @return Source
27949 **/
27950 std::string XFBExplicitLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27951 {
27952 std::string source;
27953 const testCase& test_case = m_test_cases[test_case_index];
27954
27955 switch (test_case.m_stage)
27956 {
27957 case Utils::Shader::VERTEX:
27958 switch (stage)
27959 {
27960 case Utils::Shader::FRAGMENT:
27961 case Utils::Shader::VERTEX:
27962 source = BufferTestBase::getShaderSource(test_case_index, stage);
27963 break;
27964 default:
27965 break;
27966 }
27967 break;
27968
27969 case Utils::Shader::TESS_EVAL:
27970 switch (stage)
27971 {
27972 case Utils::Shader::FRAGMENT:
27973 case Utils::Shader::TESS_CTRL:
27974 case Utils::Shader::TESS_EVAL:
27975 case Utils::Shader::VERTEX:
27976 source = BufferTestBase::getShaderSource(test_case_index, stage);
27977 break;
27978 default:
27979 break;
27980 }
27981 break;
27982
27983 case Utils::Shader::GEOMETRY:
27984 source = BufferTestBase::getShaderSource(test_case_index, stage);
27985 break;
27986
27987 default:
27988 TCU_FAIL("Invalid enum");
27989 }
27990
27991 /* */
27992 return source;
27993 }
27994
27995 /** Get name of test case
27996 *
27997 * @param test_case_index Index of test case
27998 *
27999 * @return Name of tested stage
28000 **/
28001 std::string XFBExplicitLocationTest::getTestCaseName(glw::GLuint test_case_index)
28002 {
28003 std::stringstream stream;
28004 const testCase& test_case = m_test_cases[test_case_index];
28005
28006 stream << "Type: " << test_case.m_type.GetGLSLTypeName()
28007 << ", stage: " << Utils::Shader::GetStageName(test_case.m_stage);
28008
28009 return stream.str();
28010 }
28011
28012 /** Returns number of test cases
28013 *
28014 * @return TEST_MAX
28015 **/
28016 glw::GLuint XFBExplicitLocationTest::getTestCaseNumber()
28017 {
28018 return static_cast<GLuint>(m_test_cases.size());
28019 }
28020
28021 /** Prepare all test cases
28022 *
28023 **/
28024 void XFBExplicitLocationTest::testInit()
28025 {
28026 const Functions& gl = m_context.getRenderContext().getFunctions();
28027 GLint max_xfb_int;
28028
28029 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_int);
28030 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
28031
28032 const GLuint n_types = getTypesNumber();
28033
28034 for (GLuint i = 0; i < n_types; ++i)
28035 {
28036 const Utils::Type& type = getType(i);
28037
28038 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
28039 {
28040 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
28041 (Utils::Shader::TESS_CTRL == stage))
28042 {
28043 continue;
28044 }
28045
28046 if (type.m_n_columns > 1)
28047 {
28048 testCase test_case = { (Utils::Shader::STAGES)stage, type, 0 };
28049
28050 m_test_cases.push_back(test_case);
28051 }
28052
28053 for (GLuint array_size = 3; array_size > 1; array_size--)
28054 {
28055 if (type.GetNumComponents() * array_size <= GLuint(max_xfb_int))
28056 {
28057 testCase test_case = { (Utils::Shader::STAGES)stage, type, array_size };
28058
28059 m_test_cases.push_back(test_case);
28060
28061 break;
28062 }
28063 }
28064 }
28065 }
28066 }
28067
28068 /** Constructor
28069 *
28070 * @param context Test context
28071 **/
28072 XFBExplicitLocationStructTest::XFBExplicitLocationStructTest(deqp::Context& context)
28073 : BufferTestBase(context, "xfb_struct_explicit_location", "Test verifies that explicit location on structs does not impact xfb output")
28074 {
28075 /* Nothing to be done here */
28076 }
28077
28078 /** Execute drawArrays for single vertex
28079 *
28080 * @param test_case_index
28081 *
28082 * @return true
28083 **/
28084 bool XFBExplicitLocationStructTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
28085 {
28086 const Functions& gl = m_context.getRenderContext().getFunctions();
28087 GLenum primitive_type = GL_PATCHES;
28088 const testCase& test_case = m_test_cases[test_case_index];
28089
28090 if (Utils::Shader::VERTEX == test_case.m_stage)
28091 {
28092 primitive_type = GL_POINTS;
28093 }
28094
28095 gl.disable(GL_RASTERIZER_DISCARD);
28096 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
28097
28098 gl.beginTransformFeedback(GL_POINTS);
28099 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
28100
28101 gl.drawArrays(primitive_type, 0 /* first */, 2 /* count */);
28102 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
28103
28104 gl.endTransformFeedback();
28105 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
28106
28107 return true;
28108 }
28109
28110 /** Get descriptors of buffers necessary for test
28111 *
28112 * @param test_case_index Index of test case
28113 * @param out_descriptors Descriptors of buffers used by test
28114 **/
28115 void XFBExplicitLocationStructTest::getBufferDescriptors(GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
28116 {
28117 const testCase& test_case = m_test_cases[test_case_index];
28118
28119 /* Test needs single uniform and xfb */
28120 out_descriptors.resize(2);
28121
28122 /* Get references */
28123 bufferDescriptor& uniform = out_descriptors[0];
28124 bufferDescriptor& xfb = out_descriptors[1];
28125
28126 /* Index */
28127 uniform.m_index = 0;
28128 xfb.m_index = 0;
28129
28130 /* Target */
28131 uniform.m_target = Utils::Buffer::Uniform;
28132 xfb.m_target = Utils::Buffer::Transform_feedback;
28133
28134 /* Data */
28135 const GLuint rand_start = Utils::s_rand;
28136 std::vector<GLubyte> uniform_data;
28137 GLuint max_aligment = 1;
28138
28139 for (const testType& type : test_case.m_types)
28140 {
28141 GLuint base_aligment = type.m_type.GetBaseAlignment(false);
28142 if (type.m_array_size > 0)
28143 {
28144 /**
28145 * Rule 4 of Section 7.6.2.2:
28146 *
28147 * If the member is an array of scalars or vectors, the base alignment and array stride
28148 * are set to match the base alignment of a single array element, according to rules (1),
28149 * (2), and (3), and rounded up to the base alignment of a vec4.
28150 */
28151 base_aligment = Utils::align(base_aligment, Utils::Type::vec4.GetBaseAlignment(false));
28152 }
28153
28154 max_aligment = std::max(base_aligment, max_aligment);
28155
28156 uniform_data.resize(Utils::align(uniform_data.size(), base_aligment), 0);
28157
28158 for (GLuint i = 0; i < std::max(type.m_array_size, 1u); i++)
28159 {
28160 const std::vector<GLubyte>& type_uniform_data = type.m_type.GenerateData();
28161 uniform_data.insert(uniform_data.end(), type_uniform_data.begin(), type_uniform_data.end());
28162
28163 if (type.m_array_size > 0)
28164 {
28165 uniform_data.resize(Utils::align(uniform_data.size(), base_aligment), 0);
28166 }
28167 }
28168 }
28169
28170 const GLuint struct_aligment = Utils::align(max_aligment, Utils::Type::vec4.GetBaseAlignment(false));
28171
28172 if (test_case.m_nested_struct)
28173 {
28174 uniform_data.resize(Utils::align(uniform_data.size(), struct_aligment), 0);
28175
28176 const GLuint old_size = uniform_data.size();
28177 uniform_data.resize(2 * old_size);
28178 std::copy_n(uniform_data.begin(), old_size, uniform_data.begin() + old_size);
28179 }
28180
28181 uniform_data.resize(Utils::align(uniform_data.size(), struct_aligment), 0);
28182
28183 Utils::s_rand = rand_start;
28184 std::vector<GLubyte> xfb_data;
28185
28186 GLuint max_type_size = 1;
28187 for (const testType& type : test_case.m_types)
28188 {
28189 const GLuint basic_type_size = Utils::Type::GetTypeSize(type.m_type.m_basic_type);
28190 max_type_size = std::max(max_type_size, basic_type_size);
28191
28192 /* Align per current type's aligment requirements */
28193 xfb_data.resize(Utils::align(xfb_data.size(), basic_type_size), 0);
28194
28195 for (GLuint i = 0; i < std::max(type.m_array_size, 1u); i++)
28196 {
28197 const std::vector<GLubyte>& type_xfb_data = type.m_type.GenerateDataPacked();
28198 xfb_data.insert(xfb_data.end(), type_xfb_data.begin(), type_xfb_data.end());
28199 }
28200 }
28201
28202 if (test_case.m_nested_struct)
28203 {
28204 /* Struct has aligment requirement equal to largest requirement of its members */
28205 xfb_data.resize(Utils::align(xfb_data.size(), max_type_size), 0);
28206
28207 const GLuint old_size = xfb_data.size();
28208 xfb_data.resize(2 * old_size);
28209 std::copy_n(xfb_data.begin(), old_size, xfb_data.begin() + old_size);
28210 }
28211
28212 xfb_data.resize(Utils::align(xfb_data.size(), max_type_size), 0);
28213
28214 const GLuint uni_type_size = static_cast<GLuint>(uniform_data.size());
28215 const GLuint xfb_type_size = static_cast<GLuint>(xfb_data.size());
28216
28217 /* Do not exceed the minimum value of MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS */
28218 DE_ASSERT(xfb_type_size <= 64 * sizeof(GLuint));
28219
28220 /*
28221 Note: If xfb varying output from vertex shader, the variable "goku" will only output once to transform feedback buffer,
28222 if xfb varying output from TES or GS, because the input primitive type in TES is defined as "layout(isolines, point_mode) in;",
28223 the primitive type is line which make the variable "goku" will output twice to transform feedback buffer, so for vertex shader
28224 only one valid data should be initialized in xfb.m_expected_data
28225 */
28226 const GLuint xfb_data_size = (test_case.m_stage == Utils::Shader::VERTEX) ? xfb_type_size : xfb_type_size * 2;
28227 /* Uniform data */
28228 uniform.m_initial_data.resize(uni_type_size);
28229 memcpy(&uniform.m_initial_data[0] + 0 * uni_type_size, &uniform_data[0], uni_type_size);
28230
28231 /* XFB data */
28232 xfb.m_initial_data.resize(xfb_data_size, 0);
28233 xfb.m_expected_data.resize(xfb_data_size);
28234
28235 if (test_case.m_stage == Utils::Shader::VERTEX)
28236 {
28237 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
28238 }
28239 else
28240 {
28241 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
28242 memcpy(&xfb.m_expected_data[0] + 1 * xfb_type_size, &xfb_data[0], xfb_type_size);
28243 }
28244 }
28245
28246 /** Get body of main function for given shader stage
28247 *
28248 * @param test_case_index Index of test case
28249 * @param stage Shader stage
28250 * @param out_assignments Set to empty
28251 * @param out_calculations Set to empty
28252 **/
28253 void XFBExplicitLocationStructTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_assignments,
28254 std::string& out_calculations)
28255 {
28256 const testCase& test_case = m_test_cases[test_case_index];
28257
28258 out_calculations = "";
28259
28260 static const GLchar* vs_tes_gs = " goku = uni_goku;\n";
28261 static const GLchar* vs_tes_gs_nested = " goku.inner_struct_a = uni_goku;\n"
28262 " goku.inner_struct_b = uni_goku;\n";
28263
28264 const GLchar* assignments = "";
28265
28266 if (test_case.m_stage == stage)
28267 {
28268 switch (stage)
28269 {
28270 case Utils::Shader::GEOMETRY:
28271 case Utils::Shader::TESS_EVAL:
28272 case Utils::Shader::VERTEX:
28273 if (test_case.m_nested_struct)
28274 {
28275 assignments = vs_tes_gs_nested;
28276 }
28277 else
28278 {
28279 assignments = vs_tes_gs;
28280 }
28281 break;
28282 default:
28283 TCU_FAIL("Invalid enum");
28284 }
28285 }
28286 else
28287 {
28288 switch (stage)
28289 {
28290 case Utils::Shader::FRAGMENT:
28291 assignments = "";
28292 break;
28293 case Utils::Shader::GEOMETRY:
28294 case Utils::Shader::TESS_CTRL:
28295 case Utils::Shader::TESS_EVAL:
28296 case Utils::Shader::VERTEX:
28297 break;
28298 default:
28299 TCU_FAIL("Invalid enum");
28300 }
28301 }
28302
28303 out_assignments = assignments;
28304 }
28305
28306 /** Get interface of shader
28307 *
28308 * @param test_case_index Index of test case
28309 * @param stage Shader stage
28310 * @param out_interface Set to ""
28311 **/
28312 void XFBExplicitLocationStructTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_interface)
28313 {
28314 static const GLchar* vs_tes_gs = "struct TestStruct {\n"
28315 "STRUCT_MEMBERS"
28316 "};\n"
28317 "layout (location = 0, xfb_offset = 0) flat out TestStruct goku;\n"
28318 "\n"
28319 "layout(std140, binding = 0) uniform Goku {\n"
28320 " TestStruct uni_goku;\n"
28321 "};\n";
28322
28323 static const GLchar* vs_tes_gs_nested = "struct TestStruct {\n"
28324 "STRUCT_MEMBERS"
28325 "};\n"
28326 "struct OuterStruct {\n"
28327 " TestStruct inner_struct_a;\n"
28328 " TestStruct inner_struct_b;\n"
28329 "};\n"
28330 "layout (location = 0, xfb_offset = 0) flat out OuterStruct goku;\n"
28331 "\n"
28332 "layout(std140, binding = 0) uniform Goku {\n"
28333 " TestStruct uni_goku;\n"
28334 "};\n";
28335
28336 const testCase& test_case = m_test_cases[test_case_index];
28337 const GLchar* interface = "";
28338
28339 if (test_case.m_stage == stage)
28340 {
28341 switch (stage)
28342 {
28343 case Utils::Shader::GEOMETRY:
28344 case Utils::Shader::TESS_EVAL:
28345 case Utils::Shader::VERTEX:
28346 if (test_case.m_nested_struct)
28347 {
28348 interface = vs_tes_gs_nested;
28349 }
28350 else
28351 {
28352 interface = vs_tes_gs;
28353 }
28354 break;
28355 default:
28356 TCU_FAIL("Invalid enum");
28357 }
28358 }
28359 else
28360 {
28361 switch (stage)
28362 {
28363 case Utils::Shader::FRAGMENT:
28364 interface = "";
28365 break;
28366 case Utils::Shader::GEOMETRY:
28367 case Utils::Shader::TESS_CTRL:
28368 case Utils::Shader::TESS_EVAL:
28369 case Utils::Shader::VERTEX:
28370 break;
28371 default:
28372 TCU_FAIL("Invalid enum");
28373 }
28374 }
28375
28376 out_interface = interface;
28377
28378 std::stringstream stream;
28379
28380 char member_name = 'a';
28381 for (const testType& type : test_case.m_types)
28382 {
28383 stream << " " << type.m_type.GetGLSLTypeName() << " " << member_name++;
28384 if (type.m_array_size > 0)
28385 {
28386 stream << "[" << type.m_array_size << "]";
28387 }
28388 stream << ";\n";
28389 }
28390
28391 Utils::replaceAllTokens("STRUCT_MEMBERS", stream.str().c_str(), out_interface);
28392 }
28393
28394 /** Get source code of shader
28395 *
28396 * @param test_case_index Index of test case
28397 * @param stage Shader stage
28398 *
28399 * @return Source
28400 **/
28401 std::string XFBExplicitLocationStructTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
28402 {
28403 std::string source;
28404 const testCase& test_case = m_test_cases[test_case_index];
28405
28406 switch (test_case.m_stage)
28407 {
28408 case Utils::Shader::VERTEX:
28409 switch (stage)
28410 {
28411 case Utils::Shader::FRAGMENT:
28412 case Utils::Shader::VERTEX:
28413 source = BufferTestBase::getShaderSource(test_case_index, stage);
28414 break;
28415 default:
28416 break;
28417 }
28418 break;
28419
28420 case Utils::Shader::TESS_EVAL:
28421 switch (stage)
28422 {
28423 case Utils::Shader::FRAGMENT:
28424 case Utils::Shader::TESS_CTRL:
28425 case Utils::Shader::TESS_EVAL:
28426 case Utils::Shader::VERTEX:
28427 source = BufferTestBase::getShaderSource(test_case_index, stage);
28428 break;
28429 default:
28430 break;
28431 }
28432 break;
28433
28434 case Utils::Shader::GEOMETRY:
28435 source = BufferTestBase::getShaderSource(test_case_index, stage);
28436 break;
28437
28438 default:
28439 TCU_FAIL("Invalid enum");
28440 }
28441
28442 /* */
28443 return source;
28444 }
28445
28446 /** Get name of test case
28447 *
28448 * @param test_case_index Index of test case
28449 *
28450 * @return Name of tested stage
28451 **/
28452 std::string XFBExplicitLocationStructTest::getTestCaseName(glw::GLuint test_case_index)
28453 {
28454 std::stringstream stream;
28455 const testCase& test_case = m_test_cases[test_case_index];
28456
28457 stream << "Struct: { ";
28458
28459 for (const testType& type : test_case.m_types)
28460 {
28461 stream << type.m_type.GetGLSLTypeName() << "@" << type.m_array_size << ", ";
28462 }
28463
28464 stream << "}, stage: " << Utils::Shader::GetStageName(test_case.m_stage);
28465
28466 return stream.str();
28467 }
28468
28469 /** Returns number of test cases
28470 *
28471 * @return TEST_MAX
28472 **/
28473 glw::GLuint XFBExplicitLocationStructTest::getTestCaseNumber()
28474 {
28475 return static_cast<GLuint>(m_test_cases.size());
28476 }
28477
28478 /** Prepare all test cases
28479 *
28480 **/
28481 void XFBExplicitLocationStructTest::testInit()
28482 {
28483 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
28484 {
28485 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
28486 (Utils::Shader::TESS_CTRL == stage))
28487 {
28488 continue;
28489 }
28490
28491 const GLuint n_types = getTypesNumber();
28492
28493 for (GLuint i = 0; i < n_types; ++i)
28494 {
28495 const Utils::Type& type = getType(i);
28496
28497 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_float, 0}, {type, 0} }, false });
28498 }
28499
28500 for (bool is_nested_struct : {false, true})
28501 {
28502 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_double, 0}, {Utils::Type::dvec2, 0}, {Utils::Type::dmat3, 0} }, is_nested_struct });
28503 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_double, 0}, {Utils::Type::vec3, 0} }, is_nested_struct });
28504 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::dvec3, 0}, {Utils::Type::mat4x3, 0} }, is_nested_struct });
28505 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_float, 0}, {Utils::Type::dvec3, 0}, {Utils::Type::_float, 0}, {Utils::Type::_double, 0} }, is_nested_struct });
28506 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::vec2, 0}, {Utils::Type::dvec3, 0}, {Utils::Type::_float, 0}, {Utils::Type::_double, 0} }, is_nested_struct });
28507 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_double, 0}, {Utils::Type::_float, 0}, {Utils::Type::dvec2, 0}, {Utils::Type::vec3, 0} }, is_nested_struct });
28508 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::dmat3x4, 0}, {Utils::Type::_double, 0}, {Utils::Type::_float, 0}, {Utils::Type::dvec2, 0} }, is_nested_struct });
28509
28510 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_float, 3}, {Utils::Type::dvec3, 0}, {Utils::Type::_double, 2} }, is_nested_struct });
28511 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_int, 1}, {Utils::Type::_double, 1}, {Utils::Type::_float, 1}, {Utils::Type::dmat2x4, 1} }, is_nested_struct });
28512 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::_int, 5}, {Utils::Type::dvec3, 2}, {Utils::Type::uvec3, 0}, {Utils::Type::_double, 1} }, is_nested_struct });
28513 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::mat2x3, 3}, {Utils::Type::uvec4, 1}, {Utils::Type::dvec4, 0} }, is_nested_struct });
28514 }
28515
28516 m_test_cases.push_back(testCase{(Utils::Shader::STAGES) stage, { {Utils::Type::dmat2x3, 2}, {Utils::Type::mat2x3, 2}, {Utils::Type::dvec2, 0} }, false });
28517 }
28518 }
28519 } /* EnhancedLayouts namespace */
28520
28521 /** Constructor.
28522 *
28523 * @param context Rendering context.
28524 **/
EnhancedLayoutsTests(deqp::Context & context)28525 EnhancedLayoutsTests::EnhancedLayoutsTests(deqp::Context& context)
28526 : TestCaseGroup(context, "enhanced_layouts", "Verifies \"enhanced layouts\" functionality")
28527 {
28528 /* Left blank on purpose */
28529 }
28530
28531 /** Initializes a texture_storage_multisample test group.
28532 *
28533 **/
init(void)28534 void EnhancedLayoutsTests::init(void)
28535 {
28536 addChild(new EnhancedLayouts::APIConstantValuesTest(m_context));
28537 addChild(new EnhancedLayouts::APIErrorsTest(m_context));
28538 addChild(new EnhancedLayouts::GLSLContantValuesTest(m_context));
28539 addChild(new EnhancedLayouts::GLSLContantImmutablityTest(m_context));
28540 addChild(new EnhancedLayouts::GLSLConstantIntegralExpressionTest(m_context));
28541 addChild(new EnhancedLayouts::UniformBlockLayoutQualifierConflictTest(m_context));
28542 addChild(new EnhancedLayouts::SSBMemberInvalidOffsetAlignmentTest(m_context));
28543 addChild(new EnhancedLayouts::SSBMemberOverlappingOffsetsTest(m_context));
28544 addChild(new EnhancedLayouts::VaryingInvalidValueComponentTest(m_context));
28545 addChild(new EnhancedLayouts::VaryingExceedingComponentsTest(m_context));
28546 addChild(new EnhancedLayouts::VaryingComponentOfInvalidTypeTest(m_context));
28547 addChild(new EnhancedLayouts::OutputComponentAliasingTest(m_context));
28548 addChild(new EnhancedLayouts::VertexAttribLocationAPITest(m_context));
28549 addChild(new EnhancedLayouts::XFBInputTest(m_context));
28550 addChild(new EnhancedLayouts::XFBAllStagesTest(m_context));
28551 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputVariableTest(m_context));
28552 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputComponentTest(m_context));
28553 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputBlockMemberTest(m_context));
28554 addChild(new EnhancedLayouts::XFBStrideTest(m_context));
28555
28556 addChild(new EnhancedLayouts::UniformBlockMemberOffsetAndAlignTest(m_context));
28557 addChild(new EnhancedLayouts::UniformBlockMemberInvalidOffsetAlignmentTest(m_context));
28558 addChild(new EnhancedLayouts::UniformBlockMemberOverlappingOffsetsTest(m_context));
28559 addChild(new EnhancedLayouts::UniformBlockMemberAlignNonPowerOf2Test(m_context));
28560 addChild(new EnhancedLayouts::SSBLayoutQualifierConflictTest(m_context));
28561 addChild(new EnhancedLayouts::SSBMemberAlignNonPowerOf2Test(m_context));
28562 addChild(new EnhancedLayouts::SSBAlignmentTest(m_context));
28563 addChild(new EnhancedLayouts::VaryingStructureMemberLocationTest(m_context));
28564 addChild(new EnhancedLayouts::VaryingBlockAutomaticMemberLocationsTest(m_context));
28565 addChild(new EnhancedLayouts::VaryingComponentWithoutLocationTest(m_context));
28566 addChild(new EnhancedLayouts::InputComponentAliasingTest(m_context));
28567 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedTypesTest(m_context));
28568 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedInterpolationTest(m_context));
28569 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(m_context));
28570 addChild(new EnhancedLayouts::XFBStrideOfEmptyListTest(m_context));
28571 addChild(new EnhancedLayouts::XFBStrideOfEmptyListAndAPITest(m_context));
28572 addChild(new EnhancedLayouts::XFBTooSmallStrideTest(m_context));
28573 addChild(new EnhancedLayouts::XFBBlockMemberStrideTest(m_context));
28574 addChild(new EnhancedLayouts::XFBDuplicatedStrideTest(m_context));
28575 addChild(new EnhancedLayouts::XFBGetProgramResourceAPITest(m_context));
28576 addChild(new EnhancedLayouts::XFBMultipleVertexStreamsTest(m_context));
28577 addChild(new EnhancedLayouts::XFBExceedBufferLimitTest(m_context));
28578 addChild(new EnhancedLayouts::XFBExceedOffsetLimitTest(m_context));
28579 addChild(new EnhancedLayouts::XFBBlockMemberBufferTest(m_context));
28580 addChild(new EnhancedLayouts::XFBOutputOverlappingTest(m_context));
28581 addChild(new EnhancedLayouts::XFBInvalidOffsetAlignmentTest(m_context));
28582 addChild(new EnhancedLayouts::XFBCaptureStructTest(m_context));
28583 addChild(new EnhancedLayouts::XFBCaptureUnsizedArrayTest(m_context));
28584 addChild(new EnhancedLayouts::UniformBlockAlignmentTest(m_context));
28585 addChild(new EnhancedLayouts::SSBMemberOffsetAndAlignTest(m_context));
28586 addChild(new EnhancedLayouts::VertexAttribLocationsTest(m_context));
28587 addChild(new EnhancedLayouts::VaryingLocationsTest(m_context));
28588 addChild(new EnhancedLayouts::VaryingArrayLocationsTest(m_context));
28589 addChild(new EnhancedLayouts::VaryingStructureLocationsTest(m_context));
28590 addChild(new EnhancedLayouts::VaryingBlockLocationsTest(m_context));
28591 addChild(new EnhancedLayouts::VaryingBlockMemberLocationsTest(m_context));
28592 addChild(new EnhancedLayouts::XFBVariableStrideTest(m_context));
28593 addChild(new EnhancedLayouts::XFBBlockStrideTest(m_context));
28594 addChild(new EnhancedLayouts::XFBOverrideQualifiersWithAPITest(m_context));
28595 addChild(new EnhancedLayouts::XFBVertexStreamsTest(m_context));
28596 addChild(new EnhancedLayouts::XFBGlobalBufferTest(m_context));
28597 addChild(new EnhancedLayouts::XFBExplicitLocationTest(m_context));
28598 addChild(new EnhancedLayouts::XFBExplicitLocationStructTest(m_context));
28599 addChild(new EnhancedLayouts::FragmentDataLocationAPITest(m_context));
28600 addChild(new EnhancedLayouts::VaryingLocationLimitTest(m_context));
28601 addChild(new EnhancedLayouts::VaryingComponentsTest(m_context));
28602 addChild(new EnhancedLayouts::VaryingArrayComponentsTest(m_context));
28603 }
28604
28605 } /* gl4cts namespace */
28606