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
182 std::vector<GLubyte> data;
183 data.resize(alignment * m_n_columns);
184
185 for (GLuint column = 0; column < m_n_columns; ++column)
186 {
187 GLvoid* ptr = (GLvoid*)&data[column * alignment];
188
189 switch (m_basic_type)
190 {
191 case Double:
192 {
193 GLdouble* d_ptr = (GLdouble*)ptr;
194
195 for (GLuint i = 0; i < m_n_rows; ++i)
196 {
197 d_ptr[i] = GetRandDouble();
198 }
199 }
200 break;
201 case Float:
202 {
203 GLfloat* f_ptr = (GLfloat*)ptr;
204
205 for (GLuint i = 0; i < m_n_rows; ++i)
206 {
207 f_ptr[i] = GetRandFloat();
208 }
209 }
210 break;
211 case Int:
212 {
213 GLint* i_ptr = (GLint*)ptr;
214
215 for (GLuint i = 0; i < m_n_rows; ++i)
216 {
217 i_ptr[i] = GetRandInt();
218 }
219 }
220 break;
221 case Uint:
222 {
223 GLuint* ui_ptr = (GLuint*)ptr;
224
225 for (GLuint i = 0; i < m_n_rows; ++i)
226 {
227 ui_ptr[i] = GetRandUint();
228 }
229 }
230 break;
231 }
232 }
233
234 return data;
235 }
236
237 /** Generate data for type. This routine packs data tightly.
238 *
239 * @return Vector of bytes filled with data
240 **/
GenerateDataPacked() const241 std::vector<GLubyte> Type::GenerateDataPacked() const
242 {
243 const GLuint basic_size = GetTypeSize(m_basic_type);
244 const GLuint n_elements = m_n_columns * m_n_rows;
245 const GLuint size = basic_size * n_elements;
246
247 std::vector<GLubyte> data;
248 data.resize(size);
249
250 GLvoid* ptr = (GLvoid*)&data[0];
251
252 switch (m_basic_type)
253 {
254 case Double:
255 {
256 GLdouble* d_ptr = (GLdouble*)ptr;
257
258 for (GLuint i = 0; i < n_elements; ++i)
259 {
260 d_ptr[i] = GetRandDouble();
261 }
262 }
263 break;
264 case Float:
265 {
266 GLfloat* f_ptr = (GLfloat*)ptr;
267
268 for (GLuint i = 0; i < n_elements; ++i)
269 {
270 f_ptr[i] = GetRandFloat();
271 }
272 }
273 break;
274 case Int:
275 {
276 GLint* i_ptr = (GLint*)ptr;
277
278 for (GLuint i = 0; i < n_elements; ++i)
279 {
280 i_ptr[i] = GetRandInt();
281 }
282 }
283 break;
284 case Uint:
285 {
286 GLuint* ui_ptr = (GLuint*)ptr;
287
288 for (GLuint i = 0; i < n_elements; ++i)
289 {
290 ui_ptr[i] = GetRandUint();
291 }
292 }
293 break;
294 }
295
296 return data;
297 }
298
299 /** Calculate "actual alignment". It work under assumption that align value is valid
300 *
301 * @param align Requested alignment, eg with "align" qualifier
302 * @param is_array Selects if an array of type or single instance should be considered
303 *
304 * @return Calculated value
305 **/
GetActualAlignment(GLuint align,bool is_array) const306 GLuint Type::GetActualAlignment(GLuint align, bool is_array) const
307 {
308 const GLuint base_alignment = GetBaseAlignment(is_array);
309
310 return std::max(align, base_alignment);
311 }
312
313 /** Align given ofset with specified alignment
314 *
315 * @param offset Offset
316 * @param alignment Alignment
317 *
318 * @return Calculated value
319 **/
align(GLuint offset,GLuint alignment)320 GLuint align(GLuint offset, GLuint alignment)
321 {
322 const GLuint rest = offset % alignment;
323
324 if (0 != rest)
325 {
326 GLuint missing = alignment - rest;
327 offset += missing;
328 }
329
330 return offset;
331 }
332
333 /** Calculate "actual offset"
334 *
335 * @param start_offset Requested offset
336 * @param actual_alignment Actual alignemnt
337 *
338 * @return Calculated value
339 **/
GetActualOffset(GLuint start_offset,GLuint actual_alignment)340 GLuint Type::GetActualOffset(GLuint start_offset, GLuint actual_alignment)
341 {
342 GLuint offset = align(start_offset, actual_alignment);
343
344 return offset;
345 }
346
347 /** Calculate "base alignment" for given type
348 *
349 * @param is_array Select if array or single instance should be considered
350 *
351 * @return Calculated value
352 **/
GetBaseAlignment(bool is_array) const353 GLuint Type::GetBaseAlignment(bool is_array) const
354 {
355 GLuint elements = 1;
356
357 switch (m_n_rows)
358 {
359 case 2:
360 elements = 2;
361 break;
362 case 3:
363 case 4:
364 elements = 4;
365 break;
366 default:
367 break;
368 }
369
370 GLuint N = GetTypeSize(m_basic_type);
371 GLuint alignment = N * elements;
372
373 if ((true == is_array) || (1 != m_n_columns))
374 {
375 alignment = align(alignment, 16 /* vec4 alignment */);
376 }
377
378 return alignment;
379 }
380
381 /** Returns string representing GLSL constructor of type with arguments provided in data
382 *
383 * @param data Array of values that will be used as construcotr arguments.
384 * It is interpreted as tightly packed array of type matching this type.
385 *
386 * @return String in form "Type(args)"
387 **/
GetGLSLConstructor(const GLvoid * data) const388 std::string Type::GetGLSLConstructor(const GLvoid* data) const
389 {
390 const GLchar* type = GetGLSLTypeName();
391
392 std::stringstream stream;
393
394 stream << type << "(";
395
396 /* Scalar or vector */
397 if (1 == m_n_columns)
398 {
399 for (GLuint row = 0; row < m_n_rows; ++row)
400 {
401 switch (m_basic_type)
402 {
403 case Double:
404 stream << ((GLdouble*)data)[row];
405 break;
406 case Float:
407 stream << ((GLfloat*)data)[row];
408 break;
409 case Int:
410 stream << ((GLint*)data)[row];
411 break;
412 case Uint:
413 stream << ((GLuint*)data)[row];
414 break;
415 }
416
417 if (row + 1 != m_n_rows)
418 {
419 stream << ", ";
420 }
421 }
422 }
423 else /* Matrix: mat(vec(), vec() .. ) */
424 {
425 const GLuint basic_size = GetTypeSize(m_basic_type);
426 // 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)
427 const GLuint column_stride = m_n_rows * basic_size;
428 const Type column_type = GetType(m_basic_type, 1, m_n_rows);
429
430 for (GLuint column = 0; column < m_n_columns; ++column)
431 {
432 const GLuint column_offset = column * column_stride;
433 const GLvoid* column_data = (GLubyte*)data + column_offset;
434
435 stream << column_type.GetGLSLConstructor(column_data);
436
437 if (column + 1 != m_n_columns)
438 {
439 stream << ", ";
440 }
441 }
442 }
443
444 stream << ")";
445
446 return stream.str();
447 }
448
449 /** Get glsl name of the type
450 *
451 * @return Name of glsl type
452 **/
GetGLSLTypeName() const453 const glw::GLchar* Type::GetGLSLTypeName() const
454 {
455 static const GLchar* float_lut[4][4] = {
456 { "float", "vec2", "vec3", "vec4" },
457 { 0, "mat2", "mat2x3", "mat2x4" },
458 { 0, "mat3x2", "mat3", "mat3x4" },
459 { 0, "mat4x2", "mat4x3", "mat4" },
460 };
461
462 static const GLchar* double_lut[4][4] = {
463 { "double", "dvec2", "dvec3", "dvec4" },
464 { 0, "dmat2", "dmat2x3", "dmat2x4" },
465 { 0, "dmat3x2", "dmat3", "dmat3x4" },
466 { 0, "dmat4x2", "dmat4x3", "dmat4" },
467 };
468
469 static const GLchar* int_lut[4] = { "int", "ivec2", "ivec3", "ivec4" };
470
471 static const GLchar* uint_lut[4] = { "uint", "uvec2", "uvec3", "uvec4" };
472
473 const GLchar* result = 0;
474
475 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
476 {
477 return 0;
478 }
479
480 switch (m_basic_type)
481 {
482 case Float:
483 result = float_lut[m_n_columns - 1][m_n_rows - 1];
484 break;
485 case Double:
486 result = double_lut[m_n_columns - 1][m_n_rows - 1];
487 break;
488 case Int:
489 result = int_lut[m_n_rows - 1];
490 break;
491 case Uint:
492 result = uint_lut[m_n_rows - 1];
493 break;
494 default:
495 TCU_FAIL("Invalid enum");
496 }
497
498 return result;
499 }
500
501 /** Get number of locations required for the type
502 *
503 * @return Number of columns times:
504 * - 2 when type is double with 3 or 4 rows,
505 * - 1 otherwise or if it's a vertex shader input.
506 **/
GetLocations(bool is_vs_input) const507 GLuint Type::GetLocations(bool is_vs_input) const
508 {
509 GLuint n_loc_per_column;
510
511 /* 1 or 2 doubles any for rest */
512 if ((2 >= m_n_rows) || (Double != m_basic_type) || is_vs_input)
513 {
514 n_loc_per_column = 1;
515 }
516 else
517 {
518 /* 3 and 4 doubles */
519 n_loc_per_column = 2;
520 }
521
522 return n_loc_per_column * m_n_columns;
523 }
524
525 /** Get size of the type in bytes.
526 * Note that this routine doesn't consider arrays and assumes
527 * column_major matrices.
528 *
529 * @return Formula:
530 * - If std140 packaging and matrix; number of columns * base alignment
531 * - Otherwise; number of elements * sizeof(base_type)
532 **/
GetSize(const bool is_std140) const533 GLuint Type::GetSize(const bool is_std140) const
534 {
535 const GLuint basic_type_size = GetTypeSize(m_basic_type);
536 const GLuint n_elements = m_n_columns * m_n_rows;
537
538 if (is_std140 && m_n_columns > 1)
539 {
540 return m_n_columns * GetBaseAlignment(false);
541 }
542
543 return basic_type_size * n_elements;
544 }
545
546 /** Get GLenum representing the type
547 *
548 * @return GLenum
549 **/
GetTypeGLenum() const550 GLenum Type::GetTypeGLenum() const
551 {
552 static const GLenum float_lut[4][4] = {
553 { GL_FLOAT, GL_FLOAT_VEC2, GL_FLOAT_VEC3, GL_FLOAT_VEC4 },
554 { 0, GL_FLOAT_MAT2, GL_FLOAT_MAT2x3, GL_FLOAT_MAT2x4 },
555 { 0, GL_FLOAT_MAT3x2, GL_FLOAT_MAT3, GL_FLOAT_MAT3x4 },
556 { 0, GL_FLOAT_MAT4x2, GL_FLOAT_MAT4x3, GL_FLOAT_MAT4 },
557 };
558
559 static const GLenum double_lut[4][4] = {
560 { GL_DOUBLE, GL_DOUBLE_VEC2, GL_DOUBLE_VEC3, GL_DOUBLE_VEC4 },
561 { 0, GL_DOUBLE_MAT2, GL_DOUBLE_MAT2x3, GL_DOUBLE_MAT2x4 },
562 { 0, GL_DOUBLE_MAT3x2, GL_DOUBLE_MAT3, GL_DOUBLE_MAT3x4 },
563 { 0, GL_DOUBLE_MAT4x2, GL_DOUBLE_MAT4x3, GL_DOUBLE_MAT4 },
564 };
565
566 static const GLenum int_lut[4] = { GL_INT, GL_INT_VEC2, GL_INT_VEC3, GL_INT_VEC4 };
567
568 static const GLenum uint_lut[4] = { GL_UNSIGNED_INT, GL_UNSIGNED_INT_VEC2, GL_UNSIGNED_INT_VEC3,
569 GL_UNSIGNED_INT_VEC4 };
570
571 GLenum result = 0;
572
573 if ((1 > m_n_columns) || (1 > m_n_rows) || (4 < m_n_columns) || (4 < m_n_rows))
574 {
575 return 0;
576 }
577
578 switch (m_basic_type)
579 {
580 case Float:
581 result = float_lut[m_n_columns - 1][m_n_rows - 1];
582 break;
583 case Double:
584 result = double_lut[m_n_columns - 1][m_n_rows - 1];
585 break;
586 case Int:
587 result = int_lut[m_n_rows - 1];
588 break;
589 case Uint:
590 result = uint_lut[m_n_rows - 1];
591 break;
592 default:
593 TCU_FAIL("Invalid enum");
594 }
595
596 return result;
597 }
598
599 /** Calculate the number of components consumed by a type
600 * according to 11.1.2.1 Output Variables
601 *
602 * @return Calculated number of components for the type
603 **/
GetNumComponents() const604 GLuint Type::GetNumComponents() const
605 {
606 // Rule 3 of Section 7.6.2.2
607 // If the member is a three-component vector with components consuming N
608 // basic machine units, the base alignment is 4N.
609 GLuint num_components = (m_n_rows == 3 ? 4 : m_n_rows) * m_n_columns;
610
611 if (m_basic_type == Double)
612 {
613 num_components *= 2;
614 }
615
616 return num_components;
617 }
618
619 /** Calculate the valid values to use with the component qualifier
620 *
621 * @return Vector with the valid values, in growing order, or empty if
622 * the component qualifier is not allowed
623 **/
GetValidComponents() const624 std::vector<GLuint> Type::GetValidComponents() const
625 {
626 const GLuint component_size = Utils::Type::Double == m_basic_type ? 2 : 1;
627 const GLuint n_components_per_location = Utils::Type::Double == m_basic_type ? 2 : 4;
628 const GLuint n_req_components = m_n_rows;
629 const GLint max_valid_component = (GLint)n_components_per_location - (GLint)n_req_components;
630 std::vector<GLuint> data;
631
632 /* The component qualifier cannot be used for matrices */
633 if (1 != m_n_columns)
634 {
635 return data;
636 }
637
638 /* The component qualifier cannot be used for dvec3/dvec4 */
639 if (max_valid_component < 0)
640 {
641 return data;
642 }
643
644 for (GLuint i = 0; i <= (GLuint)max_valid_component; ++i)
645 {
646 data.push_back(i * component_size);
647 }
648
649 return data;
650 }
651
652 /** Calculate stride for the type according to std140 rules
653 *
654 * @param alignment Alignment of type
655 * @param n_columns Number of columns
656 * @param n_array_elements Number of elements in array
657 *
658 * @return Calculated value
659 **/
CalculateStd140Stride(GLuint alignment,GLuint n_columns,GLuint n_array_elements)660 GLuint Type::CalculateStd140Stride(GLuint alignment, GLuint n_columns, GLuint n_array_elements)
661 {
662 GLuint stride = alignment * n_columns;
663 if (0 != n_array_elements)
664 {
665 stride *= n_array_elements;
666 }
667
668 return stride;
669 }
670
671 /** Check if glsl support matrices for specific basic type
672 *
673 * @param type Basic type
674 *
675 * @return true if matrices of <type> are supported, false otherwise
676 **/
DoesTypeSupportMatrix(TYPES type)677 bool Type::DoesTypeSupportMatrix(TYPES type)
678 {
679 bool result = false;
680
681 switch (type)
682 {
683 case Float:
684 case Double:
685 result = true;
686 break;
687 case Int:
688 case Uint:
689 result = false;
690 break;
691 default:
692 TCU_FAIL("Invalid enum");
693 }
694
695 return result;
696 }
697
698 /** Creates instance of Type
699 *
700 * @param basic_type Select basic type of instance
701 * @param n_columns Number of columns
702 * @param n_rows Number of rows
703 *
704 * @return Type instance
705 **/
GetType(TYPES basic_type,glw::GLuint n_columns,glw::GLuint n_rows)706 Type Type::GetType(TYPES basic_type, glw::GLuint n_columns, glw::GLuint n_rows)
707 {
708 Type type = { basic_type, n_columns, n_rows };
709
710 return type;
711 }
712
713 /** Get Size of given type in bytes
714 *
715 * @param type
716 *
717 * @return Size of type
718 **/
GetTypeSize(TYPES type)719 GLuint Type::GetTypeSize(TYPES type)
720 {
721 GLuint result = 0;
722
723 switch (type)
724 {
725 case Float:
726 result = sizeof(GLfloat);
727 break;
728 case Double:
729 result = sizeof(GLdouble);
730 break;
731 case Int:
732 result = sizeof(GLint);
733 break;
734 case Uint:
735 result = sizeof(GLuint);
736 break;
737 default:
738 TCU_FAIL("Invalid enum");
739 }
740
741 return result;
742 }
743
744 /** Get GLenum representing given type
745 *
746 * @param type
747 *
748 * @return GLenum value
749 **/
GetTypeGLenum(TYPES type)750 GLenum Type::GetTypeGLenum(TYPES type)
751 {
752 GLenum result = 0;
753
754 switch (type)
755 {
756 case Float:
757 result = GL_FLOAT;
758 break;
759 case Double:
760 result = GL_DOUBLE;
761 break;
762 case Int:
763 result = GL_INT;
764 break;
765 case Uint:
766 result = GL_UNSIGNED_INT;
767 break;
768 default:
769 TCU_FAIL("Invalid enum");
770 }
771
772 return result;
773 }
774
775 /** Check if two types can share the same location, based on the underlying numerical type and bit width
776 *
777 * @param first First type to compare
778 * @param second Second type to compare
779 *
780 * @return true if the types can share the same location
781 **/
CanTypesShareLocation(TYPES first,TYPES second)782 bool Type::CanTypesShareLocation(TYPES first, TYPES second)
783 {
784 if (first == second)
785 {
786 return true;
787 }
788
789 if (Float == first || Float == second || Double == first || Double == second)
790 {
791 return false;
792 }
793
794 return true;
795 }
796
797 /** Get proper glUniformNdv routine for vectors with specified number of rows
798 *
799 * @param gl GL functions
800 * @param n_rows Number of rows
801 *
802 * @return Function address
803 **/
getUniformNdv(const glw::Functions & gl,glw::GLuint n_rows)804 uniformNdv getUniformNdv(const glw::Functions& gl, glw::GLuint n_rows)
805 {
806 uniformNdv result = 0;
807
808 switch (n_rows)
809 {
810 case 1:
811 result = gl.uniform1dv;
812 break;
813 case 2:
814 result = gl.uniform2dv;
815 break;
816 case 3:
817 result = gl.uniform3dv;
818 break;
819 case 4:
820 result = gl.uniform4dv;
821 break;
822 default:
823 TCU_FAIL("Invalid number of rows");
824 }
825
826 return result;
827 }
828
829 /** Get proper glUniformNfv routine for vectors with specified number of rows
830 *
831 * @param gl GL functions
832 * @param n_rows Number of rows
833 *
834 * @return Function address
835 **/
getUniformNfv(const glw::Functions & gl,glw::GLuint n_rows)836 uniformNfv getUniformNfv(const glw::Functions& gl, glw::GLuint n_rows)
837 {
838 uniformNfv result = 0;
839
840 switch (n_rows)
841 {
842 case 1:
843 result = gl.uniform1fv;
844 break;
845 case 2:
846 result = gl.uniform2fv;
847 break;
848 case 3:
849 result = gl.uniform3fv;
850 break;
851 case 4:
852 result = gl.uniform4fv;
853 break;
854 default:
855 TCU_FAIL("Invalid number of rows");
856 }
857
858 return result;
859 }
860
861 /** Get proper glUniformNiv routine for vectors with specified number of rows
862 *
863 * @param gl GL functions
864 * @param n_rows Number of rows
865 *
866 * @return Function address
867 **/
getUniformNiv(const glw::Functions & gl,glw::GLuint n_rows)868 uniformNiv getUniformNiv(const glw::Functions& gl, glw::GLuint n_rows)
869 {
870 uniformNiv result = 0;
871
872 switch (n_rows)
873 {
874 case 1:
875 result = gl.uniform1iv;
876 break;
877 case 2:
878 result = gl.uniform2iv;
879 break;
880 case 3:
881 result = gl.uniform3iv;
882 break;
883 case 4:
884 result = gl.uniform4iv;
885 break;
886 default:
887 TCU_FAIL("Invalid number of rows");
888 }
889
890 return result;
891 }
892
893 /** Get proper glUniformNuiv routine for vectors with specified number of rows
894 *
895 * @param gl GL functions
896 * @param n_rows Number of rows
897 *
898 * @return Function address
899 **/
getUniformNuiv(const glw::Functions & gl,glw::GLuint n_rows)900 uniformNuiv getUniformNuiv(const glw::Functions& gl, glw::GLuint n_rows)
901 {
902 uniformNuiv result = 0;
903
904 switch (n_rows)
905 {
906 case 1:
907 result = gl.uniform1uiv;
908 break;
909 case 2:
910 result = gl.uniform2uiv;
911 break;
912 case 3:
913 result = gl.uniform3uiv;
914 break;
915 case 4:
916 result = gl.uniform4uiv;
917 break;
918 default:
919 TCU_FAIL("Invalid number of rows");
920 }
921
922 return result;
923 }
924
925 /** Get proper glUniformMatrixNdv routine for matrix with specified number of columns and rows
926 *
927 * @param gl GL functions
928 * @param n_rows Number of rows
929 *
930 * @return Function address
931 **/
getUniformMatrixNdv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)932 uniformMatrixNdv getUniformMatrixNdv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
933 {
934 uniformMatrixNdv result = 0;
935
936 switch (n_columns)
937 {
938 case 2:
939 switch (n_rows)
940 {
941 case 2:
942 result = gl.uniformMatrix2dv;
943 break;
944 case 3:
945 result = gl.uniformMatrix2x3dv;
946 break;
947 case 4:
948 result = gl.uniformMatrix2x4dv;
949 break;
950 default:
951 TCU_FAIL("Invalid number of rows");
952 }
953 break;
954 case 3:
955 switch (n_rows)
956 {
957 case 2:
958 result = gl.uniformMatrix3x2dv;
959 break;
960 case 3:
961 result = gl.uniformMatrix3dv;
962 break;
963 case 4:
964 result = gl.uniformMatrix3x4dv;
965 break;
966 default:
967 TCU_FAIL("Invalid number of rows");
968 }
969 break;
970 case 4:
971 switch (n_rows)
972 {
973 case 2:
974 result = gl.uniformMatrix4x2dv;
975 break;
976 case 3:
977 result = gl.uniformMatrix4x3dv;
978 break;
979 case 4:
980 result = gl.uniformMatrix4dv;
981 break;
982 default:
983 TCU_FAIL("Invalid number of rows");
984 }
985 break;
986 default:
987 TCU_FAIL("Invalid number of columns");
988 }
989
990 return result;
991 }
992
993 /** Get proper glUniformMatrixNfv routine for vectors with specified number of columns and rows
994 *
995 * @param gl GL functions
996 * @param n_rows Number of rows
997 *
998 * @return Function address
999 **/
getUniformMatrixNfv(const glw::Functions & gl,glw::GLuint n_columns,glw::GLuint n_rows)1000 uniformMatrixNfv getUniformMatrixNfv(const glw::Functions& gl, glw::GLuint n_columns, glw::GLuint n_rows)
1001 {
1002 uniformMatrixNfv result = 0;
1003
1004 switch (n_columns)
1005 {
1006 case 2:
1007 switch (n_rows)
1008 {
1009 case 2:
1010 result = gl.uniformMatrix2fv;
1011 break;
1012 case 3:
1013 result = gl.uniformMatrix2x3fv;
1014 break;
1015 case 4:
1016 result = gl.uniformMatrix2x4fv;
1017 break;
1018 default:
1019 TCU_FAIL("Invalid number of rows");
1020 }
1021 break;
1022 case 3:
1023 switch (n_rows)
1024 {
1025 case 2:
1026 result = gl.uniformMatrix3x2fv;
1027 break;
1028 case 3:
1029 result = gl.uniformMatrix3fv;
1030 break;
1031 case 4:
1032 result = gl.uniformMatrix3x4fv;
1033 break;
1034 default:
1035 TCU_FAIL("Invalid number of rows");
1036 }
1037 break;
1038 case 4:
1039 switch (n_rows)
1040 {
1041 case 2:
1042 result = gl.uniformMatrix4x2fv;
1043 break;
1044 case 3:
1045 result = gl.uniformMatrix4x3fv;
1046 break;
1047 case 4:
1048 result = gl.uniformMatrix4fv;
1049 break;
1050 default:
1051 TCU_FAIL("Invalid number of rows");
1052 }
1053 break;
1054 default:
1055 TCU_FAIL("Invalid number of columns");
1056 }
1057
1058 return result;
1059 }
1060
verifyVarying(Program & program,const std::string & parent_name,const Variable::Descriptor & desc,std::stringstream & stream,bool is_input)1061 bool verifyVarying(Program& program, const std::string& parent_name, const Variable::Descriptor& desc,
1062 std::stringstream& stream, bool is_input)
1063 {
1064 GLint component = 0;
1065 GLuint index = 0;
1066 GLenum interface = GL_PROGRAM_INPUT;
1067 GLint location = 0;
1068
1069 if (false == is_input)
1070 {
1071 interface = GL_PROGRAM_OUTPUT;
1072 }
1073
1074 const std::string& name = Utils::Variable::GetReference(parent_name, desc, Utils::Variable::BASIC, 0);
1075
1076 try
1077 {
1078 index = program.GetResourceIndex(name, interface);
1079
1080 program.GetResource(interface, index, GL_LOCATION, 1 /* size */, &location);
1081 program.GetResource(interface, index, GL_LOCATION_COMPONENT, 1 /* size */, &component);
1082 }
1083 catch (std::exception& exc)
1084 {
1085 stream << "Failed to query program for varying: " << desc.m_name << ". Reason: " << exc.what() << "\n";
1086
1087 return false;
1088 }
1089
1090 bool result = true;
1091
1092 if (location != desc.m_expected_location)
1093 {
1094 stream << "Attribute: " << desc.m_name << " - invalid location: " << location
1095 << " expected: " << desc.m_expected_location << std::endl;
1096 result = false;
1097 }
1098 if (component != desc.m_expected_component)
1099 {
1100 stream << "Attribute: " << desc.m_name << " - invalid component: " << component
1101 << " expected: " << desc.m_expected_component << std::endl;
1102 result = false;
1103 }
1104
1105 return result;
1106 }
1107
1108 /** Query program resource for given variable and verify that everything is as expected
1109 *
1110 * @param program Program object
1111 * @param variable Variable object
1112 * @param stream Stream that will be used to log any error
1113 * @param is_input Selects if varying is input or output
1114 *
1115 * @return true if verification is positive, false otherwise
1116 **/
checkVarying(Program & program,Shader::STAGES stage,const Variable & variable,std::stringstream & stream,bool is_input)1117 bool checkVarying(Program& program, Shader::STAGES stage, const Variable& variable, std::stringstream& stream, bool is_input)
1118 {
1119 bool result = true;
1120
1121 if (variable.IsBlock())
1122 {
1123 Utils::Interface* interface = variable.m_descriptor.m_interface;
1124 const size_t n_members = interface->m_members.size();
1125
1126 for (size_t i = 0; i < n_members; ++i)
1127 {
1128 const Variable::Descriptor& member = interface->m_members[i];
1129 bool member_result = verifyVarying(program, interface->m_name, member, stream, is_input);
1130
1131 if (false == member_result)
1132 {
1133 result = false;
1134 }
1135 }
1136 }
1137 /*
1138 To query the the location of struct member by glGetProgramResource, we need pass the variable name "gs_fs_output[0].single",
1139 but in original implementation, the test pass the name "Data.single", which can't get any valid result.
1140 struct Data {
1141 dmat2 single;
1142 dmat2 array[1];
1143 };
1144 layout (location = 0) in Data gs_fs_output[1];
1145 */
1146 else if (variable.IsStruct())
1147 {
1148 Utils::Interface* interface = variable.m_descriptor.m_interface;
1149 const size_t n_members = interface->m_members.size();
1150 std::string structVariable = variable.m_descriptor.m_name;
1151
1152 switch (Variable::GetFlavour(stage, is_input ? Variable::INPUT : Variable::OUTPUT))
1153 {
1154 case Variable::ARRAY:
1155 case Variable::INDEXED_BY_INVOCATION_ID:
1156 structVariable.append("[0]");
1157 break;
1158 default:
1159 break;
1160 }
1161
1162 // If struct variable is an array
1163 if (0 != variable.m_descriptor.m_n_array_elements)
1164 {
1165 for (GLuint i = 0; i < variable.m_descriptor.m_n_array_elements; i++)
1166 {
1167 GLchar buffer[16];
1168 sprintf(buffer, "%d", i);
1169 structVariable.append("[");
1170 structVariable.append(buffer);
1171 structVariable.append("]");
1172 for (size_t j = 0; j < n_members; ++j)
1173 {
1174 const Variable::Descriptor& member = interface->m_members[j];
1175 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1176
1177 if (false == member_result)
1178 {
1179 result = false;
1180 }
1181 }
1182 }
1183 }
1184 else
1185 {
1186 for (GLuint i = 0; i < n_members; ++i)
1187 {
1188 const Variable::Descriptor& member = interface->m_members[i];
1189 bool member_result = verifyVarying(program, structVariable, member, stream, is_input);
1190
1191 if (false == member_result)
1192 {
1193 result = false;
1194 }
1195 }
1196 }
1197 }
1198 else
1199 {
1200 result = verifyVarying(program, "", variable.m_descriptor, stream, is_input);
1201 }
1202 return result;
1203 }
1204
1205 /** Query program resource for given variable and verify that everything is as expected
1206 *
1207 * @param program Program object
1208 * @param variable Variable object
1209 * @param stream Stream that will be used to log any error
1210 *
1211 * @return true if verification is positive, false otherwise
1212 **/
checkUniform(Program & program,const Utils::Variable & variable,std::stringstream & stream)1213 bool checkUniform(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1214 {
1215 bool result = true;
1216
1217 if (false == variable.IsBlock())
1218 {
1219 TCU_FAIL("Not implemented");
1220 }
1221 else
1222 {
1223 Utils::Interface* interface = variable.m_descriptor.m_interface;
1224
1225 size_t size = interface->m_members.size();
1226
1227 std::vector<GLuint> indices;
1228 std::vector<const char*> names;
1229 std::vector<std::string> names_str;
1230 std::vector<GLint> offsets;
1231
1232 indices.resize(size);
1233 names.resize(size);
1234 names_str.resize(size);
1235 offsets.resize(size);
1236
1237 for (size_t i = 0; i < size; ++i)
1238 {
1239 indices[i] = 0;
1240 offsets[i] = 0;
1241
1242 const std::string& name =
1243 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1244
1245 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1246 {
1247 const std::string& member_name = Utils::Variable::GetReference(
1248 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1249
1250 names_str[i] = member_name;
1251 }
1252 else
1253 {
1254 names_str[i] = name;
1255 }
1256
1257 names[i] = names_str[i].c_str();
1258 }
1259
1260 try
1261 {
1262 program.GetUniformIndices(static_cast<glw::GLsizei>(size), &names[0], &indices[0]);
1263 program.GetActiveUniformsiv(static_cast<glw::GLsizei>(size), &indices[0], GL_UNIFORM_OFFSET, &offsets[0]);
1264 }
1265 catch (std::exception& exc)
1266 {
1267 stream << "Failed to query program for uniforms in block: " << variable.m_descriptor.m_name
1268 << ". Reason: " << exc.what() << "\n";
1269
1270 return false;
1271 }
1272
1273 for (size_t i = 0; i < size; ++i)
1274 {
1275 Utils::Variable::Descriptor& desc = interface->m_members[i];
1276
1277 if (offsets[i] != (GLint)desc.m_offset)
1278 {
1279 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offsets[i]
1280 << " expected: " << desc.m_offset << std::endl;
1281 result = false;
1282 }
1283 }
1284 }
1285
1286 return result;
1287 }
1288
1289 /** Query program resource for given variable and verify that everything is as expected
1290 *
1291 * @param program Program object
1292 * @param variable Variable object
1293 * @param stream Stream that will be used to log any error
1294 *
1295 * @return true if verification is positive, false otherwise
1296 **/
checkSSB(Program & program,const Utils::Variable & variable,std::stringstream & stream)1297 bool checkSSB(Program& program, const Utils::Variable& variable, std::stringstream& stream)
1298 {
1299 bool result = true;
1300
1301 if (false == variable.IsBlock())
1302 {
1303 TCU_FAIL("Not implemented");
1304 }
1305 else
1306 {
1307 Utils::Interface* interface = variable.m_descriptor.m_interface;
1308
1309 size_t size = interface->m_members.size();
1310
1311 for (size_t i = 0; i < size; ++i)
1312 {
1313 GLuint index = 0;
1314 std::string name_str = "";
1315 GLint offset = 0;
1316
1317 const std::string& name =
1318 Utils::Variable::GetReference(interface->m_name, interface->m_members[i], Utils::Variable::BASIC, 0);
1319
1320 if (Utils::Variable::INTERFACE == interface->m_members[i].m_type)
1321 {
1322 const std::string& member_name = Utils::Variable::GetReference(
1323 name, interface->m_members[i].m_interface->m_members[0], Utils::Variable::BASIC, 0);
1324
1325 name_str = member_name;
1326 }
1327 else
1328 {
1329 name_str = name;
1330 }
1331
1332 try
1333 {
1334 index = program.GetResourceIndex(name_str, GL_BUFFER_VARIABLE);
1335
1336 program.GetResource(GL_BUFFER_VARIABLE, index, GL_OFFSET, 1, &offset);
1337 }
1338 catch (std::exception& exc)
1339 {
1340 stream << "Failed to query program for buffer variable: " << variable.m_descriptor.m_name
1341 << ". Reason: " << exc.what() << "\n";
1342
1343 return false;
1344 }
1345
1346 Utils::Variable::Descriptor& desc = interface->m_members[i];
1347
1348 if (offset != (GLint)desc.m_offset)
1349 {
1350 stream << "Uniform: " << desc.m_name << " - invalid offset: " << offset
1351 << " expected: " << desc.m_offset << std::endl;
1352 result = false;
1353 }
1354 }
1355 }
1356
1357 return result;
1358 }
1359
1360 /** Query program resources at given stage and verifies results
1361 *
1362 * @param program Program object
1363 * @param program_interface Definition of program interface
1364 * @param stage Stage to be verified
1365 * @param check_inputs Select if inputs should be verified
1366 * @param check_outputs Select if output should be verified
1367 * @param check_uniforms Select if uniforms should be verified
1368 * @param check_ssbs Select if buffers should be verified
1369 * @param stream Stream that will be used to log any error
1370 *
1371 * @return true if verification is positive, false otherwise
1372 **/
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)1373 bool checkProgramStage(Program& program, const ProgramInterface& program_interface, Utils::Shader::STAGES stage,
1374 bool check_inputs, bool check_outputs, bool check_uniforms, bool check_ssbs,
1375 std::stringstream& stream)
1376 {
1377 typedef Variable::PtrVector::const_iterator const_iterator;
1378
1379 const ShaderInterface& interface = program_interface.GetShaderInterface(stage);
1380
1381 bool result = true;
1382
1383 /* Inputs */
1384 if (true == check_inputs)
1385 {
1386 const Variable::PtrVector& inputs = interface.m_inputs;
1387
1388 for (const_iterator it = inputs.begin(); it != inputs.end(); ++it)
1389 {
1390 if (false == checkVarying(program, stage, **it, stream, true))
1391 {
1392 result = false;
1393 }
1394 }
1395 }
1396
1397 /* Outputs */
1398 if (true == check_outputs)
1399 {
1400 const Variable::PtrVector& outputs = interface.m_outputs;
1401
1402 for (const_iterator it = outputs.begin(); it != outputs.end(); ++it)
1403 {
1404 if (false == checkVarying(program, stage, **it, stream, false))
1405 {
1406 result = false;
1407 }
1408 }
1409 }
1410
1411 /* Uniforms */
1412 if (true == check_uniforms)
1413 {
1414 const Variable::PtrVector& uniforms = interface.m_uniforms;
1415
1416 for (const_iterator it = uniforms.begin(); it != uniforms.end(); ++it)
1417 {
1418 if (false == checkUniform(program, **it, stream))
1419 {
1420 result = false;
1421 }
1422 }
1423 }
1424
1425 /* SSBs */
1426 if (true == check_ssbs)
1427 {
1428 const Variable::PtrVector& ssbs = interface.m_ssb_blocks;
1429
1430 for (const_iterator it = ssbs.begin(); it != ssbs.end(); ++it)
1431 {
1432 if (false == checkSSB(program, **it, stream))
1433 {
1434 result = false;
1435 }
1436 }
1437 }
1438
1439 return result;
1440 }
1441
1442 /** Query resources of monolithic compute program and verifies results
1443 *
1444 * @param program Program object
1445 * @param program_interface Definition of program interface
1446 * @param stream Stream that will be used to log any error
1447 *
1448 * @return true if verification is positive, false otherwise
1449 **/
checkMonolithicComputeProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1450 bool checkMonolithicComputeProgramInterface(Program& program, const ProgramInterface& program_interface,
1451 std::stringstream& stream)
1452 {
1453 bool result = true;
1454
1455 if (false == checkProgramStage(program, program_interface, Shader::COMPUTE, false, false, true, true, stream))
1456 {
1457 result = false;
1458 }
1459
1460 /* Done */
1461 return result;
1462 }
1463
1464 /** Query resources of monolithic draw program and verifies results
1465 *
1466 * @param program Program object
1467 * @param program_interface Definition of program interface
1468 * @param stream Stream that will be used to log any error
1469 *
1470 * @return true if verification is positive, false otherwise
1471 **/
checkMonolithicDrawProgramInterface(Program & program,const ProgramInterface & program_interface,std::stringstream & stream)1472 bool checkMonolithicDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1473 std::stringstream& stream)
1474 {
1475 bool result = true;
1476
1477 if (false == checkProgramStage(program, program_interface, Shader::VERTEX, true, false, true, true, stream))
1478 {
1479 result = false;
1480 }
1481
1482 /* Done */
1483 return result;
1484 }
1485
1486 /** Query resources of separable draw program and verifies results
1487 *
1488 * @param program Program object
1489 * @param program_interface Definition of program interface
1490 * @param stream Stream that will be used to log any error
1491 *
1492 * @return true if verification is positive, false otherwise
1493 **/
checkSeparableDrawProgramInterface(Program & program,const ProgramInterface & program_interface,Utils::Shader::STAGES stage,std::stringstream & stream)1494 bool checkSeparableDrawProgramInterface(Program& program, const ProgramInterface& program_interface,
1495 Utils::Shader::STAGES stage, std::stringstream& stream)
1496 {
1497 bool result = true;
1498
1499 if (false == checkProgramStage(program, program_interface, stage, true, true, true, true, stream))
1500 {
1501 result = false;
1502 }
1503
1504 /* Done */
1505 return result;
1506 }
1507
1508 /** Check if extension is supported
1509 *
1510 * @param context Test context
1511 * @param extension_name Name of extension
1512 *
1513 * @return true if extension is supported, false otherwise
1514 **/
isExtensionSupported(deqp::Context & context,const GLchar * extension_name)1515 bool isExtensionSupported(deqp::Context& context, const GLchar* extension_name)
1516 {
1517 const std::vector<std::string>& extensions = context.getContextInfo().getExtensions();
1518
1519 if (std::find(extensions.begin(), extensions.end(), extension_name) == extensions.end())
1520 {
1521 return false;
1522 }
1523
1524 return true;
1525 }
1526
1527 /** Check if GL context meets version requirements
1528 *
1529 * @param gl Functions
1530 * @param required_major Minimum required MAJOR_VERSION
1531 * @param required_minor Minimum required MINOR_VERSION
1532 *
1533 * @return true if GL context version is at least as requested, false otherwise
1534 **/
isGLVersionAtLeast(const Functions & gl,GLint required_major,GLint required_minor)1535 bool isGLVersionAtLeast(const Functions& gl, GLint required_major, GLint required_minor)
1536 {
1537 glw::GLint major = 0;
1538 glw::GLint minor = 0;
1539
1540 gl.getIntegerv(GL_MAJOR_VERSION, &major);
1541 gl.getIntegerv(GL_MINOR_VERSION, &minor);
1542
1543 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
1544
1545 if (major > required_major)
1546 {
1547 /* Major is higher than required one */
1548 return true;
1549 }
1550 else if (major == required_major)
1551 {
1552 if (minor >= required_minor)
1553 {
1554 /* Major is equal to required one */
1555 /* Minor is higher than or equal to required one */
1556 return true;
1557 }
1558 else
1559 {
1560 /* Major is equal to required one */
1561 /* Minor is lower than required one */
1562 return false;
1563 }
1564 }
1565 else
1566 {
1567 /* Major is lower than required one */
1568 return false;
1569 }
1570 }
1571
1572 /** Replace first occurance of <token> with <text> in <string> starting at <search_posistion>
1573 *
1574 * @param token Token string
1575 * @param search_position Position at which find will start, it is updated to position at which replaced text ends
1576 * @param text String that will be used as replacement for <token>
1577 * @param string String to work on
1578 **/
replaceToken(const GLchar * token,size_t & search_position,const GLchar * text,std::string & string)1579 void replaceToken(const GLchar* token, size_t& search_position, const GLchar* text, std::string& string)
1580 {
1581 const size_t text_length = strlen(text);
1582 const size_t token_length = strlen(token);
1583 const size_t token_position = string.find(token, search_position);
1584
1585 #if DEBUG_REPLACE_TOKEN
1586 if (std::string::npos == token_position)
1587 {
1588 string.append("\n\nInvalid token: ");
1589 string.append(token);
1590
1591 TCU_FAIL(string.c_str());
1592 }
1593 #endif /* DEBUG_REPLACE_TOKEN */
1594
1595 string.replace(token_position, token_length, text, text_length);
1596
1597 search_position = token_position + text_length;
1598 }
1599
1600 /** Replace all occurances of <token> with <text> in <string>
1601 *
1602 * @param token Token string
1603 * @param text String that will be used as replacement for <token>
1604 * @param string String to work on
1605 **/
replaceAllTokens(const GLchar * token,const GLchar * text,std::string & string)1606 void replaceAllTokens(const GLchar* token, const GLchar* text, std::string& string)
1607 {
1608 const size_t text_length = strlen(text);
1609 const size_t token_length = strlen(token);
1610
1611 size_t search_position = 0;
1612
1613 while (1)
1614 {
1615 const size_t token_position = string.find(token, search_position);
1616
1617 if (std::string::npos == token_position)
1618 {
1619 break;
1620 }
1621
1622 search_position = token_position + text_length;
1623
1624 string.replace(token_position, token_length, text, text_length);
1625 }
1626 }
1627
1628 /** Rounds up the value to the next power of 2.
1629 * This routine does not work for 0, see the url for explanations.
1630 *
1631 * @param value Starting point
1632 *
1633 * @return Calculated value
1634 **/
roundUpToPowerOf2(glw::GLuint value)1635 glw::GLuint roundUpToPowerOf2(glw::GLuint value)
1636 {
1637 /* Taken from: graphics.stanford.edu/~seander/bithacks.html */
1638 --value;
1639
1640 value |= value >> 1;
1641 value |= value >> 2;
1642 value |= value >> 4;
1643 value |= value >> 8;
1644 value |= value >> 16;
1645
1646 ++value;
1647
1648 return value;
1649 }
1650
1651 /** Insert elements of list into string.
1652 * List in string is represented either by token "LIST" or "SEPARATORLIST".
1653 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>.
1654 * LIST is replaced with <element>SEPARATORLIST
1655 *
1656 * @param element Element to be inserted
1657 * @param separator Separator inserted between elements
1658 * @param search_position Position in string, where search for list should start
1659 * @param string String
1660 **/
insertElementOfList(const GLchar * element,const GLchar * separator,size_t & search_position,std::string & string)1661 void insertElementOfList(const GLchar* element, const GLchar* separator, size_t& search_position, std::string& string)
1662 {
1663 static const char* list = g_list;
1664 static const char* sep_list = "SEPARATORLIST";
1665
1666 /* Try to get "list" positions */
1667 const size_t list_position = string.find(list, search_position);
1668 const size_t sep_list_position = string.find(sep_list, search_position);
1669
1670 /* There is no list in string */
1671 if (std::string::npos == list_position)
1672 {
1673 return;
1674 }
1675
1676 if (9 /* strlen(SEPARATOR) */ == list_position - sep_list_position)
1677 {
1678 replaceToken("SEPARATOR", search_position, separator, string);
1679 }
1680
1681 /* Save search_position */
1682 const size_t start_position = search_position;
1683
1684 /* Prepare new element */
1685 replaceToken("LIST", search_position, "ELEMENTSEPARATORLIST", string);
1686
1687 /* Restore search_position */
1688 search_position = start_position;
1689
1690 /* Replace element and separator */
1691 replaceToken("ELEMENT", search_position, element, string);
1692 }
1693
1694 /** Close list in string.
1695 * If SEPARATORLIST is available, than SEPARATOR is replaced with <separator>
1696 * LIST is replaced with ""
1697 *
1698 * @param separator Separator inserted between elements
1699 * @param search_position Position in string, where search for list should start
1700 * @param string String
1701 **/
endList(const glw::GLchar * separator,size_t & search_position,std::string & string)1702 void endList(const glw::GLchar* separator, size_t& search_position, std::string& string)
1703 {
1704 const size_t sep_position = string.find("SEPARATOR", search_position);
1705 if (std::string::npos != sep_position)
1706 {
1707 replaceToken("SEPARATOR", search_position, separator, string);
1708 }
1709
1710 replaceToken("LIST", search_position, "", string);
1711 }
1712
1713 /* Buffer constants */
1714 const GLuint Buffer::m_invalid_id = -1;
1715
1716 /** Constructor.
1717 *
1718 * @param context CTS context.
1719 **/
Buffer(deqp::Context & context)1720 Buffer::Buffer(deqp::Context& context) : m_id(m_invalid_id), m_buffer(Array), m_context(context)
1721 {
1722 }
1723
1724 /** Destructor
1725 *
1726 **/
~Buffer()1727 Buffer::~Buffer()
1728 {
1729 Release();
1730 }
1731
1732 /** Initialize buffer instance
1733 *
1734 * @param buffer Buffer type
1735 * @param usage Buffer usage enum
1736 * @param size <size> parameter
1737 * @param data <data> parameter
1738 **/
Init(BUFFERS buffer,USAGE usage,GLsizeiptr size,GLvoid * data)1739 void Buffer::Init(BUFFERS buffer, USAGE usage, GLsizeiptr size, GLvoid* data)
1740 {
1741 /* Delete previous buffer instance */
1742 Release();
1743
1744 m_buffer = buffer;
1745
1746 const Functions& gl = m_context.getRenderContext().getFunctions();
1747
1748 Generate(gl, m_id);
1749 Bind(gl, m_id, m_buffer);
1750 Data(gl, m_buffer, usage, size, data);
1751 }
1752
1753 /** Release buffer instance
1754 *
1755 **/
Release()1756 void Buffer::Release()
1757 {
1758 if (m_invalid_id != m_id)
1759 {
1760 const Functions& gl = m_context.getRenderContext().getFunctions();
1761
1762 gl.deleteBuffers(1, &m_id);
1763 m_id = m_invalid_id;
1764 }
1765 }
1766
1767 /** Binds buffer to its target
1768 *
1769 **/
Bind() const1770 void Buffer::Bind() const
1771 {
1772 const Functions& gl = m_context.getRenderContext().getFunctions();
1773
1774 Bind(gl, m_id, m_buffer);
1775 }
1776
1777 /** Binds indexed buffer
1778 *
1779 * @param index <index> parameter
1780 **/
BindBase(GLuint index) const1781 void Buffer::BindBase(GLuint index) const
1782 {
1783 const Functions& gl = m_context.getRenderContext().getFunctions();
1784
1785 BindBase(gl, m_id, m_buffer, index);
1786 }
1787
1788 /** Binds range of buffer
1789 *
1790 * @param index <index> parameter
1791 * @param offset <offset> parameter
1792 * @param size <size> parameter
1793 **/
BindRange(GLuint index,GLintptr offset,GLsizeiptr size) const1794 void Buffer::BindRange(GLuint index, GLintptr offset, GLsizeiptr size) const
1795 {
1796 const Functions& gl = m_context.getRenderContext().getFunctions();
1797
1798 BindRange(gl, m_id, m_buffer, index, offset, size);
1799 }
1800
1801 /** Allocate memory for buffer and sends initial content
1802 *
1803 * @param usage Buffer usage enum
1804 * @param size <size> parameter
1805 * @param data <data> parameter
1806 **/
Data(USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1807 void Buffer::Data(USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1808 {
1809 const Functions& gl = m_context.getRenderContext().getFunctions();
1810
1811 Data(gl, m_buffer, usage, size, data);
1812 }
1813
1814 /** Maps contents of buffer into CPU space
1815 *
1816 * @param access Requested access
1817 *
1818 * @return Pointer to memory region available for CPU
1819 **/
Map(ACCESS access)1820 GLvoid* Buffer::Map(ACCESS access)
1821 {
1822 const Functions& gl = m_context.getRenderContext().getFunctions();
1823
1824 return Map(gl, m_buffer, access);
1825 }
1826
1827 /** Allocate memory for buffer and sends initial content
1828 *
1829 * @param offset Offset in buffer
1830 * @param size <size> parameter
1831 * @param data <data> parameter
1832 **/
SubData(glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1833 void Buffer::SubData(glw::GLintptr offset, glw::GLsizeiptr size, glw::GLvoid* data)
1834 {
1835 const Functions& gl = m_context.getRenderContext().getFunctions();
1836
1837 SubData(gl, m_buffer, offset, size, data);
1838 }
1839
1840 /** Maps contents of buffer into CPU space
1841 **/
UnMap()1842 void Buffer::UnMap()
1843 {
1844 const Functions& gl = m_context.getRenderContext().getFunctions();
1845
1846 return UnMap(gl, m_buffer);
1847 }
1848
1849 /** Bind buffer to given target
1850 *
1851 * @param gl GL functions
1852 * @param id Id of buffer
1853 * @param buffer Buffer enum
1854 **/
Bind(const Functions & gl,GLuint id,BUFFERS buffer)1855 void Buffer::Bind(const Functions& gl, GLuint id, BUFFERS buffer)
1856 {
1857 GLenum target = GetBufferGLenum(buffer);
1858
1859 gl.bindBuffer(target, id);
1860 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBuffer");
1861 }
1862
1863 /** Binds indexed buffer
1864 *
1865 * @param gl GL functions
1866 * @param id Id of buffer
1867 * @param buffer Buffer enum
1868 * @param index <index> parameter
1869 **/
BindBase(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index)1870 void Buffer::BindBase(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index)
1871 {
1872 GLenum target = GetBufferGLenum(buffer);
1873
1874 gl.bindBufferBase(target, index, id);
1875 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferBase");
1876 }
1877
1878 /** Binds buffer range
1879 *
1880 * @param gl GL functions
1881 * @param id Id of buffer
1882 * @param buffer Buffer enum
1883 * @param index <index> parameter
1884 * @param offset <offset> parameter
1885 * @param size <size> parameter
1886 **/
BindRange(const Functions & gl,GLuint id,BUFFERS buffer,GLuint index,GLintptr offset,GLsizeiptr size)1887 void Buffer::BindRange(const Functions& gl, GLuint id, BUFFERS buffer, GLuint index, GLintptr offset, GLsizeiptr size)
1888 {
1889 GLenum target = GetBufferGLenum(buffer);
1890
1891 gl.bindBufferRange(target, index, id, offset, size);
1892 GLU_EXPECT_NO_ERROR(gl.getError(), "BindBufferRange");
1893 }
1894
1895 /** Allocate memory for buffer and sends initial content
1896 *
1897 * @param gl GL functions
1898 * @param buffer Buffer enum
1899 * @param usage Buffer usage enum
1900 * @param size <size> parameter
1901 * @param data <data> parameter
1902 **/
Data(const glw::Functions & gl,BUFFERS buffer,USAGE usage,glw::GLsizeiptr size,glw::GLvoid * data)1903 void Buffer::Data(const glw::Functions& gl, BUFFERS buffer, USAGE usage, glw::GLsizeiptr size, glw::GLvoid* data)
1904 {
1905 GLenum target = GetBufferGLenum(buffer);
1906 GLenum gl_usage = GetUsageGLenum(usage);
1907
1908 gl.bufferData(target, size, data, gl_usage);
1909 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferData");
1910 }
1911
1912 /** Allocate memory for buffer and sends initial content
1913 *
1914 * @param gl GL functions
1915 * @param buffer Buffer enum
1916 * @param offset Offset in buffer
1917 * @param size <size> parameter
1918 * @param data <data> parameter
1919 **/
SubData(const glw::Functions & gl,BUFFERS buffer,glw::GLintptr offset,glw::GLsizeiptr size,glw::GLvoid * data)1920 void Buffer::SubData(const glw::Functions& gl, BUFFERS buffer, glw::GLintptr offset, glw::GLsizeiptr size,
1921 glw::GLvoid* data)
1922 {
1923 GLenum target = GetBufferGLenum(buffer);
1924
1925 gl.bufferSubData(target, offset, size, data);
1926 GLU_EXPECT_NO_ERROR(gl.getError(), "BufferSubData");
1927 }
1928
1929 /** Generate buffer
1930 *
1931 * @param gl GL functions
1932 * @param out_id Id of buffer
1933 **/
Generate(const Functions & gl,GLuint & out_id)1934 void Buffer::Generate(const Functions& gl, GLuint& out_id)
1935 {
1936 GLuint id = m_invalid_id;
1937
1938 gl.genBuffers(1, &id);
1939 GLU_EXPECT_NO_ERROR(gl.getError(), "GenBuffers");
1940
1941 if (m_invalid_id == id)
1942 {
1943 TCU_FAIL("Got invalid id");
1944 }
1945
1946 out_id = id;
1947 }
1948
1949 /** Maps buffer content
1950 *
1951 * @param gl GL functions
1952 * @param buffer Buffer enum
1953 * @param access Access rights for mapped region
1954 *
1955 * @return Mapped memory
1956 **/
Map(const Functions & gl,BUFFERS buffer,ACCESS access)1957 void* Buffer::Map(const Functions& gl, BUFFERS buffer, ACCESS access)
1958 {
1959 GLenum target = GetBufferGLenum(buffer);
1960 GLenum gl_access = GetAccessGLenum(access);
1961
1962 void* result = gl.mapBuffer(target, gl_access);
1963 GLU_EXPECT_NO_ERROR(gl.getError(), "MapBuffer");
1964
1965 return result;
1966 }
1967
1968 /** Unmaps buffer
1969 *
1970 **/
UnMap(const Functions & gl,BUFFERS buffer)1971 void Buffer::UnMap(const Functions& gl, BUFFERS buffer)
1972 {
1973 GLenum target = GetBufferGLenum(buffer);
1974
1975 gl.unmapBuffer(target);
1976 GLU_EXPECT_NO_ERROR(gl.getError(), "UnmapBuffer");
1977 }
1978
1979 /** Return GLenum representation of requested access
1980 *
1981 * @param access Requested access
1982 *
1983 * @return GLenum value
1984 **/
GetAccessGLenum(ACCESS access)1985 GLenum Buffer::GetAccessGLenum(ACCESS access)
1986 {
1987 GLenum result = 0;
1988
1989 switch (access)
1990 {
1991 case ReadOnly:
1992 result = GL_READ_ONLY;
1993 break;
1994 case WriteOnly:
1995 result = GL_WRITE_ONLY;
1996 break;
1997 case ReadWrite:
1998 result = GL_READ_WRITE;
1999 break;
2000 default:
2001 TCU_FAIL("Invalid enum");
2002 }
2003
2004 return result;
2005 }
2006
2007 /** Return GLenum representation of requested buffer type
2008 *
2009 * @param buffer Requested buffer type
2010 *
2011 * @return GLenum value
2012 **/
GetBufferGLenum(BUFFERS buffer)2013 GLenum Buffer::GetBufferGLenum(BUFFERS buffer)
2014 {
2015 GLenum result = 0;
2016
2017 switch (buffer)
2018 {
2019 case Array:
2020 result = GL_ARRAY_BUFFER;
2021 break;
2022 case Element:
2023 result = GL_ELEMENT_ARRAY_BUFFER;
2024 break;
2025 case Shader_Storage:
2026 result = GL_SHADER_STORAGE_BUFFER;
2027 break;
2028 case Texture:
2029 result = GL_TEXTURE_BUFFER;
2030 break;
2031 case Transform_feedback:
2032 result = GL_TRANSFORM_FEEDBACK_BUFFER;
2033 break;
2034 case Uniform:
2035 result = GL_UNIFORM_BUFFER;
2036 break;
2037 default:
2038 TCU_FAIL("Invalid enum");
2039 }
2040
2041 return result;
2042 }
2043
2044 /** Return GLenum representation of requested usage
2045 *
2046 * @param usage Requested usage
2047 *
2048 * @return GLenum value
2049 **/
GetUsageGLenum(USAGE usage)2050 GLenum Buffer::GetUsageGLenum(USAGE usage)
2051 {
2052 GLenum result = 0;
2053
2054 switch (usage)
2055 {
2056 case DynamicCopy:
2057 result = GL_DYNAMIC_COPY;
2058 break;
2059 case DynamicDraw:
2060 result = GL_DYNAMIC_DRAW;
2061 break;
2062 case DynamicRead:
2063 result = GL_DYNAMIC_READ;
2064 break;
2065 case StaticCopy:
2066 result = GL_STATIC_COPY;
2067 break;
2068 case StaticDraw:
2069 result = GL_STATIC_DRAW;
2070 break;
2071 case StaticRead:
2072 result = GL_STATIC_READ;
2073 break;
2074 case StreamCopy:
2075 result = GL_STREAM_COPY;
2076 break;
2077 case StreamDraw:
2078 result = GL_STREAM_DRAW;
2079 break;
2080 case StreamRead:
2081 result = GL_STREAM_READ;
2082 break;
2083 default:
2084 TCU_FAIL("Invalid enum");
2085 }
2086
2087 return result;
2088 }
2089
2090 /** Returns name of buffer target
2091 *
2092 * @param buffer Target enum
2093 *
2094 * @return Name of target
2095 **/
GetBufferName(BUFFERS buffer)2096 const GLchar* Buffer::GetBufferName(BUFFERS buffer)
2097 {
2098 const GLchar* name = 0;
2099
2100 switch (buffer)
2101 {
2102 case Array:
2103 name = "Array";
2104 break;
2105 case Element:
2106 name = "Element";
2107 break;
2108 case Shader_Storage:
2109 name = "Shader_Storage";
2110 break;
2111 case Texture:
2112 name = "Texture";
2113 break;
2114 case Transform_feedback:
2115 name = "Transform_feedback";
2116 break;
2117 case Uniform:
2118 name = "Uniform";
2119 break;
2120 default:
2121 TCU_FAIL("Invalid enum");
2122 }
2123
2124 return name;
2125 }
2126
2127 /* Framebuffer constants */
2128 const GLuint Framebuffer::m_invalid_id = -1;
2129
2130 /** Constructor
2131 *
2132 * @param context CTS context
2133 **/
Framebuffer(deqp::Context & context)2134 Framebuffer::Framebuffer(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2135 {
2136 /* Nothing to be done here */
2137 }
2138
2139 /** Destructor
2140 *
2141 **/
~Framebuffer()2142 Framebuffer::~Framebuffer()
2143 {
2144 Release();
2145 }
2146
2147 /** Initialize framebuffer instance
2148 *
2149 **/
Init()2150 void Framebuffer::Init()
2151 {
2152 /* Delete previous instance */
2153 Release();
2154
2155 const Functions& gl = m_context.getRenderContext().getFunctions();
2156
2157 Generate(gl, m_id);
2158 }
2159
2160 /** Release framebuffer instance
2161 *
2162 **/
Release()2163 void Framebuffer::Release()
2164 {
2165 if (m_invalid_id != m_id)
2166 {
2167 const Functions& gl = m_context.getRenderContext().getFunctions();
2168
2169 gl.deleteFramebuffers(1, &m_id);
2170 m_id = m_invalid_id;
2171 }
2172 }
2173
2174 /** Attach texture to specified attachment
2175 *
2176 * @param attachment Attachment
2177 * @param texture_id Texture id
2178 * @param width Texture width
2179 * @param height Texture height
2180 **/
AttachTexture(GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2181 void Framebuffer::AttachTexture(GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2182 {
2183 const Functions& gl = m_context.getRenderContext().getFunctions();
2184
2185 AttachTexture(gl, attachment, texture_id, width, height);
2186 }
2187
2188 /** Binds framebuffer to DRAW_FRAMEBUFFER
2189 *
2190 **/
Bind()2191 void Framebuffer::Bind()
2192 {
2193 const Functions& gl = m_context.getRenderContext().getFunctions();
2194
2195 Bind(gl, m_id);
2196 }
2197
2198 /** Clear framebuffer
2199 *
2200 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2201 **/
Clear(GLenum mask)2202 void Framebuffer::Clear(GLenum mask)
2203 {
2204 const Functions& gl = m_context.getRenderContext().getFunctions();
2205
2206 Clear(gl, mask);
2207 }
2208
2209 /** Specifies clear color
2210 *
2211 * @param red Red channel
2212 * @param green Green channel
2213 * @param blue Blue channel
2214 * @param alpha Alpha channel
2215 **/
ClearColor(GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2216 void Framebuffer::ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2217 {
2218 const Functions& gl = m_context.getRenderContext().getFunctions();
2219
2220 ClearColor(gl, red, green, blue, alpha);
2221 }
2222
2223 /** Attach texture to specified attachment
2224 *
2225 * @param gl GL functions
2226 * @param attachment Attachment
2227 * @param texture_id Texture id
2228 * @param width Texture width
2229 * @param height Texture height
2230 **/
AttachTexture(const Functions & gl,GLenum attachment,GLuint texture_id,GLuint width,GLuint height)2231 void Framebuffer::AttachTexture(const Functions& gl, GLenum attachment, GLuint texture_id, GLuint width, GLuint height)
2232 {
2233 gl.framebufferTexture(GL_DRAW_FRAMEBUFFER, attachment, texture_id, 0 /* level */);
2234 GLU_EXPECT_NO_ERROR(gl.getError(), "FramebufferTexture");
2235
2236 gl.viewport(0 /* x */, 0 /* y */, width, height);
2237 GLU_EXPECT_NO_ERROR(gl.getError(), "Viewport");
2238 }
2239
2240 /** Binds framebuffer to DRAW_FRAMEBUFFER
2241 *
2242 * @param gl GL functions
2243 * @param id ID of framebuffer
2244 **/
Bind(const Functions & gl,GLuint id)2245 void Framebuffer::Bind(const Functions& gl, GLuint id)
2246 {
2247 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
2248 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFramebuffer");
2249 }
2250
2251 /** Clear framebuffer
2252 *
2253 * @param gl GL functions
2254 * @param mask <mask> parameter of glClear. Decides which shall be cleared
2255 **/
Clear(const Functions & gl,GLenum mask)2256 void Framebuffer::Clear(const Functions& gl, GLenum mask)
2257 {
2258 gl.clear(mask);
2259 GLU_EXPECT_NO_ERROR(gl.getError(), "Clear");
2260 }
2261
2262 /** Specifies clear color
2263 *
2264 * @param gl GL functions
2265 * @param red Red channel
2266 * @param green Green channel
2267 * @param blue Blue channel
2268 * @param alpha Alpha channel
2269 **/
ClearColor(const Functions & gl,GLfloat red,GLfloat green,GLfloat blue,GLfloat alpha)2270 void Framebuffer::ClearColor(const Functions& gl, GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
2271 {
2272 gl.clearColor(red, green, blue, alpha);
2273 GLU_EXPECT_NO_ERROR(gl.getError(), "ClearColor");
2274 }
2275
2276 /** Generate framebuffer
2277 *
2278 **/
Generate(const Functions & gl,GLuint & out_id)2279 void Framebuffer::Generate(const Functions& gl, GLuint& out_id)
2280 {
2281 GLuint id = m_invalid_id;
2282
2283 gl.genFramebuffers(1, &id);
2284 GLU_EXPECT_NO_ERROR(gl.getError(), "GenFramebuffers");
2285
2286 if (m_invalid_id == id)
2287 {
2288 TCU_FAIL("Invalid id");
2289 }
2290
2291 out_id = id;
2292 }
2293
2294 /* Shader's constants */
2295 const GLuint Shader::m_invalid_id = 0;
2296
2297 /** Constructor.
2298 *
2299 * @param context CTS context.
2300 **/
Shader(deqp::Context & context)2301 Shader::Shader(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2302 {
2303 /* Nothing to be done here */
2304 }
2305
2306 /** Destructor
2307 *
2308 **/
~Shader()2309 Shader::~Shader()
2310 {
2311 Release();
2312 }
2313
2314 /** Initialize shader instance
2315 *
2316 * @param stage Shader stage
2317 * @param source Source code
2318 **/
Init(STAGES stage,const std::string & source)2319 void Shader::Init(STAGES stage, const std::string& source)
2320 {
2321 if (true == source.empty())
2322 {
2323 /* No source == no shader */
2324 return;
2325 }
2326
2327 /* Delete any previous shader */
2328 Release();
2329
2330 /* Create, set source and compile */
2331 const Functions& gl = m_context.getRenderContext().getFunctions();
2332
2333 Create(gl, stage, m_id);
2334 Source(gl, m_id, source);
2335
2336 try
2337 {
2338 Compile(gl, m_id);
2339 }
2340 catch (const CompilationException& exc)
2341 {
2342 throw InvalidSourceException(exc.what(), source, stage);
2343 }
2344 }
2345
2346 /** Release shader instance
2347 *
2348 **/
Release()2349 void Shader::Release()
2350 {
2351 if (m_invalid_id != m_id)
2352 {
2353 const Functions& gl = m_context.getRenderContext().getFunctions();
2354
2355 gl.deleteShader(m_id);
2356 m_id = m_invalid_id;
2357 }
2358 }
2359
2360 /** Compile shader
2361 *
2362 * @param gl GL functions
2363 * @param id Shader id
2364 **/
Compile(const Functions & gl,GLuint id)2365 void Shader::Compile(const Functions& gl, GLuint id)
2366 {
2367 GLint status = GL_FALSE;
2368
2369 /* Compile */
2370 gl.compileShader(id);
2371 GLU_EXPECT_NO_ERROR(gl.getError(), "CompileShader");
2372
2373 /* Get compilation status */
2374 gl.getShaderiv(id, GL_COMPILE_STATUS, &status);
2375 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2376
2377 /* Log compilation error */
2378 if (GL_TRUE != status)
2379 {
2380 glw::GLint length = 0;
2381 std::string message;
2382
2383 /* Error log length */
2384 gl.getShaderiv(id, GL_INFO_LOG_LENGTH, &length);
2385 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderiv");
2386
2387 /* Prepare storage */
2388 message.resize(length, 0);
2389
2390 /* Get error log */
2391 gl.getShaderInfoLog(id, length, 0, &message[0]);
2392 GLU_EXPECT_NO_ERROR(gl.getError(), "GetShaderInfoLog");
2393
2394 throw CompilationException(message.c_str());
2395 }
2396 }
2397
2398 /** Create shader
2399 *
2400 * @param gl GL functions
2401 * @param stage Shader stage
2402 * @param out_id Shader id
2403 **/
Create(const Functions & gl,STAGES stage,GLuint & out_id)2404 void Shader::Create(const Functions& gl, STAGES stage, GLuint& out_id)
2405 {
2406 const GLenum shaderType = GetShaderStageGLenum(stage);
2407 const GLuint id = gl.createShader(shaderType);
2408 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateShader");
2409
2410 if (m_invalid_id == id)
2411 {
2412 TCU_FAIL("Failed to create shader");
2413 }
2414
2415 out_id = id;
2416 }
2417
2418 /** Set shader's source code
2419 *
2420 * @param gl GL functions
2421 * @param id Shader id
2422 * @param source Shader source code
2423 **/
Source(const Functions & gl,GLuint id,const std::string & source)2424 void Shader::Source(const Functions& gl, GLuint id, const std::string& source)
2425 {
2426 const GLchar* code = source.c_str();
2427
2428 gl.shaderSource(id, 1 /* count */, &code, 0 /* lengths */);
2429 GLU_EXPECT_NO_ERROR(gl.getError(), "ShaderSource");
2430 }
2431
2432 /** Get GLenum repesenting shader stage
2433 *
2434 * @param stage Shader stage
2435 *
2436 * @return GLenum
2437 **/
GetShaderStageGLenum(STAGES stage)2438 GLenum Shader::GetShaderStageGLenum(STAGES stage)
2439 {
2440 GLenum result = 0;
2441
2442 switch (stage)
2443 {
2444 case COMPUTE:
2445 result = GL_COMPUTE_SHADER;
2446 break;
2447 case FRAGMENT:
2448 result = GL_FRAGMENT_SHADER;
2449 break;
2450 case GEOMETRY:
2451 result = GL_GEOMETRY_SHADER;
2452 break;
2453 case TESS_CTRL:
2454 result = GL_TESS_CONTROL_SHADER;
2455 break;
2456 case TESS_EVAL:
2457 result = GL_TESS_EVALUATION_SHADER;
2458 break;
2459 case VERTEX:
2460 result = GL_VERTEX_SHADER;
2461 break;
2462 default:
2463 TCU_FAIL("Invalid enum");
2464 }
2465
2466 return result;
2467 }
2468
2469 /** Get string representing name of shader stage
2470 *
2471 * @param stage Shader stage
2472 *
2473 * @return String with name of shader stage
2474 **/
GetStageName(STAGES stage)2475 const glw::GLchar* Shader::GetStageName(STAGES stage)
2476 {
2477 const GLchar* result = 0;
2478
2479 switch (stage)
2480 {
2481 case COMPUTE:
2482 result = "compute";
2483 break;
2484 case VERTEX:
2485 result = "vertex";
2486 break;
2487 case TESS_CTRL:
2488 result = "tessellation control";
2489 break;
2490 case TESS_EVAL:
2491 result = "tessellation evaluation";
2492 break;
2493 case GEOMETRY:
2494 result = "geometry";
2495 break;
2496 case FRAGMENT:
2497 result = "fragment";
2498 break;
2499 default:
2500 TCU_FAIL("Invalid enum");
2501 }
2502
2503 return result;
2504 }
2505
2506 /** Logs shader source
2507 *
2508 * @param context CTS context
2509 * @param source Source of shader
2510 * @param stage Shader stage
2511 **/
LogSource(deqp::Context & context,const std::string & source,STAGES stage)2512 void Shader::LogSource(deqp::Context& context, const std::string& source, STAGES stage)
2513 {
2514 /* Skip empty shaders */
2515 if (true == source.empty())
2516 {
2517 return;
2518 }
2519
2520 context.getTestContext().getLog() << tcu::TestLog::Message
2521 << "Shader source. Stage: " << Shader::GetStageName(stage)
2522 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(source);
2523 }
2524
2525 /** Constructor
2526 *
2527 * @param message Compilation error message
2528 **/
CompilationException(const GLchar * message)2529 Shader::CompilationException::CompilationException(const GLchar* message)
2530 {
2531 m_message = message;
2532 }
2533
2534 /** Returns error messages
2535 *
2536 * @return Compilation error message
2537 **/
what() const2538 const char* Shader::CompilationException::what() const throw()
2539 {
2540 return m_message.c_str();
2541 }
2542
2543 /** Constructor
2544 *
2545 * @param message Compilation error message
2546 **/
InvalidSourceException(const GLchar * error_message,const std::string & source,STAGES stage)2547 Shader::InvalidSourceException::InvalidSourceException(const GLchar* error_message, const std::string& source,
2548 STAGES stage)
2549 : m_message(error_message), m_source(source), m_stage(stage)
2550 {
2551 }
2552
2553 /** Returns error messages
2554 *
2555 * @return Compilation error message
2556 **/
what() const2557 const char* Shader::InvalidSourceException::what() const throw()
2558 {
2559 return "Compilation error";
2560 }
2561
2562 /** Logs error message and shader sources **/
log(deqp::Context & context) const2563 void Shader::InvalidSourceException::log(deqp::Context& context) const
2564 {
2565 context.getTestContext().getLog() << tcu::TestLog::Message << "Failed to compile shader: " << m_message.c_str()
2566 << tcu::TestLog::EndMessage;
2567
2568 LogSource(context, m_source, m_stage);
2569 }
2570
2571 /* Program constants */
2572 const GLuint Pipeline::m_invalid_id = 0;
2573
2574 /** Constructor.
2575 *
2576 * @param context CTS context.
2577 **/
Pipeline(deqp::Context & context)2578 Pipeline::Pipeline(deqp::Context& context) : m_id(m_invalid_id), m_context(context)
2579 {
2580 /* Nothing to be done here */
2581 }
2582
2583 /** Destructor
2584 *
2585 **/
~Pipeline()2586 Pipeline::~Pipeline()
2587 {
2588 Release();
2589 }
2590
2591 /** Initialize pipline object
2592 *
2593 **/
Init()2594 void Pipeline::Init()
2595 {
2596 Release();
2597
2598 const Functions& gl = m_context.getRenderContext().getFunctions();
2599
2600 /* Generate */
2601 gl.genProgramPipelines(1, &m_id);
2602 GLU_EXPECT_NO_ERROR(gl.getError(), "GenProgramPipelines");
2603 }
2604
2605 /** Release pipeline object
2606 *
2607 **/
Release()2608 void Pipeline::Release()
2609 {
2610 if (m_invalid_id != m_id)
2611 {
2612 const Functions& gl = m_context.getRenderContext().getFunctions();
2613
2614 /* Generate */
2615 gl.deleteProgramPipelines(1, &m_id);
2616 GLU_EXPECT_NO_ERROR(gl.getError(), "DeleteProgramPipelines");
2617
2618 m_id = m_invalid_id;
2619 }
2620 }
2621
2622 /** Bind pipeline
2623 *
2624 **/
Bind()2625 void Pipeline::Bind()
2626 {
2627 const Functions& gl = m_context.getRenderContext().getFunctions();
2628
2629 Bind(gl, m_id);
2630 }
2631
2632 /** Set which stages should be active
2633 *
2634 * @param program_id Id of program
2635 * @param stages Logical combination of enums representing stages
2636 **/
UseProgramStages(GLuint program_id,GLenum stages)2637 void Pipeline::UseProgramStages(GLuint program_id, GLenum stages)
2638 {
2639 const Functions& gl = m_context.getRenderContext().getFunctions();
2640
2641 UseProgramStages(gl, m_id, program_id, stages);
2642 }
2643
2644 /** Bind pipeline
2645 *
2646 * @param gl Functiions
2647 * @param id Pipeline id
2648 **/
Bind(const Functions & gl,GLuint id)2649 void Pipeline::Bind(const Functions& gl, GLuint id)
2650 {
2651 gl.bindProgramPipeline(id);
2652 GLU_EXPECT_NO_ERROR(gl.getError(), "BindProgramPipeline");
2653 }
2654
2655 /** Set which stages should be active
2656 *
2657 * @param gl Functiions
2658 * @param id Pipeline id
2659 * @param program_id Id of program
2660 * @param stages Logical combination of enums representing stages
2661 **/
UseProgramStages(const Functions & gl,GLuint id,GLuint program_id,GLenum stages)2662 void Pipeline::UseProgramStages(const Functions& gl, GLuint id, GLuint program_id, GLenum stages)
2663 {
2664 gl.useProgramStages(id, stages, program_id);
2665 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgramStages");
2666 }
2667
2668 /* Program constants */
2669 const GLuint Program::m_invalid_id = 0;
2670
2671 /** Constructor.
2672 *
2673 * @param context CTS context.
2674 **/
Program(deqp::Context & context)2675 Program::Program(deqp::Context& context)
2676 : m_id(m_invalid_id)
2677 , m_compute(context)
2678 , m_fragment(context)
2679 , m_geometry(context)
2680 , m_tess_ctrl(context)
2681 , m_tess_eval(context)
2682 , m_vertex(context)
2683 , m_context(context)
2684 {
2685 /* Nothing to be done here */
2686 }
2687
2688 /** Destructor
2689 *
2690 **/
~Program()2691 Program::~Program()
2692 {
2693 Release();
2694 }
2695
2696 /** Initialize program instance
2697 *
2698 * @param compute_shader Compute shader source code
2699 * @param fragment_shader Fragment shader source code
2700 * @param geometry_shader Geometry shader source code
2701 * @param tessellation_control_shader Tessellation control shader source code
2702 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2703 * @param vertex_shader Vertex shader source code
2704 * @param captured_varyings Vector of variables to be captured with transfrom feedback
2705 * @param capture_interleaved Select mode of transform feedback (separate or interleaved)
2706 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2707 **/
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)2708 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2709 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2710 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2711 const NameVector& captured_varyings, bool capture_interleaved, bool is_separable)
2712 {
2713 /* Delete previous program */
2714 Release();
2715
2716 /* GL entry points */
2717 const Functions& gl = m_context.getRenderContext().getFunctions();
2718
2719 /* Initialize shaders */
2720 m_compute.Init(Shader::COMPUTE, compute_shader);
2721 m_fragment.Init(Shader::FRAGMENT, fragment_shader);
2722 m_geometry.Init(Shader::GEOMETRY, geometry_shader);
2723 m_tess_ctrl.Init(Shader::TESS_CTRL, tessellation_control_shader);
2724 m_tess_eval.Init(Shader::TESS_EVAL, tessellation_evaluation_shader);
2725 m_vertex.Init(Shader::VERTEX, vertex_shader);
2726
2727 /* Create program, set up transform feedback and attach shaders */
2728 Create(gl, m_id);
2729 Capture(gl, m_id, captured_varyings, capture_interleaved);
2730 Attach(gl, m_id, m_compute.m_id);
2731 Attach(gl, m_id, m_fragment.m_id);
2732 Attach(gl, m_id, m_geometry.m_id);
2733 Attach(gl, m_id, m_tess_ctrl.m_id);
2734 Attach(gl, m_id, m_tess_eval.m_id);
2735 Attach(gl, m_id, m_vertex.m_id);
2736
2737 /* Set separable parameter */
2738 if (true == is_separable)
2739 {
2740 gl.programParameteri(m_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2741 GLU_EXPECT_NO_ERROR(gl.getError(), "ProgramParameteri");
2742 }
2743
2744 try
2745 {
2746 /* Link program */
2747 Link(gl, m_id);
2748 }
2749 catch (const LinkageException& exc)
2750 {
2751 throw BuildException(exc.what(), compute_shader, fragment_shader, geometry_shader, tessellation_control_shader,
2752 tessellation_evaluation_shader, vertex_shader);
2753 }
2754 }
2755
2756 /** Initialize program instance
2757 *
2758 * @param compute_shader Compute shader source code
2759 * @param fragment_shader Fragment shader source code
2760 * @param geometry_shader Geometry shader source code
2761 * @param tessellation_control_shader Tessellation control shader source code
2762 * @param tessellation_evaluation_shader Tessellation evaluation shader source code
2763 * @param vertex_shader Vertex shader source code
2764 * @param is_separable Selects if monolithic or separable program should be built. Defaults to false
2765 **/
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)2766 void Program::Init(const std::string& compute_shader, const std::string& fragment_shader,
2767 const std::string& geometry_shader, const std::string& tessellation_control_shader,
2768 const std::string& tessellation_evaluation_shader, const std::string& vertex_shader,
2769 bool is_separable)
2770 {
2771 NameVector captured_varying;
2772
2773 Init(compute_shader, fragment_shader, geometry_shader, tessellation_control_shader, tessellation_evaluation_shader,
2774 vertex_shader, captured_varying, true, is_separable);
2775 }
2776
2777 /** Release program instance
2778 *
2779 **/
Release()2780 void Program::Release()
2781 {
2782 const Functions& gl = m_context.getRenderContext().getFunctions();
2783
2784 if (m_invalid_id != m_id)
2785 {
2786 Use(gl, m_invalid_id);
2787
2788 gl.deleteProgram(m_id);
2789 m_id = m_invalid_id;
2790 }
2791
2792 m_compute.Release();
2793 m_fragment.Release();
2794 m_geometry.Release();
2795 m_tess_ctrl.Release();
2796 m_tess_eval.Release();
2797 m_vertex.Release();
2798 }
2799
2800 /** Get <pname> for a set of active uniforms
2801 *
2802 * @param count Number of indices
2803 * @param indices Indices of uniforms
2804 * @param pname Queired pname
2805 * @param params Array that will be filled with values of parameters
2806 **/
GetActiveUniformsiv(GLsizei count,const GLuint * indices,GLenum pname,GLint * params) const2807 void Program::GetActiveUniformsiv(GLsizei count, const GLuint* indices, GLenum pname, GLint* params) const
2808 {
2809 const Functions& gl = m_context.getRenderContext().getFunctions();
2810
2811 GetActiveUniformsiv(gl, m_id, count, indices, pname, params);
2812 }
2813
2814 /** Get location of attribute
2815 *
2816 * @param name Name of attribute
2817 *
2818 * @return Result of query
2819 **/
GetAttribLocation(const std::string & name) const2820 glw::GLint Program::GetAttribLocation(const std::string& name) const
2821 {
2822 const Functions& gl = m_context.getRenderContext().getFunctions();
2823
2824 return GetAttribLocation(gl, m_id, name);
2825 }
2826
2827 /** Query resource
2828 *
2829 * @param interface Interface to be queried
2830 * @param index Index of resource
2831 * @param property Property to be queried
2832 * @param buf_size Size of <params> buffer
2833 * @param params Results of query
2834 **/
GetResource(GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params) const2835 void Program::GetResource(GLenum interface, GLuint index, GLenum property, GLsizei buf_size, GLint* params) const
2836 {
2837 const Functions& gl = m_context.getRenderContext().getFunctions();
2838
2839 GetResource(gl, m_id, interface, index, property, buf_size, params);
2840 }
2841
2842 /** Query for index of resource
2843 *
2844 * @param name Name of resource
2845 * @param interface Interface to be queried
2846 *
2847 * @return Result of query
2848 **/
GetResourceIndex(const std::string & name,GLenum interface) const2849 glw::GLuint Program::GetResourceIndex(const std::string& name, GLenum interface) const
2850 {
2851 const Functions& gl = m_context.getRenderContext().getFunctions();
2852
2853 return GetResourceIndex(gl, m_id, name, interface);
2854 }
2855
2856 /** Get indices for a set of uniforms
2857 *
2858 * @param count Count number of uniforms
2859 * @param names Names of uniforms
2860 * @param indices Buffer that will be filled with indices
2861 **/
GetUniformIndices(GLsizei count,const GLchar ** names,GLuint * indices) const2862 void Program::GetUniformIndices(GLsizei count, const GLchar** names, GLuint* indices) const
2863 {
2864 const Functions& gl = m_context.getRenderContext().getFunctions();
2865
2866 GetUniformIndices(gl, m_id, count, names, indices);
2867 }
2868
2869 /** Get uniform location
2870 *
2871 * @param name Name of uniform
2872 *
2873 * @return Results of query
2874 **/
GetUniformLocation(const std::string & name) const2875 glw::GLint Program::GetUniformLocation(const std::string& name) const
2876 {
2877 const Functions& gl = m_context.getRenderContext().getFunctions();
2878
2879 return GetUniformLocation(gl, m_id, name);
2880 }
2881
2882 /** Set program as active
2883 *
2884 **/
Use() const2885 void Program::Use() const
2886 {
2887 const Functions& gl = m_context.getRenderContext().getFunctions();
2888
2889 Use(gl, m_id);
2890 }
2891
2892 /** Attach shader to program
2893 *
2894 * @param gl GL functions
2895 * @param program_id Id of program
2896 * @param shader_id Id of shader
2897 **/
Attach(const Functions & gl,GLuint program_id,GLuint shader_id)2898 void Program::Attach(const Functions& gl, GLuint program_id, GLuint shader_id)
2899 {
2900 /* Sanity checks */
2901 if ((m_invalid_id == program_id) || (Shader::m_invalid_id == shader_id))
2902 {
2903 return;
2904 }
2905
2906 gl.attachShader(program_id, shader_id);
2907 GLU_EXPECT_NO_ERROR(gl.getError(), "AttachShader");
2908 }
2909
2910 /** Set up captured varyings
2911 *
2912 * @param gl GL functions
2913 * @param id Id of program
2914 * @param captured_varyings Vector of varyings
2915 * @param capture_interleaved Selects if interleaved or separate mode should be used
2916 **/
Capture(const Functions & gl,GLuint id,const NameVector & captured_varyings,bool capture_interleaved)2917 void Program::Capture(const Functions& gl, GLuint id, const NameVector& captured_varyings, bool capture_interleaved)
2918 {
2919 const size_t n_varyings = captured_varyings.size();
2920
2921 if (0 == n_varyings)
2922 {
2923 /* empty list, skip */
2924 return;
2925 }
2926
2927 std::vector<const GLchar*> varying_names;
2928 varying_names.resize(n_varyings);
2929
2930 for (size_t i = 0; i < n_varyings; ++i)
2931 {
2932 varying_names[i] = captured_varyings[i].c_str();
2933 }
2934
2935 GLenum mode = 0;
2936 if (true == capture_interleaved)
2937 {
2938 mode = GL_INTERLEAVED_ATTRIBS;
2939 }
2940 else
2941 {
2942 mode = GL_SEPARATE_ATTRIBS;
2943 }
2944
2945 gl.transformFeedbackVaryings(id, static_cast<GLsizei>(n_varyings), &varying_names[0], mode);
2946 GLU_EXPECT_NO_ERROR(gl.getError(), "TransformFeedbackVaryings");
2947 }
2948
2949 /** Create program instance
2950 *
2951 * @param gl GL functions
2952 * @param out_id Id of program
2953 **/
Create(const Functions & gl,GLuint & out_id)2954 void Program::Create(const Functions& gl, GLuint& out_id)
2955 {
2956 const GLuint id = gl.createProgram();
2957 GLU_EXPECT_NO_ERROR(gl.getError(), "CreateProgram");
2958
2959 if (m_invalid_id == id)
2960 {
2961 TCU_FAIL("Failed to create program");
2962 }
2963
2964 out_id = id;
2965 }
2966
2967 /** Get <pname> for a set of active uniforms
2968 *
2969 * @param gl Functions
2970 * @param program_id Id of program
2971 * @param count Number of indices
2972 * @param indices Indices of uniforms
2973 * @param pname Queired pname
2974 * @param params Array that will be filled with values of parameters
2975 **/
GetActiveUniformsiv(const Functions & gl,GLuint program_id,GLsizei count,const GLuint * indices,GLenum pname,GLint * params)2976 void Program::GetActiveUniformsiv(const Functions& gl, GLuint program_id, GLsizei count, const GLuint* indices,
2977 GLenum pname, GLint* params)
2978 {
2979 gl.getActiveUniformsiv(program_id, count, indices, pname, params);
2980 GLU_EXPECT_NO_ERROR(gl.getError(), "GetActiveUniformsiv");
2981 }
2982
2983 /** Get indices for a set of uniforms
2984 *
2985 * @param gl Functions
2986 * @param program_id Id of program
2987 * @param count Count number of uniforms
2988 * @param names Names of uniforms
2989 * @param indices Buffer that will be filled with indices
2990 **/
GetUniformIndices(const Functions & gl,GLuint program_id,GLsizei count,const GLchar ** names,GLuint * indices)2991 void Program::GetUniformIndices(const Functions& gl, GLuint program_id, GLsizei count, const GLchar** names,
2992 GLuint* indices)
2993 {
2994 gl.getUniformIndices(program_id, count, names, indices);
2995 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformIndices");
2996 }
2997
2998 /** Link program
2999 *
3000 * @param gl GL functions
3001 * @param id Id of program
3002 **/
Link(const Functions & gl,GLuint id)3003 void Program::Link(const Functions& gl, GLuint id)
3004 {
3005 GLint status = GL_FALSE;
3006
3007 gl.linkProgram(id);
3008 GLU_EXPECT_NO_ERROR(gl.getError(), "LinkProgram");
3009
3010 /* Get link status */
3011 gl.getProgramiv(id, GL_LINK_STATUS, &status);
3012 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
3013
3014 /* Log link error */
3015 if (GL_TRUE != status)
3016 {
3017 glw::GLint length = 0;
3018 std::string message;
3019
3020 /* Get error log length */
3021 gl.getProgramiv(id, GL_INFO_LOG_LENGTH, &length);
3022 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramiv");
3023
3024 message.resize(length, 0);
3025
3026 /* Get error log */
3027 gl.getProgramInfoLog(id, length, 0, &message[0]);
3028 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramInfoLog");
3029
3030 throw LinkageException(message.c_str());
3031 }
3032 }
3033
3034 /** Set generic uniform
3035 *
3036 * @param gl Functions
3037 * @param type Type of uniform
3038 * @param count Length of array
3039 * @param location Location of uniform
3040 * @param data Data that will be used
3041 **/
Uniform(const Functions & gl,const Type & type,GLsizei count,GLint location,const GLvoid * data)3042 void Program::Uniform(const Functions& gl, const Type& type, GLsizei count, GLint location, const GLvoid* data)
3043 {
3044 if (-1 == location)
3045 {
3046 TCU_FAIL("Uniform is inactive");
3047 }
3048
3049 switch (type.m_basic_type)
3050 {
3051 case Type::Double:
3052 if (1 == type.m_n_columns)
3053 {
3054 getUniformNdv(gl, type.m_n_rows)(location, count, (const GLdouble*)data);
3055 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNdv");
3056 }
3057 else
3058 {
3059 getUniformMatrixNdv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLdouble*)data);
3060 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNdv");
3061 }
3062 break;
3063 case Type::Float:
3064 if (1 == type.m_n_columns)
3065 {
3066 getUniformNfv(gl, type.m_n_rows)(location, count, (const GLfloat*)data);
3067 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNfv");
3068 }
3069 else
3070 {
3071 getUniformMatrixNfv(gl, type.m_n_columns, type.m_n_rows)(location, count, false, (const GLfloat*)data);
3072 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformMatrixNfv");
3073 }
3074 break;
3075 case Type::Int:
3076 getUniformNiv(gl, type.m_n_rows)(location, count, (const GLint*)data);
3077 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNiv");
3078 break;
3079 case Type::Uint:
3080 getUniformNuiv(gl, type.m_n_rows)(location, count, (const GLuint*)data);
3081 GLU_EXPECT_NO_ERROR(gl.getError(), "UniformNuiv");
3082 break;
3083 default:
3084 TCU_FAIL("Invalid enum");
3085 }
3086 }
3087
3088 /** Use program
3089 *
3090 * @param gl GL functions
3091 * @param id Id of program
3092 **/
Use(const Functions & gl,GLuint id)3093 void Program::Use(const Functions& gl, GLuint id)
3094 {
3095 gl.useProgram(id);
3096 GLU_EXPECT_NO_ERROR(gl.getError(), "UseProgram");
3097 }
3098
3099 /** Get location of attribute
3100 *
3101 * @param gl GL functions
3102 * @param id Id of program
3103 * @param name Name of attribute
3104 *
3105 * @return Location of attribute
3106 **/
GetAttribLocation(const Functions & gl,GLuint id,const std::string & name)3107 GLint Program::GetAttribLocation(const Functions& gl, GLuint id, const std::string& name)
3108 {
3109 GLint location = gl.getAttribLocation(id, name.c_str());
3110 GLU_EXPECT_NO_ERROR(gl.getError(), "GetAttribLocation");
3111
3112 return location;
3113 }
3114
3115 /** Query resource
3116 *
3117 * @param gl GL functions
3118 * @param id Id of program
3119 * @param interface Interface to be queried
3120 * @param index Index of resource
3121 * @param property Property to be queried
3122 * @param buf_size Size of <params> buffer
3123 * @param params Results of query
3124 **/
GetResource(const Functions & gl,GLuint id,GLenum interface,GLuint index,GLenum property,GLsizei buf_size,GLint * params)3125 void Program::GetResource(const Functions& gl, GLuint id, GLenum interface, GLuint index, GLenum property,
3126 GLsizei buf_size, GLint* params)
3127 {
3128 gl.getProgramResourceiv(id, interface, index, 1 /* propCount */, &property, buf_size /* bufSize */, 0 /* length */,
3129 params);
3130 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceiv");
3131 }
3132
3133 /** Get index of resource
3134 *
3135 * @param gl GL functions
3136 * @param id Id of program
3137 * @param name Name of resource
3138 * @param interface Program interface to queried
3139 *
3140 * @return Location of attribute
3141 **/
GetResourceIndex(const Functions & gl,GLuint id,const std::string & name,GLenum interface)3142 GLuint Program::GetResourceIndex(const Functions& gl, GLuint id, const std::string& name, GLenum interface)
3143 {
3144 GLuint index = gl.getProgramResourceIndex(id, interface, name.c_str());
3145 GLU_EXPECT_NO_ERROR(gl.getError(), "GetProgramResourceIndex");
3146
3147 return index;
3148 }
3149
3150 /** Get location of attribute
3151 *
3152 * @param gl GL functions
3153 * @param id Id of program
3154 * @param name Name of attribute
3155 *
3156 * @return Location of uniform
3157 **/
GetUniformLocation(const Functions & gl,GLuint id,const std::string & name)3158 GLint Program::GetUniformLocation(const Functions& gl, GLuint id, const std::string& name)
3159 {
3160 GLint location = gl.getUniformLocation(id, name.c_str());
3161 GLU_EXPECT_NO_ERROR(gl.getError(), "GetUniformLocation");
3162
3163 return location;
3164 }
3165
3166 /** Constructor
3167 *
3168 * @param error_message Error message
3169 * @param compute_shader Source code for compute stage
3170 * @param fragment_shader Source code for fragment stage
3171 * @param geometry_shader Source code for geometry stage
3172 * @param tess_ctrl_shader Source code for tessellation control stage
3173 * @param tess_eval_shader Source code for tessellation evaluation stage
3174 * @param vertex_shader Source code for vertex stage
3175 **/
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)3176 Program::BuildException::BuildException(const glw::GLchar* error_message, const std::string compute_shader,
3177 const std::string fragment_shader, const std::string geometry_shader,
3178 const std::string tess_ctrl_shader, const std::string tess_eval_shader,
3179 const std::string vertex_shader)
3180 : m_error_message(error_message)
3181 , m_compute_shader(compute_shader)
3182 , m_fragment_shader(fragment_shader)
3183 , m_geometry_shader(geometry_shader)
3184 , m_tess_ctrl_shader(tess_ctrl_shader)
3185 , m_tess_eval_shader(tess_eval_shader)
3186 , m_vertex_shader(vertex_shader)
3187 {
3188 }
3189
3190 /** Overwrites std::exception::what method
3191 *
3192 * @return Message compossed from error message and shader sources
3193 **/
what() const3194 const char* Program::BuildException::what() const throw()
3195 {
3196 return "Failed to link program";
3197 }
3198
3199 /** Logs error message and shader sources **/
log(deqp::Context & context) const3200 void Program::BuildException::log(deqp::Context& context) const
3201 {
3202 context.getTestContext().getLog() << tcu::TestLog::Message << "Link failure: " << m_error_message
3203 << tcu::TestLog::EndMessage;
3204
3205 Shader::LogSource(context, m_vertex_shader, Shader::VERTEX);
3206 Shader::LogSource(context, m_tess_ctrl_shader, Shader::TESS_CTRL);
3207 Shader::LogSource(context, m_tess_eval_shader, Shader::TESS_EVAL);
3208 Shader::LogSource(context, m_geometry_shader, Shader::GEOMETRY);
3209 Shader::LogSource(context, m_fragment_shader, Shader::FRAGMENT);
3210 Shader::LogSource(context, m_compute_shader, Shader::COMPUTE);
3211 }
3212
3213 /** Constructor
3214 *
3215 * @param message Linking error message
3216 **/
LinkageException(const glw::GLchar * message)3217 Program::LinkageException::LinkageException(const glw::GLchar* message) : m_error_message(message)
3218 {
3219 /* Nothing to be done */
3220 }
3221
3222 /** Returns error messages
3223 *
3224 * @return Linking error message
3225 **/
what() const3226 const char* Program::LinkageException::what() const throw()
3227 {
3228 return m_error_message.c_str();
3229 }
3230
3231 /* Texture constants */
3232 const GLuint Texture::m_invalid_id = -1;
3233
3234 /** Constructor.
3235 *
3236 * @param context CTS context.
3237 **/
Texture(deqp::Context & context)3238 Texture::Texture(deqp::Context& context) : m_id(m_invalid_id), m_context(context), m_type(TEX_2D)
3239 {
3240 /* Nothing to done here */
3241 }
3242
3243 /** Destructor
3244 *
3245 **/
~Texture()3246 Texture::~Texture()
3247 {
3248 Release();
3249 }
3250
3251 /** Initialize texture instance
3252 *
3253 * @param tex_type Type of texture
3254 * @param width Width of texture
3255 * @param height Height of texture
3256 * @param depth Depth of texture
3257 * @param internal_format Internal format of texture
3258 * @param format Format of texture data
3259 * @param type Type of texture data
3260 * @param data Texture data
3261 **/
Init(TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format,GLenum format,GLenum type,GLvoid * data)3262 void Texture::Init(TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum internal_format, GLenum format,
3263 GLenum type, GLvoid* data)
3264 {
3265 const Functions& gl = m_context.getRenderContext().getFunctions();
3266
3267 /* Delete previous texture */
3268 Release();
3269
3270 m_type = tex_type;
3271
3272 /* Generate, bind, allocate storage and upload data */
3273 Generate(gl, m_id);
3274 Bind(gl, m_id, tex_type);
3275 Storage(gl, tex_type, width, height, depth, internal_format);
3276 Update(gl, tex_type, width, height, depth, format, type, data);
3277 }
3278
3279 /** Initialize buffer texture
3280 *
3281 * @param internal_format Internal format of texture
3282 * @param buffer_id Id of buffer that will be used as data source
3283 **/
Init(GLenum internal_format,GLuint buffer_id)3284 void Texture::Init(GLenum internal_format, GLuint buffer_id)
3285 {
3286 const Functions& gl = m_context.getRenderContext().getFunctions();
3287
3288 /* Delete previous texture */
3289 Release();
3290
3291 m_type = TEX_BUFFER;
3292
3293 /* Generate, bind and attach buffer */
3294 Generate(gl, m_id);
3295 Bind(gl, m_id, TEX_BUFFER);
3296 TexBuffer(gl, buffer_id, internal_format);
3297 }
3298
3299 /** Release texture instance
3300 *
3301 **/
Release()3302 void Texture::Release()
3303 {
3304 if (m_invalid_id != m_id)
3305 {
3306 const Functions& gl = m_context.getRenderContext().getFunctions();
3307
3308 gl.deleteTextures(1, &m_id);
3309 m_id = m_invalid_id;
3310 }
3311 }
3312
3313 /** Bind texture to its target
3314 *
3315 **/
Bind() const3316 void Texture::Bind() const
3317 {
3318 const Functions& gl = m_context.getRenderContext().getFunctions();
3319
3320 Bind(gl, m_id, m_type);
3321 }
3322
3323 /** Get texture data
3324 *
3325 * @param format Format of data
3326 * @param type Type of data
3327 * @param out_data Buffer for data
3328 **/
Get(GLenum format,GLenum type,GLvoid * out_data) const3329 void Texture::Get(GLenum format, GLenum type, GLvoid* out_data) const
3330 {
3331 const Functions& gl = m_context.getRenderContext().getFunctions();
3332
3333 Bind(gl, m_id, m_type);
3334 Get(gl, m_type, format, type, out_data);
3335 }
3336
3337 /** Bind texture to target
3338 *
3339 * @param gl GL functions
3340 * @param id Id of texture
3341 * @param tex_type Type of texture
3342 **/
Bind(const Functions & gl,GLuint id,TYPES tex_type)3343 void Texture::Bind(const Functions& gl, GLuint id, TYPES tex_type)
3344 {
3345 GLenum target = GetTargetGLenum(tex_type);
3346
3347 gl.bindTexture(target, id);
3348 GLU_EXPECT_NO_ERROR(gl.getError(), "BindTexture");
3349 }
3350
3351 /** Generate texture instance
3352 *
3353 * @param gl GL functions
3354 * @param out_id Id of texture
3355 **/
Generate(const Functions & gl,GLuint & out_id)3356 void Texture::Generate(const Functions& gl, GLuint& out_id)
3357 {
3358 GLuint id = m_invalid_id;
3359
3360 gl.genTextures(1, &id);
3361 GLU_EXPECT_NO_ERROR(gl.getError(), "GenTextures");
3362
3363 if (m_invalid_id == id)
3364 {
3365 TCU_FAIL("Invalid id");
3366 }
3367
3368 out_id = id;
3369 }
3370
3371 /** Get texture data
3372 *
3373 * @param gl GL functions
3374 * @param format Format of data
3375 * @param type Type of data
3376 * @param out_data Buffer for data
3377 **/
Get(const Functions & gl,TYPES tex_type,GLenum format,GLenum type,GLvoid * out_data)3378 void Texture::Get(const Functions& gl, TYPES tex_type, GLenum format, GLenum type, GLvoid* out_data)
3379 {
3380 GLenum target = GetTargetGLenum(tex_type);
3381
3382 if (TEX_CUBE != tex_type)
3383 {
3384 gl.getTexImage(target, 0 /* level */, format, type, out_data);
3385 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3386 }
3387 else
3388 {
3389 GLint width;
3390 GLint height;
3391
3392 if ((GL_RGBA != format) && (GL_UNSIGNED_BYTE != type))
3393 {
3394 TCU_FAIL("Not implemented");
3395 }
3396
3397 GLuint texel_size = 4;
3398
3399 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_WIDTH, &width);
3400 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3401
3402 gl.getTexLevelParameteriv(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, GL_TEXTURE_HEIGHT, &height);
3403 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexLevelParameteriv");
3404
3405 const GLuint image_size = width * height * texel_size;
3406
3407 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0 /* level */, format, type,
3408 (GLvoid*)((GLchar*)out_data + (image_size * 0)));
3409 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0 /* level */, format, type,
3410 (GLvoid*)((GLchar*)out_data + (image_size * 1)));
3411 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0 /* level */, format, type,
3412 (GLvoid*)((GLchar*)out_data + (image_size * 2)));
3413 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0 /* level */, format, type,
3414 (GLvoid*)((GLchar*)out_data + (image_size * 3)));
3415 gl.getTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0 /* level */, format, type,
3416 (GLvoid*)((GLchar*)out_data + (image_size * 4)));
3417 gl.getTexImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0 /* level */, format, type,
3418 (GLvoid*)((GLchar*)out_data + (image_size * 5)));
3419 GLU_EXPECT_NO_ERROR(gl.getError(), "GetTexImage");
3420 }
3421 }
3422
3423 /** Allocate storage for texture
3424 *
3425 * @param gl GL functions
3426 * @param tex_type Type of texture
3427 * @param width Width of texture
3428 * @param height Height of texture
3429 * @param depth Depth of texture
3430 * @param internal_format Internal format of texture
3431 **/
Storage(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum internal_format)3432 void Texture::Storage(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth,
3433 GLenum internal_format)
3434 {
3435 static const GLuint levels = 1;
3436
3437 GLenum target = GetTargetGLenum(tex_type);
3438
3439 switch (tex_type)
3440 {
3441 case TEX_1D:
3442 gl.texStorage1D(target, levels, internal_format, width);
3443 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3444 break;
3445 case TEX_2D:
3446 case TEX_1D_ARRAY:
3447 case TEX_2D_RECT:
3448 case TEX_CUBE:
3449 gl.texStorage2D(target, levels, internal_format, width, height);
3450 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3451 break;
3452 case TEX_3D:
3453 case TEX_2D_ARRAY:
3454 gl.texStorage3D(target, levels, internal_format, width, height, depth);
3455 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3456 break;
3457 default:
3458 TCU_FAIL("Invalid enum");
3459 break;
3460 }
3461 }
3462
3463 /** Attach buffer as source of texture buffer data
3464 *
3465 * @param gl GL functions
3466 * @param internal_format Internal format of texture
3467 * @param buffer_id Id of buffer that will be used as data source
3468 **/
TexBuffer(const Functions & gl,GLenum internal_format,GLuint & buffer_id)3469 void Texture::TexBuffer(const Functions& gl, GLenum internal_format, GLuint& buffer_id)
3470 {
3471 gl.texBuffer(GL_TEXTURE_BUFFER, internal_format, buffer_id);
3472 GLU_EXPECT_NO_ERROR(gl.getError(), "TexBuffer");
3473 }
3474
3475 /** Update contents of texture
3476 *
3477 * @param gl GL functions
3478 * @param tex_type Type of texture
3479 * @param width Width of texture
3480 * @param height Height of texture
3481 * @param format Format of data
3482 * @param type Type of data
3483 * @param data Buffer with image data
3484 **/
Update(const Functions & gl,TYPES tex_type,GLuint width,GLuint height,GLuint depth,GLenum format,GLenum type,GLvoid * data)3485 void Texture::Update(const Functions& gl, TYPES tex_type, GLuint width, GLuint height, GLuint depth, GLenum format,
3486 GLenum type, GLvoid* data)
3487 {
3488 static const GLuint level = 0;
3489
3490 GLenum target = GetTargetGLenum(tex_type);
3491
3492 switch (tex_type)
3493 {
3494 case TEX_1D:
3495 gl.texSubImage1D(target, level, 0 /* x */, width, format, type, data);
3496 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage1D");
3497 break;
3498 case TEX_2D:
3499 case TEX_1D_ARRAY:
3500 case TEX_2D_RECT:
3501 gl.texSubImage2D(target, level, 0 /* x */, 0 /* y */, width, height, format, type, data);
3502 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3503 break;
3504 case TEX_CUBE:
3505 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3506 data);
3507 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, level, 0 /* x */, 0 /* y */, width, height, format, type,
3508 data);
3509 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3510 data);
3511 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, level, 0 /* x */, 0 /* y */, width, height, format, type,
3512 data);
3513 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3514 data);
3515 gl.texSubImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, level, 0 /* x */, 0 /* y */, width, height, format, type,
3516 data);
3517 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage2D");
3518 break;
3519 case TEX_3D:
3520 case TEX_2D_ARRAY:
3521 gl.texSubImage3D(target, level, 0 /* x */, 0 /* y */, 0 /* z */, width, height, depth, format, type, data);
3522 GLU_EXPECT_NO_ERROR(gl.getError(), "TexStorage3D");
3523 break;
3524 default:
3525 TCU_FAIL("Invalid enum");
3526 break;
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 break;
4074 }
4075
4076 if (BUILTIN != m_type)
4077 {
4078 if (0 == m_interface)
4079 {
4080 TCU_FAIL("Nullptr");
4081 }
4082 }
4083
4084 /* Qualifiers */
4085 if (true == m_qualifiers.empty())
4086 {
4087 replaceToken("QUALIFIERS ", position, "", definition);
4088 }
4089 else
4090 {
4091 replaceToken("QUALIFIERS", position, m_qualifiers.c_str(), definition);
4092 }
4093
4094 // According to spec: int, uint, and double type must always be declared with flat qualifier
4095 bool flat_qualifier = false;
4096 if (m_type != BUILTIN && m_interface != NULL)
4097 {
4098 if (m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Int ||
4099 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Uint ||
4100 m_interface->m_members[0].m_builtin.m_basic_type == Utils::Type::Double)
4101 {
4102 flat_qualifier = true;
4103 }
4104 }
4105 /* Storage */
4106 switch (storage)
4107 {
4108 case VARYING_INPUT:
4109 storage_str = flat_qualifier ? "flat in " : "in ";
4110 break;
4111 case VARYING_OUTPUT:
4112 storage_str = "out ";
4113 break;
4114 case UNIFORM:
4115 storage_str = "uniform ";
4116 break;
4117 case SSB:
4118 storage_str = "buffer ";
4119 break;
4120 case MEMBER:
4121 storage_str = "";
4122 break;
4123 default:
4124 TCU_FAIL("Invalid enum");
4125 break;
4126 }
4127
4128 replaceToken("STORAGE", position, storage_str, definition);
4129
4130 /* Type */
4131 if (BUILTIN == m_type)
4132 {
4133 replaceToken("TYPE", position, m_builtin.GetGLSLTypeName(), definition);
4134 }
4135 else
4136 {
4137 if (Interface::STRUCT == m_interface->m_type)
4138 {
4139 replaceToken("TYPE", position, m_interface->m_name.c_str(), definition);
4140 }
4141 else
4142 {
4143 const std::string& block_definition = m_interface->GetDefinition();
4144
4145 replaceToken("TYPE", position, block_definition.c_str(), definition);
4146 }
4147 }
4148
4149 /* Name */
4150 replaceToken("NAME", position, m_name.c_str(), definition);
4151
4152 /* Array size */
4153 if (0 == m_n_array_elements)
4154 {
4155 replaceToken("ARRAY", position, "", definition);
4156 }
4157 else
4158 {
4159 char buffer[16];
4160 sprintf(buffer, "[%d]", m_n_array_elements);
4161
4162 replaceToken("ARRAY", position, buffer, definition);
4163 }
4164
4165 /* Done */
4166 return definition;
4167 }
4168
4169 /** Get definitions for variables collected in vector
4170 *
4171 * @param vector Collection of variables
4172 * @param flavour Flavour of variables
4173 *
4174 * @return Code with definitions
4175 **/
GetDefinitions(const Variable::PtrVector & vector,Variable::FLAVOUR flavour)4176 std::string GetDefinitions(const Variable::PtrVector& vector, Variable::FLAVOUR flavour)
4177 {
4178 std::string list = Utils::g_list;
4179 size_t position = 0;
4180
4181 for (GLuint i = 0; i < vector.size(); ++i)
4182 {
4183 Utils::insertElementOfList(vector[i]->GetDefinition(flavour).c_str(), "\n", position, list);
4184 }
4185
4186 Utils::endList("", position, list);
4187
4188 return list;
4189 }
4190
4191 /** Get definitions for interfaces collected in vector
4192 *
4193 * @param vector Collection of interfaces
4194 *
4195 * @return Code with definitions
4196 **/
GetDefinitions(const Interface::PtrVector & vector)4197 std::string GetDefinitions(const Interface::PtrVector& vector)
4198 {
4199 std::string list = Utils::g_list;
4200 size_t position = 0;
4201
4202 for (GLuint i = 0; i < vector.size(); ++i)
4203 {
4204 Utils::insertElementOfList(vector[i]->GetDefinition().c_str(), "\n", position, list);
4205 }
4206
4207 Utils::endList("", position, list);
4208
4209 return list;
4210 }
4211
4212 /** Constructor
4213 *
4214 * @param name Name
4215 * @param type Type of interface
4216 **/
Interface(const GLchar * name,Interface::TYPE type)4217 Interface::Interface(const GLchar* name, Interface::TYPE type) : m_name(name), m_type(type)
4218 {
4219 }
4220
4221 /** Adds member to interface
4222 *
4223 * @param member Descriptor of new member
4224 *
4225 * @return Pointer to just created member
4226 **/
AddMember(const Variable::Descriptor & member)4227 Variable::Descriptor* Interface::AddMember(const Variable::Descriptor& member)
4228 {
4229 m_members.push_back(member);
4230
4231 return &m_members.back();
4232 }
4233
4234 /** Get definition of interface
4235 *
4236 * @param Code with definition
4237 **/
GetDefinition() const4238 std::string Interface::GetDefinition() const
4239 {
4240 std::string definition;
4241 size_t position = 0;
4242
4243 const GLchar* member_list = " MEMBER_DEFINITION\nMEMBER_LIST";
4244
4245 if (STRUCT == m_type)
4246 {
4247 definition = "struct NAME {\nMEMBER_LIST};";
4248 }
4249 else
4250 {
4251 definition = "NAME {\nMEMBER_LIST}";
4252 }
4253
4254 /* Name */
4255 replaceToken("NAME", position, m_name.c_str(), definition);
4256
4257 /* Member list */
4258 for (GLuint i = 0; i < m_members.size(); ++i)
4259 {
4260 const size_t start_position = position;
4261 const std::string& member_definition = m_members[i].GetDefinition(Variable::BASIC, Variable::MEMBER);
4262
4263 /* Member list */
4264 replaceToken("MEMBER_LIST", position, member_list, definition);
4265
4266 /* Move back position */
4267 position = start_position;
4268
4269 /* Member definition */
4270 replaceToken("MEMBER_DEFINITION", position, member_definition.c_str(), definition);
4271 }
4272
4273 /* Remove last member list */
4274 replaceToken("MEMBER_LIST", position, "", definition);
4275
4276 /* Done */
4277 return definition;
4278 }
4279
4280 /** Adds member of built-in type to interface
4281 *
4282 * @param name Name
4283 * @param qualifiers Qualifiers
4284 * @param expected_component Expected component of variable
4285 * @param expected_location Expected location
4286 * @param type Type
4287 * @param normalized Selects if data should be normalized
4288 * @param n_array_elements Length of array
4289 * @param expected_stride_of_element Expected stride of element
4290 * @param offset Offset
4291 *
4292 * @return Pointer to just created member
4293 **/
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)4294 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4295 GLint expected_location, const Type& type, GLboolean normalized,
4296 GLuint n_array_elements, GLint expected_stride_of_element, GLuint offset)
4297 {
4298 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, type, normalized,
4299 n_array_elements, expected_stride_of_element, offset));
4300 }
4301
4302 /** Adds member of interface type to interface
4303 *
4304 * @param name Name
4305 * @param qualifiers Qualifiers
4306 * @param expected_component Expected component of variable
4307 * @param expected_location Expected location
4308 * @param type Type
4309 * @param normalized Selects if data should be normalized
4310 * @param n_array_elements Length of array
4311 * @param expected_stride_of_element Expected stride of element
4312 * @param offset Offset
4313 *
4314 * @return Pointer to just created member
4315 **/
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)4316 Variable::Descriptor* Interface::Member(const GLchar* name, const GLchar* qualifiers, GLint expected_component,
4317 GLint expected_location, Interface* nterface, GLuint n_array_elements,
4318 GLint expected_stride_of_element, GLuint offset)
4319 {
4320 return AddMember(Variable::Descriptor(name, qualifiers, expected_component, expected_location, nterface,
4321 n_array_elements, expected_stride_of_element, offset));
4322 }
4323
4324 /** Clears contents of vector of pointers
4325 *
4326 * @tparam T Type of elements
4327 *
4328 * @param vector Collection to be cleared
4329 **/
4330 template <typename T>
clearPtrVector(std::vector<T * > & vector)4331 void clearPtrVector(std::vector<T*>& vector)
4332 {
4333 for (size_t i = 0; i < vector.size(); ++i)
4334 {
4335 T* t = vector[i];
4336
4337 vector[i] = 0;
4338
4339 if (0 != t)
4340 {
4341 delete t;
4342 }
4343 }
4344
4345 vector.clear();
4346 }
4347
4348 /** Constructor
4349 *
4350 * @param stage Stage described by that interface
4351 **/
ShaderInterface(Shader::STAGES stage)4352 ShaderInterface::ShaderInterface(Shader::STAGES stage) : m_stage(stage)
4353 {
4354 /* Nothing to be done */
4355 }
4356
4357 /** Get definitions of globals
4358 *
4359 * @return Code with definitions
4360 **/
GetDefinitionsGlobals() const4361 std::string ShaderInterface::GetDefinitionsGlobals() const
4362 {
4363 return m_globals;
4364 }
4365
4366 /** Get definitions of inputs
4367 *
4368 * @return Code with definitions
4369 **/
GetDefinitionsInputs() const4370 std::string ShaderInterface::GetDefinitionsInputs() const
4371 {
4372 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::INPUT);
4373
4374 return GetDefinitions(m_inputs, flavour);
4375 }
4376
4377 /** Get definitions of outputs
4378 *
4379 * @return Code with definitions
4380 **/
GetDefinitionsOutputs() const4381 std::string ShaderInterface::GetDefinitionsOutputs() const
4382 {
4383 Variable::FLAVOUR flavour = Variable::GetFlavour(m_stage, Variable::OUTPUT);
4384
4385 return GetDefinitions(m_outputs, flavour);
4386 }
4387
4388 /** Get definitions of buffers
4389 *
4390 * @return Code with definitions
4391 **/
GetDefinitionsSSBs() const4392 std::string ShaderInterface::GetDefinitionsSSBs() const
4393 {
4394 return GetDefinitions(m_ssb_blocks, Variable::BASIC);
4395 }
4396
4397 /** Get definitions of uniforms
4398 *
4399 * @return Code with definitions
4400 **/
GetDefinitionsUniforms() const4401 std::string ShaderInterface::GetDefinitionsUniforms() const
4402 {
4403 return GetDefinitions(m_uniforms, Variable::BASIC);
4404 }
4405
4406 /** Constructor
4407 *
4408 * @param in Input variable
4409 * @param out Output variable
4410 **/
VaryingConnection(Variable * in,Variable * out)4411 VaryingConnection::VaryingConnection(Variable* in, Variable* out) : m_in(in), m_out(out)
4412 {
4413 /* NBothing to be done here */
4414 }
4415
4416 /** Adds new varying connection to given stage
4417 *
4418 * @param stage Shader stage
4419 * @param in In varying
4420 * @param out Out varying
4421 **/
Add(Shader::STAGES stage,Variable * in,Variable * out)4422 void VaryingPassthrough::Add(Shader::STAGES stage, Variable* in, Variable* out)
4423 {
4424 VaryingConnection::Vector& vector = Get(stage);
4425
4426 vector.push_back(VaryingConnection(in, out));
4427 }
4428
4429 /** Get all passthrough connections for given stage
4430 *
4431 * @param stage Shader stage
4432 *
4433 * @return Vector of connections
4434 **/
Get(Shader::STAGES stage)4435 VaryingConnection::Vector& VaryingPassthrough::Get(Shader::STAGES stage)
4436 {
4437 VaryingConnection::Vector* result = 0;
4438
4439 switch (stage)
4440 {
4441 case Shader::FRAGMENT:
4442 result = &m_fragment;
4443 break;
4444 case Shader::GEOMETRY:
4445 result = &m_geometry;
4446 break;
4447 case Shader::TESS_CTRL:
4448 result = &m_tess_ctrl;
4449 break;
4450 case Shader::TESS_EVAL:
4451 result = &m_tess_eval;
4452 break;
4453 case Shader::VERTEX:
4454 result = &m_vertex;
4455 break;
4456 default:
4457 TCU_FAIL("Invalid enum");
4458 }
4459
4460 return *result;
4461 }
4462
4463 /** Constructor
4464 *
4465 **/
ProgramInterface()4466 ProgramInterface::ProgramInterface()
4467 : m_compute(Shader::COMPUTE)
4468 , m_vertex(Shader::VERTEX)
4469 , m_tess_ctrl(Shader::TESS_CTRL)
4470 , m_tess_eval(Shader::TESS_EVAL)
4471 , m_geometry(Shader::GEOMETRY)
4472 , m_fragment(Shader::FRAGMENT)
4473 {
4474 }
4475
4476 /** Destructor
4477 *
4478 **/
~ProgramInterface()4479 ProgramInterface::~ProgramInterface()
4480 {
4481 clearPtrVector(m_blocks);
4482 clearPtrVector(m_structures);
4483 }
4484
4485 /** Adds new interface
4486 *
4487 * @param name
4488 * @param type
4489 *
4490 * @return Pointer to created interface
4491 **/
AddInterface(const GLchar * name,Interface::TYPE type)4492 Interface* ProgramInterface::AddInterface(const GLchar* name, Interface::TYPE type)
4493 {
4494 Interface* interface = 0;
4495
4496 if (Interface::STRUCT == type)
4497 {
4498 interface = new Interface(name, type);
4499
4500 m_structures.push_back(interface);
4501 }
4502 else
4503 {
4504 interface = new Interface(name, type);
4505
4506 m_blocks.push_back(interface);
4507 }
4508
4509 return interface;
4510 }
4511
4512 /** Adds new block interface
4513 *
4514 * @param name
4515 *
4516 * @return Pointer to created interface
4517 **/
Block(const GLchar * name)4518 Interface* ProgramInterface::Block(const GLchar* name)
4519 {
4520 return AddInterface(name, Interface::BLOCK);
4521 }
4522
4523 /** Get interface of given shader stage
4524 *
4525 * @param stage Shader stage
4526 *
4527 * @return Reference to stage interface
4528 **/
GetShaderInterface(Shader::STAGES stage)4529 ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage)
4530 {
4531 ShaderInterface* interface = 0;
4532
4533 switch (stage)
4534 {
4535 case Shader::COMPUTE:
4536 interface = &m_compute;
4537 break;
4538 case Shader::FRAGMENT:
4539 interface = &m_fragment;
4540 break;
4541 case Shader::GEOMETRY:
4542 interface = &m_geometry;
4543 break;
4544 case Shader::TESS_CTRL:
4545 interface = &m_tess_ctrl;
4546 break;
4547 case Shader::TESS_EVAL:
4548 interface = &m_tess_eval;
4549 break;
4550 case Shader::VERTEX:
4551 interface = &m_vertex;
4552 break;
4553 default:
4554 TCU_FAIL("Invalid enum");
4555 }
4556
4557 return *interface;
4558 }
4559
4560 /** Get interface of given shader stage
4561 *
4562 * @param stage Shader stage
4563 *
4564 * @return Reference to stage interface
4565 **/
GetShaderInterface(Shader::STAGES stage) const4566 const ShaderInterface& ProgramInterface::GetShaderInterface(Shader::STAGES stage) const
4567 {
4568 const ShaderInterface* interface = 0;
4569
4570 switch (stage)
4571 {
4572 case Shader::COMPUTE:
4573 interface = &m_compute;
4574 break;
4575 case Shader::FRAGMENT:
4576 interface = &m_fragment;
4577 break;
4578 case Shader::GEOMETRY:
4579 interface = &m_geometry;
4580 break;
4581 case Shader::TESS_CTRL:
4582 interface = &m_tess_ctrl;
4583 break;
4584 case Shader::TESS_EVAL:
4585 interface = &m_tess_eval;
4586 break;
4587 case Shader::VERTEX:
4588 interface = &m_vertex;
4589 break;
4590 default:
4591 TCU_FAIL("Invalid enum");
4592 }
4593
4594 return *interface;
4595 }
4596
4597 /** Clone interface of Vertex shader stage to other stages
4598 * It creates matching inputs, outputs, uniforms and buffers in other stages.
4599 * There are no additional outputs for FRAGMENT shader generated.
4600 *
4601 * @param varying_passthrough Collection of varyings connections
4602 **/
CloneVertexInterface(VaryingPassthrough & varying_passthrough)4603 void ProgramInterface::CloneVertexInterface(VaryingPassthrough& varying_passthrough)
4604 {
4605 /* VS outputs >> TCS inputs >> TCS outputs >> .. >> FS inputs */
4606 for (size_t i = 0; i < m_vertex.m_outputs.size(); ++i)
4607 {
4608 const Variable& vs_var = *m_vertex.m_outputs[i];
4609 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4610
4611 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4612 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4613 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4614 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4615 }
4616
4617 /* Copy uniforms from VS to other stages */
4618 for (size_t i = 0; i < m_vertex.m_uniforms.size(); ++i)
4619 {
4620 Variable& vs_var = *m_vertex.m_uniforms[i];
4621 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4622
4623 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4624 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4625 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4626 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4627 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4628
4629 /* Uniform blocks needs unique binding */
4630 if (true == vs_var.IsBlock())
4631 {
4632 replaceBinding(vs_var, Shader::VERTEX);
4633 }
4634 }
4635
4636 /* Copy SSBs from VS to other stages */
4637 for (size_t i = 0; i < m_vertex.m_ssb_blocks.size(); ++i)
4638 {
4639 Variable& vs_var = *m_vertex.m_ssb_blocks[i];
4640 const GLchar* prefix = GetStagePrefix(Shader::VERTEX, vs_var.m_storage);
4641
4642 cloneVariableForStage(vs_var, Shader::COMPUTE, prefix, varying_passthrough);
4643 cloneVariableForStage(vs_var, Shader::TESS_CTRL, prefix, varying_passthrough);
4644 cloneVariableForStage(vs_var, Shader::TESS_EVAL, prefix, varying_passthrough);
4645 cloneVariableForStage(vs_var, Shader::GEOMETRY, prefix, varying_passthrough);
4646 cloneVariableForStage(vs_var, Shader::FRAGMENT, prefix, varying_passthrough);
4647
4648 /* SSBs blocks needs unique binding */
4649 if (true == vs_var.IsBlock())
4650 {
4651 replaceBinding(vs_var, Shader::VERTEX);
4652 }
4653 }
4654
4655 m_compute.m_globals = m_vertex.m_globals;
4656 m_fragment.m_globals = m_vertex.m_globals;
4657 m_geometry.m_globals = m_vertex.m_globals;
4658 m_tess_ctrl.m_globals = m_vertex.m_globals;
4659 m_tess_eval.m_globals = m_vertex.m_globals;
4660 }
4661
4662 /** Clone variable for specific stage
4663 *
4664 * @param variable Variable
4665 * @param stage Requested stage
4666 * @param prefix Prefix used in variable name that is specific for original stage
4667 * @param varying_passthrough Collection of varyings connections
4668 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,const GLchar * prefix,VaryingPassthrough & varying_passthrough)4669 void ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage, const GLchar* prefix,
4670 VaryingPassthrough& varying_passthrough)
4671 {
4672 switch (variable.m_storage)
4673 {
4674 case Variable::VARYING_OUTPUT:
4675 {
4676 Variable* in = cloneVariableForStage(variable, stage, Variable::VARYING_INPUT, prefix);
4677
4678 if (Shader::FRAGMENT != stage)
4679 {
4680 Variable* out = cloneVariableForStage(variable, stage, Variable::VARYING_OUTPUT, prefix);
4681 varying_passthrough.Add(stage, in, out);
4682 }
4683 }
4684 break;
4685 case Variable::UNIFORM:
4686 case Variable::SSB:
4687 cloneVariableForStage(variable, stage, variable.m_storage, prefix);
4688 break;
4689 default:
4690 TCU_FAIL("Invalid enum");
4691 break;
4692 }
4693 }
4694
4695 /** Clone variable for specific stage
4696 *
4697 * @param variable Variable
4698 * @param stage Requested stage
4699 * @param storage Storage used by variable
4700 * @param prefix Prefix used in variable name that is specific for original stage
4701 *
4702 * @return New variable
4703 **/
cloneVariableForStage(const Variable & variable,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4704 Variable* ProgramInterface::cloneVariableForStage(const Variable& variable, Shader::STAGES stage,
4705 Variable::STORAGE storage, const GLchar* prefix)
4706 {
4707 /* Initialize with original variable */
4708 Variable* var = new Variable(variable);
4709 if (0 == var)
4710 {
4711 TCU_FAIL("Memory allocation");
4712 }
4713
4714 /* Set up storage */
4715 var->m_storage = storage;
4716
4717 /* Get name */
4718 std::string name = variable.m_descriptor.m_name;
4719
4720 /* Prefix name with stage ID, empty means default block */
4721 if (false == name.empty())
4722 {
4723 size_t position = 0;
4724 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4725 Utils::replaceToken(prefix, position, stage_prefix, name);
4726 }
4727 var->m_descriptor.m_name = name;
4728
4729 /* Clone block */
4730 const bool is_block = variable.IsBlock();
4731 if (true == is_block)
4732 {
4733 const Interface* interface = variable.m_descriptor.m_interface;
4734
4735 Interface* block = CloneBlockForStage(*interface, stage, storage, prefix);
4736
4737 var->m_descriptor.m_interface = block;
4738 }
4739
4740 /* Store variable */
4741 ShaderInterface& si = GetShaderInterface(stage);
4742 Variable* result = 0;
4743
4744 switch (storage)
4745 {
4746 case Variable::VARYING_INPUT:
4747 si.m_inputs.push_back(var);
4748 result = si.m_inputs.back();
4749 break;
4750 case Variable::VARYING_OUTPUT:
4751 si.m_outputs.push_back(var);
4752 result = si.m_outputs.back();
4753 break;
4754 case Variable::UNIFORM:
4755 /* Uniform blocks needs unique binding */
4756 if (true == is_block)
4757 {
4758 replaceBinding(*var, stage);
4759 }
4760
4761 si.m_uniforms.push_back(var);
4762 result = si.m_uniforms.back();
4763 break;
4764 case Variable::SSB:
4765 /* SSBs needs unique binding */
4766 if (true == is_block)
4767 {
4768 replaceBinding(*var, stage);
4769 }
4770
4771 si.m_ssb_blocks.push_back(var);
4772 result = si.m_ssb_blocks.back();
4773 break;
4774 default:
4775 TCU_FAIL("Invalid enum");
4776 break;
4777 }
4778
4779 return result;
4780 }
4781
4782 /** clone block to specific stage
4783 *
4784 * @param block Block to be copied
4785 * @param stage Specific stage
4786 * @param storage Storage used by block
4787 * @param prefix Prefix used in block name
4788 *
4789 * @return New interface
4790 **/
CloneBlockForStage(const Interface & block,Shader::STAGES stage,Variable::STORAGE storage,const GLchar * prefix)4791 Interface* ProgramInterface::CloneBlockForStage(const Interface& block, Shader::STAGES stage, Variable::STORAGE storage,
4792 const GLchar* prefix)
4793 {
4794 /* Get name */
4795 std::string name = block.m_name;
4796
4797 /* Prefix name with stage ID */
4798 size_t position = 0;
4799 const GLchar* stage_prefix = GetStagePrefix(stage, storage);
4800 Utils::replaceToken(prefix, position, stage_prefix, name);
4801
4802 Interface* ptr = GetBlock(name.c_str());
4803
4804 if (0 == ptr)
4805 {
4806 ptr = AddInterface(name.c_str(), Interface::BLOCK);
4807 }
4808
4809 ptr->m_members = block.m_members;
4810
4811 return ptr;
4812 }
4813
4814 /** Get stage specific prefix used in names
4815 *
4816 * @param stage Stage
4817 * @param storage Storage class
4818 *
4819 * @return String
4820 **/
GetStagePrefix(Shader::STAGES stage,Variable::STORAGE storage)4821 const GLchar* ProgramInterface::GetStagePrefix(Shader::STAGES stage, Variable::STORAGE storage)
4822 {
4823 static const GLchar* lut[Shader::STAGE_MAX][Variable::STORAGE_MAX] = {
4824 /* IN OUT UNIFORM SSB MEMBER */
4825 /* CS */ { 0, 0, "cs_uni_", "cs_buf_", "" },
4826 /* VS */ { "in_vs_", "vs_tcs_", "vs_uni_", "vs_buf_", "" },
4827 /* TCS */ { "vs_tcs_", "tcs_tes_", "tcs_uni_", "tcs_buf_", "" },
4828 /* TES */ { "tcs_tes_", "tes_gs_", "tes_uni_", "tes_buf_", "" },
4829 /* GS */ { "tes_gs_", "gs_fs_", "gs_uni_", "gs_buf_", "" },
4830 /* FS */ { "gs_fs_", "fs_out_", "fs_uni_", "fs_buf_", "" },
4831 };
4832
4833 const GLchar* result = 0;
4834
4835 result = lut[stage][storage];
4836
4837 return result;
4838 }
4839
4840 /** Get definitions of all structures used in program interface
4841 *
4842 * @return String with code
4843 **/
GetDefinitionsStructures() const4844 std::string ProgramInterface::GetDefinitionsStructures() const
4845 {
4846 return GetDefinitions(m_structures);
4847 }
4848
4849 /** Get interface code for stage
4850 *
4851 * @param stage Specific stage
4852 *
4853 * @return String with code
4854 **/
GetInterfaceForStage(Shader::STAGES stage) const4855 std::string ProgramInterface::GetInterfaceForStage(Shader::STAGES stage) const
4856 {
4857 size_t position = 0;
4858 std::string interface = "/* Globals */\n"
4859 "GLOBALS\n"
4860 "\n"
4861 "/* Structures */\n"
4862 "STRUCTURES\n"
4863 "\n"
4864 "/* Uniforms */\n"
4865 "UNIFORMS\n"
4866 "\n"
4867 "/* Inputs */\n"
4868 "INPUTS\n"
4869 "\n"
4870 "/* Outputs */\n"
4871 "OUTPUTS\n"
4872 "\n"
4873 "/* Storage */\n"
4874 "STORAGE\n";
4875
4876 const ShaderInterface& si = GetShaderInterface(stage);
4877
4878 const std::string& structures = GetDefinitionsStructures();
4879
4880 const std::string& globals = si.GetDefinitionsGlobals();
4881 const std::string& inputs = si.GetDefinitionsInputs();
4882 const std::string& outputs = si.GetDefinitionsOutputs();
4883 const std::string& uniforms = si.GetDefinitionsUniforms();
4884 const std::string& ssbs = si.GetDefinitionsSSBs();
4885
4886 replaceToken("GLOBALS", position, globals.c_str(), interface);
4887 replaceToken("STRUCTURES", position, structures.c_str(), interface);
4888 replaceToken("UNIFORMS", position, uniforms.c_str(), interface);
4889 replaceToken("INPUTS", position, inputs.c_str(), interface);
4890 replaceToken("OUTPUTS", position, outputs.c_str(), interface);
4891 replaceToken("STORAGE", position, ssbs.c_str(), interface);
4892
4893 return interface;
4894 }
4895
4896 /** Functional object used in find_if algorithm, in search for interface of given name
4897 *
4898 **/
4899 struct matchInterfaceName
4900 {
matchInterfaceNamegl4cts::EnhancedLayouts::Utils::matchInterfaceName4901 matchInterfaceName(const GLchar* name) : m_name(name)
4902 {
4903 }
4904
operator ()gl4cts::EnhancedLayouts::Utils::matchInterfaceName4905 bool operator()(const Interface* interface)
4906 {
4907 return 0 == interface->m_name.compare(m_name);
4908 }
4909
4910 const GLchar* m_name;
4911 };
4912
4913 /** Finds interface of given name in given vector of interfaces
4914 *
4915 * @param vector Collection of interfaces
4916 * @param name Requested name
4917 *
4918 * @return Pointer to interface if available, 0 otherwise
4919 **/
findInterfaceByName(Interface::PtrVector & vector,const GLchar * name)4920 static Interface* findInterfaceByName(Interface::PtrVector& vector, const GLchar* name)
4921 {
4922 Interface::PtrVector::iterator it = std::find_if(vector.begin(), vector.end(), matchInterfaceName(name));
4923
4924 if (vector.end() != it)
4925 {
4926 return *it;
4927 }
4928 else
4929 {
4930 return 0;
4931 }
4932 }
4933
4934 /** Search for block of given name
4935 *
4936 * @param name Name of block
4937 *
4938 * @return Pointer to block or 0
4939 **/
GetBlock(const GLchar * name)4940 Interface* ProgramInterface::GetBlock(const GLchar* name)
4941 {
4942 return findInterfaceByName(m_blocks, name);
4943 }
4944
4945 /** Search for structure of given name
4946 *
4947 * @param name Name of structure
4948 *
4949 * @return Pointer to structure or 0
4950 **/
GetStructure(const GLchar * name)4951 Interface* ProgramInterface::GetStructure(const GLchar* name)
4952 {
4953 return findInterfaceByName(m_structures, name);
4954 }
4955
4956 /** Adds new sturcture to interface
4957 *
4958 * @param name Name of structure
4959 *
4960 * @return Created structure
4961 **/
Structure(const GLchar * name)4962 Interface* ProgramInterface::Structure(const GLchar* name)
4963 {
4964 return AddInterface(name, Interface::STRUCT);
4965 }
4966
4967 /** Replace "BINDING" token in qualifiers string to value specific for given stage
4968 *
4969 * @param variable Variable to modify
4970 * @param stage Requested stage
4971 **/
replaceBinding(Variable & variable,Shader::STAGES stage)4972 void ProgramInterface::replaceBinding(Variable& variable, Shader::STAGES stage)
4973 {
4974 GLchar binding[16];
4975 sprintf(binding, "%d", stage);
4976 replaceAllTokens("BINDING", binding, variable.m_descriptor.m_qualifiers);
4977 }
4978 } /* Utils namespace */
4979
4980 /** Debuging procedure. Logs parameters.
4981 *
4982 * @param source As specified in GL spec.
4983 * @param type As specified in GL spec.
4984 * @param id As specified in GL spec.
4985 * @param severity As specified in GL spec.
4986 * @param ignored
4987 * @param message As specified in GL spec.
4988 * @param info Pointer to instance of Context used by test.
4989 */
debug_proc(GLenum source,GLenum type,GLuint id,GLenum severity,GLsizei,const GLchar * message,void * info)4990 void GLW_APIENTRY debug_proc(GLenum source, GLenum type, GLuint id, GLenum severity, GLsizei /* length */,
4991 const GLchar* message, void* info)
4992 {
4993 deqp::Context* ctx = (deqp::Context*)info;
4994
4995 const GLchar* source_str = "Unknown";
4996 const GLchar* type_str = "Unknown";
4997 const GLchar* severity_str = "Unknown";
4998
4999 switch (source)
5000 {
5001 case GL_DEBUG_SOURCE_API:
5002 source_str = "API";
5003 break;
5004 case GL_DEBUG_SOURCE_APPLICATION:
5005 source_str = "APP";
5006 break;
5007 case GL_DEBUG_SOURCE_OTHER:
5008 source_str = "OTR";
5009 break;
5010 case GL_DEBUG_SOURCE_SHADER_COMPILER:
5011 source_str = "COM";
5012 break;
5013 case GL_DEBUG_SOURCE_THIRD_PARTY:
5014 source_str = "3RD";
5015 break;
5016 case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
5017 source_str = "WS";
5018 break;
5019 default:
5020 break;
5021 }
5022
5023 switch (type)
5024 {
5025 case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
5026 type_str = "DEPRECATED_BEHAVIOR";
5027 break;
5028 case GL_DEBUG_TYPE_ERROR:
5029 type_str = "ERROR";
5030 break;
5031 case GL_DEBUG_TYPE_MARKER:
5032 type_str = "MARKER";
5033 break;
5034 case GL_DEBUG_TYPE_OTHER:
5035 type_str = "OTHER";
5036 break;
5037 case GL_DEBUG_TYPE_PERFORMANCE:
5038 type_str = "PERFORMANCE";
5039 break;
5040 case GL_DEBUG_TYPE_POP_GROUP:
5041 type_str = "POP_GROUP";
5042 break;
5043 case GL_DEBUG_TYPE_PORTABILITY:
5044 type_str = "PORTABILITY";
5045 break;
5046 case GL_DEBUG_TYPE_PUSH_GROUP:
5047 type_str = "PUSH_GROUP";
5048 break;
5049 case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
5050 type_str = "UNDEFINED_BEHAVIOR";
5051 break;
5052 default:
5053 break;
5054 }
5055
5056 switch (severity)
5057 {
5058 case GL_DEBUG_SEVERITY_HIGH:
5059 severity_str = "H";
5060 break;
5061 case GL_DEBUG_SEVERITY_LOW:
5062 severity_str = "L";
5063 break;
5064 case GL_DEBUG_SEVERITY_MEDIUM:
5065 severity_str = "M";
5066 break;
5067 case GL_DEBUG_SEVERITY_NOTIFICATION:
5068 severity_str = "N";
5069 break;
5070 default:
5071 break;
5072 }
5073
5074 ctx->getTestContext().getLog() << tcu::TestLog::Message << "DEBUG_INFO: " << std::setw(3) << source_str << "|"
5075 << severity_str << "|" << std::setw(18) << type_str << "|" << std::setw(12) << id
5076 << ": " << message << tcu::TestLog::EndMessage;
5077 }
5078
5079 /** Constructor
5080 *
5081 * @param context Test context
5082 * @param test_name Test name
5083 * @param test_description Test description
5084 **/
TestBase(deqp::Context & context,const GLchar * test_name,const GLchar * test_description)5085 TestBase::TestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5086 : TestCase(context, test_name, test_description)
5087 {
5088 /* Nothing to be done here */
5089 }
5090
5091 /** Execute test
5092 *
5093 * @return tcu::TestNode::STOP otherwise
5094 **/
iterate()5095 tcu::TestNode::IterateResult TestBase::iterate()
5096 {
5097 bool test_result;
5098
5099 #if DEBUG_ENBALE_MESSAGE_CALLBACK
5100 const Functions& gl = m_context.getRenderContext().getFunctions();
5101
5102 gl.debugMessageCallback(debug_proc, &m_context);
5103 GLU_EXPECT_NO_ERROR(gl.getError(), "DebugMessageCallback");
5104 #endif /* DEBUG_ENBALE_MESSAGE_CALLBACK */
5105
5106 try
5107 {
5108 /* Execute test */
5109 test_result = test();
5110 }
5111 catch (std::exception& exc)
5112 {
5113 TCU_FAIL(exc.what());
5114 }
5115
5116 /* Set result */
5117 if (true == test_result)
5118 {
5119 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
5120 }
5121 else
5122 {
5123 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5124 }
5125
5126 /* Done */
5127 return tcu::TestNode::STOP;
5128 }
5129
5130 /** Get last input location available for given type at specific stage
5131 *
5132 * @param stage Shader stage
5133 * @param type Input type
5134 * @param array_length Length of input array
5135 *
5136 * @return Last location index
5137 **/
getLastInputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_prev_stage)5138 GLint TestBase::getLastInputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_prev_stage)
5139 {
5140 GLint divide = 4; /* 4 components per location */
5141 GLint param = 0;
5142 GLenum pname = 0;
5143 GLint paramPrev = 0;
5144 GLenum pnamePrev = 0;
5145
5146 /* Select pnmae */
5147 switch (stage)
5148 {
5149 case Utils::Shader::FRAGMENT:
5150 pname = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5151 pnamePrev = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5152 break;
5153 case Utils::Shader::GEOMETRY:
5154 pname = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5155 pnamePrev = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5156 break;
5157 case Utils::Shader::TESS_CTRL:
5158 pname = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5159 pnamePrev = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5160 break;
5161 case Utils::Shader::TESS_EVAL:
5162 pname = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5163 pnamePrev = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5164 break;
5165 case Utils::Shader::VERTEX:
5166 pname = GL_MAX_VERTEX_ATTRIBS;
5167 divide = 1;
5168 break;
5169 default:
5170 TCU_FAIL("Invalid enum");
5171 break;
5172 }
5173
5174 /* Zero means no array, but 1 slot is required */
5175 if (0 == array_length)
5176 {
5177 array_length += 1;
5178 }
5179
5180 /* Get MAX */
5181 const Functions& gl = m_context.getRenderContext().getFunctions();
5182
5183 gl.getIntegerv(pname, ¶m);
5184 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5185
5186 if (pnamePrev && !ignore_prev_stage) {
5187 gl.getIntegerv(pnamePrev, ¶mPrev);
5188 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5189
5190 /* Don't read from a location that doesn't exist in the previous stage */
5191 param = de::min(param, paramPrev);
5192 }
5193
5194 /* Calculate */
5195 #if WRKARD_VARYINGLOCATIONSTEST
5196
5197 const GLint n_avl_locations = 16;
5198
5199 #else
5200
5201 const GLint n_avl_locations = param / divide;
5202
5203 #endif
5204
5205 const GLuint n_req_location = type.GetLocations(stage == Utils::Shader::VERTEX) * array_length;
5206
5207 return n_avl_locations - n_req_location; /* last is max - 1 */
5208 }
5209
5210 /** Get last output location available for given type at specific stage
5211 *
5212 * @param stage Shader stage
5213 * @param type Input type
5214 * @param array_length Length of input array
5215 *
5216 * @return Last location index
5217 **/
getLastOutputLocation(Utils::Shader::STAGES stage,const Utils::Type & type,GLuint array_length,bool ignore_next_stage)5218 GLint TestBase::getLastOutputLocation(Utils::Shader::STAGES stage, const Utils::Type& type, GLuint array_length, bool ignore_next_stage)
5219 {
5220 GLint param = 0;
5221 GLenum pname = 0;
5222 GLint paramNext = 0;
5223 GLenum pnameNext = 0;
5224
5225 /* Select pname */
5226 switch (stage)
5227 {
5228 case Utils::Shader::GEOMETRY:
5229 pname = GL_MAX_GEOMETRY_OUTPUT_COMPONENTS;
5230 pnameNext = GL_MAX_FRAGMENT_INPUT_COMPONENTS;
5231 break;
5232 case Utils::Shader::TESS_CTRL:
5233 pname = GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS;
5234 pnameNext = GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS;
5235 break;
5236 case Utils::Shader::TESS_EVAL:
5237 pname = GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS;
5238 pnameNext = GL_MAX_GEOMETRY_INPUT_COMPONENTS;
5239 break;
5240 case Utils::Shader::VERTEX:
5241 pname = GL_MAX_VERTEX_OUTPUT_COMPONENTS;
5242 pnameNext = GL_MAX_TESS_CONTROL_INPUT_COMPONENTS;
5243 break;
5244 default:
5245 TCU_FAIL("Invalid enum");
5246 break;
5247 }
5248
5249 /* Zero means no array, but 1 slot is required */
5250 if (0 == array_length)
5251 {
5252 array_length += 1;
5253 }
5254
5255 /* Get MAX */
5256 const Functions& gl = m_context.getRenderContext().getFunctions();
5257
5258 gl.getIntegerv(pname, ¶m);
5259 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5260
5261 /* Calculate */
5262 #if WRKARD_VARYINGLOCATIONSTEST
5263
5264 const GLint n_avl_locations = 16;
5265
5266 #else
5267
5268 /* Don't write to a location that doesn't exist in the next stage */
5269 if (!ignore_next_stage)
5270 {
5271 gl.getIntegerv(pnameNext, ¶mNext);
5272 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5273
5274 param = de::min(param, paramNext);
5275 }
5276
5277 const GLint n_avl_locations = param / 4; /* 4 components per location */
5278
5279 #endif
5280
5281 const GLuint n_req_location = type.GetLocations() * array_length;
5282
5283 return n_avl_locations - n_req_location; /* last is max - 1 */
5284 }
5285
5286 /** Basic implementation
5287 *
5288 * @param ignored
5289 *
5290 * @return Empty string
5291 **/
getTestCaseName(GLuint)5292 std::string TestBase::getTestCaseName(GLuint /* test_case_index */)
5293 {
5294 std::string result;
5295
5296 return result;
5297 }
5298
5299 /** Basic implementation
5300 *
5301 * @return 1
5302 **/
getTestCaseNumber()5303 GLuint TestBase::getTestCaseNumber()
5304 {
5305 return 1;
5306 }
5307
5308 /** Check if flat qualifier is required for given type, stage and storage
5309 *
5310 * @param stage Shader stage
5311 * @param type Input type
5312 * @param storage Storage of variable
5313 *
5314 * @return Last location index
5315 **/
isFlatRequired(Utils::Shader::STAGES stage,const Utils::Type & type,Utils::Variable::STORAGE storage,const bool coherent) const5316 bool TestBase::isFlatRequired(Utils::Shader::STAGES stage, const Utils::Type& type, Utils::Variable::STORAGE storage,
5317 const bool coherent) const
5318 {
5319 /* Float types do not need flat at all */
5320 if (Utils::Type::Float == type.m_basic_type)
5321 {
5322 return false;
5323 }
5324
5325 /* Inputs to fragment shader */
5326 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Variable::VARYING_INPUT == storage))
5327 {
5328 return true;
5329 }
5330
5331 /* Outputs from geometry shader
5332 *
5333 * This is not strictly needed since fragment shader input
5334 * interpolation qualifiers will override whatever comes from the
5335 * previous stage. However, if we want to have a coherent
5336 * interface, let's better do it.
5337 */
5338 if ((Utils::Shader::GEOMETRY == stage) && (Utils::Variable::VARYING_OUTPUT == storage) && coherent)
5339 {
5340 return true;
5341 }
5342
5343 return false;
5344 }
5345
5346 /** Basic implementation of testInit method
5347 *
5348 **/
testInit()5349 void TestBase::testInit()
5350 {
5351 }
5352
5353 /** Calculate stride for interface
5354 *
5355 * @param interface Interface
5356 *
5357 * @return Calculated value
5358 **/
calculateStride(const Utils::Interface & interface) const5359 GLuint TestBase::calculateStride(const Utils::Interface& interface) const
5360 {
5361 const size_t n_members = interface.m_members.size();
5362
5363 GLuint stride = 0;
5364
5365 for (size_t i = 0; i < n_members; ++i)
5366 {
5367 const Utils::Variable::Descriptor& member = interface.m_members[i];
5368 const GLuint member_offset = member.m_offset;
5369 const GLuint member_stride = member.m_expected_stride_of_element;
5370 const GLuint member_ends_at = member_offset + member_stride;
5371
5372 stride = std::max(stride, member_ends_at);
5373 }
5374
5375 return stride;
5376 }
5377
5378 /** Generate data for interface. This routine is recursive
5379 *
5380 * @param interface Interface
5381 * @param offset Offset in out_data
5382 * @param out_data Buffer to be filled
5383 **/
generateData(const Utils::Interface & interface,GLuint offset,std::vector<GLubyte> & out_data) const5384 void TestBase::generateData(const Utils::Interface& interface, GLuint offset, std::vector<GLubyte>& out_data) const
5385 {
5386 const size_t n_members = interface.m_members.size();
5387 GLubyte* ptr = &out_data[offset];
5388
5389 for (size_t i = 0; i < n_members; ++i)
5390 {
5391 const Utils::Variable::Descriptor& member = interface.m_members[i];
5392 const GLuint member_offset = member.m_offset;
5393 const GLuint n_elements = (0 == member.m_n_array_elements) ? 1 : member.m_n_array_elements;
5394
5395 for (GLuint element = 0; element < n_elements; ++element)
5396 {
5397 const GLuint element_offset = element * member.m_expected_stride_of_element;
5398 const GLuint data_offfset = member_offset + element_offset;
5399
5400 if (Utils::Variable::BUILTIN == member.m_type)
5401 {
5402 const std::vector<GLubyte>& data = member.m_builtin.GenerateData();
5403
5404 memcpy(ptr + data_offfset, &data[0], data.size());
5405 }
5406 else
5407 {
5408 generateData(*member.m_interface, offset + data_offfset, out_data);
5409 }
5410 }
5411 }
5412 }
5413
5414 /** Get type at index
5415 *
5416 * @param index Index of requested type
5417 *
5418 * @return Type
5419 **/
getType(GLuint index) const5420 Utils::Type TestBase::getType(GLuint index) const
5421 {
5422 Utils::Type type;
5423
5424 switch (index)
5425 {
5426 case 0:
5427 type = Utils::Type::_double;
5428 break;
5429 case 1:
5430 type = Utils::Type::dmat2;
5431 break;
5432 case 2:
5433 type = Utils::Type::dmat2x3;
5434 break;
5435 case 3:
5436 type = Utils::Type::dmat2x4;
5437 break;
5438 case 4:
5439 type = Utils::Type::dmat3;
5440 break;
5441 case 5:
5442 type = Utils::Type::dmat3x2;
5443 break;
5444 case 6:
5445 type = Utils::Type::dmat3x4;
5446 break;
5447 case 7:
5448 type = Utils::Type::dmat4;
5449 break;
5450 case 8:
5451 type = Utils::Type::dmat4x2;
5452 break;
5453 case 9:
5454 type = Utils::Type::dmat4x3;
5455 break;
5456 case 10:
5457 type = Utils::Type::dvec2;
5458 break;
5459 case 11:
5460 type = Utils::Type::dvec3;
5461 break;
5462 case 12:
5463 type = Utils::Type::dvec4;
5464 break;
5465 case 13:
5466 type = Utils::Type::_float;
5467 break;
5468 case 14:
5469 type = Utils::Type::mat2;
5470 break;
5471 case 15:
5472 type = Utils::Type::mat2x3;
5473 break;
5474 case 16:
5475 type = Utils::Type::mat2x4;
5476 break;
5477 case 17:
5478 type = Utils::Type::mat3;
5479 break;
5480 case 18:
5481 type = Utils::Type::mat3x2;
5482 break;
5483 case 19:
5484 type = Utils::Type::mat3x4;
5485 break;
5486 case 20:
5487 type = Utils::Type::mat4;
5488 break;
5489 case 21:
5490 type = Utils::Type::mat4x2;
5491 break;
5492 case 22:
5493 type = Utils::Type::mat4x3;
5494 break;
5495 case 23:
5496 type = Utils::Type::vec2;
5497 break;
5498 case 24:
5499 type = Utils::Type::vec3;
5500 break;
5501 case 25:
5502 type = Utils::Type::vec4;
5503 break;
5504 case 26:
5505 type = Utils::Type::_int;
5506 break;
5507 case 27:
5508 type = Utils::Type::ivec2;
5509 break;
5510 case 28:
5511 type = Utils::Type::ivec3;
5512 break;
5513 case 29:
5514 type = Utils::Type::ivec4;
5515 break;
5516 case 30:
5517 type = Utils::Type::uint;
5518 break;
5519 case 31:
5520 type = Utils::Type::uvec2;
5521 break;
5522 case 32:
5523 type = Utils::Type::uvec3;
5524 break;
5525 case 33:
5526 type = Utils::Type::uvec4;
5527 break;
5528 default:
5529 TCU_FAIL("invalid enum");
5530 }
5531
5532 return type;
5533 }
5534
5535 /** Get name of type at index
5536 *
5537 * @param index Index of type
5538 *
5539 * @return Name
5540 **/
getTypeName(GLuint index) const5541 std::string TestBase::getTypeName(GLuint index) const
5542 {
5543 std::string name = getType(index).GetGLSLTypeName();
5544
5545 return name;
5546 }
5547
5548 /** Get number of types
5549 *
5550 * @return 34
5551 **/
getTypesNumber() const5552 glw::GLuint TestBase::getTypesNumber() const
5553 {
5554 return 34;
5555 }
5556
5557 /** Execute test
5558 *
5559 * @return true if test pass, false otherwise
5560 **/
test()5561 bool TestBase::test()
5562 {
5563 bool result = true;
5564 GLuint n_test_cases = 0;
5565
5566 /* Prepare test */
5567 testInit();
5568
5569 /* GL entry points */
5570 const Functions& gl = m_context.getRenderContext().getFunctions();
5571
5572 /* Tessellation patch set up */
5573 gl.patchParameteri(GL_PATCH_VERTICES, 1);
5574 GLU_EXPECT_NO_ERROR(gl.getError(), "PatchParameteri");
5575
5576 /* Get number of test cases */
5577 n_test_cases = getTestCaseNumber();
5578
5579 #if DEBUG_REPEAT_TEST_CASE
5580
5581 while (1)
5582 {
5583 GLuint test_case = DEBUG_REPEATED_TEST_CASE;
5584
5585 #else /* DEBUG_REPEAT_TEST_CASE */
5586
5587 for (GLuint test_case = 0; test_case < n_test_cases; ++test_case)
5588 {
5589 #endif /* DEBUG_REPEAT_TEST_CASE */
5590
5591 /* Execute case */
5592 if (!testCase(test_case))
5593 {
5594 const std::string& test_case_name = getTestCaseName(test_case);
5595
5596 if (false == test_case_name.empty())
5597 {
5598 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case_name
5599 << ") failed." << tcu::TestLog::EndMessage;
5600 }
5601 else
5602 {
5603 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Test case (" << test_case
5604 << ") failed." << tcu::TestLog::EndMessage;
5605 }
5606
5607 result = false;
5608 }
5609 }
5610
5611 /* Done */
5612 return result;
5613 }
5614
5615 /* Constants used by BufferTestBase */
5616 const GLuint BufferTestBase::bufferDescriptor::m_non_indexed = -1;
5617
5618 /** Constructor
5619 *
5620 * @param context Test context
5621 * @param test_name Name of test
5622 * @param test_description Description of test
5623 **/
5624 BufferTestBase::BufferTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
5625 : TestBase(context, test_name, test_description)
5626 {
5627 }
5628
5629 /** Execute drawArrays for single vertex
5630 *
5631 * @param ignored
5632 *
5633 * @return true
5634 **/
5635 bool BufferTestBase::executeDrawCall(bool tesEnabled, GLuint /* test_case_index */)
5636 {
5637 const Functions& gl = m_context.getRenderContext().getFunctions();
5638
5639 gl.disable(GL_RASTERIZER_DISCARD);
5640 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
5641
5642 gl.beginTransformFeedback(GL_POINTS);
5643 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
5644
5645 // Only TES is existed, glDrawArray can use the parameter GL_PATCHES
5646 if (tesEnabled == false)
5647 {
5648 gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
5649 }
5650 else
5651 {
5652 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
5653 }
5654
5655 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
5656
5657 gl.endTransformFeedback();
5658 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
5659
5660 return true;
5661 }
5662
5663 /** Get descriptors of buffers necessary for test
5664 *
5665 * @param ignored
5666 * @param ignored
5667 **/
5668 void BufferTestBase::getBufferDescriptors(glw::GLuint /* test_case_index */,
5669 bufferDescriptor::Vector& /* out_descriptors */)
5670 {
5671 /* Nothhing to be done */
5672 }
5673
5674 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
5675 *
5676 * @param ignored
5677 * @param ignored
5678 **/
5679 void BufferTestBase::getCapturedVaryings(glw::GLuint /* test_case_index */,
5680 Utils::Program::NameVector& /* captured_varyings */,
5681 GLint* /* xfb_components */)
5682 {
5683 /* Nothing to be done */
5684 }
5685
5686 /** Get body of main function for given shader stage
5687 *
5688 * @param ignored
5689 * @param ignored
5690 * @param out_assignments Set to empty
5691 * @param out_calculations Set to empty
5692 **/
5693 void BufferTestBase::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5694 std::string& out_assignments, std::string& out_calculations)
5695 {
5696 out_assignments = "";
5697 out_calculations = "";
5698 }
5699
5700 /** Get interface of shader
5701 *
5702 * @param ignored
5703 * @param ignored
5704 * @param out_interface Set to ""
5705 **/
5706 void BufferTestBase::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES /* stage */,
5707 std::string& out_interface)
5708 {
5709 out_interface = "";
5710 }
5711
5712 /** Get source code of shader
5713 *
5714 * @param test_case_index Index of test case
5715 * @param stage Shader stage
5716 *
5717 * @return Source
5718 **/
5719 std::string BufferTestBase::getShaderSource(glw::GLuint test_case_index, Utils::Shader::STAGES stage)
5720 {
5721 std::string assignments;
5722 std::string calculations;
5723 std::string interface;
5724
5725 /* */
5726 getShaderBody(test_case_index, stage, assignments, calculations);
5727 getShaderInterface(test_case_index, stage, interface);
5728
5729 /* */
5730 std::string source = getShaderTemplate(stage);
5731
5732 /* */
5733 size_t position = 0;
5734 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
5735 Utils::replaceToken("CALCULATIONS", position, calculations.c_str(), source);
5736 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
5737
5738 /* */
5739 return source;
5740 }
5741
5742 /** Inspects program to check if all resources are as expected
5743 *
5744 * @param ignored
5745 * @param ignored
5746 * @param ignored
5747 *
5748 * @return true
5749 **/
5750 bool BufferTestBase::inspectProgram(GLuint /* test_case_index */, Utils::Program& /* program */,
5751 std::stringstream& /* out_stream */)
5752 {
5753 return true;
5754 }
5755
5756 /** Runs test case
5757 *
5758 * @param test_case_index Id of test case
5759 *
5760 * @return true if test case pass, false otherwise
5761 **/
5762 bool BufferTestBase::testCase(GLuint test_case_index)
5763 {
5764 try
5765 {
5766 bufferCollection buffers;
5767 Utils::Program::NameVector captured_varyings;
5768 bufferDescriptor::Vector descriptors;
5769 Utils::Program program(m_context);
5770 Utils::VertexArray vao(m_context);
5771
5772 /* Get captured varyings */
5773 GLint xfb_components;
5774 getCapturedVaryings(test_case_index, captured_varyings, &xfb_components);
5775
5776 /* Don't generate shaders that try to capture more XFB components than the implementation's limit */
5777 if (captured_varyings.size() > 0)
5778 {
5779 const Functions& gl = m_context.getRenderContext().getFunctions();
5780
5781 GLint max_xfb_components;
5782 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_components);
5783 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5784
5785 if (xfb_components > max_xfb_components)
5786 return true;
5787 }
5788
5789 /* Get shader sources */
5790 const std::string& fragment_shader = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
5791 const std::string& geometry_shader = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
5792 const std::string& tess_ctrl_shader = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
5793 const std::string& tess_eval_shader = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
5794 const std::string& vertex_shader = getShaderSource(test_case_index, Utils::Shader::VERTEX);
5795
5796 /* Set up program */
5797 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
5798 vertex_shader, captured_varyings, true, false /* is_separable */);
5799
5800 /* Inspection */
5801 {
5802 std::stringstream stream;
5803 if (false == inspectProgram(test_case_index, program, stream))
5804 {
5805 m_context.getTestContext().getLog()
5806 << tcu::TestLog::Message
5807 << "Program inspection failed. Test case: " << getTestCaseName(test_case_index)
5808 << ". Reason: " << stream.str() << tcu::TestLog::EndMessage
5809 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5810 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5811 << tcu::TestLog::KernelSource(fragment_shader);
5812
5813 return false;
5814 }
5815 }
5816
5817 program.Use();
5818
5819 /* Set up buffers */
5820 getBufferDescriptors(test_case_index, descriptors);
5821 cleanBuffers();
5822 prepareBuffers(descriptors, buffers);
5823
5824 /* Set up vao */
5825 vao.Init();
5826 vao.Bind();
5827
5828 /* Draw */
5829 bool result = executeDrawCall((program.m_tess_eval.m_id != 0), test_case_index);
5830
5831 #if USE_NSIGHT
5832 m_context.getRenderContext().postIterate();
5833 #endif
5834
5835 if (false == result)
5836 {
5837 m_context.getTestContext().getLog()
5838 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5839 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5840 << tcu::TestLog::KernelSource(fragment_shader);
5841
5842 return false;
5843 }
5844
5845 /* Verify result */
5846 if (false == verifyBuffers(buffers))
5847 {
5848 m_context.getTestContext().getLog()
5849 << tcu::TestLog::KernelSource(vertex_shader) << tcu::TestLog::KernelSource(tess_ctrl_shader)
5850 << tcu::TestLog::KernelSource(tess_eval_shader) << tcu::TestLog::KernelSource(geometry_shader)
5851 << tcu::TestLog::KernelSource(fragment_shader);
5852
5853 return false;
5854 }
5855 }
5856 catch (Utils::Shader::InvalidSourceException& exc)
5857 {
5858 exc.log(m_context);
5859 TCU_FAIL(exc.what());
5860 }
5861 catch (Utils::Program::BuildException& exc)
5862 {
5863 exc.log(m_context);
5864 TCU_FAIL(exc.what());
5865 }
5866
5867 /* Done */
5868 return true;
5869 }
5870
5871 /** Verify contents of buffers
5872 *
5873 * @param buffers Collection of buffers to be verified
5874 *
5875 * @return true if everything is as expected, false otherwise
5876 **/
5877 bool BufferTestBase::verifyBuffers(bufferCollection& buffers)
5878 {
5879 bool result = true;
5880
5881 for (bufferCollection::Vector::iterator it = buffers.m_vector.begin(), end = buffers.m_vector.end(); end != it;
5882 ++it)
5883 {
5884 bufferCollection::pair& pair = *it;
5885 Utils::Buffer* buffer = pair.m_buffer;
5886 bufferDescriptor* descriptor = pair.m_descriptor;
5887 size_t size = descriptor->m_expected_data.size();
5888
5889 /* Skip buffers that have no expected data */
5890 if (0 == size)
5891 {
5892 continue;
5893 }
5894
5895 /* Get pointer to contents of buffer */
5896 buffer->Bind();
5897 GLvoid* buffer_data = buffer->Map(Utils::Buffer::ReadOnly);
5898
5899 /* Get pointer to expected data */
5900 GLvoid* expected_data = &descriptor->m_expected_data[0];
5901
5902 /* Compare */
5903 int res = memcmp(buffer_data, expected_data, size);
5904
5905 if (0 != res)
5906 {
5907 m_context.getTestContext().getLog()
5908 << tcu::TestLog::Message
5909 << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
5910 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
5911
5912 result = false;
5913 }
5914
5915 /* Release buffer mapping */
5916 buffer->UnMap();
5917 }
5918
5919 return result;
5920 }
5921
5922 /** Unbinds all uniforms and xfb
5923 *
5924 **/
5925 void BufferTestBase::cleanBuffers()
5926 {
5927 const Functions& gl = m_context.getRenderContext().getFunctions();
5928
5929 GLint max_uni = 0;
5930 GLint max_xfb = 0;
5931
5932 gl.getIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &max_uni);
5933 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
5934 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
5935
5936 for (GLint i = 0; i < max_uni; ++i)
5937 {
5938 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Uniform, i);
5939 }
5940
5941 for (GLint i = 0; i < max_xfb; ++i)
5942 {
5943 Utils::Buffer::BindBase(gl, 0, Utils::Buffer::Transform_feedback, i);
5944 }
5945 }
5946
5947 /** Get template of shader for given stage
5948 *
5949 * @param stage Stage
5950 *
5951 * @return Template of shader source
5952 **/
5953 std::string BufferTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
5954 {
5955 static const GLchar* compute_shader_template = "#version 430 core\n"
5956 "#extension GL_ARB_enhanced_layouts : require\n"
5957 "\n"
5958 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
5959 "\n"
5960 "writeonly uniform uimage2D uni_image;\n"
5961 "\n"
5962 "INTERFACE"
5963 "\n"
5964 "void main()\n"
5965 "{\n"
5966 "CALCULATIONS"
5967 "\n"
5968 "ASSIGNMENTS"
5969 "}\n"
5970 "\n";
5971
5972 static const GLchar* fragment_shader_template = "#version 430 core\n"
5973 "#extension GL_ARB_enhanced_layouts : require\n"
5974 "\n"
5975 "INTERFACE"
5976 "\n"
5977 "void main()\n"
5978 "{\n"
5979 "CALCULATIONS"
5980 "\n"
5981 "ASSIGNMENTS"
5982 "}\n"
5983 "\n";
5984
5985 // max_vertices is set to 3 for the test case "xfb_vertex_streams" declares 3 streams in geometry shader,
5986 // according to spec, max_vertices should be no less than 3 if there are 3 streams in GS.
5987 static const GLchar* geometry_shader_template = "#version 430 core\n"
5988 "#extension GL_ARB_enhanced_layouts : require\n"
5989 "\n"
5990 "layout(points) in;\n"
5991 "layout(points, max_vertices = 3) out;\n"
5992 "\n"
5993 "INTERFACE"
5994 "\n"
5995 "void main()\n"
5996 "{\n"
5997 "CALCULATIONS"
5998 "\n"
5999 "\n"
6000 "ASSIGNMENTS"
6001 " gl_Position = vec4(0, 0, 0, 1);\n"
6002 " EmitVertex();\n"
6003 "}\n"
6004 "\n";
6005
6006 static const GLchar* tess_ctrl_shader_template = "#version 430 core\n"
6007 "#extension GL_ARB_enhanced_layouts : require\n"
6008 "\n"
6009 "layout(vertices = 1) out;\n"
6010 "\n"
6011 "INTERFACE"
6012 "\n"
6013 "void main()\n"
6014 "{\n"
6015 "CALCULATIONS"
6016 "\n"
6017 "ASSIGNMENTS"
6018 "\n"
6019 " gl_TessLevelOuter[0] = 1.0;\n"
6020 " gl_TessLevelOuter[1] = 1.0;\n"
6021 " gl_TessLevelOuter[2] = 1.0;\n"
6022 " gl_TessLevelOuter[3] = 1.0;\n"
6023 " gl_TessLevelInner[0] = 1.0;\n"
6024 " gl_TessLevelInner[1] = 1.0;\n"
6025 "}\n"
6026 "\n";
6027
6028 static const GLchar* tess_eval_shader_template = "#version 430 core\n"
6029 "#extension GL_ARB_enhanced_layouts : require\n"
6030 "\n"
6031 "layout(isolines, point_mode) in;\n"
6032 "\n"
6033 "INTERFACE"
6034 "\n"
6035 "void main()\n"
6036 "{\n"
6037 "CALCULATIONS"
6038 "\n"
6039 "ASSIGNMENTS"
6040 "}\n"
6041 "\n";
6042
6043 static const GLchar* vertex_shader_template = "#version 430 core\n"
6044 "#extension GL_ARB_enhanced_layouts : require\n"
6045 "\n"
6046 "INTERFACE"
6047 "\n"
6048 "void main()\n"
6049 "{\n"
6050 "CALCULATIONS"
6051 "\n"
6052 "ASSIGNMENTS"
6053 "}\n"
6054 "\n";
6055
6056 const GLchar* result = 0;
6057
6058 switch (stage)
6059 {
6060 case Utils::Shader::COMPUTE:
6061 result = compute_shader_template;
6062 break;
6063 case Utils::Shader::FRAGMENT:
6064 result = fragment_shader_template;
6065 break;
6066 case Utils::Shader::GEOMETRY:
6067 result = geometry_shader_template;
6068 break;
6069 case Utils::Shader::TESS_CTRL:
6070 result = tess_ctrl_shader_template;
6071 break;
6072 case Utils::Shader::TESS_EVAL:
6073 result = tess_eval_shader_template;
6074 break;
6075 case Utils::Shader::VERTEX:
6076 result = vertex_shader_template;
6077 break;
6078 default:
6079 TCU_FAIL("Invalid enum");
6080 }
6081
6082 return result;
6083 }
6084
6085 /** Prepare buffer according to descriptor
6086 *
6087 * @param buffer Buffer to prepare
6088 * @param desc Descriptor
6089 **/
6090 void BufferTestBase::prepareBuffer(Utils::Buffer& buffer, bufferDescriptor& desc)
6091 {
6092 GLsizeiptr size = 0;
6093 GLvoid* data = 0;
6094
6095 if (false == desc.m_initial_data.empty())
6096 {
6097 size = desc.m_initial_data.size();
6098 data = &desc.m_initial_data[0];
6099 }
6100 else if (false == desc.m_expected_data.empty())
6101 {
6102 size = desc.m_expected_data.size();
6103 }
6104
6105 buffer.Init(desc.m_target, Utils::Buffer::StaticDraw, size, data);
6106
6107 if (bufferDescriptor::m_non_indexed != desc.m_index)
6108 {
6109 buffer.BindBase(desc.m_index);
6110 }
6111 else
6112 {
6113 buffer.Bind();
6114 }
6115 }
6116
6117 /** Prepare collection of buffer
6118 *
6119 * @param descriptors Collection of descriptors
6120 * @param out_buffers Collection of buffers
6121 **/
6122 void BufferTestBase::prepareBuffers(bufferDescriptor::Vector& descriptors, bufferCollection& out_buffers)
6123 {
6124 for (bufferDescriptor::Vector::iterator it = descriptors.begin(), end = descriptors.end(); end != it; ++it)
6125 {
6126 bufferCollection::pair pair;
6127
6128 pair.m_buffer = new Utils::Buffer(m_context);
6129 if (0 == pair.m_buffer)
6130 {
6131 TCU_FAIL("Memory allocation failed");
6132 }
6133
6134 pair.m_descriptor = &(*it);
6135
6136 prepareBuffer(*pair.m_buffer, *pair.m_descriptor);
6137
6138 out_buffers.m_vector.push_back(pair);
6139 }
6140 }
6141
6142 /** Destructor
6143 *
6144 **/
6145 BufferTestBase::bufferCollection::~bufferCollection()
6146 {
6147 for (Vector::iterator it = m_vector.begin(), end = m_vector.end(); end != it; ++it)
6148 {
6149 if (0 != it->m_buffer)
6150 {
6151 delete it->m_buffer;
6152 it->m_buffer = 0;
6153 }
6154 }
6155 }
6156
6157 /** Constructor
6158 *
6159 * @param context Test context
6160 * @param test_name Name of test
6161 * @param test_description Description of test
6162 **/
6163 NegativeTestBase::NegativeTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6164 : TestBase(context, test_name, test_description)
6165 {
6166 }
6167
6168 /** Selects if "compute" stage is relevant for test
6169 *
6170 * @param ignored
6171 *
6172 * @return true
6173 **/
6174 bool NegativeTestBase::isComputeRelevant(GLuint /* test_case_index */)
6175 {
6176 return true;
6177 }
6178
6179 /** Selects if compilation failure is expected result
6180 *
6181 * @param ignored
6182 *
6183 * @return true
6184 **/
6185 bool NegativeTestBase::isFailureExpected(GLuint /* test_case_index */)
6186 {
6187 return true;
6188 }
6189
6190 /** Selects if the test case should use a separable program
6191 *
6192 * @param ignored
6193 *
6194 * @return false
6195 **/
6196 bool NegativeTestBase::isSeparable(const GLuint /* test_case_index */)
6197 {
6198 return false;
6199 }
6200
6201 /** Runs test case
6202 *
6203 * @param test_case_index Id of test case
6204 *
6205 * @return true if test case pass, false otherwise
6206 **/
6207 bool NegativeTestBase::testCase(GLuint test_case_index)
6208 {
6209 bool test_case_result = true;
6210
6211 /* Compute */
6212 if (true == isComputeRelevant(test_case_index))
6213 {
6214 const std::string& cs_source = getShaderSource(test_case_index, Utils::Shader::COMPUTE);
6215 bool is_build_error = false;
6216 const bool is_failure_expected = isFailureExpected(test_case_index);
6217 Utils::Program program(m_context);
6218
6219 try
6220 {
6221 program.Init(cs_source, "" /* fs */, "" /* gs */, "" /* tcs */, "" /* tes */, "" /* vs */,
6222 false /* separable */);
6223 }
6224 catch (Utils::Shader::InvalidSourceException& exc)
6225 {
6226 if (false == is_failure_expected)
6227 {
6228 m_context.getTestContext().getLog()
6229 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6230 exc.log(m_context);
6231 }
6232
6233 #if DEBUG_NEG_LOG_ERROR
6234
6235 else
6236 {
6237 m_context.getTestContext().getLog()
6238 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6239 << tcu::TestLog::EndMessage;
6240 exc.log(m_context);
6241 }
6242
6243 #endif /* DEBUG_NEG_LOG_ERROR */
6244
6245 is_build_error = true;
6246 }
6247 catch (Utils::Program::BuildException& exc)
6248 {
6249 if (false == is_failure_expected)
6250 {
6251 m_context.getTestContext().getLog()
6252 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6253 exc.log(m_context);
6254 }
6255
6256 #if DEBUG_NEG_LOG_ERROR
6257
6258 else
6259 {
6260 m_context.getTestContext().getLog()
6261 << tcu::TestLog::Message
6262 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6263 exc.log(m_context);
6264 }
6265
6266 #endif /* DEBUG_NEG_LOG_ERROR */
6267
6268 is_build_error = true;
6269 }
6270
6271 if (is_build_error != is_failure_expected)
6272 {
6273 if (!is_build_error)
6274 {
6275 m_context.getTestContext().getLog()
6276 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6277 Utils::Shader::LogSource(m_context, cs_source, Utils::Shader::COMPUTE);
6278 }
6279 test_case_result = false;
6280 }
6281 }
6282 else /* Draw */
6283 {
6284 const std::string& fs_source = getShaderSource(test_case_index, Utils::Shader::FRAGMENT);
6285 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
6286 bool is_build_error = false;
6287 const bool is_failure_expected = isFailureExpected(test_case_index);
6288 Utils::Program program(m_context);
6289 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
6290 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
6291 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
6292
6293 try
6294 {
6295 if (isSeparable(test_case_index))
6296 {
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 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, tcs_source, "" /*tes_source*/,
6302 "" /*vs_source*/, true /* separable */);
6303 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, "" /*tcs_source*/, tes_source,
6304 "" /*vs_source*/, true /* separable */);
6305 program.Init("" /*cs*/, "" /*fs_source*/, "" /*gs_source*/, "" /*tcs_source*/, "" /*tes_source*/,
6306 vs_source, true /* separable */);
6307 }
6308 else
6309 {
6310 program.Init("" /* cs */, fs_source, gs_source, tcs_source, tes_source, vs_source,
6311 false /* separable */);
6312 }
6313 }
6314 catch (Utils::Shader::InvalidSourceException& exc)
6315 {
6316 if (false == is_failure_expected)
6317 {
6318 m_context.getTestContext().getLog()
6319 << tcu::TestLog::Message << "Unexpected error in shader compilation: " << tcu::TestLog::EndMessage;
6320 exc.log(m_context);
6321 }
6322
6323 #if DEBUG_NEG_LOG_ERROR
6324
6325 else
6326 {
6327 m_context.getTestContext().getLog()
6328 << tcu::TestLog::Message << "Error in shader compilation was expected, logged for verification: "
6329 << tcu::TestLog::EndMessage;
6330 exc.log(m_context);
6331 }
6332
6333 #endif /* DEBUG_NEG_LOG_ERROR */
6334
6335 is_build_error = true;
6336 }
6337 catch (Utils::Program::BuildException& exc)
6338 {
6339 if (false == is_failure_expected)
6340 {
6341 m_context.getTestContext().getLog()
6342 << tcu::TestLog::Message << "Unexpected error in program linking: " << tcu::TestLog::EndMessage;
6343 exc.log(m_context);
6344 }
6345
6346 #if DEBUG_NEG_LOG_ERROR
6347
6348 else
6349 {
6350 m_context.getTestContext().getLog()
6351 << tcu::TestLog::Message
6352 << "Error in program linking was expected, logged for verification: " << tcu::TestLog::EndMessage;
6353 exc.log(m_context);
6354 }
6355
6356 #endif /* DEBUG_NEG_LOG_ERROR */
6357
6358 is_build_error = true;
6359 }
6360
6361 if (is_build_error != is_failure_expected)
6362 {
6363 if (!is_build_error)
6364 {
6365 m_context.getTestContext().getLog()
6366 << tcu::TestLog::Message << "Unexpected success: " << tcu::TestLog::EndMessage;
6367 Utils::Shader::LogSource(m_context, vs_source, Utils::Shader::VERTEX);
6368 Utils::Shader::LogSource(m_context, tcs_source, Utils::Shader::TESS_CTRL);
6369 Utils::Shader::LogSource(m_context, tes_source, Utils::Shader::TESS_EVAL);
6370 Utils::Shader::LogSource(m_context, gs_source, Utils::Shader::GEOMETRY);
6371 Utils::Shader::LogSource(m_context, fs_source, Utils::Shader::FRAGMENT);
6372 }
6373 test_case_result = false;
6374 }
6375 }
6376
6377 return test_case_result;
6378 }
6379
6380 /* Constants used by TextureTestBase */
6381 const glw::GLuint TextureTestBase::m_width = 16;
6382 const glw::GLuint TextureTestBase::m_height = 16;
6383
6384 /** Constructor
6385 *
6386 * @param context Test context
6387 * @param test_name Name of test
6388 * @param test_description Description of test
6389 **/
6390 TextureTestBase::TextureTestBase(deqp::Context& context, const GLchar* test_name, const GLchar* test_description)
6391 : TestBase(context, test_name, test_description)
6392 {
6393 }
6394
6395 /** Get locations for all inputs with automatic_location
6396 *
6397 * @param program Program object
6398 * @param program_interface Interface of program
6399 **/
6400 void TextureTestBase::prepareAttribLocation(Utils::Program& program, Utils::ProgramInterface& program_interface)
6401 {
6402 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6403
6404 Utils::Variable::PtrVector& inputs = si.m_inputs;
6405
6406 for (Utils::Variable::PtrVector::iterator it = inputs.begin(); inputs.end() != it; ++it)
6407 {
6408 /* Test does not specify location, query value and set */
6409 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6410 {
6411 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_INPUT);
6412 GLint location = 0;
6413
6414 program.GetResource(GL_PROGRAM_INPUT, index, GL_LOCATION, 1 /* size */, &location);
6415
6416 (*it)->m_descriptor.m_expected_location = location;
6417 }
6418 }
6419 }
6420
6421 /** Verifies contents of drawn image
6422 *
6423 * @param ignored
6424 * @param color_0 Verified image
6425 *
6426 * @return true if image is filled with 1, false otherwise
6427 **/
6428 bool TextureTestBase::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& color_0)
6429 {
6430 static const GLuint size = m_width * m_height;
6431 static const GLuint expected_color = 1;
6432
6433 std::vector<GLuint> data;
6434 data.resize(size);
6435
6436 color_0.Get(GL_RED_INTEGER, GL_UNSIGNED_INT, &data[0]);
6437
6438 for (GLuint i = 0; i < size; ++i)
6439 {
6440 const GLuint color = data[i];
6441
6442 if (expected_color != color)
6443 {
6444 m_context.getTestContext().getLog() << tcu::TestLog::Message << "R32UI[" << i << "]:" << color
6445 << tcu::TestLog::EndMessage;
6446 return false;
6447 }
6448 }
6449
6450 return true;
6451 }
6452
6453 /** Execute dispatch compute for 16x16x1
6454 *
6455 * @param ignored
6456 **/
6457 void TextureTestBase::executeDispatchCall(GLuint /* test_case_index */)
6458 {
6459 const Functions& gl = m_context.getRenderContext().getFunctions();
6460
6461 gl.dispatchCompute(16 /* x */, 16 /* y */, 1 /* z */);
6462 GLU_EXPECT_NO_ERROR(gl.getError(), "DispatchCompute");
6463 }
6464
6465 /** Execute drawArrays for single vertex
6466 *
6467 * @param ignored
6468 **/
6469 void TextureTestBase::executeDrawCall(GLuint /* test_case_index */)
6470 {
6471 const Functions& gl = m_context.getRenderContext().getFunctions();
6472
6473 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
6474 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
6475 }
6476
6477 /** Prepare code snippet that will pass in variables to out variables
6478 *
6479 * @param ignored
6480 * @param varying_passthrough Collection of connections between in and out variables
6481 * @param stage Shader stage
6482 *
6483 * @return Code that pass in variables to next stage
6484 **/
6485 std::string TextureTestBase::getPassSnippet(GLuint /* test_case_index */,
6486 Utils::VaryingPassthrough& varying_passthrough, Utils::Shader::STAGES stage)
6487 {
6488 static const GLchar* separator = "\n ";
6489
6490 /* Skip for compute shader */
6491 if (Utils::Shader::COMPUTE == stage)
6492 {
6493 return "";
6494 }
6495
6496 Utils::VaryingConnection::Vector& vector = varying_passthrough.Get(stage);
6497
6498 std::string result = Utils::g_list;
6499 size_t position = 0;
6500
6501 for (GLuint i = 0; i < vector.size(); ++i)
6502 {
6503
6504 Utils::VaryingConnection& connection = vector[i];
6505
6506 Utils::Variable* in = connection.m_in;
6507 Utils::Variable* out = connection.m_out;
6508
6509 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6510 Utils::Variable::FLAVOUR out_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::OUTPUT);
6511
6512 const std::string passthrough =
6513 getVariablePassthrough("", in->m_descriptor, in_flavour, "", out->m_descriptor, out_flavour);
6514
6515 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6516 }
6517
6518 Utils::endList("", position, result);
6519
6520 return result;
6521 }
6522
6523 /** Basic implementation of method getProgramInterface
6524 *
6525 * @param ignored
6526 * @param ignored
6527 * @param ignored
6528 **/
6529 void TextureTestBase::getProgramInterface(GLuint /* test_case_index */,
6530 Utils::ProgramInterface& /* program_interface */,
6531 Utils::VaryingPassthrough& /* varying_passthrough */)
6532 {
6533 }
6534
6535 /** Prepare code snippet that will verify in and uniform variables
6536 *
6537 * @param ignored
6538 * @param program_interface Interface of program
6539 * @param stage Shader stage
6540 *
6541 * @return Code that verify variables
6542 **/
6543 std::string TextureTestBase::getVerificationSnippet(GLuint /* test_case_index */,
6544 Utils::ProgramInterface& program_interface,
6545 Utils::Shader::STAGES stage)
6546 {
6547 static const GLchar* separator = " ||\n ";
6548
6549 std::string verification = "if (LIST)\n"
6550 " {\n"
6551 " result = 0u;\n"
6552 " }\n";
6553
6554 /* Get flavour of in and out variables */
6555 Utils::Variable::FLAVOUR in_flavour = Utils::Variable::GetFlavour(stage, Utils::Variable::INPUT);
6556
6557 /* Get interface for shader stage */
6558 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
6559
6560 /* There are no varialbes to verify */
6561 if ((0 == si.m_inputs.size()) && (0 == si.m_uniforms.size()) && (0 == si.m_ssb_blocks.size()))
6562 {
6563 return "";
6564 }
6565
6566 /* For each in variable insert verification code */
6567 size_t position = 0;
6568
6569 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6570 {
6571 const Utils::Variable& var = *si.m_inputs[i];
6572 const std::string& var_verification = getVariableVerification("", var.m_data, var.m_descriptor, in_flavour);
6573
6574 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6575 }
6576
6577 /* For each unifrom variable insert verification code */
6578 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
6579 {
6580 const Utils::Variable& var = *si.m_uniforms[i];
6581 const std::string& var_verification =
6582 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6583
6584 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6585 }
6586
6587 /* For each ssb variable insert verification code */
6588 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
6589 {
6590 const Utils::Variable& var = *si.m_ssb_blocks[i];
6591 const std::string& var_verification =
6592 getVariableVerification("", var.m_data, var.m_descriptor, Utils::Variable::BASIC);
6593
6594 Utils::insertElementOfList(var_verification.c_str(), separator, position, verification);
6595 }
6596
6597 Utils::endList("", position, verification);
6598
6599 #if DEBUG_TTB_VERIFICATION_SNIPPET_STAGE
6600
6601 {
6602 GLchar buffer[16];
6603 sprintf(buffer, "%d", stage + 10);
6604 Utils::replaceToken("0u", position, buffer, verification);
6605 }
6606
6607 #elif DEBUG_TTB_VERIFICATION_SNIPPET_VARIABLE
6608
6609 if (Utils::Shader::VERTEX == stage)
6610 {
6611 Utils::replaceToken("0u", position, "in_vs_first.x", verification);
6612 }
6613 else
6614 {
6615 Utils::replaceToken("0u", position, "31u", verification);
6616 }
6617
6618 #endif
6619
6620 /* Done */
6621 return verification;
6622 }
6623
6624 /** Selects if "compute" stage is relevant for test
6625 *
6626 * @param ignored
6627 *
6628 * @return true
6629 **/
6630 bool TextureTestBase::isComputeRelevant(GLuint /* test_case_index */)
6631 {
6632 return true;
6633 }
6634
6635 /** Selects if "draw" stages are relevant for test
6636 *
6637 * @param ignored
6638 *
6639 * @return true
6640 **/
6641 bool TextureTestBase::isDrawRelevant(GLuint /* test_case_index */)
6642 {
6643 return true;
6644 }
6645
6646 /** Prepare code that will do assignment of single in to single out
6647 *
6648 * @param in_parent_name Name of parent in variable
6649 * @param in_variable Descriptor of in variable
6650 * @param in_flavour Flavoud of in variable
6651 * @param out_parent_name Name of parent out variable
6652 * @param out_variable Descriptor of out variable
6653 * @param out_flavour Flavoud of out variable
6654 *
6655 * @return Code that does OUT = IN
6656 **/
6657 std::string TextureTestBase::getVariablePassthrough(const std::string& in_parent_name,
6658 const Utils::Variable::Descriptor& in_variable,
6659 Utils::Variable::FLAVOUR in_flavour,
6660 const std::string& out_parent_name,
6661 const Utils::Variable::Descriptor& out_variable,
6662 Utils::Variable::FLAVOUR out_flavour)
6663 {
6664 bool done = false;
6665 GLuint index = 0;
6666 GLuint member_index = 0;
6667 size_t position = 0;
6668 std::string result = Utils::g_list;
6669 static const GLchar* separator = ";\n ";
6670
6671 /* For each member of each array element */
6672 do
6673 {
6674 const std::string in_name = Utils::Variable::GetReference(in_parent_name, in_variable, in_flavour, index);
6675 const std::string out_name = Utils::Variable::GetReference(out_parent_name, out_variable, out_flavour, index);
6676 std::string passthrough;
6677
6678 /* Prepare verification */
6679 if (Utils::Variable::BUILTIN == in_variable.m_type)
6680 {
6681 size_t pass_position = 0;
6682
6683 passthrough = "OUT = IN;";
6684
6685 Utils::replaceToken("OUT", pass_position, out_name.c_str(), passthrough);
6686 Utils::replaceToken("IN", pass_position, in_name.c_str(), passthrough);
6687
6688 /* Increment index */
6689 ++index;
6690 }
6691 else
6692 {
6693 const Utils::Interface* in_interface = in_variable.m_interface;
6694 const Utils::Interface* out_interface = out_variable.m_interface;
6695
6696 if ((0 == in_interface) || (0 == out_interface))
6697 {
6698 TCU_FAIL("Nullptr");
6699 }
6700
6701 const Utils::Variable::Descriptor& in_member = in_interface->m_members[member_index];
6702 const Utils::Variable::Descriptor& out_member = out_interface->m_members[member_index];
6703
6704 passthrough = getVariablePassthrough(in_name, in_member, Utils::Variable::BASIC, out_name, out_member,
6705 Utils::Variable::BASIC);
6706
6707 /* Increment member_index */
6708 ++member_index;
6709
6710 /* Increment index and reset member_index if all members were processed */
6711 if (in_interface->m_members.size() == member_index)
6712 {
6713 ++index;
6714 member_index = 0;
6715 }
6716 }
6717
6718 /* Check if loop should end */
6719 if ((index >= in_variable.m_n_array_elements) && (0 == member_index))
6720 {
6721 done = true;
6722 }
6723
6724 Utils::insertElementOfList(passthrough.c_str(), separator, position, result);
6725
6726 } while (true != done);
6727
6728 Utils::endList("", position, result);
6729
6730 /* Done */
6731 return result;
6732 }
6733
6734 /** Get verification of single variable
6735 *
6736 * @param parent_name Name of parent variable
6737 * @param data Data that should be used as EXPECTED
6738 * @param variable Descriptor of variable
6739 * @param flavour Flavour of variable
6740 *
6741 * @return Code that does (EXPECTED != VALUE) ||
6742 **/
6743 std::string TextureTestBase::getVariableVerification(const std::string& parent_name, const GLvoid* data,
6744 const Utils::Variable::Descriptor& variable,
6745 Utils::Variable::FLAVOUR flavour)
6746 {
6747 static const GLchar* logic_op = " ||\n ";
6748 const GLuint n_elements = (0 == variable.m_n_array_elements) ? 1 : variable.m_n_array_elements;
6749 size_t position = 0;
6750 std::string result = Utils::g_list;
6751 GLint stride = variable.m_expected_stride_of_element;
6752
6753 /* For each each array element */
6754 for (GLuint element = 0; element < n_elements; ++element)
6755 {
6756 const std::string name = Utils::Variable::GetReference(parent_name, variable, flavour, element);
6757
6758 /* Calculate data pointer */
6759 GLvoid* data_ptr = (GLvoid*)((GLubyte*)data + element * stride);
6760
6761 /* Prepare verification */
6762 if (Utils::Variable::BUILTIN == variable.m_type)
6763 {
6764 const std::string& expected = variable.m_builtin.GetGLSLConstructor(data_ptr);
6765 std::string verification;
6766 size_t verification_position = 0;
6767
6768 verification = "(EXPECTED != NAME)";
6769
6770 Utils::replaceToken("EXPECTED", verification_position, expected.c_str(), verification);
6771 Utils::replaceToken("NAME", verification_position, name.c_str(), verification);
6772
6773 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6774 }
6775 else
6776 {
6777 const Utils::Interface* interface = variable.m_interface;
6778
6779 if (0 == interface)
6780 {
6781 TCU_FAIL("Nullptr");
6782 }
6783
6784 const GLuint n_members = static_cast<GLuint>(interface->m_members.size());
6785
6786 /* for each member */
6787 for (GLuint member_index = 0; member_index < n_members; ++member_index)
6788 {
6789 const Utils::Variable::Descriptor& member = interface->m_members[member_index];
6790
6791 /* Get verification of member */
6792 const std::string& verification =
6793 getVariableVerification(name, (GLubyte*)data_ptr + member.m_offset, member, Utils::Variable::BASIC);
6794
6795 Utils::insertElementOfList(verification.c_str(), logic_op, position, result);
6796 }
6797 }
6798 }
6799
6800 Utils::endList("", position, result);
6801
6802 return result;
6803 }
6804
6805 /** Prepare attributes, vertex array object and array buffer
6806 *
6807 * @param test_case_index Index of test case
6808 * @param program_interface Interface of program
6809 * @param buffer Array buffer
6810 * @param vao Vertex array object
6811 **/
6812 void TextureTestBase::prepareAttributes(GLuint test_case_index, Utils::ProgramInterface& program_interface,
6813 Utils::Buffer& buffer, Utils::VertexArray& vao)
6814 {
6815 const bool use_component_qualifier = useComponentQualifier(test_case_index);
6816
6817 /* Get shader interface */
6818 const Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
6819
6820 /* Bind vao and buffer */
6821 vao.Bind();
6822 buffer.Bind();
6823
6824 /* Skip if there are no input variables in vertex shader */
6825 if (0 == si.m_inputs.size())
6826 {
6827 return;
6828 }
6829
6830 const Functions& gl = m_context.getRenderContext().getFunctions();
6831
6832 /* Calculate vertex stride and check */
6833 GLint max_inputs;
6834 gl.getIntegerv(GL_MAX_VERTEX_ATTRIBS, &max_inputs);
6835 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
6836
6837 /* dvec3/4 vertex inputs use a single location but require 2x16B slots */
6838 const GLuint max_slots = max_inputs * 2;
6839
6840 /* Compute used slots */
6841 std::vector<GLuint> slot_sizes(max_slots, 0);
6842 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6843 {
6844 const Utils::Variable& variable = *si.m_inputs[i];
6845
6846 const GLuint variable_size = static_cast<GLuint>(variable.m_data_size);
6847
6848 const GLuint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6849 const GLuint ends_at = variable.m_descriptor.m_offset % 16 + variable_size;
6850
6851 const GLuint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6852 for (GLuint loc = 0; loc < array_length; loc++)
6853 {
6854 const GLuint slot = base_slot + loc;
6855 slot_sizes[slot] = std::max(slot_sizes[slot], ends_at);
6856 }
6857 }
6858
6859 /* Compute the offsets where we need to put vertex buffer data for each slot */
6860 std::vector<GLint> slot_offsets(max_slots, -1);
6861 GLuint buffer_size = 0;
6862 for (GLuint i = 0; i < max_slots; i++)
6863 {
6864 if (slot_sizes[i] == 0)
6865 continue;
6866 slot_offsets[i] = buffer_size;
6867 buffer_size += slot_sizes[i];
6868 }
6869
6870 /* Prepare buffer data and set up vao */
6871 std::vector<GLubyte> buffer_data(buffer_size);
6872
6873 GLubyte* ptr = &buffer_data[0];
6874
6875 for (GLuint i = 0; i < si.m_inputs.size(); ++i)
6876 {
6877 const Utils::Variable& variable = *si.m_inputs[i];
6878
6879 const GLuint base_slot = variable.m_descriptor.m_expected_location + variable.m_descriptor.m_offset / 16;
6880 const GLuint variable_offset = variable.m_descriptor.m_offset % 16;
6881 const GLuint array_length = std::max(1u, variable.m_descriptor.m_n_array_elements);
6882 for (GLuint loc = 0; loc < array_length; loc++)
6883 {
6884 const GLuint slot = base_slot + loc;
6885 memcpy(ptr + slot_offsets[slot] + variable_offset, variable.m_data, variable.m_data_size);
6886 }
6887
6888 if (!use_component_qualifier)
6889 {
6890 vao.Attribute(variable.m_descriptor.m_expected_location, variable.m_descriptor.m_builtin,
6891 variable.m_descriptor.m_n_array_elements, variable.m_descriptor.m_normalized,
6892 variable.GetStride(), (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6893 }
6894 else if (0 == variable.m_descriptor.m_expected_component)
6895 {
6896 /* Components can only be applied to types not surpassing
6897 * the bounds of a single slot. Therefore, we calculate
6898 * the amount of used components in the varying based on
6899 * the calculated slot sizes.
6900 */
6901 const GLuint n_component_size = Utils::Type::Double == variable.m_descriptor.m_builtin.m_basic_type ? 8 : 4;
6902 const GLuint n_rows = slot_sizes[base_slot] / n_component_size;
6903
6904 const Utils::Type& type = Utils::Type::GetType(variable.m_descriptor.m_builtin.m_basic_type,
6905 1 /* n_columns */, n_rows /* n_rows */);
6906
6907 vao.Attribute(variable.m_descriptor.m_expected_location, type, variable.m_descriptor.m_n_array_elements,
6908 variable.m_descriptor.m_normalized, variable.GetStride(),
6909 (GLvoid*)(intptr_t)(slot_offsets[base_slot] + variable_offset));
6910 }
6911 }
6912
6913 /* Update buffer */
6914 buffer.Data(Utils::Buffer::StaticDraw, buffer_size, ptr);
6915 }
6916
6917 /** Get locations for all outputs with automatic_location
6918 *
6919 * @param program Program object
6920 * @param program_interface Interface of program
6921 **/
6922 void TextureTestBase::prepareFragmentDataLoc(Utils::Program& program, Utils::ProgramInterface& program_interface)
6923 {
6924 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
6925 Utils::Variable::PtrVector& outputs = si.m_outputs;
6926
6927 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
6928 {
6929 /* Test does not specify location, query value and set */
6930 if (Utils::Variable::m_automatic_location == (*it)->m_descriptor.m_expected_location)
6931 {
6932 GLuint index = program.GetResourceIndex((*it)->m_descriptor.m_name, GL_PROGRAM_OUTPUT);
6933 GLint location = 0;
6934
6935 program.GetResource(GL_PROGRAM_OUTPUT, index, GL_LOCATION, 1 /* size */, &location);
6936
6937 (*it)->m_descriptor.m_expected_location = location;
6938 }
6939 }
6940 }
6941
6942 /** Prepare framebuffer with single texture as color attachment
6943 *
6944 * @param framebuffer Framebuffer
6945 * @param color_0_texture Texture that will used as color attachment
6946 **/
6947 void TextureTestBase::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
6948 {
6949 /* Prepare data */
6950 std::vector<GLuint> texture_data;
6951 texture_data.resize(m_width * m_height);
6952
6953 for (GLuint i = 0; i < texture_data.size(); ++i)
6954 {
6955 texture_data[i] = 0x20406080;
6956 }
6957
6958 /* Prepare texture */
6959 color_0_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6960 &texture_data[0]);
6961
6962 /* Prepare framebuffer */
6963 framebuffer.Init();
6964 framebuffer.Bind();
6965 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0, color_0_texture.m_id, m_width, m_height);
6966
6967 framebuffer.ClearColor(0.0f, 0.0f, 0.0f, 0.0f);
6968 framebuffer.Clear(GL_COLOR_BUFFER_BIT);
6969 }
6970
6971 /** Prepare iamge unit for compute shader
6972 *
6973 * @param location Uniform location
6974 * @param image_texture Texture that will used as color attachment
6975 **/
6976 void TextureTestBase::prepareImage(GLint location, Utils::Texture& image_texture) const
6977 {
6978 static const GLuint image_unit = 0;
6979
6980 std::vector<GLuint> texture_data;
6981 texture_data.resize(m_width * m_height);
6982
6983 for (GLuint i = 0; i < texture_data.size(); ++i)
6984 {
6985 texture_data[i] = 0x20406080;
6986 }
6987
6988 image_texture.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_R32UI, GL_RED_INTEGER, GL_UNSIGNED_INT,
6989 &texture_data[0]);
6990
6991 const Functions& gl = m_context.getRenderContext().getFunctions();
6992
6993 gl.bindImageTexture(image_unit, image_texture.m_id, 0 /* level */, GL_FALSE /* layered */, 0 /* Layer */,
6994 GL_WRITE_ONLY, GL_R32UI);
6995 GLU_EXPECT_NO_ERROR(gl.getError(), "BindImageTexture");
6996
6997 Utils::Program::Uniform(gl, Utils::Type::_int, 1 /* count */, location, &image_unit);
6998 }
6999
7000 /** Basic implementation
7001 *
7002 * @param ignored
7003 * @param si Shader interface
7004 * @param program Program
7005 * @param cs_buffer Buffer for ssb blocks
7006 **/
7007 void TextureTestBase::prepareSSBs(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
7008 Utils::Buffer& buffer)
7009 {
7010 /* Skip if there are no input variables in vertex shader */
7011 if (0 == si.m_ssb_blocks.size())
7012 {
7013 return;
7014 }
7015
7016 /* Calculate vertex stride */
7017 GLint ssbs_stride = 0;
7018
7019 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
7020 {
7021 Utils::Variable& variable = *si.m_ssb_blocks[i];
7022
7023 if (false == variable.IsBlock())
7024 {
7025 continue;
7026 }
7027
7028 GLint variable_stride = variable.GetStride();
7029
7030 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
7031
7032 ssbs_stride = std::max(ssbs_stride, ends_at);
7033 }
7034
7035 /* Set active program */
7036 program.Use();
7037
7038 /* Allocate */
7039 buffer.Bind();
7040 buffer.Data(Utils::Buffer::StaticDraw, ssbs_stride, 0);
7041
7042 /* Set up uniforms */
7043 for (GLuint i = 0; i < si.m_ssb_blocks.size(); ++i)
7044 {
7045 Utils::Variable& variable = *si.m_ssb_blocks[i];
7046
7047 /* prepareUnifor should work fine for ssb blocks */
7048 prepareUniform(program, variable, buffer);
7049 }
7050 }
7051
7052 /** Basic implementation
7053 *
7054 * @param test_case_index Test case index
7055 * @param program_interface Program interface
7056 * @param program Program
7057 * @param cs_buffer Buffer for compute shader stage
7058 **/
7059 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7060 Utils::Program& program, Utils::Buffer& cs_buffer)
7061 {
7062 cs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7063
7064 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
7065
7066 prepareSSBs(test_case_index, cs, program, cs_buffer);
7067
7068 cs_buffer.BindBase(Utils::Shader::COMPUTE);
7069 }
7070
7071 /** Basic implementation
7072 *
7073 * @param test_case_index Test case index
7074 * @param program_interface Program interface
7075 * @param program Program
7076 * @param fs_buffer Buffer for fragment shader stage
7077 * @param gs_buffer Buffer for geometry shader stage
7078 * @param tcs_buffer Buffer for tessellation control shader stage
7079 * @param tes_buffer Buffer for tessellation evaluation shader stage
7080 * @param vs_buffer Buffer for vertex shader stage
7081 **/
7082 void TextureTestBase::prepareSSBs(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7083 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7084 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7085 {
7086 fs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7087 gs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7088 tcs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7089 tes_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7090 vs_buffer.Init(Utils::Buffer::Shader_Storage, Utils::Buffer::StaticDraw, 0, 0);
7091
7092 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7093 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7094 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7095 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7096 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7097
7098 prepareSSBs(test_case_index, fs, program, fs_buffer);
7099 prepareSSBs(test_case_index, gs, program, gs_buffer);
7100 prepareSSBs(test_case_index, tcs, program, tcs_buffer);
7101 prepareSSBs(test_case_index, tes, program, tes_buffer);
7102 prepareSSBs(test_case_index, vs, program, vs_buffer);
7103
7104 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7105 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7106 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7107 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7108 vs_buffer.BindBase(Utils::Shader::VERTEX);
7109 }
7110
7111 /** Updates buffer data with variable
7112 *
7113 * @param program Program object
7114 * @param variable Variable
7115 * @param buffer Buffer
7116 **/
7117 void TextureTestBase::prepareUniform(Utils::Program& program, Utils::Variable& variable, Utils::Buffer& buffer)
7118 {
7119 const Functions& gl = m_context.getRenderContext().getFunctions();
7120
7121 GLsizei count = variable.m_descriptor.m_n_array_elements;
7122 if (0 == count)
7123 {
7124 count = 1;
7125 }
7126
7127 if (Utils::Variable::BUILTIN == variable.m_descriptor.m_type)
7128 {
7129 program.Uniform(gl, variable.m_descriptor.m_builtin, count, variable.m_descriptor.m_expected_location,
7130 variable.m_data);
7131 }
7132 else
7133 {
7134 const bool is_block = variable.IsBlock();
7135
7136 if (false == is_block)
7137 {
7138 TCU_FAIL("Not implemented");
7139 }
7140 else
7141 {
7142 buffer.SubData(variable.m_descriptor.m_offset, variable.m_descriptor.m_expected_stride_of_element * count,
7143 variable.m_data);
7144 }
7145 }
7146 }
7147
7148 /** Basic implementation
7149 *
7150 * @param ignored
7151 * @param si Shader interface
7152 * @param program Program
7153 * @param cs_buffer Buffer for uniform blocks
7154 **/
7155 void TextureTestBase::prepareUniforms(GLuint /* test_case_index */, Utils::ShaderInterface& si, Utils::Program& program,
7156 Utils::Buffer& buffer)
7157 {
7158 /* Skip if there are no input variables in vertex shader */
7159 if (0 == si.m_uniforms.size())
7160 {
7161 return;
7162 }
7163
7164 /* Calculate vertex stride */
7165 GLint uniforms_stride = 0;
7166
7167 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7168 {
7169 Utils::Variable& variable = *si.m_uniforms[i];
7170
7171 if (false == variable.IsBlock())
7172 {
7173 continue;
7174 }
7175
7176 GLint variable_stride = variable.GetStride();
7177
7178 GLint ends_at = variable_stride + variable.m_descriptor.m_offset;
7179
7180 uniforms_stride = std::max(uniforms_stride, ends_at);
7181 }
7182
7183 /* Set active program */
7184 program.Use();
7185
7186 /* Allocate */
7187 buffer.Bind();
7188 buffer.Data(Utils::Buffer::StaticDraw, uniforms_stride, 0);
7189
7190 /* Set up uniforms */
7191 for (GLuint i = 0; i < si.m_uniforms.size(); ++i)
7192 {
7193 Utils::Variable& variable = *si.m_uniforms[i];
7194
7195 prepareUniform(program, variable, buffer);
7196 }
7197 }
7198
7199 /** Basic implementation
7200 *
7201 * @param test_case_index Test case index
7202 * @param program_interface Program interface
7203 * @param program Program
7204 * @param cs_buffer Buffer for compute shader stage
7205 **/
7206 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7207 Utils::Program& program, Utils::Buffer& cs_buffer)
7208 {
7209 cs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7210
7211 Utils::ShaderInterface& cs = program_interface.GetShaderInterface(Utils::Shader::COMPUTE);
7212
7213 prepareUniforms(test_case_index, cs, program, cs_buffer);
7214
7215 cs_buffer.BindBase(Utils::Shader::COMPUTE);
7216 }
7217
7218 /** Basic implementation
7219 *
7220 * @param test_case_index Test case index
7221 * @param program_interface Program interface
7222 * @param program Program
7223 * @param fs_buffer Buffer for fragment shader stage
7224 * @param gs_buffer Buffer for geometry shader stage
7225 * @param tcs_buffer Buffer for tessellation control shader stage
7226 * @param tes_buffer Buffer for tessellation evaluation shader stage
7227 * @param vs_buffer Buffer for vertex shader stage
7228 **/
7229 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7230 Utils::Program& program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7231 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7232 {
7233 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7234 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7235 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7236 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7237 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7238
7239 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7240 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7241 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7242 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7243 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7244
7245 prepareUniforms(test_case_index, fs, program, fs_buffer);
7246 prepareUniforms(test_case_index, gs, program, gs_buffer);
7247 prepareUniforms(test_case_index, tcs, program, tcs_buffer);
7248 prepareUniforms(test_case_index, tes, program, tes_buffer);
7249 prepareUniforms(test_case_index, vs, program, vs_buffer);
7250
7251 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7252 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7253 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7254 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7255 vs_buffer.BindBase(Utils::Shader::VERTEX);
7256 }
7257
7258 /** Basic implementation
7259 *
7260 * @param test_case_index Test case index
7261 * @param program_interface Program interface
7262 * @param program Program
7263 * @param fs_buffer Buffer for fragment shader stage
7264 * @param gs_buffer Buffer for geometry shader stage
7265 * @param tcs_buffer Buffer for tessellation control shader stage
7266 * @param tes_buffer Buffer for tessellation evaluation shader stage
7267 * @param vs_buffer Buffer for vertex shader stage
7268 **/
7269 void TextureTestBase::prepareUniforms(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7270 Utils::Program& fs_program, Utils::Program& gs_program,
7271 Utils::Program& tcs_program, Utils::Program& tes_program,
7272 Utils::Program& vs_program, Utils::Buffer& fs_buffer, Utils::Buffer& gs_buffer,
7273 Utils::Buffer& tcs_buffer, Utils::Buffer& tes_buffer, Utils::Buffer& vs_buffer)
7274 {
7275 fs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7276 gs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7277 tcs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7278 tes_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7279 vs_buffer.Init(Utils::Buffer::Uniform, Utils::Buffer::StaticDraw, 0, 0);
7280
7281 Utils::ShaderInterface& fs = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
7282 Utils::ShaderInterface& gs = program_interface.GetShaderInterface(Utils::Shader::GEOMETRY);
7283 Utils::ShaderInterface& tcs = program_interface.GetShaderInterface(Utils::Shader::TESS_CTRL);
7284 Utils::ShaderInterface& tes = program_interface.GetShaderInterface(Utils::Shader::TESS_EVAL);
7285 Utils::ShaderInterface& vs = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
7286
7287 prepareUniforms(test_case_index, fs, fs_program, fs_buffer);
7288 fs_buffer.BindBase(Utils::Shader::FRAGMENT);
7289
7290 prepareUniforms(test_case_index, gs, gs_program, gs_buffer);
7291 gs_buffer.BindBase(Utils::Shader::GEOMETRY);
7292
7293 prepareUniforms(test_case_index, tcs, tcs_program, tcs_buffer);
7294 tcs_buffer.BindBase(Utils::Shader::TESS_CTRL);
7295
7296 prepareUniforms(test_case_index, tes, tes_program, tes_buffer);
7297 tes_buffer.BindBase(Utils::Shader::TESS_EVAL);
7298
7299 prepareUniforms(test_case_index, vs, vs_program, vs_buffer);
7300 vs_buffer.BindBase(Utils::Shader::VERTEX);
7301 }
7302
7303 /** Prepare source for shader
7304 *
7305 * @param test_case_index Index of test case
7306 * @param program_interface Interface of program
7307 * @param varying_passthrough Collection of connection between in and out variables
7308 * @param stage Shader stage
7309 *
7310 * @return Source of shader
7311 **/
7312 std::string TextureTestBase::getShaderSource(GLuint test_case_index, Utils::ProgramInterface& program_interface,
7313 Utils::VaryingPassthrough& varying_passthrough,
7314 Utils::Shader::STAGES stage)
7315 {
7316 /* Get strings */
7317 const GLchar* shader_template = getShaderTemplate(stage);
7318 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType());
7319 const char* shader_version = glu::getGLSLVersionDeclaration(glslVersion);
7320 const std::string& shader_interface = program_interface.GetInterfaceForStage(stage);
7321 const std::string& verification = getVerificationSnippet(test_case_index, program_interface, stage);
7322 const std::string& passthrough = getPassSnippet(test_case_index, varying_passthrough, stage);
7323
7324 const GLchar* per_vertex = "";
7325
7326 std::string source = shader_template;
7327 size_t position = 0;
7328
7329 Utils::replaceToken("VERSION", position, shader_version, source);
7330
7331 /* Replace tokens in template */
7332 if (Utils::Shader::GEOMETRY == stage)
7333 {
7334 if (false == useMonolithicProgram(test_case_index))
7335 {
7336 per_vertex = "out gl_PerVertex {\n"
7337 "vec4 gl_Position;\n"
7338 "};\n"
7339 "\n";
7340 }
7341
7342 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
7343 }
7344
7345 Utils::replaceToken("INTERFACE", position, shader_interface.c_str(), source);
7346 Utils::replaceToken("VERIFICATION", position, verification.c_str(), source);
7347
7348 if (false == verification.empty())
7349 {
7350 Utils::replaceAllTokens("ELSE", " else ", source);
7351 }
7352 else
7353 {
7354 Utils::replaceAllTokens("ELSE", "", source);
7355 }
7356
7357 Utils::replaceAllTokens("PASSTHROUGH", passthrough.c_str(), source);
7358
7359 /* Done */
7360 return source;
7361 }
7362
7363 /** Returns template of shader for given stage
7364 *
7365 * @param stage Shade stage
7366 *
7367 * @return Proper template
7368 **/
7369 const GLchar* TextureTestBase::getShaderTemplate(Utils::Shader::STAGES stage)
7370 {
7371
7372 static const GLchar* compute_shader_template =
7373 "VERSION\n"
7374 "#extension GL_ARB_enhanced_layouts : require\n"
7375 "\n"
7376 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
7377 "\n"
7378 "writeonly uniform uimage2D uni_image;\n"
7379 "\n"
7380 "INTERFACE"
7381 "\n"
7382 "void main()\n"
7383 "{\n"
7384 " uint result = 1u;\n"
7385 "\n"
7386 " VERIFICATION"
7387 "\n"
7388 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
7389 "}\n"
7390 "\n";
7391
7392 static const GLchar* fragment_shader_template = "VERSION\n"
7393 "#extension GL_ARB_enhanced_layouts : require\n"
7394 "\n"
7395 "flat in uint gs_fs_result;\n"
7396 " out uint fs_out_result;\n"
7397 "\n"
7398 "INTERFACE"
7399 "\n"
7400 "void main()\n"
7401 "{\n"
7402 " uint result = 1u;\n"
7403 "\n"
7404 " if (1u != gs_fs_result)\n"
7405 " {\n"
7406 " result = gs_fs_result;\n"
7407 " }\n"
7408 "ELSEVERIFICATION"
7409 "\n"
7410 " fs_out_result = result;\n"
7411 " PASSTHROUGH\n"
7412 "}\n"
7413 "\n";
7414
7415 static const GLchar* geometry_shader_template =
7416 "VERSION\n"
7417 "#extension GL_ARB_enhanced_layouts : require\n"
7418 "\n"
7419 "layout(points) in;\n"
7420 "layout(triangle_strip, max_vertices = 4) out;\n"
7421 "\n"
7422 " in uint tes_gs_result[];\n"
7423 " flat out uint gs_fs_result;\n"
7424 "\n"
7425 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
7426 "INTERFACE"
7427 "\n"
7428 "void main()\n"
7429 "{\n"
7430 " uint result = 1u;\n"
7431 "\n"
7432 " if (1u != tes_gs_result[0])\n"
7433 " {\n"
7434 " result = tes_gs_result[0];\n"
7435 " }\n"
7436 "ELSEVERIFICATION"
7437 "\n"
7438 " gs_fs_result = result;\n"
7439 " PASSTHROUGH\n"
7440 " gl_Position = vec4(-1, -1, 0, 1);\n"
7441 " EmitVertex();\n"
7442 " gs_fs_result = result;\n"
7443 " PASSTHROUGH\n"
7444 " gl_Position = vec4(-1, 1, 0, 1);\n"
7445 " EmitVertex();\n"
7446 " gs_fs_result = result;\n"
7447 " PASSTHROUGH\n"
7448 " gl_Position = vec4(1, -1, 0, 1);\n"
7449 " EmitVertex();\n"
7450 " gs_fs_result = result;\n"
7451 " PASSTHROUGH\n"
7452 " gl_Position = vec4(1, 1, 0, 1);\n"
7453 " EmitVertex();\n"
7454 "}\n"
7455 "\n";
7456
7457 static const GLchar* tess_ctrl_shader_template = "VERSION\n"
7458 "#extension GL_ARB_enhanced_layouts : require\n"
7459 "\n"
7460 "layout(vertices = 1) out;\n"
7461 "\n"
7462 "in uint vs_tcs_result[];\n"
7463 "out uint tcs_tes_result[];\n"
7464 "\n"
7465 "INTERFACE"
7466 "\n"
7467 "void main()\n"
7468 "{\n"
7469 " uint result = 1u;\n"
7470 "\n"
7471 " if (1u != vs_tcs_result[gl_InvocationID])\n"
7472 " {\n"
7473 " result = vs_tcs_result[gl_InvocationID];\n"
7474 " }\n"
7475 "ELSEVERIFICATION"
7476 "\n"
7477 " tcs_tes_result[gl_InvocationID] = result;\n"
7478 "\n"
7479 " PASSTHROUGH\n"
7480 "\n"
7481 " gl_TessLevelOuter[0] = 1.0;\n"
7482 " gl_TessLevelOuter[1] = 1.0;\n"
7483 " gl_TessLevelOuter[2] = 1.0;\n"
7484 " gl_TessLevelOuter[3] = 1.0;\n"
7485 " gl_TessLevelInner[0] = 1.0;\n"
7486 " gl_TessLevelInner[1] = 1.0;\n"
7487 "}\n"
7488 "\n";
7489
7490 static const GLchar* tess_eval_shader_template = "VERSION\n"
7491 "#extension GL_ARB_enhanced_layouts : require\n"
7492 "\n"
7493 "layout(isolines, point_mode) in;\n"
7494 "\n"
7495 "in uint tcs_tes_result[];\n"
7496 "out uint tes_gs_result;\n"
7497 "\n"
7498 "INTERFACE"
7499 "\n"
7500 "void main()\n"
7501 "{\n"
7502 " uint result = 1u;\n"
7503 "\n"
7504 " if (1u != tcs_tes_result[0])\n"
7505 " {\n"
7506 " result = tcs_tes_result[0];\n"
7507 " }\n"
7508 "ELSEVERIFICATION"
7509 "\n"
7510 " tes_gs_result = result;\n"
7511 "\n"
7512 " PASSTHROUGH\n"
7513 "}\n"
7514 "\n";
7515
7516 static const GLchar* vertex_shader_template = "VERSION\n"
7517 "#extension GL_ARB_enhanced_layouts : require\n"
7518 "\n"
7519 "out uint vs_tcs_result;\n"
7520 "\n"
7521 "INTERFACE"
7522 "\n"
7523 "void main()\n"
7524 "{\n"
7525 " uint result = 1u;\n"
7526 "\n"
7527 " VERIFICATION\n"
7528 "\n"
7529 " vs_tcs_result = result;\n"
7530 "\n"
7531 " PASSTHROUGH\n"
7532 "}\n"
7533 "\n";
7534
7535 const GLchar* result = 0;
7536
7537 switch (stage)
7538 {
7539 case Utils::Shader::COMPUTE:
7540 result = compute_shader_template;
7541 break;
7542 case Utils::Shader::FRAGMENT:
7543 result = fragment_shader_template;
7544 break;
7545 case Utils::Shader::GEOMETRY:
7546 result = geometry_shader_template;
7547 break;
7548 case Utils::Shader::TESS_CTRL:
7549 result = tess_ctrl_shader_template;
7550 break;
7551 case Utils::Shader::TESS_EVAL:
7552 result = tess_eval_shader_template;
7553 break;
7554 case Utils::Shader::VERTEX:
7555 result = vertex_shader_template;
7556 break;
7557 default:
7558 TCU_FAIL("Invalid enum");
7559 }
7560
7561 return result;
7562 }
7563
7564 /** Runs test case
7565 *
7566 * @param test_case_index Id of test case
7567 *
7568 * @return true if test case pass, false otherwise
7569 **/
7570 bool TextureTestBase::testCase(GLuint test_case_index)
7571 {
7572 try
7573 {
7574 if (true == useMonolithicProgram(test_case_index))
7575 {
7576 return testMonolithic(test_case_index);
7577 }
7578 else
7579 {
7580 return testSeparable(test_case_index);
7581 }
7582 }
7583 catch (Utils::Shader::InvalidSourceException& exc)
7584 {
7585 exc.log(m_context);
7586 TCU_FAIL(exc.what());
7587 }
7588 catch (Utils::Program::BuildException& exc)
7589 {
7590 exc.log(m_context);
7591 TCU_FAIL(exc.what());
7592 }
7593 }
7594
7595 /** Runs "draw" test with monolithic program
7596 *
7597 * @param test_case_index Id of test case
7598 **/
7599 bool TextureTestBase::testMonolithic(GLuint test_case_index)
7600 {
7601 Utils::ProgramInterface program_interface;
7602 Utils::VaryingPassthrough varying_passthrough;
7603
7604 /* */
7605 const std::string& test_name = getTestCaseName(test_case_index);
7606
7607 /* */
7608 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7609
7610 bool result = true;
7611 /* Draw */
7612 if (true == isDrawRelevant(test_case_index))
7613 {
7614 Utils::Buffer buffer_attr(m_context);
7615 Utils::Buffer buffer_ssb_fs(m_context);
7616 Utils::Buffer buffer_ssb_gs(m_context);
7617 Utils::Buffer buffer_ssb_tcs(m_context);
7618 Utils::Buffer buffer_ssb_tes(m_context);
7619 Utils::Buffer buffer_ssb_vs(m_context);
7620 Utils::Buffer buffer_u_fs(m_context);
7621 Utils::Buffer buffer_u_gs(m_context);
7622 Utils::Buffer buffer_u_tcs(m_context);
7623 Utils::Buffer buffer_u_tes(m_context);
7624 Utils::Buffer buffer_u_vs(m_context);
7625 Utils::Framebuffer framebuffer(m_context);
7626 Utils::Program program(m_context);
7627 Utils::Texture texture_fb(m_context);
7628 Utils::VertexArray vao(m_context);
7629
7630 /* */
7631 const std::string& fragment_shader =
7632 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7633 const std::string& geometry_shader =
7634 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7635 const std::string& tess_ctrl_shader =
7636 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7637 const std::string& tess_eval_shader =
7638 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7639 const std::string& vertex_shader =
7640 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7641
7642 program.Init("" /* compute_shader */, fragment_shader, geometry_shader, tess_ctrl_shader, tess_eval_shader,
7643 vertex_shader, false /* is_separable */);
7644
7645 /* */
7646 prepareAttribLocation(program, program_interface);
7647 prepareFragmentDataLoc(program, program_interface);
7648
7649 /* */
7650 std::stringstream stream;
7651 if (false == Utils::checkMonolithicDrawProgramInterface(program, program_interface, stream))
7652 {
7653 m_context.getTestContext().getLog()
7654 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7655 << ". Inspection of draw program interface failed:\n"
7656 << stream.str() << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7657 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7658 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7659
7660 return false;
7661 }
7662
7663 /* */
7664 program.Use();
7665
7666 /* */
7667 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7668 vao.Init();
7669 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7670
7671 /* */
7672 prepareUniforms(test_case_index, program_interface, program, buffer_u_fs, buffer_u_gs, buffer_u_tcs,
7673 buffer_u_tes, buffer_u_vs);
7674
7675 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_fs, buffer_ssb_gs, buffer_ssb_tcs,
7676 buffer_ssb_tes, buffer_ssb_vs);
7677
7678 /* */
7679 prepareFramebuffer(framebuffer, texture_fb);
7680
7681 /* Draw */
7682 executeDrawCall(test_case_index);
7683
7684 #if USE_NSIGHT
7685 m_context.getRenderContext().postIterate();
7686 #endif
7687
7688 /* Check results */
7689 if (false == checkResults(test_case_index, texture_fb))
7690 {
7691 m_context.getTestContext().getLog()
7692 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7693 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vertex_shader)
7694 << tcu::TestLog::KernelSource(tess_ctrl_shader) << tcu::TestLog::KernelSource(tess_eval_shader)
7695 << tcu::TestLog::KernelSource(geometry_shader) << tcu::TestLog::KernelSource(fragment_shader);
7696
7697 result = false;
7698 }
7699 }
7700
7701 /* Compute */
7702 if (true == isComputeRelevant(test_case_index))
7703 {
7704 Utils::Buffer buffer_ssb_cs(m_context);
7705 Utils::Buffer buffer_u_cs(m_context);
7706 Utils::Program program(m_context);
7707 Utils::Texture texture_im(m_context);
7708 Utils::VertexArray vao(m_context);
7709
7710 /* */
7711 const std::string& compute_shader =
7712 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7713
7714 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7715 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7716
7717 /* */
7718 {
7719 std::stringstream stream;
7720
7721 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7722 {
7723 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7724 << ". Inspection of compute program interface failed:\n"
7725 << stream.str() << tcu::TestLog::EndMessage;
7726
7727 return false;
7728 }
7729 }
7730
7731 /* */
7732 program.Use();
7733
7734 /* */
7735 vao.Init();
7736 vao.Bind();
7737
7738 /* */
7739 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7740
7741 prepareSSBs(test_case_index, program_interface, program, buffer_ssb_cs);
7742
7743 /* */
7744 GLint image_location = program.GetUniformLocation("uni_image");
7745 prepareImage(image_location, texture_im);
7746
7747 /* Draw */
7748 executeDispatchCall(test_case_index);
7749
7750 #if USE_NSIGHT
7751 m_context.getRenderContext().postIterate();
7752 #endif
7753
7754 /* Check results */
7755 if (false == checkResults(test_case_index, texture_im))
7756 {
7757 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7758 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7759 << tcu::TestLog::KernelSource(compute_shader);
7760
7761 result = false;
7762 }
7763 }
7764
7765 return result;
7766 }
7767
7768 /** Runs "draw" test with separable program
7769 *
7770 * @param test_case_index Id of test case
7771 **/
7772 bool TextureTestBase::testSeparable(GLuint test_case_index)
7773 {
7774 Utils::ProgramInterface program_interface;
7775 Utils::VaryingPassthrough varying_passthrough;
7776
7777 /* */
7778 const std::string& test_name = getTestCaseName(test_case_index);
7779
7780 /* */
7781 getProgramInterface(test_case_index, program_interface, varying_passthrough);
7782
7783 bool result = true;
7784 /* Draw */
7785 if (true == isDrawRelevant(test_case_index))
7786 {
7787 Utils::Buffer buffer_attr(m_context);
7788 Utils::Buffer buffer_u_fs(m_context);
7789 Utils::Buffer buffer_u_gs(m_context);
7790 Utils::Buffer buffer_u_tcs(m_context);
7791 Utils::Buffer buffer_u_tes(m_context);
7792 Utils::Buffer buffer_u_vs(m_context);
7793 Utils::Framebuffer framebuffer(m_context);
7794 Utils::Pipeline pipeline(m_context);
7795 Utils::Program program_fs(m_context);
7796 Utils::Program program_gs(m_context);
7797 Utils::Program program_tcs(m_context);
7798 Utils::Program program_tes(m_context);
7799 Utils::Program program_vs(m_context);
7800 Utils::Texture texture_fb(m_context);
7801 Utils::VertexArray vao(m_context);
7802
7803 /* */
7804 const std::string& fs =
7805 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::FRAGMENT);
7806 const std::string& gs =
7807 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::GEOMETRY);
7808 const std::string& tcs =
7809 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_CTRL);
7810 const std::string& tes =
7811 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::TESS_EVAL);
7812 const std::string& vs =
7813 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::VERTEX);
7814
7815 program_fs.Init("" /*cs*/, fs, "" /*gs*/, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7816 program_gs.Init("" /*cs*/, "" /*fs*/, gs, "" /*tcs*/, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7817 program_tcs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, tcs, "" /*tes*/, "" /*vs*/, true /* is_separable */);
7818 program_tes.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, tes, "" /*vs*/, true /* is_separable */);
7819 program_vs.Init("" /*cs*/, "" /*fs*/, "" /*gs*/, "" /*tcs*/, "" /*tes*/, vs, true /* is_separable */);
7820
7821 /* */
7822 prepareAttribLocation(program_vs, program_interface);
7823 prepareFragmentDataLoc(program_vs, program_interface);
7824
7825 /* */
7826 std::stringstream stream;
7827 if ((false ==
7828 Utils::checkSeparableDrawProgramInterface(program_vs, program_interface, Utils::Shader::VERTEX, stream)) ||
7829 (false == Utils::checkSeparableDrawProgramInterface(program_fs, program_interface, Utils::Shader::FRAGMENT,
7830 stream)) ||
7831 (false == Utils::checkSeparableDrawProgramInterface(program_gs, program_interface, Utils::Shader::GEOMETRY,
7832 stream)) ||
7833 (false == Utils::checkSeparableDrawProgramInterface(program_tcs, program_interface,
7834 Utils::Shader::TESS_CTRL, stream)) ||
7835 (false == Utils::checkSeparableDrawProgramInterface(program_tes, program_interface,
7836 Utils::Shader::TESS_EVAL, stream)))
7837 {
7838 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7839 << ". Inspection of separable draw program interface failed:\n"
7840 << stream.str() << tcu::TestLog::EndMessage
7841 << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7842 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs)
7843 << tcu::TestLog::KernelSource(fs);
7844
7845 return false;
7846 }
7847
7848 /* */
7849 pipeline.Init();
7850 pipeline.UseProgramStages(program_fs.m_id, GL_FRAGMENT_SHADER_BIT);
7851 pipeline.UseProgramStages(program_gs.m_id, GL_GEOMETRY_SHADER_BIT);
7852 pipeline.UseProgramStages(program_tcs.m_id, GL_TESS_CONTROL_SHADER_BIT);
7853 pipeline.UseProgramStages(program_tes.m_id, GL_TESS_EVALUATION_SHADER_BIT);
7854 pipeline.UseProgramStages(program_vs.m_id, GL_VERTEX_SHADER_BIT);
7855 pipeline.Bind();
7856
7857 /* */
7858
7859 buffer_attr.Init(Utils::Buffer::Array, Utils::Buffer::StaticDraw, 0, 0);
7860 vao.Init();
7861 prepareAttributes(test_case_index, program_interface, buffer_attr, vao);
7862
7863 /* */
7864 prepareUniforms(test_case_index, program_interface, program_fs, program_gs, program_tcs, program_tes,
7865 program_vs, buffer_u_fs, buffer_u_gs, buffer_u_tcs, buffer_u_tes, buffer_u_vs);
7866
7867 Utils::Program::Use(m_context.getRenderContext().getFunctions(), Utils::Program::m_invalid_id);
7868
7869 /* */
7870 prepareFramebuffer(framebuffer, texture_fb);
7871
7872 /* Draw */
7873 executeDrawCall(test_case_index);
7874
7875 #if USE_NSIGHT
7876 m_context.getRenderContext().postIterate();
7877 #endif
7878
7879 /* Check results */
7880 if (false == checkResults(test_case_index, texture_fb))
7881 {
7882 m_context.getTestContext().getLog()
7883 << tcu::TestLog::Message << "FAILURE. Test case: " << test_name << ". Draw - invalid results."
7884 << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vs) << tcu::TestLog::KernelSource(tcs)
7885 << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs) << tcu::TestLog::KernelSource(fs);
7886
7887 result = false;
7888 }
7889 else
7890 {
7891 m_context.getTestContext().getLog()
7892 << tcu::TestLog::Message << "Success." << tcu::TestLog::EndMessage << tcu::TestLog::KernelSource(vs)
7893 << tcu::TestLog::KernelSource(tcs) << tcu::TestLog::KernelSource(tes) << tcu::TestLog::KernelSource(gs)
7894 << tcu::TestLog::KernelSource(fs);
7895 }
7896 }
7897
7898 /* Compute */
7899 if (true == isComputeRelevant(test_case_index))
7900 {
7901 Utils::Buffer buffer_u_cs(m_context);
7902 Utils::Program program(m_context);
7903 Utils::Texture texture_im(m_context);
7904 Utils::VertexArray vao(m_context);
7905
7906 /* */
7907 const std::string& compute_shader =
7908 getShaderSource(test_case_index, program_interface, varying_passthrough, Utils::Shader::COMPUTE);
7909
7910 program.Init(compute_shader, "" /* fragment_shader */, "" /* geometry_shader */, "" /* tess_ctrl_shader */,
7911 "" /* tess_eval_shader */, "" /* vertex_shader */, false /* is_separable */);
7912
7913 /* */
7914 {
7915 std::stringstream stream;
7916
7917 if (false == Utils::checkMonolithicComputeProgramInterface(program, program_interface, stream))
7918 {
7919 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7920 << ". Inspection of compute program interface failed:\n"
7921 << stream.str() << tcu::TestLog::EndMessage;
7922
7923 return false;
7924 }
7925 }
7926
7927 /* */
7928 program.Use();
7929
7930 /* */
7931 vao.Init();
7932 vao.Bind();
7933
7934 /* */
7935 prepareUniforms(test_case_index, program_interface, program, buffer_u_cs);
7936
7937 /* */
7938 GLint image_location = program.GetUniformLocation("uni_image");
7939 prepareImage(image_location, texture_im);
7940
7941 /* Draw */
7942 executeDispatchCall(test_case_index);
7943
7944 #if USE_NSIGHT
7945 m_context.getRenderContext().postIterate();
7946 #endif
7947
7948 /* Check results */
7949 if (false == checkResults(test_case_index, texture_im))
7950 {
7951 m_context.getTestContext().getLog() << tcu::TestLog::Message << "FAILURE. Test case: " << test_name
7952 << ". Compute - invalid results." << tcu::TestLog::EndMessage
7953 << tcu::TestLog::KernelSource(compute_shader);
7954
7955 result = false;
7956 }
7957 }
7958
7959 return result;
7960 }
7961
7962 /** Basic implementation
7963 *
7964 * @param ignored
7965 *
7966 * @return false
7967 **/
7968 bool TextureTestBase::useComponentQualifier(glw::GLuint /* test_case_index */)
7969 {
7970 return false;
7971 }
7972
7973 /** Basic implementation
7974 *
7975 * @param ignored
7976 *
7977 * @return true
7978 **/
7979 bool TextureTestBase::useMonolithicProgram(GLuint /* test_case_index */)
7980 {
7981 return true;
7982 }
7983
7984 /** Constructor
7985 *
7986 * @param context Test framework context
7987 **/
7988 APIConstantValuesTest::APIConstantValuesTest(deqp::Context& context)
7989 : TestCase(context, "api_constant_values", "Test verifies values of api constants")
7990 {
7991 /* Nothing to be done here */
7992 }
7993
7994 /** Execute test
7995 *
7996 * @return tcu::TestNode::STOP otherwise
7997 **/
7998 tcu::TestNode::IterateResult APIConstantValuesTest::iterate()
7999 {
8000 static const GLuint expected_comp = 64;
8001 static const GLuint expected_xfb = 4;
8002 static const GLuint expected_sep = 4;
8003 GLint max_comp = 0;
8004 GLint max_xfb = 0;
8005 GLint max_sep = 0;
8006 bool test_result = true;
8007
8008 const Functions& gl = m_context.getRenderContext().getFunctions();
8009
8010 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_xfb);
8011 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8012 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_comp);
8013 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8014 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_sep);
8015 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8016
8017 if (expected_xfb > (GLuint)max_xfb)
8018 {
8019 m_context.getTestContext().getLog() << tcu::TestLog::Message
8020 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_BUFFERS. Got " << max_xfb
8021 << " Expected at least " << expected_xfb << tcu::TestLog::EndMessage;
8022
8023 test_result = false;
8024 }
8025
8026 if (expected_comp > (GLuint)max_comp)
8027 {
8028 m_context.getTestContext().getLog()
8029 << tcu::TestLog::Message << "Invalid GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. Got " << max_comp
8030 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
8031
8032 test_result = false;
8033 }
8034
8035 if (expected_sep > (GLuint)max_sep)
8036 {
8037 m_context.getTestContext().getLog() << tcu::TestLog::Message
8038 << "Invalid GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS. Got " << max_comp
8039 << " Expected at least " << expected_comp << tcu::TestLog::EndMessage;
8040
8041 test_result = false;
8042 }
8043
8044 /* Set result */
8045 if (true == test_result)
8046 {
8047 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
8048 }
8049 else
8050 {
8051 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8052 }
8053
8054 /* Done */
8055 return tcu::TestNode::STOP;
8056 }
8057
8058 /** Constructor
8059 *
8060 * @param context Test framework context
8061 **/
8062 APIErrorsTest::APIErrorsTest(deqp::Context& context)
8063 : TestCase(context, "api_errors", "Test verifies errors reeturned by api")
8064 {
8065 /* Nothing to be done here */
8066 }
8067
8068 /** Execute test
8069 *
8070 * @return tcu::TestNode::STOP otherwise
8071 **/
8072 tcu::TestNode::IterateResult APIErrorsTest::iterate()
8073 {
8074 GLint length = 0;
8075 GLchar name[64];
8076 GLint param = 0;
8077 Utils::Program program(m_context);
8078 bool test_result = true;
8079
8080 const Functions& gl = m_context.getRenderContext().getFunctions();
8081
8082 try
8083 {
8084 program.Init("" /* cs */, "#version 430 core\n"
8085 "#extension GL_ARB_enhanced_layouts : require\n"
8086 "\n"
8087 "in vec4 vs_fs;\n"
8088 "out vec4 fs_out;\n"
8089 "\n"
8090 "void main()\n"
8091 "{\n"
8092 " fs_out = vs_fs;\n"
8093 "}\n"
8094 "\n" /* fs */,
8095 "" /* gs */, "" /* tcs */, "" /* tes */, "#version 430 core\n"
8096 "#extension GL_ARB_enhanced_layouts : require\n"
8097 "\n"
8098 "in vec4 in_vs;\n"
8099 "layout (xfb_offset = 16) out vec4 vs_fs;\n"
8100 "\n"
8101 "void main()\n"
8102 "{\n"
8103 " vs_fs = in_vs;\n"
8104 "}\n"
8105 "\n" /* vs */,
8106 false /* separable */);
8107 }
8108 catch (Utils::Shader::InvalidSourceException& exc)
8109 {
8110 exc.log(m_context);
8111 TCU_FAIL(exc.what());
8112 }
8113 catch (Utils::Program::BuildException& exc)
8114 {
8115 TCU_FAIL(exc.what());
8116 }
8117
8118 /*
8119 * - GetProgramInterfaceiv should generate INVALID_OPERATION when
8120 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER and <pname> is one of the
8121 * following:
8122 * * MAX_NAME_LENGTH,
8123 * * MAX_NUM_ACTIVE_VARIABLES;
8124 */
8125 gl.getProgramInterfaceiv(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH, ¶m);
8126 checkError(GL_INVALID_OPERATION, "GetProgramInterfaceiv(GL_TRANSFORM_FEEDBACK_BUFFER, GL_MAX_NAME_LENGTH)",
8127 test_result);
8128
8129 /*
8130 * - GetProgramResourceIndex should generate INVALID_ENUM when
8131 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8132 */
8133 gl.getProgramResourceIndex(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, "0");
8134 checkError(GL_INVALID_ENUM, "GetProgramResourceIndex(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8135 /*
8136 * - GetProgramResourceName should generate INVALID_ENUM when
8137 * <programInterface> is TRANSFORM_FEEDBACK_BUFFER;
8138 */
8139 gl.getProgramResourceName(program.m_id, GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 64 /* bufSize */, &length,
8140 name);
8141 checkError(GL_INVALID_ENUM, "GetProgramResourceName(GL_TRANSFORM_FEEDBACK_BUFFER)", test_result);
8142
8143 /* Set result */
8144 if (true == test_result)
8145 {
8146 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Pass");
8147 }
8148 else
8149 {
8150 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Fail");
8151 }
8152
8153 /* Done */
8154 return tcu::TestNode::STOP;
8155 }
8156
8157 /** Check if error is the expected one.
8158 *
8159 * @param expected_error Expected error
8160 * @param message Message to log in case of error
8161 * @param test_result Test result, set to false in case of invalid error
8162 **/
8163 void APIErrorsTest::checkError(GLenum expected_error, const GLchar* message, bool& test_result)
8164 {
8165 const Functions& gl = m_context.getRenderContext().getFunctions();
8166
8167 GLenum error = gl.getError();
8168
8169 if (error != expected_error)
8170 {
8171 m_context.getTestContext().getLog()
8172 << tcu::TestLog::Message << "Failure. Invalid error. Got " << glu::getErrorStr(error) << " expected "
8173 << glu::getErrorStr(expected_error) << " Msg: " << message << tcu::TestLog::EndMessage;
8174
8175 test_result = false;
8176 }
8177 }
8178
8179 /** Constructor
8180 *
8181 * @param context Test framework context
8182 **/
8183 GLSLContantImmutablityTest::GLSLContantImmutablityTest(deqp::Context& context)
8184 : NegativeTestBase(context, "glsl_contant_immutablity", "Test verifies that glsl constants cannot be modified")
8185 {
8186 /* Nothing to be done here */
8187 }
8188
8189 /** Source for given test case and stage
8190 *
8191 * @param test_case_index Index of test case
8192 * @param stage Shader stage
8193 *
8194 * @return Shader source
8195 **/
8196 std::string GLSLContantImmutablityTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
8197 {
8198 static const GLchar* cs = "#version 430 core\n"
8199 "#extension GL_ARB_enhanced_layouts : require\n"
8200 "\n"
8201 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8202 "\n"
8203 "writeonly uniform uimage2D uni_image;\n"
8204 "\n"
8205 "void main()\n"
8206 "{\n"
8207 " uint result = 1u;\n"
8208 " CONSTANT = 3;\n"
8209 "\n"
8210 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), uvec4(result, 0, 0, 0));\n"
8211 "}\n"
8212 "\n";
8213 static const GLchar* fs = "#version 430 core\n"
8214 "#extension GL_ARB_enhanced_layouts : require\n"
8215 "\n"
8216 "in vec4 gs_fs;\n"
8217 "out vec4 fs_out;\n"
8218 "\n"
8219 "void main()\n"
8220 "{\n"
8221 "ASSIGNMENT"
8222 " fs_out = gs_fs;\n"
8223 "}\n"
8224 "\n";
8225 static const GLchar* gs = "#version 430 core\n"
8226 "#extension GL_ARB_enhanced_layouts : require\n"
8227 "\n"
8228 "layout(points) in;\n"
8229 "layout(triangle_strip, max_vertices = 4) out;\n"
8230 "\n"
8231 "in vec4 tes_gs[];\n"
8232 "out vec4 gs_fs;\n"
8233 "\n"
8234 "void main()\n"
8235 "{\n"
8236 "ASSIGNMENT"
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 " gs_fs = tes_gs[0];\n"
8244 " gl_Position = vec4(1, -1, 0, 1);\n"
8245 " EmitVertex();\n"
8246 " gs_fs = tes_gs[0];\n"
8247 " gl_Position = vec4(1, 1, 0, 1);\n"
8248 " EmitVertex();\n"
8249 "}\n"
8250 "\n";
8251 static const GLchar* tcs = "#version 430 core\n"
8252 "#extension GL_ARB_enhanced_layouts : require\n"
8253 "\n"
8254 "layout(vertices = 1) out;\n"
8255 "\n"
8256 "in vec4 vs_tcs[];\n"
8257 "out vec4 tcs_tes[];\n"
8258 "\n"
8259 "void main()\n"
8260 "{\n"
8261 "\n"
8262 "ASSIGNMENT"
8263 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
8264 "\n"
8265 " gl_TessLevelOuter[0] = 1.0;\n"
8266 " gl_TessLevelOuter[1] = 1.0;\n"
8267 " gl_TessLevelOuter[2] = 1.0;\n"
8268 " gl_TessLevelOuter[3] = 1.0;\n"
8269 " gl_TessLevelInner[0] = 1.0;\n"
8270 " gl_TessLevelInner[1] = 1.0;\n"
8271 "}\n"
8272 "\n";
8273 static const GLchar* tes = "#version 430 core\n"
8274 "#extension GL_ARB_enhanced_layouts : require\n"
8275 "\n"
8276 "layout(isolines, point_mode) in;\n"
8277 "\n"
8278 "in vec4 tcs_tes[];\n"
8279 "out vec4 tes_gs;\n"
8280 "\n"
8281 "void main()\n"
8282 "{\n"
8283 "ASSIGNMENT"
8284 " tes_gs = tcs_tes[0];\n"
8285 "}\n"
8286 "\n";
8287 static const GLchar* vs = "#version 430 core\n"
8288 "#extension GL_ARB_enhanced_layouts : require\n"
8289 "\n"
8290 "in vec4 in_vs;\n"
8291 "out vec4 vs_tcs;\n"
8292 "\n"
8293 "void main()\n"
8294 "{\n"
8295 "ASSIGNMENT"
8296 " vs_tcs = in_vs;\n"
8297 "}\n"
8298 "\n";
8299
8300 std::string source;
8301 testCase& test_case = m_test_cases[test_case_index];
8302
8303 if (Utils::Shader::COMPUTE == test_case.m_stage)
8304 {
8305 size_t position = 0;
8306
8307 source = cs;
8308
8309 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), source);
8310 }
8311 else
8312 {
8313 std::string assignment = " CONSTANT = 3;\n";
8314 size_t position = 0;
8315
8316 switch (stage)
8317 {
8318 case Utils::Shader::FRAGMENT:
8319 source = fs;
8320 break;
8321 case Utils::Shader::GEOMETRY:
8322 source = gs;
8323 break;
8324 case Utils::Shader::TESS_CTRL:
8325 source = tcs;
8326 break;
8327 case Utils::Shader::TESS_EVAL:
8328 source = tes;
8329 break;
8330 case Utils::Shader::VERTEX:
8331 source = vs;
8332 break;
8333 default:
8334 TCU_FAIL("Invalid enum");
8335 }
8336
8337 if (test_case.m_stage == stage)
8338 {
8339 Utils::replaceToken("CONSTANT", position, getConstantName(test_case.m_constant), assignment);
8340 }
8341 else
8342 {
8343 assignment = "";
8344 }
8345
8346 position = 0;
8347 Utils::replaceToken("ASSIGNMENT", position, assignment.c_str(), source);
8348 }
8349
8350 return source;
8351 }
8352
8353 /** Get description of test case
8354 *
8355 * @param test_case_index Index of test case
8356 *
8357 * @return Constant name
8358 **/
8359 std::string GLSLContantImmutablityTest::getTestCaseName(GLuint test_case_index)
8360 {
8361 std::string result = getConstantName(m_test_cases[test_case_index].m_constant);
8362
8363 return result;
8364 }
8365
8366 /** Get number of test cases
8367 *
8368 * @return Number of test cases
8369 **/
8370 GLuint GLSLContantImmutablityTest::getTestCaseNumber()
8371 {
8372 return static_cast<GLuint>(m_test_cases.size());
8373 }
8374
8375 /** Selects if "compute" stage is relevant for test
8376 *
8377 * @param test_case_index Index of test case
8378 *
8379 * @return true when tested stage is compute
8380 **/
8381 bool GLSLContantImmutablityTest::isComputeRelevant(GLuint test_case_index)
8382 {
8383 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
8384 }
8385
8386 /** Prepare all test cases
8387 *
8388 **/
8389 void GLSLContantImmutablityTest::testInit()
8390 {
8391 for (GLuint constant = 0; constant < CONSTANTS_MAX; ++constant)
8392 {
8393 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
8394 {
8395 testCase test_case = { (CONSTANTS)constant, (Utils::Shader::STAGES)stage };
8396
8397 m_test_cases.push_back(test_case);
8398 }
8399 }
8400 }
8401
8402 /** Get name of glsl constant
8403 *
8404 * @param Constant id
8405 *
8406 * @return Name of constant used in GLSL
8407 **/
8408 const GLchar* GLSLContantImmutablityTest::getConstantName(CONSTANTS constant)
8409 {
8410 const GLchar* name = "";
8411
8412 switch (constant)
8413 {
8414 case GL_ARB_ENHANCED_LAYOUTS:
8415 name = "GL_ARB_enhanced_layouts";
8416 break;
8417 case GL_MAX_XFB:
8418 name = "gl_MaxTransformFeedbackBuffers";
8419 break;
8420 case GL_MAX_XFB_INT_COMP:
8421 name = "gl_MaxTransformFeedbackInterleavedComponents";
8422 break;
8423 default:
8424 TCU_FAIL("Invalid enum");
8425 }
8426
8427 return name;
8428 }
8429
8430 /** Constructor
8431 *
8432 * @param context Test framework context
8433 **/
8434 GLSLContantValuesTest::GLSLContantValuesTest(deqp::Context& context)
8435 : TextureTestBase(context, "glsl_contant_values", "Test verifies values of constant symbols")
8436 {
8437 }
8438
8439 /** Selects if "compute" stage is relevant for test
8440 *
8441 * @param ignored
8442 *
8443 * @return false
8444 **/
8445 bool GLSLContantValuesTest::isComputeRelevant(GLuint /* test_case_index */)
8446 {
8447 return false;
8448 }
8449
8450 /** Prepare code snippet that will verify in and uniform variables
8451 *
8452 * @param ignored
8453 * @param ignored
8454 * @param stage Shader stage
8455 *
8456 * @return Code that verify variables
8457 **/
8458 std::string GLSLContantValuesTest::getVerificationSnippet(GLuint /* test_case_index */,
8459 Utils::ProgramInterface& /* program_interface */,
8460 Utils::Shader::STAGES stage)
8461 {
8462 /* Get constants */
8463 const Functions& gl = m_context.getRenderContext().getFunctions();
8464
8465 GLint max_transform_feedback_buffers = 0;
8466 GLint max_transform_feedback_interleaved_components = 0;
8467
8468 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8469 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8470 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8471 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8472
8473 std::string verification;
8474
8475 if (Utils::Shader::VERTEX == stage)
8476 {
8477 verification = "if (1 != GL_ARB_enhanced_layouts)\n"
8478 " {\n"
8479 " result = 0;\n"
8480 " }\n"
8481 " else if (MAX_TRANSFORM_FEEDBACK_BUFFERS\n"
8482 " != gl_MaxTransformFeedbackBuffers)\n"
8483 " {\n"
8484 " result = 0;\n"
8485 " }\n"
8486 " else if (MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS \n"
8487 " != gl_MaxTransformFeedbackInterleavedComponents)\n"
8488 " {\n"
8489 " result = 0;\n"
8490 " }\n";
8491
8492 size_t position = 0;
8493 GLchar buffer[16];
8494
8495 sprintf(buffer, "%d", max_transform_feedback_buffers);
8496 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_BUFFERS", position, buffer, verification);
8497
8498 sprintf(buffer, "%d", max_transform_feedback_interleaved_components);
8499 Utils::replaceToken("MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", position, buffer, verification);
8500 }
8501 else
8502 {
8503 verification = "";
8504 }
8505
8506 return verification;
8507 }
8508
8509 /** Constructor
8510 *
8511 * @param context Test framework context
8512 **/
8513 GLSLConstantIntegralExpressionTest::GLSLConstantIntegralExpressionTest(deqp::Context& context)
8514 : TextureTestBase(context, "glsl_constant_integral_expression",
8515 "Test verifies that symbols can be used as constant integral expressions")
8516 {
8517 }
8518
8519 /** Get interface of program
8520 *
8521 * @param ignored
8522 * @param program_interface Interface of program
8523 * @param ignored
8524 **/
8525 void GLSLConstantIntegralExpressionTest::getProgramInterface(GLuint /* test_case_index */,
8526 Utils::ProgramInterface& program_interface,
8527 Utils::VaryingPassthrough& /* varying_passthrough */)
8528 {
8529 /* Get constants */
8530 const Functions& gl = m_context.getRenderContext().getFunctions();
8531
8532 GLint max_transform_feedback_buffers = 0;
8533 GLint max_transform_feedback_interleaved_components = 0;
8534
8535 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
8536 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8537 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
8538 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
8539
8540 GLuint gohan_div = std::max(1, max_transform_feedback_buffers / 16);
8541 GLuint goten_div = std::max(1, max_transform_feedback_interleaved_components / 16);
8542
8543 m_gohan_length = max_transform_feedback_buffers / gohan_div;
8544 m_goten_length = max_transform_feedback_interleaved_components / goten_div;
8545
8546 /* Globals */
8547 std::string globals = "uniform uint goku [GL_ARB_enhanced_layouts / 1];\n"
8548 "uniform uint gohan[gl_MaxTransformFeedbackBuffers / GOHAN_DIV];\n"
8549 "uniform uint goten[gl_MaxTransformFeedbackInterleavedComponents / GOTEN_DIV];\n";
8550
8551 size_t position = 0;
8552 GLchar buffer[16];
8553
8554 sprintf(buffer, "%d", gohan_div);
8555 Utils::replaceToken("GOHAN_DIV", position, buffer, globals);
8556
8557 sprintf(buffer, "%d", goten_div);
8558 Utils::replaceToken("GOTEN_DIV", position, buffer, globals);
8559
8560 program_interface.m_vertex.m_globals = globals;
8561 program_interface.m_tess_ctrl.m_globals = globals;
8562 program_interface.m_tess_eval.m_globals = globals;
8563 program_interface.m_geometry.m_globals = globals;
8564 program_interface.m_fragment.m_globals = globals;
8565 program_interface.m_compute.m_globals = globals;
8566 }
8567
8568 /** Prepare code snippet that will verify in and uniform variables
8569 *
8570 * @param ignored
8571 * @param ignored
8572 * @param ignored
8573 *
8574 * @return Code that verify variables
8575 **/
8576 std::string GLSLConstantIntegralExpressionTest::getVerificationSnippet(GLuint /* test_case_index */,
8577 Utils::ProgramInterface& /* program_interface */,
8578 Utils::Shader::STAGES /* stage */)
8579 {
8580 std::string verification = "{\n"
8581 " uint goku_sum = 0;\n"
8582 " uint gohan_sum = 0;\n"
8583 " uint goten_sum = 0;\n"
8584 "\n"
8585 " for (uint i = 0u; i < goku.length(); ++i)\n"
8586 " {\n"
8587 " goku_sum += goku[i];\n"
8588 " }\n"
8589 "\n"
8590 " for (uint i = 0u; i < gohan.length(); ++i)\n"
8591 " {\n"
8592 " gohan_sum += gohan[i];\n"
8593 " }\n"
8594 "\n"
8595 " for (uint i = 0u; i < goten.length(); ++i)\n"
8596 " {\n"
8597 " goten_sum += goten[i];\n"
8598 " }\n"
8599 "\n"
8600 " if ( (1u != goku_sum) &&\n"
8601 " (EXPECTED_GOHAN_SUMu != gohan_sum) ||\n"
8602 " (EXPECTED_GOTEN_SUMu != goten_sum) )\n"
8603 " {\n"
8604 " result = 0u;\n"
8605 " }\n"
8606 " }\n";
8607
8608 size_t position = 0;
8609 GLchar buffer[16];
8610
8611 sprintf(buffer, "%d", m_gohan_length);
8612 Utils::replaceToken("EXPECTED_GOHAN_SUM", position, buffer, verification);
8613
8614 sprintf(buffer, "%d", m_goten_length);
8615 Utils::replaceToken("EXPECTED_GOTEN_SUM", position, buffer, verification);
8616
8617 return verification;
8618 }
8619
8620 /** Prepare unifroms
8621 *
8622 * @param ignored
8623 * @param ignored
8624 * @param program Program object
8625 * @param ignored
8626 **/
8627 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint /* test_case_index */,
8628 Utils::ProgramInterface& /* program_interface */,
8629 Utils::Program& program, Utils::Buffer& /* cs_buffer */)
8630 {
8631 static const GLuint uniform_data[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
8632
8633 const Functions& gl = m_context.getRenderContext().getFunctions();
8634
8635 GLint goku_location = program.GetUniformLocation("goku");
8636 GLint gohan_location = program.GetUniformLocation("gohan");
8637 GLint goten_location = program.GetUniformLocation("goten");
8638
8639 program.Uniform(gl, Utils::Type::uint, 1 /* count */, goku_location, uniform_data);
8640 program.Uniform(gl, Utils::Type::uint, m_gohan_length, gohan_location, uniform_data);
8641 program.Uniform(gl, Utils::Type::uint, m_goten_length, goten_location, uniform_data);
8642 }
8643
8644 /** Prepare unifroms
8645 *
8646 * @param test_case_index Pass as param to first implemetnation
8647 * @param program_interface Pass as param to first implemetnation
8648 * @param program Pass as param to first implemetnation
8649 * @param ignored
8650 * @param ignored
8651 * @param ignored
8652 * @param ignored
8653 * @param vs_buffer Pass as param to first implemetnation
8654 **/
8655 void GLSLConstantIntegralExpressionTest::prepareUniforms(GLuint test_case_index,
8656 Utils::ProgramInterface& program_interface,
8657 Utils::Program& program, Utils::Buffer& /* fs_buffer */,
8658 Utils::Buffer& /* gs_buffer */,
8659 Utils::Buffer& /* tcs_buffer */,
8660 Utils::Buffer& /* tes_buffer */, Utils::Buffer& vs_buffer)
8661 {
8662 /* Call first implementation */
8663 prepareUniforms(test_case_index, program_interface, program, vs_buffer);
8664 }
8665
8666 /** Constructor
8667 *
8668 * @param context Test framework context
8669 **/
8670 UniformBlockMemberOffsetAndAlignTest::UniformBlockMemberOffsetAndAlignTest(deqp::Context& context)
8671 : TextureTestBase(context, "uniform_block_member_offset_and_align",
8672 "Test verifies offsets and alignment of uniform buffer members")
8673 {
8674 }
8675
8676 /** Get interface of program
8677 *
8678 * @param test_case_index Test case index
8679 * @param program_interface Interface of program
8680 * @param varying_passthrough Collection of connections between in and out variables
8681 **/
8682 void UniformBlockMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
8683 Utils::ProgramInterface& program_interface,
8684 Utils::VaryingPassthrough& varying_passthrough)
8685 {
8686 std::string globals = "const int basic_size = BASIC_SIZE;\n"
8687 "const int type_align = TYPE_ALIGN;\n"
8688 "const int type_size = TYPE_SIZE;\n";
8689
8690 Utils::Type type = getType(test_case_index);
8691 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
8692 const GLuint base_align = type.GetBaseAlignment(false);
8693 const GLuint array_align = type.GetBaseAlignment(true);
8694 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
8695 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
8696
8697 /* Calculate offsets */
8698 const GLuint first_offset = 0;
8699 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
8700
8701 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
8702
8703 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
8704 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
8705 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8706 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8707 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8708 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
8709
8710 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8711
8712 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
8713 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
8714 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
8715 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
8716 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
8717 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
8718
8719 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
8720
8721 /* Prepare data */
8722 const std::vector<GLubyte>& first = type.GenerateData();
8723 const std::vector<GLubyte>& second = type.GenerateData();
8724 const std::vector<GLubyte>& third = type.GenerateData();
8725 const std::vector<GLubyte>& fourth = type.GenerateData();
8726
8727 m_data.resize(eigth_offset + base_stride);
8728 GLubyte* ptr = &m_data[0];
8729 memcpy(ptr + first_offset, &first[0], first.size());
8730 memcpy(ptr + second_offset, &second[0], second.size());
8731 memcpy(ptr + third_offset, &third[0], third.size());
8732 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
8733 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
8734 memcpy(ptr + sixth_offset, &third[0], third.size());
8735 memcpy(ptr + seventh_offset, &second[0], second.size());
8736 memcpy(ptr + eigth_offset, &first[0], first.size());
8737
8738 /* Prepare globals */
8739 size_t position = 0;
8740 GLchar buffer[16];
8741
8742 sprintf(buffer, "%d", basic_size);
8743 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
8744
8745 sprintf(buffer, "%d", type_align);
8746 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
8747
8748 sprintf(buffer, "%d", base_stride);
8749 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
8750
8751 /* Prepare Block */
8752 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
8753
8754 vs_uni_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
8755 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8756 first_offset);
8757
8758 vs_uni_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
8759 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
8760 0 /* n_array_elements */, base_stride, second_offset);
8761
8762 vs_uni_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
8763 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8764 third_offset);
8765
8766 vs_uni_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
8767 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8768 fourth_offset);
8769
8770 vs_uni_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8771 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
8772
8773 vs_uni_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
8774 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
8775
8776 vs_uni_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
8777 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
8778 eigth_offset);
8779
8780 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
8781
8782 /* Add globals */
8783 vs_si.m_globals = globals;
8784
8785 /* Add uniform BLOCK */
8786 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
8787 static_cast<glw::GLint>(m_data.size()), 0, &m_data[0], m_data.size());
8788
8789 /* */
8790 program_interface.CloneVertexInterface(varying_passthrough);
8791 }
8792
8793 /** Get type name
8794 *
8795 * @param test_case_index Index of test case
8796 *
8797 * @return Name of type test in test_case_index
8798 **/
8799 std::string UniformBlockMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
8800 {
8801 return getTypeName(test_case_index);
8802 }
8803
8804 /** Returns number of types to test
8805 *
8806 * @return Number of types, 34
8807 **/
8808 glw::GLuint UniformBlockMemberOffsetAndAlignTest::getTestCaseNumber()
8809 {
8810 return getTypesNumber();
8811 }
8812
8813 /** Prepare code snippet that will verify in and uniform variables
8814 *
8815 * @param ignored
8816 * @param ignored
8817 * @param stage Shader stage
8818 *
8819 * @return Code that verify variables
8820 **/
8821 std::string UniformBlockMemberOffsetAndAlignTest::getVerificationSnippet(
8822 GLuint /* test_case_index */, Utils::ProgramInterface& /* program_interface */, Utils::Shader::STAGES stage)
8823 {
8824 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
8825 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
8826 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
8827 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
8828 " {\n"
8829 " result = 0;\n"
8830 " }";
8831
8832 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::UNIFORM);
8833
8834 Utils::replaceAllTokens("PREFIX", prefix, verification);
8835
8836 return verification;
8837 }
8838
8839 /** Constructor
8840 *
8841 * @param context Test framework context
8842 **/
8843 UniformBlockLayoutQualifierConflictTest::UniformBlockLayoutQualifierConflictTest(deqp::Context& context)
8844 : NegativeTestBase(
8845 context, "uniform_block_layout_qualifier_conflict",
8846 "Test verifies that std140 is required when offset and/or align qualifiers are used with uniform block")
8847 {
8848 /* Nothing to be done here */
8849 }
8850
8851 /** Source for given test case and stage
8852 *
8853 * @param test_case_index Index of test case
8854 * @param stage Shader stage
8855 *
8856 * @return Shader source
8857 **/
8858 std::string UniformBlockLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index,
8859 Utils::Shader::STAGES stage)
8860 {
8861 static const GLchar* cs = "#version 430 core\n"
8862 "#extension GL_ARB_enhanced_layouts : require\n"
8863 "\n"
8864 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
8865 "\n"
8866 "LAYOUTuniform Block {\n"
8867 " layout(offset = 16) vec4 boy;\n"
8868 " layout(align = 64) vec4 man;\n"
8869 "} uni_block;\n"
8870 "\n"
8871 "writeonly uniform image2D uni_image;\n"
8872 "\n"
8873 "void main()\n"
8874 "{\n"
8875 " vec4 result = uni_block.boy + uni_block.man;\n"
8876 "\n"
8877 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
8878 "}\n"
8879 "\n";
8880 static const GLchar* fs = "#version 430 core\n"
8881 "#extension GL_ARB_enhanced_layouts : require\n"
8882 "\n"
8883 "LAYOUTuniform Block {\n"
8884 " layout(offset = 16) vec4 boy;\n"
8885 " layout(align = 64) vec4 man;\n"
8886 "} uni_block;\n"
8887 "\n"
8888 "in vec4 gs_fs;\n"
8889 "out vec4 fs_out;\n"
8890 "\n"
8891 "void main()\n"
8892 "{\n"
8893 " fs_out = gs_fs + uni_block.boy + uni_block.man;\n"
8894 "}\n"
8895 "\n";
8896 static const GLchar* gs = "#version 430 core\n"
8897 "#extension GL_ARB_enhanced_layouts : require\n"
8898 "\n"
8899 "layout(points) in;\n"
8900 "layout(triangle_strip, max_vertices = 4) out;\n"
8901 "\n"
8902 "LAYOUTuniform Block {\n"
8903 " layout(offset = 16) vec4 boy;\n"
8904 " layout(align = 64) vec4 man;\n"
8905 "} uni_block;\n"
8906 "\n"
8907 "in vec4 tes_gs[];\n"
8908 "out vec4 gs_fs;\n"
8909 "\n"
8910 "void main()\n"
8911 "{\n"
8912 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8913 " gl_Position = vec4(-1, -1, 0, 1);\n"
8914 " EmitVertex();\n"
8915 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8916 " gl_Position = vec4(-1, 1, 0, 1);\n"
8917 " EmitVertex();\n"
8918 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8919 " gl_Position = vec4(1, -1, 0, 1);\n"
8920 " EmitVertex();\n"
8921 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
8922 " gl_Position = vec4(1, 1, 0, 1);\n"
8923 " EmitVertex();\n"
8924 "}\n"
8925 "\n";
8926 static const GLchar* tcs =
8927 "#version 430 core\n"
8928 "#extension GL_ARB_enhanced_layouts : require\n"
8929 "\n"
8930 "layout(vertices = 1) out;\n"
8931 "\n"
8932 "LAYOUTuniform Block {\n"
8933 " layout(offset = 16) vec4 boy;\n"
8934 " layout(align = 64) vec4 man;\n"
8935 "} uni_block;\n"
8936 "\n"
8937 "in vec4 vs_tcs[];\n"
8938 "out vec4 tcs_tes[];\n"
8939 "\n"
8940 "void main()\n"
8941 "{\n"
8942 "\n"
8943 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.boy + uni_block.man;\n"
8944 "\n"
8945 " gl_TessLevelOuter[0] = 1.0;\n"
8946 " gl_TessLevelOuter[1] = 1.0;\n"
8947 " gl_TessLevelOuter[2] = 1.0;\n"
8948 " gl_TessLevelOuter[3] = 1.0;\n"
8949 " gl_TessLevelInner[0] = 1.0;\n"
8950 " gl_TessLevelInner[1] = 1.0;\n"
8951 "}\n"
8952 "\n";
8953 static const GLchar* tes = "#version 430 core\n"
8954 "#extension GL_ARB_enhanced_layouts : require\n"
8955 "\n"
8956 "layout(isolines, point_mode) in;\n"
8957 "\n"
8958 "LAYOUTuniform Block {\n"
8959 " layout(offset = 16) vec4 boy;\n"
8960 " layout(align = 64) vec4 man;\n"
8961 "} uni_block;\n"
8962 "\n"
8963 "in vec4 tcs_tes[];\n"
8964 "out vec4 tes_gs;\n"
8965 "\n"
8966 "void main()\n"
8967 "{\n"
8968 " tes_gs = tcs_tes[0] + uni_block.boy + uni_block.man;\n"
8969 "}\n"
8970 "\n";
8971 static const GLchar* vs = "#version 430 core\n"
8972 "#extension GL_ARB_enhanced_layouts : require\n"
8973 "\n"
8974 "LAYOUTuniform Block {\n"
8975 " layout(offset = 16) vec4 boy;\n"
8976 " layout(align = 64) vec4 man;\n"
8977 "} uni_block;\n"
8978 "\n"
8979 "in vec4 in_vs;\n"
8980 "out vec4 vs_tcs;\n"
8981 "\n"
8982 "void main()\n"
8983 "{\n"
8984 " vs_tcs = in_vs + uni_block.boy + uni_block.man;\n"
8985 "}\n"
8986 "\n";
8987
8988 std::string layout = "";
8989 size_t position = 0;
8990 testCase& test_case = m_test_cases[test_case_index];
8991 const GLchar* qualifier = getQualifierName(test_case.m_qualifier);
8992 std::string source;
8993
8994 if (0 != qualifier[0])
8995 {
8996 size_t layout_position = 0;
8997
8998 layout = "layout (QUALIFIER) ";
8999
9000 Utils::replaceToken("QUALIFIER", layout_position, qualifier, layout);
9001 }
9002
9003 switch (stage)
9004 {
9005 case Utils::Shader::COMPUTE:
9006 source = cs;
9007 break;
9008 case Utils::Shader::FRAGMENT:
9009 source = fs;
9010 break;
9011 case Utils::Shader::GEOMETRY:
9012 source = gs;
9013 break;
9014 case Utils::Shader::TESS_CTRL:
9015 source = tcs;
9016 break;
9017 case Utils::Shader::TESS_EVAL:
9018 source = tes;
9019 break;
9020 case Utils::Shader::VERTEX:
9021 source = vs;
9022 break;
9023 default:
9024 TCU_FAIL("Invalid enum");
9025 }
9026
9027 if (test_case.m_stage == stage)
9028 {
9029 Utils::replaceToken("LAYOUT", position, layout.c_str(), source);
9030 }
9031 else
9032 {
9033 Utils::replaceToken("LAYOUT", position, "layout (std140) ", source);
9034 }
9035
9036 return source;
9037 }
9038
9039 /** Get description of test case
9040 *
9041 * @param test_case_index Index of test case
9042 *
9043 * @return Qualifier name
9044 **/
9045 std::string UniformBlockLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
9046 {
9047 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
9048
9049 return result;
9050 }
9051
9052 /** Get number of test cases
9053 *
9054 * @return Number of test cases
9055 **/
9056 GLuint UniformBlockLayoutQualifierConflictTest::getTestCaseNumber()
9057 {
9058 return static_cast<GLuint>(m_test_cases.size());
9059 }
9060
9061 /** Selects if "compute" stage is relevant for test
9062 *
9063 * @param test_case_index Index of test case
9064 *
9065 * @return true when tested stage is compute
9066 **/
9067 bool UniformBlockLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
9068 {
9069 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9070 }
9071
9072 /** Selects if compilation failure is expected result
9073 *
9074 * @param test_case_index Index of test case
9075 *
9076 * @return false for STD140 cases, true otherwise
9077 **/
9078 bool UniformBlockLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
9079 {
9080 return (STD140 != m_test_cases[test_case_index].m_qualifier);
9081 }
9082
9083 /** Prepare all test cases
9084 *
9085 **/
9086 void UniformBlockLayoutQualifierConflictTest::testInit()
9087 {
9088 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
9089 {
9090 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9091 {
9092 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
9093
9094 m_test_cases.push_back(test_case);
9095 }
9096 }
9097 }
9098
9099 /** Get name of glsl constant
9100 *
9101 * @param Constant id
9102 *
9103 * @return Name of constant used in GLSL
9104 **/
9105 const GLchar* UniformBlockLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
9106 {
9107 const GLchar* name = "";
9108
9109 switch (qualifier)
9110 {
9111 case DEFAULT:
9112 name = "";
9113 break;
9114 case STD140:
9115 name = "std140";
9116 break;
9117 case SHARED:
9118 name = "shared";
9119 break;
9120 case PACKED:
9121 name = "packed";
9122 break;
9123 default:
9124 TCU_FAIL("Invalid enum");
9125 }
9126
9127 return name;
9128 }
9129
9130 /** Constructor
9131 *
9132 * @param context Test framework context
9133 **/
9134 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(deqp::Context& context)
9135 : NegativeTestBase(context, "uniform_block_member_invalid_offset_alignment",
9136 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
9137 {
9138 /* Nothing to be done here */
9139 }
9140
9141 /** Constructor
9142 *
9143 * @param context Test framework context
9144 * @param name Test name
9145 * @param description Test description
9146 **/
9147 UniformBlockMemberInvalidOffsetAlignmentTest::UniformBlockMemberInvalidOffsetAlignmentTest(
9148 deqp::Context& context, const glw::GLchar* name, const glw::GLchar* description)
9149 : NegativeTestBase(context, name, description)
9150 {
9151 /* Nothing to be done here */
9152 }
9153
9154 /** Source for given test case and stage
9155 *
9156 * @param test_case_index Index of test case
9157 * @param stage Shader stage
9158 *
9159 * @return Shader source
9160 **/
9161 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index,
9162 Utils::Shader::STAGES stage)
9163 {
9164 static const GLchar* cs = "#version 430 core\n"
9165 "#extension GL_ARB_enhanced_layouts : require\n"
9166 "\n"
9167 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9168 "\n"
9169 "layout (std140) uniform Block {\n"
9170 " layout (offset = OFFSET) TYPE member;\n"
9171 "} block;\n"
9172 "\n"
9173 "writeonly uniform image2D uni_image;\n"
9174 "\n"
9175 "void main()\n"
9176 "{\n"
9177 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9178 "\n"
9179 " if (TYPE(1) == block.member)\n"
9180 " {\n"
9181 " result = vec4(1, 1, 1, 1);\n"
9182 " }\n"
9183 "\n"
9184 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9185 "}\n"
9186 "\n";
9187 static const GLchar* fs = "#version 430 core\n"
9188 "#extension GL_ARB_enhanced_layouts : require\n"
9189 "\n"
9190 "in vec4 gs_fs;\n"
9191 "out vec4 fs_out;\n"
9192 "\n"
9193 "void main()\n"
9194 "{\n"
9195 " fs_out = gs_fs;\n"
9196 "}\n"
9197 "\n";
9198 static const GLchar* fs_tested = "#version 430 core\n"
9199 "#extension GL_ARB_enhanced_layouts : require\n"
9200 "\n"
9201 "layout (std140) uniform Block {\n"
9202 " layout (offset = OFFSET) TYPE member;\n"
9203 "} block;\n"
9204 "\n"
9205 "in vec4 gs_fs;\n"
9206 "out vec4 fs_out;\n"
9207 "\n"
9208 "void main()\n"
9209 "{\n"
9210 " if (TYPE(1) == block.member)\n"
9211 " {\n"
9212 " fs_out = vec4(1, 1, 1, 1);\n"
9213 " }\n"
9214 "\n"
9215 " fs_out += gs_fs;\n"
9216 "}\n"
9217 "\n";
9218 static const GLchar* gs = "#version 430 core\n"
9219 "#extension GL_ARB_enhanced_layouts : require\n"
9220 "\n"
9221 "layout(points) in;\n"
9222 "layout(triangle_strip, max_vertices = 4) out;\n"
9223 "\n"
9224 "in vec4 tes_gs[];\n"
9225 "out vec4 gs_fs;\n"
9226 "\n"
9227 "void main()\n"
9228 "{\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 " gs_fs = tes_gs[0];\n"
9236 " gl_Position = vec4(1, -1, 0, 1);\n"
9237 " EmitVertex();\n"
9238 " gs_fs = tes_gs[0];\n"
9239 " gl_Position = vec4(1, 1, 0, 1);\n"
9240 " EmitVertex();\n"
9241 "}\n"
9242 "\n";
9243 static const GLchar* gs_tested = "#version 430 core\n"
9244 "#extension GL_ARB_enhanced_layouts : require\n"
9245 "\n"
9246 "layout(points) in;\n"
9247 "layout(triangle_strip, max_vertices = 4) out;\n"
9248 "\n"
9249 "layout (std140) uniform Block {\n"
9250 " layout (offset = OFFSET) TYPE member;\n"
9251 "} block;\n"
9252 "\n"
9253 "in vec4 tes_gs[];\n"
9254 "out vec4 gs_fs;\n"
9255 "\n"
9256 "void main()\n"
9257 "{\n"
9258 " if (TYPE(1) == block.member)\n"
9259 " {\n"
9260 " gs_fs = vec4(1, 1, 1, 1);\n"
9261 " }\n"
9262 "\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 " gs_fs += tes_gs[0];\n"
9270 " gl_Position = vec4(1, -1, 0, 1);\n"
9271 " EmitVertex();\n"
9272 " gs_fs += tes_gs[0];\n"
9273 " gl_Position = vec4(1, 1, 0, 1);\n"
9274 " EmitVertex();\n"
9275 "}\n"
9276 "\n";
9277 static const GLchar* tcs = "#version 430 core\n"
9278 "#extension GL_ARB_enhanced_layouts : require\n"
9279 "\n"
9280 "layout(vertices = 1) out;\n"
9281 "\n"
9282 "in vec4 vs_tcs[];\n"
9283 "out vec4 tcs_tes[];\n"
9284 "\n"
9285 "void main()\n"
9286 "{\n"
9287 "\n"
9288 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9289 "\n"
9290 " gl_TessLevelOuter[0] = 1.0;\n"
9291 " gl_TessLevelOuter[1] = 1.0;\n"
9292 " gl_TessLevelOuter[2] = 1.0;\n"
9293 " gl_TessLevelOuter[3] = 1.0;\n"
9294 " gl_TessLevelInner[0] = 1.0;\n"
9295 " gl_TessLevelInner[1] = 1.0;\n"
9296 "}\n"
9297 "\n";
9298 static const GLchar* tcs_tested = "#version 430 core\n"
9299 "#extension GL_ARB_enhanced_layouts : require\n"
9300 "\n"
9301 "layout(vertices = 1) out;\n"
9302 "\n"
9303 "layout (std140) uniform Block {\n"
9304 " layout (offset = OFFSET) TYPE member;\n"
9305 "} block;\n"
9306 "\n"
9307 "in vec4 vs_tcs[];\n"
9308 "out vec4 tcs_tes[];\n"
9309 "\n"
9310 "void main()\n"
9311 "{\n"
9312 " if (TYPE(1) == block.member)\n"
9313 " {\n"
9314 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9315 " }\n"
9316 "\n"
9317 "\n"
9318 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9319 "\n"
9320 " gl_TessLevelOuter[0] = 1.0;\n"
9321 " gl_TessLevelOuter[1] = 1.0;\n"
9322 " gl_TessLevelOuter[2] = 1.0;\n"
9323 " gl_TessLevelOuter[3] = 1.0;\n"
9324 " gl_TessLevelInner[0] = 1.0;\n"
9325 " gl_TessLevelInner[1] = 1.0;\n"
9326 "}\n"
9327 "\n";
9328 static const GLchar* tes = "#version 430 core\n"
9329 "#extension GL_ARB_enhanced_layouts : require\n"
9330 "\n"
9331 "layout(isolines, point_mode) in;\n"
9332 "\n"
9333 "in vec4 tcs_tes[];\n"
9334 "out vec4 tes_gs;\n"
9335 "\n"
9336 "void main()\n"
9337 "{\n"
9338 " tes_gs = tcs_tes[0];\n"
9339 "}\n"
9340 "\n";
9341 static const GLchar* tes_tested = "#version 430 core\n"
9342 "#extension GL_ARB_enhanced_layouts : require\n"
9343 "\n"
9344 "layout(isolines, point_mode) in;\n"
9345 "\n"
9346 "layout (std140) uniform Block {\n"
9347 " layout (offset = OFFSET) TYPE member;\n"
9348 "} block;\n"
9349 "\n"
9350 "in vec4 tcs_tes[];\n"
9351 "out vec4 tes_gs;\n"
9352 "\n"
9353 "void main()\n"
9354 "{\n"
9355 " if (TYPE(1) == block.member)\n"
9356 " {\n"
9357 " tes_gs = vec4(1, 1, 1, 1);\n"
9358 " }\n"
9359 "\n"
9360 " tes_gs += tcs_tes[0];\n"
9361 "}\n"
9362 "\n";
9363 static const GLchar* vs = "#version 430 core\n"
9364 "#extension GL_ARB_enhanced_layouts : require\n"
9365 "\n"
9366 "in vec4 in_vs;\n"
9367 "out vec4 vs_tcs;\n"
9368 "\n"
9369 "void main()\n"
9370 "{\n"
9371 " vs_tcs = in_vs;\n"
9372 "}\n"
9373 "\n";
9374 static const GLchar* vs_tested = "#version 430 core\n"
9375 "#extension GL_ARB_enhanced_layouts : require\n"
9376 "\n"
9377 "layout (std140) uniform Block {\n"
9378 " layout (offset = OFFSET) TYPE member;\n"
9379 "} block;\n"
9380 "\n"
9381 "in vec4 in_vs;\n"
9382 "out vec4 vs_tcs;\n"
9383 "\n"
9384 "void main()\n"
9385 "{\n"
9386 " if (TYPE(1) == block.member)\n"
9387 " {\n"
9388 " vs_tcs = vec4(1, 1, 1, 1);\n"
9389 " }\n"
9390 "\n"
9391 " vs_tcs += in_vs;\n"
9392 "}\n"
9393 "\n";
9394
9395 std::string source;
9396 testCase& test_case = m_test_cases[test_case_index];
9397
9398 if (test_case.m_stage == stage)
9399 {
9400 GLchar buffer[16];
9401 const GLuint offset = test_case.m_offset;
9402 size_t position = 0;
9403 const Utils::Type& type = test_case.m_type;
9404 const GLchar* type_name = type.GetGLSLTypeName();
9405
9406 sprintf(buffer, "%d", offset);
9407
9408 switch (stage)
9409 {
9410 case Utils::Shader::COMPUTE:
9411 source = cs;
9412 break;
9413 case Utils::Shader::FRAGMENT:
9414 source = fs_tested;
9415 break;
9416 case Utils::Shader::GEOMETRY:
9417 source = gs_tested;
9418 break;
9419 case Utils::Shader::TESS_CTRL:
9420 source = tcs_tested;
9421 break;
9422 case Utils::Shader::TESS_EVAL:
9423 source = tes_tested;
9424 break;
9425 case Utils::Shader::VERTEX:
9426 source = vs_tested;
9427 break;
9428 default:
9429 TCU_FAIL("Invalid enum");
9430 }
9431
9432 Utils::replaceToken("OFFSET", position, buffer, source);
9433 Utils::replaceToken("TYPE", position, type_name, source);
9434 Utils::replaceToken("TYPE", position, type_name, source);
9435 }
9436 else
9437 {
9438 switch (stage)
9439 {
9440 case Utils::Shader::FRAGMENT:
9441 source = fs;
9442 break;
9443 case Utils::Shader::GEOMETRY:
9444 source = gs;
9445 break;
9446 case Utils::Shader::TESS_CTRL:
9447 source = tcs;
9448 break;
9449 case Utils::Shader::TESS_EVAL:
9450 source = tes;
9451 break;
9452 case Utils::Shader::VERTEX:
9453 source = vs;
9454 break;
9455 default:
9456 TCU_FAIL("Invalid enum");
9457 }
9458 }
9459
9460 return source;
9461 }
9462
9463 /** Get description of test case
9464 *
9465 * @param test_case_index Index of test case
9466 *
9467 * @return Type name and offset
9468 **/
9469 std::string UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
9470 {
9471 std::stringstream stream;
9472 testCase& test_case = m_test_cases[test_case_index];
9473
9474 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
9475
9476 return stream.str();
9477 }
9478
9479 /** Get number of test cases
9480 *
9481 * @return Number of test cases
9482 **/
9483 GLuint UniformBlockMemberInvalidOffsetAlignmentTest::getTestCaseNumber()
9484 {
9485 return static_cast<GLuint>(m_test_cases.size());
9486 }
9487
9488 /** Get the maximum size for an uniform block
9489 *
9490 * @return The maximum size in basic machine units of a uniform block.
9491 **/
9492 GLint UniformBlockMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
9493 {
9494 const Functions& gl = m_context.getRenderContext().getFunctions();
9495 GLint max_size = 0;
9496
9497 gl.getIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &max_size);
9498 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
9499
9500 return max_size;
9501 }
9502
9503 /** Selects if "compute" stage is relevant for test
9504 *
9505 * @param test_case_index Index of test case
9506 *
9507 * @return true when tested stage is compute
9508 **/
9509 bool UniformBlockMemberInvalidOffsetAlignmentTest::isComputeRelevant(GLuint test_case_index)
9510 {
9511 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9512 }
9513
9514 /** Selects if compilation failure is expected result
9515 *
9516 * @param test_case_index Index of test case
9517 *
9518 * @return should_fail field from testCase
9519 **/
9520 bool UniformBlockMemberInvalidOffsetAlignmentTest::isFailureExpected(GLuint test_case_index)
9521 {
9522 return m_test_cases[test_case_index].m_should_fail;
9523 }
9524
9525 /** Checks if stage is supported
9526 *
9527 * @param stage ignored
9528 *
9529 * @return true
9530 **/
9531 bool UniformBlockMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9532 {
9533 return true;
9534 }
9535
9536 /** Prepare all test cases
9537 *
9538 **/
9539 void UniformBlockMemberInvalidOffsetAlignmentTest::testInit()
9540 {
9541 const GLuint n_types = getTypesNumber();
9542 bool stage_support[Utils::Shader::STAGE_MAX];
9543
9544 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9545 {
9546 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9547 }
9548
9549 for (GLuint i = 0; i < n_types; ++i)
9550 {
9551 const Utils::Type& type = getType(i);
9552 const GLuint alignment = type.GetBaseAlignment(false);
9553 const GLuint type_size = type.GetSize(true);
9554 const GLuint sec_to_end = getMaxBlockSize() - 2 * type_size;
9555
9556 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9557 {
9558 if (false == stage_support[stage])
9559 {
9560 continue;
9561 }
9562
9563 for (GLuint offset = 0; offset <= type_size; ++offset)
9564 {
9565 const GLuint modulo = offset % alignment;
9566 const bool is_aligned = (0 == modulo) ? true : false;
9567 const bool should_fail = !is_aligned;
9568
9569 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9570
9571 m_test_cases.push_back(test_case);
9572 }
9573
9574 for (GLuint offset = sec_to_end; offset <= sec_to_end + type_size; ++offset)
9575 {
9576 const GLuint modulo = offset % alignment;
9577 const bool is_aligned = (0 == modulo) ? true : false;
9578 const bool should_fail = !is_aligned;
9579
9580 testCase test_case = { offset, should_fail, (Utils::Shader::STAGES)stage, type };
9581
9582 m_test_cases.push_back(test_case);
9583 }
9584 }
9585 }
9586 }
9587
9588 /** Constructor
9589 *
9590 * @param context Test framework context
9591 **/
9592 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context)
9593 : NegativeTestBase(context, "uniform_block_member_overlapping_offsets",
9594 "Test verifies that overlapping offsets qualifiers cause compilation failure")
9595 {
9596 /* Nothing to be done here */
9597 }
9598
9599 /** Constructor
9600 *
9601 * @param context Test framework context
9602 * @param name Test name
9603 * @param description Test description
9604 **/
9605 UniformBlockMemberOverlappingOffsetsTest::UniformBlockMemberOverlappingOffsetsTest(deqp::Context& context,
9606 const glw::GLchar* name,
9607 const glw::GLchar* description)
9608 : NegativeTestBase(context, name, description)
9609 {
9610 /* Nothing to be done here */
9611 }
9612
9613 /** Source for given test case and stage
9614 *
9615 * @param test_case_index Index of test case
9616 * @param stage Shader stage
9617 *
9618 * @return Shader source
9619 **/
9620 std::string UniformBlockMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index,
9621 Utils::Shader::STAGES stage)
9622 {
9623 static const GLchar* cs = "#version 430 core\n"
9624 "#extension GL_ARB_enhanced_layouts : require\n"
9625 "\n"
9626 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
9627 "\n"
9628 "layout (std140) uniform Block {\n"
9629 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9630 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9631 "} block;\n"
9632 "\n"
9633 "writeonly uniform image2D uni_image;\n"
9634 "\n"
9635 "void main()\n"
9636 "{\n"
9637 " vec4 result = vec4(1, 0, 0.5, 1);\n"
9638 "\n"
9639 " if ((BOY_TYPE(1) == block.boy) ||\n"
9640 " (MAN_TYPE(0) == block.man) )\n"
9641 " {\n"
9642 " result = vec4(1, 1, 1, 1);\n"
9643 " }\n"
9644 "\n"
9645 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
9646 "}\n"
9647 "\n";
9648 static const GLchar* fs = "#version 430 core\n"
9649 "#extension GL_ARB_enhanced_layouts : require\n"
9650 "\n"
9651 "in vec4 gs_fs;\n"
9652 "out vec4 fs_out;\n"
9653 "\n"
9654 "void main()\n"
9655 "{\n"
9656 " fs_out = gs_fs;\n"
9657 "}\n"
9658 "\n";
9659 static const GLchar* fs_tested = "#version 430 core\n"
9660 "#extension GL_ARB_enhanced_layouts : require\n"
9661 "\n"
9662 "layout (std140) uniform Block {\n"
9663 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9664 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9665 "} block;\n"
9666 "\n"
9667 "in vec4 gs_fs;\n"
9668 "out vec4 fs_out;\n"
9669 "\n"
9670 "void main()\n"
9671 "{\n"
9672 " if ((BOY_TYPE(1) == block.boy) ||\n"
9673 " (MAN_TYPE(0) == block.man) )\n"
9674 " {\n"
9675 " fs_out = vec4(1, 1, 1, 1);\n"
9676 " }\n"
9677 "\n"
9678 " fs_out += gs_fs;\n"
9679 "}\n"
9680 "\n";
9681 static const GLchar* gs = "#version 430 core\n"
9682 "#extension GL_ARB_enhanced_layouts : require\n"
9683 "\n"
9684 "layout(points) in;\n"
9685 "layout(triangle_strip, max_vertices = 4) out;\n"
9686 "\n"
9687 "in vec4 tes_gs[];\n"
9688 "out vec4 gs_fs;\n"
9689 "\n"
9690 "void main()\n"
9691 "{\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 " gs_fs = tes_gs[0];\n"
9699 " gl_Position = vec4(1, -1, 0, 1);\n"
9700 " EmitVertex();\n"
9701 " gs_fs = tes_gs[0];\n"
9702 " gl_Position = vec4(1, 1, 0, 1);\n"
9703 " EmitVertex();\n"
9704 "}\n"
9705 "\n";
9706 static const GLchar* gs_tested = "#version 430 core\n"
9707 "#extension GL_ARB_enhanced_layouts : require\n"
9708 "\n"
9709 "layout(points) in;\n"
9710 "layout(triangle_strip, max_vertices = 4) out;\n"
9711 "\n"
9712 "layout (std140) uniform Block {\n"
9713 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9714 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9715 "} block;\n"
9716 "\n"
9717 "in vec4 tes_gs[];\n"
9718 "out vec4 gs_fs;\n"
9719 "\n"
9720 "void main()\n"
9721 "{\n"
9722 " if ((BOY_TYPE(1) == block.boy) ||\n"
9723 " (MAN_TYPE(0) == block.man) )\n"
9724 " {\n"
9725 " gs_fs = vec4(1, 1, 1, 1);\n"
9726 " }\n"
9727 "\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 " gs_fs += tes_gs[0];\n"
9735 " gl_Position = vec4(1, -1, 0, 1);\n"
9736 " EmitVertex();\n"
9737 " gs_fs += tes_gs[0];\n"
9738 " gl_Position = vec4(1, 1, 0, 1);\n"
9739 " EmitVertex();\n"
9740 "}\n"
9741 "\n";
9742 static const GLchar* tcs = "#version 430 core\n"
9743 "#extension GL_ARB_enhanced_layouts : require\n"
9744 "\n"
9745 "layout(vertices = 1) out;\n"
9746 "\n"
9747 "in vec4 vs_tcs[];\n"
9748 "out vec4 tcs_tes[];\n"
9749 "\n"
9750 "void main()\n"
9751 "{\n"
9752 "\n"
9753 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
9754 "\n"
9755 " gl_TessLevelOuter[0] = 1.0;\n"
9756 " gl_TessLevelOuter[1] = 1.0;\n"
9757 " gl_TessLevelOuter[2] = 1.0;\n"
9758 " gl_TessLevelOuter[3] = 1.0;\n"
9759 " gl_TessLevelInner[0] = 1.0;\n"
9760 " gl_TessLevelInner[1] = 1.0;\n"
9761 "}\n"
9762 "\n";
9763 static const GLchar* tcs_tested = "#version 430 core\n"
9764 "#extension GL_ARB_enhanced_layouts : require\n"
9765 "\n"
9766 "layout(vertices = 1) out;\n"
9767 "\n"
9768 "layout (std140) uniform Block {\n"
9769 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9770 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9771 "} block;\n"
9772 "\n"
9773 "in vec4 vs_tcs[];\n"
9774 "out vec4 tcs_tes[];\n"
9775 "\n"
9776 "void main()\n"
9777 "{\n"
9778 " if ((BOY_TYPE(1) == block.boy) ||\n"
9779 " (MAN_TYPE(0) == block.man) )\n"
9780 " {\n"
9781 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
9782 " }\n"
9783 "\n"
9784 "\n"
9785 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
9786 "\n"
9787 " gl_TessLevelOuter[0] = 1.0;\n"
9788 " gl_TessLevelOuter[1] = 1.0;\n"
9789 " gl_TessLevelOuter[2] = 1.0;\n"
9790 " gl_TessLevelOuter[3] = 1.0;\n"
9791 " gl_TessLevelInner[0] = 1.0;\n"
9792 " gl_TessLevelInner[1] = 1.0;\n"
9793 "}\n"
9794 "\n";
9795 static const GLchar* tes = "#version 430 core\n"
9796 "#extension GL_ARB_enhanced_layouts : require\n"
9797 "\n"
9798 "layout(isolines, point_mode) in;\n"
9799 "\n"
9800 "in vec4 tcs_tes[];\n"
9801 "out vec4 tes_gs;\n"
9802 "\n"
9803 "void main()\n"
9804 "{\n"
9805 " tes_gs = tcs_tes[0];\n"
9806 "}\n"
9807 "\n";
9808 static const GLchar* tes_tested = "#version 430 core\n"
9809 "#extension GL_ARB_enhanced_layouts : require\n"
9810 "\n"
9811 "layout(isolines, point_mode) in;\n"
9812 "\n"
9813 "layout (std140) uniform Block {\n"
9814 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9815 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9816 "} block;\n"
9817 "\n"
9818 "in vec4 tcs_tes[];\n"
9819 "out vec4 tes_gs;\n"
9820 "\n"
9821 "void main()\n"
9822 "{\n"
9823 " if ((BOY_TYPE(1) == block.boy) ||\n"
9824 " (MAN_TYPE(0) == block.man) )\n"
9825 " {\n"
9826 " tes_gs = vec4(1, 1, 1, 1);\n"
9827 " }\n"
9828 "\n"
9829 " tes_gs += tcs_tes[0];\n"
9830 "}\n"
9831 "\n";
9832 static const GLchar* vs = "#version 430 core\n"
9833 "#extension GL_ARB_enhanced_layouts : require\n"
9834 "\n"
9835 "in vec4 in_vs;\n"
9836 "out vec4 vs_tcs;\n"
9837 "\n"
9838 "void main()\n"
9839 "{\n"
9840 " vs_tcs = in_vs;\n"
9841 "}\n"
9842 "\n";
9843 static const GLchar* vs_tested = "#version 430 core\n"
9844 "#extension GL_ARB_enhanced_layouts : require\n"
9845 "\n"
9846 "layout (std140) uniform Block {\n"
9847 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
9848 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
9849 "} block;\n"
9850 "\n"
9851 "in vec4 in_vs;\n"
9852 "out vec4 vs_tcs;\n"
9853 "\n"
9854 "void main()\n"
9855 "{\n"
9856 " if ((BOY_TYPE(1) == block.boy) ||\n"
9857 " (MAN_TYPE(0) == block.man) )\n"
9858 " {\n"
9859 " vs_tcs = vec4(1, 1, 1, 1);\n"
9860 " }\n"
9861 "\n"
9862 " vs_tcs += in_vs;\n"
9863 "}\n"
9864 "\n";
9865
9866 std::string source;
9867 testCase& test_case = m_test_cases[test_case_index];
9868
9869 if (test_case.m_stage == stage)
9870 {
9871 GLchar buffer[16];
9872 const GLuint boy_offset = test_case.m_boy_offset;
9873 const Utils::Type& boy_type = test_case.m_boy_type;
9874 const GLchar* boy_type_name = boy_type.GetGLSLTypeName();
9875 const GLuint man_offset = test_case.m_man_offset;
9876 const Utils::Type& man_type = test_case.m_man_type;
9877 const GLchar* man_type_name = man_type.GetGLSLTypeName();
9878 size_t position = 0;
9879
9880 switch (stage)
9881 {
9882 case Utils::Shader::COMPUTE:
9883 source = cs;
9884 break;
9885 case Utils::Shader::FRAGMENT:
9886 source = fs_tested;
9887 break;
9888 case Utils::Shader::GEOMETRY:
9889 source = gs_tested;
9890 break;
9891 case Utils::Shader::TESS_CTRL:
9892 source = tcs_tested;
9893 break;
9894 case Utils::Shader::TESS_EVAL:
9895 source = tes_tested;
9896 break;
9897 case Utils::Shader::VERTEX:
9898 source = vs_tested;
9899 break;
9900 default:
9901 TCU_FAIL("Invalid enum");
9902 }
9903
9904 sprintf(buffer, "%d", boy_offset);
9905 Utils::replaceToken("BOY_OFFSET", position, buffer, source);
9906 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
9907 sprintf(buffer, "%d", man_offset);
9908 Utils::replaceToken("MAN_OFFSET", position, buffer, source);
9909 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
9910 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
9911 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
9912 }
9913 else
9914 {
9915 switch (stage)
9916 {
9917 case Utils::Shader::FRAGMENT:
9918 source = fs;
9919 break;
9920 case Utils::Shader::GEOMETRY:
9921 source = gs;
9922 break;
9923 case Utils::Shader::TESS_CTRL:
9924 source = tcs;
9925 break;
9926 case Utils::Shader::TESS_EVAL:
9927 source = tes;
9928 break;
9929 case Utils::Shader::VERTEX:
9930 source = vs;
9931 break;
9932 default:
9933 TCU_FAIL("Invalid enum");
9934 }
9935 }
9936
9937 return source;
9938 }
9939
9940 /** Get description of test case
9941 *
9942 * @param test_case_index Index of test case
9943 *
9944 * @return Type name and offset
9945 **/
9946 std::string UniformBlockMemberOverlappingOffsetsTest::getTestCaseName(GLuint test_case_index)
9947 {
9948 std::stringstream stream;
9949 testCase& test_case = m_test_cases[test_case_index];
9950
9951 stream << "Type: " << test_case.m_boy_type.GetGLSLTypeName() << ", offset: " << test_case.m_boy_offset
9952 << ". Type: " << test_case.m_man_type.GetGLSLTypeName() << ", offset: " << test_case.m_man_offset;
9953
9954 return stream.str();
9955 }
9956
9957 /** Get number of test cases
9958 *
9959 * @return Number of test cases
9960 **/
9961 GLuint UniformBlockMemberOverlappingOffsetsTest::getTestCaseNumber()
9962 {
9963 return static_cast<GLuint>(m_test_cases.size());
9964 }
9965
9966 /** Selects if "compute" stage is relevant for test
9967 *
9968 * @param test_case_index Index of test case
9969 *
9970 * @return true when tested stage is compute
9971 **/
9972 bool UniformBlockMemberOverlappingOffsetsTest::isComputeRelevant(GLuint test_case_index)
9973 {
9974 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
9975 }
9976
9977 /** Checks if stage is supported
9978 *
9979 * @param stage ignored
9980 *
9981 * @return true
9982 **/
9983 bool UniformBlockMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES /* stage */)
9984 {
9985 return true;
9986 }
9987
9988 /** Prepare all test cases
9989 *
9990 **/
9991 void UniformBlockMemberOverlappingOffsetsTest::testInit()
9992 {
9993 const GLuint n_types = getTypesNumber();
9994 bool stage_support[Utils::Shader::STAGE_MAX];
9995
9996 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
9997 {
9998 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
9999 }
10000
10001 for (GLuint i = 0; i < n_types; ++i)
10002 {
10003 const Utils::Type& boy_type = getType(i);
10004 const GLuint boy_size = boy_type.GetActualAlignment(1 /* align */, false /* is_array*/);
10005
10006 for (GLuint j = 0; j < n_types; ++j)
10007 {
10008 const Utils::Type& man_type = getType(j);
10009 const GLuint man_align = man_type.GetBaseAlignment(false);
10010 const GLuint man_size = man_type.GetActualAlignment(1 /* align */, false /* is_array*/);
10011
10012 const GLuint boy_offset = lcm(boy_size, man_size);
10013 const GLuint man_after_start = boy_offset + 1;
10014 const GLuint man_after_off = man_type.GetActualOffset(man_after_start, man_size);
10015 const GLuint man_before_start = boy_offset - man_align;
10016 const GLuint man_before_off = man_type.GetActualOffset(man_before_start, man_size);
10017
10018 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10019 {
10020 if (false == stage_support[stage])
10021 {
10022 continue;
10023 }
10024
10025 if ((boy_offset > man_before_off) && (boy_offset < man_before_off + man_size))
10026 {
10027 testCase test_case = { boy_offset, boy_type, man_before_off, man_type,
10028 (Utils::Shader::STAGES)stage };
10029
10030 m_test_cases.push_back(test_case);
10031 }
10032
10033 if ((boy_offset < man_after_off) && (boy_offset + boy_size > man_after_off))
10034 {
10035 testCase test_case = { boy_offset, boy_type, man_after_off, man_type,
10036 (Utils::Shader::STAGES)stage };
10037
10038 m_test_cases.push_back(test_case);
10039 }
10040
10041 /* Boy offset, should be fine for both types */
10042 testCase test_case = { boy_offset, boy_type, boy_offset, man_type, (Utils::Shader::STAGES)stage };
10043
10044 m_test_cases.push_back(test_case);
10045 }
10046 }
10047 }
10048 }
10049
10050 /** Find greatest common divisor for a and b
10051 *
10052 * @param a A argument
10053 * @param b B argument
10054 *
10055 * @return Found gcd value
10056 **/
10057 GLuint UniformBlockMemberOverlappingOffsetsTest::gcd(GLuint a, GLuint b)
10058 {
10059 if ((0 != a) && (0 == b))
10060 {
10061 return a;
10062 }
10063 else
10064 {
10065 GLuint greater = std::max(a, b);
10066 GLuint lesser = std::min(a, b);
10067
10068 return gcd(lesser, greater % lesser);
10069 }
10070 }
10071
10072 /** Find lowest common multiple for a and b
10073 *
10074 * @param a A argument
10075 * @param b B argument
10076 *
10077 * @return Found gcd value
10078 **/
10079 GLuint UniformBlockMemberOverlappingOffsetsTest::lcm(GLuint a, GLuint b)
10080 {
10081 return (a * b) / gcd(a, b);
10082 }
10083
10084 /** Constructor
10085 *
10086 * @param context Test framework context
10087 **/
10088 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context)
10089 : NegativeTestBase(context, "uniform_block_member_align_non_power_of_2",
10090 "Test verifies that align qualifier requires value that is a power of 2")
10091 {
10092 /* Nothing to be done here */
10093 }
10094
10095 /** Constructor
10096 *
10097 * @param context Test framework context
10098 * @param name Test name
10099 * @param description Test description
10100 **/
10101 UniformBlockMemberAlignNonPowerOf2Test::UniformBlockMemberAlignNonPowerOf2Test(deqp::Context& context,
10102 const glw::GLchar* name,
10103 const glw::GLchar* description)
10104 : NegativeTestBase(context, name, description)
10105 {
10106 /* Nothing to be done here */
10107 }
10108
10109 /** Source for given test case and stage
10110 *
10111 * @param test_case_index Index of test case
10112 * @param stage Shader stage
10113 *
10114 * @return Shader source
10115 **/
10116 std::string UniformBlockMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10117 {
10118 static const GLchar* cs = "#version 430 core\n"
10119 "#extension GL_ARB_enhanced_layouts : require\n"
10120 "\n"
10121 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10122 "\n"
10123 "layout (std140) uniform Block {\n"
10124 " vec4 boy;\n"
10125 " layout (align = ALIGN) TYPE man;\n"
10126 "} block;\n"
10127 "\n"
10128 "writeonly uniform image2D uni_image;\n"
10129 "\n"
10130 "void main()\n"
10131 "{\n"
10132 " vec4 result = vec4(1, 0, 0.5, 1);\n"
10133 "\n"
10134 " if (TYPE(0) == block.man)\n"
10135 " {\n"
10136 " result = vec4(1, 1, 1, 1) - block.boy;\n"
10137 " }\n"
10138 "\n"
10139 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10140 "}\n"
10141 "\n";
10142 static const GLchar* fs = "#version 430 core\n"
10143 "#extension GL_ARB_enhanced_layouts : require\n"
10144 "\n"
10145 "in vec4 gs_fs;\n"
10146 "out vec4 fs_out;\n"
10147 "\n"
10148 "void main()\n"
10149 "{\n"
10150 " fs_out = gs_fs;\n"
10151 "}\n"
10152 "\n";
10153 static const GLchar* fs_tested = "#version 430 core\n"
10154 "#extension GL_ARB_enhanced_layouts : require\n"
10155 "\n"
10156 "layout (std140) uniform Block {\n"
10157 " vec4 boy;\n"
10158 " layout (align = ALIGN) TYPE man;\n"
10159 "} block;\n"
10160 "\n"
10161 "in vec4 gs_fs;\n"
10162 "out vec4 fs_out;\n"
10163 "\n"
10164 "void main()\n"
10165 "{\n"
10166 " if (TYPE(0) == block.man)\n"
10167 " {\n"
10168 " fs_out = block.boy;\n"
10169 " }\n"
10170 "\n"
10171 " fs_out += gs_fs;\n"
10172 "}\n"
10173 "\n";
10174 static const GLchar* gs = "#version 430 core\n"
10175 "#extension GL_ARB_enhanced_layouts : require\n"
10176 "\n"
10177 "layout(points) in;\n"
10178 "layout(triangle_strip, max_vertices = 4) out;\n"
10179 "\n"
10180 "in vec4 tes_gs[];\n"
10181 "out vec4 gs_fs;\n"
10182 "\n"
10183 "void main()\n"
10184 "{\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 " gs_fs = tes_gs[0];\n"
10192 " gl_Position = vec4(1, -1, 0, 1);\n"
10193 " EmitVertex();\n"
10194 " gs_fs = tes_gs[0];\n"
10195 " gl_Position = vec4(1, 1, 0, 1);\n"
10196 " EmitVertex();\n"
10197 "}\n"
10198 "\n";
10199 static const GLchar* gs_tested = "#version 430 core\n"
10200 "#extension GL_ARB_enhanced_layouts : require\n"
10201 "\n"
10202 "layout(points) in;\n"
10203 "layout(triangle_strip, max_vertices = 4) out;\n"
10204 "\n"
10205 "layout (std140) uniform Block {\n"
10206 " vec4 boy;\n"
10207 " layout (align = ALIGN) TYPE man;\n"
10208 "} block;\n"
10209 "\n"
10210 "in vec4 tes_gs[];\n"
10211 "out vec4 gs_fs;\n"
10212 "\n"
10213 "void main()\n"
10214 "{\n"
10215 " if (TYPE(0) == block.man)\n"
10216 " {\n"
10217 " gs_fs = block.boy;\n"
10218 " }\n"
10219 "\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 " gs_fs += tes_gs[0];\n"
10227 " gl_Position = vec4(1, -1, 0, 1);\n"
10228 " EmitVertex();\n"
10229 " gs_fs += tes_gs[0];\n"
10230 " gl_Position = vec4(1, 1, 0, 1);\n"
10231 " EmitVertex();\n"
10232 "}\n"
10233 "\n";
10234 static const GLchar* tcs = "#version 430 core\n"
10235 "#extension GL_ARB_enhanced_layouts : require\n"
10236 "\n"
10237 "layout(vertices = 1) out;\n"
10238 "\n"
10239 "in vec4 vs_tcs[];\n"
10240 "out vec4 tcs_tes[];\n"
10241 "\n"
10242 "void main()\n"
10243 "{\n"
10244 "\n"
10245 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
10246 "\n"
10247 " gl_TessLevelOuter[0] = 1.0;\n"
10248 " gl_TessLevelOuter[1] = 1.0;\n"
10249 " gl_TessLevelOuter[2] = 1.0;\n"
10250 " gl_TessLevelOuter[3] = 1.0;\n"
10251 " gl_TessLevelInner[0] = 1.0;\n"
10252 " gl_TessLevelInner[1] = 1.0;\n"
10253 "}\n"
10254 "\n";
10255 static const GLchar* tcs_tested = "#version 430 core\n"
10256 "#extension GL_ARB_enhanced_layouts : require\n"
10257 "\n"
10258 "layout(vertices = 1) out;\n"
10259 "\n"
10260 "layout (std140) uniform Block {\n"
10261 " vec4 boy;\n"
10262 " layout (align = ALIGN) TYPE man;\n"
10263 "} block;\n"
10264 "\n"
10265 "in vec4 vs_tcs[];\n"
10266 "out vec4 tcs_tes[];\n"
10267 "\n"
10268 "void main()\n"
10269 "{\n"
10270 " if (TYPE(0) == block.man)\n"
10271 " {\n"
10272 " tcs_tes[gl_InvocationID] = block.boy;\n"
10273 " }\n"
10274 "\n"
10275 "\n"
10276 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
10277 "\n"
10278 " gl_TessLevelOuter[0] = 1.0;\n"
10279 " gl_TessLevelOuter[1] = 1.0;\n"
10280 " gl_TessLevelOuter[2] = 1.0;\n"
10281 " gl_TessLevelOuter[3] = 1.0;\n"
10282 " gl_TessLevelInner[0] = 1.0;\n"
10283 " gl_TessLevelInner[1] = 1.0;\n"
10284 "}\n"
10285 "\n";
10286 static const GLchar* tes = "#version 430 core\n"
10287 "#extension GL_ARB_enhanced_layouts : require\n"
10288 "\n"
10289 "layout(isolines, point_mode) in;\n"
10290 "\n"
10291 "in vec4 tcs_tes[];\n"
10292 "out vec4 tes_gs;\n"
10293 "\n"
10294 "void main()\n"
10295 "{\n"
10296 " tes_gs = tcs_tes[0];\n"
10297 "}\n"
10298 "\n";
10299 static const GLchar* tes_tested = "#version 430 core\n"
10300 "#extension GL_ARB_enhanced_layouts : require\n"
10301 "\n"
10302 "layout(isolines, point_mode) in;\n"
10303 "\n"
10304 "layout (std140) uniform Block {\n"
10305 " vec4 boy;\n"
10306 " layout (align = ALIGN) TYPE man;\n"
10307 "} block;\n"
10308 "\n"
10309 "in vec4 tcs_tes[];\n"
10310 "out vec4 tes_gs;\n"
10311 "\n"
10312 "void main()\n"
10313 "{\n"
10314 " if (TYPE(0) == block.man)\n"
10315 " {\n"
10316 " tes_gs = block.boy;\n"
10317 " }\n"
10318 "\n"
10319 " tes_gs += tcs_tes[0];\n"
10320 "}\n"
10321 "\n";
10322 static const GLchar* vs = "#version 430 core\n"
10323 "#extension GL_ARB_enhanced_layouts : require\n"
10324 "\n"
10325 "in vec4 in_vs;\n"
10326 "out vec4 vs_tcs;\n"
10327 "\n"
10328 "void main()\n"
10329 "{\n"
10330 " vs_tcs = in_vs;\n"
10331 "}\n"
10332 "\n";
10333 static const GLchar* vs_tested = "#version 430 core\n"
10334 "#extension GL_ARB_enhanced_layouts : require\n"
10335 "\n"
10336 "layout (std140) uniform Block {\n"
10337 " vec4 boy;\n"
10338 " layout (align = ALIGN) TYPE man;\n"
10339 "} block;\n"
10340 "\n"
10341 "in vec4 in_vs;\n"
10342 "out vec4 vs_tcs;\n"
10343 "\n"
10344 "void main()\n"
10345 "{\n"
10346 " if (TYPE(0) == block.man)\n"
10347 " {\n"
10348 " vs_tcs = block.boy;\n"
10349 " }\n"
10350 "\n"
10351 " vs_tcs += in_vs;\n"
10352 "}\n"
10353 "\n";
10354
10355 std::string source;
10356 testCase& test_case = m_test_cases[test_case_index];
10357
10358 if (test_case.m_stage == stage)
10359 {
10360 GLchar buffer[16];
10361 const GLuint alignment = test_case.m_alignment;
10362 const Utils::Type& type = test_case.m_type;
10363 const GLchar* type_name = type.GetGLSLTypeName();
10364 size_t position = 0;
10365
10366 switch (stage)
10367 {
10368 case Utils::Shader::COMPUTE:
10369 source = cs;
10370 break;
10371 case Utils::Shader::FRAGMENT:
10372 source = fs_tested;
10373 break;
10374 case Utils::Shader::GEOMETRY:
10375 source = gs_tested;
10376 break;
10377 case Utils::Shader::TESS_CTRL:
10378 source = tcs_tested;
10379 break;
10380 case Utils::Shader::TESS_EVAL:
10381 source = tes_tested;
10382 break;
10383 case Utils::Shader::VERTEX:
10384 source = vs_tested;
10385 break;
10386 default:
10387 TCU_FAIL("Invalid enum");
10388 }
10389
10390 sprintf(buffer, "%d", alignment);
10391 Utils::replaceToken("ALIGN", position, buffer, source);
10392 Utils::replaceToken("TYPE", position, type_name, source);
10393 Utils::replaceToken("TYPE", position, type_name, source);
10394 }
10395 else
10396 {
10397 switch (stage)
10398 {
10399 case Utils::Shader::FRAGMENT:
10400 source = fs;
10401 break;
10402 case Utils::Shader::GEOMETRY:
10403 source = gs;
10404 break;
10405 case Utils::Shader::TESS_CTRL:
10406 source = tcs;
10407 break;
10408 case Utils::Shader::TESS_EVAL:
10409 source = tes;
10410 break;
10411 case Utils::Shader::VERTEX:
10412 source = vs;
10413 break;
10414 default:
10415 TCU_FAIL("Invalid enum");
10416 }
10417 }
10418
10419 return source;
10420 }
10421
10422 /** Get description of test case
10423 *
10424 * @param test_case_index Index of test case
10425 *
10426 * @return Type name and offset
10427 **/
10428 std::string UniformBlockMemberAlignNonPowerOf2Test::getTestCaseName(GLuint test_case_index)
10429 {
10430 std::stringstream stream;
10431 testCase& test_case = m_test_cases[test_case_index];
10432
10433 stream << "Type: " << test_case.m_type.GetGLSLTypeName() << ", align: " << test_case.m_alignment;
10434
10435 return stream.str();
10436 }
10437
10438 /** Get number of test cases
10439 *
10440 * @return Number of test cases
10441 **/
10442 GLuint UniformBlockMemberAlignNonPowerOf2Test::getTestCaseNumber()
10443 {
10444 return static_cast<GLuint>(m_test_cases.size());
10445 }
10446
10447 /** Selects if "compute" stage is relevant for test
10448 *
10449 * @param test_case_index Index of test case
10450 *
10451 * @return true when tested stage is compute
10452 **/
10453 bool UniformBlockMemberAlignNonPowerOf2Test::isComputeRelevant(GLuint test_case_index)
10454 {
10455 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
10456 }
10457
10458 /** Checks if stage is supported
10459 *
10460 * @param ignored
10461 *
10462 * @return true
10463 **/
10464 bool UniformBlockMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES /* stage */)
10465 {
10466 return true;
10467 }
10468
10469 /** Selects if compilation failure is expected result
10470 *
10471 * @param test_case_index Index of test case
10472 *
10473 * @return should_fail field from testCase
10474 **/
10475 bool UniformBlockMemberAlignNonPowerOf2Test::isFailureExpected(GLuint test_case_index)
10476 {
10477 return m_test_cases[test_case_index].m_should_fail;
10478 }
10479
10480 /** Prepare all test cases
10481 *
10482 **/
10483 void UniformBlockMemberAlignNonPowerOf2Test::testInit()
10484 {
10485 static const GLuint dmat4_size = 128;
10486 const GLuint n_types = getTypesNumber();
10487 bool stage_support[Utils::Shader::STAGE_MAX];
10488
10489 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10490 {
10491 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
10492 }
10493
10494 for (GLuint j = 0; j < n_types; ++j)
10495 {
10496 const Utils::Type& type = getType(j);
10497
10498 for (GLuint align = 0; align <= dmat4_size; ++align)
10499 {
10500
10501 #if WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST
10502
10503 const bool should_fail = (0 == align) ? false : !isPowerOf2(align);
10504
10505 #else /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10506
10507 const bool should_fail = !isPowerOf2(align);
10508
10509 #endif /* WRKARD_UNIFORMBLOCKMEMBERALIGNNONPOWEROF2TEST */
10510
10511 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
10512 {
10513 if (false == stage_support[stage])
10514 {
10515 continue;
10516 }
10517
10518 testCase test_case = { align, type, should_fail, (Utils::Shader::STAGES)stage };
10519
10520 m_test_cases.push_back(test_case);
10521 }
10522 }
10523 }
10524 }
10525
10526 /** Check if value is power of 2
10527 *
10528 * @param val Tested value
10529 *
10530 * @return true if val is power of 2, false otherwise
10531 **/
10532 bool UniformBlockMemberAlignNonPowerOf2Test::isPowerOf2(GLuint val)
10533 {
10534 if (0 == val)
10535 {
10536 return false;
10537 }
10538
10539 return (0 == (val & (val - 1)));
10540 }
10541
10542 /** Constructor
10543 *
10544 * @param context Test framework context
10545 **/
10546 UniformBlockAlignmentTest::UniformBlockAlignmentTest(deqp::Context& context)
10547 : TextureTestBase(context, "uniform_block_alignment", "Test verifies offset and alignment of uniform buffer")
10548 {
10549 }
10550
10551 /** Get interface of program
10552 *
10553 * @param ignored
10554 * @param program_interface Interface of program
10555 * @param varying_passthrough Collection of connections between in and out variables
10556 **/
10557 void UniformBlockAlignmentTest::getProgramInterface(GLuint /* test_case_index */,
10558 Utils::ProgramInterface& program_interface,
10559 Utils::VaryingPassthrough& varying_passthrough)
10560 {
10561 static const Utils::Type vec4 = Utils::Type::vec4;
10562
10563 #if WRKARD_UNIFORMBLOCKALIGNMENT
10564
10565 static const GLuint block_align = 16;
10566
10567 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10568
10569 static const GLuint block_align = 64;
10570
10571 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10572
10573 static const GLuint vec4_stride = 16;
10574 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
10575
10576 /*Fixed a test issue, the fifth_offset should be calculated by block_align, instead of fifth_align, according to spec, the actual
10577 alignment of a member will be the greater of the specified alignment and the base aligment for the member type
10578 */
10579 const GLuint first_offset = 0; /* vec4 at 0 */
10580 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
10581 const GLuint third_offset =
10582 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
10583 const GLuint fourth_offset =
10584 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
10585 const GLuint fifth_offset =
10586 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, block_align); /* vec4[2] at 160 */
10587 const GLuint sixth_offset =
10588 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
10589
10590 Utils::Interface* structure = program_interface.Structure("Data");
10591
10592 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10593 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
10594
10595 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
10596 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
10597 Utils::Type::vec4.GetSize() /* offset */);
10598
10599 /* Prepare Block */
10600 Utils::Interface* vs_uni_block = program_interface.Block("vs_uni_Block");
10601
10602 vs_uni_block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
10603 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
10604
10605 vs_uni_block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10606 0 /* n_array_elements */, data_stride, second_offset);
10607
10608 vs_uni_block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10609 2 /* n_array_elements */, data_stride, third_offset);
10610
10611 vs_uni_block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
10612 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
10613
10614 vs_uni_block->Member("fifth", "layout(align = 64)", 0 /* expected_component */, 0 /* expected_location */, vec4,
10615 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
10616
10617 vs_uni_block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
10618 0 /* n_array_elements */, data_stride, sixth_offset);
10619
10620 const GLuint stride = calculateStride(*vs_uni_block);
10621 m_data.resize(stride);
10622 generateData(*vs_uni_block, 0, m_data);
10623
10624 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10625
10626 /* Add uniform BLOCK */
10627 #if WRKARD_UNIFORMBLOCKALIGNMENT
10628 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING)", 0, 0, vs_uni_block, 0,
10629 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10630 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
10631 vs_si.Uniform("vs_uni_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_uni_block, 0,
10632 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10633 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
10634
10635 program_interface.CloneVertexInterface(varying_passthrough);
10636 }
10637
10638 /** Constructor
10639 *
10640 * @param context Test framework context
10641 **/
10642 SSBMemberOffsetAndAlignTest::SSBMemberOffsetAndAlignTest(deqp::Context& context)
10643 : TextureTestBase(context, "ssb_member_offset_and_align",
10644 "Test verifies offsets and alignment of storage buffer members")
10645 {
10646 }
10647
10648 /** Get interface of program
10649 *
10650 * @param test_case_index Test case index
10651 * @param program_interface Interface of program
10652 * @param varying_passthrough Collection of connections between in and out variables
10653 **/
10654 void SSBMemberOffsetAndAlignTest::getProgramInterface(GLuint test_case_index,
10655 Utils::ProgramInterface& program_interface,
10656 Utils::VaryingPassthrough& varying_passthrough)
10657 {
10658 std::string globals = "const int basic_size = BASIC_SIZE;\n"
10659 "const int type_align = TYPE_ALIGN;\n"
10660 "const int type_size = TYPE_SIZE;\n";
10661
10662 Utils::Type type = getType(test_case_index);
10663 GLuint basic_size = Utils::Type::GetTypeSize(type.m_basic_type);
10664 const GLuint base_align = type.GetBaseAlignment(false);
10665 const GLuint array_align = type.GetBaseAlignment(true);
10666 const GLuint base_stride = Utils::Type::CalculateStd140Stride(base_align, type.m_n_columns, 0);
10667 const GLuint type_align = Utils::roundUpToPowerOf2(base_stride);
10668
10669 /* Calculate offsets */
10670 const GLuint first_offset = 0;
10671 const GLuint second_offset = type.GetActualOffset(base_stride, basic_size / 2);
10672
10673 #if WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST
10674
10675 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, base_align);
10676 const GLuint fourth_offset = type.GetActualOffset(third_offset + base_stride, base_align);
10677 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10678 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10679 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10680 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, array_align);
10681
10682 #else /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10683
10684 const GLuint third_offset = type.GetActualOffset(second_offset + base_stride, 2 * type_align);
10685 const GLuint fourth_offset = type.GetActualOffset(3 * type_align + base_stride, base_align);
10686 const GLuint fifth_offset = type.GetActualOffset(fourth_offset + base_stride, base_align);
10687 const GLuint sixth_offset = type.GetActualOffset(fifth_offset + base_stride, array_align);
10688 const GLuint seventh_offset = type.GetActualOffset(sixth_offset + base_stride, array_align);
10689 const GLuint eigth_offset = type.GetActualOffset(seventh_offset + base_stride, 8 * basic_size);
10690
10691 #endif /* WRKARD_UNIFORMBLOCKMEMBEROFFSETANDALIGNTEST */
10692
10693 /* Prepare data */
10694 const std::vector<GLubyte>& first = type.GenerateData();
10695 const std::vector<GLubyte>& second = type.GenerateData();
10696 const std::vector<GLubyte>& third = type.GenerateData();
10697 const std::vector<GLubyte>& fourth = type.GenerateData();
10698
10699 m_data.resize(eigth_offset + base_stride);
10700 GLubyte* ptr = &m_data[0];
10701 memcpy(ptr + first_offset, &first[0], first.size());
10702 memcpy(ptr + second_offset, &second[0], second.size());
10703 memcpy(ptr + third_offset, &third[0], third.size());
10704 memcpy(ptr + fourth_offset, &fourth[0], fourth.size());
10705 memcpy(ptr + fifth_offset, &fourth[0], fourth.size());
10706 memcpy(ptr + sixth_offset, &third[0], third.size());
10707 memcpy(ptr + seventh_offset, &second[0], second.size());
10708 memcpy(ptr + eigth_offset, &first[0], first.size());
10709
10710 /* Prepare globals */
10711 size_t position = 0;
10712 GLchar buffer[16];
10713
10714 sprintf(buffer, "%d", basic_size);
10715 Utils::replaceToken("BASIC_SIZE", position, buffer, globals);
10716
10717 sprintf(buffer, "%d", type_align);
10718 Utils::replaceToken("TYPE_ALIGN", position, buffer, globals);
10719
10720 sprintf(buffer, "%d", base_stride);
10721 Utils::replaceToken("TYPE_SIZE", position, buffer, globals);
10722
10723 /* Prepare Block */
10724 Utils::Interface* vs_buf_block = program_interface.Block("vs_buf_Block");
10725
10726 vs_buf_block->Member("at_first_offset", "layout(offset = 0, align = 8 * basic_size)", 0 /* expected_component */,
10727 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10728 first_offset);
10729
10730 vs_buf_block->Member("at_second_offset", "layout(offset = type_size, align = basic_size / 2)",
10731 0 /* expected_component */, 0 /* expected_location */, type, false /* normalized */,
10732 0 /* n_array_elements */, base_stride, second_offset);
10733
10734 vs_buf_block->Member("at_third_offset", "layout(align = 2 * type_align)", 0 /* expected_component */,
10735 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10736 third_offset);
10737
10738 vs_buf_block->Member("at_fourth_offset", "layout(offset = 3 * type_align + type_size)", 0 /* expected_component */,
10739 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10740 fourth_offset);
10741
10742 vs_buf_block->Member("at_fifth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10743 false /* normalized */, 0 /* n_array_elements */, base_stride, fifth_offset);
10744
10745 vs_buf_block->Member("at_sixth_offset", "", 0 /* expected_component */, 0 /* expected_location */, type,
10746 false /* normalized */, 2 /* n_array_elements */, array_align * 2, sixth_offset);
10747
10748 vs_buf_block->Member("at_eigth_offset", "layout(align = 8 * basic_size)", 0 /* expected_component */,
10749 0 /* expected_location */, type, false /* normalized */, 0 /* n_array_elements */, base_stride,
10750 eigth_offset);
10751
10752 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
10753
10754 /* Add globals */
10755 vs_si.m_globals = globals;
10756
10757 /* Add uniform BLOCK */
10758 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_block, 0,
10759 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
10760
10761 /* */
10762 program_interface.CloneVertexInterface(varying_passthrough);
10763 }
10764
10765 /** Get type name
10766 *
10767 * @param test_case_index Index of test case
10768 *
10769 * @return Name of type test in test_case_index
10770 **/
10771 std::string SSBMemberOffsetAndAlignTest::getTestCaseName(glw::GLuint test_case_index)
10772 {
10773 return getTypeName(test_case_index);
10774 }
10775
10776 /** Returns number of types to test
10777 *
10778 * @return Number of types, 34
10779 **/
10780 glw::GLuint SSBMemberOffsetAndAlignTest::getTestCaseNumber()
10781 {
10782 return getTypesNumber();
10783 }
10784
10785 /** Prepare code snippet that will verify in and uniform variables
10786 *
10787 * @param ignored
10788 * @param ignored
10789 * @param stage Shader stage
10790 *
10791 * @return Code that verify variables
10792 **/
10793 std::string SSBMemberOffsetAndAlignTest::getVerificationSnippet(GLuint /* test_case_index */,
10794 Utils::ProgramInterface& /* program_interface */,
10795 Utils::Shader::STAGES stage)
10796 {
10797 std::string verification = "if ( (PREFIXblock.at_first_offset != PREFIXblock.at_eigth_offset ) ||\n"
10798 " (PREFIXblock.at_second_offset != PREFIXblock.at_sixth_offset[1]) ||\n"
10799 " (PREFIXblock.at_third_offset != PREFIXblock.at_sixth_offset[0]) ||\n"
10800 " (PREFIXblock.at_fourth_offset != PREFIXblock.at_fifth_offset ) )\n"
10801 " {\n"
10802 " result = 0;\n"
10803 " }";
10804
10805 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::SSB);
10806
10807 Utils::replaceAllTokens("PREFIX", prefix, verification);
10808
10809 return verification;
10810 }
10811
10812 /** Selects if "draw" stages are relevant for test
10813 *
10814 * @param ignored
10815 *
10816 * @return true if all stages support shader storage buffers, false otherwise
10817 **/
10818 bool SSBMemberOffsetAndAlignTest::isDrawRelevant(GLuint /* test_case_index */)
10819 {
10820 const Functions& gl = m_context.getRenderContext().getFunctions();
10821 GLint gs_supported_buffers = 0;
10822 GLint tcs_supported_buffers = 0;
10823 GLint tes_supported_buffers = 0;
10824 GLint vs_supported_buffers = 0;
10825
10826 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
10827 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
10828 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
10829 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
10830
10831 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
10832
10833 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
10834 (1 <= vs_supported_buffers));
10835 }
10836
10837 /** Constructor
10838 *
10839 * @param context Test framework context
10840 **/
10841 SSBLayoutQualifierConflictTest::SSBLayoutQualifierConflictTest(deqp::Context& context)
10842 : NegativeTestBase(context, "ssb_layout_qualifier_conflict", "Test verifies that std140 or std430 is required when "
10843 "offset and/or align qualifiers are used with storage "
10844 "block")
10845 {
10846 /* Nothing to be done here */
10847 }
10848
10849 /** Source for given test case and stage
10850 *
10851 * @param test_case_index Index of test case
10852 * @param stage Shader stage
10853 *
10854 * @return Shader source
10855 **/
10856 std::string SSBLayoutQualifierConflictTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
10857 {
10858 static const GLchar* cs = "#version 430 core\n"
10859 "#extension GL_ARB_enhanced_layouts : require\n"
10860 "\n"
10861 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
10862 "\n"
10863 "layout (QUALIFIERbinding = BINDING) buffer cs_Block {\n"
10864 " layout(offset = 16) vec4 boy;\n"
10865 " layout(align = 64) vec4 man;\n"
10866 "} uni_block;\n"
10867 "\n"
10868 "writeonly uniform image2D uni_image;\n"
10869 "\n"
10870 "void main()\n"
10871 "{\n"
10872 " vec4 result = uni_block.boy + uni_block.man;\n"
10873 "\n"
10874 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
10875 "}\n"
10876 "\n";
10877 static const GLchar* fs = "#version 430 core\n"
10878 "#extension GL_ARB_enhanced_layouts : require\n"
10879 "\n"
10880 "layout (QUALIFIERbinding = BINDING) buffer Block {\n"
10881 " layout(offset = 16) vec4 boy;\n"
10882 " layout(align = 64) vec4 man;\n"
10883 "} uni_block;\n"
10884 "\n"
10885 "in vec4 gs_fs;\n"
10886 "out vec4 fs_out;\n"
10887 "\n"
10888 "void main()\n"
10889 "{\n"
10890 " fs_out = gs_fs + uni_block.boy + uni_block.man;\n"
10891 "}\n"
10892 "\n";
10893 static const GLchar* gs = "#version 430 core\n"
10894 "#extension GL_ARB_enhanced_layouts : require\n"
10895 "\n"
10896 "layout(points) in;\n"
10897 "layout(triangle_strip, max_vertices = 4) out;\n"
10898 "\n"
10899 "layout (QUALIFIERbinding = BINDING) buffer gs_Block {\n"
10900 " layout(offset = 16) vec4 boy;\n"
10901 " layout(align = 64) vec4 man;\n"
10902 "} uni_block;\n"
10903 "\n"
10904 "in vec4 tes_gs[];\n"
10905 "out vec4 gs_fs;\n"
10906 "\n"
10907 "void main()\n"
10908 "{\n"
10909 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10910 " gl_Position = vec4(-1, -1, 0, 1);\n"
10911 " EmitVertex();\n"
10912 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10913 " gl_Position = vec4(-1, 1, 0, 1);\n"
10914 " EmitVertex();\n"
10915 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10916 " gl_Position = vec4(1, -1, 0, 1);\n"
10917 " EmitVertex();\n"
10918 " gs_fs = tes_gs[0] + uni_block.boy + uni_block.man;\n"
10919 " gl_Position = vec4(1, 1, 0, 1);\n"
10920 " EmitVertex();\n"
10921 "}\n"
10922 "\n";
10923 static const GLchar* tcs =
10924 "#version 430 core\n"
10925 "#extension GL_ARB_enhanced_layouts : require\n"
10926 "\n"
10927 "layout(vertices = 1) out;\n"
10928 "\n"
10929 "layout (QUALIFIERbinding = BINDING) buffer tcs_Block {\n"
10930 " layout(offset = 16) vec4 boy;\n"
10931 " layout(align = 64) vec4 man;\n"
10932 "} uni_block;\n"
10933 "\n"
10934 "in vec4 vs_tcs[];\n"
10935 "out vec4 tcs_tes[];\n"
10936 "\n"
10937 "void main()\n"
10938 "{\n"
10939 "\n"
10940 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID] + uni_block.boy + uni_block.man;\n"
10941 "\n"
10942 " gl_TessLevelOuter[0] = 1.0;\n"
10943 " gl_TessLevelOuter[1] = 1.0;\n"
10944 " gl_TessLevelOuter[2] = 1.0;\n"
10945 " gl_TessLevelOuter[3] = 1.0;\n"
10946 " gl_TessLevelInner[0] = 1.0;\n"
10947 " gl_TessLevelInner[1] = 1.0;\n"
10948 "}\n"
10949 "\n";
10950 static const GLchar* tes = "#version 430 core\n"
10951 "#extension GL_ARB_enhanced_layouts : require\n"
10952 "\n"
10953 "layout(isolines, point_mode) in;\n"
10954 "\n"
10955 "layout (QUALIFIERbinding = BINDING) buffer tes_Block {\n"
10956 " layout(offset = 16) vec4 boy;\n"
10957 " layout(align = 64) vec4 man;\n"
10958 "} uni_block;\n"
10959 "\n"
10960 "in vec4 tcs_tes[];\n"
10961 "out vec4 tes_gs;\n"
10962 "\n"
10963 "void main()\n"
10964 "{\n"
10965 " tes_gs = tcs_tes[0] + uni_block.boy + uni_block.man;\n"
10966 "}\n"
10967 "\n";
10968 static const GLchar* vs = "#version 430 core\n"
10969 "#extension GL_ARB_enhanced_layouts : require\n"
10970 "\n"
10971 "layout (QUALIFIERbinding = BINDING) buffer vs_Block {\n"
10972 " layout(offset = 16) vec4 boy;\n"
10973 " layout(align = 64) vec4 man;\n"
10974 "} uni_block;\n"
10975 "\n"
10976 "in vec4 in_vs;\n"
10977 "out vec4 vs_tcs;\n"
10978 "\n"
10979 "void main()\n"
10980 "{\n"
10981 " vs_tcs = in_vs + uni_block.boy + uni_block.man;\n"
10982 "}\n"
10983 "\n";
10984
10985 GLchar buffer[16];
10986 size_t position = 0;
10987 std::string source;
10988 testCase& test_case = m_test_cases[test_case_index];
10989 std::string qualifier = getQualifierName(test_case.m_qualifier);
10990
10991 if (false == qualifier.empty())
10992 {
10993 qualifier.append(", ");
10994 }
10995
10996 sprintf(buffer, "%d", stage);
10997
10998 switch (stage)
10999 {
11000 case Utils::Shader::COMPUTE:
11001 source = cs;
11002 break;
11003 case Utils::Shader::FRAGMENT:
11004 source = fs;
11005 break;
11006 case Utils::Shader::GEOMETRY:
11007 source = gs;
11008 break;
11009 case Utils::Shader::TESS_CTRL:
11010 source = tcs;
11011 break;
11012 case Utils::Shader::TESS_EVAL:
11013 source = tes;
11014 break;
11015 case Utils::Shader::VERTEX:
11016 source = vs;
11017 break;
11018 default:
11019 TCU_FAIL("Invalid enum");
11020 }
11021
11022 if (test_case.m_stage == stage)
11023 {
11024 Utils::replaceToken("QUALIFIER", position, qualifier.c_str(), source);
11025 }
11026 else
11027 {
11028 Utils::replaceToken("QUALIFIER", position, "std140, ", source);
11029 }
11030
11031 Utils::replaceToken("BINDING", position, buffer, source);
11032
11033 return source;
11034 }
11035
11036 /** Get description of test case
11037 *
11038 * @param test_case_index Index of test case
11039 *
11040 * @return Qualifier name
11041 **/
11042 std::string SSBLayoutQualifierConflictTest::getTestCaseName(GLuint test_case_index)
11043 {
11044 std::string result = getQualifierName(m_test_cases[test_case_index].m_qualifier);
11045
11046 return result;
11047 }
11048
11049 /** Get number of test cases
11050 *
11051 * @return Number of test cases
11052 **/
11053 GLuint SSBLayoutQualifierConflictTest::getTestCaseNumber()
11054 {
11055 return static_cast<GLuint>(m_test_cases.size());
11056 }
11057
11058 /** Selects if "compute" stage is relevant for test
11059 *
11060 * @param test_case_index Index of test case
11061 *
11062 * @return true when tested stage is compute
11063 **/
11064 bool SSBLayoutQualifierConflictTest::isComputeRelevant(GLuint test_case_index)
11065 {
11066 return (Utils::Shader::COMPUTE == m_test_cases[test_case_index].m_stage);
11067 }
11068
11069 /** Selects if compilation failure is expected result
11070 *
11071 * @param test_case_index Index of test case
11072 *
11073 * @return false for STD140 and STD430 cases, true otherwise
11074 **/
11075 bool SSBLayoutQualifierConflictTest::isFailureExpected(GLuint test_case_index)
11076 {
11077 const QUALIFIERS qualifier = m_test_cases[test_case_index].m_qualifier;
11078
11079 return !((STD140 == qualifier) || (STD430 == qualifier));
11080 }
11081
11082 /** Checks if stage is supported
11083 *
11084 * @param stage Shader stage
11085 *
11086 * @return true if supported, false otherwise
11087 **/
11088 bool SSBLayoutQualifierConflictTest::isStageSupported(Utils::Shader::STAGES stage)
11089 {
11090 const Functions& gl = m_context.getRenderContext().getFunctions();
11091 GLint max_supported_buffers = 0;
11092 GLenum pname = 0;
11093
11094 switch (stage)
11095 {
11096 case Utils::Shader::COMPUTE:
11097 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11098 break;
11099 case Utils::Shader::FRAGMENT:
11100 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11101 break;
11102 case Utils::Shader::GEOMETRY:
11103 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11104 break;
11105 case Utils::Shader::TESS_CTRL:
11106 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11107 break;
11108 case Utils::Shader::TESS_EVAL:
11109 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11110 break;
11111 case Utils::Shader::VERTEX:
11112 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11113 break;
11114 default:
11115 TCU_FAIL("Invalid enum");
11116 }
11117
11118 gl.getIntegerv(pname, &max_supported_buffers);
11119 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11120
11121 return 1 <= max_supported_buffers;
11122 }
11123
11124 /** Prepare all test cases
11125 *
11126 **/
11127 void SSBLayoutQualifierConflictTest::testInit()
11128 {
11129 bool stage_support[Utils::Shader::STAGE_MAX];
11130
11131 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11132 {
11133 stage_support[stage] = isStageSupported((Utils::Shader::STAGES)stage);
11134 }
11135
11136 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
11137 {
11138 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
11139 {
11140 if (false == stage_support[stage])
11141 {
11142 continue;
11143 }
11144
11145 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
11146
11147 m_test_cases.push_back(test_case);
11148 }
11149 }
11150 }
11151
11152 /** Get name of glsl constant
11153 *
11154 * @param Constant id
11155 *
11156 * @return Name of constant used in GLSL
11157 **/
11158 const GLchar* SSBLayoutQualifierConflictTest::getQualifierName(QUALIFIERS qualifier)
11159 {
11160 const GLchar* name = "";
11161
11162 switch (qualifier)
11163 {
11164 case DEFAULT:
11165 name = "";
11166 break;
11167 case STD140:
11168 name = "std140";
11169 break;
11170 case STD430:
11171 name = "std430";
11172 break;
11173 case SHARED:
11174 name = "shared";
11175 break;
11176 case PACKED:
11177 name = "packed";
11178 break;
11179 default:
11180 TCU_FAIL("Invalid enum");
11181 }
11182
11183 return name;
11184 }
11185
11186 /** Constructor
11187 *
11188 * @param context Test framework context
11189 **/
11190 SSBMemberInvalidOffsetAlignmentTest::SSBMemberInvalidOffsetAlignmentTest(deqp::Context& context)
11191 : UniformBlockMemberInvalidOffsetAlignmentTest(
11192 context, "ssb_member_invalid_offset_alignment",
11193 "Test verifies that invalid alignment of offset qualifiers cause compilation failure")
11194 {
11195 /* Nothing to be done here */
11196 }
11197
11198 /** Get the maximum size for a shader storage block
11199 *
11200 * @return The maximum size in basic machine units of a shader storage block.
11201 **/
11202 GLint SSBMemberInvalidOffsetAlignmentTest::getMaxBlockSize()
11203 {
11204 const Functions& gl = m_context.getRenderContext().getFunctions();
11205 GLint max_size = 0;
11206
11207 gl.getIntegerv(GL_MAX_SHADER_STORAGE_BLOCK_SIZE, &max_size);
11208 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11209
11210 return max_size;
11211 }
11212
11213 /** Source for given test case and stage
11214 *
11215 * @param test_case_index Index of test case
11216 * @param stage Shader stage
11217 *
11218 * @return Shader source
11219 **/
11220 std::string SSBMemberInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11221 {
11222 static const GLchar* cs = "#version 430 core\n"
11223 "#extension GL_ARB_enhanced_layouts : require\n"
11224 "\n"
11225 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11226 "\n"
11227 "layout (std140) buffer Block {\n"
11228 " layout (offset = OFFSET) TYPE member;\n"
11229 "} block;\n"
11230 "\n"
11231 "writeonly uniform image2D uni_image;\n"
11232 "\n"
11233 "void main()\n"
11234 "{\n"
11235 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11236 "\n"
11237 " if (TYPE(1) == block.member)\n"
11238 " {\n"
11239 " result = vec4(1, 1, 1, 1);\n"
11240 " }\n"
11241 "\n"
11242 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11243 "}\n"
11244 "\n";
11245 static const GLchar* fs = "#version 430 core\n"
11246 "#extension GL_ARB_enhanced_layouts : require\n"
11247 "\n"
11248 "in vec4 gs_fs;\n"
11249 "out vec4 fs_out;\n"
11250 "\n"
11251 "void main()\n"
11252 "{\n"
11253 " fs_out = gs_fs;\n"
11254 "}\n"
11255 "\n";
11256 static const GLchar* fs_tested = "#version 430 core\n"
11257 "#extension GL_ARB_enhanced_layouts : require\n"
11258 "\n"
11259 "layout (std140) buffer Block {\n"
11260 " layout (offset = OFFSET) TYPE member;\n"
11261 "} block;\n"
11262 "\n"
11263 "in vec4 gs_fs;\n"
11264 "out vec4 fs_out;\n"
11265 "\n"
11266 "void main()\n"
11267 "{\n"
11268 " if (TYPE(1) == block.member)\n"
11269 " {\n"
11270 " fs_out = vec4(1, 1, 1, 1);\n"
11271 " }\n"
11272 "\n"
11273 " fs_out += gs_fs;\n"
11274 "}\n"
11275 "\n";
11276 static const GLchar* gs = "#version 430 core\n"
11277 "#extension GL_ARB_enhanced_layouts : require\n"
11278 "\n"
11279 "layout(points) in;\n"
11280 "layout(triangle_strip, max_vertices = 4) out;\n"
11281 "\n"
11282 "in vec4 tes_gs[];\n"
11283 "out vec4 gs_fs;\n"
11284 "\n"
11285 "void main()\n"
11286 "{\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 " gs_fs = tes_gs[0];\n"
11294 " gl_Position = vec4(1, -1, 0, 1);\n"
11295 " EmitVertex();\n"
11296 " gs_fs = tes_gs[0];\n"
11297 " gl_Position = vec4(1, 1, 0, 1);\n"
11298 " EmitVertex();\n"
11299 "}\n"
11300 "\n";
11301 static const GLchar* gs_tested = "#version 430 core\n"
11302 "#extension GL_ARB_enhanced_layouts : require\n"
11303 "\n"
11304 "layout(points) in;\n"
11305 "layout(triangle_strip, max_vertices = 4) out;\n"
11306 "\n"
11307 "layout (std140) buffer Block {\n"
11308 " layout (offset = OFFSET) TYPE member;\n"
11309 "} block;\n"
11310 "\n"
11311 "in vec4 tes_gs[];\n"
11312 "out vec4 gs_fs;\n"
11313 "\n"
11314 "void main()\n"
11315 "{\n"
11316 " if (TYPE(1) == block.member)\n"
11317 " {\n"
11318 " gs_fs = vec4(1, 1, 1, 1);\n"
11319 " }\n"
11320 "\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 " gs_fs += tes_gs[0];\n"
11328 " gl_Position = vec4(1, -1, 0, 1);\n"
11329 " EmitVertex();\n"
11330 " gs_fs += tes_gs[0];\n"
11331 " gl_Position = vec4(1, 1, 0, 1);\n"
11332 " EmitVertex();\n"
11333 "}\n"
11334 "\n";
11335 static const GLchar* tcs = "#version 430 core\n"
11336 "#extension GL_ARB_enhanced_layouts : require\n"
11337 "\n"
11338 "layout(vertices = 1) out;\n"
11339 "\n"
11340 "in vec4 vs_tcs[];\n"
11341 "out vec4 tcs_tes[];\n"
11342 "\n"
11343 "void main()\n"
11344 "{\n"
11345 "\n"
11346 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11347 "\n"
11348 " gl_TessLevelOuter[0] = 1.0;\n"
11349 " gl_TessLevelOuter[1] = 1.0;\n"
11350 " gl_TessLevelOuter[2] = 1.0;\n"
11351 " gl_TessLevelOuter[3] = 1.0;\n"
11352 " gl_TessLevelInner[0] = 1.0;\n"
11353 " gl_TessLevelInner[1] = 1.0;\n"
11354 "}\n"
11355 "\n";
11356 static const GLchar* tcs_tested = "#version 430 core\n"
11357 "#extension GL_ARB_enhanced_layouts : require\n"
11358 "\n"
11359 "layout(vertices = 1) out;\n"
11360 "\n"
11361 "layout (std140) buffer Block {\n"
11362 " layout (offset = OFFSET) TYPE member;\n"
11363 "} block;\n"
11364 "\n"
11365 "in vec4 vs_tcs[];\n"
11366 "out vec4 tcs_tes[];\n"
11367 "\n"
11368 "void main()\n"
11369 "{\n"
11370 " if (TYPE(1) == block.member)\n"
11371 " {\n"
11372 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11373 " }\n"
11374 "\n"
11375 "\n"
11376 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11377 "\n"
11378 " gl_TessLevelOuter[0] = 1.0;\n"
11379 " gl_TessLevelOuter[1] = 1.0;\n"
11380 " gl_TessLevelOuter[2] = 1.0;\n"
11381 " gl_TessLevelOuter[3] = 1.0;\n"
11382 " gl_TessLevelInner[0] = 1.0;\n"
11383 " gl_TessLevelInner[1] = 1.0;\n"
11384 "}\n"
11385 "\n";
11386 static const GLchar* tes = "#version 430 core\n"
11387 "#extension GL_ARB_enhanced_layouts : require\n"
11388 "\n"
11389 "layout(isolines, point_mode) in;\n"
11390 "\n"
11391 "in vec4 tcs_tes[];\n"
11392 "out vec4 tes_gs;\n"
11393 "\n"
11394 "void main()\n"
11395 "{\n"
11396 " tes_gs = tcs_tes[0];\n"
11397 "}\n"
11398 "\n";
11399 static const GLchar* tes_tested = "#version 430 core\n"
11400 "#extension GL_ARB_enhanced_layouts : require\n"
11401 "\n"
11402 "layout(isolines, point_mode) in;\n"
11403 "\n"
11404 "layout (std140) buffer Block {\n"
11405 " layout (offset = OFFSET) TYPE member;\n"
11406 "} block;\n"
11407 "\n"
11408 "in vec4 tcs_tes[];\n"
11409 "out vec4 tes_gs;\n"
11410 "\n"
11411 "void main()\n"
11412 "{\n"
11413 " if (TYPE(1) == block.member)\n"
11414 " {\n"
11415 " tes_gs = vec4(1, 1, 1, 1);\n"
11416 " }\n"
11417 "\n"
11418 " tes_gs += tcs_tes[0];\n"
11419 "}\n"
11420 "\n";
11421 static const GLchar* vs = "#version 430 core\n"
11422 "#extension GL_ARB_enhanced_layouts : require\n"
11423 "\n"
11424 "in vec4 in_vs;\n"
11425 "out vec4 vs_tcs;\n"
11426 "\n"
11427 "void main()\n"
11428 "{\n"
11429 " vs_tcs = in_vs;\n"
11430 "}\n"
11431 "\n";
11432 static const GLchar* vs_tested = "#version 430 core\n"
11433 "#extension GL_ARB_enhanced_layouts : require\n"
11434 "\n"
11435 "layout (std140) buffer Block {\n"
11436 " layout (offset = OFFSET) TYPE member;\n"
11437 "} block;\n"
11438 "\n"
11439 "in vec4 in_vs;\n"
11440 "out vec4 vs_tcs;\n"
11441 "\n"
11442 "void main()\n"
11443 "{\n"
11444 " if (TYPE(1) == block.member)\n"
11445 " {\n"
11446 " vs_tcs = vec4(1, 1, 1, 1);\n"
11447 " }\n"
11448 "\n"
11449 " vs_tcs += in_vs;\n"
11450 "}\n"
11451 "\n";
11452
11453 std::string source;
11454 testCase& test_case = m_test_cases[test_case_index];
11455
11456 if (test_case.m_stage == stage)
11457 {
11458 GLchar buffer[16];
11459 const GLuint offset = test_case.m_offset;
11460 size_t position = 0;
11461 const Utils::Type& type = test_case.m_type;
11462 const GLchar* type_name = type.GetGLSLTypeName();
11463
11464 sprintf(buffer, "%d", offset);
11465
11466 switch (stage)
11467 {
11468 case Utils::Shader::COMPUTE:
11469 source = cs;
11470 break;
11471 case Utils::Shader::FRAGMENT:
11472 source = fs_tested;
11473 break;
11474 case Utils::Shader::GEOMETRY:
11475 source = gs_tested;
11476 break;
11477 case Utils::Shader::TESS_CTRL:
11478 source = tcs_tested;
11479 break;
11480 case Utils::Shader::TESS_EVAL:
11481 source = tes_tested;
11482 break;
11483 case Utils::Shader::VERTEX:
11484 source = vs_tested;
11485 break;
11486 default:
11487 TCU_FAIL("Invalid enum");
11488 }
11489
11490 Utils::replaceToken("OFFSET", position, buffer, source);
11491 Utils::replaceToken("TYPE", position, type_name, source);
11492 Utils::replaceToken("TYPE", position, type_name, source);
11493 }
11494 else
11495 {
11496 switch (stage)
11497 {
11498 case Utils::Shader::FRAGMENT:
11499 source = fs;
11500 break;
11501 case Utils::Shader::GEOMETRY:
11502 source = gs;
11503 break;
11504 case Utils::Shader::TESS_CTRL:
11505 source = tcs;
11506 break;
11507 case Utils::Shader::TESS_EVAL:
11508 source = tes;
11509 break;
11510 case Utils::Shader::VERTEX:
11511 source = vs;
11512 break;
11513 default:
11514 TCU_FAIL("Invalid enum");
11515 }
11516 }
11517
11518 return source;
11519 }
11520
11521 /** Checks if stage is supported
11522 *
11523 * @param stage Shader stage
11524 *
11525 * @return true if supported, false otherwise
11526 **/
11527 bool SSBMemberInvalidOffsetAlignmentTest::isStageSupported(Utils::Shader::STAGES stage)
11528 {
11529 const Functions& gl = m_context.getRenderContext().getFunctions();
11530 GLint max_supported_buffers = 0;
11531 GLenum pname = 0;
11532
11533 switch (stage)
11534 {
11535 case Utils::Shader::COMPUTE:
11536 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11537 break;
11538 case Utils::Shader::FRAGMENT:
11539 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11540 break;
11541 case Utils::Shader::GEOMETRY:
11542 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11543 break;
11544 case Utils::Shader::TESS_CTRL:
11545 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11546 break;
11547 case Utils::Shader::TESS_EVAL:
11548 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11549 break;
11550 case Utils::Shader::VERTEX:
11551 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11552 break;
11553 default:
11554 TCU_FAIL("Invalid enum");
11555 }
11556
11557 gl.getIntegerv(pname, &max_supported_buffers);
11558 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11559
11560 return 1 <= max_supported_buffers;
11561 }
11562
11563 /** Constructor
11564 *
11565 * @param context Test framework context
11566 **/
11567 SSBMemberOverlappingOffsetsTest::SSBMemberOverlappingOffsetsTest(deqp::Context& context)
11568 : UniformBlockMemberOverlappingOffsetsTest(
11569 context, "ssb_member_overlapping_offsets",
11570 "Test verifies that overlapping offsets qualifiers cause compilation failure")
11571 {
11572 /* Nothing to be done here */
11573 }
11574
11575 /** Source for given test case and stage
11576 *
11577 * @param test_case_index Index of test case
11578 * @param stage Shader stage
11579 *
11580 * @return Shader source
11581 **/
11582 std::string SSBMemberOverlappingOffsetsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11583 {
11584 static const GLchar* cs = "#version 430 core\n"
11585 "#extension GL_ARB_enhanced_layouts : require\n"
11586 "\n"
11587 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11588 "\n"
11589 "layout (std140) buffer Block {\n"
11590 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11591 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11592 "} block;\n"
11593 "\n"
11594 "writeonly uniform image2D uni_image;\n"
11595 "\n"
11596 "void main()\n"
11597 "{\n"
11598 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11599 "\n"
11600 " if ((BOY_TYPE(1) == block.boy) ||\n"
11601 " (MAN_TYPE(0) == block.man) )\n"
11602 " {\n"
11603 " result = vec4(1, 1, 1, 1);\n"
11604 " }\n"
11605 "\n"
11606 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11607 "}\n"
11608 "\n";
11609 static const GLchar* fs = "#version 430 core\n"
11610 "#extension GL_ARB_enhanced_layouts : require\n"
11611 "\n"
11612 "in vec4 gs_fs;\n"
11613 "out vec4 fs_out;\n"
11614 "\n"
11615 "void main()\n"
11616 "{\n"
11617 " fs_out = gs_fs;\n"
11618 "}\n"
11619 "\n";
11620 static const GLchar* fs_tested = "#version 430 core\n"
11621 "#extension GL_ARB_enhanced_layouts : require\n"
11622 "\n"
11623 "layout (std140) buffer Block {\n"
11624 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11625 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11626 "} block;\n"
11627 "\n"
11628 "in vec4 gs_fs;\n"
11629 "out vec4 fs_out;\n"
11630 "\n"
11631 "void main()\n"
11632 "{\n"
11633 " if ((BOY_TYPE(1) == block.boy) ||\n"
11634 " (MAN_TYPE(0) == block.man) )\n"
11635 " {\n"
11636 " fs_out = vec4(1, 1, 1, 1);\n"
11637 " }\n"
11638 "\n"
11639 " fs_out += gs_fs;\n"
11640 "}\n"
11641 "\n";
11642 static const GLchar* gs = "#version 430 core\n"
11643 "#extension GL_ARB_enhanced_layouts : require\n"
11644 "\n"
11645 "layout(points) in;\n"
11646 "layout(triangle_strip, max_vertices = 4) out;\n"
11647 "\n"
11648 "in vec4 tes_gs[];\n"
11649 "out vec4 gs_fs;\n"
11650 "\n"
11651 "void main()\n"
11652 "{\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 " gs_fs = tes_gs[0];\n"
11660 " gl_Position = vec4(1, -1, 0, 1);\n"
11661 " EmitVertex();\n"
11662 " gs_fs = tes_gs[0];\n"
11663 " gl_Position = vec4(1, 1, 0, 1);\n"
11664 " EmitVertex();\n"
11665 "}\n"
11666 "\n";
11667 static const GLchar* gs_tested = "#version 430 core\n"
11668 "#extension GL_ARB_enhanced_layouts : require\n"
11669 "\n"
11670 "layout(points) in;\n"
11671 "layout(triangle_strip, max_vertices = 4) out;\n"
11672 "\n"
11673 "layout (std140) buffer Block {\n"
11674 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11675 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11676 "} block;\n"
11677 "\n"
11678 "in vec4 tes_gs[];\n"
11679 "out vec4 gs_fs;\n"
11680 "\n"
11681 "void main()\n"
11682 "{\n"
11683 " if ((BOY_TYPE(1) == block.boy) ||\n"
11684 " (MAN_TYPE(0) == block.man) )\n"
11685 " {\n"
11686 " gs_fs = vec4(1, 1, 1, 1);\n"
11687 " }\n"
11688 "\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 " gs_fs += tes_gs[0];\n"
11696 " gl_Position = vec4(1, -1, 0, 1);\n"
11697 " EmitVertex();\n"
11698 " gs_fs += tes_gs[0];\n"
11699 " gl_Position = vec4(1, 1, 0, 1);\n"
11700 " EmitVertex();\n"
11701 "}\n"
11702 "\n";
11703 static const GLchar* tcs = "#version 430 core\n"
11704 "#extension GL_ARB_enhanced_layouts : require\n"
11705 "\n"
11706 "layout(vertices = 1) out;\n"
11707 "\n"
11708 "in vec4 vs_tcs[];\n"
11709 "out vec4 tcs_tes[];\n"
11710 "\n"
11711 "void main()\n"
11712 "{\n"
11713 "\n"
11714 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
11715 "\n"
11716 " gl_TessLevelOuter[0] = 1.0;\n"
11717 " gl_TessLevelOuter[1] = 1.0;\n"
11718 " gl_TessLevelOuter[2] = 1.0;\n"
11719 " gl_TessLevelOuter[3] = 1.0;\n"
11720 " gl_TessLevelInner[0] = 1.0;\n"
11721 " gl_TessLevelInner[1] = 1.0;\n"
11722 "}\n"
11723 "\n";
11724 static const GLchar* tcs_tested = "#version 430 core\n"
11725 "#extension GL_ARB_enhanced_layouts : require\n"
11726 "\n"
11727 "layout(vertices = 1) out;\n"
11728 "\n"
11729 "layout (std140) buffer Block {\n"
11730 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11731 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11732 "} block;\n"
11733 "\n"
11734 "in vec4 vs_tcs[];\n"
11735 "out vec4 tcs_tes[];\n"
11736 "\n"
11737 "void main()\n"
11738 "{\n"
11739 " if ((BOY_TYPE(1) == block.boy) ||\n"
11740 " (MAN_TYPE(0) == block.man) )\n"
11741 " {\n"
11742 " tcs_tes[gl_InvocationID] = vec4(1, 1, 1, 1);\n"
11743 " }\n"
11744 "\n"
11745 "\n"
11746 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
11747 "\n"
11748 " gl_TessLevelOuter[0] = 1.0;\n"
11749 " gl_TessLevelOuter[1] = 1.0;\n"
11750 " gl_TessLevelOuter[2] = 1.0;\n"
11751 " gl_TessLevelOuter[3] = 1.0;\n"
11752 " gl_TessLevelInner[0] = 1.0;\n"
11753 " gl_TessLevelInner[1] = 1.0;\n"
11754 "}\n"
11755 "\n";
11756 static const GLchar* tes = "#version 430 core\n"
11757 "#extension GL_ARB_enhanced_layouts : require\n"
11758 "\n"
11759 "layout(isolines, point_mode) in;\n"
11760 "\n"
11761 "in vec4 tcs_tes[];\n"
11762 "out vec4 tes_gs;\n"
11763 "\n"
11764 "void main()\n"
11765 "{\n"
11766 " tes_gs = tcs_tes[0];\n"
11767 "}\n"
11768 "\n";
11769 static const GLchar* tes_tested = "#version 430 core\n"
11770 "#extension GL_ARB_enhanced_layouts : require\n"
11771 "\n"
11772 "layout(isolines, point_mode) in;\n"
11773 "\n"
11774 "layout (std140) buffer Block {\n"
11775 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11776 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11777 "} block;\n"
11778 "\n"
11779 "in vec4 tcs_tes[];\n"
11780 "out vec4 tes_gs;\n"
11781 "\n"
11782 "void main()\n"
11783 "{\n"
11784 " if ((BOY_TYPE(1) == block.boy) ||\n"
11785 " (MAN_TYPE(0) == block.man) )\n"
11786 " {\n"
11787 " tes_gs = vec4(1, 1, 1, 1);\n"
11788 " }\n"
11789 "\n"
11790 " tes_gs += tcs_tes[0];\n"
11791 "}\n"
11792 "\n";
11793 static const GLchar* vs = "#version 430 core\n"
11794 "#extension GL_ARB_enhanced_layouts : require\n"
11795 "\n"
11796 "in vec4 in_vs;\n"
11797 "out vec4 vs_tcs;\n"
11798 "\n"
11799 "void main()\n"
11800 "{\n"
11801 " vs_tcs = in_vs;\n"
11802 "}\n"
11803 "\n";
11804 static const GLchar* vs_tested = "#version 430 core\n"
11805 "#extension GL_ARB_enhanced_layouts : require\n"
11806 "\n"
11807 "layout (std140) buffer Block {\n"
11808 " layout (offset = BOY_OFFSET) BOY_TYPE boy;\n"
11809 " layout (offset = MAN_OFFSET) MAN_TYPE man;\n"
11810 "} block;\n"
11811 "\n"
11812 "in vec4 in_vs;\n"
11813 "out vec4 vs_tcs;\n"
11814 "\n"
11815 "void main()\n"
11816 "{\n"
11817 " if ((BOY_TYPE(1) == block.boy) ||\n"
11818 " (MAN_TYPE(0) == block.man) )\n"
11819 " {\n"
11820 " vs_tcs = vec4(1, 1, 1, 1);\n"
11821 " }\n"
11822 "\n"
11823 " vs_tcs += in_vs;\n"
11824 "}\n"
11825 "\n";
11826
11827 std::string source;
11828 testCase& test_case = m_test_cases[test_case_index];
11829
11830 if (test_case.m_stage == stage)
11831 {
11832 GLchar buffer[16];
11833 const GLuint boy_offset = test_case.m_boy_offset;
11834 const Utils::Type& boy_type = test_case.m_boy_type;
11835 const GLchar* boy_type_name = boy_type.GetGLSLTypeName();
11836 const GLuint man_offset = test_case.m_man_offset;
11837 const Utils::Type& man_type = test_case.m_man_type;
11838 const GLchar* man_type_name = man_type.GetGLSLTypeName();
11839 size_t position = 0;
11840
11841 switch (stage)
11842 {
11843 case Utils::Shader::COMPUTE:
11844 source = cs;
11845 break;
11846 case Utils::Shader::FRAGMENT:
11847 source = fs_tested;
11848 break;
11849 case Utils::Shader::GEOMETRY:
11850 source = gs_tested;
11851 break;
11852 case Utils::Shader::TESS_CTRL:
11853 source = tcs_tested;
11854 break;
11855 case Utils::Shader::TESS_EVAL:
11856 source = tes_tested;
11857 break;
11858 case Utils::Shader::VERTEX:
11859 source = vs_tested;
11860 break;
11861 default:
11862 TCU_FAIL("Invalid enum");
11863 }
11864
11865 sprintf(buffer, "%d", boy_offset);
11866 Utils::replaceToken("BOY_OFFSET", position, buffer, source);
11867 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
11868 sprintf(buffer, "%d", man_offset);
11869 Utils::replaceToken("MAN_OFFSET", position, buffer, source);
11870 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
11871 Utils::replaceToken("BOY_TYPE", position, boy_type_name, source);
11872 Utils::replaceToken("MAN_TYPE", position, man_type_name, source);
11873 }
11874 else
11875 {
11876 switch (stage)
11877 {
11878 case Utils::Shader::FRAGMENT:
11879 source = fs;
11880 break;
11881 case Utils::Shader::GEOMETRY:
11882 source = gs;
11883 break;
11884 case Utils::Shader::TESS_CTRL:
11885 source = tcs;
11886 break;
11887 case Utils::Shader::TESS_EVAL:
11888 source = tes;
11889 break;
11890 case Utils::Shader::VERTEX:
11891 source = vs;
11892 break;
11893 default:
11894 TCU_FAIL("Invalid enum");
11895 }
11896 }
11897
11898 return source;
11899 }
11900
11901 /** Checks if stage is supported
11902 *
11903 * @param stage Shader stage
11904 *
11905 * @return true if supported, false otherwise
11906 **/
11907 bool SSBMemberOverlappingOffsetsTest::isStageSupported(Utils::Shader::STAGES stage)
11908 {
11909 const Functions& gl = m_context.getRenderContext().getFunctions();
11910 GLint max_supported_buffers = 0;
11911 GLenum pname = 0;
11912
11913 switch (stage)
11914 {
11915 case Utils::Shader::COMPUTE:
11916 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
11917 break;
11918 case Utils::Shader::FRAGMENT:
11919 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
11920 break;
11921 case Utils::Shader::GEOMETRY:
11922 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
11923 break;
11924 case Utils::Shader::TESS_CTRL:
11925 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
11926 break;
11927 case Utils::Shader::TESS_EVAL:
11928 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
11929 break;
11930 case Utils::Shader::VERTEX:
11931 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
11932 break;
11933 default:
11934 TCU_FAIL("Invalid enum");
11935 }
11936
11937 gl.getIntegerv(pname, &max_supported_buffers);
11938 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
11939
11940 return 1 <= max_supported_buffers;
11941 }
11942
11943 /** Constructor
11944 *
11945 * @param context Test framework context
11946 **/
11947 SSBMemberAlignNonPowerOf2Test::SSBMemberAlignNonPowerOf2Test(deqp::Context& context)
11948 : UniformBlockMemberAlignNonPowerOf2Test(context, "ssb_member_align_non_power_of_2",
11949 "Test verifies that align qualifier requires value that is a power of 2")
11950 {
11951 /* Nothing to be done here */
11952 }
11953
11954 /** Source for given test case and stage
11955 *
11956 * @param test_case_index Index of test case
11957 * @param stage Shader stage
11958 *
11959 * @return Shader source
11960 **/
11961 std::string SSBMemberAlignNonPowerOf2Test::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
11962 {
11963 static const GLchar* cs = "#version 430 core\n"
11964 "#extension GL_ARB_enhanced_layouts : require\n"
11965 "\n"
11966 "layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
11967 "\n"
11968 "layout (std140) buffer Block {\n"
11969 " vec4 boy;\n"
11970 " layout (align = ALIGN) TYPE man;\n"
11971 "} block;\n"
11972 "\n"
11973 "writeonly uniform image2D uni_image;\n"
11974 "\n"
11975 "void main()\n"
11976 "{\n"
11977 " vec4 result = vec4(1, 0, 0.5, 1);\n"
11978 "\n"
11979 " if (TYPE(0) == block.man)\n"
11980 " {\n"
11981 " result = vec4(1, 1, 1, 1) - block.boy;\n"
11982 " }\n"
11983 "\n"
11984 " imageStore(uni_image, ivec2(gl_GlobalInvocationID.xy), result);\n"
11985 "}\n"
11986 "\n";
11987 static const GLchar* fs = "#version 430 core\n"
11988 "#extension GL_ARB_enhanced_layouts : require\n"
11989 "\n"
11990 "in vec4 gs_fs;\n"
11991 "out vec4 fs_out;\n"
11992 "\n"
11993 "void main()\n"
11994 "{\n"
11995 " fs_out = gs_fs;\n"
11996 "}\n"
11997 "\n";
11998 static const GLchar* fs_tested = "#version 430 core\n"
11999 "#extension GL_ARB_enhanced_layouts : require\n"
12000 "\n"
12001 "layout (std140) buffer Block {\n"
12002 " vec4 boy;\n"
12003 " layout (align = ALIGN) TYPE man;\n"
12004 "} block;\n"
12005 "\n"
12006 "in vec4 gs_fs;\n"
12007 "out vec4 fs_out;\n"
12008 "\n"
12009 "void main()\n"
12010 "{\n"
12011 " if (TYPE(0) == block.man)\n"
12012 " {\n"
12013 " fs_out = block.boy;\n"
12014 " }\n"
12015 "\n"
12016 " fs_out += gs_fs;\n"
12017 "}\n"
12018 "\n";
12019 static const GLchar* gs = "#version 430 core\n"
12020 "#extension GL_ARB_enhanced_layouts : require\n"
12021 "\n"
12022 "layout(points) in;\n"
12023 "layout(triangle_strip, max_vertices = 4) out;\n"
12024 "\n"
12025 "in vec4 tes_gs[];\n"
12026 "out vec4 gs_fs;\n"
12027 "\n"
12028 "void main()\n"
12029 "{\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 " gs_fs = tes_gs[0];\n"
12037 " gl_Position = vec4(1, -1, 0, 1);\n"
12038 " EmitVertex();\n"
12039 " gs_fs = tes_gs[0];\n"
12040 " gl_Position = vec4(1, 1, 0, 1);\n"
12041 " EmitVertex();\n"
12042 "}\n"
12043 "\n";
12044 static const GLchar* gs_tested = "#version 430 core\n"
12045 "#extension GL_ARB_enhanced_layouts : require\n"
12046 "\n"
12047 "layout(points) in;\n"
12048 "layout(triangle_strip, max_vertices = 4) out;\n"
12049 "\n"
12050 "layout (std140) buffer Block {\n"
12051 " vec4 boy;\n"
12052 " layout (align = ALIGN) TYPE man;\n"
12053 "} block;\n"
12054 "\n"
12055 "in vec4 tes_gs[];\n"
12056 "out vec4 gs_fs;\n"
12057 "\n"
12058 "void main()\n"
12059 "{\n"
12060 " if (TYPE(0) == block.man)\n"
12061 " {\n"
12062 " gs_fs = block.boy;\n"
12063 " }\n"
12064 "\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 " gs_fs += tes_gs[0];\n"
12072 " gl_Position = vec4(1, -1, 0, 1);\n"
12073 " EmitVertex();\n"
12074 " gs_fs += tes_gs[0];\n"
12075 " gl_Position = vec4(1, 1, 0, 1);\n"
12076 " EmitVertex();\n"
12077 "}\n"
12078 "\n";
12079 static const GLchar* tcs = "#version 430 core\n"
12080 "#extension GL_ARB_enhanced_layouts : require\n"
12081 "\n"
12082 "layout(vertices = 1) out;\n"
12083 "\n"
12084 "in vec4 vs_tcs[];\n"
12085 "out vec4 tcs_tes[];\n"
12086 "\n"
12087 "void main()\n"
12088 "{\n"
12089 "\n"
12090 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
12091 "\n"
12092 " gl_TessLevelOuter[0] = 1.0;\n"
12093 " gl_TessLevelOuter[1] = 1.0;\n"
12094 " gl_TessLevelOuter[2] = 1.0;\n"
12095 " gl_TessLevelOuter[3] = 1.0;\n"
12096 " gl_TessLevelInner[0] = 1.0;\n"
12097 " gl_TessLevelInner[1] = 1.0;\n"
12098 "}\n"
12099 "\n";
12100 static const GLchar* tcs_tested = "#version 430 core\n"
12101 "#extension GL_ARB_enhanced_layouts : require\n"
12102 "\n"
12103 "layout(vertices = 1) out;\n"
12104 "\n"
12105 "layout (std140) buffer Block {\n"
12106 " vec4 boy;\n"
12107 " layout (align = ALIGN) TYPE man;\n"
12108 "} block;\n"
12109 "\n"
12110 "in vec4 vs_tcs[];\n"
12111 "out vec4 tcs_tes[];\n"
12112 "\n"
12113 "void main()\n"
12114 "{\n"
12115 " if (TYPE(0) == block.man)\n"
12116 " {\n"
12117 " tcs_tes[gl_InvocationID] = block.boy;\n"
12118 " }\n"
12119 "\n"
12120 "\n"
12121 " tcs_tes[gl_InvocationID] += vs_tcs[gl_InvocationID];\n"
12122 "\n"
12123 " gl_TessLevelOuter[0] = 1.0;\n"
12124 " gl_TessLevelOuter[1] = 1.0;\n"
12125 " gl_TessLevelOuter[2] = 1.0;\n"
12126 " gl_TessLevelOuter[3] = 1.0;\n"
12127 " gl_TessLevelInner[0] = 1.0;\n"
12128 " gl_TessLevelInner[1] = 1.0;\n"
12129 "}\n"
12130 "\n";
12131 static const GLchar* tes = "#version 430 core\n"
12132 "#extension GL_ARB_enhanced_layouts : require\n"
12133 "\n"
12134 "layout(isolines, point_mode) in;\n"
12135 "\n"
12136 "in vec4 tcs_tes[];\n"
12137 "out vec4 tes_gs;\n"
12138 "\n"
12139 "void main()\n"
12140 "{\n"
12141 " tes_gs = tcs_tes[0];\n"
12142 "}\n"
12143 "\n";
12144 static const GLchar* tes_tested = "#version 430 core\n"
12145 "#extension GL_ARB_enhanced_layouts : require\n"
12146 "\n"
12147 "layout(isolines, point_mode) in;\n"
12148 "\n"
12149 "layout (std140) buffer Block {\n"
12150 " vec4 boy;\n"
12151 " layout (align = ALIGN) TYPE man;\n"
12152 "} block;\n"
12153 "\n"
12154 "in vec4 tcs_tes[];\n"
12155 "out vec4 tes_gs;\n"
12156 "\n"
12157 "void main()\n"
12158 "{\n"
12159 " if (TYPE(0) == block.man)\n"
12160 " {\n"
12161 " tes_gs = block.boy;\n"
12162 " }\n"
12163 "\n"
12164 " tes_gs += tcs_tes[0];\n"
12165 "}\n"
12166 "\n";
12167 static const GLchar* vs = "#version 430 core\n"
12168 "#extension GL_ARB_enhanced_layouts : require\n"
12169 "\n"
12170 "in vec4 in_vs;\n"
12171 "out vec4 vs_tcs;\n"
12172 "\n"
12173 "void main()\n"
12174 "{\n"
12175 " vs_tcs = in_vs;\n"
12176 "}\n"
12177 "\n";
12178 static const GLchar* vs_tested = "#version 430 core\n"
12179 "#extension GL_ARB_enhanced_layouts : require\n"
12180 "\n"
12181 "layout (std140) buffer Block {\n"
12182 " vec4 boy;\n"
12183 " layout (align = ALIGN) TYPE man;\n"
12184 "} block;\n"
12185 "\n"
12186 "in vec4 in_vs;\n"
12187 "out vec4 vs_tcs;\n"
12188 "\n"
12189 "void main()\n"
12190 "{\n"
12191 " if (TYPE(0) == block.man)\n"
12192 " {\n"
12193 " vs_tcs = block.boy;\n"
12194 " }\n"
12195 "\n"
12196 " vs_tcs += in_vs;\n"
12197 "}\n"
12198 "\n";
12199
12200 std::string source;
12201 testCase& test_case = m_test_cases[test_case_index];
12202
12203 if (test_case.m_stage == stage)
12204 {
12205 GLchar buffer[16];
12206 const GLuint alignment = test_case.m_alignment;
12207 const Utils::Type& type = test_case.m_type;
12208 const GLchar* type_name = type.GetGLSLTypeName();
12209 size_t position = 0;
12210
12211 switch (stage)
12212 {
12213 case Utils::Shader::COMPUTE:
12214 source = cs;
12215 break;
12216 case Utils::Shader::FRAGMENT:
12217 source = fs_tested;
12218 break;
12219 case Utils::Shader::GEOMETRY:
12220 source = gs_tested;
12221 break;
12222 case Utils::Shader::TESS_CTRL:
12223 source = tcs_tested;
12224 break;
12225 case Utils::Shader::TESS_EVAL:
12226 source = tes_tested;
12227 break;
12228 case Utils::Shader::VERTEX:
12229 source = vs_tested;
12230 break;
12231 default:
12232 TCU_FAIL("Invalid enum");
12233 }
12234
12235 sprintf(buffer, "%d", alignment);
12236 Utils::replaceToken("ALIGN", position, buffer, source);
12237 Utils::replaceToken("TYPE", position, type_name, source);
12238 Utils::replaceToken("TYPE", position, type_name, source);
12239 }
12240 else
12241 {
12242 switch (stage)
12243 {
12244 case Utils::Shader::FRAGMENT:
12245 source = fs;
12246 break;
12247 case Utils::Shader::GEOMETRY:
12248 source = gs;
12249 break;
12250 case Utils::Shader::TESS_CTRL:
12251 source = tcs;
12252 break;
12253 case Utils::Shader::TESS_EVAL:
12254 source = tes;
12255 break;
12256 case Utils::Shader::VERTEX:
12257 source = vs;
12258 break;
12259 default:
12260 TCU_FAIL("Invalid enum");
12261 }
12262 }
12263
12264 return source;
12265 }
12266
12267 /** Checks if stage is supported
12268 *
12269 * @param stage Shader stage
12270 *
12271 * @return true if supported, false otherwise
12272 **/
12273 bool SSBMemberAlignNonPowerOf2Test::isStageSupported(Utils::Shader::STAGES stage)
12274 {
12275 const Functions& gl = m_context.getRenderContext().getFunctions();
12276 GLint max_supported_buffers = 0;
12277 GLenum pname = 0;
12278
12279 switch (stage)
12280 {
12281 case Utils::Shader::COMPUTE:
12282 pname = GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS;
12283 break;
12284 case Utils::Shader::FRAGMENT:
12285 pname = GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS;
12286 break;
12287 case Utils::Shader::GEOMETRY:
12288 pname = GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS;
12289 break;
12290 case Utils::Shader::TESS_CTRL:
12291 pname = GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS;
12292 break;
12293 case Utils::Shader::TESS_EVAL:
12294 pname = GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS;
12295 break;
12296 case Utils::Shader::VERTEX:
12297 pname = GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS;
12298 break;
12299 default:
12300 TCU_FAIL("Invalid enum");
12301 }
12302
12303 gl.getIntegerv(pname, &max_supported_buffers);
12304 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12305
12306 return 1 <= max_supported_buffers;
12307 }
12308
12309 /** Constructor
12310 *
12311 * @param context Test framework context
12312 **/
12313 SSBAlignmentTest::SSBAlignmentTest(deqp::Context& context)
12314 : TextureTestBase(context, "ssb_alignment", "Test verifies offset and alignment of ssb buffer")
12315 {
12316 }
12317
12318 /** Get interface of program
12319 *
12320 * @param ignored
12321 * @param program_interface Interface of program
12322 * @param varying_passthrough Collection of connections between in and out variables
12323 **/
12324 void SSBAlignmentTest::getProgramInterface(GLuint /* test_case_index */, Utils::ProgramInterface& program_interface,
12325 Utils::VaryingPassthrough& varying_passthrough)
12326 {
12327 static const Utils::Type vec4 = Utils::Type::vec4;
12328
12329 #if WRKARD_UNIFORMBLOCKALIGNMENT
12330
12331 static const GLuint block_align = 16;
12332
12333 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12334
12335 static const GLuint block_align = 64;
12336
12337 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12338
12339 static const GLuint fifth_align = 16;
12340 static const GLuint vec4_stride = 16;
12341 static const GLuint data_stride = vec4_stride * 2; /* one vec4 + one scalar aligned to 16 */
12342
12343 const GLuint first_offset = 0; /* vec4 at 0 */
12344 const GLuint second_offset = Utils::Type::GetActualOffset(first_offset + vec4_stride, block_align); /* Data at 32 */
12345 const GLuint third_offset =
12346 Utils::Type::GetActualOffset(second_offset + data_stride, block_align); /* Data[2] at 64 */
12347 const GLuint fourth_offset =
12348 Utils::Type::GetActualOffset(third_offset + data_stride * 2, block_align); /* vec4[3] at 96 */
12349 const GLuint fifth_offset =
12350 Utils::Type::GetActualOffset(fourth_offset + vec4_stride * 3, fifth_align); /* vec4[2] at 160 */
12351 const GLuint sixth_offset =
12352 Utils::Type::GetActualOffset(fifth_offset + vec4_stride * 2, block_align); /* Data at 192 */
12353
12354 Utils::Interface* structure = program_interface.Structure("Data");
12355
12356 structure->Member("vector", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12357 false /* normalized */, 0 /* n_array_elements */, Utils::Type::vec4.GetSize(), 0 /* offset */);
12358
12359 structure->Member("scalar", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::_float,
12360 false /* normalized */, 0 /* n_array_elements */, Utils::Type::_float.GetSize(),
12361 Utils::Type::vec4.GetSize() /* offset */);
12362
12363 /* Prepare Block */
12364 Utils::Interface* vs_buf_Block = program_interface.Block("vs_buf_Block");
12365
12366 vs_buf_Block->Member("first", "", 0 /* expected_component */, 0 /* expected_location */, Utils::Type::vec4,
12367 false /* normalized */, 0 /* n_array_elements */, vec4_stride, first_offset /* offset */);
12368
12369 vs_buf_Block->Member("second", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12370 0 /* n_array_elements */, data_stride, second_offset);
12371
12372 vs_buf_Block->Member("third", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12373 2 /* n_array_elements */, data_stride, third_offset);
12374
12375 vs_buf_Block->Member("fourth", "", 0 /* expected_component */, 0 /* expected_location */, vec4,
12376 false /* normalized */, 3 /* n_array_elements */, vec4_stride, fourth_offset);
12377
12378 vs_buf_Block->Member("fifth", "layout(align = 16)", 0 /* expected_component */, 0 /* expected_location */, vec4,
12379 false /* normalized */, 2 /* n_array_elements */, vec4_stride, fifth_offset);
12380
12381 vs_buf_Block->Member("sixth", "", 0 /* expected_component */, 0 /* expected_location */, structure,
12382 0 /* n_array_elements */, data_stride, sixth_offset);
12383
12384 const GLuint stride = calculateStride(*vs_buf_Block);
12385 m_data.resize(stride);
12386 generateData(*vs_buf_Block, 0, m_data);
12387
12388 Utils::ShaderInterface& vs_si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12389
12390 /* Add uniform BLOCK */
12391 #if WRKARD_UNIFORMBLOCKALIGNMENT
12392 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING)", 0, 0, vs_buf_Block, 0,
12393 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12394 #else /* WRKARD_UNIFORMBLOCKALIGNMENT */
12395 vs_si.SSB("vs_buf_block", "layout (std140, binding = BINDING, align = 64)", 0, 0, vs_buf_Block, 0,
12396 static_cast<GLuint>(m_data.size()), 0, &m_data[0], m_data.size());
12397 #endif /* WRKARD_UNIFORMBLOCKALIGNMENT */
12398
12399 program_interface.CloneVertexInterface(varying_passthrough);
12400 }
12401
12402 /** Selects if "draw" stages are relevant for test
12403 *
12404 * @param ignored
12405 *
12406 * @return true if all stages support shader storage buffers, false otherwise
12407 **/
12408 bool SSBAlignmentTest::isDrawRelevant(GLuint /* test_case_index */)
12409 {
12410 const Functions& gl = m_context.getRenderContext().getFunctions();
12411 GLint gs_supported_buffers = 0;
12412 GLint tcs_supported_buffers = 0;
12413 GLint tes_supported_buffers = 0;
12414 GLint vs_supported_buffers = 0;
12415
12416 gl.getIntegerv(GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS, &gs_supported_buffers);
12417 gl.getIntegerv(GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS, &tcs_supported_buffers);
12418 gl.getIntegerv(GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS, &tes_supported_buffers);
12419 gl.getIntegerv(GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS, &vs_supported_buffers);
12420
12421 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
12422
12423 return ((1 <= gs_supported_buffers) && (1 <= tcs_supported_buffers) && (1 <= tes_supported_buffers) &&
12424 (1 <= vs_supported_buffers));
12425 }
12426
12427 /** Constructor
12428 *
12429 * @param context Test framework context
12430 **/
12431 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context)
12432 : TextureTestBase(context, "varying_locations", "Test verifies that input and output locations are respected")
12433 {
12434 }
12435
12436 /** Constructor
12437 *
12438 * @param context Test context
12439 * @param test_name Name of test
12440 * @param test_description Description of test
12441 **/
12442 VaryingLocationsTest::VaryingLocationsTest(deqp::Context& context, const glw::GLchar* test_name,
12443 const glw::GLchar* test_description)
12444 : TextureTestBase(context, test_name, test_description)
12445 {
12446 }
12447
12448 /** Get interface of program
12449 *
12450 * @param test_case_index Test case
12451 * @param program_interface Interface of program
12452 * @param varying_passthrough Collection of connections between in and out variables
12453 **/
12454 void VaryingLocationsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
12455 Utils::VaryingPassthrough& varying_passthrough)
12456 {
12457 const Utils::Type type = getType(test_case_index);
12458
12459 m_first_data = type.GenerateDataPacked();
12460 m_last_data = type.GenerateDataPacked();
12461
12462 prepareShaderStage(Utils::Shader::FRAGMENT, type, program_interface, varying_passthrough);
12463 prepareShaderStage(Utils::Shader::GEOMETRY, type, program_interface, varying_passthrough);
12464 prepareShaderStage(Utils::Shader::TESS_CTRL, type, program_interface, varying_passthrough);
12465 prepareShaderStage(Utils::Shader::TESS_EVAL, type, program_interface, varying_passthrough);
12466 prepareShaderStage(Utils::Shader::VERTEX, type, program_interface, varying_passthrough);
12467 }
12468
12469 /** Get type name
12470 *
12471 * @param test_case_index Index of test case
12472 *
12473 * @return Name of type test in test_case_index
12474 **/
12475 std::string VaryingLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12476 {
12477 return getTypeName(test_case_index);
12478 }
12479
12480 /** Returns number of types to test
12481 *
12482 * @return Number of types, 34
12483 **/
12484 glw::GLuint VaryingLocationsTest::getTestCaseNumber()
12485 {
12486 return getTypesNumber();
12487 }
12488
12489 /** Selects if "compute" stage is relevant for test
12490 *
12491 * @param ignored
12492 *
12493 * @return false
12494 **/
12495 bool VaryingLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12496 {
12497 return false;
12498 }
12499
12500 /**
12501 *
12502 *
12503 **/
12504 std::string VaryingLocationsTest::prepareGlobals(GLint last_in_loc, GLint last_out_loc)
12505 {
12506 GLchar buffer[16];
12507 std::string globals = "const uint first_input_location = 0u;\n"
12508 "const uint first_output_location = 0u;\n"
12509 "const uint last_input_location = LAST_INPUTu;\n"
12510 "const uint last_output_location = LAST_OUTPUTu;\n";
12511 size_t position = 100; /* Skip first part */
12512
12513 sprintf(buffer, "%d", last_in_loc);
12514 Utils::replaceToken("LAST_INPUT", position, buffer, globals);
12515
12516 sprintf(buffer, "%d", last_out_loc);
12517 Utils::replaceToken("LAST_OUTPUT", position, buffer, globals);
12518
12519 return globals;
12520 }
12521
12522 /**
12523 *
12524 **/
12525 void VaryingLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12526 Utils::ProgramInterface& program_interface,
12527 Utils::VaryingPassthrough& varying_passthrough)
12528 {
12529 const GLuint array_length = 1;
12530 const GLuint first_in_loc = 0;
12531 const GLuint first_out_loc = 0;
12532 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12533 size_t position = 0;
12534
12535 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12536
12537 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12538
12539 const GLchar* qual_first_in = "layout (location = first_input_location)";
12540 const GLchar* qual_first_out = "layout (location = first_output_location)";
12541 const GLchar* qual_last_in = "layout (location = last_input_location)";
12542 const GLchar* qual_last_out = "layout (location = last_output_location)";
12543
12544 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12545 const GLuint type_size = type.GetSize();
12546
12547 std::string first_in_name = "PREFIXfirst";
12548 std::string first_out_name = "PREFIXfirst";
12549 std::string last_in_name = "PREFIXlast";
12550 std::string last_out_name = "PREFIXlast";
12551
12552 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12553 position = 0;
12554 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12555 position = 0;
12556 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12557 position = 0;
12558 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12559
12560 if (Utils::Shader::FRAGMENT == stage)
12561 {
12562 qual_first_in = "layout (location = first_input_location) flat";
12563 qual_last_in = "layout (location = last_input_location) flat";
12564 }
12565 if (Utils::Shader::GEOMETRY == stage)
12566 {
12567 qual_first_out = "layout (location = first_output_location) flat";
12568 qual_last_out = "layout (location = last_output_location) flat";
12569 }
12570
12571 Utils::Variable* first_in = si.Input(
12572 first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12573 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12574 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12575
12576 Utils::Variable* last_in =
12577 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12578 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12579 0u /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12580 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12581
12582 if (Utils::Shader::FRAGMENT != stage)
12583 {
12584 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12585
12586 Utils::Variable* first_out =
12587 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12588 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12589 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_first_data[0] /* data */,
12590 m_first_data.size() /* data_size */);
12591
12592 Utils::Variable* last_out = si.Output(
12593 last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12594 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */, 0u /* n_array_elements */,
12595 0u /* stride */, 0u /* offset */, (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12596
12597 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12598
12599 varying_passthrough.Add(stage, first_in, first_out);
12600 varying_passthrough.Add(stage, last_in, last_out);
12601 }
12602 else
12603 {
12604 /* No outputs for fragment shader, so last_output_location can be 0 */
12605 si.m_globals = prepareGlobals(last_in_loc, 0);
12606 }
12607 }
12608
12609 /** This test should be run with separable programs
12610 *
12611 * @param ignored
12612 *
12613 * @return true
12614 **/
12615 bool VaryingLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12616 {
12617 return false;
12618 }
12619
12620 /* Constants used by VertexAttribLocationsTest */
12621 const GLuint VertexAttribLocationsTest::m_base_vertex = 4;
12622 const GLuint VertexAttribLocationsTest::m_base_instance = 2;
12623 const GLuint VertexAttribLocationsTest::m_loc_vertex = 2;
12624 const GLuint VertexAttribLocationsTest::m_loc_instance = 5;
12625 const GLuint VertexAttribLocationsTest::m_n_instances = 4;
12626
12627 /** Constructor
12628 *
12629 * @param context Test framework context
12630 **/
12631 VertexAttribLocationsTest::VertexAttribLocationsTest(deqp::Context& context)
12632 : TextureTestBase(context, "vertex_attrib_locations",
12633 "Test verifies that attribute locations are respected by drawing operations")
12634 {
12635 }
12636
12637 /** Execute proper draw command for test case
12638 *
12639 * @param test_case_index Index of test case
12640 **/
12641 void VertexAttribLocationsTest::executeDrawCall(GLuint test_case_index)
12642 {
12643 const Functions& gl = m_context.getRenderContext().getFunctions();
12644
12645 switch (test_case_index)
12646 {
12647 case DRAWARRAYS:
12648 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
12649 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
12650 break;
12651 case DRAWARRAYSINSTANCED:
12652 gl.drawArraysInstanced(GL_PATCHES, 0 /* first */, 1 /* count */, m_n_instances);
12653 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArraysInstanced");
12654 break;
12655 case DRAWELEMENTS:
12656 gl.drawElements(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL);
12657 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElements");
12658 break;
12659 case DRAWELEMENTSBASEVERTEX:
12660 gl.drawElementsBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_base_vertex);
12661 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsBaseVertex");
12662 break;
12663 case DRAWELEMENTSINSTANCED:
12664 gl.drawElementsInstanced(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances);
12665 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstanced");
12666 break;
12667 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12668 gl.drawElementsInstancedBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12669 m_base_instance);
12670 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseInstance");
12671 break;
12672 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12673 gl.drawElementsInstancedBaseVertex(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL, m_n_instances,
12674 m_base_vertex);
12675 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertex");
12676 break;
12677 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12678 gl.drawElementsInstancedBaseVertexBaseInstance(GL_PATCHES, 1 /* count */, GL_UNSIGNED_BYTE, DE_NULL,
12679 m_n_instances, m_base_vertex, m_base_instance);
12680 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawElementsInstancedBaseVertexBaseInstance");
12681 break;
12682 default:
12683 TCU_FAIL("Invalid enum");
12684 }
12685 }
12686
12687 /** Get interface of program
12688 *
12689 * @param ignored
12690 * @param program_interface Interface of program
12691 * @param ignored
12692 **/
12693 void VertexAttribLocationsTest::getProgramInterface(GLuint /* test_case_index */,
12694 Utils::ProgramInterface& program_interface,
12695 Utils::VaryingPassthrough& /* varying_passthrough */)
12696 {
12697 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
12698
12699 /* Globals */
12700 si.m_globals = "const uint vertex_index_location = 2;\n"
12701 "const uint instance_index_location = 5;\n";
12702
12703 /* Attributes */
12704 si.Input("vertex_index" /* name */, "layout (location = vertex_index_location)" /* qualifiers */,
12705 0 /* expected_componenet */, m_loc_vertex /* expected_location */, Utils::Type::uint /* type */,
12706 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 0u /* offset */,
12707 (GLvoid*)0 /* data */, 0 /* data_size */);
12708 si.Input("instance_index" /* name */, "layout (location = instance_index_location)" /* qualifiers */,
12709 0 /* expected_componenet */, m_loc_instance /* expected_location */, Utils::Type::uint /* type */,
12710 GL_FALSE /* normalized */, 0u /* n_array_elements */, 16 /* stride */, 16u /* offset */,
12711 (GLvoid*)0 /* data */, 0 /* data_size */);
12712 }
12713
12714 /** Get name of test case
12715 *
12716 * @param test_case_index Index of test case
12717 *
12718 * @return Name of test case
12719 **/
12720 std::string VertexAttribLocationsTest::getTestCaseName(glw::GLuint test_case_index)
12721 {
12722 std::string result;
12723
12724 switch (test_case_index)
12725 {
12726 case DRAWARRAYS:
12727 result = "DrawArrays";
12728 break;
12729 case DRAWARRAYSINSTANCED:
12730 result = "DrawArraysInstanced";
12731 break;
12732 case DRAWELEMENTS:
12733 result = "DrawElements";
12734 break;
12735 case DRAWELEMENTSBASEVERTEX:
12736 result = "DrawElementsBaseVertex";
12737 break;
12738 case DRAWELEMENTSINSTANCED:
12739 result = "DrawElementsInstanced";
12740 break;
12741 case DRAWELEMENTSINSTANCEDBASEINSTANCE:
12742 result = "DrawElementsInstancedBaseInstance";
12743 break;
12744 case DRAWELEMENTSINSTANCEDBASEVERTEX:
12745 result = "DrawElementsInstancedBaseVertex";
12746 break;
12747 case DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE:
12748 result = "DrawElementsInstancedBaseVertexBaseInstance";
12749 break;
12750 default:
12751 TCU_FAIL("Invalid enum");
12752 }
12753
12754 return result;
12755 }
12756
12757 /** Get number of test cases
12758 *
12759 * @return Number of test cases
12760 **/
12761 GLuint VertexAttribLocationsTest::getTestCaseNumber()
12762 {
12763 return TESTCASES_MAX;
12764 }
12765
12766 /** Prepare code snippet that will verify in and uniform variables
12767 *
12768 * @param ignored
12769 * @param ignored
12770 * @param stage Shader stage
12771 *
12772 * @return Code that verify variables
12773 **/
12774 std::string VertexAttribLocationsTest::getVerificationSnippet(GLuint /* test_case_index */,
12775 Utils::ProgramInterface& /* program_interface */,
12776 Utils::Shader::STAGES stage)
12777 {
12778 std::string verification;
12779
12780 if (Utils::Shader::VERTEX == stage)
12781 {
12782
12783 #if DEBUG_VERTEX_ATTRIB_LOCATIONS_TEST_VARIABLE
12784
12785 verification = "if (gl_InstanceID != instance_index)\n"
12786 " {\n"
12787 " result = 12u;\n"
12788 " }\n"
12789 " else if (gl_VertexID != vertex_index)\n"
12790 " {\n"
12791 " result = 11u;\n"
12792 " }\n";
12793
12794 #else
12795
12796 verification = "if ((gl_VertexID != vertex_index) ||\n"
12797 " (gl_InstanceID != instance_index) )\n"
12798 " {\n"
12799 " result = 0u;\n"
12800 " }\n";
12801
12802 #endif
12803 }
12804 else
12805 {
12806 verification = "";
12807 }
12808
12809 return verification;
12810 }
12811
12812 /** Selects if "compute" stage is relevant for test
12813 *
12814 * @param ignored
12815 *
12816 * @return false
12817 **/
12818 bool VertexAttribLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
12819 {
12820 return false;
12821 }
12822
12823 /** Prepare attributes, vertex array object and array buffer
12824 *
12825 * @param ignored
12826 * @param ignored Interface of program
12827 * @param buffer Array buffer
12828 * @param vao Vertex array object
12829 **/
12830 void VertexAttribLocationsTest::prepareAttributes(GLuint test_case_index /* test_case_index */,
12831 Utils::ProgramInterface& /* program_interface */,
12832 Utils::Buffer& buffer, Utils::VertexArray& vao)
12833 {
12834 static const GLuint vertex_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12835 static const GLuint instance_index_data[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
12836
12837 std::vector<GLuint> buffer_data;
12838 buffer_data.resize(8 + 8); /* vertex_index_data + instance_index_data */
12839
12840 GLubyte* ptr = (GLubyte*)&buffer_data[0];
12841
12842 /*
12843 When case index >=2, the test calls glDrawElement*(), such as glDrawElementsBaseVertex(), glDrawElementsInstanced(), glDrawElementsInstancedBaseInstance() and so on,
12844 So we need to change the buffer type as GL_ELEMENT_ARRAY_BUFFER
12845 */
12846 if (test_case_index >= 2)
12847 {
12848 buffer.m_buffer = Utils::Buffer::Element;
12849 }
12850 vao.Bind();
12851 buffer.Bind();
12852
12853 vao.Attribute(m_loc_vertex /* vertex_index */, Utils::Type::uint, 0 /* array_elements */, false /* normalized */,
12854 0 /* stride */, 0 /* offset */);
12855
12856 vao.Attribute(m_loc_instance /* instance_index */, Utils::Type::uint, 0 /* array_elements */,
12857 false /* normalized */, 0 /* stride */, (GLvoid*)sizeof(vertex_index_data) /* offset */);
12858 // when test_case_index is 5 or 7, the draw call is glDrawElementsInstancedBaseInstance, glDrawElementsInstancedBaseVertexBaseInstance
12859 // the instancecount is 4, the baseinstance is 2, the divisor should be set 2
12860 bool isBaseInstanced = (test_case_index == DRAWELEMENTSINSTANCEDBASEINSTANCE ||
12861 test_case_index == DRAWELEMENTSINSTANCEDBASEVERTEXBASEINSTANCE);
12862 vao.Divisor(m_context.getRenderContext().getFunctions() /* gl */, m_loc_instance /* instance_index */,
12863 isBaseInstanced ? 2 : 1 /* divisor. 1 - advance once per instance */);
12864
12865 memcpy(ptr + 0, vertex_index_data, sizeof(vertex_index_data));
12866 memcpy(ptr + sizeof(vertex_index_data), instance_index_data, sizeof(instance_index_data));
12867
12868 buffer.Data(Utils::Buffer::StaticDraw, buffer_data.size() * sizeof(GLuint), ptr);
12869 }
12870
12871 /** This test should be run with separable programs
12872 *
12873 * @param ignored
12874 *
12875 * @return true
12876 **/
12877 bool VertexAttribLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
12878 {
12879 return false;
12880 }
12881
12882 /** Constructor
12883 *
12884 * @param context Test framework context
12885 **/
12886 VaryingArrayLocationsTest::VaryingArrayLocationsTest(deqp::Context& context)
12887 : VaryingLocationsTest(context, "varying_array_locations",
12888 "Test verifies that input and output locations are respected for arrays")
12889 {
12890 }
12891
12892 /**
12893 *
12894 **/
12895 void VaryingArrayLocationsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& type,
12896 Utils::ProgramInterface& program_interface,
12897 Utils::VaryingPassthrough& varying_passthrough)
12898 {
12899 const GLuint array_length = 1u;
12900 const GLuint first_in_loc = 0;
12901 const GLuint first_out_loc = 0;
12902 const GLuint last_in_loc = getLastInputLocation(stage, type, array_length, false);
12903 size_t position = 0;
12904
12905 const GLchar* prefix_in = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_INPUT);
12906
12907 const GLchar* prefix_out = Utils::ProgramInterface::GetStagePrefix(stage, Utils::Variable::VARYING_OUTPUT);
12908
12909 const GLchar* qual_first_in = "layout (location = first_input_location)";
12910 const GLchar* qual_first_out = "layout (location = first_output_location)";
12911 const GLchar* qual_last_in = "layout (location = last_input_location)";
12912 const GLchar* qual_last_out = "layout (location = last_output_location)";
12913
12914 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
12915 const GLuint type_size = type.GetSize();
12916
12917 std::string first_in_name = "PREFIXfirst";
12918 std::string first_out_name = "PREFIXfirst";
12919 std::string last_in_name = "PREFIXlast";
12920 std::string last_out_name = "PREFIXlast";
12921
12922 Utils::replaceToken("PREFIX", position, prefix_in, first_in_name);
12923 position = 0;
12924 Utils::replaceToken("PREFIX", position, prefix_out, first_out_name);
12925 position = 0;
12926 Utils::replaceToken("PREFIX", position, prefix_in, last_in_name);
12927 position = 0;
12928 Utils::replaceToken("PREFIX", position, prefix_out, last_out_name);
12929
12930 if (Utils::Shader::FRAGMENT == stage)
12931 {
12932 qual_first_in = "layout (location = first_input_location) flat";
12933 qual_last_in = "layout (location = last_input_location) flat";
12934 }
12935 if (Utils::Shader::GEOMETRY == stage)
12936 {
12937 qual_first_out = "layout (location = first_output_location) flat";
12938 qual_last_out = "layout (location = last_output_location) flat";
12939 }
12940
12941 Utils::Variable* first_in =
12942 si.Input(first_in_name.c_str(), qual_first_in /* qualifiers */, 0 /* expected_componenet */,
12943 first_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12944 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12945 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12946
12947 Utils::Variable* last_in =
12948 si.Input(last_in_name.c_str(), qual_last_in /* qualifiers */, 0 /* expected_componenet */,
12949 last_in_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12950 array_length /* n_array_elements */, 0u /* stride */, type_size /* offset */,
12951 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12952
12953 if (Utils::Shader::FRAGMENT != stage)
12954 {
12955 const GLuint last_out_loc = getLastOutputLocation(stage, type, array_length, false);
12956
12957 Utils::Variable* first_out =
12958 si.Output(first_out_name.c_str(), qual_first_out /* qualifiers */, 0 /* expected_componenet */,
12959 first_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12960 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12961 (GLvoid*)&m_first_data[0] /* data */, m_first_data.size() /* data_size */);
12962
12963 Utils::Variable* last_out =
12964 si.Output(last_out_name.c_str(), qual_last_out /* qualifiers */, 0 /* expected_componenet */,
12965 last_out_loc /* expected_location */, type /* type */, GL_FALSE /* normalized */,
12966 array_length /* n_array_elements */, 0u /* stride */, 0u /* offset */,
12967 (GLvoid*)&m_last_data[0] /* data */, m_last_data.size() /* data_size */);
12968
12969 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
12970
12971 varying_passthrough.Add(stage, first_in, first_out);
12972 varying_passthrough.Add(stage, last_in, last_out);
12973 }
12974 else
12975 {
12976 /* No outputs for fragment shader, so last_output_location can be 0 */
12977 si.m_globals = prepareGlobals(last_in_loc, 0);
12978 }
12979 }
12980
12981 /** Constructor
12982 *
12983 * @param context Test framework context
12984 **/
12985 VaryingStructureLocationsTest::VaryingStructureLocationsTest(deqp::Context& context)
12986 : TextureTestBase(context, "varying_structure_locations",
12987 "Test verifies that locations are respected when structures are used as in and out ")
12988 {
12989 }
12990
12991 /** Prepare code snippet that will pass in variables to out variables
12992 *
12993 * @param ignored
12994 * @param varying_passthrough Collection of connections between in and out variables
12995 * @param stage Shader stage
12996 *
12997 * @return Code that pass in variables to next stage
12998 **/
12999 std::string VaryingStructureLocationsTest::getPassSnippet(GLuint /* test_case_index */,
13000 Utils::VaryingPassthrough& varying_passthrough,
13001 Utils::Shader::STAGES stage)
13002 {
13003 std::string result;
13004
13005 if (Utils::Shader::VERTEX != stage)
13006 {
13007 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
13008 }
13009 else
13010 {
13011 result = " vs_tcs_output[0].single = vs_in_single[0];\n"
13012 " vs_tcs_output[0].array[0] = vs_in_array[0];\n";
13013 }
13014
13015 return result;
13016 }
13017
13018 /** Get interface of program
13019 *
13020 * @param test_case_index Test case
13021 * @param program_interface Interface of program
13022 * @param varying_passthrough Collection of connections between in and out variables
13023 **/
13024 void VaryingStructureLocationsTest::getProgramInterface(GLuint test_case_index,
13025 Utils::ProgramInterface& program_interface,
13026 Utils::VaryingPassthrough& varying_passthrough)
13027 {
13028 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
13029 const Utils::Type type = getType(test_case_index);
13030
13031 /* Prepare data */
13032 // We should call GenerateDataPacked() to generate data, which can make sure the data in shader is correct
13033 m_single_data = type.GenerateDataPacked();
13034 m_array_data = type.GenerateDataPacked();
13035
13036 m_data.resize(m_single_data.size() + m_array_data.size());
13037 GLubyte* ptr = (GLubyte*)&m_data[0];
13038 memcpy(ptr, &m_single_data[0], m_single_data.size());
13039 memcpy(ptr + m_single_data.size(), &m_array_data[0], m_array_data.size());
13040
13041 Utils::Interface* structure = program_interface.Structure("Data");
13042
13043 structure->Member("single", "" /* qualifiers */, 0 /* component */, 0 /* location */, type, false /* normalized */,
13044 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */);
13045
13046 // the second struct member 's location should not be 0, it is based on by how many the locations the first struct member consumed.
13047 structure->Member("array", "" /* qualifiers */, 0 /* component */, type.GetLocations() /* location */, type,
13048 false /* normalized */, 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */);
13049
13050 si.Input("vs_in_single", "layout (location = 0)", 0 /* component */, 0 /* location */, type, false /* normalized */,
13051 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_single_data[0] /* data */,
13052 m_single_data.size() /* data_size */);
13053
13054 si.Input("vs_in_array", "layout (location = 8)", 0 /* component */, 8 /* location */, type, false /* normalized */,
13055 1u /* n_array_elements */, 0u /* stride */, type.GetSize() /* offset */,
13056 (GLvoid*)&m_array_data[0] /* data */, m_array_data.size() /* data_size */);
13057
13058 si.Output("vs_tcs_output", "layout (location = 0)", 0 /* component */, 0 /* location */, structure,
13059 1u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
13060 m_data.size() /* data_size */);
13061
13062 program_interface.CloneVertexInterface(varying_passthrough);
13063 }
13064
13065 /** Get type name
13066 *
13067 * @param test_case_index Index of test case
13068 *
13069 * @return Name of type test in test_case_index
13070 **/
13071 std::string VaryingStructureLocationsTest::getTestCaseName(glw::GLuint test_case_index)
13072 {
13073 return getTypeName(test_case_index);
13074 }
13075
13076 /** Returns number of types to test
13077 *
13078 * @return Number of types, 34
13079 **/
13080 glw::GLuint VaryingStructureLocationsTest::getTestCaseNumber()
13081 {
13082 return getTypesNumber();
13083 }
13084
13085 /** Selects if "compute" stage is relevant for test
13086 *
13087 * @param ignored
13088 *
13089 * @return false
13090 **/
13091 bool VaryingStructureLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13092 {
13093 return false;
13094 }
13095
13096 /** This test should be run with separable programs
13097 *
13098 * @param ignored
13099 *
13100 * @return true
13101 **/
13102 bool VaryingStructureLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13103 {
13104 return false;
13105 }
13106
13107 /** Constructor
13108 *
13109 * @param context Test context
13110 * @param test_name Name of test
13111 * @param test_description Description of test
13112 **/
13113 VaryingStructureMemberLocationTest::VaryingStructureMemberLocationTest(deqp::Context& context)
13114 : NegativeTestBase(context, "varying_structure_member_location",
13115 "Test verifies that compiler does not allow location qualifier on member of structure")
13116 {
13117 }
13118
13119 /** Source for given test case and stage
13120 *
13121 * @param test_case_index Index of test case
13122 * @param stage Shader stage
13123 *
13124 * @return Shader source
13125 **/
13126 std::string VaryingStructureMemberLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13127 {
13128 static const GLchar* struct_definition = "struct Data {\n"
13129 " vec4 gohan;\n"
13130 #if DEBUG_NEG_REMOVE_ERROR
13131 " /* layout (location = 4) */ vec4 goten;\n"
13132 #else
13133 " layout (location = 4) vec4 goten;\n"
13134 #endif /* DEBUG_NEG_REMOVE_ERROR */
13135 "};\n";
13136 static const GLchar* input_use = " result += data.gohan + data.goten;\n";
13137 static const GLchar* input_var = "in Data dataARRAY;\n";
13138 static const GLchar* output_var = "out Data dataARRAY;\n";
13139 static const GLchar* output_use = " dataINDEX.gohan = result / 2;\n"
13140 " dataINDEX.goten = result / 4 - dataINDEX.gohan;\n";
13141 static const GLchar* fs = "#version 430 core\n"
13142 "#extension GL_ARB_enhanced_layouts : require\n"
13143 "\n"
13144 "in vec4 gs_fs;\n"
13145 "out vec4 fs_out;\n"
13146 "\n"
13147 "void main()\n"
13148 "{\n"
13149 " fs_out = gs_fs;\n"
13150 "}\n"
13151 "\n";
13152 static const GLchar* fs_tested = "#version 430 core\n"
13153 "#extension GL_ARB_enhanced_layouts : require\n"
13154 "\n"
13155 "STRUCT_DEFINITION"
13156 "\n"
13157 "VARIABLE_DEFINITION"
13158 "\n"
13159 "in vec4 gs_fs;\n"
13160 "out vec4 fs_out;\n"
13161 "\n"
13162 "void main()\n"
13163 "{\n"
13164 " vec4 result = gs_fs;\n"
13165 "\n"
13166 "VARIABLE_USE"
13167 "\n"
13168 " fs_out += result;\n"
13169 "}\n"
13170 "\n";
13171 static const GLchar* gs = "#version 430 core\n"
13172 "#extension GL_ARB_enhanced_layouts : require\n"
13173 "\n"
13174 "layout(points) in;\n"
13175 "layout(triangle_strip, max_vertices = 4) out;\n"
13176 "\n"
13177 "in vec4 tes_gs[];\n"
13178 "out vec4 gs_fs;\n"
13179 "\n"
13180 "void main()\n"
13181 "{\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 " gs_fs = tes_gs[0];\n"
13189 " gl_Position = vec4(1, -1, 0, 1);\n"
13190 " EmitVertex();\n"
13191 " gs_fs = tes_gs[0];\n"
13192 " gl_Position = vec4(1, 1, 0, 1);\n"
13193 " EmitVertex();\n"
13194 "}\n"
13195 "\n";
13196 static const GLchar* gs_tested = "#version 430 core\n"
13197 "#extension GL_ARB_enhanced_layouts : require\n"
13198 "\n"
13199 "layout(points) in;\n"
13200 "layout(triangle_strip, max_vertices = 4) out;\n"
13201 "\n"
13202 "STRUCT_DEFINITION"
13203 "\n"
13204 "VARIABLE_DEFINITION"
13205 "\n"
13206 "in vec4 tes_gs[];\n"
13207 "out vec4 gs_fs;\n"
13208 "\n"
13209 "void main()\n"
13210 "{\n"
13211 " vec4 result = tes_gs[0];\n"
13212 "\n"
13213 "VARIABLE_USE"
13214 "\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 " gs_fs = result;\n"
13222 " gl_Position = vec4(1, -1, 0, 1);\n"
13223 " EmitVertex();\n"
13224 " gs_fs = result;\n"
13225 " gl_Position = vec4(1, 1, 0, 1);\n"
13226 " EmitVertex();\n"
13227 "}\n"
13228 "\n";
13229 static const GLchar* tcs = "#version 430 core\n"
13230 "#extension GL_ARB_enhanced_layouts : require\n"
13231 "\n"
13232 "layout(vertices = 1) out;\n"
13233 "\n"
13234 "in vec4 vs_tcs[];\n"
13235 "out vec4 tcs_tes[];\n"
13236 "\n"
13237 "void main()\n"
13238 "{\n"
13239 "\n"
13240 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13241 "\n"
13242 " gl_TessLevelOuter[0] = 1.0;\n"
13243 " gl_TessLevelOuter[1] = 1.0;\n"
13244 " gl_TessLevelOuter[2] = 1.0;\n"
13245 " gl_TessLevelOuter[3] = 1.0;\n"
13246 " gl_TessLevelInner[0] = 1.0;\n"
13247 " gl_TessLevelInner[1] = 1.0;\n"
13248 "}\n"
13249 "\n";
13250 static const GLchar* tcs_tested = "#version 430 core\n"
13251 "#extension GL_ARB_enhanced_layouts : require\n"
13252 "\n"
13253 "layout(vertices = 1) out;\n"
13254 "\n"
13255 "STRUCT_DEFINITION"
13256 "\n"
13257 "VARIABLE_DEFINITION"
13258 "\n"
13259 "in vec4 vs_tcs[];\n"
13260 "out vec4 tcs_tes[];\n"
13261 "\n"
13262 "void main()\n"
13263 "{\n"
13264 " vec4 result = vs_tcs[gl_InvocationID];\n"
13265 "\n"
13266 "VARIABLE_USE"
13267 "\n"
13268 " tcs_tes[gl_InvocationID] = result;\n"
13269 "\n"
13270 " gl_TessLevelOuter[0] = 1.0;\n"
13271 " gl_TessLevelOuter[1] = 1.0;\n"
13272 " gl_TessLevelOuter[2] = 1.0;\n"
13273 " gl_TessLevelOuter[3] = 1.0;\n"
13274 " gl_TessLevelInner[0] = 1.0;\n"
13275 " gl_TessLevelInner[1] = 1.0;\n"
13276 "}\n"
13277 "\n";
13278 static const GLchar* tes = "#version 430 core\n"
13279 "#extension GL_ARB_enhanced_layouts : require\n"
13280 "\n"
13281 "layout(isolines, point_mode) in;\n"
13282 "\n"
13283 "in vec4 tcs_tes[];\n"
13284 "out vec4 tes_gs;\n"
13285 "\n"
13286 "void main()\n"
13287 "{\n"
13288 " tes_gs = tcs_tes[0];\n"
13289 "}\n"
13290 "\n";
13291 static const GLchar* tes_tested = "#version 430 core\n"
13292 "#extension GL_ARB_enhanced_layouts : require\n"
13293 "\n"
13294 "layout(isolines, point_mode) in;\n"
13295 "\n"
13296 "STRUCT_DEFINITION"
13297 "\n"
13298 "VARIABLE_DEFINITION"
13299 "\n"
13300 "in vec4 tcs_tes[];\n"
13301 "out vec4 tes_gs;\n"
13302 "\n"
13303 "void main()\n"
13304 "{\n"
13305 " vec4 result = tcs_tes[0];\n"
13306 "\n"
13307 "VARIABLE_USE"
13308 "\n"
13309 " tes_gs += result;\n"
13310 "}\n"
13311 "\n";
13312 static const GLchar* vs = "#version 430 core\n"
13313 "#extension GL_ARB_enhanced_layouts : require\n"
13314 "\n"
13315 "in vec4 in_vs;\n"
13316 "out vec4 vs_tcs;\n"
13317 "\n"
13318 "void main()\n"
13319 "{\n"
13320 " vs_tcs = in_vs;\n"
13321 "}\n"
13322 "\n";
13323 static const GLchar* vs_tested = "#version 430 core\n"
13324 "#extension GL_ARB_enhanced_layouts : require\n"
13325 "\n"
13326 "STRUCT_DEFINITION"
13327 "\n"
13328 "VARIABLE_DEFINITION"
13329 "\n"
13330 "in vec4 in_vs;\n"
13331 "out vec4 vs_tcs;\n"
13332 "\n"
13333 "void main()\n"
13334 "{\n"
13335 " vec4 result = in_vs;\n"
13336 "\n"
13337 "VARIABLE_USE"
13338 "\n"
13339 " vs_tcs += result;\n"
13340 "}\n"
13341 "\n";
13342
13343 std::string source;
13344 testCase& test_case = m_test_cases[test_case_index];
13345 const GLchar* var_definition = input_var;
13346 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
13347 const GLchar* array = "";
13348 const GLchar* index = "";
13349
13350 if (!test_case.m_is_input)
13351 {
13352 var_definition = output_var;
13353 var_use = output_use;
13354 }
13355
13356 if (test_case.m_stage == stage)
13357 {
13358 size_t position = 0;
13359 size_t temp = 0;
13360
13361 switch (stage)
13362 {
13363 case Utils::Shader::FRAGMENT:
13364 source = fs_tested;
13365 break;
13366 case Utils::Shader::GEOMETRY:
13367 source = gs_tested;
13368 array = test_case.m_is_input ? "[]" : "";
13369 index = test_case.m_is_input ? "[0]" : "";
13370 break;
13371 case Utils::Shader::TESS_CTRL:
13372 source = tcs_tested;
13373 array = "[]";
13374 index = "[gl_InvocationID]";
13375 break;
13376 case Utils::Shader::TESS_EVAL:
13377 source = tes_tested;
13378 array = test_case.m_is_input ? "[]" : "";
13379 index = test_case.m_is_input ? "[0]" : "";
13380 break;
13381 case Utils::Shader::VERTEX:
13382 source = vs_tested;
13383 break;
13384 default:
13385 TCU_FAIL("Invalid enum");
13386 }
13387
13388 Utils::replaceToken("STRUCT_DEFINITION", position, struct_definition, source);
13389 temp = position;
13390 Utils::replaceToken("VARIABLE_DEFINITION", position, var_definition, source);
13391 position = temp;
13392 Utils::replaceToken("ARRAY", position, array, source);
13393 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13394
13395 Utils::replaceAllTokens("INDEX", index, source);
13396 }
13397 else
13398 {
13399 switch (stage)
13400 {
13401 case Utils::Shader::FRAGMENT:
13402 source = fs;
13403 break;
13404 case Utils::Shader::GEOMETRY:
13405 source = gs;
13406 break;
13407 case Utils::Shader::TESS_CTRL:
13408 source = tcs;
13409 break;
13410 case Utils::Shader::TESS_EVAL:
13411 source = tes;
13412 break;
13413 case Utils::Shader::VERTEX:
13414 source = vs;
13415 break;
13416 default:
13417 TCU_FAIL("Invalid enum");
13418 }
13419 }
13420
13421 return source;
13422 }
13423
13424 /** Get description of test case
13425 *
13426 * @param test_case_index Index of test case
13427 *
13428 * @return Test case description
13429 **/
13430 std::string VaryingStructureMemberLocationTest::getTestCaseName(GLuint test_case_index)
13431 {
13432 std::stringstream stream;
13433 testCase& test_case = m_test_cases[test_case_index];
13434
13435 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13436
13437 if (true == test_case.m_is_input)
13438 {
13439 stream << "input";
13440 }
13441 else
13442 {
13443 stream << "output";
13444 }
13445
13446 return stream.str();
13447 }
13448
13449 /** Get number of test cases
13450 *
13451 * @return Number of test cases
13452 **/
13453 GLuint VaryingStructureMemberLocationTest::getTestCaseNumber()
13454 {
13455 return static_cast<GLuint>(m_test_cases.size());
13456 }
13457
13458 /** Selects if "compute" stage is relevant for test
13459 *
13460 * @param ignored
13461 *
13462 * @return false
13463 **/
13464 bool VaryingStructureMemberLocationTest::isComputeRelevant(GLuint /* test_case_index */)
13465 {
13466 return false;
13467 }
13468
13469 /** Prepare all test cases
13470 *
13471 **/
13472 void VaryingStructureMemberLocationTest::testInit()
13473 {
13474 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13475 {
13476 if (Utils::Shader::COMPUTE == stage)
13477 {
13478 continue;
13479 }
13480
13481 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
13482 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
13483
13484 /* It is a compile-time error to declare a struct as a VS input */
13485 if (Utils::Shader::VERTEX != stage)
13486 {
13487 m_test_cases.push_back(test_case_in);
13488 }
13489
13490 if (Utils::Shader::FRAGMENT != stage)
13491 {
13492 m_test_cases.push_back(test_case_out);
13493 }
13494 }
13495 }
13496
13497 /** Constructor
13498 *
13499 * @param context Test framework context
13500 **/
13501 VaryingBlockLocationsTest::VaryingBlockLocationsTest(deqp::Context& context)
13502 : TextureTestBase(context, "varying_block_locations",
13503 "Test verifies that locations are respected when blocks are used as in and out ")
13504 {
13505 }
13506
13507 /** Prepare code snippet that will pass in variables to out variables
13508 *
13509 * @param ignored
13510 * @param varying_passthrough Collection of connections between in and out variables
13511 * @param stage Shader stage
13512 *
13513 * @return Code that pass in variables to next stage
13514 **/
13515 std::string VaryingBlockLocationsTest::getPassSnippet(GLuint /* test_case_index */,
13516 Utils::VaryingPassthrough& varying_passthrough,
13517 Utils::Shader::STAGES stage)
13518 {
13519 std::string result;
13520
13521 if (Utils::Shader::VERTEX != stage)
13522 {
13523 result = TextureTestBase::getPassSnippet(0, varying_passthrough, stage);
13524 }
13525 else
13526 {
13527 result = "vs_tcs_block.third = vs_in_third;\n"
13528 " vs_tcs_block.fourth = vs_in_fourth;\n"
13529 " vs_tcs_block.fifth = vs_in_fifth;\n";
13530 }
13531
13532 return result;
13533 }
13534
13535 /** Get interface of program
13536 *
13537 * @param ignored
13538 * @param program_interface Interface of program
13539 * @param varying_passthrough Collection of connections between in and out variables
13540 **/
13541 void VaryingBlockLocationsTest::getProgramInterface(GLuint /* test_case_index */,
13542 Utils::ProgramInterface& program_interface,
13543 Utils::VaryingPassthrough& varying_passthrough)
13544 {
13545 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
13546 const Utils::Type vec4 = Utils::Type::vec4;
13547
13548 /* Prepare data */
13549 m_third_data = vec4.GenerateData();
13550 m_fourth_data = vec4.GenerateData();
13551 m_fifth_data = vec4.GenerateData();
13552
13553 /* Memory layout is different from location layout */
13554 const GLuint fifth_offset = 0u;
13555 const GLuint third_offset = static_cast<GLuint>(fifth_offset + m_fifth_data.size());
13556 const GLuint fourth_offset = static_cast<GLuint>(third_offset + m_fourth_data.size());
13557
13558 m_data.resize(fourth_offset + m_fourth_data.size());
13559 GLubyte* ptr = (GLubyte*)&m_data[0];
13560 memcpy(ptr + third_offset, &m_third_data[0], m_third_data.size());
13561 memcpy(ptr + fourth_offset, &m_fourth_data[0], m_fourth_data.size());
13562 memcpy(ptr + fifth_offset, &m_fifth_data[0], m_fifth_data.size());
13563
13564 Utils::Interface* block = program_interface.Block("vs_tcs_Block");
13565
13566 block->Member("fifth", "" /* qualifiers */, 0 /* component */, 4 /* location */, vec4, false /* normalized */,
13567 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */);
13568
13569 block->Member("third", "layout (location = 2)" /* qualifiers */, 0 /* component */, 2 /* location */, vec4,
13570 false /* normalized */, 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */);
13571
13572 block->Member("fourth", "" /* qualifiers */, 0 /* component */, 3 /* location */, vec4, false /* normalized */,
13573 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */);
13574
13575 si.Output("vs_tcs_block", "layout (location = 4)", 0 /* component */, 4 /* location */, block,
13576 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)&m_data[0] /* data */,
13577 m_data.size() /* data_size */);
13578
13579 si.Input("vs_in_third", "layout (location = 0)", 0 /* component */, 0 /* location */, vec4, false /* normalized */,
13580 0u /* n_array_elements */, 0u /* stride */, third_offset /* offset */,
13581 (GLvoid*)&m_third_data[0] /* data */, m_third_data.size() /* data_size */);
13582
13583 si.Input("vs_in_fourth", "layout (location = 1)", 0 /* component */, 1 /* location */, vec4, false /* normalized */,
13584 0u /* n_array_elements */, 0u /* stride */, fourth_offset /* offset */,
13585 (GLvoid*)&m_fourth_data[0] /* data */, m_fourth_data.size() /* data_size */);
13586
13587 si.Input("vs_in_fifth", "layout (location = 2)", 0 /* component */, 2 /* location */, vec4, false /* normalized */,
13588 0u /* n_array_elements */, 0u /* stride */, fifth_offset /* offset */,
13589 (GLvoid*)&m_fifth_data[0] /* data */, m_fifth_data.size() /* data_size */);
13590
13591 program_interface.CloneVertexInterface(varying_passthrough);
13592 }
13593
13594 /** Selects if "compute" stage is relevant for test
13595 *
13596 * @param ignored
13597 *
13598 * @return false
13599 **/
13600 bool VaryingBlockLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13601 {
13602 return false;
13603 }
13604
13605 /** This test should be run with separable programs
13606 *
13607 * @param ignored
13608 *
13609 * @return true
13610 **/
13611 bool VaryingBlockLocationsTest::useMonolithicProgram(GLuint /* test_case_index */)
13612 {
13613 return false;
13614 }
13615
13616 /** Constructor
13617 *
13618 * @param context Test framework context
13619 **/
13620 VaryingBlockMemberLocationsTest::VaryingBlockMemberLocationsTest(deqp::Context& context)
13621 : NegativeTestBase(
13622 context, "varying_block_member_locations",
13623 "Test verifies that compilation error is reported when not all members of block are qualified with location")
13624 {
13625 }
13626
13627 /** Source for given test case and stage
13628 *
13629 * @param test_case_index Index of test case
13630 * @param stage Shader stage
13631 *
13632 * @return Shader source
13633 **/
13634 std::string VaryingBlockMemberLocationsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
13635 {
13636 static const GLchar* block_definition_all = "Goku {\n"
13637 " layout (location = 2) vec4 gohan;\n"
13638 " layout (location = 4) vec4 goten;\n"
13639 " layout (location = 6) vec4 chichi;\n"
13640 "} gokuARRAY;\n";
13641 static const GLchar* block_definition_one = "Goku {\n"
13642 " vec4 gohan;\n"
13643 #if DEBUG_NEG_REMOVE_ERROR
13644 " /* layout (location = 4) */ vec4 goten;\n"
13645 #else
13646 " layout (location = 4) vec4 goten;\n"
13647 #endif /* DEBUG_NEG_REMOVE_ERROR */
13648 " vec4 chichi;\n"
13649 "} gokuARRAY;\n";
13650 static const GLchar* input_use = " result += gokuINDEX.gohan + gokuINDEX.goten + gokuINDEX.chichi;\n";
13651 static const GLchar* output_use = " gokuINDEX.gohan = result / 2;\n"
13652 " gokuINDEX.goten = result / 4 - gokuINDEX.gohan;\n"
13653 " gokuINDEX.chichi = result / 8 - gokuINDEX.goten;\n";
13654 static const GLchar* fs = "#version 430 core\n"
13655 "#extension GL_ARB_enhanced_layouts : require\n"
13656 "\n"
13657 "in vec4 gs_fs;\n"
13658 "out vec4 fs_out;\n"
13659 "\n"
13660 "void main()\n"
13661 "{\n"
13662 " fs_out = gs_fs;\n"
13663 "}\n"
13664 "\n";
13665 static const GLchar* fs_tested = "#version 430 core\n"
13666 "#extension GL_ARB_enhanced_layouts : require\n"
13667 "\n"
13668 "DIRECTION BLOCK_DEFINITION"
13669 "\n"
13670 "in vec4 gs_fs;\n"
13671 "out vec4 fs_out;\n"
13672 "\n"
13673 "void main()\n"
13674 "{\n"
13675 " vec4 result = gs_fs;\n"
13676 "\n"
13677 "VARIABLE_USE"
13678 "\n"
13679 " fs_out = result;\n"
13680 "}\n"
13681 "\n";
13682 static const GLchar* gs = "#version 430 core\n"
13683 "#extension GL_ARB_enhanced_layouts : require\n"
13684 "\n"
13685 "layout(points) in;\n"
13686 "layout(triangle_strip, max_vertices = 4) out;\n"
13687 "\n"
13688 "in vec4 tes_gs[];\n"
13689 "out vec4 gs_fs;\n"
13690 "\n"
13691 "void main()\n"
13692 "{\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 " gs_fs = tes_gs[0];\n"
13700 " gl_Position = vec4(1, -1, 0, 1);\n"
13701 " EmitVertex();\n"
13702 " gs_fs = tes_gs[0];\n"
13703 " gl_Position = vec4(1, 1, 0, 1);\n"
13704 " EmitVertex();\n"
13705 "}\n"
13706 "\n";
13707 static const GLchar* gs_tested = "#version 430 core\n"
13708 "#extension GL_ARB_enhanced_layouts : require\n"
13709 "\n"
13710 "layout(points) in;\n"
13711 "layout(triangle_strip, max_vertices = 4) out;\n"
13712 "\n"
13713 "DIRECTION BLOCK_DEFINITION"
13714 "\n"
13715 "in vec4 tes_gs[];\n"
13716 "out vec4 gs_fs;\n"
13717 "\n"
13718 "void main()\n"
13719 "{\n"
13720 " vec4 result = tes_gs[0];\n"
13721 "\n"
13722 "VARIABLE_USE"
13723 "\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 " gs_fs = result;\n"
13731 " gl_Position = vec4(1, -1, 0, 1);\n"
13732 " EmitVertex();\n"
13733 " gs_fs = result;\n"
13734 " gl_Position = vec4(1, 1, 0, 1);\n"
13735 " EmitVertex();\n"
13736 "}\n"
13737 "\n";
13738 static const GLchar* tcs = "#version 430 core\n"
13739 "#extension GL_ARB_enhanced_layouts : require\n"
13740 "\n"
13741 "layout(vertices = 1) out;\n"
13742 "\n"
13743 "in vec4 vs_tcs[];\n"
13744 "out vec4 tcs_tes[];\n"
13745 "\n"
13746 "void main()\n"
13747 "{\n"
13748 "\n"
13749 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
13750 "\n"
13751 " gl_TessLevelOuter[0] = 1.0;\n"
13752 " gl_TessLevelOuter[1] = 1.0;\n"
13753 " gl_TessLevelOuter[2] = 1.0;\n"
13754 " gl_TessLevelOuter[3] = 1.0;\n"
13755 " gl_TessLevelInner[0] = 1.0;\n"
13756 " gl_TessLevelInner[1] = 1.0;\n"
13757 "}\n"
13758 "\n";
13759 static const GLchar* tcs_tested = "#version 430 core\n"
13760 "#extension GL_ARB_enhanced_layouts : require\n"
13761 "\n"
13762 "layout(vertices = 1) out;\n"
13763 "\n"
13764 "DIRECTION BLOCK_DEFINITION"
13765 "\n"
13766 "in vec4 vs_tcs[];\n"
13767 "out vec4 tcs_tes[];\n"
13768 "\n"
13769 "void main()\n"
13770 "{\n"
13771 " vec4 result = vs_tcs[gl_InvocationID];\n"
13772 "\n"
13773 "VARIABLE_USE"
13774 "\n"
13775 " tcs_tes[gl_InvocationID] = result;\n"
13776 "\n"
13777 " gl_TessLevelOuter[0] = 1.0;\n"
13778 " gl_TessLevelOuter[1] = 1.0;\n"
13779 " gl_TessLevelOuter[2] = 1.0;\n"
13780 " gl_TessLevelOuter[3] = 1.0;\n"
13781 " gl_TessLevelInner[0] = 1.0;\n"
13782 " gl_TessLevelInner[1] = 1.0;\n"
13783 "}\n"
13784 "\n";
13785 static const GLchar* tes = "#version 430 core\n"
13786 "#extension GL_ARB_enhanced_layouts : require\n"
13787 "\n"
13788 "layout(isolines, point_mode) in;\n"
13789 "\n"
13790 "in vec4 tcs_tes[];\n"
13791 "out vec4 tes_gs;\n"
13792 "\n"
13793 "void main()\n"
13794 "{\n"
13795 " tes_gs = tcs_tes[0];\n"
13796 "}\n"
13797 "\n";
13798 static const GLchar* tes_tested = "#version 430 core\n"
13799 "#extension GL_ARB_enhanced_layouts : require\n"
13800 "\n"
13801 "layout(isolines, point_mode) in;\n"
13802 "\n"
13803 "DIRECTION BLOCK_DEFINITION"
13804 "\n"
13805 "in vec4 tcs_tes[];\n"
13806 "out vec4 tes_gs;\n"
13807 "\n"
13808 "void main()\n"
13809 "{\n"
13810 " vec4 result = tcs_tes[0];\n"
13811 "\n"
13812 "VARIABLE_USE"
13813 "\n"
13814 " tes_gs = result;\n"
13815 "}\n"
13816 "\n";
13817 static const GLchar* vs = "#version 430 core\n"
13818 "#extension GL_ARB_enhanced_layouts : require\n"
13819 "\n"
13820 "in vec4 in_vs;\n"
13821 "out vec4 vs_tcs;\n"
13822 "\n"
13823 "void main()\n"
13824 "{\n"
13825 " vs_tcs = in_vs;\n"
13826 "}\n"
13827 "\n";
13828 static const GLchar* vs_tested = "#version 430 core\n"
13829 "#extension GL_ARB_enhanced_layouts : require\n"
13830 "\n"
13831 "DIRECTION BLOCK_DEFINITION"
13832 "\n"
13833 "in vec4 in_vs;\n"
13834 "out vec4 vs_tcs;\n"
13835 "\n"
13836 "void main()\n"
13837 "{\n"
13838 " vec4 result = in_vs;\n"
13839 "\n"
13840 "VARIABLE_USE"
13841 "\n"
13842 " vs_tcs = result;\n"
13843 "}\n"
13844 "\n";
13845
13846 const GLchar* array = "";
13847 const GLchar* direction = "in";
13848 const GLchar* index = "";
13849 std::string source;
13850 testCase& test_case = m_test_cases[test_case_index];
13851 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
13852 const GLchar* definition = test_case.m_qualify_all ? block_definition_all : block_definition_one;
13853
13854 if (!test_case.m_is_input)
13855 {
13856 direction = "out";
13857 var_use = output_use;
13858 }
13859
13860 if (test_case.m_stage == stage)
13861 {
13862 size_t position = 0;
13863 size_t temp = 0;
13864
13865 switch (stage)
13866 {
13867 case Utils::Shader::FRAGMENT:
13868 source = fs_tested;
13869 break;
13870 case Utils::Shader::GEOMETRY:
13871 source = gs_tested;
13872 array = test_case.m_is_input ? "[]" : "";
13873 index = test_case.m_is_input ? "[0]" : "";
13874 break;
13875 case Utils::Shader::TESS_CTRL:
13876 source = tcs_tested;
13877 array = "[]";
13878 index = "[gl_InvocationID]";
13879 break;
13880 case Utils::Shader::TESS_EVAL:
13881 source = tes_tested;
13882 array = test_case.m_is_input ? "[]" : "";
13883 index = test_case.m_is_input ? "[0]" : "";
13884 break;
13885 case Utils::Shader::VERTEX:
13886 source = vs_tested;
13887 break;
13888 default:
13889 TCU_FAIL("Invalid enum");
13890 }
13891
13892 Utils::replaceToken("DIRECTION", position, direction, source);
13893 temp = position;
13894 Utils::replaceToken("BLOCK_DEFINITION", position, definition, source);
13895 position = temp;
13896 Utils::replaceToken("ARRAY", position, array, source);
13897 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
13898
13899 Utils::replaceAllTokens("INDEX", index, source);
13900 }
13901 else
13902 {
13903 switch (stage)
13904 {
13905 case Utils::Shader::FRAGMENT:
13906 source = fs;
13907 break;
13908 case Utils::Shader::GEOMETRY:
13909 source = gs;
13910 break;
13911 case Utils::Shader::TESS_CTRL:
13912 source = tcs;
13913 break;
13914 case Utils::Shader::TESS_EVAL:
13915 source = tes;
13916 break;
13917 case Utils::Shader::VERTEX:
13918 source = vs;
13919 break;
13920 default:
13921 TCU_FAIL("Invalid enum");
13922 }
13923 }
13924
13925 return source;
13926 }
13927
13928 /** Get description of test case
13929 *
13930 * @param test_case_index Index of test case
13931 *
13932 * @return Test case description
13933 **/
13934 std::string VaryingBlockMemberLocationsTest::getTestCaseName(GLuint test_case_index)
13935 {
13936 std::stringstream stream;
13937 testCase& test_case = m_test_cases[test_case_index];
13938
13939 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
13940
13941 if (true == test_case.m_is_input)
13942 {
13943 stream << "input";
13944 }
13945 else
13946 {
13947 stream << "output";
13948 }
13949
13950 if (true == test_case.m_qualify_all)
13951 {
13952 stream << ", all members qualified";
13953 }
13954 else
13955 {
13956 stream << ", not all members qualified";
13957 }
13958
13959 return stream.str();
13960 }
13961
13962 /** Get number of test cases
13963 *
13964 * @return Number of test cases
13965 **/
13966 GLuint VaryingBlockMemberLocationsTest::getTestCaseNumber()
13967 {
13968 return static_cast<GLuint>(m_test_cases.size());
13969 }
13970
13971 /** Selects if "compute" stage is relevant for test
13972 *
13973 * @param ignored
13974 *
13975 * @return false
13976 **/
13977 bool VaryingBlockMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
13978 {
13979 return false;
13980 }
13981
13982 /** Selects if compilation failure is expected result
13983 *
13984 * @param test_case_index Index of test case
13985 *
13986 * @return false when all members are qualified, true otherwise
13987 **/
13988 bool VaryingBlockMemberLocationsTest::isFailureExpected(GLuint test_case_index)
13989 {
13990 return (true != m_test_cases[test_case_index].m_qualify_all);
13991 }
13992
13993 /** Prepare all test cases
13994 *
13995 **/
13996 void VaryingBlockMemberLocationsTest::testInit()
13997 {
13998 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
13999 {
14000 if (Utils::Shader::COMPUTE == stage)
14001 {
14002 continue;
14003 }
14004
14005 testCase test_case_in_all = { true, true, (Utils::Shader::STAGES)stage };
14006 testCase test_case_in_one = { true, false, (Utils::Shader::STAGES)stage };
14007 testCase test_case_out_all = { false, true, (Utils::Shader::STAGES)stage };
14008 testCase test_case_out_one = { false, false, (Utils::Shader::STAGES)stage };
14009
14010 if (Utils::Shader::VERTEX != stage)
14011 {
14012 m_test_cases.push_back(test_case_in_all);
14013 m_test_cases.push_back(test_case_in_one);
14014 }
14015
14016 if (Utils::Shader::FRAGMENT != stage)
14017 {
14018 m_test_cases.push_back(test_case_out_all);
14019 m_test_cases.push_back(test_case_out_one);
14020 }
14021 }
14022 }
14023
14024 /** Constructor
14025 *
14026 * @param context Test framework context
14027 **/
14028 VaryingBlockAutomaticMemberLocationsTest::VaryingBlockAutomaticMemberLocationsTest(deqp::Context& context)
14029 : NegativeTestBase(
14030 context, "varying_block_automatic_member_locations",
14031 "Test verifies that compiler assigns subsequent locations to block members, even if this causes errors")
14032 {
14033 }
14034
14035 /** Source for given test case and stage
14036 *
14037 * @param test_case_index Index of test case
14038 * @param stage Shader stage
14039 *
14040 * @return Shader source
14041 **/
14042 std::string VaryingBlockAutomaticMemberLocationsTest::getShaderSource(GLuint test_case_index,
14043 Utils::Shader::STAGES stage)
14044 {
14045 static const GLchar* block_definition = "layout (location = 2) DIRECTION DBZ {\n"
14046 " vec4 goku;\n"
14047 " vec4 gohan[4];\n"
14048 " vec4 goten;\n"
14049 #if DEBUG_NEG_REMOVE_ERROR
14050 " /* layout (location = 1) */ vec4 chichi;\n"
14051 #else
14052 " layout (location = 1) vec4 chichi;\n"
14053 #endif /* DEBUG_NEG_REMOVE_ERROR */
14054 " vec4 pan;\n"
14055 "} dbzARRAY;\n";
14056 static const GLchar* input_use = " result += dbzINDEX.goku + dbzINDEX.gohan[0] + dbzINDEX.gohan[1] + "
14057 "dbzINDEX.gohan[3] + dbzINDEX.gohan[2] + dbzINDEX.goten + dbzINDEX.chichi + "
14058 "dbzINDEX.pan;\n";
14059 static const GLchar* output_use = " dbzINDEX.goku = result;\n"
14060 " dbzINDEX.gohan[0] = result / 2;\n"
14061 " dbzINDEX.gohan[1] = result / 2.25;\n"
14062 " dbzINDEX.gohan[2] = result / 2.5;\n"
14063 " dbzINDEX.gohan[3] = result / 2.75;\n"
14064 " dbzINDEX.goten = result / 4 - dbzINDEX.gohan[0] - dbzINDEX.gohan[1] - "
14065 "dbzINDEX.gohan[2] - dbzINDEX.gohan[3];\n"
14066 " dbzINDEX.chichi = result / 8 - dbzINDEX.goten;\n"
14067 " dbzINDEX.pan = result / 16 - dbzINDEX.chichi;\n";
14068 static const GLchar* fs = "#version 430 core\n"
14069 "#extension GL_ARB_enhanced_layouts : require\n"
14070 "\n"
14071 "in vec4 gs_fs;\n"
14072 "out vec4 fs_out;\n"
14073 "\n"
14074 "void main()\n"
14075 "{\n"
14076 " fs_out = gs_fs;\n"
14077 "}\n"
14078 "\n";
14079 static const GLchar* fs_tested = "#version 430 core\n"
14080 "#extension GL_ARB_enhanced_layouts : require\n"
14081 "\n"
14082 "BLOCK_DEFINITION"
14083 "\n"
14084 "in vec4 gs_fs;\n"
14085 "out vec4 fs_out;\n"
14086 "\n"
14087 "void main()\n"
14088 "{\n"
14089 " vec4 result = gs_fs;\n"
14090 "\n"
14091 "VARIABLE_USE"
14092 "\n"
14093 " fs_out += result;\n"
14094 "}\n"
14095 "\n";
14096 static const GLchar* gs = "#version 430 core\n"
14097 "#extension GL_ARB_enhanced_layouts : require\n"
14098 "\n"
14099 "layout(points) in;\n"
14100 "layout(triangle_strip, max_vertices = 4) out;\n"
14101 "\n"
14102 "in vec4 tes_gs[];\n"
14103 "out vec4 gs_fs;\n"
14104 "\n"
14105 "void main()\n"
14106 "{\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 " gs_fs = tes_gs[0];\n"
14114 " gl_Position = vec4(1, -1, 0, 1);\n"
14115 " EmitVertex();\n"
14116 " gs_fs = tes_gs[0];\n"
14117 " gl_Position = vec4(1, 1, 0, 1);\n"
14118 " EmitVertex();\n"
14119 "}\n"
14120 "\n";
14121 static const GLchar* gs_tested = "#version 430 core\n"
14122 "#extension GL_ARB_enhanced_layouts : require\n"
14123 "\n"
14124 "layout(points) in;\n"
14125 "layout(triangle_strip, max_vertices = 4) out;\n"
14126 "\n"
14127 "BLOCK_DEFINITION"
14128 "\n"
14129 "in vec4 tes_gs[];\n"
14130 "out vec4 gs_fs;\n"
14131 "\n"
14132 "void main()\n"
14133 "{\n"
14134 " vec4 result = tes_gs[0];\n"
14135 "\n"
14136 "VARIABLE_USE"
14137 "\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 " gs_fs = result;\n"
14145 " gl_Position = vec4(1, -1, 0, 1);\n"
14146 " EmitVertex();\n"
14147 " gs_fs = result;\n"
14148 " gl_Position = vec4(1, 1, 0, 1);\n"
14149 " EmitVertex();\n"
14150 "}\n"
14151 "\n";
14152 static const GLchar* tcs = "#version 430 core\n"
14153 "#extension GL_ARB_enhanced_layouts : require\n"
14154 "\n"
14155 "layout(vertices = 1) out;\n"
14156 "\n"
14157 "in vec4 vs_tcs[];\n"
14158 "out vec4 tcs_tes[];\n"
14159 "\n"
14160 "void main()\n"
14161 "{\n"
14162 "\n"
14163 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14164 "\n"
14165 " gl_TessLevelOuter[0] = 1.0;\n"
14166 " gl_TessLevelOuter[1] = 1.0;\n"
14167 " gl_TessLevelOuter[2] = 1.0;\n"
14168 " gl_TessLevelOuter[3] = 1.0;\n"
14169 " gl_TessLevelInner[0] = 1.0;\n"
14170 " gl_TessLevelInner[1] = 1.0;\n"
14171 "}\n"
14172 "\n";
14173 static const GLchar* tcs_tested = "#version 430 core\n"
14174 "#extension GL_ARB_enhanced_layouts : require\n"
14175 "\n"
14176 "layout(vertices = 1) out;\n"
14177 "\n"
14178 "BLOCK_DEFINITION"
14179 "\n"
14180 "in vec4 vs_tcs[];\n"
14181 "out vec4 tcs_tes[];\n"
14182 "\n"
14183 "void main()\n"
14184 "{\n"
14185 " vec4 result = vs_tcs[gl_InvocationID];\n"
14186 "\n"
14187 "VARIABLE_USE"
14188 "\n"
14189 " tcs_tes[gl_InvocationID] = result;\n"
14190 "\n"
14191 " gl_TessLevelOuter[0] = 1.0;\n"
14192 " gl_TessLevelOuter[1] = 1.0;\n"
14193 " gl_TessLevelOuter[2] = 1.0;\n"
14194 " gl_TessLevelOuter[3] = 1.0;\n"
14195 " gl_TessLevelInner[0] = 1.0;\n"
14196 " gl_TessLevelInner[1] = 1.0;\n"
14197 "}\n"
14198 "\n";
14199 static const GLchar* tes = "#version 430 core\n"
14200 "#extension GL_ARB_enhanced_layouts : require\n"
14201 "\n"
14202 "layout(isolines, point_mode) in;\n"
14203 "\n"
14204 "in vec4 tcs_tes[];\n"
14205 "out vec4 tes_gs;\n"
14206 "\n"
14207 "void main()\n"
14208 "{\n"
14209 " tes_gs = tcs_tes[0];\n"
14210 "}\n"
14211 "\n";
14212 static const GLchar* tes_tested = "#version 430 core\n"
14213 "#extension GL_ARB_enhanced_layouts : require\n"
14214 "\n"
14215 "layout(isolines, point_mode) in;\n"
14216 "\n"
14217 "BLOCK_DEFINITION"
14218 "\n"
14219 "in vec4 tcs_tes[];\n"
14220 "out vec4 tes_gs;\n"
14221 "\n"
14222 "void main()\n"
14223 "{\n"
14224 " vec4 result = tcs_tes[0];\n"
14225 "\n"
14226 "VARIABLE_USE"
14227 "\n"
14228 " tes_gs += result;\n"
14229 "}\n"
14230 "\n";
14231 static const GLchar* vs = "#version 430 core\n"
14232 "#extension GL_ARB_enhanced_layouts : require\n"
14233 "\n"
14234 "in vec4 in_vs;\n"
14235 "out vec4 vs_tcs;\n"
14236 "\n"
14237 "void main()\n"
14238 "{\n"
14239 " vs_tcs = in_vs;\n"
14240 "}\n"
14241 "\n";
14242 static const GLchar* vs_tested = "#version 430 core\n"
14243 "#extension GL_ARB_enhanced_layouts : require\n"
14244 "\n"
14245 "BLOCK_DEFINITION"
14246 "\n"
14247 "in vec4 in_vs;\n"
14248 "out vec4 vs_tcs;\n"
14249 "\n"
14250 "void main()\n"
14251 "{\n"
14252 " vec4 result = in_vs;\n"
14253 "\n"
14254 "VARIABLE_USE"
14255 "\n"
14256 " vs_tcs += result;\n"
14257 "}\n"
14258 "\n";
14259
14260 const GLchar* array = "";
14261 const GLchar* direction = "in";
14262 const GLchar* index = "";
14263 std::string source;
14264 testCase& test_case = m_test_cases[test_case_index];
14265 const GLchar* var_use = Utils::Shader::VERTEX == test_case.m_stage ? input_use : "\n";
14266
14267 if (!test_case.m_is_input)
14268 {
14269 direction = "out";
14270 var_use = output_use;
14271 }
14272
14273 if (test_case.m_stage == stage)
14274 {
14275 size_t position = 0;
14276
14277 switch (stage)
14278 {
14279 case Utils::Shader::FRAGMENT:
14280 source = fs_tested;
14281 break;
14282 case Utils::Shader::GEOMETRY:
14283 source = gs_tested;
14284 array = test_case.m_is_input ? "[]" : "";
14285 index = test_case.m_is_input ? "[0]" : "";
14286 break;
14287 case Utils::Shader::TESS_CTRL:
14288 source = tcs_tested;
14289 array = "[]";
14290 index = "[gl_InvocationID]";
14291 break;
14292 case Utils::Shader::TESS_EVAL:
14293 source = tes_tested;
14294 array = test_case.m_is_input ? "[]" : "";
14295 index = test_case.m_is_input ? "[0]" : "";
14296 break;
14297 case Utils::Shader::VERTEX:
14298 source = vs_tested;
14299 break;
14300 default:
14301 TCU_FAIL("Invalid enum");
14302 }
14303
14304 Utils::replaceToken("BLOCK_DEFINITION", position, block_definition, source);
14305 position = 0;
14306 Utils::replaceToken("DIRECTION", position, direction, source);
14307 Utils::replaceToken("ARRAY", position, array, source);
14308 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14309
14310 Utils::replaceAllTokens("INDEX", index, source);
14311 }
14312 else
14313 {
14314 switch (stage)
14315 {
14316 case Utils::Shader::FRAGMENT:
14317 source = fs;
14318 break;
14319 case Utils::Shader::GEOMETRY:
14320 source = gs;
14321 break;
14322 case Utils::Shader::TESS_CTRL:
14323 source = tcs;
14324 break;
14325 case Utils::Shader::TESS_EVAL:
14326 source = tes;
14327 break;
14328 case Utils::Shader::VERTEX:
14329 source = vs;
14330 break;
14331 default:
14332 TCU_FAIL("Invalid enum");
14333 }
14334 }
14335
14336 return source;
14337 }
14338
14339 /** Get description of test case
14340 *
14341 * @param test_case_index Index of test case
14342 *
14343 * @return Test case description
14344 **/
14345 std::string VaryingBlockAutomaticMemberLocationsTest::getTestCaseName(GLuint test_case_index)
14346 {
14347 std::stringstream stream;
14348 testCase& test_case = m_test_cases[test_case_index];
14349
14350 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", direction: ";
14351
14352 if (true == test_case.m_is_input)
14353 {
14354 stream << "input";
14355 }
14356 else
14357 {
14358 stream << "output";
14359 }
14360
14361 return stream.str();
14362 }
14363
14364 /** Get number of test cases
14365 *
14366 * @return Number of test cases
14367 **/
14368 GLuint VaryingBlockAutomaticMemberLocationsTest::getTestCaseNumber()
14369 {
14370 return static_cast<GLuint>(m_test_cases.size());
14371 }
14372
14373 /** Selects if "compute" stage is relevant for test
14374 *
14375 * @param ignored
14376 *
14377 * @return false
14378 **/
14379 bool VaryingBlockAutomaticMemberLocationsTest::isComputeRelevant(GLuint /* test_case_index */)
14380 {
14381 return false;
14382 }
14383
14384 /** Prepare all test cases
14385 *
14386 **/
14387 void VaryingBlockAutomaticMemberLocationsTest::testInit()
14388 {
14389 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14390 {
14391 if (Utils::Shader::COMPUTE == stage)
14392 {
14393 continue;
14394 }
14395
14396 testCase test_case_in = { true, (Utils::Shader::STAGES)stage };
14397 testCase test_case_out = { false, (Utils::Shader::STAGES)stage };
14398
14399 if (Utils::Shader::VERTEX != stage)
14400 {
14401 m_test_cases.push_back(test_case_in);
14402 }
14403
14404 if (Utils::Shader::FRAGMENT != stage)
14405 {
14406 m_test_cases.push_back(test_case_out);
14407 }
14408 }
14409 }
14410
14411 /** Constructor
14412 *
14413 * @param context Test framework context
14414 **/
14415 VaryingLocationLimitTest::VaryingLocationLimitTest(deqp::Context& context)
14416 : NegativeTestBase(context, "varying_location_limit",
14417 "Test verifies that compiler reports error when location qualifier exceeds limits")
14418 {
14419 }
14420
14421 /** Source for given test case and stage
14422 *
14423 * @param test_case_index Index of test case
14424 * @param stage Shader stage
14425 *
14426 * @return Shader source
14427 **/
14428 std::string VaryingLocationLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
14429 {
14430 #if DEBUG_NEG_REMOVE_ERROR
14431 static const GLchar* var_definition = "layout (location = LAST /* + 1 */) FLAT DIRECTION TYPE gokuARRAY;\n";
14432 #else
14433 static const GLchar* var_definition = "layout (location = LAST + 1) FLAT DIRECTION TYPE gokuARRAY;\n";
14434 #endif /* DEBUG_NEG_REMOVE_ERROR */
14435 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
14436 " {\n"
14437 " result += vec4(1, 0.5, 0.25, 0.125);\n"
14438 " }\n";
14439 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
14440 " if (vec4(0) == result)\n"
14441 " {\n"
14442 " gokuINDEX = TYPE(1);\n"
14443 " }\n";
14444 static const GLchar* fs = "#version 430 core\n"
14445 "#extension GL_ARB_enhanced_layouts : require\n"
14446 "\n"
14447 "in vec4 gs_fs;\n"
14448 "out vec4 fs_out;\n"
14449 "\n"
14450 "void main()\n"
14451 "{\n"
14452 " fs_out = gs_fs;\n"
14453 "}\n"
14454 "\n";
14455 static const GLchar* fs_tested = "#version 430 core\n"
14456 "#extension GL_ARB_enhanced_layouts : require\n"
14457 "\n"
14458 "VAR_DEFINITION"
14459 "\n"
14460 "in vec4 gs_fs;\n"
14461 "out vec4 fs_out;\n"
14462 "\n"
14463 "void main()\n"
14464 "{\n"
14465 " vec4 result = gs_fs;\n"
14466 "\n"
14467 "VARIABLE_USE"
14468 "\n"
14469 " fs_out += result;\n"
14470 "}\n"
14471 "\n";
14472 static const GLchar* gs = "#version 430 core\n"
14473 "#extension GL_ARB_enhanced_layouts : require\n"
14474 "\n"
14475 "layout(points) in;\n"
14476 "layout(triangle_strip, max_vertices = 4) out;\n"
14477 "\n"
14478 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
14479 "in vec4 tes_gs[];\n"
14480 "out vec4 gs_fs;\n"
14481 "\n"
14482 "void main()\n"
14483 "{\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 " gs_fs = tes_gs[0];\n"
14491 " gl_Position = vec4(1, -1, 0, 1);\n"
14492 " EmitVertex();\n"
14493 " gs_fs = tes_gs[0];\n"
14494 " gl_Position = vec4(1, 1, 0, 1);\n"
14495 " EmitVertex();\n"
14496 "}\n"
14497 "\n";
14498 static const GLchar* gs_tested = "#version 430 core\n"
14499 "#extension GL_ARB_enhanced_layouts : require\n"
14500 "\n"
14501 "layout(points) in;\n"
14502 "layout(triangle_strip, max_vertices = 4) out;\n"
14503 "\n"
14504 "PERVERTEX" /* Separable programs require explicit declaration of gl_PerVertex */
14505 "VAR_DEFINITION"
14506 "\n"
14507 "in vec4 tes_gs[];\n"
14508 "out vec4 gs_fs;\n"
14509 "\n"
14510 "void main()\n"
14511 "{\n"
14512 " vec4 result = tes_gs[0];\n"
14513 "\n"
14514 "VARIABLE_USE"
14515 "\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 " gs_fs = result;\n"
14523 " gl_Position = vec4(1, -1, 0, 1);\n"
14524 " EmitVertex();\n"
14525 " gs_fs = result;\n"
14526 " gl_Position = vec4(1, 1, 0, 1);\n"
14527 " EmitVertex();\n"
14528 "}\n"
14529 "\n";
14530 static const GLchar* tcs = "#version 430 core\n"
14531 "#extension GL_ARB_enhanced_layouts : require\n"
14532 "\n"
14533 "layout(vertices = 1) out;\n"
14534 "\n"
14535 "in vec4 vs_tcs[];\n"
14536 "out vec4 tcs_tes[];\n"
14537 "\n"
14538 "void main()\n"
14539 "{\n"
14540 "\n"
14541 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
14542 "\n"
14543 " gl_TessLevelOuter[0] = 1.0;\n"
14544 " gl_TessLevelOuter[1] = 1.0;\n"
14545 " gl_TessLevelOuter[2] = 1.0;\n"
14546 " gl_TessLevelOuter[3] = 1.0;\n"
14547 " gl_TessLevelInner[0] = 1.0;\n"
14548 " gl_TessLevelInner[1] = 1.0;\n"
14549 "}\n"
14550 "\n";
14551 static const GLchar* tcs_tested = "#version 430 core\n"
14552 "#extension GL_ARB_enhanced_layouts : require\n"
14553 "\n"
14554 "layout(vertices = 1) out;\n"
14555 "\n"
14556 "VAR_DEFINITION"
14557 "\n"
14558 "in vec4 vs_tcs[];\n"
14559 "out vec4 tcs_tes[];\n"
14560 "\n"
14561 "void main()\n"
14562 "{\n"
14563 " vec4 result = vs_tcs[gl_InvocationID];\n"
14564 "\n"
14565 "VARIABLE_USE"
14566 "\n"
14567 " tcs_tes[gl_InvocationID] = result;\n"
14568 "\n"
14569 " gl_TessLevelOuter[0] = 1.0;\n"
14570 " gl_TessLevelOuter[1] = 1.0;\n"
14571 " gl_TessLevelOuter[2] = 1.0;\n"
14572 " gl_TessLevelOuter[3] = 1.0;\n"
14573 " gl_TessLevelInner[0] = 1.0;\n"
14574 " gl_TessLevelInner[1] = 1.0;\n"
14575 "}\n"
14576 "\n";
14577 static const GLchar* tes = "#version 430 core\n"
14578 "#extension GL_ARB_enhanced_layouts : require\n"
14579 "\n"
14580 "layout(isolines, point_mode) in;\n"
14581 "\n"
14582 "in vec4 tcs_tes[];\n"
14583 "out vec4 tes_gs;\n"
14584 "\n"
14585 "void main()\n"
14586 "{\n"
14587 " tes_gs = tcs_tes[0];\n"
14588 "}\n"
14589 "\n";
14590 static const GLchar* tes_tested = "#version 430 core\n"
14591 "#extension GL_ARB_enhanced_layouts : require\n"
14592 "\n"
14593 "layout(isolines, point_mode) in;\n"
14594 "\n"
14595 "VAR_DEFINITION"
14596 "\n"
14597 "in vec4 tcs_tes[];\n"
14598 "out vec4 tes_gs;\n"
14599 "\n"
14600 "void main()\n"
14601 "{\n"
14602 " vec4 result = tcs_tes[0];\n"
14603 "\n"
14604 "VARIABLE_USE"
14605 "\n"
14606 " tes_gs += result;\n"
14607 "}\n"
14608 "\n";
14609 static const GLchar* vs = "#version 430 core\n"
14610 "#extension GL_ARB_enhanced_layouts : require\n"
14611 "\n"
14612 "in vec4 in_vs;\n"
14613 "out vec4 vs_tcs;\n"
14614 "\n"
14615 "void main()\n"
14616 "{\n"
14617 " vs_tcs = in_vs;\n"
14618 "}\n"
14619 "\n";
14620 static const GLchar* vs_tested = "#version 430 core\n"
14621 "#extension GL_ARB_enhanced_layouts : require\n"
14622 "\n"
14623 "VAR_DEFINITION"
14624 "\n"
14625 "in vec4 in_vs;\n"
14626 "out vec4 vs_tcs;\n"
14627 "\n"
14628 "void main()\n"
14629 "{\n"
14630 " vec4 result = in_vs;\n"
14631 "\n"
14632 "VARIABLE_USE"
14633 "\n"
14634 " vs_tcs += result;\n"
14635 "}\n"
14636 "\n";
14637
14638 std::string source;
14639 testCase& test_case = m_test_cases[test_case_index];
14640 size_t position = 0;
14641 const GLchar* per_vertex = !isSeparable(test_case_index) ? "" : "out gl_PerVertex {\n"
14642 "vec4 gl_Position;\n"
14643 "};\n"
14644 "\n";
14645
14646 if (test_case.m_stage == stage)
14647 {
14648 const GLchar* array = "";
14649 GLchar buffer[16];
14650 const GLchar* direction = "in ";
14651 const GLchar* flat = "";
14652 const GLchar* index = "";
14653 GLuint last = getLastInputLocation(stage, test_case.m_type, 0, true);
14654 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
14655 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
14656 const GLchar* var_use = input_use;
14657
14658 if (false == test_case.m_is_input)
14659 {
14660 direction = "out";
14661 last = getLastOutputLocation(stage, test_case.m_type, 0, true);
14662 storage = Utils::Variable::VARYING_OUTPUT;
14663 var_use = output_use;
14664 }
14665
14666 if (isFlatRequired(stage, test_case.m_type, storage))
14667 {
14668 flat = "flat";
14669 }
14670
14671 sprintf(buffer, "%d", last);
14672
14673 switch (stage)
14674 {
14675 case Utils::Shader::FRAGMENT:
14676 source = fs_tested;
14677 break;
14678 case Utils::Shader::GEOMETRY:
14679 source = gs_tested;
14680 array = test_case.m_is_input ? "[]" : "";
14681 index = test_case.m_is_input ? "[0]" : "";
14682 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
14683 break;
14684 case Utils::Shader::TESS_CTRL:
14685 source = tcs_tested;
14686 array = "[]";
14687 index = "[gl_InvocationID]";
14688 break;
14689 case Utils::Shader::TESS_EVAL:
14690 source = tes_tested;
14691 array = test_case.m_is_input ? "[]" : "";
14692 index = test_case.m_is_input ? "[0]" : "";
14693 break;
14694 case Utils::Shader::VERTEX:
14695 source = vs_tested;
14696 break;
14697 default:
14698 TCU_FAIL("Invalid enum");
14699 }
14700
14701 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
14702 position = 0;
14703 Utils::replaceToken("LAST", position, buffer, source);
14704 Utils::replaceToken("FLAT", position, flat, source);
14705 Utils::replaceToken("DIRECTION", position, direction, source);
14706 Utils::replaceToken("ARRAY", position, array, source);
14707 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
14708
14709 Utils::replaceAllTokens("TYPE", type_name, source);
14710 Utils::replaceAllTokens("INDEX", index, source);
14711 }
14712 else
14713 {
14714 switch (stage)
14715 {
14716 case Utils::Shader::FRAGMENT:
14717 source = fs;
14718 break;
14719 case Utils::Shader::GEOMETRY:
14720 source = gs;
14721 Utils::replaceToken("PERVERTEX", position, per_vertex, source);
14722 break;
14723 case Utils::Shader::TESS_CTRL:
14724 source = tcs;
14725 break;
14726 case Utils::Shader::TESS_EVAL:
14727 source = tes;
14728 break;
14729 case Utils::Shader::VERTEX:
14730 source = vs;
14731 break;
14732 default:
14733 TCU_FAIL("Invalid enum");
14734 }
14735 }
14736
14737 return source;
14738 }
14739
14740 /** Get description of test case
14741 *
14742 * @param test_case_index Index of test case
14743 *
14744 * @return Test case description
14745 **/
14746 std::string VaryingLocationLimitTest::getTestCaseName(GLuint test_case_index)
14747 {
14748 std::stringstream stream;
14749 testCase& test_case = m_test_cases[test_case_index];
14750
14751 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
14752 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
14753
14754 if (true == test_case.m_is_input)
14755 {
14756 stream << "input";
14757 }
14758 else
14759 {
14760 stream << "output";
14761 }
14762
14763 return stream.str();
14764 }
14765
14766 /** Get number of test cases
14767 *
14768 * @return Number of test cases
14769 **/
14770 GLuint VaryingLocationLimitTest::getTestCaseNumber()
14771 {
14772 return static_cast<GLuint>(m_test_cases.size());
14773 }
14774
14775 /** Selects if "compute" stage is relevant for test
14776 *
14777 * @param ignored
14778 *
14779 * @return false
14780 **/
14781 bool VaryingLocationLimitTest::isComputeRelevant(GLuint /* test_case_index */)
14782 {
14783 return false;
14784 }
14785
14786 /** Selects if the test case should use a separable program
14787 *
14788 * @param test_case_index Id of test case
14789 *
14790 * @return whether the test should use separable programs or not
14791 **/
14792 bool VaryingLocationLimitTest::isSeparable(const GLuint test_case_index)
14793 {
14794 const testCase& test_case = m_test_cases[test_case_index];
14795
14796 return test_case.m_is_input && test_case.m_stage != Utils::Shader::VERTEX;
14797 }
14798
14799 /** Prepare all test cases
14800 *
14801 **/
14802 void VaryingLocationLimitTest::testInit()
14803 {
14804 const GLuint n_types = getTypesNumber();
14805
14806 for (GLuint i = 0; i < n_types; ++i)
14807 {
14808 const Utils::Type& type = getType(i);
14809
14810 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
14811 {
14812 if (Utils::Shader::COMPUTE == stage)
14813 {
14814 continue;
14815 }
14816
14817 testCase test_case_in = { true, type, (Utils::Shader::STAGES)stage };
14818 testCase test_case_out = { false, type, (Utils::Shader::STAGES)stage };
14819
14820 m_test_cases.push_back(test_case_in);
14821
14822 if (Utils::Shader::FRAGMENT != stage)
14823 {
14824 m_test_cases.push_back(test_case_out);
14825 }
14826 }
14827 }
14828 }
14829
14830 /** Constructor
14831 *
14832 * @param context Test framework context
14833 **/
14834 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context)
14835 : VaryingLocationsTest(context, "varying_components",
14836 "Test verifies that input and output components are respected")
14837 {
14838 }
14839
14840 /** Constructor
14841 *
14842 * @param context Test framework context
14843 * @param test_name Name of test
14844 * @param test_description Description of test
14845 **/
14846 VaryingComponentsTest::VaryingComponentsTest(deqp::Context& context, const glw::GLchar* test_name,
14847 const glw::GLchar* test_description)
14848 : VaryingLocationsTest(context, test_name, test_description)
14849 {
14850 }
14851
14852 /** Get interface of program
14853 *
14854 * @param test_case_index Test case
14855 * @param program_interface Interface of program
14856 * @param varying_passthrough Collection of connections between in and out variables
14857 **/
14858 void VaryingComponentsTest::getProgramInterface(GLuint test_case_index, Utils::ProgramInterface& program_interface,
14859 Utils::VaryingPassthrough& varying_passthrough)
14860 {
14861 GLuint array_length = getArrayLength();
14862 const testCase& test_case = m_test_cases[test_case_index];
14863 const Utils::Type vector_type = Utils::Type::GetType(test_case.m_type, 1, 4);
14864 Utils::ShaderInterface si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
14865
14866 /* Zero means no array, however we still need at least 1 slot of data */
14867 if (0 == array_length)
14868 {
14869 array_length += 1;
14870 }
14871
14872 /* Generate data */
14873 const std::vector<GLubyte>& data = vector_type.GenerateDataPacked();
14874 const size_t data_size = data.size();
14875
14876 /* Prepare data for variables */
14877 m_data.resize(array_length * data_size);
14878
14879 GLubyte* dst = &m_data[0];
14880 const GLubyte* src = &data[0];
14881
14882 for (GLuint i = 0; i < array_length; ++i)
14883 {
14884 memcpy(dst + data_size * i, src, data_size);
14885 }
14886
14887 /* Prepare interface for each stage */
14888 prepareShaderStage(Utils::Shader::FRAGMENT, vector_type, program_interface, test_case, varying_passthrough);
14889 prepareShaderStage(Utils::Shader::GEOMETRY, vector_type, program_interface, test_case, varying_passthrough);
14890 prepareShaderStage(Utils::Shader::TESS_CTRL, vector_type, program_interface, test_case, varying_passthrough);
14891 prepareShaderStage(Utils::Shader::TESS_EVAL, vector_type, program_interface, test_case, varying_passthrough);
14892 prepareShaderStage(Utils::Shader::VERTEX, vector_type, program_interface, test_case, varying_passthrough);
14893 }
14894
14895 /** Get type name
14896 *
14897 * @param test_case_index Index of test case
14898 *
14899 * @return Name of type test in test_case_index
14900 **/
14901 std::string VaryingComponentsTest::getTestCaseName(glw::GLuint test_case_index)
14902 {
14903 std::string name;
14904
14905 const testCase& test_case = m_test_cases[test_case_index];
14906
14907 name = "Type: ";
14908
14909 switch (test_case.m_type)
14910 {
14911 case Utils::Type::Double:
14912 name.append(Utils::Type::_double.GetGLSLTypeName());
14913 break;
14914 case Utils::Type::Float:
14915 name.append(Utils::Type::_float.GetGLSLTypeName());
14916 break;
14917 case Utils::Type::Int:
14918 name.append(Utils::Type::_int.GetGLSLTypeName());
14919 break;
14920 case Utils::Type::Uint:
14921 name.append(Utils::Type::uint.GetGLSLTypeName());
14922 break;
14923 }
14924
14925 name.append(", layout: ");
14926
14927 switch (test_case.m_layout)
14928 {
14929 case G64VEC2:
14930 name.append("G64VEC2");
14931 break;
14932 case G64SCALAR_G64SCALAR:
14933 name.append("G64SCALAR_G64SCALAR");
14934 break;
14935 case GVEC4:
14936 name.append("GVEC4");
14937 break;
14938 case SCALAR_GVEC3:
14939 name.append("SCALAR_GVEC3");
14940 break;
14941 case GVEC3_SCALAR:
14942 name.append("GVEC3_SCALAR");
14943 break;
14944 case GVEC2_GVEC2:
14945 name.append("GVEC2_GVEC2");
14946 break;
14947 case GVEC2_SCALAR_SCALAR:
14948 name.append("GVEC2_SCALAR_SCALAR");
14949 break;
14950 case SCALAR_GVEC2_SCALAR:
14951 name.append("SCALAR_GVEC2_SCALAR");
14952 break;
14953 case SCALAR_SCALAR_GVEC2:
14954 name.append("SCALAR_SCALAR_GVEC2");
14955 break;
14956 case SCALAR_SCALAR_SCALAR_SCALAR:
14957 name.append("SCALAR_SCALAR_SCALAR_SCALAR");
14958 break;
14959 }
14960
14961 return name;
14962 }
14963
14964 /** Returns number of types to test
14965 *
14966 * @return Number of types
14967 **/
14968 glw::GLuint VaryingComponentsTest::getTestCaseNumber()
14969 {
14970 return static_cast<GLuint>(m_test_cases.size());
14971 }
14972
14973 /* Prepare test cases */
14974 void VaryingComponentsTest::testInit()
14975 {
14976 m_test_cases.push_back(testCase(G64VEC2, Utils::Type::Double));
14977 m_test_cases.push_back(testCase(G64SCALAR_G64SCALAR, Utils::Type::Double));
14978
14979 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Float));
14980 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Float));
14981 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Float));
14982 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Float));
14983 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Float));
14984 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Float));
14985 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Float));
14986 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Float));
14987
14988 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Int));
14989 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Int));
14990 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Int));
14991 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Int));
14992 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Int));
14993 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Int));
14994 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Int));
14995 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Int));
14996
14997 m_test_cases.push_back(testCase(GVEC4, Utils::Type::Uint));
14998 m_test_cases.push_back(testCase(SCALAR_GVEC3, Utils::Type::Uint));
14999 m_test_cases.push_back(testCase(GVEC3_SCALAR, Utils::Type::Uint));
15000 m_test_cases.push_back(testCase(GVEC2_GVEC2, Utils::Type::Uint));
15001 m_test_cases.push_back(testCase(GVEC2_SCALAR_SCALAR, Utils::Type::Uint));
15002 m_test_cases.push_back(testCase(SCALAR_GVEC2_SCALAR, Utils::Type::Uint));
15003 m_test_cases.push_back(testCase(SCALAR_SCALAR_GVEC2, Utils::Type::Uint));
15004 m_test_cases.push_back(testCase(SCALAR_SCALAR_SCALAR_SCALAR, Utils::Type::Uint));
15005 }
15006
15007 /** Inform that test use components
15008 *
15009 * @param ignored
15010 *
15011 * @return true
15012 **/
15013 bool VaryingComponentsTest::useComponentQualifier(glw::GLuint /* test_case_index */)
15014 {
15015 return true;
15016 }
15017
15018 /** Get length of arrays that should be used during test
15019 *
15020 * @return 0u - no array at all
15021 **/
15022 GLuint VaryingComponentsTest::getArrayLength()
15023 {
15024 return 0;
15025 }
15026
15027 std::string VaryingComponentsTest::prepareGlobals(GLuint last_in_location, GLuint last_out_location)
15028 {
15029 std::string globals = VaryingLocationsTest::prepareGlobals(last_in_location, last_out_location);
15030
15031 globals.append("const uint comp_x = 0u;\n"
15032 "const uint comp_y = 1u;\n"
15033 "const uint comp_z = 2u;\n"
15034 "const uint comp_w = 3u;\n");
15035
15036 return globals;
15037 }
15038
15039 /**
15040 *
15041 **/
15042 std::string VaryingComponentsTest::prepareName(const glw::GLchar* name, glw::GLint location, glw::GLint component,
15043 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
15044 {
15045 GLchar buffer[16];
15046 std::string result = "PREFIXNAME_lLOCATION_cCOMPONENT";
15047 size_t position = 0;
15048 const GLchar* prefix = Utils::ProgramInterface::GetStagePrefix(stage, storage);
15049
15050 Utils::replaceToken("PREFIX", position, prefix, result);
15051 Utils::replaceToken("NAME", position, name, result);
15052
15053 sprintf(buffer, "%d", location);
15054 Utils::replaceToken("LOCATION", position, buffer, result);
15055
15056 sprintf(buffer, "%d", component);
15057 Utils::replaceToken("COMPONENT", position, buffer, result);
15058
15059 return result;
15060 }
15061
15062 std::string VaryingComponentsTest::prepareQualifiers(const glw::GLchar* location, const glw::GLchar* component,
15063 const glw::GLchar* interpolation)
15064 {
15065 size_t position = 0;
15066 std::string qualifiers = "layout (location = LOCATION, component = COMPONENT) INTERPOLATION";
15067
15068 Utils::replaceToken("LOCATION", position, location, qualifiers);
15069 Utils::replaceToken("COMPONENT", position, component, qualifiers);
15070 Utils::replaceToken("INTERPOLATION", position, interpolation, qualifiers);
15071
15072 return qualifiers;
15073 }
15074
15075 /**
15076 *
15077 **/
15078 void VaryingComponentsTest::prepareShaderStage(Utils::Shader::STAGES stage, const Utils::Type& vector_type,
15079 Utils::ProgramInterface& program_interface, const testCase& test_case,
15080 Utils::VaryingPassthrough& varying_passthrough)
15081 {
15082 const GLuint array_length = getArrayLength();
15083 const Utils::Type& basic_type = Utils::Type::GetType(vector_type.m_basic_type, 1 /* n_cols */, 1 /* n_rows */);
15084 descriptor desc_in[8];
15085 descriptor desc_out[8];
15086 const GLuint first_in_loc = 0;
15087 const GLuint first_out_loc = 0;
15088 const GLchar* interpolation = "";
15089 const GLuint last_in_loc = getLastInputLocation(stage, vector_type, array_length, false);
15090 GLuint last_out_loc = 0;
15091 GLuint n_desc = 0;
15092 Utils::ShaderInterface& si = program_interface.GetShaderInterface(stage);
15093
15094 /* Select interpolation */
15095 if ((Utils::Shader::FRAGMENT == stage) || (Utils::Shader::GEOMETRY == stage))
15096 {
15097 interpolation = " flat";
15098 }
15099
15100 if (Utils::Shader::FRAGMENT != stage)
15101 {
15102 last_out_loc = getLastOutputLocation(stage, vector_type, array_length, false);
15103 }
15104
15105 switch (test_case.m_layout)
15106 {
15107 case G64VEC2:
15108 n_desc = 2;
15109 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "g64vec2");
15110 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "g64vec2");
15111
15112 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "g64vec2");
15113 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "g64vec2");
15114 break;
15115
15116 case G64SCALAR_G64SCALAR:
15117 n_desc = 4;
15118 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "g64scalar");
15119 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "g64scalar");
15120 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "g64scalar");
15121 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "g64scalar");
15122
15123 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "g64scalar");
15124 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "g64scalar");
15125 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "g64scalar");
15126 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "g64scalar");
15127 break;
15128 case GVEC4:
15129 n_desc = 2;
15130 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 4, "gvec4");
15131 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 4, "gvec4");
15132
15133 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 4, "gvec4");
15134 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 4, "gvec4");
15135 break;
15136 case SCALAR_GVEC3:
15137 n_desc = 4;
15138 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15139 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15140 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 3, "gvec3");
15141 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 3, "gvec3");
15142
15143 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15144 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15145 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 3, "gvec3");
15146 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 3, "gvec3");
15147 break;
15148 case GVEC3_SCALAR:
15149 n_desc = 4;
15150 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 3, "gvec3");
15151 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 3, "gvec3");
15152 desc_in[2].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15153 desc_in[3].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15154
15155 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 3, "gvec3");
15156 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 3, "gvec3");
15157 desc_out[2].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15158 desc_out[3].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15159 break;
15160 case GVEC2_GVEC2:
15161 n_desc = 4;
15162 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15163 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15164 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15165 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15166
15167 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15168 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15169 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15170 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15171 break;
15172 case GVEC2_SCALAR_SCALAR:
15173 n_desc = 6;
15174 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 2, "gvec2");
15175 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 2, "gvec2");
15176 desc_in[2].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15177 desc_in[3].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15178 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15179 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15180
15181 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 2, "gvec2");
15182 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 2, "gvec2");
15183 desc_out[2].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15184 desc_out[3].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15185 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15186 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15187 break;
15188 case SCALAR_GVEC2_SCALAR:
15189 n_desc = 6;
15190 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15191 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15192 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 2, "gvec2");
15193 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 2, "gvec2");
15194 desc_in[4].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15195 desc_in[5].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15196
15197 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15198 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15199 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 2, "gvec2");
15200 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 2, "gvec2");
15201 desc_out[4].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15202 desc_out[5].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15203 break;
15204 case SCALAR_SCALAR_GVEC2:
15205 n_desc = 6;
15206 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15207 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15208 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15209 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15210 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 2, "gvec2");
15211 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 2, "gvec2");
15212
15213 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15214 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15215 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15216 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15217 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 2, "gvec2");
15218 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 2, "gvec2");
15219 break;
15220 case SCALAR_SCALAR_SCALAR_SCALAR:
15221 n_desc = 8;
15222 desc_in[0].assign(0, "comp_x", first_in_loc, "first_input_location", 1, "scalar");
15223 desc_in[1].assign(0, "comp_x", last_in_loc, "last_input_location", 1, "scalar");
15224 desc_in[2].assign(1, "comp_y", first_in_loc, "first_input_location", 1, "scalar");
15225 desc_in[3].assign(1, "comp_y", last_in_loc, "last_input_location", 1, "scalar");
15226 desc_in[4].assign(2, "comp_z", first_in_loc, "first_input_location", 1, "scalar");
15227 desc_in[5].assign(2, "comp_z", last_in_loc, "last_input_location", 1, "scalar");
15228 desc_in[6].assign(3, "comp_w", first_in_loc, "first_input_location", 1, "scalar");
15229 desc_in[7].assign(3, "comp_w", last_in_loc, "last_input_location", 1, "scalar");
15230
15231 desc_out[0].assign(0, "comp_x", first_out_loc, "first_output_location", 1, "scalar");
15232 desc_out[1].assign(0, "comp_x", last_out_loc, "last_output_location", 1, "scalar");
15233 desc_out[2].assign(1, "comp_y", first_out_loc, "first_output_location", 1, "scalar");
15234 desc_out[3].assign(1, "comp_y", last_out_loc, "last_output_location", 1, "scalar");
15235 desc_out[4].assign(2, "comp_z", first_out_loc, "first_output_location", 1, "scalar");
15236 desc_out[5].assign(2, "comp_z", last_out_loc, "last_output_location", 1, "scalar");
15237 desc_out[6].assign(3, "comp_w", first_out_loc, "first_output_location", 1, "scalar");
15238 desc_out[7].assign(3, "comp_w", last_out_loc, "last_output_location", 1, "scalar");
15239 break;
15240 }
15241
15242 for (GLuint i = 0; i < n_desc; ++i)
15243 {
15244 const descriptor& in_desc = desc_in[i];
15245
15246 Utils::Variable* in =
15247 prepareVarying(basic_type, in_desc, interpolation, si, stage, Utils::Variable::VARYING_INPUT);
15248
15249 if (Utils::Shader::FRAGMENT != stage)
15250 {
15251 const descriptor& out_desc = desc_out[i];
15252
15253 Utils::Variable* out =
15254 prepareVarying(basic_type, out_desc, interpolation, si, stage, Utils::Variable::VARYING_OUTPUT);
15255
15256 varying_passthrough.Add(stage, in, out);
15257 }
15258 }
15259
15260 si.m_globals = prepareGlobals(last_in_loc, last_out_loc);
15261 }
15262
15263 /**
15264 *
15265 **/
15266 Utils::Variable* VaryingComponentsTest::prepareVarying(const Utils::Type& basic_type, const descriptor& desc,
15267 const GLchar* interpolation, Utils::ShaderInterface& si,
15268 Utils::Shader::STAGES stage, Utils::Variable::STORAGE storage)
15269 {
15270 const GLuint array_length = getArrayLength();
15271 const GLuint component_size = Utils::Type::_float.GetSize();
15272 const std::string& name = prepareName(desc.m_name, desc.m_location, desc.m_component, stage, storage);
15273 const GLuint offset = desc.m_component * component_size;
15274 const std::string& qual = prepareQualifiers(desc.m_location_str, desc.m_component_str, interpolation);
15275 const GLuint size = desc.m_n_rows * basic_type.GetSize();
15276 const Utils::Type& type = Utils::Type::GetType(basic_type.m_basic_type, 1 /* n_columns */, desc.m_n_rows);
15277 Utils::Variable* var = 0;
15278
15279 if (Utils::Variable::VARYING_INPUT == storage)
15280 {
15281 var = si.Input(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15282 desc.m_location /* expected_location */, type, /* built_in_type */
15283 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15284 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15285 }
15286 else
15287 {
15288 var = si.Output(name.c_str(), qual.c_str() /* qualifiers */, desc.m_component /* expected_componenet */,
15289 desc.m_location /* expected_location */, type, /* built_in_type */
15290 GL_FALSE /* normalized */, array_length /* n_array_elements */, 0u /* stride */,
15291 offset /* offset */, (GLvoid*)&m_data[offset] /* data */, size /* data_size */);
15292 }
15293
15294 return var;
15295 }
15296
15297 void VaryingComponentsTest::descriptor::assign(glw::GLint component, const glw::GLchar* component_str,
15298 glw::GLint location, const glw::GLchar* location_str, glw::GLuint n_rows,
15299 const glw::GLchar* name)
15300 {
15301 m_component = component;
15302 m_component_str = component_str;
15303 m_location = location;
15304 m_location_str = location_str;
15305 m_n_rows = n_rows;
15306 m_name = name;
15307 }
15308
15309 VaryingComponentsTest::testCase::testCase(COMPONENTS_LAYOUT layout, Utils::Type::TYPES type)
15310 : m_layout(layout), m_type(type)
15311 {
15312 }
15313
15314 /** Constructor
15315 *
15316 * @param context Test framework context
15317 **/
15318 VaryingArrayComponentsTest::VaryingArrayComponentsTest(deqp::Context& context)
15319 : VaryingComponentsTest(context, "varying_array_components",
15320 "Test verifies that input and output components are respected for arrays")
15321 {
15322 }
15323
15324 /** Get length of arrays that should be used during test
15325 *
15326 * @return 4u
15327 **/
15328 GLuint VaryingArrayComponentsTest::getArrayLength()
15329 {
15330 return 4u;
15331 }
15332
15333 /** Constructor
15334 *
15335 * @param context Test framework context
15336 **/
15337 VaryingInvalidValueComponentTest::VaryingInvalidValueComponentTest(deqp::Context& context)
15338 : NegativeTestBase(context, "varying_invalid_value_component", "Test verifies that compiler reports error when "
15339 "using an invalid value in the component "
15340 "qualification for a specific type")
15341 {
15342 }
15343
15344 /** Source for given test case and stage
15345 *
15346 * @param test_case_index Index of test case
15347 * @param stage Shader stage
15348 *
15349 * @return Shader source
15350 **/
15351 std::string VaryingInvalidValueComponentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15352 {
15353 #if DEBUG_NEG_REMOVE_ERROR
15354 static const GLchar* var_definition_arr =
15355 "layout (location = 1 /*, component = COMPONENT */) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15356 static const GLchar* var_definition_one =
15357 "layout (location = 1 /*, component = COMPONENT */) FLAT DIRECTION TYPE gokuARRAY;\n";
15358 #else
15359 static const GLchar* var_definition_arr =
15360 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15361 static const GLchar* var_definition_one =
15362 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
15363 #endif /* DEBUG_NEG_REMOVE_ERROR */
15364 static const GLchar* input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
15365 " {\n"
15366 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15367 " }\n";
15368 static const GLchar* input_use_one = " if (TYPE(0) == gokuINDEX)\n"
15369 " {\n"
15370 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15371 " }\n";
15372 static const GLchar* output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
15373 " if (vec4(0) == result)\n"
15374 " {\n"
15375 " gokuINDEX[0] = TYPE(1);\n"
15376 " }\n";
15377 static const GLchar* output_use_one = " gokuINDEX = TYPE(0);\n"
15378 " if (vec4(0) == result)\n"
15379 " {\n"
15380 " gokuINDEX = TYPE(1);\n"
15381 " }\n";
15382 static const GLchar* fs = "#version 430 core\n"
15383 "#extension GL_ARB_enhanced_layouts : require\n"
15384 "\n"
15385 "in vec4 gs_fs;\n"
15386 "out vec4 fs_out;\n"
15387 "\n"
15388 "void main()\n"
15389 "{\n"
15390 " fs_out = gs_fs;\n"
15391 "}\n"
15392 "\n";
15393 static const GLchar* fs_tested = "#version 430 core\n"
15394 "#extension GL_ARB_enhanced_layouts : require\n"
15395 "\n"
15396 "VAR_DEFINITION"
15397 "\n"
15398 "in vec4 gs_fs;\n"
15399 "out vec4 fs_out;\n"
15400 "\n"
15401 "void main()\n"
15402 "{\n"
15403 " vec4 result = gs_fs;\n"
15404 "\n"
15405 "VARIABLE_USE"
15406 "\n"
15407 " fs_out += result;\n"
15408 "}\n"
15409 "\n";
15410 static const GLchar* gs = "#version 430 core\n"
15411 "#extension GL_ARB_enhanced_layouts : require\n"
15412 "\n"
15413 "layout(points) in;\n"
15414 "layout(triangle_strip, max_vertices = 4) out;\n"
15415 "\n"
15416 "in vec4 tes_gs[];\n"
15417 "out vec4 gs_fs;\n"
15418 "\n"
15419 "void main()\n"
15420 "{\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 " gs_fs = tes_gs[0];\n"
15428 " gl_Position = vec4(1, -1, 0, 1);\n"
15429 " EmitVertex();\n"
15430 " gs_fs = tes_gs[0];\n"
15431 " gl_Position = vec4(1, 1, 0, 1);\n"
15432 " EmitVertex();\n"
15433 "}\n"
15434 "\n";
15435 static const GLchar* gs_tested = "#version 430 core\n"
15436 "#extension GL_ARB_enhanced_layouts : require\n"
15437 "\n"
15438 "layout(points) in;\n"
15439 "layout(triangle_strip, max_vertices = 4) out;\n"
15440 "\n"
15441 "VAR_DEFINITION"
15442 "\n"
15443 "in vec4 tes_gs[];\n"
15444 "out vec4 gs_fs;\n"
15445 "\n"
15446 "void main()\n"
15447 "{\n"
15448 " vec4 result = tes_gs[0];\n"
15449 "\n"
15450 "VARIABLE_USE"
15451 "\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 " gs_fs = result;\n"
15459 " gl_Position = vec4(1, -1, 0, 1);\n"
15460 " EmitVertex();\n"
15461 " gs_fs = result;\n"
15462 " gl_Position = vec4(1, 1, 0, 1);\n"
15463 " EmitVertex();\n"
15464 "}\n"
15465 "\n";
15466 static const GLchar* tcs = "#version 430 core\n"
15467 "#extension GL_ARB_enhanced_layouts : require\n"
15468 "\n"
15469 "layout(vertices = 1) out;\n"
15470 "\n"
15471 "in vec4 vs_tcs[];\n"
15472 "out vec4 tcs_tes[];\n"
15473 "\n"
15474 "void main()\n"
15475 "{\n"
15476 "\n"
15477 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15478 "\n"
15479 " gl_TessLevelOuter[0] = 1.0;\n"
15480 " gl_TessLevelOuter[1] = 1.0;\n"
15481 " gl_TessLevelOuter[2] = 1.0;\n"
15482 " gl_TessLevelOuter[3] = 1.0;\n"
15483 " gl_TessLevelInner[0] = 1.0;\n"
15484 " gl_TessLevelInner[1] = 1.0;\n"
15485 "}\n"
15486 "\n";
15487 static const GLchar* tcs_tested = "#version 430 core\n"
15488 "#extension GL_ARB_enhanced_layouts : require\n"
15489 "\n"
15490 "layout(vertices = 1) out;\n"
15491 "\n"
15492 "VAR_DEFINITION"
15493 "\n"
15494 "in vec4 vs_tcs[];\n"
15495 "out vec4 tcs_tes[];\n"
15496 "\n"
15497 "void main()\n"
15498 "{\n"
15499 " vec4 result = vs_tcs[gl_InvocationID];\n"
15500 "\n"
15501 "VARIABLE_USE"
15502 "\n"
15503 " tcs_tes[gl_InvocationID] = result;\n"
15504 "\n"
15505 " gl_TessLevelOuter[0] = 1.0;\n"
15506 " gl_TessLevelOuter[1] = 1.0;\n"
15507 " gl_TessLevelOuter[2] = 1.0;\n"
15508 " gl_TessLevelOuter[3] = 1.0;\n"
15509 " gl_TessLevelInner[0] = 1.0;\n"
15510 " gl_TessLevelInner[1] = 1.0;\n"
15511 "}\n"
15512 "\n";
15513 static const GLchar* tes = "#version 430 core\n"
15514 "#extension GL_ARB_enhanced_layouts : require\n"
15515 "\n"
15516 "layout(isolines, point_mode) in;\n"
15517 "\n"
15518 "in vec4 tcs_tes[];\n"
15519 "out vec4 tes_gs;\n"
15520 "\n"
15521 "void main()\n"
15522 "{\n"
15523 " tes_gs = tcs_tes[0];\n"
15524 "}\n"
15525 "\n";
15526 static const GLchar* tes_tested = "#version 430 core\n"
15527 "#extension GL_ARB_enhanced_layouts : require\n"
15528 "\n"
15529 "layout(isolines, point_mode) in;\n"
15530 "\n"
15531 "VAR_DEFINITION"
15532 "\n"
15533 "in vec4 tcs_tes[];\n"
15534 "out vec4 tes_gs;\n"
15535 "\n"
15536 "void main()\n"
15537 "{\n"
15538 " vec4 result = tcs_tes[0];\n"
15539 "\n"
15540 "VARIABLE_USE"
15541 "\n"
15542 " tes_gs += result;\n"
15543 "}\n"
15544 "\n";
15545 static const GLchar* vs = "#version 430 core\n"
15546 "#extension GL_ARB_enhanced_layouts : require\n"
15547 "\n"
15548 "in vec4 in_vs;\n"
15549 "out vec4 vs_tcs;\n"
15550 "\n"
15551 "void main()\n"
15552 "{\n"
15553 " vs_tcs = in_vs;\n"
15554 "}\n"
15555 "\n";
15556 static const GLchar* vs_tested = "#version 430 core\n"
15557 "#extension GL_ARB_enhanced_layouts : require\n"
15558 "\n"
15559 "VAR_DEFINITION"
15560 "\n"
15561 "in vec4 in_vs;\n"
15562 "out vec4 vs_tcs;\n"
15563 "\n"
15564 "void main()\n"
15565 "{\n"
15566 " vec4 result = in_vs;\n"
15567 "\n"
15568 "VARIABLE_USE"
15569 "\n"
15570 " vs_tcs += result;\n"
15571 "}\n"
15572 "\n";
15573
15574 std::string source;
15575 testCase& test_case = m_test_cases[test_case_index];
15576
15577 if (test_case.m_stage == stage)
15578 {
15579 const GLchar* array = "";
15580 GLchar buffer[16];
15581 const GLchar* var_definition = 0;
15582 const GLchar* direction = "in";
15583 const GLchar* index = "";
15584 size_t position = 0;
15585 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
15586 const GLchar* var_use = 0;
15587 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
15588 const GLchar* flat = "";
15589
15590 if (false == test_case.m_is_input)
15591 {
15592 direction = "out";
15593 storage = Utils::Variable::VARYING_OUTPUT;
15594
15595 if (false == test_case.m_is_array)
15596 {
15597 var_definition = var_definition_one;
15598 var_use = output_use_one;
15599 }
15600 else
15601 {
15602 var_definition = var_definition_arr;
15603 var_use = output_use_arr;
15604 }
15605 }
15606 else
15607 {
15608 if (false == test_case.m_is_array)
15609 {
15610 var_definition = var_definition_one;
15611 var_use = Utils::Shader::VERTEX == stage ? input_use_one : "\n";
15612 }
15613 else
15614 {
15615 var_definition = var_definition_arr;
15616 var_use = Utils::Shader::VERTEX == stage ? input_use_arr : "\n";
15617 }
15618 }
15619
15620 if (isFlatRequired(stage, test_case.m_type, storage, true))
15621 {
15622 flat = "flat";
15623 }
15624
15625 sprintf(buffer, "%d", test_case.m_component);
15626
15627 switch (stage)
15628 {
15629 case Utils::Shader::FRAGMENT:
15630 source = fs_tested;
15631 break;
15632 case Utils::Shader::GEOMETRY:
15633 source = gs_tested;
15634 array = test_case.m_is_input ? "[]" : "";
15635 index = test_case.m_is_input ? "[0]" : "";
15636 break;
15637 case Utils::Shader::TESS_CTRL:
15638 source = tcs_tested;
15639 array = "[]";
15640 index = "[gl_InvocationID]";
15641 break;
15642 case Utils::Shader::TESS_EVAL:
15643 source = tes_tested;
15644 array = test_case.m_is_input ? "[]" : "";
15645 index = test_case.m_is_input ? "[0]" : "";
15646 break;
15647 case Utils::Shader::VERTEX:
15648 source = vs_tested;
15649 break;
15650 default:
15651 TCU_FAIL("Invalid enum");
15652 }
15653
15654 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
15655 position = 0;
15656 Utils::replaceToken("COMPONENT", position, buffer, source);
15657 Utils::replaceToken("FLAT", position, flat, source);
15658 Utils::replaceToken("DIRECTION", position, direction, source);
15659 Utils::replaceToken("ARRAY", position, array, source);
15660 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
15661
15662 Utils::replaceAllTokens("TYPE", type_name, source);
15663 Utils::replaceAllTokens("INDEX", index, source);
15664 }
15665 else
15666 {
15667 switch (stage)
15668 {
15669 case Utils::Shader::FRAGMENT:
15670 source = fs;
15671 break;
15672 case Utils::Shader::GEOMETRY:
15673 source = gs;
15674 break;
15675 case Utils::Shader::TESS_CTRL:
15676 source = tcs;
15677 break;
15678 case Utils::Shader::TESS_EVAL:
15679 source = tes;
15680 break;
15681 case Utils::Shader::VERTEX:
15682 source = vs;
15683 break;
15684 default:
15685 TCU_FAIL("Invalid enum");
15686 }
15687 }
15688
15689 return source;
15690 }
15691
15692 /** Get description of test case
15693 *
15694 * @param test_case_index Index of test case
15695 *
15696 * @return Test case description
15697 **/
15698 std::string VaryingInvalidValueComponentTest::getTestCaseName(GLuint test_case_index)
15699 {
15700 std::stringstream stream;
15701 testCase& test_case = m_test_cases[test_case_index];
15702
15703 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
15704 << " type: " << test_case.m_type.GetGLSLTypeName();
15705
15706 if (true == test_case.m_is_array)
15707 {
15708 stream << "[1]";
15709 }
15710
15711 stream << ", direction: ";
15712
15713 if (true == test_case.m_is_input)
15714 {
15715 stream << "input";
15716 }
15717 else
15718 {
15719 stream << "output";
15720 }
15721
15722 stream << ", component: " << test_case.m_component;
15723
15724 return stream.str();
15725 }
15726
15727 /** Get number of test cases
15728 *
15729 * @return Number of test cases
15730 **/
15731 GLuint VaryingInvalidValueComponentTest::getTestCaseNumber()
15732 {
15733 return static_cast<GLuint>(m_test_cases.size());
15734 }
15735
15736 /** Selects if "compute" stage is relevant for test
15737 *
15738 * @param ignored
15739 *
15740 * @return false
15741 **/
15742 bool VaryingInvalidValueComponentTest::isComputeRelevant(GLuint /* test_case_index */)
15743 {
15744 return false;
15745 }
15746
15747 /** Prepare all test cases
15748 *
15749 **/
15750 void VaryingInvalidValueComponentTest::testInit()
15751 {
15752 const GLuint n_types = getTypesNumber();
15753
15754 for (GLuint i = 0; i < n_types; ++i)
15755 {
15756 const Utils::Type& type = getType(i);
15757 const std::vector<GLuint>& valid_components = type.GetValidComponents();
15758
15759 if (valid_components.empty())
15760 {
15761 continue;
15762 }
15763
15764 std::vector<GLuint> every_component(4, 0);
15765 every_component[1] = 1;
15766 every_component[2] = 2;
15767 every_component[3] = 3;
15768 std::vector<GLuint> invalid_components;
15769
15770 std::set_symmetric_difference(every_component.begin(), every_component.end(), valid_components.begin(),
15771 valid_components.end(), back_inserter(invalid_components));
15772
15773 for (std::vector<GLuint>::const_iterator it_invalid_components = invalid_components.begin();
15774 it_invalid_components != invalid_components.end(); ++it_invalid_components)
15775 {
15776 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
15777 {
15778 if (Utils::Shader::COMPUTE == stage)
15779 {
15780 continue;
15781 }
15782
15783 testCase test_case_in_arr = { *it_invalid_components, true, true, (Utils::Shader::STAGES)stage, type };
15784 testCase test_case_in_one = { *it_invalid_components, true, false, (Utils::Shader::STAGES)stage, type };
15785 testCase test_case_out_arr = { *it_invalid_components, false, true, (Utils::Shader::STAGES)stage,
15786 type };
15787 testCase test_case_out_one = { *it_invalid_components, false, false, (Utils::Shader::STAGES)stage,
15788 type };
15789
15790 m_test_cases.push_back(test_case_in_arr);
15791 m_test_cases.push_back(test_case_in_one);
15792
15793 if (Utils::Shader::FRAGMENT != stage)
15794 {
15795 m_test_cases.push_back(test_case_out_arr);
15796 m_test_cases.push_back(test_case_out_one);
15797 }
15798 }
15799 }
15800 }
15801 }
15802
15803 /** Constructor
15804 *
15805 * @param context Test framework context
15806 **/
15807 VaryingExceedingComponentsTest::VaryingExceedingComponentsTest(deqp::Context& context)
15808 : NegativeTestBase(context, "varying_exceeding_components",
15809 "Test verifies that compiler reports error when component qualifier exceeds limits")
15810 {
15811 }
15812
15813 /** Source for given test case and stage
15814 *
15815 * @param test_case_index Index of test case
15816 * @param stage Shader stage
15817 *
15818 * @return Shader source
15819 **/
15820 std::string VaryingExceedingComponentsTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
15821 {
15822 #if DEBUG_NEG_REMOVE_ERROR
15823 static const GLchar* var_definition_arr =
15824 "layout (location = 1 /*, component = 4 */) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15825 static const GLchar* var_definition_one =
15826 "layout (location = 1 /*, component = 4 */) FLAT DIRECTION TYPE gokuARRAY;\n";
15827 #else
15828 static const GLchar* var_definition_arr =
15829 "layout (location = 1, component = 4) FLAT DIRECTION TYPE gokuARRAY[1];\n";
15830 static const GLchar* var_definition_one = "layout (location = 1, component = 4) FLAT DIRECTION TYPE gokuARRAY;\n";
15831 #endif /* DEBUG_NEG_REMOVE_ERROR */
15832 static const GLchar* input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
15833 " {\n"
15834 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15835 " }\n";
15836 static const GLchar* input_use_one = " if (TYPE(0) == gokuINDEX)\n"
15837 " {\n"
15838 " result += vec4(1, 0.5, 0.25, 0.125);\n"
15839 " }\n";
15840 static const GLchar* output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
15841 " if (vec4(0) == result)\n"
15842 " {\n"
15843 " gokuINDEX[0] = TYPE(1);\n"
15844 " }\n";
15845 static const GLchar* output_use_one = " gokuINDEX = TYPE(0);\n"
15846 " if (vec4(0) == result)\n"
15847 " {\n"
15848 " gokuINDEX = TYPE(1);\n"
15849 " }\n";
15850 static const GLchar* fs = "#version 430 core\n"
15851 "#extension GL_ARB_enhanced_layouts : require\n"
15852 "\n"
15853 "in vec4 gs_fs;\n"
15854 "out vec4 fs_out;\n"
15855 "\n"
15856 "void main()\n"
15857 "{\n"
15858 " fs_out = gs_fs;\n"
15859 "}\n"
15860 "\n";
15861 static const GLchar* fs_tested = "#version 430 core\n"
15862 "#extension GL_ARB_enhanced_layouts : require\n"
15863 "\n"
15864 "VAR_DEFINITION"
15865 "\n"
15866 "in vec4 gs_fs;\n"
15867 "out vec4 fs_out;\n"
15868 "\n"
15869 "void main()\n"
15870 "{\n"
15871 " vec4 result = gs_fs;\n"
15872 "\n"
15873 "VARIABLE_USE"
15874 "\n"
15875 " fs_out += result;\n"
15876 "}\n"
15877 "\n";
15878 static const GLchar* gs = "#version 430 core\n"
15879 "#extension GL_ARB_enhanced_layouts : require\n"
15880 "\n"
15881 "layout(points) in;\n"
15882 "layout(triangle_strip, max_vertices = 4) out;\n"
15883 "\n"
15884 "in vec4 tes_gs[];\n"
15885 "out vec4 gs_fs;\n"
15886 "\n"
15887 "void main()\n"
15888 "{\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 " gs_fs = tes_gs[0];\n"
15896 " gl_Position = vec4(1, -1, 0, 1);\n"
15897 " EmitVertex();\n"
15898 " gs_fs = tes_gs[0];\n"
15899 " gl_Position = vec4(1, 1, 0, 1);\n"
15900 " EmitVertex();\n"
15901 "}\n"
15902 "\n";
15903 static const GLchar* gs_tested = "#version 430 core\n"
15904 "#extension GL_ARB_enhanced_layouts : require\n"
15905 "\n"
15906 "layout(points) in;\n"
15907 "layout(triangle_strip, max_vertices = 4) out;\n"
15908 "\n"
15909 "VAR_DEFINITION"
15910 "\n"
15911 "in vec4 tes_gs[];\n"
15912 "out vec4 gs_fs;\n"
15913 "\n"
15914 "void main()\n"
15915 "{\n"
15916 " vec4 result = tes_gs[0];\n"
15917 "\n"
15918 "VARIABLE_USE"
15919 "\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 " gs_fs = result;\n"
15927 " gl_Position = vec4(1, -1, 0, 1);\n"
15928 " EmitVertex();\n"
15929 " gs_fs = result;\n"
15930 " gl_Position = vec4(1, 1, 0, 1);\n"
15931 " EmitVertex();\n"
15932 "}\n"
15933 "\n";
15934 static const GLchar* tcs = "#version 430 core\n"
15935 "#extension GL_ARB_enhanced_layouts : require\n"
15936 "\n"
15937 "layout(vertices = 1) out;\n"
15938 "\n"
15939 "in vec4 vs_tcs[];\n"
15940 "out vec4 tcs_tes[];\n"
15941 "\n"
15942 "void main()\n"
15943 "{\n"
15944 "\n"
15945 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
15946 "\n"
15947 " gl_TessLevelOuter[0] = 1.0;\n"
15948 " gl_TessLevelOuter[1] = 1.0;\n"
15949 " gl_TessLevelOuter[2] = 1.0;\n"
15950 " gl_TessLevelOuter[3] = 1.0;\n"
15951 " gl_TessLevelInner[0] = 1.0;\n"
15952 " gl_TessLevelInner[1] = 1.0;\n"
15953 "}\n"
15954 "\n";
15955 static const GLchar* tcs_tested = "#version 430 core\n"
15956 "#extension GL_ARB_enhanced_layouts : require\n"
15957 "\n"
15958 "layout(vertices = 1) out;\n"
15959 "\n"
15960 "VAR_DEFINITION"
15961 "\n"
15962 "in vec4 vs_tcs[];\n"
15963 "out vec4 tcs_tes[];\n"
15964 "\n"
15965 "void main()\n"
15966 "{\n"
15967 " vec4 result = vs_tcs[gl_InvocationID];\n"
15968 "\n"
15969 "VARIABLE_USE"
15970 "\n"
15971 " tcs_tes[gl_InvocationID] = result;\n"
15972 "\n"
15973 " gl_TessLevelOuter[0] = 1.0;\n"
15974 " gl_TessLevelOuter[1] = 1.0;\n"
15975 " gl_TessLevelOuter[2] = 1.0;\n"
15976 " gl_TessLevelOuter[3] = 1.0;\n"
15977 " gl_TessLevelInner[0] = 1.0;\n"
15978 " gl_TessLevelInner[1] = 1.0;\n"
15979 "}\n"
15980 "\n";
15981 static const GLchar* tes = "#version 430 core\n"
15982 "#extension GL_ARB_enhanced_layouts : require\n"
15983 "\n"
15984 "layout(isolines, point_mode) in;\n"
15985 "\n"
15986 "in vec4 tcs_tes[];\n"
15987 "out vec4 tes_gs;\n"
15988 "\n"
15989 "void main()\n"
15990 "{\n"
15991 " tes_gs = tcs_tes[0];\n"
15992 "}\n"
15993 "\n";
15994 static const GLchar* tes_tested = "#version 430 core\n"
15995 "#extension GL_ARB_enhanced_layouts : require\n"
15996 "\n"
15997 "layout(isolines, point_mode) in;\n"
15998 "\n"
15999 "VAR_DEFINITION"
16000 "\n"
16001 "in vec4 tcs_tes[];\n"
16002 "out vec4 tes_gs;\n"
16003 "\n"
16004 "void main()\n"
16005 "{\n"
16006 " vec4 result = tcs_tes[0];\n"
16007 "\n"
16008 "VARIABLE_USE"
16009 "\n"
16010 " tes_gs += result;\n"
16011 "}\n"
16012 "\n";
16013 static const GLchar* vs = "#version 430 core\n"
16014 "#extension GL_ARB_enhanced_layouts : require\n"
16015 "\n"
16016 "in vec4 in_vs;\n"
16017 "out vec4 vs_tcs;\n"
16018 "\n"
16019 "void main()\n"
16020 "{\n"
16021 " vs_tcs = in_vs;\n"
16022 "}\n"
16023 "\n";
16024 static const GLchar* vs_tested = "#version 430 core\n"
16025 "#extension GL_ARB_enhanced_layouts : require\n"
16026 "\n"
16027 "VAR_DEFINITION"
16028 "\n"
16029 "in vec4 in_vs;\n"
16030 "out vec4 vs_tcs;\n"
16031 "\n"
16032 "void main()\n"
16033 "{\n"
16034 " vec4 result = in_vs;\n"
16035 "\n"
16036 "VARIABLE_USE"
16037 "\n"
16038 " vs_tcs += result;\n"
16039 "}\n"
16040 "\n";
16041
16042 std::string source;
16043 testCase& test_case = m_test_cases[test_case_index];
16044
16045 if (test_case.m_stage == stage)
16046 {
16047 const GLchar* array = "";
16048 const GLchar* var_definition = 0;
16049 const GLchar* direction = "in";
16050 const GLchar* index = "";
16051 size_t position = 0;
16052 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16053 const GLchar* var_use = 0;
16054 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16055 const GLchar* flat = "";
16056
16057 if (false == test_case.m_is_input)
16058 {
16059 direction = "out";
16060 storage = Utils::Variable::VARYING_OUTPUT;
16061
16062 if (false == test_case.m_is_array)
16063 {
16064 var_definition = var_definition_one;
16065 var_use = output_use_one;
16066 }
16067 else
16068 {
16069 var_definition = var_definition_arr;
16070 var_use = output_use_arr;
16071 }
16072 }
16073 else
16074 {
16075 if (false == test_case.m_is_array)
16076 {
16077 var_definition = var_definition_one;
16078 var_use = Utils::Shader::VERTEX == stage ? input_use_one : "\n";
16079 }
16080 else
16081 {
16082 var_definition = var_definition_arr;
16083 var_use = Utils::Shader::VERTEX == stage ? input_use_arr : "\n";
16084 }
16085 }
16086
16087 if (isFlatRequired(stage, test_case.m_type, storage, true))
16088 {
16089 flat = "flat";
16090 }
16091
16092 switch (stage)
16093 {
16094 case Utils::Shader::FRAGMENT:
16095 source = fs_tested;
16096 break;
16097 case Utils::Shader::GEOMETRY:
16098 source = gs_tested;
16099 array = test_case.m_is_input ? "[]" : "";
16100 index = test_case.m_is_input ? "[0]" : "";
16101 break;
16102 case Utils::Shader::TESS_CTRL:
16103 source = tcs_tested;
16104 array = "[]";
16105 index = "[gl_InvocationID]";
16106 break;
16107 case Utils::Shader::TESS_EVAL:
16108 source = tes_tested;
16109 array = test_case.m_is_input ? "[]" : "";
16110 index = test_case.m_is_input ? "[0]" : "";
16111 break;
16112 case Utils::Shader::VERTEX:
16113 source = vs_tested;
16114 break;
16115 default:
16116 TCU_FAIL("Invalid enum");
16117 }
16118
16119 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16120 position = 0;
16121 Utils::replaceToken("FLAT", position, flat, source);
16122 Utils::replaceToken("DIRECTION", position, direction, source);
16123 Utils::replaceToken("ARRAY", position, array, source);
16124 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16125
16126 Utils::replaceAllTokens("TYPE", type_name, source);
16127 Utils::replaceAllTokens("INDEX", index, source);
16128 }
16129 else
16130 {
16131 switch (stage)
16132 {
16133 case Utils::Shader::FRAGMENT:
16134 source = fs;
16135 break;
16136 case Utils::Shader::GEOMETRY:
16137 source = gs;
16138 break;
16139 case Utils::Shader::TESS_CTRL:
16140 source = tcs;
16141 break;
16142 case Utils::Shader::TESS_EVAL:
16143 source = tes;
16144 break;
16145 case Utils::Shader::VERTEX:
16146 source = vs;
16147 break;
16148 default:
16149 TCU_FAIL("Invalid enum");
16150 }
16151 }
16152
16153 return source;
16154 }
16155
16156 /** Get description of test case
16157 *
16158 * @param test_case_index Index of test case
16159 *
16160 * @return Test case description
16161 **/
16162 std::string VaryingExceedingComponentsTest::getTestCaseName(GLuint test_case_index)
16163 {
16164 std::stringstream stream;
16165 testCase& test_case = m_test_cases[test_case_index];
16166
16167 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16168 << " type: " << test_case.m_type.GetGLSLTypeName();
16169
16170 if (true == test_case.m_is_array)
16171 {
16172 stream << "[1]";
16173 }
16174
16175 stream << ", direction: ";
16176
16177 if (true == test_case.m_is_input)
16178 {
16179 stream << "input";
16180 }
16181 else
16182 {
16183 stream << "output";
16184 }
16185
16186 return stream.str();
16187 }
16188
16189 /** Get number of test cases
16190 *
16191 * @return Number of test cases
16192 **/
16193 GLuint VaryingExceedingComponentsTest::getTestCaseNumber()
16194 {
16195 return static_cast<GLuint>(m_test_cases.size());
16196 }
16197
16198 /** Selects if "compute" stage is relevant for test
16199 *
16200 * @param ignored
16201 *
16202 * @return false
16203 **/
16204 bool VaryingExceedingComponentsTest::isComputeRelevant(GLuint /* test_case_index */)
16205 {
16206 return false;
16207 }
16208
16209 /** Prepare all test cases
16210 *
16211 **/
16212 void VaryingExceedingComponentsTest::testInit()
16213 {
16214 const GLuint n_types = getTypesNumber();
16215
16216 for (GLuint i = 0; i < n_types; ++i)
16217 {
16218 const Utils::Type& type = getType(i);
16219 const std::vector<GLuint>& valid_components = type.GetValidComponents();
16220
16221 if (valid_components.empty())
16222 {
16223 continue;
16224 }
16225
16226 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16227 {
16228 if (Utils::Shader::COMPUTE == stage)
16229 {
16230 continue;
16231 }
16232
16233 testCase test_case_in_arr = { true, true, (Utils::Shader::STAGES)stage, type };
16234 testCase test_case_in_one = { true, false, (Utils::Shader::STAGES)stage, type };
16235 testCase test_case_out_arr = { false, true, (Utils::Shader::STAGES)stage, type };
16236 testCase test_case_out_one = { false, false, (Utils::Shader::STAGES)stage, type };
16237
16238 m_test_cases.push_back(test_case_in_arr);
16239 m_test_cases.push_back(test_case_in_one);
16240
16241 if (Utils::Shader::FRAGMENT != stage)
16242 {
16243 m_test_cases.push_back(test_case_out_arr);
16244 m_test_cases.push_back(test_case_out_one);
16245 }
16246 }
16247 }
16248 }
16249
16250 /** Constructor
16251 *
16252 * @param context Test framework context
16253 **/
16254 VaryingComponentWithoutLocationTest::VaryingComponentWithoutLocationTest(deqp::Context& context)
16255 : NegativeTestBase(context, "varying_component_without_location",
16256 "Test verifies that compiler reports error when component qualifier is used without location")
16257 {
16258 }
16259
16260 /** Source for given test case and stage
16261 *
16262 * @param test_case_index Index of test case
16263 * @param stage Shader stage
16264 *
16265 * @return Shader source
16266 **/
16267 std::string VaryingComponentWithoutLocationTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16268 {
16269 #if DEBUG_NEG_REMOVE_ERROR
16270 static const GLchar* var_definition = "/* layout (component = COMPONENT) */ FLAT DIRECTION TYPE gokuARRAY;\n";
16271 #else
16272 static const GLchar* var_definition = "layout (component = COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
16273 #endif /* DEBUG_NEG_REMOVE_ERROR */
16274 static const GLchar* input_use = " if (TYPE(0) == gokuINDEX)\n"
16275 " {\n"
16276 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16277 " }\n";
16278 static const GLchar* output_use = " gokuINDEX = TYPE(0);\n"
16279 " if (vec4(0) == result)\n"
16280 " {\n"
16281 " gokuINDEX = TYPE(1);\n"
16282 " }\n";
16283 static const GLchar* fs = "#version 430 core\n"
16284 "#extension GL_ARB_enhanced_layouts : require\n"
16285 "\n"
16286 "in vec4 gs_fs;\n"
16287 "out vec4 fs_out;\n"
16288 "\n"
16289 "void main()\n"
16290 "{\n"
16291 " fs_out = gs_fs;\n"
16292 "}\n"
16293 "\n";
16294 static const GLchar* fs_tested = "#version 430 core\n"
16295 "#extension GL_ARB_enhanced_layouts : require\n"
16296 "\n"
16297 "VAR_DEFINITION"
16298 "\n"
16299 "in vec4 gs_fs;\n"
16300 "out vec4 fs_out;\n"
16301 "\n"
16302 "void main()\n"
16303 "{\n"
16304 " vec4 result = gs_fs;\n"
16305 "\n"
16306 "VARIABLE_USE"
16307 "\n"
16308 " fs_out = result;\n"
16309 "}\n"
16310 "\n";
16311 static const GLchar* gs = "#version 430 core\n"
16312 "#extension GL_ARB_enhanced_layouts : require\n"
16313 "\n"
16314 "layout(points) in;\n"
16315 "layout(triangle_strip, max_vertices = 4) out;\n"
16316 "\n"
16317 "in vec4 tes_gs[];\n"
16318 "out vec4 gs_fs;\n"
16319 "\n"
16320 "void main()\n"
16321 "{\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 " gs_fs = tes_gs[0];\n"
16329 " gl_Position = vec4(1, -1, 0, 1);\n"
16330 " EmitVertex();\n"
16331 " gs_fs = tes_gs[0];\n"
16332 " gl_Position = vec4(1, 1, 0, 1);\n"
16333 " EmitVertex();\n"
16334 "}\n"
16335 "\n";
16336 static const GLchar* gs_tested = "#version 430 core\n"
16337 "#extension GL_ARB_enhanced_layouts : require\n"
16338 "\n"
16339 "layout(points) in;\n"
16340 "layout(triangle_strip, max_vertices = 4) out;\n"
16341 "\n"
16342 "VAR_DEFINITION"
16343 "\n"
16344 "in vec4 tes_gs[];\n"
16345 "out vec4 gs_fs;\n"
16346 "\n"
16347 "void main()\n"
16348 "{\n"
16349 " vec4 result = tes_gs[0];\n"
16350 "\n"
16351 "VARIABLE_USE"
16352 "\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 " gs_fs = result;\n"
16360 " gl_Position = vec4(1, -1, 0, 1);\n"
16361 " EmitVertex();\n"
16362 " gs_fs = result;\n"
16363 " gl_Position = vec4(1, 1, 0, 1);\n"
16364 " EmitVertex();\n"
16365 "}\n"
16366 "\n";
16367 static const GLchar* tcs = "#version 430 core\n"
16368 "#extension GL_ARB_enhanced_layouts : require\n"
16369 "\n"
16370 "layout(vertices = 1) out;\n"
16371 "\n"
16372 "in vec4 vs_tcs[];\n"
16373 "out vec4 tcs_tes[];\n"
16374 "\n"
16375 "void main()\n"
16376 "{\n"
16377 "\n"
16378 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16379 "\n"
16380 " gl_TessLevelOuter[0] = 1.0;\n"
16381 " gl_TessLevelOuter[1] = 1.0;\n"
16382 " gl_TessLevelOuter[2] = 1.0;\n"
16383 " gl_TessLevelOuter[3] = 1.0;\n"
16384 " gl_TessLevelInner[0] = 1.0;\n"
16385 " gl_TessLevelInner[1] = 1.0;\n"
16386 "}\n"
16387 "\n";
16388 static const GLchar* tcs_tested = "#version 430 core\n"
16389 "#extension GL_ARB_enhanced_layouts : require\n"
16390 "\n"
16391 "layout(vertices = 1) out;\n"
16392 "\n"
16393 "VAR_DEFINITION"
16394 "\n"
16395 "in vec4 vs_tcs[];\n"
16396 "out vec4 tcs_tes[];\n"
16397 "\n"
16398 "void main()\n"
16399 "{\n"
16400 " vec4 result = vs_tcs[gl_InvocationID];\n"
16401 "\n"
16402 "VARIABLE_USE"
16403 "\n"
16404 " tcs_tes[gl_InvocationID] = result;\n"
16405 "\n"
16406 " gl_TessLevelOuter[0] = 1.0;\n"
16407 " gl_TessLevelOuter[1] = 1.0;\n"
16408 " gl_TessLevelOuter[2] = 1.0;\n"
16409 " gl_TessLevelOuter[3] = 1.0;\n"
16410 " gl_TessLevelInner[0] = 1.0;\n"
16411 " gl_TessLevelInner[1] = 1.0;\n"
16412 "}\n"
16413 "\n";
16414 static const GLchar* tes = "#version 430 core\n"
16415 "#extension GL_ARB_enhanced_layouts : require\n"
16416 "\n"
16417 "layout(isolines, point_mode) in;\n"
16418 "\n"
16419 "in vec4 tcs_tes[];\n"
16420 "out vec4 tes_gs;\n"
16421 "\n"
16422 "void main()\n"
16423 "{\n"
16424 " tes_gs = tcs_tes[0];\n"
16425 "}\n"
16426 "\n";
16427 static const GLchar* tes_tested = "#version 430 core\n"
16428 "#extension GL_ARB_enhanced_layouts : require\n"
16429 "\n"
16430 "layout(isolines, point_mode) in;\n"
16431 "\n"
16432 "VAR_DEFINITION"
16433 "\n"
16434 "in vec4 tcs_tes[];\n"
16435 "out vec4 tes_gs;\n"
16436 "\n"
16437 "void main()\n"
16438 "{\n"
16439 " vec4 result = tcs_tes[0];\n"
16440 "\n"
16441 "VARIABLE_USE"
16442 "\n"
16443 " tes_gs = result;\n"
16444 "}\n"
16445 "\n";
16446 static const GLchar* vs = "#version 430 core\n"
16447 "#extension GL_ARB_enhanced_layouts : require\n"
16448 "\n"
16449 "in vec4 in_vs;\n"
16450 "out vec4 vs_tcs;\n"
16451 "\n"
16452 "void main()\n"
16453 "{\n"
16454 " vs_tcs = in_vs;\n"
16455 "}\n"
16456 "\n";
16457 static const GLchar* vs_tested = "#version 430 core\n"
16458 "#extension GL_ARB_enhanced_layouts : require\n"
16459 "\n"
16460 "VAR_DEFINITION"
16461 "\n"
16462 "in vec4 in_vs;\n"
16463 "out vec4 vs_tcs;\n"
16464 "\n"
16465 "void main()\n"
16466 "{\n"
16467 " vec4 result = in_vs;\n"
16468 "\n"
16469 "VARIABLE_USE"
16470 "\n"
16471 " vs_tcs = result;\n"
16472 "}\n"
16473 "\n";
16474
16475 std::string source;
16476 testCase& test_case = m_test_cases[test_case_index];
16477
16478 if (test_case.m_stage == stage)
16479 {
16480 const GLchar* array = "";
16481 GLchar buffer[16];
16482 const GLchar* direction = "in";
16483 const GLchar* index = "";
16484 size_t position = 0;
16485 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16486 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
16487 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16488 const GLchar* flat = "";
16489
16490 if (false == test_case.m_is_input)
16491 {
16492 direction = "out";
16493 storage = Utils::Variable::VARYING_OUTPUT;
16494 var_use = output_use;
16495 }
16496
16497 if (isFlatRequired(stage, test_case.m_type, storage, true))
16498 {
16499 flat = "flat";
16500 }
16501
16502 sprintf(buffer, "%d", test_case.m_component);
16503
16504 switch (stage)
16505 {
16506 case Utils::Shader::FRAGMENT:
16507 source = fs_tested;
16508 break;
16509 case Utils::Shader::GEOMETRY:
16510 source = gs_tested;
16511 array = test_case.m_is_input ? "[]" : "";
16512 index = test_case.m_is_input ? "[0]" : "";
16513 break;
16514 case Utils::Shader::TESS_CTRL:
16515 source = tcs_tested;
16516 array = "[]";
16517 index = "[gl_InvocationID]";
16518 break;
16519 case Utils::Shader::TESS_EVAL:
16520 source = tes_tested;
16521 array = test_case.m_is_input ? "[]" : "";
16522 index = test_case.m_is_input ? "[0]" : "";
16523 break;
16524 case Utils::Shader::VERTEX:
16525 source = vs_tested;
16526 break;
16527 default:
16528 TCU_FAIL("Invalid enum");
16529 }
16530
16531 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
16532 position = 0;
16533 Utils::replaceToken("COMPONENT", position, buffer, source);
16534 Utils::replaceToken("FLAT", position, flat, source);
16535 Utils::replaceToken("DIRECTION", position, direction, source);
16536 Utils::replaceToken("ARRAY", position, array, source);
16537 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
16538
16539 Utils::replaceAllTokens("TYPE", type_name, source);
16540 Utils::replaceAllTokens("INDEX", index, source);
16541 }
16542 else
16543 {
16544 switch (stage)
16545 {
16546 case Utils::Shader::FRAGMENT:
16547 source = fs;
16548 break;
16549 case Utils::Shader::GEOMETRY:
16550 source = gs;
16551 break;
16552 case Utils::Shader::TESS_CTRL:
16553 source = tcs;
16554 break;
16555 case Utils::Shader::TESS_EVAL:
16556 source = tes;
16557 break;
16558 case Utils::Shader::VERTEX:
16559 source = vs;
16560 break;
16561 default:
16562 TCU_FAIL("Invalid enum");
16563 }
16564 }
16565
16566 return source;
16567 }
16568
16569 /** Get description of test case
16570 *
16571 * @param test_case_index Index of test case
16572 *
16573 * @return Test case description
16574 **/
16575 std::string VaryingComponentWithoutLocationTest::getTestCaseName(GLuint test_case_index)
16576 {
16577 std::stringstream stream;
16578 testCase& test_case = m_test_cases[test_case_index];
16579
16580 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
16581 << " type: " << test_case.m_type.GetGLSLTypeName() << ", direction: ";
16582
16583 if (true == test_case.m_is_input)
16584 {
16585 stream << "input";
16586 }
16587 else
16588 {
16589 stream << "output";
16590 }
16591
16592 stream << ", component: " << test_case.m_component;
16593
16594 return stream.str();
16595 }
16596
16597 /** Get number of test cases
16598 *
16599 * @return Number of test cases
16600 **/
16601 GLuint VaryingComponentWithoutLocationTest::getTestCaseNumber()
16602 {
16603 return static_cast<GLuint>(m_test_cases.size());
16604 }
16605
16606 /** Selects if "compute" stage is relevant for test
16607 *
16608 * @param ignored
16609 *
16610 * @return false
16611 **/
16612 bool VaryingComponentWithoutLocationTest::isComputeRelevant(GLuint /* test_case_index */)
16613 {
16614 return false;
16615 }
16616
16617 /** Prepare all test cases
16618 *
16619 **/
16620 void VaryingComponentWithoutLocationTest::testInit()
16621 {
16622 const GLuint n_types = getTypesNumber();
16623
16624 for (GLuint i = 0; i < n_types; ++i)
16625 {
16626 const Utils::Type& type = getType(i);
16627 const std::vector<GLuint>& valid_components = type.GetValidComponents();
16628
16629 if (valid_components.empty())
16630 {
16631 continue;
16632 }
16633
16634 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
16635 {
16636 if (Utils::Shader::COMPUTE == stage)
16637 {
16638 continue;
16639 }
16640
16641 testCase test_case_in = { valid_components.back(), true, (Utils::Shader::STAGES)stage, type };
16642 testCase test_case_out = { valid_components.back(), false, (Utils::Shader::STAGES)stage, type };
16643
16644 m_test_cases.push_back(test_case_in);
16645
16646 if (Utils::Shader::FRAGMENT != stage)
16647 {
16648 m_test_cases.push_back(test_case_out);
16649 }
16650 }
16651 }
16652 }
16653
16654 /** Constructor
16655 *
16656 * @param context Test framework context
16657 **/
16658 VaryingComponentOfInvalidTypeTest::VaryingComponentOfInvalidTypeTest(deqp::Context& context)
16659 : NegativeTestBase(context, "varying_component_of_invalid_type",
16660 "Test verifies that compiler reports error when component qualifier is used for invalid type")
16661 {
16662 }
16663
16664 /** Source for given test case and stage
16665 *
16666 * @param test_case_index Index of test case
16667 * @param stage Shader stage
16668 *
16669 * @return Shader source
16670 **/
16671 std::string VaryingComponentOfInvalidTypeTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
16672 {
16673 static const GLchar* block_definition_arr = "layout (location = 1COMPONENT) DIRECTION Goku {\n"
16674 " FLAT TYPE member;\n"
16675 "} gokuARRAY[1];\n";
16676 static const GLchar* block_definition_one = "layout (location = 1COMPONENT) DIRECTION Goku {\n"
16677 " FLAT TYPE member;\n"
16678 "} gokuARRAY;\n";
16679 static const GLchar* matrix_dvec3_dvec4_definition_arr =
16680 "layout (location = 1COMPONENT) FLAT DIRECTION TYPE gokuARRAY[1];\n";
16681 static const GLchar* matrix_dvec3_dvec4_definition_one =
16682 "layout (location = 1COMPONENT) FLAT DIRECTION TYPE gokuARRAY;\n";
16683 static const GLchar* struct_definition_arr = "struct Goku {\n"
16684 " TYPE member;\n"
16685 "};\n"
16686 "\n"
16687 "layout (location = 1COMPONENT) FLAT DIRECTION Goku gokuARRAY[1];\n";
16688 static const GLchar* struct_definition_one = "struct Goku {\n"
16689 " TYPE member;\n"
16690 "};\n"
16691 "\n"
16692 "layout (location = 1COMPONENT) FLAT DIRECTION Goku gokuARRAY;\n";
16693 static const GLchar* matrix_dvec3_dvec4_input_use_arr = " if (TYPE(0) == gokuINDEX[0])\n"
16694 " {\n"
16695 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16696 " }\n";
16697 static const GLchar* matrix_dvec3_dvec4_input_use_one = " if (TYPE(0) == gokuINDEX)\n"
16698 " {\n"
16699 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16700 " }\n";
16701 static const GLchar* matrix_dvec3_dvec4_output_use_arr = " gokuINDEX[0] = TYPE(0);\n"
16702 " if (vec4(0) == result)\n"
16703 " {\n"
16704 " gokuINDEX[0] = TYPE(1);\n"
16705 " }\n";
16706 static const GLchar* matrix_dvec3_dvec4_output_use_one = " gokuINDEX = TYPE(0);\n"
16707 " if (vec4(0) == result)\n"
16708 " {\n"
16709 " gokuINDEX = TYPE(1);\n"
16710 " }\n";
16711 static const GLchar* member_input_use_arr = " if (TYPE(0) == gokuINDEX[0].member)\n"
16712 " {\n"
16713 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16714 " }\n";
16715 static const GLchar* member_input_use_one = " if (TYPE(0) == gokuINDEX.member)\n"
16716 " {\n"
16717 " result += vec4(1, 0.5, 0.25, 0.125);\n"
16718 " }\n";
16719 static const GLchar* member_output_use_arr = " gokuINDEX[0].member = TYPE(0);\n"
16720 " if (vec4(0) == result)\n"
16721 " {\n"
16722 " gokuINDEX[0].member = TYPE(1);\n"
16723 " }\n";
16724 static const GLchar* member_output_use_one = " gokuINDEX.member = TYPE(0);\n"
16725 " if (vec4(0) == result)\n"
16726 " {\n"
16727 " gokuINDEX.member = TYPE(1);\n"
16728 " }\n";
16729 static const GLchar* fs = "#version 430 core\n"
16730 "#extension GL_ARB_enhanced_layouts : require\n"
16731 "\n"
16732 "in vec4 gs_fs;\n"
16733 "out vec4 fs_out;\n"
16734 "\n"
16735 "void main()\n"
16736 "{\n"
16737 " fs_out = gs_fs;\n"
16738 "}\n"
16739 "\n";
16740 static const GLchar* fs_tested = "#version 430 core\n"
16741 "#extension GL_ARB_enhanced_layouts : require\n"
16742 "\n"
16743 "VAR_DEFINITION"
16744 "\n"
16745 "in vec4 gs_fs;\n"
16746 "out vec4 fs_out;\n"
16747 "\n"
16748 "void main()\n"
16749 "{\n"
16750 " vec4 result = gs_fs;\n"
16751 "\n"
16752 "VARIABLE_USE"
16753 "\n"
16754 " fs_out += result;\n"
16755 "}\n"
16756 "\n";
16757 static const GLchar* gs = "#version 430 core\n"
16758 "#extension GL_ARB_enhanced_layouts : require\n"
16759 "\n"
16760 "layout(points) in;\n"
16761 "layout(triangle_strip, max_vertices = 4) out;\n"
16762 "\n"
16763 "in vec4 tes_gs[];\n"
16764 "out vec4 gs_fs;\n"
16765 "\n"
16766 "void main()\n"
16767 "{\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 " gs_fs = tes_gs[0];\n"
16775 " gl_Position = vec4(1, -1, 0, 1);\n"
16776 " EmitVertex();\n"
16777 " gs_fs = tes_gs[0];\n"
16778 " gl_Position = vec4(1, 1, 0, 1);\n"
16779 " EmitVertex();\n"
16780 "}\n"
16781 "\n";
16782 static const GLchar* gs_tested = "#version 430 core\n"
16783 "#extension GL_ARB_enhanced_layouts : require\n"
16784 "\n"
16785 "layout(points) in;\n"
16786 "layout(triangle_strip, max_vertices = 4) out;\n"
16787 "\n"
16788 "VAR_DEFINITION"
16789 "\n"
16790 "in vec4 tes_gs[];\n"
16791 "out vec4 gs_fs;\n"
16792 "\n"
16793 "void main()\n"
16794 "{\n"
16795 " vec4 result = tes_gs[0];\n"
16796 "\n"
16797 "VARIABLE_USE"
16798 "\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 " gs_fs = result;\n"
16806 " gl_Position = vec4(1, -1, 0, 1);\n"
16807 " EmitVertex();\n"
16808 " gs_fs = result;\n"
16809 " gl_Position = vec4(1, 1, 0, 1);\n"
16810 " EmitVertex();\n"
16811 "}\n"
16812 "\n";
16813 static const GLchar* tcs = "#version 430 core\n"
16814 "#extension GL_ARB_enhanced_layouts : require\n"
16815 "\n"
16816 "layout(vertices = 1) out;\n"
16817 "\n"
16818 "in vec4 vs_tcs[];\n"
16819 "out vec4 tcs_tes[];\n"
16820 "\n"
16821 "void main()\n"
16822 "{\n"
16823 "\n"
16824 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
16825 "\n"
16826 " gl_TessLevelOuter[0] = 1.0;\n"
16827 " gl_TessLevelOuter[1] = 1.0;\n"
16828 " gl_TessLevelOuter[2] = 1.0;\n"
16829 " gl_TessLevelOuter[3] = 1.0;\n"
16830 " gl_TessLevelInner[0] = 1.0;\n"
16831 " gl_TessLevelInner[1] = 1.0;\n"
16832 "}\n"
16833 "\n";
16834 static const GLchar* tcs_tested = "#version 430 core\n"
16835 "#extension GL_ARB_enhanced_layouts : require\n"
16836 "\n"
16837 "layout(vertices = 1) out;\n"
16838 "\n"
16839 "VAR_DEFINITION"
16840 "\n"
16841 "in vec4 vs_tcs[];\n"
16842 "out vec4 tcs_tes[];\n"
16843 "\n"
16844 "void main()\n"
16845 "{\n"
16846 " vec4 result = vs_tcs[gl_InvocationID];\n"
16847 "\n"
16848 "VARIABLE_USE"
16849 "\n"
16850 " tcs_tes[gl_InvocationID] = result;\n"
16851 "\n"
16852 " gl_TessLevelOuter[0] = 1.0;\n"
16853 " gl_TessLevelOuter[1] = 1.0;\n"
16854 " gl_TessLevelOuter[2] = 1.0;\n"
16855 " gl_TessLevelOuter[3] = 1.0;\n"
16856 " gl_TessLevelInner[0] = 1.0;\n"
16857 " gl_TessLevelInner[1] = 1.0;\n"
16858 "}\n"
16859 "\n";
16860 static const GLchar* tes = "#version 430 core\n"
16861 "#extension GL_ARB_enhanced_layouts : require\n"
16862 "\n"
16863 "layout(isolines, point_mode) in;\n"
16864 "\n"
16865 "in vec4 tcs_tes[];\n"
16866 "out vec4 tes_gs;\n"
16867 "\n"
16868 "void main()\n"
16869 "{\n"
16870 " tes_gs = tcs_tes[0];\n"
16871 "}\n"
16872 "\n";
16873 static const GLchar* tes_tested = "#version 430 core\n"
16874 "#extension GL_ARB_enhanced_layouts : require\n"
16875 "\n"
16876 "layout(isolines, point_mode) in;\n"
16877 "\n"
16878 "VAR_DEFINITION"
16879 "\n"
16880 "in vec4 tcs_tes[];\n"
16881 "out vec4 tes_gs;\n"
16882 "\n"
16883 "void main()\n"
16884 "{\n"
16885 " vec4 result = tcs_tes[0];\n"
16886 "\n"
16887 "VARIABLE_USE"
16888 "\n"
16889 " tes_gs += result;\n"
16890 "}\n"
16891 "\n";
16892 static const GLchar* vs = "#version 430 core\n"
16893 "#extension GL_ARB_enhanced_layouts : require\n"
16894 "\n"
16895 "in vec4 in_vs;\n"
16896 "out vec4 vs_tcs;\n"
16897 "\n"
16898 "void main()\n"
16899 "{\n"
16900 " vs_tcs = in_vs;\n"
16901 "}\n"
16902 "\n";
16903 static const GLchar* vs_tested = "#version 430 core\n"
16904 "#extension GL_ARB_enhanced_layouts : require\n"
16905 "\n"
16906 "VAR_DEFINITION"
16907 "\n"
16908 "in vec4 in_vs;\n"
16909 "out vec4 vs_tcs;\n"
16910 "\n"
16911 "void main()\n"
16912 "{\n"
16913 " vec4 result = in_vs;\n"
16914 "\n"
16915 "VARIABLE_USE"
16916 "\n"
16917 " vs_tcs += result;\n"
16918 "}\n"
16919 "\n";
16920
16921 std::string source;
16922 testCase& test_case = m_test_cases[test_case_index];
16923
16924 if (test_case.m_stage == stage)
16925 {
16926 const GLchar* array = "";
16927 GLchar buffer[32];
16928 const GLchar* var_definition = 0;
16929 const GLchar* direction = "in ";
16930 const GLchar* index = "";
16931 size_t position = 0;
16932 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
16933 const GLchar* var_use = 0;
16934 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
16935 const GLchar* flat = "";
16936
16937 if (false == test_case.m_is_input)
16938 {
16939 direction = "out";
16940 storage = Utils::Variable::VARYING_OUTPUT;
16941
16942 if (false == test_case.m_is_array)
16943 {
16944 switch (test_case.m_case)
16945 {
16946 case BLOCK:
16947 var_definition = block_definition_one;
16948 var_use = member_output_use_one;
16949 break;
16950 case MATRIX:
16951 case DVEC3_DVEC4:
16952 var_definition = matrix_dvec3_dvec4_definition_one;
16953 var_use = matrix_dvec3_dvec4_output_use_one;
16954 break;
16955 case STRUCT:
16956 var_definition = struct_definition_one;
16957 var_use = member_output_use_one;
16958 break;
16959 default:
16960 TCU_FAIL("Invalid enum");
16961 }
16962 }
16963 else
16964 {
16965 switch (test_case.m_case)
16966 {
16967 case BLOCK:
16968 var_definition = block_definition_arr;
16969 var_use = member_output_use_arr;
16970 break;
16971 case MATRIX:
16972 case DVEC3_DVEC4:
16973 var_definition = matrix_dvec3_dvec4_definition_arr;
16974 var_use = matrix_dvec3_dvec4_output_use_arr;
16975 break;
16976 case STRUCT:
16977 var_definition = struct_definition_arr;
16978 var_use = member_output_use_arr;
16979 break;
16980 default:
16981 TCU_FAIL("Invalid enum");
16982 }
16983 }
16984 }
16985 else
16986 {
16987 if (false == test_case.m_is_array)
16988 {
16989 switch (test_case.m_case)
16990 {
16991 case BLOCK:
16992 var_definition = block_definition_one;
16993 var_use = Utils::Shader::VERTEX == stage ? member_input_use_one : "\n";
16994 break;
16995 case MATRIX:
16996 case DVEC3_DVEC4:
16997 var_definition = matrix_dvec3_dvec4_definition_one;
16998 var_use = Utils::Shader::VERTEX == stage ? matrix_dvec3_dvec4_input_use_one : "\n";
16999 break;
17000 case STRUCT:
17001 var_definition = struct_definition_one;
17002 var_use = Utils::Shader::VERTEX == stage ? member_input_use_one : "\n";
17003 break;
17004 default:
17005 TCU_FAIL("Invalid enum");
17006 }
17007 }
17008 else
17009 {
17010 switch (test_case.m_case)
17011 {
17012 case BLOCK:
17013 var_definition = block_definition_arr;
17014 var_use = Utils::Shader::VERTEX == stage ? member_input_use_arr : "\n";
17015 break;
17016 case MATRIX:
17017 case DVEC3_DVEC4:
17018 var_definition = matrix_dvec3_dvec4_definition_arr;
17019 var_use = Utils::Shader::VERTEX == stage ? matrix_dvec3_dvec4_input_use_arr : "\n";
17020 break;
17021 case STRUCT:
17022 var_definition = struct_definition_arr;
17023 var_use = Utils::Shader::VERTEX == stage ? member_input_use_arr : "\n";
17024 break;
17025 default:
17026 TCU_FAIL("Invalid enum");
17027 }
17028 }
17029 }
17030
17031 if (isFlatRequired(stage, test_case.m_type, storage))
17032 {
17033 flat = "flat";
17034 }
17035
17036 #if DEBUG_NEG_REMOVE_ERROR
17037 sprintf(buffer, " /* , component = %d */", test_case.m_component);
17038 #else
17039 sprintf(buffer, ", component = %d", test_case.m_component);
17040 #endif /* DEBUG_NEG_REMOVE_ERROR */
17041
17042 switch (stage)
17043 {
17044 case Utils::Shader::FRAGMENT:
17045 source = fs_tested;
17046 break;
17047 case Utils::Shader::GEOMETRY:
17048 source = gs_tested;
17049 array = test_case.m_is_input ? "[]" : "";
17050 index = test_case.m_is_input ? "[0]" : "";
17051 break;
17052 case Utils::Shader::TESS_CTRL:
17053 source = tcs_tested;
17054 array = "[]";
17055 index = "[gl_InvocationID]";
17056 break;
17057 case Utils::Shader::TESS_EVAL:
17058 source = tes_tested;
17059 array = test_case.m_is_input ? "[]" : "";
17060 index = test_case.m_is_input ? "[0]" : "";
17061 break;
17062 case Utils::Shader::VERTEX:
17063 source = vs_tested;
17064 break;
17065 default:
17066 TCU_FAIL("Invalid enum");
17067 }
17068
17069 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17070 position = 0;
17071 Utils::replaceToken("COMPONENT", position, buffer, source);
17072 Utils::replaceToken("DIRECTION", position, direction, source);
17073 Utils::replaceToken("ARRAY", position, array, source);
17074 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
17075
17076 Utils::replaceAllTokens("FLAT", flat, source);
17077 Utils::replaceAllTokens("TYPE", type_name, source);
17078 Utils::replaceAllTokens("INDEX", index, source);
17079 }
17080 else
17081 {
17082 switch (stage)
17083 {
17084 case Utils::Shader::FRAGMENT:
17085 source = fs;
17086 break;
17087 case Utils::Shader::GEOMETRY:
17088 source = gs;
17089 break;
17090 case Utils::Shader::TESS_CTRL:
17091 source = tcs;
17092 break;
17093 case Utils::Shader::TESS_EVAL:
17094 source = tes;
17095 break;
17096 case Utils::Shader::VERTEX:
17097 source = vs;
17098 break;
17099 default:
17100 TCU_FAIL("Invalid enum");
17101 }
17102 }
17103
17104 return source;
17105 }
17106
17107 /** Get description of test case
17108 *
17109 * @param test_case_index Index of test case
17110 *
17111 * @return Test case description
17112 **/
17113 std::string VaryingComponentOfInvalidTypeTest::getTestCaseName(GLuint test_case_index)
17114 {
17115 std::stringstream stream;
17116 testCase& test_case = m_test_cases[test_case_index];
17117
17118 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17119 << " type: " << test_case.m_type.GetGLSLTypeName();
17120
17121 if (true == test_case.m_is_array)
17122 {
17123 stream << "[1]";
17124 }
17125
17126 stream << ", direction: ";
17127
17128 if (true == test_case.m_is_input)
17129 {
17130 stream << "input";
17131 }
17132 else
17133 {
17134 stream << "output";
17135 }
17136
17137 stream << ", component: " << test_case.m_component;
17138
17139 return stream.str();
17140 }
17141
17142 /** Get number of test cases
17143 *
17144 * @return Number of test cases
17145 **/
17146 GLuint VaryingComponentOfInvalidTypeTest::getTestCaseNumber()
17147 {
17148 return static_cast<GLuint>(m_test_cases.size());
17149 }
17150
17151 /** Selects if "compute" stage is relevant for test
17152 *
17153 * @param ignored
17154 *
17155 * @return false
17156 **/
17157 bool VaryingComponentOfInvalidTypeTest::isComputeRelevant(GLuint /* test_case_index */)
17158 {
17159 return false;
17160 }
17161
17162 /** Prepare all test cases
17163 *
17164 **/
17165 void VaryingComponentOfInvalidTypeTest::testInit()
17166 {
17167 const GLuint n_types = getTypesNumber();
17168
17169 for (GLuint i = 0; i < n_types; ++i)
17170 {
17171 const Utils::Type& type = getType(i);
17172 const std::vector<GLuint>& valid_components = type.GetValidComponents();
17173
17174 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17175 {
17176 if (Utils::Shader::COMPUTE == stage)
17177 {
17178 continue;
17179 }
17180
17181 /* matrices */
17182 if (1 != type.m_n_columns)
17183 {
17184 testCase test_case_in_arr = { MATRIX, 0, true, true, (Utils::Shader::STAGES)stage, type };
17185 testCase test_case_in_one = { MATRIX, 0, false, true, (Utils::Shader::STAGES)stage, type };
17186 testCase test_case_out_arr = { MATRIX, 0, true, false, (Utils::Shader::STAGES)stage, type };
17187 testCase test_case_out_one = { MATRIX, 0, false, false, (Utils::Shader::STAGES)stage, type };
17188
17189 m_test_cases.push_back(test_case_in_arr);
17190 m_test_cases.push_back(test_case_in_one);
17191
17192 if (Utils::Shader::FRAGMENT != stage)
17193 {
17194 m_test_cases.push_back(test_case_out_arr);
17195 m_test_cases.push_back(test_case_out_one);
17196 }
17197 }
17198 else if (Utils::Type::Double == type.m_basic_type && 2 < type.m_n_rows) /* dvec3 and dvec4 */
17199 {
17200 testCase test_case_in_arr = { DVEC3_DVEC4, 0, true, true, (Utils::Shader::STAGES)stage, type };
17201 testCase test_case_in_one = { DVEC3_DVEC4, 0, false, true, (Utils::Shader::STAGES)stage, type };
17202 testCase test_case_out_arr = { DVEC3_DVEC4, 0, true, false, (Utils::Shader::STAGES)stage, type };
17203 testCase test_case_out_one = { DVEC3_DVEC4, 0, false, false, (Utils::Shader::STAGES)stage, type };
17204
17205 m_test_cases.push_back(test_case_in_arr);
17206 m_test_cases.push_back(test_case_in_one);
17207
17208 if (Utils::Shader::FRAGMENT != stage)
17209 {
17210 m_test_cases.push_back(test_case_out_arr);
17211 m_test_cases.push_back(test_case_out_one);
17212 }
17213 }
17214 else
17215 {
17216 if (valid_components.empty())
17217 {
17218 TCU_FAIL("Unhandled type");
17219 }
17220
17221 for (GLuint c = BLOCK; c < MAX_CASES; ++c)
17222 {
17223 testCase test_case_in_arr = { (CASES)c, valid_components.back(), true,
17224 true, (Utils::Shader::STAGES)stage, type };
17225 testCase test_case_in_one = { (CASES)c, valid_components.back(), false,
17226 true, (Utils::Shader::STAGES)stage, type };
17227 testCase test_case_out_arr = { (CASES)c, valid_components.back(), true,
17228 false, (Utils::Shader::STAGES)stage, type };
17229 testCase test_case_out_one = { (CASES)c, valid_components.back(), false,
17230 false, (Utils::Shader::STAGES)stage, type };
17231
17232 if (Utils::Shader::VERTEX != stage)
17233 {
17234 m_test_cases.push_back(test_case_in_arr);
17235 m_test_cases.push_back(test_case_in_one);
17236 }
17237
17238 if (Utils::Shader::FRAGMENT != stage)
17239 {
17240 m_test_cases.push_back(test_case_out_arr);
17241 m_test_cases.push_back(test_case_out_one);
17242 }
17243 }
17244 }
17245 }
17246 }
17247 }
17248
17249 /** Constructor
17250 *
17251 * @param context Test framework context
17252 **/
17253 InputComponentAliasingTest::InputComponentAliasingTest(deqp::Context& context)
17254 : NegativeTestBase(context, "input_component_aliasing",
17255 "Test verifies that compiler reports component aliasing as error")
17256 {
17257 }
17258
17259 /** Source for given test case and stage
17260 *
17261 * @param test_case_index Index of test case
17262 * @param stage Shader stage
17263 *
17264 * @return Shader source
17265 **/
17266 std::string InputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
17267 {
17268 static const GLchar* var_definition =
17269 "layout (location = 1, component = COMPONENT) FLAT in TYPE gohanARRAY;\n"
17270 #if DEBUG_NEG_REMOVE_ERROR
17271 "/* layout (location = 1, component = COMPONENT) */ FLAT in TYPE gotenARRAY;\n";
17272 #else
17273 "layout (location = 1, component = COMPONENT) FLAT in TYPE gotenARRAY;\n";
17274 #endif /* DEBUG_NEG_REMOVE_ERROR */
17275 static const GLchar* test_one = " if (TYPE(0) == gohanINDEX)\n"
17276 " {\n"
17277 " result += vec4(1, 0.5, 0.25, 0.125);\n"
17278 " }\n";
17279 static const GLchar* fs = "#version 430 core\n"
17280 "#extension GL_ARB_enhanced_layouts : require\n"
17281 "\n"
17282 "in vec4 gs_fs;\n"
17283 "out vec4 fs_out;\n"
17284 "\n"
17285 "void main()\n"
17286 "{\n"
17287 " fs_out = gs_fs;\n"
17288 "}\n"
17289 "\n";
17290 static const GLchar* fs_tested = "#version 430 core\n"
17291 "#extension GL_ARB_enhanced_layouts : require\n"
17292 "\n"
17293 "VAR_DEFINITION"
17294 "\n"
17295 "in vec4 gs_fs;\n"
17296 "out vec4 fs_out;\n"
17297 "\n"
17298 "void main()\n"
17299 "{\n"
17300 " vec4 result = gs_fs;\n"
17301 "\n"
17302 "VARIABLE_USE"
17303 "\n"
17304 " fs_out += result;\n"
17305 "}\n"
17306 "\n";
17307 static const GLchar* gs = "#version 430 core\n"
17308 "#extension GL_ARB_enhanced_layouts : require\n"
17309 "\n"
17310 "layout(points) in;\n"
17311 "layout(triangle_strip, max_vertices = 4) out;\n"
17312 "\n"
17313 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17314 "\n"
17315 "in vec4 tes_gs[];\n"
17316 "out vec4 gs_fs;\n"
17317 "\n"
17318 "void main()\n"
17319 "{\n"
17320 " gohan = TYPE(1);\n"
17321 "\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 " gs_fs = tes_gs[0];\n"
17329 " gl_Position = vec4(1, -1, 0, 1);\n"
17330 " EmitVertex();\n"
17331 " gs_fs = tes_gs[0];\n"
17332 " gl_Position = vec4(1, 1, 0, 1);\n"
17333 " EmitVertex();\n"
17334 "}\n"
17335 "\n";
17336 static const GLchar* gs_tested = "#version 430 core\n"
17337 "#extension GL_ARB_enhanced_layouts : require\n"
17338 "\n"
17339 "layout(points) in;\n"
17340 "layout(triangle_strip, max_vertices = 4) out;\n"
17341 "\n"
17342 "VAR_DEFINITION"
17343 "\n"
17344 "in vec4 tes_gs[];\n"
17345 "out vec4 gs_fs;\n"
17346 "\n"
17347 "void main()\n"
17348 "{\n"
17349 " vec4 result = tes_gs[0];\n"
17350 "\n"
17351 "VARIABLE_USE"
17352 "\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 " gs_fs = result;\n"
17360 " gl_Position = vec4(1, -1, 0, 1);\n"
17361 " EmitVertex();\n"
17362 " gs_fs = result;\n"
17363 " gl_Position = vec4(1, 1, 0, 1);\n"
17364 " EmitVertex();\n"
17365 "}\n"
17366 "\n";
17367 static const GLchar* tcs = "#version 430 core\n"
17368 "#extension GL_ARB_enhanced_layouts : require\n"
17369 "\n"
17370 "layout(vertices = 1) out;\n"
17371 "\n"
17372 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan[];\n"
17373 "\n"
17374 "in vec4 vs_tcs[];\n"
17375 "out vec4 tcs_tes[];\n"
17376 "\n"
17377 "void main()\n"
17378 "{\n"
17379 " gohan[gl_InvocationID] = TYPE(1);\n"
17380 "\n"
17381 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17382 "\n"
17383 " gl_TessLevelOuter[0] = 1.0;\n"
17384 " gl_TessLevelOuter[1] = 1.0;\n"
17385 " gl_TessLevelOuter[2] = 1.0;\n"
17386 " gl_TessLevelOuter[3] = 1.0;\n"
17387 " gl_TessLevelInner[0] = 1.0;\n"
17388 " gl_TessLevelInner[1] = 1.0;\n"
17389 "}\n"
17390 "\n";
17391 static const GLchar* tcs_tested = "#version 430 core\n"
17392 "#extension GL_ARB_enhanced_layouts : require\n"
17393 "\n"
17394 "layout(vertices = 1) out;\n"
17395 "\n"
17396 "VAR_DEFINITION"
17397 "\n"
17398 "in vec4 vs_tcs[];\n"
17399 "out vec4 tcs_tes[];\n"
17400 "\n"
17401 "void main()\n"
17402 "{\n"
17403 " vec4 result = vs_tcs[gl_InvocationID];\n"
17404 "\n"
17405 "VARIABLE_USE"
17406 "\n"
17407 " tcs_tes[gl_InvocationID] = result;\n"
17408 "\n"
17409 " gl_TessLevelOuter[0] = 1.0;\n"
17410 " gl_TessLevelOuter[1] = 1.0;\n"
17411 " gl_TessLevelOuter[2] = 1.0;\n"
17412 " gl_TessLevelOuter[3] = 1.0;\n"
17413 " gl_TessLevelInner[0] = 1.0;\n"
17414 " gl_TessLevelInner[1] = 1.0;\n"
17415 "}\n"
17416 "\n";
17417 static const GLchar* tes = "#version 430 core\n"
17418 "#extension GL_ARB_enhanced_layouts : require\n"
17419 "\n"
17420 "layout(isolines, point_mode) in;\n"
17421 "\n"
17422 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17423 "\n"
17424 "in vec4 tcs_tes[];\n"
17425 "out vec4 tes_gs;\n"
17426 "\n"
17427 "void main()\n"
17428 "{\n"
17429 " gohan = TYPE(1);\n"
17430 "\n"
17431 " tes_gs = tcs_tes[0];\n"
17432 "}\n"
17433 "\n";
17434 static const GLchar* tes_tested = "#version 430 core\n"
17435 "#extension GL_ARB_enhanced_layouts : require\n"
17436 "\n"
17437 "layout(isolines, point_mode) in;\n"
17438 "\n"
17439 "VAR_DEFINITION"
17440 "\n"
17441 "in vec4 tcs_tes[];\n"
17442 "out vec4 tes_gs;\n"
17443 "\n"
17444 "void main()\n"
17445 "{\n"
17446 " vec4 result = tcs_tes[0];\n"
17447 "\n"
17448 "VARIABLE_USE"
17449 "\n"
17450 " tes_gs += result;\n"
17451 "}\n"
17452 "\n";
17453 static const GLchar* vs = "#version 430 core\n"
17454 "#extension GL_ARB_enhanced_layouts : require\n"
17455 "\n"
17456 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohan;\n"
17457 "\n"
17458 "in vec4 in_vs;\n"
17459 "out vec4 vs_tcs;\n"
17460 "\n"
17461 "void main()\n"
17462 "{\n"
17463 " gohan = TYPE(1);\n"
17464 "\n"
17465 " vs_tcs = in_vs;\n"
17466 "}\n"
17467 "\n";
17468 static const GLchar* vs_tested = "#version 430 core\n"
17469 "#extension GL_ARB_enhanced_layouts : require\n"
17470 "\n"
17471 "VAR_DEFINITION"
17472 "\n"
17473 "in vec4 in_vs;\n"
17474 "out vec4 vs_tcs;\n"
17475 "\n"
17476 "void main()\n"
17477 "{\n"
17478 " vec4 result = in_vs;\n"
17479 "\n"
17480 "VARIABLE_USE"
17481 "\n"
17482 " vs_tcs += result;\n"
17483 "}\n"
17484 "\n";
17485
17486 std::string source;
17487 testCase& test_case = m_test_cases[test_case_index];
17488 GLchar buffer_gohan[16];
17489 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
17490
17491 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17492
17493 if (test_case.m_stage == stage)
17494 {
17495 const GLchar* array = "";
17496 GLchar buffer_goten[16];
17497 const GLchar* flat = "";
17498 const GLchar* index = "";
17499 size_t position = 0;
17500 const GLchar* var_use = test_one;
17501
17502 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_INPUT, true))
17503 {
17504 flat = "flat";
17505 }
17506
17507 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17508
17509 switch (stage)
17510 {
17511 case Utils::Shader::FRAGMENT:
17512 source = fs_tested;
17513 break;
17514 case Utils::Shader::GEOMETRY:
17515 source = gs_tested;
17516 array = "[]";
17517 index = "[0]";
17518 break;
17519 case Utils::Shader::TESS_CTRL:
17520 source = tcs_tested;
17521 array = "[]";
17522 index = "[gl_InvocationID]";
17523 break;
17524 case Utils::Shader::TESS_EVAL:
17525 source = tes_tested;
17526 array = "[]";
17527 index = "[0]";
17528 break;
17529 case Utils::Shader::VERTEX:
17530 source = vs_tested;
17531 break;
17532 default:
17533 TCU_FAIL("Invalid enum");
17534 }
17535
17536 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17537 position = 0;
17538 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17539 Utils::replaceToken("ARRAY", position, array, source);
17540 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17541 Utils::replaceToken("ARRAY", position, array, source);
17542 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
17543
17544 Utils::replaceAllTokens("FLAT", flat, source);
17545 Utils::replaceAllTokens("TYPE", type_name, source);
17546 Utils::replaceAllTokens("INDEX", index, source);
17547 }
17548 else
17549 {
17550 const GLchar* flat = "";
17551
17552 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_OUTPUT, true))
17553 {
17554 flat = "flat";
17555 }
17556
17557 switch (stage)
17558 {
17559 case Utils::Shader::FRAGMENT:
17560 source = fs;
17561 break;
17562 case Utils::Shader::GEOMETRY:
17563 source = gs;
17564 break;
17565 case Utils::Shader::TESS_CTRL:
17566 source = tcs;
17567 break;
17568 case Utils::Shader::TESS_EVAL:
17569 source = tes;
17570 break;
17571 case Utils::Shader::VERTEX:
17572 source = vs;
17573 break;
17574 default:
17575 TCU_FAIL("Invalid enum");
17576 }
17577
17578 Utils::replaceAllTokens("FLAT", flat, source);
17579 Utils::replaceAllTokens("COMPONENT", buffer_gohan, source);
17580 Utils::replaceAllTokens("TYPE", type_name, source);
17581 }
17582
17583 return source;
17584 }
17585
17586 /** Get description of test case
17587 *
17588 * @param test_case_index Index of test case
17589 *
17590 * @return Test case description
17591 **/
17592 std::string InputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
17593 {
17594 std::stringstream stream;
17595 testCase& test_case = m_test_cases[test_case_index];
17596
17597 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17598 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
17599 << " & " << test_case.m_component_goten;
17600
17601 return stream.str();
17602 }
17603
17604 /** Get number of test cases
17605 *
17606 * @return Number of test cases
17607 **/
17608 GLuint InputComponentAliasingTest::getTestCaseNumber()
17609 {
17610 return static_cast<GLuint>(m_test_cases.size());
17611 }
17612
17613 /** Selects if "compute" stage is relevant for test
17614 *
17615 * @param ignored
17616 *
17617 * @return false
17618 **/
17619 bool InputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
17620 {
17621 return false;
17622 }
17623
17624 /** Selects if compilation failure is expected result
17625 *
17626 * @param test_case_index Index of test case
17627 *
17628 * @return false for VS that use only single variable, true otherwise
17629 **/
17630 bool InputComponentAliasingTest::isFailureExpected(GLuint test_case_index)
17631 {
17632 testCase& test_case = m_test_cases[test_case_index];
17633
17634 return (Utils::Shader::VERTEX != test_case.m_stage);
17635 }
17636
17637 /** Prepare all test cases
17638 *
17639 **/
17640 void InputComponentAliasingTest::testInit()
17641 {
17642 const GLuint n_types = getTypesNumber();
17643
17644 for (GLuint i = 0; i < n_types; ++i)
17645 {
17646 const Utils::Type& type = getType(i);
17647 const std::vector<GLuint>& valid_components = type.GetValidComponents();
17648
17649 if (valid_components.empty())
17650 {
17651 continue;
17652 }
17653
17654 for (std::vector<GLuint>::const_iterator it_gohan = valid_components.begin();
17655 it_gohan != valid_components.end(); ++it_gohan)
17656 {
17657 const GLuint max_component = *it_gohan + type.GetNumComponents();
17658 for (std::vector<GLuint>::const_iterator it_goten = it_gohan;
17659 it_goten != valid_components.end() && max_component > *it_goten; ++it_goten)
17660 {
17661 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
17662 {
17663 /* Skip compute shader */
17664 if (Utils::Shader::COMPUTE == stage)
17665 {
17666 continue;
17667 }
17668
17669 testCase test_case = { *it_gohan, *it_goten, (Utils::Shader::STAGES)stage, type };
17670
17671 m_test_cases.push_back(test_case);
17672 }
17673 }
17674 }
17675 }
17676 }
17677
17678 /** Constructor
17679 *
17680 * @param context Test framework context
17681 **/
17682 OutputComponentAliasingTest::OutputComponentAliasingTest(deqp::Context& context)
17683 : NegativeTestBase(context, "output_component_aliasing",
17684 "Test verifies that compiler reports component aliasing as error")
17685 {
17686 }
17687
17688 /** Source for given test case and stage
17689 *
17690 * @param test_case_index Index of test case
17691 * @param stage Shader stage
17692 *
17693 * @return Shader source
17694 **/
17695 std::string OutputComponentAliasingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
17696 {
17697 static const GLchar* var_definition =
17698 "layout (location = 1, component = COMPONENT) FLAT out TYPE gohanARRAY;\n"
17699 #if DEBUG_NEG_REMOVE_ERROR
17700 "/* layout (location = 1, component = COMPONENT) */ FLAT out TYPE gotenARRAY;\n";
17701 #else
17702 "layout (location = 1, component = COMPONENT) FLAT out TYPE gotenARRAY;\n";
17703 #endif /* DEBUG_NEG_REMOVE_ERROR */
17704 static const GLchar* l_test = " gohanINDEX = TYPE(1);\n"
17705 " gotenINDEX = TYPE(0);\n";
17706 static const GLchar* fs = "#version 430 core\n"
17707 "#extension GL_ARB_enhanced_layouts : require\n"
17708 "\n"
17709 "in vec4 gs_fs;\n"
17710 "out vec4 fs_out;\n"
17711 "\n"
17712 "void main()\n"
17713 "{\n"
17714 " fs_out = gs_fs;\n"
17715 "}\n"
17716 "\n";
17717 static const GLchar* fs_tested = "#version 430 core\n"
17718 "#extension GL_ARB_enhanced_layouts : require\n"
17719 "\n"
17720 "VAR_DEFINITION"
17721 "\n"
17722 "in vec4 gs_fs;\n"
17723 "out vec4 fs_out;\n"
17724 "\n"
17725 "void main()\n"
17726 "{\n"
17727 " vec4 result = gs_fs;\n"
17728 "\n"
17729 "VARIABLE_USE"
17730 "\n"
17731 " fs_out += result;\n"
17732 "}\n"
17733 "\n";
17734 static const GLchar* gs = "#version 430 core\n"
17735 "#extension GL_ARB_enhanced_layouts : require\n"
17736 "\n"
17737 "layout(points) in;\n"
17738 "layout(triangle_strip, max_vertices = 4) out;\n"
17739 "\n"
17740 "in vec4 tes_gs[];\n"
17741 "out vec4 gs_fs;\n"
17742 "\n"
17743 "void main()\n"
17744 "{\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 " gs_fs = tes_gs[0];\n"
17752 " gl_Position = vec4(1, -1, 0, 1);\n"
17753 " EmitVertex();\n"
17754 " gs_fs = tes_gs[0];\n"
17755 " gl_Position = vec4(1, 1, 0, 1);\n"
17756 " EmitVertex();\n"
17757 "}\n"
17758 "\n";
17759 static const GLchar* gs_tested = "#version 430 core\n"
17760 "#extension GL_ARB_enhanced_layouts : require\n"
17761 "\n"
17762 "layout(points) in;\n"
17763 "layout(triangle_strip, max_vertices = 4) out;\n"
17764 "\n"
17765 "VAR_DEFINITION"
17766 "\n"
17767 "in vec4 tes_gs[];\n"
17768 "out vec4 gs_fs;\n"
17769 "\n"
17770 "void main()\n"
17771 "{\n"
17772 " vec4 result = tes_gs[0];\n"
17773 "\n"
17774 "VARIABLE_USE"
17775 "\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 " gs_fs = result;\n"
17783 " gl_Position = vec4(1, -1, 0, 1);\n"
17784 " EmitVertex();\n"
17785 " gs_fs = result;\n"
17786 " gl_Position = vec4(1, 1, 0, 1);\n"
17787 " EmitVertex();\n"
17788 "}\n"
17789 "\n";
17790 static const GLchar* tcs = "#version 430 core\n"
17791 "#extension GL_ARB_enhanced_layouts : require\n"
17792 "\n"
17793 "layout(vertices = 1) out;\n"
17794 "\n"
17795 "in vec4 vs_tcs[];\n"
17796 "out vec4 tcs_tes[];\n"
17797 "\n"
17798 "void main()\n"
17799 "{\n"
17800 "\n"
17801 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
17802 "\n"
17803 " gl_TessLevelOuter[0] = 1.0;\n"
17804 " gl_TessLevelOuter[1] = 1.0;\n"
17805 " gl_TessLevelOuter[2] = 1.0;\n"
17806 " gl_TessLevelOuter[3] = 1.0;\n"
17807 " gl_TessLevelInner[0] = 1.0;\n"
17808 " gl_TessLevelInner[1] = 1.0;\n"
17809 "}\n"
17810 "\n";
17811 static const GLchar* tcs_tested = "#version 430 core\n"
17812 "#extension GL_ARB_enhanced_layouts : require\n"
17813 "\n"
17814 "layout(vertices = 1) out;\n"
17815 "\n"
17816 "VAR_DEFINITION"
17817 "\n"
17818 "in vec4 vs_tcs[];\n"
17819 "out vec4 tcs_tes[];\n"
17820 "\n"
17821 "void main()\n"
17822 "{\n"
17823 " vec4 result = vs_tcs[gl_InvocationID];\n"
17824 "\n"
17825 "VARIABLE_USE"
17826 "\n"
17827 " tcs_tes[gl_InvocationID] = result;\n"
17828 "\n"
17829 " gl_TessLevelOuter[0] = 1.0;\n"
17830 " gl_TessLevelOuter[1] = 1.0;\n"
17831 " gl_TessLevelOuter[2] = 1.0;\n"
17832 " gl_TessLevelOuter[3] = 1.0;\n"
17833 " gl_TessLevelInner[0] = 1.0;\n"
17834 " gl_TessLevelInner[1] = 1.0;\n"
17835 "}\n"
17836 "\n";
17837 static const GLchar* tes = "#version 430 core\n"
17838 "#extension GL_ARB_enhanced_layouts : require\n"
17839 "\n"
17840 "layout(isolines, point_mode) in;\n"
17841 "\n"
17842 "in vec4 tcs_tes[];\n"
17843 "out vec4 tes_gs;\n"
17844 "\n"
17845 "void main()\n"
17846 "{\n"
17847 " tes_gs = tcs_tes[0];\n"
17848 "}\n"
17849 "\n";
17850 static const GLchar* tes_tested = "#version 430 core\n"
17851 "#extension GL_ARB_enhanced_layouts : require\n"
17852 "\n"
17853 "layout(isolines, point_mode) in;\n"
17854 "\n"
17855 "VAR_DEFINITION"
17856 "\n"
17857 "in vec4 tcs_tes[];\n"
17858 "out vec4 tes_gs;\n"
17859 "\n"
17860 "void main()\n"
17861 "{\n"
17862 " vec4 result = tcs_tes[0];\n"
17863 "\n"
17864 "VARIABLE_USE"
17865 "\n"
17866 " tes_gs += result;\n"
17867 "}\n"
17868 "\n";
17869 static const GLchar* vs = "#version 430 core\n"
17870 "#extension GL_ARB_enhanced_layouts : require\n"
17871 "\n"
17872 "in vec4 in_vs;\n"
17873 "out vec4 vs_tcs;\n"
17874 "\n"
17875 "void main()\n"
17876 "{\n"
17877 " vs_tcs = in_vs;\n"
17878 "}\n"
17879 "\n";
17880 static const GLchar* vs_tested = "#version 430 core\n"
17881 "#extension GL_ARB_enhanced_layouts : require\n"
17882 "\n"
17883 "VAR_DEFINITION"
17884 "\n"
17885 "in vec4 in_vs;\n"
17886 "out vec4 vs_tcs;\n"
17887 "\n"
17888 "void main()\n"
17889 "{\n"
17890 " vec4 result = in_vs;\n"
17891 "\n"
17892 "VARIABLE_USE"
17893 "\n"
17894 " vs_tcs += result;\n"
17895 "}\n"
17896 "\n";
17897
17898 std::string source;
17899 testCase& test_case = m_test_cases[test_case_index];
17900
17901 if (test_case.m_stage == stage)
17902 {
17903 const GLchar* array = "";
17904 GLchar buffer_gohan[16];
17905 GLchar buffer_goten[16];
17906 const GLchar* flat = "";
17907 const GLchar* index = "";
17908 size_t position = 0;
17909 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
17910
17911 if (isFlatRequired(stage, test_case.m_type, Utils::Variable::VARYING_OUTPUT))
17912 {
17913 flat = "flat";
17914 }
17915
17916 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
17917 sprintf(buffer_goten, "%d", test_case.m_component_goten);
17918
17919 switch (stage)
17920 {
17921 case Utils::Shader::FRAGMENT:
17922 source = fs_tested;
17923 break;
17924 case Utils::Shader::GEOMETRY:
17925 source = gs_tested;
17926 break;
17927 case Utils::Shader::TESS_CTRL:
17928 source = tcs_tested;
17929 array = "[]";
17930 index = "[gl_InvocationID]";
17931 break;
17932 case Utils::Shader::TESS_EVAL:
17933 source = tes_tested;
17934 break;
17935 case Utils::Shader::VERTEX:
17936 source = vs_tested;
17937 break;
17938 default:
17939 TCU_FAIL("Invalid enum");
17940 }
17941
17942 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
17943 position = 0;
17944 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
17945 Utils::replaceToken("FLAT", position, flat, source);
17946 Utils::replaceToken("ARRAY", position, array, source);
17947 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
17948 Utils::replaceToken("FLAT", position, flat, source);
17949 Utils::replaceToken("ARRAY", position, array, source);
17950 Utils::replaceToken("VARIABLE_USE", position, l_test, source);
17951
17952 Utils::replaceAllTokens("TYPE", type_name, source);
17953 Utils::replaceAllTokens("INDEX", index, source);
17954 }
17955 else
17956 {
17957 switch (stage)
17958 {
17959 case Utils::Shader::FRAGMENT:
17960 source = fs;
17961 break;
17962 case Utils::Shader::GEOMETRY:
17963 source = gs;
17964 break;
17965 case Utils::Shader::TESS_CTRL:
17966 source = tcs;
17967 break;
17968 case Utils::Shader::TESS_EVAL:
17969 source = tes;
17970 break;
17971 case Utils::Shader::VERTEX:
17972 source = vs;
17973 break;
17974 default:
17975 TCU_FAIL("Invalid enum");
17976 }
17977 }
17978
17979 return source;
17980 }
17981
17982 /** Get description of test case
17983 *
17984 * @param test_case_index Index of test case
17985 *
17986 * @return Test case description
17987 **/
17988 std::string OutputComponentAliasingTest::getTestCaseName(GLuint test_case_index)
17989 {
17990 std::stringstream stream;
17991 testCase& test_case = m_test_cases[test_case_index];
17992
17993 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
17994 << " type: " << test_case.m_type.GetGLSLTypeName() << ", components: " << test_case.m_component_gohan
17995 << " & " << test_case.m_component_goten;
17996
17997 return stream.str();
17998 }
17999
18000 /** Get number of test cases
18001 *
18002 * @return Number of test cases
18003 **/
18004 GLuint OutputComponentAliasingTest::getTestCaseNumber()
18005 {
18006 return static_cast<GLuint>(m_test_cases.size());
18007 }
18008
18009 /** Selects if "compute" stage is relevant for test
18010 *
18011 * @param ignored
18012 *
18013 * @return false
18014 **/
18015 bool OutputComponentAliasingTest::isComputeRelevant(GLuint /* test_case_index */)
18016 {
18017 return false;
18018 }
18019
18020 /** Prepare all test cases
18021 *
18022 **/
18023 void OutputComponentAliasingTest::testInit()
18024 {
18025 const GLuint n_types = getTypesNumber();
18026
18027 for (GLuint i = 0; i < n_types; ++i)
18028 {
18029 const Utils::Type& type = getType(i);
18030 const std::vector<GLuint>& valid_components = type.GetValidComponents();
18031
18032 if (valid_components.empty())
18033 {
18034 continue;
18035 }
18036
18037 for (std::vector<GLuint>::const_iterator it_gohan = valid_components.begin();
18038 it_gohan != valid_components.end(); ++it_gohan)
18039 {
18040 const GLuint max_component = *it_gohan + type.GetNumComponents();
18041 for (std::vector<GLuint>::const_iterator it_goten = it_gohan;
18042 it_goten != valid_components.end() && max_component > *it_goten; ++it_goten)
18043 {
18044 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18045 {
18046 /* Skip compute shader */
18047 if (Utils::Shader::COMPUTE == stage)
18048 {
18049 continue;
18050 }
18051
18052 if ((Utils::Shader::FRAGMENT == stage) && (Utils::Type::Double == type.m_basic_type))
18053 {
18054 continue;
18055 }
18056
18057 testCase test_case = { *it_gohan, *it_goten, (Utils::Shader::STAGES)stage, type };
18058
18059 m_test_cases.push_back(test_case);
18060 }
18061 }
18062 }
18063 }
18064 }
18065
18066 /** Constructor
18067 *
18068 * @param context Test framework context
18069 **/
18070 VaryingLocationAliasingWithMixedTypesTest::VaryingLocationAliasingWithMixedTypesTest(deqp::Context& context)
18071 : NegativeTestBase(context, "varying_location_aliasing_with_mixed_types",
18072 "Test verifies that compiler reports error when float/int types are mixed at one location")
18073 {
18074 }
18075
18076 /** Source for given test case and stage
18077 *
18078 * @param test_case_index Index of test case
18079 * @param stage Shader stage
18080 *
18081 * @return Shader source
18082 **/
18083 std::string VaryingLocationAliasingWithMixedTypesTest::getShaderSource(GLuint test_case_index,
18084 Utils::Shader::STAGES stage)
18085 {
18086 static const GLchar* var_definition =
18087 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gohanARRAY;\n"
18088 "layout (location = 1, component = COMPONENT) FLAT DIRECTION TYPE gotenARRAY;\n";
18089 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
18090 " (TYPE(1) == gotenINDEX) )\n"
18091 " {\n"
18092 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18093 " }\n";
18094 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
18095 " gotenINDEX = TYPE(1);\n"
18096 " if (vec4(0) == result)\n"
18097 " {\n"
18098 " gohanINDEX = TYPE(1);\n"
18099 " gotenINDEX = TYPE(0);\n"
18100 " }\n";
18101 static const GLchar* fs = "#version 430 core\n"
18102 "#extension GL_ARB_enhanced_layouts : require\n"
18103 "\n"
18104 "in vec4 gs_fs;\n"
18105 "out vec4 fs_out;\n"
18106 "\n"
18107 "void main()\n"
18108 "{\n"
18109 " fs_out = gs_fs;\n"
18110 "}\n"
18111 "\n";
18112 static const GLchar* fs_tested = "#version 430 core\n"
18113 "#extension GL_ARB_enhanced_layouts : require\n"
18114 "\n"
18115 "VAR_DEFINITION"
18116 "\n"
18117 "in vec4 gs_fs;\n"
18118 "out vec4 fs_out;\n"
18119 "\n"
18120 "void main()\n"
18121 "{\n"
18122 " vec4 result = gs_fs;\n"
18123 "\n"
18124 "VARIABLE_USE"
18125 "\n"
18126 " fs_out += result;\n"
18127 "}\n"
18128 "\n";
18129 static const GLchar* gs = "#version 430 core\n"
18130 "#extension GL_ARB_enhanced_layouts : require\n"
18131 "\n"
18132 "layout(points) in;\n"
18133 "layout(triangle_strip, max_vertices = 4) out;\n"
18134 "\n"
18135 "in vec4 tes_gs[];\n"
18136 "out vec4 gs_fs;\n"
18137 "\n"
18138 "void main()\n"
18139 "{\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 " gs_fs = tes_gs[0];\n"
18147 " gl_Position = vec4(1, -1, 0, 1);\n"
18148 " EmitVertex();\n"
18149 " gs_fs = tes_gs[0];\n"
18150 " gl_Position = vec4(1, 1, 0, 1);\n"
18151 " EmitVertex();\n"
18152 "}\n"
18153 "\n";
18154 static const GLchar* gs_tested = "#version 430 core\n"
18155 "#extension GL_ARB_enhanced_layouts : require\n"
18156 "\n"
18157 "layout(points) in;\n"
18158 "layout(triangle_strip, max_vertices = 4) out;\n"
18159 "\n"
18160 "VAR_DEFINITION"
18161 "\n"
18162 "in vec4 tes_gs[];\n"
18163 "out vec4 gs_fs;\n"
18164 "\n"
18165 "void main()\n"
18166 "{\n"
18167 " vec4 result = tes_gs[0];\n"
18168 "\n"
18169 "VARIABLE_USE"
18170 "\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 " gs_fs = result;\n"
18178 " gl_Position = vec4(1, -1, 0, 1);\n"
18179 " EmitVertex();\n"
18180 " gs_fs = result;\n"
18181 " gl_Position = vec4(1, 1, 0, 1);\n"
18182 " EmitVertex();\n"
18183 "}\n"
18184 "\n";
18185 static const GLchar* tcs = "#version 430 core\n"
18186 "#extension GL_ARB_enhanced_layouts : require\n"
18187 "\n"
18188 "layout(vertices = 1) out;\n"
18189 "\n"
18190 "in vec4 vs_tcs[];\n"
18191 "out vec4 tcs_tes[];\n"
18192 "\n"
18193 "void main()\n"
18194 "{\n"
18195 "\n"
18196 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18197 "\n"
18198 " gl_TessLevelOuter[0] = 1.0;\n"
18199 " gl_TessLevelOuter[1] = 1.0;\n"
18200 " gl_TessLevelOuter[2] = 1.0;\n"
18201 " gl_TessLevelOuter[3] = 1.0;\n"
18202 " gl_TessLevelInner[0] = 1.0;\n"
18203 " gl_TessLevelInner[1] = 1.0;\n"
18204 "}\n"
18205 "\n";
18206 static const GLchar* tcs_tested = "#version 430 core\n"
18207 "#extension GL_ARB_enhanced_layouts : require\n"
18208 "\n"
18209 "layout(vertices = 1) out;\n"
18210 "\n"
18211 "VAR_DEFINITION"
18212 "\n"
18213 "in vec4 vs_tcs[];\n"
18214 "out vec4 tcs_tes[];\n"
18215 "\n"
18216 "void main()\n"
18217 "{\n"
18218 " vec4 result = vs_tcs[gl_InvocationID];\n"
18219 "\n"
18220 "VARIABLE_USE"
18221 "\n"
18222 " tcs_tes[gl_InvocationID] = result;\n"
18223 "\n"
18224 " gl_TessLevelOuter[0] = 1.0;\n"
18225 " gl_TessLevelOuter[1] = 1.0;\n"
18226 " gl_TessLevelOuter[2] = 1.0;\n"
18227 " gl_TessLevelOuter[3] = 1.0;\n"
18228 " gl_TessLevelInner[0] = 1.0;\n"
18229 " gl_TessLevelInner[1] = 1.0;\n"
18230 "}\n"
18231 "\n";
18232 static const GLchar* tes = "#version 430 core\n"
18233 "#extension GL_ARB_enhanced_layouts : require\n"
18234 "\n"
18235 "layout(isolines, point_mode) in;\n"
18236 "\n"
18237 "in vec4 tcs_tes[];\n"
18238 "out vec4 tes_gs;\n"
18239 "\n"
18240 "void main()\n"
18241 "{\n"
18242 " tes_gs = tcs_tes[0];\n"
18243 "}\n"
18244 "\n";
18245 static const GLchar* tes_tested = "#version 430 core\n"
18246 "#extension GL_ARB_enhanced_layouts : require\n"
18247 "\n"
18248 "layout(isolines, point_mode) in;\n"
18249 "\n"
18250 "VAR_DEFINITION"
18251 "\n"
18252 "in vec4 tcs_tes[];\n"
18253 "out vec4 tes_gs;\n"
18254 "\n"
18255 "void main()\n"
18256 "{\n"
18257 " vec4 result = tcs_tes[0];\n"
18258 "\n"
18259 "VARIABLE_USE"
18260 "\n"
18261 " tes_gs += result;\n"
18262 "}\n"
18263 "\n";
18264 static const GLchar* vs = "#version 430 core\n"
18265 "#extension GL_ARB_enhanced_layouts : require\n"
18266 "\n"
18267 "in vec4 in_vs;\n"
18268 "out vec4 vs_tcs;\n"
18269 "\n"
18270 "void main()\n"
18271 "{\n"
18272 " vs_tcs = in_vs;\n"
18273 "}\n"
18274 "\n";
18275 static const GLchar* vs_tested = "#version 430 core\n"
18276 "#extension GL_ARB_enhanced_layouts : require\n"
18277 "\n"
18278 "VAR_DEFINITION"
18279 "\n"
18280 "in vec4 in_vs;\n"
18281 "out vec4 vs_tcs;\n"
18282 "\n"
18283 "void main()\n"
18284 "{\n"
18285 " vec4 result = in_vs;\n"
18286 "\n"
18287 "VARIABLE_USE"
18288 "\n"
18289 " vs_tcs += result;\n"
18290 "}\n"
18291 "\n";
18292
18293 std::string source;
18294 testCase& test_case = m_test_cases[test_case_index];
18295
18296 if (test_case.m_stage == stage)
18297 {
18298 const GLchar* array = "";
18299 GLchar buffer_gohan[16];
18300 GLchar buffer_goten[16];
18301 const GLchar* direction = "in ";
18302 const GLchar* flat_gohan = "";
18303 const GLchar* flat_goten = "";
18304 const GLchar* index = "";
18305 size_t position = 0;
18306 size_t temp;
18307 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18308 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18309 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
18310 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
18311
18312 if (false == test_case.m_is_input)
18313 {
18314 direction = "out";
18315 storage = Utils::Variable::VARYING_OUTPUT;
18316 var_use = output_use;
18317 }
18318
18319 /* If the interpolation qualifier would be different, the test
18320 * would fail and we are testing here mixed types, not mixed
18321 * interpolation qualifiers.
18322 */
18323 if (isFlatRequired(stage, test_case.m_type_gohan, storage) ||
18324 isFlatRequired(stage, test_case.m_type_goten, storage))
18325 {
18326 flat_gohan = "flat";
18327 flat_goten = "flat";
18328 }
18329
18330 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18331 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18332
18333 #if DEBUG_NEG_REMOVE_ERROR
18334 type_goten_name = Utils::Type::GetType(test_case.m_type_gohan.m_basic_type, 1, 1).GetGLSLTypeName();
18335 if (Utils::Type::Double == test_case.m_type_gohan.m_basic_type)
18336 {
18337 sprintf(buffer_goten, "%d", 0 == test_case.m_component_gohan ? 2 : 0);
18338 }
18339 #endif /* DEBUG_NEG_REMOVE_ERROR */
18340
18341 switch (stage)
18342 {
18343 case Utils::Shader::FRAGMENT:
18344 source = fs_tested;
18345 break;
18346 case Utils::Shader::GEOMETRY:
18347 source = gs_tested;
18348 array = test_case.m_is_input ? "[]" : "";
18349 index = test_case.m_is_input ? "[0]" : "";
18350 break;
18351 case Utils::Shader::TESS_CTRL:
18352 source = tcs_tested;
18353 array = "[]";
18354 index = "[gl_InvocationID]";
18355 break;
18356 case Utils::Shader::TESS_EVAL:
18357 source = tes_tested;
18358 array = test_case.m_is_input ? "[]" : "";
18359 index = test_case.m_is_input ? "[0]" : "";
18360 break;
18361 case Utils::Shader::VERTEX:
18362 source = vs_tested;
18363 break;
18364 default:
18365 TCU_FAIL("Invalid enum");
18366 }
18367
18368 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18369 position = 0;
18370 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18371 Utils::replaceToken("FLAT", position, flat_gohan, source);
18372 Utils::replaceToken("DIRECTION", position, direction, source);
18373 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18374 Utils::replaceToken("ARRAY", position, array, source);
18375 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18376 Utils::replaceToken("FLAT", position, flat_goten, source);
18377 Utils::replaceToken("DIRECTION", position, direction, source);
18378 Utils::replaceToken("TYPE", position, type_goten_name, source);
18379 Utils::replaceToken("ARRAY", position, array, source);
18380
18381 temp = position;
18382 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18383 position = temp;
18384 if (!test_case.m_is_input)
18385 {
18386 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18387 Utils::replaceToken("TYPE", position, type_goten_name, source);
18388 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18389 Utils::replaceToken("TYPE", position, type_goten_name, source);
18390 }
18391 else if (Utils::Shader::VERTEX == stage)
18392 {
18393 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18394 Utils::replaceToken("TYPE", position, type_goten_name, source);
18395 }
18396
18397 Utils::replaceAllTokens("INDEX", index, source);
18398 }
18399 else
18400 {
18401 switch (stage)
18402 {
18403 case Utils::Shader::FRAGMENT:
18404 source = fs;
18405 break;
18406 case Utils::Shader::GEOMETRY:
18407 source = gs;
18408 break;
18409 case Utils::Shader::TESS_CTRL:
18410 source = tcs;
18411 break;
18412 case Utils::Shader::TESS_EVAL:
18413 source = tes;
18414 break;
18415 case Utils::Shader::VERTEX:
18416 source = vs;
18417 break;
18418 default:
18419 TCU_FAIL("Invalid enum");
18420 }
18421 }
18422
18423 return source;
18424 }
18425
18426 /** Get description of test case
18427 *
18428 * @param test_case_index Index of test case
18429 *
18430 * @return Test case description
18431 **/
18432 std::string VaryingLocationAliasingWithMixedTypesTest::getTestCaseName(GLuint test_case_index)
18433 {
18434 std::stringstream stream;
18435 testCase& test_case = m_test_cases[test_case_index];
18436
18437 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18438 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
18439 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18440
18441 if (true == test_case.m_is_input)
18442 {
18443 stream << "input";
18444 }
18445 else
18446 {
18447 stream << "output";
18448 }
18449
18450 return stream.str();
18451 }
18452
18453 /** Get number of test cases
18454 *
18455 * @return Number of test cases
18456 **/
18457 GLuint VaryingLocationAliasingWithMixedTypesTest::getTestCaseNumber()
18458 {
18459 return static_cast<GLuint>(m_test_cases.size());
18460 }
18461
18462 /** Selects if "compute" stage is relevant for test
18463 *
18464 * @param ignored
18465 *
18466 * @return false
18467 **/
18468 bool VaryingLocationAliasingWithMixedTypesTest::isComputeRelevant(GLuint /* test_case_index */)
18469 {
18470 return false;
18471 }
18472
18473 /** Prepare all test cases
18474 *
18475 **/
18476 void VaryingLocationAliasingWithMixedTypesTest::testInit()
18477 {
18478 const GLuint n_types = getTypesNumber();
18479
18480 for (GLuint i = 0; i < n_types; ++i)
18481 {
18482 const Utils::Type& type_gohan = getType(i);
18483 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
18484
18485 if (valid_components_gohan.empty())
18486 {
18487 continue;
18488 }
18489
18490 for (GLuint j = 0; j < n_types; ++j)
18491 {
18492 const Utils::Type& type_goten = getType(j);
18493 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
18494
18495 if (valid_components_goten.empty())
18496 {
18497 continue;
18498 }
18499
18500 /* Skip valid combinations */
18501 if (Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
18502 {
18503 continue;
18504 }
18505
18506 for (std::vector<GLuint>::const_iterator it_gohan = valid_components_gohan.begin();
18507 it_gohan != valid_components_gohan.end(); ++it_gohan)
18508 {
18509 const GLuint min_component = *it_gohan + type_gohan.GetNumComponents();
18510 for (std::vector<GLuint>::const_iterator it_goten = valid_components_goten.begin();
18511 it_goten != valid_components_goten.end(); ++it_goten)
18512 {
18513
18514 if (min_component > *it_goten)
18515 {
18516 continue;
18517 }
18518
18519 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18520 {
18521 /* Skip compute shader */
18522 if (Utils::Shader::COMPUTE == stage)
18523 {
18524 continue;
18525 }
18526
18527 if (Utils::Shader::VERTEX != stage)
18528 {
18529 testCase test_case_in = { *it_gohan, *it_goten, true, (Utils::Shader::STAGES)stage,
18530 type_gohan, type_goten };
18531
18532 m_test_cases.push_back(test_case_in);
18533 }
18534
18535 /* Skip double outputs in fragment shader */
18536 if ((Utils::Shader::FRAGMENT != stage) || ((Utils::Type::Double != type_gohan.m_basic_type) &&
18537 (Utils::Type::Double != type_goten.m_basic_type)))
18538 {
18539 testCase test_case_out = { *it_gohan, *it_goten, false, (Utils::Shader::STAGES)stage,
18540 type_gohan, type_goten };
18541
18542 m_test_cases.push_back(test_case_out);
18543 }
18544 }
18545 }
18546 }
18547 }
18548 }
18549 }
18550
18551 /** Constructor
18552 *
18553 * @param context Test framework context
18554 **/
18555 VaryingLocationAliasingWithMixedInterpolationTest::VaryingLocationAliasingWithMixedInterpolationTest(
18556 deqp::Context& context)
18557 : NegativeTestBase(
18558 context, "varying_location_aliasing_with_mixed_interpolation",
18559 "Test verifies that compiler reports error when interpolation qualifiers are mixed at one location")
18560 {
18561 }
18562
18563 /** Source for given test case and stage
18564 *
18565 * @param test_case_index Index of test case
18566 * @param stage Shader stage
18567 *
18568 * @return Shader source
18569 **/
18570 std::string VaryingLocationAliasingWithMixedInterpolationTest::getShaderSource(GLuint test_case_index,
18571 Utils::Shader::STAGES stage)
18572 {
18573 static const GLchar* var_definition =
18574 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
18575 "layout (location = 1, component = COMPONENT) INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
18576 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX) &&\n"
18577 " (TYPE(1) == gotenINDEX) )\n"
18578 " {\n"
18579 " result += vec4(1, 0.5, 0.25, 0.125);\n"
18580 " }\n";
18581 static const GLchar* output_use = " gohanINDEX = TYPE(0);\n"
18582 " gotenINDEX = TYPE(1);\n"
18583 " if (vec4(0) == result)\n"
18584 " {\n"
18585 " gohanINDEX = TYPE(1);\n"
18586 " gotenINDEX = TYPE(0);\n"
18587 " }\n";
18588 static const GLchar* fs = "#version 430 core\n"
18589 "#extension GL_ARB_enhanced_layouts : require\n"
18590 "\n"
18591 "in vec4 gs_fs;\n"
18592 "out vec4 fs_out;\n"
18593 "\n"
18594 "void main()\n"
18595 "{\n"
18596 " fs_out = gs_fs;\n"
18597 "}\n"
18598 "\n";
18599 static const GLchar* fs_tested = "#version 430 core\n"
18600 "#extension GL_ARB_enhanced_layouts : require\n"
18601 "\n"
18602 "VAR_DEFINITION"
18603 "\n"
18604 "in vec4 gs_fs;\n"
18605 "out vec4 fs_out;\n"
18606 "\n"
18607 "void main()\n"
18608 "{\n"
18609 " vec4 result = gs_fs;\n"
18610 "\n"
18611 "VARIABLE_USE"
18612 "\n"
18613 " fs_out = result;\n"
18614 "}\n"
18615 "\n";
18616 static const GLchar* gs = "#version 430 core\n"
18617 "#extension GL_ARB_enhanced_layouts : require\n"
18618 "\n"
18619 "layout(points) in;\n"
18620 "layout(triangle_strip, max_vertices = 4) out;\n"
18621 "\n"
18622 "in vec4 tes_gs[];\n"
18623 "out vec4 gs_fs;\n"
18624 "\n"
18625 "void main()\n"
18626 "{\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 " gs_fs = tes_gs[0];\n"
18634 " gl_Position = vec4(1, -1, 0, 1);\n"
18635 " EmitVertex();\n"
18636 " gs_fs = tes_gs[0];\n"
18637 " gl_Position = vec4(1, 1, 0, 1);\n"
18638 " EmitVertex();\n"
18639 "}\n"
18640 "\n";
18641 static const GLchar* gs_tested = "#version 430 core\n"
18642 "#extension GL_ARB_enhanced_layouts : require\n"
18643 "\n"
18644 "layout(points) in;\n"
18645 "layout(triangle_strip, max_vertices = 4) out;\n"
18646 "\n"
18647 "VAR_DEFINITION"
18648 "\n"
18649 "in vec4 tes_gs[];\n"
18650 "out vec4 gs_fs;\n"
18651 "\n"
18652 "void main()\n"
18653 "{\n"
18654 " vec4 result = tes_gs[0];\n"
18655 "\n"
18656 "VARIABLE_USE"
18657 "\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 " gs_fs = result;\n"
18665 " gl_Position = vec4(1, -1, 0, 1);\n"
18666 " EmitVertex();\n"
18667 " gs_fs = result;\n"
18668 " gl_Position = vec4(1, 1, 0, 1);\n"
18669 " EmitVertex();\n"
18670 "}\n"
18671 "\n";
18672 static const GLchar* tcs = "#version 430 core\n"
18673 "#extension GL_ARB_enhanced_layouts : require\n"
18674 "\n"
18675 "layout(vertices = 1) out;\n"
18676 "\n"
18677 "in vec4 vs_tcs[];\n"
18678 "out vec4 tcs_tes[];\n"
18679 "\n"
18680 "void main()\n"
18681 "{\n"
18682 "\n"
18683 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
18684 "\n"
18685 " gl_TessLevelOuter[0] = 1.0;\n"
18686 " gl_TessLevelOuter[1] = 1.0;\n"
18687 " gl_TessLevelOuter[2] = 1.0;\n"
18688 " gl_TessLevelOuter[3] = 1.0;\n"
18689 " gl_TessLevelInner[0] = 1.0;\n"
18690 " gl_TessLevelInner[1] = 1.0;\n"
18691 "}\n"
18692 "\n";
18693 static const GLchar* tcs_tested = "#version 430 core\n"
18694 "#extension GL_ARB_enhanced_layouts : require\n"
18695 "\n"
18696 "layout(vertices = 1) out;\n"
18697 "\n"
18698 "VAR_DEFINITION"
18699 "\n"
18700 "in vec4 vs_tcs[];\n"
18701 "out vec4 tcs_tes[];\n"
18702 "\n"
18703 "void main()\n"
18704 "{\n"
18705 " vec4 result = vs_tcs[gl_InvocationID];\n"
18706 "\n"
18707 "VARIABLE_USE"
18708 "\n"
18709 " tcs_tes[gl_InvocationID] = result;\n"
18710 "\n"
18711 " gl_TessLevelOuter[0] = 1.0;\n"
18712 " gl_TessLevelOuter[1] = 1.0;\n"
18713 " gl_TessLevelOuter[2] = 1.0;\n"
18714 " gl_TessLevelOuter[3] = 1.0;\n"
18715 " gl_TessLevelInner[0] = 1.0;\n"
18716 " gl_TessLevelInner[1] = 1.0;\n"
18717 "}\n"
18718 "\n";
18719 static const GLchar* tes = "#version 430 core\n"
18720 "#extension GL_ARB_enhanced_layouts : require\n"
18721 "\n"
18722 "layout(isolines, point_mode) in;\n"
18723 "\n"
18724 "in vec4 tcs_tes[];\n"
18725 "out vec4 tes_gs;\n"
18726 "\n"
18727 "void main()\n"
18728 "{\n"
18729 " tes_gs = tcs_tes[0];\n"
18730 "}\n"
18731 "\n";
18732 static const GLchar* tes_tested = "#version 430 core\n"
18733 "#extension GL_ARB_enhanced_layouts : require\n"
18734 "\n"
18735 "layout(isolines, point_mode) in;\n"
18736 "\n"
18737 "VAR_DEFINITION"
18738 "\n"
18739 "in vec4 tcs_tes[];\n"
18740 "out vec4 tes_gs;\n"
18741 "\n"
18742 "void main()\n"
18743 "{\n"
18744 " vec4 result = tcs_tes[0];\n"
18745 "\n"
18746 "VARIABLE_USE"
18747 "\n"
18748 " tes_gs += result;\n"
18749 "}\n"
18750 "\n";
18751 static const GLchar* vs = "#version 430 core\n"
18752 "#extension GL_ARB_enhanced_layouts : require\n"
18753 "\n"
18754 "in vec4 in_vs;\n"
18755 "out vec4 vs_tcs;\n"
18756 "\n"
18757 "void main()\n"
18758 "{\n"
18759 " vs_tcs = in_vs;\n"
18760 "}\n"
18761 "\n";
18762 static const GLchar* vs_tested = "#version 430 core\n"
18763 "#extension GL_ARB_enhanced_layouts : require\n"
18764 "\n"
18765 "VAR_DEFINITION"
18766 "\n"
18767 "in vec4 in_vs;\n"
18768 "out vec4 vs_tcs;\n"
18769 "\n"
18770 "void main()\n"
18771 "{\n"
18772 " vec4 result = in_vs;\n"
18773 "\n"
18774 "VARIABLE_USE"
18775 "\n"
18776 " vs_tcs += result;\n"
18777 "}\n"
18778 "\n";
18779
18780 std::string source;
18781 testCase& test_case = m_test_cases[test_case_index];
18782
18783 if (test_case.m_stage == stage)
18784 {
18785 const GLchar* array = "";
18786 GLchar buffer_gohan[16];
18787 GLchar buffer_goten[16];
18788 const GLchar* direction = "in ";
18789 const GLchar* index = "";
18790 const GLchar* int_gohan = getInterpolationQualifier(test_case.m_interpolation_gohan);
18791 const GLchar* int_goten = getInterpolationQualifier(test_case.m_interpolation_goten);
18792 #if DEBUG_NEG_REMOVE_ERROR
18793 if (FLAT == test_case.m_interpolation_goten)
18794 {
18795 int_gohan = int_goten;
18796 }
18797 else
18798 {
18799 int_goten = int_gohan;
18800 }
18801 #endif /* DEBUG_NEG_REMOVE_ERROR */
18802 size_t position = 0;
18803 size_t temp;
18804 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
18805 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
18806 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
18807
18808 if (false == test_case.m_is_input)
18809 {
18810 direction = "out";
18811
18812 var_use = output_use;
18813 }
18814
18815 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
18816 sprintf(buffer_goten, "%d", test_case.m_component_goten);
18817
18818 switch (stage)
18819 {
18820 case Utils::Shader::FRAGMENT:
18821 source = fs_tested;
18822 break;
18823 case Utils::Shader::GEOMETRY:
18824 source = gs_tested;
18825 array = test_case.m_is_input ? "[]" : "";
18826 index = test_case.m_is_input ? "[0]" : "";
18827 break;
18828 case Utils::Shader::TESS_CTRL:
18829 source = tcs_tested;
18830 array = "[]";
18831 index = "[gl_InvocationID]";
18832 break;
18833 case Utils::Shader::TESS_EVAL:
18834 source = tes_tested;
18835 array = test_case.m_is_input ? "[]" : "";
18836 index = test_case.m_is_input ? "[0]" : "";
18837 break;
18838 case Utils::Shader::VERTEX:
18839 source = vs_tested;
18840 break;
18841 default:
18842 TCU_FAIL("Invalid enum");
18843 }
18844
18845 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
18846 position = 0;
18847 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
18848 Utils::replaceToken("INTERPOLATION", position, int_gohan, source);
18849 Utils::replaceToken("DIRECTION", position, direction, source);
18850 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18851 Utils::replaceToken("ARRAY", position, array, source);
18852 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
18853 Utils::replaceToken("INTERPOLATION", position, int_goten, source);
18854 Utils::replaceToken("DIRECTION", position, direction, source);
18855 Utils::replaceToken("TYPE", position, type_goten_name, source);
18856 Utils::replaceToken("ARRAY", position, array, source);
18857
18858 temp = position;
18859 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
18860 position = temp;
18861 if (!test_case.m_is_input)
18862 {
18863 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18864 Utils::replaceToken("TYPE", position, type_goten_name, source);
18865 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18866 Utils::replaceToken("TYPE", position, type_goten_name, source);
18867 }
18868 else if (Utils::Shader::VERTEX == stage)
18869 {
18870 Utils::replaceToken("TYPE", position, type_gohan_name, source);
18871 Utils::replaceToken("TYPE", position, type_goten_name, source);
18872 }
18873
18874 Utils::replaceAllTokens("INDEX", index, source);
18875 }
18876 else
18877 {
18878 switch (stage)
18879 {
18880 case Utils::Shader::FRAGMENT:
18881 source = fs;
18882 break;
18883 case Utils::Shader::GEOMETRY:
18884 source = gs;
18885 break;
18886 case Utils::Shader::TESS_CTRL:
18887 source = tcs;
18888 break;
18889 case Utils::Shader::TESS_EVAL:
18890 source = tes;
18891 break;
18892 case Utils::Shader::VERTEX:
18893 source = vs;
18894 break;
18895 default:
18896 TCU_FAIL("Invalid enum");
18897 }
18898 }
18899
18900 return source;
18901 }
18902
18903 /** Get description of test case
18904 *
18905 * @param test_case_index Index of test case
18906 *
18907 * @return Test case description
18908 **/
18909 std::string VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseName(GLuint test_case_index)
18910 {
18911 std::stringstream stream;
18912 testCase& test_case = m_test_cases[test_case_index];
18913
18914 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
18915 << getInterpolationQualifier(test_case.m_interpolation_gohan) << " "
18916 << test_case.m_type_gohan.GetGLSLTypeName() << " at " << test_case.m_component_gohan << ", "
18917 << getInterpolationQualifier(test_case.m_interpolation_goten) << " "
18918 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
18919
18920 if (true == test_case.m_is_input)
18921 {
18922 stream << "input";
18923 }
18924 else
18925 {
18926 stream << "output";
18927 }
18928
18929 return stream.str();
18930 }
18931
18932 /** Get number of test cases
18933 *
18934 * @return Number of test cases
18935 **/
18936 GLuint VaryingLocationAliasingWithMixedInterpolationTest::getTestCaseNumber()
18937 {
18938 return static_cast<GLuint>(m_test_cases.size());
18939 }
18940
18941 /** Selects if "compute" stage is relevant for test
18942 *
18943 * @param ignored
18944 *
18945 * @return false
18946 **/
18947 bool VaryingLocationAliasingWithMixedInterpolationTest::isComputeRelevant(GLuint /* test_case_index */)
18948 {
18949 return false;
18950 }
18951
18952 /** Prepare all test cases
18953 *
18954 **/
18955 void VaryingLocationAliasingWithMixedInterpolationTest::testInit()
18956 {
18957 const GLuint n_types = getTypesNumber();
18958
18959 for (GLuint i = 0; i < n_types; ++i)
18960 {
18961 const Utils::Type& type_gohan = getType(i);
18962 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
18963
18964 if (valid_components_gohan.empty())
18965 {
18966 continue;
18967 }
18968
18969 const GLuint gohan = valid_components_gohan.front();
18970
18971 for (GLuint j = 0; j < n_types; ++j)
18972 {
18973 const Utils::Type& type_goten = getType(j);
18974 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
18975
18976 if (valid_components_goten.empty())
18977 {
18978 continue;
18979 }
18980
18981 /* Just get the highest valid component for goten and
18982 * check if we can use it.
18983 */
18984 const GLuint min_component = gohan + type_gohan.GetNumComponents();
18985 const GLuint goten = valid_components_goten.back();
18986
18987 if (min_component > goten)
18988 {
18989 continue;
18990 }
18991
18992 /* Skip invalid combinations */
18993 if (!Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
18994 {
18995 continue;
18996 }
18997
18998 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
18999 {
19000 /* Skip compute shader */
19001 if (Utils::Shader::COMPUTE == stage)
19002 {
19003 continue;
19004 }
19005
19006 for (GLuint int_gohan = 0; int_gohan < INTERPOLATION_MAX; ++int_gohan)
19007 {
19008 for (GLuint int_goten = 0; int_goten < INTERPOLATION_MAX; ++int_goten)
19009 {
19010 /* Skip when both are the same */
19011 if (int_gohan == int_goten)
19012 {
19013 continue;
19014 }
19015
19016 /* Skip inputs in: vertex shader and whenever
19017 * flat is mandatory and is not the chosen
19018 * one.
19019 */
19020 bool skip_inputs = Utils::Shader::VERTEX == stage;
19021 skip_inputs |=
19022 (FLAT != int_gohan && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_gohan,
19023 Utils::Variable::VARYING_INPUT));
19024 skip_inputs |=
19025 (FLAT != int_goten && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_goten,
19026 Utils::Variable::VARYING_INPUT));
19027
19028 if (!skip_inputs)
19029 {
19030 testCase test_case_in = { gohan,
19031 goten,
19032 static_cast<INTERPOLATIONS>(int_gohan),
19033 static_cast<INTERPOLATIONS>(int_goten),
19034 true,
19035 static_cast<Utils::Shader::STAGES>(stage),
19036 type_gohan,
19037 type_goten };
19038 m_test_cases.push_back(test_case_in);
19039 }
19040
19041 /* Skip outputs in fragment shader and
19042 * whenever flat is mandatory and is not the
19043 * chosen one.
19044 */
19045 bool skip_outputs = Utils::Shader::FRAGMENT == stage;
19046 skip_outputs |=
19047 (FLAT != int_gohan && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_gohan,
19048 Utils::Variable::VARYING_OUTPUT));
19049 skip_outputs |=
19050 (FLAT != int_goten && isFlatRequired(static_cast<Utils::Shader::STAGES>(stage), type_goten,
19051 Utils::Variable::VARYING_OUTPUT));
19052
19053 if (!skip_outputs)
19054 {
19055 testCase test_case_out = { gohan,
19056 goten,
19057 static_cast<INTERPOLATIONS>(int_gohan),
19058 static_cast<INTERPOLATIONS>(int_goten),
19059 false,
19060 static_cast<Utils::Shader::STAGES>(stage),
19061 type_gohan,
19062 type_goten };
19063 m_test_cases.push_back(test_case_out);
19064 }
19065 }
19066 }
19067 }
19068 }
19069 }
19070 }
19071
19072 /** Get interpolation qualifier
19073 *
19074 * @param interpolation Enumeration
19075 *
19076 * @return GLSL qualifier
19077 **/
19078 const GLchar* VaryingLocationAliasingWithMixedInterpolationTest::getInterpolationQualifier(INTERPOLATIONS interpolation)
19079 {
19080 const GLchar* result = 0;
19081
19082 switch (interpolation)
19083 {
19084 case SMOOTH:
19085 result = "smooth";
19086 break;
19087 case FLAT:
19088 result = "flat";
19089 break;
19090 case NO_PERSPECTIVE:
19091 result = "noperspective";
19092 break;
19093 default:
19094 TCU_FAIL("Invalid enum");
19095 }
19096
19097 return result;
19098 }
19099
19100 /** Constructor
19101 *
19102 * @param context Test framework context
19103 **/
19104 VaryingLocationAliasingWithMixedAuxiliaryStorageTest::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(
19105 deqp::Context& context)
19106 : NegativeTestBase(
19107 context, "varying_location_aliasing_with_mixed_auxiliary_storage",
19108 "Test verifies that compiler reports error when auxiliary storage qualifiers are mixed at one location")
19109 {
19110 }
19111
19112 /** Source for given test case and stage
19113 *
19114 * @param test_case_index Index of test case
19115 * @param stage Shader stage
19116 *
19117 * @return Shader source
19118 **/
19119 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getShaderSource(GLuint test_case_index,
19120 Utils::Shader::STAGES stage)
19121 {
19122 static const GLchar* var_definition =
19123 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gohanARRAY;\n"
19124 "layout (location = 1, component = COMPONENT) AUX INTERPOLATION DIRECTION TYPE gotenARRAY;\n";
19125 static const GLchar* input_use = " if ((TYPE(0) == gohanINDEX_GOHAN) &&\n"
19126 " (TYPE(1) == gotenINDEX_GOTEN) )\n"
19127 " {\n"
19128 " result += vec4(1, 0.5, 0.25, 0.125);\n"
19129 " }\n";
19130 static const GLchar* output_use = " gohanINDEX_GOHAN = TYPE(0);\n"
19131 " gotenINDEX_GOTEN = TYPE(1);\n"
19132 " if (vec4(0) == result)\n"
19133 " {\n"
19134 " gohanINDEX_GOHAN = TYPE(1);\n"
19135 " gotenINDEX_GOTEN = TYPE(0);\n"
19136 " }\n";
19137 static const GLchar* fs = "#version 430 core\n"
19138 "#extension GL_ARB_enhanced_layouts : require\n"
19139 "\n"
19140 "in vec4 gs_fs;\n"
19141 "out vec4 fs_out;\n"
19142 "\n"
19143 "void main()\n"
19144 "{\n"
19145 " fs_out = gs_fs;\n"
19146 "}\n"
19147 "\n";
19148 static const GLchar* fs_tested = "#version 430 core\n"
19149 "#extension GL_ARB_enhanced_layouts : require\n"
19150 "\n"
19151 "VAR_DEFINITION"
19152 "\n"
19153 "in vec4 gs_fs;\n"
19154 "out vec4 fs_out;\n"
19155 "\n"
19156 "void main()\n"
19157 "{\n"
19158 " vec4 result = gs_fs;\n"
19159 "\n"
19160 "VARIABLE_USE"
19161 "\n"
19162 " fs_out = result;\n"
19163 "}\n"
19164 "\n";
19165 static const GLchar* gs = "#version 430 core\n"
19166 "#extension GL_ARB_enhanced_layouts : require\n"
19167 "\n"
19168 "layout(points) in;\n"
19169 "layout(triangle_strip, max_vertices = 4) out;\n"
19170 "\n"
19171 "in vec4 tes_gs[];\n"
19172 "out vec4 gs_fs;\n"
19173 "\n"
19174 "void main()\n"
19175 "{\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 " gs_fs = tes_gs[0];\n"
19183 " gl_Position = vec4(1, -1, 0, 1);\n"
19184 " EmitVertex();\n"
19185 " gs_fs = tes_gs[0];\n"
19186 " gl_Position = vec4(1, 1, 0, 1);\n"
19187 " EmitVertex();\n"
19188 "}\n"
19189 "\n";
19190 static const GLchar* gs_tested = "#version 430 core\n"
19191 "#extension GL_ARB_enhanced_layouts : require\n"
19192 "\n"
19193 "layout(points) in;\n"
19194 "layout(triangle_strip, max_vertices = 4) out;\n"
19195 "\n"
19196 "VAR_DEFINITION"
19197 "\n"
19198 "in vec4 tes_gs[];\n"
19199 "out vec4 gs_fs;\n"
19200 "\n"
19201 "void main()\n"
19202 "{\n"
19203 " vec4 result = tes_gs[0];\n"
19204 "\n"
19205 "VARIABLE_USE"
19206 "\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 " gs_fs = result;\n"
19214 " gl_Position = vec4(1, -1, 0, 1);\n"
19215 " EmitVertex();\n"
19216 " gs_fs = result;\n"
19217 " gl_Position = vec4(1, 1, 0, 1);\n"
19218 " EmitVertex();\n"
19219 "}\n"
19220 "\n";
19221 static const GLchar* tcs = "#version 430 core\n"
19222 "#extension GL_ARB_enhanced_layouts : require\n"
19223 "\n"
19224 "layout(vertices = 1) out;\n"
19225 "\n"
19226 "in vec4 vs_tcs[];\n"
19227 "out vec4 tcs_tes[];\n"
19228 "\n"
19229 "void main()\n"
19230 "{\n"
19231 "\n"
19232 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
19233 "\n"
19234 " gl_TessLevelOuter[0] = 1.0;\n"
19235 " gl_TessLevelOuter[1] = 1.0;\n"
19236 " gl_TessLevelOuter[2] = 1.0;\n"
19237 " gl_TessLevelOuter[3] = 1.0;\n"
19238 " gl_TessLevelInner[0] = 1.0;\n"
19239 " gl_TessLevelInner[1] = 1.0;\n"
19240 "}\n"
19241 "\n";
19242 static const GLchar* tcs_tested = "#version 430 core\n"
19243 "#extension GL_ARB_enhanced_layouts : require\n"
19244 "\n"
19245 "layout(vertices = 1) out;\n"
19246 "\n"
19247 "VAR_DEFINITION"
19248 "\n"
19249 "in vec4 vs_tcs[];\n"
19250 "out vec4 tcs_tes[];\n"
19251 "\n"
19252 "void main()\n"
19253 "{\n"
19254 " vec4 result = vs_tcs[gl_InvocationID];\n"
19255 "\n"
19256 "VARIABLE_USE"
19257 "\n"
19258 " tcs_tes[gl_InvocationID] = result;\n"
19259 "\n"
19260 " gl_TessLevelOuter[0] = 1.0;\n"
19261 " gl_TessLevelOuter[1] = 1.0;\n"
19262 " gl_TessLevelOuter[2] = 1.0;\n"
19263 " gl_TessLevelOuter[3] = 1.0;\n"
19264 " gl_TessLevelInner[0] = 1.0;\n"
19265 " gl_TessLevelInner[1] = 1.0;\n"
19266 "}\n"
19267 "\n";
19268 static const GLchar* tes = "#version 430 core\n"
19269 "#extension GL_ARB_enhanced_layouts : require\n"
19270 "\n"
19271 "layout(isolines, point_mode) in;\n"
19272 "\n"
19273 "in vec4 tcs_tes[];\n"
19274 "out vec4 tes_gs;\n"
19275 "\n"
19276 "void main()\n"
19277 "{\n"
19278 " tes_gs = tcs_tes[0];\n"
19279 "}\n"
19280 "\n";
19281 static const GLchar* tes_tested = "#version 430 core\n"
19282 "#extension GL_ARB_enhanced_layouts : require\n"
19283 "\n"
19284 "layout(isolines, point_mode) in;\n"
19285 "\n"
19286 "VAR_DEFINITION"
19287 "\n"
19288 "in vec4 tcs_tes[];\n"
19289 "out vec4 tes_gs;\n"
19290 "\n"
19291 "void main()\n"
19292 "{\n"
19293 " vec4 result = tcs_tes[0];\n"
19294 "\n"
19295 "VARIABLE_USE"
19296 "\n"
19297 " tes_gs += result;\n"
19298 "}\n"
19299 "\n";
19300 static const GLchar* vs = "#version 430 core\n"
19301 "#extension GL_ARB_enhanced_layouts : require\n"
19302 "\n"
19303 "in vec4 in_vs;\n"
19304 "out vec4 vs_tcs;\n"
19305 "\n"
19306 "void main()\n"
19307 "{\n"
19308 " vs_tcs = in_vs;\n"
19309 "}\n"
19310 "\n";
19311 static const GLchar* vs_tested = "#version 430 core\n"
19312 "#extension GL_ARB_enhanced_layouts : require\n"
19313 "\n"
19314 "VAR_DEFINITION"
19315 "\n"
19316 "in vec4 in_vs;\n"
19317 "out vec4 vs_tcs;\n"
19318 "\n"
19319 "void main()\n"
19320 "{\n"
19321 " vec4 result = in_vs;\n"
19322 "\n"
19323 "VARIABLE_USE"
19324 "\n"
19325 " vs_tcs += result;\n"
19326 "}\n"
19327 "\n";
19328
19329 std::string source;
19330 testCase& test_case = m_test_cases[test_case_index];
19331
19332 if (test_case.m_stage == stage)
19333 {
19334 const GLchar* array_gohan = "";
19335 const GLchar* array_goten = "";
19336 const GLchar* aux_gohan = getAuxiliaryQualifier(test_case.m_aux_gohan);
19337 #if DEBUG_NEG_REMOVE_ERROR
19338 const GLchar* aux_goten = aux_gohan;
19339 #else
19340 const GLchar* aux_goten = getAuxiliaryQualifier(test_case.m_aux_goten);
19341 #endif /* DEBUG_NEG_REMOVE_ERROR */
19342 GLchar buffer_gohan[16];
19343 GLchar buffer_goten[16];
19344 const GLchar* direction = "in";
19345 const GLchar* index_gohan = "";
19346 const GLchar* index_goten = "";
19347 Utils::Variable::STORAGE storage = Utils::Variable::VARYING_INPUT;
19348 const GLchar* interpolation = "";
19349 size_t position = 0;
19350 size_t temp;
19351 const GLchar* type_gohan_name = test_case.m_type_gohan.GetGLSLTypeName();
19352 const GLchar* type_goten_name = test_case.m_type_goten.GetGLSLTypeName();
19353 const GLchar* var_use = Utils::Shader::VERTEX == stage ? input_use : "\n";
19354
19355 if (false == test_case.m_is_input)
19356 {
19357 direction = "out";
19358 storage = Utils::Variable::VARYING_OUTPUT;
19359 var_use = output_use;
19360 }
19361
19362 if (isFlatRequired(stage, test_case.m_type_gohan, storage) ||
19363 isFlatRequired(stage, test_case.m_type_goten, storage))
19364 {
19365 interpolation = "flat";
19366 }
19367
19368 sprintf(buffer_gohan, "%d", test_case.m_component_gohan);
19369 sprintf(buffer_goten, "%d", test_case.m_component_goten);
19370
19371 switch (stage)
19372 {
19373 case Utils::Shader::FRAGMENT:
19374 source = fs_tested;
19375 break;
19376 case Utils::Shader::GEOMETRY:
19377 source = gs_tested;
19378 array_gohan = test_case.m_is_input ? "[]" : "";
19379 index_gohan = test_case.m_is_input ? "[0]" : "";
19380 array_goten = test_case.m_is_input ? "[]" : "";
19381 index_goten = test_case.m_is_input ? "[0]" : "";
19382 break;
19383 case Utils::Shader::TESS_CTRL:
19384 source = tcs_tested;
19385 if (PATCH != test_case.m_aux_gohan)
19386 {
19387 array_gohan = "[]";
19388 index_gohan = "[gl_InvocationID]";
19389 }
19390 #if DEBUG_NEG_REMOVE_ERROR
19391 array_goten = array_gohan;
19392 index_goten = index_gohan;
19393 #else
19394 if (PATCH != test_case.m_aux_goten)
19395 {
19396 array_goten = "[]";
19397 index_goten = "[gl_InvocationID]";
19398 }
19399 #endif /* DEBUG_NEG_REMOVE_ERROR */
19400 break;
19401 case Utils::Shader::TESS_EVAL:
19402 source = tes_tested;
19403 if (PATCH != test_case.m_aux_gohan)
19404 {
19405 array_gohan = test_case.m_is_input ? "[]" : "";
19406 index_gohan = test_case.m_is_input ? "[0]" : "";
19407 }
19408 #if DEBUG_NEG_REMOVE_ERROR
19409 array_goten = array_gohan;
19410 index_goten = index_gohan;
19411 #else
19412 if (PATCH != test_case.m_aux_goten)
19413 {
19414 array_goten = test_case.m_is_input ? "[]" : "";
19415 index_goten = test_case.m_is_input ? "[0]" : "";
19416 }
19417 #endif /* DEBUG_NEG_REMOVE_ERROR */
19418 break;
19419 case Utils::Shader::VERTEX:
19420 source = vs_tested;
19421 break;
19422 default:
19423 TCU_FAIL("Invalid enum");
19424 }
19425
19426 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
19427 position = 0;
19428 Utils::replaceToken("COMPONENT", position, buffer_gohan, source);
19429 Utils::replaceToken("AUX", position, aux_gohan, source);
19430 Utils::replaceToken("INTERPOLATION", position, interpolation, source);
19431 Utils::replaceToken("DIRECTION", position, direction, source);
19432 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19433 Utils::replaceToken("ARRAY", position, array_gohan, source);
19434 Utils::replaceToken("COMPONENT", position, buffer_goten, source);
19435 Utils::replaceToken("AUX", position, aux_goten, source);
19436 Utils::replaceToken("INTERPOLATION", position, interpolation, source);
19437 Utils::replaceToken("DIRECTION", position, direction, source);
19438 Utils::replaceToken("TYPE", position, type_goten_name, source);
19439 Utils::replaceToken("ARRAY", position, array_goten, source);
19440
19441 temp = position;
19442 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
19443 position = temp;
19444 if (!test_case.m_is_input)
19445 {
19446 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19447 Utils::replaceToken("TYPE", position, type_goten_name, source);
19448 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19449 Utils::replaceToken("TYPE", position, type_goten_name, source);
19450 }
19451 else if (Utils::Shader::VERTEX == stage)
19452 {
19453 Utils::replaceToken("TYPE", position, type_gohan_name, source);
19454 Utils::replaceToken("TYPE", position, type_goten_name, source);
19455 }
19456
19457 Utils::replaceAllTokens("INDEX_GOHAN", index_gohan, source);
19458 Utils::replaceAllTokens("INDEX_GOTEN", index_goten, source);
19459 }
19460 else
19461 {
19462 switch (stage)
19463 {
19464 case Utils::Shader::FRAGMENT:
19465 source = fs;
19466 break;
19467 case Utils::Shader::GEOMETRY:
19468 source = gs;
19469 break;
19470 case Utils::Shader::TESS_CTRL:
19471 source = tcs;
19472 break;
19473 case Utils::Shader::TESS_EVAL:
19474 source = tes;
19475 break;
19476 case Utils::Shader::VERTEX:
19477 source = vs;
19478 break;
19479 default:
19480 TCU_FAIL("Invalid enum");
19481 }
19482 }
19483
19484 return source;
19485 }
19486
19487 /** Get description of test case
19488 *
19489 * @param test_case_index Index of test case
19490 *
19491 * @return Test case description
19492 **/
19493 std::string VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseName(GLuint test_case_index)
19494 {
19495 std::stringstream stream;
19496 testCase& test_case = m_test_cases[test_case_index];
19497
19498 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", "
19499 << getAuxiliaryQualifier(test_case.m_aux_gohan) << " " << test_case.m_type_gohan.GetGLSLTypeName() << " at "
19500 << test_case.m_component_gohan << ", " << getAuxiliaryQualifier(test_case.m_aux_goten) << " "
19501 << test_case.m_type_goten.GetGLSLTypeName() << " at " << test_case.m_component_goten << ". Direction: ";
19502
19503 if (true == test_case.m_is_input)
19504 {
19505 stream << "input";
19506 }
19507 else
19508 {
19509 stream << "output";
19510 }
19511
19512 return stream.str();
19513 }
19514
19515 /** Get number of test cases
19516 *
19517 * @return Number of test cases
19518 **/
19519 GLuint VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getTestCaseNumber()
19520 {
19521 return static_cast<GLuint>(m_test_cases.size());
19522 }
19523
19524 /** Selects if "compute" stage is relevant for test
19525 *
19526 * @param ignored
19527 *
19528 * @return false
19529 **/
19530 bool VaryingLocationAliasingWithMixedAuxiliaryStorageTest::isComputeRelevant(GLuint /* test_case_index */)
19531 {
19532 return false;
19533 }
19534
19535 /** Prepare all test cases
19536 *
19537 **/
19538 void VaryingLocationAliasingWithMixedAuxiliaryStorageTest::testInit()
19539 {
19540 const GLuint n_types = getTypesNumber();
19541
19542 for (GLuint i = 0; i < n_types; ++i)
19543 {
19544 const Utils::Type& type_gohan = getType(i);
19545 const std::vector<GLuint>& valid_components_gohan = type_gohan.GetValidComponents();
19546
19547 if (valid_components_gohan.empty())
19548 {
19549 continue;
19550 }
19551
19552 const GLuint gohan = valid_components_gohan.front();
19553
19554 for (GLuint j = 0; j < n_types; ++j)
19555 {
19556 const Utils::Type& type_goten = getType(j);
19557 const std::vector<GLuint>& valid_components_goten = type_goten.GetValidComponents();
19558
19559 if (valid_components_goten.empty())
19560 {
19561 continue;
19562 }
19563
19564 /* Just get the highest valid component for goten and
19565 * check if we can use it.
19566 */
19567 const GLuint min_component = gohan + type_gohan.GetNumComponents();
19568 const GLuint goten = valid_components_goten.back();
19569
19570 if (min_component > goten)
19571 {
19572 continue;
19573 }
19574
19575 /* Skip invalid combinations */
19576 if (!Utils::Type::CanTypesShareLocation(type_gohan.m_basic_type, type_goten.m_basic_type))
19577 {
19578 continue;
19579 }
19580
19581 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
19582 {
19583 /* Skip compute shader */
19584 if (Utils::Shader::COMPUTE == stage)
19585 {
19586 continue;
19587 }
19588
19589 for (GLuint aux = 0; aux < AUXILIARY_MAX; ++aux)
19590 {
19591 Utils::Shader::STAGES const shader_stage = static_cast<Utils::Shader::STAGES>(stage);
19592 AUXILIARIES const auxiliary = static_cast<AUXILIARIES>(aux);
19593
19594 if (PATCH == auxiliary)
19595 {
19596 if (Utils::Shader::TESS_CTRL == shader_stage || Utils::Shader::TESS_EVAL == shader_stage)
19597 {
19598 bool direction = Utils::Shader::TESS_EVAL == shader_stage;
19599 testCase test_case_patch_gohan = { gohan, goten, auxiliary, NONE,
19600 direction, shader_stage, type_gohan, type_goten };
19601 testCase test_case_patch_goten = { gohan, goten, NONE, auxiliary,
19602 direction, shader_stage, type_gohan, type_goten };
19603
19604 m_test_cases.push_back(test_case_patch_gohan);
19605 m_test_cases.push_back(test_case_patch_goten);
19606 }
19607 continue;
19608 }
19609
19610 for (GLuint second_aux = 0; second_aux < AUXILIARY_MAX; ++second_aux)
19611 {
19612 AUXILIARIES const second_auxiliary = static_cast<AUXILIARIES>(second_aux);
19613
19614 if (PATCH == second_auxiliary || auxiliary == second_auxiliary)
19615 {
19616 continue;
19617 }
19618
19619 if (Utils::Shader::FRAGMENT != shader_stage)
19620 {
19621 testCase test_case_out = { gohan, goten, auxiliary, second_auxiliary,
19622 false, shader_stage, type_gohan, type_goten };
19623
19624 m_test_cases.push_back(test_case_out);
19625 }
19626
19627 if (Utils::Shader::VERTEX != shader_stage)
19628 {
19629 testCase test_case_in = { gohan, goten, auxiliary, second_auxiliary,
19630 true, shader_stage, type_gohan, type_goten };
19631
19632 m_test_cases.push_back(test_case_in);
19633 }
19634 }
19635 }
19636 }
19637 }
19638 }
19639 }
19640
19641 /** Get auxiliary storage qualifier
19642 *
19643 * @param aux Enumeration
19644 *
19645 * @return GLSL qualifier
19646 **/
19647 const GLchar* VaryingLocationAliasingWithMixedAuxiliaryStorageTest::getAuxiliaryQualifier(AUXILIARIES aux)
19648 {
19649 const GLchar* result = 0;
19650
19651 switch (aux)
19652 {
19653 case NONE:
19654 result = "";
19655 break;
19656 case PATCH:
19657 result = "patch";
19658 break;
19659 case CENTROID:
19660 result = "centroid";
19661 break;
19662 case SAMPLE:
19663 result = "sample";
19664 break;
19665 default:
19666 TCU_FAIL("Invalid enum");
19667 }
19668
19669 return result;
19670 }
19671
19672 /* Constants used by VertexAttribLocationAPITest */
19673 const GLuint VertexAttribLocationAPITest::m_goten_location = 6;
19674
19675 /** Constructor
19676 *
19677 * @param context Test framework context
19678 **/
19679 VertexAttribLocationAPITest::VertexAttribLocationAPITest(deqp::Context& context)
19680 : TextureTestBase(context, "vertex_attrib_location_api",
19681 "Test verifies that attribute locations API works as expected")
19682 {
19683 }
19684
19685 /** Does BindAttribLocation for "goten" and relink program
19686 *
19687 * @param program Program object
19688 * @param program_interface Interface of program
19689 **/
19690 void VertexAttribLocationAPITest::prepareAttribLocation(Utils::Program& program,
19691 Utils::ProgramInterface& program_interface)
19692 {
19693 const Functions& gl = m_context.getRenderContext().getFunctions();
19694
19695 gl.bindAttribLocation(program.m_id, m_goten_location, "goten");
19696 GLU_EXPECT_NO_ERROR(gl.getError(), "BindAttribLocation");
19697
19698 program.Link(gl, program.m_id);
19699
19700 /* We still need to get locations for gohan and chichi */
19701 TextureTestBase::prepareAttribLocation(program, program_interface);
19702 }
19703
19704 /** Get interface of program
19705 *
19706 * @param ignored
19707 * @param program_interface Interface of program
19708 * @param ignored
19709 **/
19710 void VertexAttribLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19711 Utils::ProgramInterface& program_interface,
19712 Utils::VaryingPassthrough& /* varying_passthrough */)
19713 {
19714 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::VERTEX);
19715 const Utils::Type& type = Utils::Type::vec4;
19716 const GLuint type_size = type.GetSize();
19717
19718 /* Offsets */
19719 const GLuint chichi_offset = 0;
19720 const GLuint goten_offset = chichi_offset + type_size;
19721 const GLuint gohan_offset = goten_offset + type_size;
19722 const GLuint goku_offset = gohan_offset + type_size;
19723
19724 /* Locations */
19725 const GLuint goku_location = 2;
19726 const GLuint goten_location = m_goten_location;
19727
19728 /* Generate data */
19729 m_goku_data = type.GenerateDataPacked();
19730 m_gohan_data = type.GenerateDataPacked();
19731 m_goten_data = type.GenerateDataPacked();
19732 m_chichi_data = type.GenerateDataPacked();
19733
19734 /* Globals */
19735 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19736
19737 /* Attributes */
19738 si.Input("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19739 goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19740 0u /* n_array_elements */, 0u /* stride */, goku_offset /* offset */, (GLvoid*)&m_goku_data[0] /* data */,
19741 m_goku_data.size() /* data_size */);
19742
19743 si.Input("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19744 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19745 0u /* n_array_elements */, 0u /* stride */, gohan_offset /* offset */,
19746 (GLvoid*)&m_gohan_data[0] /* data */, m_gohan_data.size() /* data_size */);
19747
19748 si.Input("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19749 goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19750 0u /* n_array_elements */, 0u /* stride */, goten_offset /* offset */,
19751 (GLvoid*)&m_goten_data[0] /* data */, m_goten_data.size() /* data_size */);
19752
19753 si.Input("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19754 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19755 0u /* n_array_elements */, 0u /* stride */, chichi_offset /* offset */,
19756 (GLvoid*)&m_chichi_data[0] /* data */, m_chichi_data.size() /* data_size */);
19757 }
19758
19759 /** Selects if "compute" stage is relevant for test
19760 *
19761 * @param ignored
19762 *
19763 * @return false
19764 **/
19765 bool VertexAttribLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19766 {
19767 return false;
19768 }
19769
19770 /* Constants used by FragmentDataLocationAPITest */
19771 const GLuint FragmentDataLocationAPITest::m_goten_location = 6;
19772
19773 /** Constructor
19774 *
19775 * @param context Test framework context
19776 **/
19777 FragmentDataLocationAPITest::FragmentDataLocationAPITest(deqp::Context& context)
19778 : TextureTestBase(context, "fragment_data_location_api",
19779 "Test verifies that fragment data locations API works as expected")
19780 , m_goku(context)
19781 , m_gohan(context)
19782 , m_goten(context)
19783 , m_chichi(context)
19784 {
19785 }
19786
19787 /** Verifies contents of drawn images
19788 *
19789 * @param ignored
19790 * @param ignored
19791 *
19792 * @return true if images are filled with expected values, false otherwise
19793 **/
19794 bool FragmentDataLocationAPITest::checkResults(glw::GLuint /* test_case_index */, Utils::Texture& /* color_0 */)
19795 {
19796 static const GLuint size = m_width * m_height;
19797 static const GLuint expected_goku = 0xff000000;
19798 static const GLuint expected_gohan = 0xff0000ff;
19799 static const GLuint expected_goten = 0xff00ff00;
19800 static const GLuint expected_chichi = 0xffff0000;
19801
19802 std::vector<GLuint> data;
19803 data.resize(size);
19804
19805 m_goku.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19806
19807 for (GLuint i = 0; i < size; ++i)
19808 {
19809 const GLuint color = data[i];
19810
19811 if (expected_goku != color)
19812 {
19813 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19814 << tcu::TestLog::EndMessage;
19815 return false;
19816 }
19817 }
19818
19819 m_gohan.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19820
19821 for (GLuint i = 0; i < size; ++i)
19822 {
19823 const GLuint color = data[i];
19824
19825 if (expected_gohan != color)
19826 {
19827 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19828 << tcu::TestLog::EndMessage;
19829 return false;
19830 }
19831 }
19832
19833 m_goten.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19834
19835 for (GLuint i = 0; i < size; ++i)
19836 {
19837 const GLuint color = data[i];
19838
19839 if (expected_goten != color)
19840 {
19841 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19842 << tcu::TestLog::EndMessage;
19843 return false;
19844 }
19845 }
19846
19847 m_chichi.Get(GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
19848
19849 for (GLuint i = 0; i < size; ++i)
19850 {
19851 const GLuint color = data[i];
19852
19853 if (expected_chichi != color)
19854 {
19855 m_context.getTestContext().getLog() << tcu::TestLog::Message << "RGBA8[" << i << "]:" << color
19856 << tcu::TestLog::EndMessage;
19857 return false;
19858 }
19859 }
19860
19861 return true;
19862 }
19863
19864 /** Prepare code snippet that will set out variables
19865 *
19866 * @param ignored
19867 * @param ignored
19868 * @param stage Shader stage
19869 *
19870 * @return Code that pass in variables to next stage
19871 **/
19872 std::string FragmentDataLocationAPITest::getPassSnippet(GLuint /* test_case_index */,
19873 Utils::VaryingPassthrough& /* varying_passthrough */,
19874 Utils::Shader::STAGES stage)
19875 {
19876 std::string result;
19877
19878 /* Skip for compute shader */
19879 if (Utils::Shader::FRAGMENT != stage)
19880 {
19881 result = "";
19882 }
19883 else
19884 {
19885 result = "chichi = vec4(0, 0, 1, 1);\n"
19886 " goku = vec4(0, 0, 0, 1);\n"
19887 " goten = vec4(0, 1, 0, 1);\n"
19888 " gohan = vec4(1, 0, 0, 1);\n";
19889 }
19890
19891 return result;
19892 }
19893
19894 /** Get interface of program
19895 *
19896 * @param ignored
19897 * @param program_interface Interface of program
19898 * @param ignored
19899 **/
19900 void FragmentDataLocationAPITest::getProgramInterface(GLuint /* test_case_index */,
19901 Utils::ProgramInterface& program_interface,
19902 Utils::VaryingPassthrough& /* varying_passthrough */)
19903 {
19904 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19905 const Utils::Type& type = Utils::Type::vec4;
19906
19907 /* Locations */
19908 m_goku_location = 2;
19909
19910 /* Globals */
19911 si.m_globals = "const uint GOKU_LOCATION = 2;\n";
19912
19913 /* Attributes */
19914 si.Output("goku" /* name */, "layout (location = GOKU_LOCATION)" /* qualifiers */, 0 /* expected_componenet */,
19915 m_goku_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19916 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19917
19918 si.Output("gohan" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19919 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19920 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19921
19922 si.Output("goten" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19923 m_goten_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19924 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19925
19926 si.Output("chichi" /* name */, "" /* qualifiers */, 0 /* expected_componenet */,
19927 Utils::Variable::m_automatic_location /* expected_location */, type /* type */, GL_FALSE /* normalized */,
19928 0u /* n_array_elements */, 0u /* stride */, 0u /* offset */, (GLvoid*)0 /* data */, 0u /* data_size */);
19929 }
19930
19931 /** Selects if "compute" stage is relevant for test
19932 *
19933 * @param ignored
19934 *
19935 * @return false
19936 **/
19937 bool FragmentDataLocationAPITest::isComputeRelevant(GLuint /* test_case_index */)
19938 {
19939 return false;
19940 }
19941
19942 /** Get locations for all outputs with automatic_location
19943 *
19944 * @param program Program object
19945 * @param program_interface Interface of program
19946 **/
19947 void FragmentDataLocationAPITest::prepareFragmentDataLoc(Utils::Program& program,
19948 Utils::ProgramInterface& program_interface)
19949 {
19950 /* Bind location of goten */
19951 const Functions& gl = m_context.getRenderContext().getFunctions();
19952
19953 gl.bindFragDataLocation(program.m_id, m_goten_location, "goten");
19954 GLU_EXPECT_NO_ERROR(gl.getError(), "BindFragDataLocation");
19955
19956 program.Link(gl, program.m_id);
19957
19958 /* Prepare locations for gohan and chichi */
19959 TextureTestBase::prepareFragmentDataLoc(program, program_interface);
19960
19961 /* Get all locations */
19962 Utils::ShaderInterface& si = program_interface.GetShaderInterface(Utils::Shader::FRAGMENT);
19963
19964 Utils::Variable::PtrVector& outputs = si.m_outputs;
19965
19966 for (Utils::Variable::PtrVector::iterator it = outputs.begin(); outputs.end() != it; ++it)
19967 {
19968 const Utils::Variable::Descriptor& desc = (*it)->m_descriptor;
19969
19970 if (0 == desc.m_name.compare("gohan"))
19971 {
19972 m_gohan_location = desc.m_expected_location;
19973 }
19974 else if (0 == desc.m_name.compare("chichi"))
19975 {
19976 m_chichi_location = desc.m_expected_location;
19977 }
19978
19979 /* Locations of goku and goten are fixed */
19980 }
19981 }
19982
19983 /** Prepare framebuffer with single texture as color attachment
19984 *
19985 * @param framebuffer Framebuffer
19986 * @param color_0_texture Texture that will used as color attachment
19987 **/
19988 void FragmentDataLocationAPITest::prepareFramebuffer(Utils::Framebuffer& framebuffer, Utils::Texture& color_0_texture)
19989 {
19990 /* Let parent prepare its stuff */
19991 TextureTestBase::prepareFramebuffer(framebuffer, color_0_texture);
19992
19993 /* Prepare data */
19994 std::vector<GLuint> texture_data;
19995 texture_data.resize(m_width * m_height);
19996
19997 for (GLuint i = 0; i < texture_data.size(); ++i)
19998 {
19999 texture_data[i] = 0x20406080;
20000 }
20001
20002 /* Prepare textures */
20003 m_goku.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20004
20005 m_gohan.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20006
20007 m_goten.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20008
20009 m_chichi.Init(Utils::Texture::TEX_2D, m_width, m_height, 0, GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE, &texture_data[0]);
20010
20011 /* Attach textures to framebuffer */
20012 framebuffer.Bind();
20013 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goku_location, m_goku.m_id, m_width, m_height);
20014 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_gohan_location, m_gohan.m_id, m_width, m_height);
20015 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_goten_location, m_goten.m_id, m_width, m_height);
20016 framebuffer.AttachTexture(GL_COLOR_ATTACHMENT0 + m_chichi_location, m_chichi.m_id, m_width, m_height);
20017
20018 /* Set up drawbuffers */
20019 const Functions& gl = m_context.getRenderContext().getFunctions();
20020 // The fragment shader can have more than 4 color outputs, but it only care about 4 (goku, gohan, goten, chichi).
20021 // We will first initialize all draw buffers to NONE and then set the real value for the 4 outputs we care about
20022 GLint maxDrawBuffers = 0;
20023 gl.getIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers);
20024
20025 std::vector<GLenum> buffers(maxDrawBuffers, GL_NONE);
20026 buffers[m_chichi_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_chichi_location);
20027 buffers[m_goten_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goten_location);
20028 buffers[m_goku_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_goku_location);
20029 buffers[m_gohan_location] = GLenum(GL_COLOR_ATTACHMENT0 + m_gohan_location);
20030
20031 gl.drawBuffers(maxDrawBuffers, buffers.data());
20032 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawBuffers");
20033 }
20034
20035 /** Constructor
20036 *
20037 * @param context Test framework context
20038 **/
20039 XFBInputTest::XFBInputTest(deqp::Context& context)
20040 : NegativeTestBase(context, "xfb_input",
20041 "Test verifies that compiler reports error when xfb qualifiers are used with input")
20042 {
20043 }
20044
20045 /** Source for given test case and stage
20046 *
20047 * @param test_case_index Index of test case
20048 * @param stage Shader stage
20049 *
20050 * @return Shader source
20051 **/
20052 std::string XFBInputTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
20053 {
20054 #if DEBUG_NEG_REMOVE_ERROR
20055 static const GLchar* buffer_var_definition = "/* layout (xfb_buffer = 2) */ in vec4 gohanARRAY;\n";
20056 static const GLchar* offset_var_definition = "/* layout (xfb_offset = 16) */ in vec4 gohanARRAY;\n";
20057 static const GLchar* stride_var_definition = "/* layout (xfb_stride = 32) */ in vec4 gohanARRAY;\n";
20058 #else
20059 static const GLchar* buffer_var_definition = "layout (xfb_buffer = 2) in vec4 gohanARRAY;\n";
20060 static const GLchar* offset_var_definition = "layout (xfb_offset = 16) in vec4 gohanARRAY;\n";
20061 static const GLchar* stride_var_definition = "layout (xfb_stride = 32) in vec4 gohanARRAY;\n";
20062 #endif /* DEBUG_NEG_REMOVE_ERROR */
20063 static const GLchar* fs = "#version 430 core\n"
20064 "#extension GL_ARB_enhanced_layouts : require\n"
20065 "\n"
20066 "in vec4 gs_fs;\n"
20067 "out vec4 fs_out;\n"
20068 "\n"
20069 "void main()\n"
20070 "{\n"
20071 " fs_out = gs_fs;\n"
20072 "}\n"
20073 "\n";
20074 static const GLchar* fs_tested = "#version 430 core\n"
20075 "#extension GL_ARB_enhanced_layouts : require\n"
20076 "\n"
20077 "VAR_DEFINITION"
20078 "\n"
20079 "in vec4 gs_fs;\n"
20080 "out vec4 fs_out;\n"
20081 "\n"
20082 "void main()\n"
20083 "{\n"
20084 " vec4 result = gs_fs;\n"
20085 "\n"
20086 " fs_out = result;\n"
20087 "}\n"
20088 "\n";
20089 static const GLchar* gs = "#version 430 core\n"
20090 "#extension GL_ARB_enhanced_layouts : require\n"
20091 "\n"
20092 "layout(points) in;\n"
20093 "layout(triangle_strip, max_vertices = 4) out;\n"
20094 "\n"
20095 "in vec4 tes_gs[];\n"
20096 "out vec4 gs_fs;\n"
20097 "\n"
20098 "void main()\n"
20099 "{\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 " gs_fs = tes_gs[0];\n"
20110 " gl_Position = vec4(1, 1, 0, 1);\n"
20111 " EmitVertex();\n"
20112 "}\n"
20113 "\n";
20114 static const GLchar* gs_tested = "#version 430 core\n"
20115 "#extension GL_ARB_enhanced_layouts : require\n"
20116 "\n"
20117 "layout(points) in;\n"
20118 "layout(triangle_strip, max_vertices = 4) out;\n"
20119 "\n"
20120 "VAR_DEFINITION"
20121 "\n"
20122 "in vec4 tes_gs[];\n"
20123 "out vec4 gs_fs;\n"
20124 "\n"
20125 "void main()\n"
20126 "{\n"
20127 " vec4 result = tes_gs[0];\n"
20128 "\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 " gs_fs = result;\n"
20139 " gl_Position = vec4(1, 1, 0, 1);\n"
20140 " EmitVertex();\n"
20141 "}\n"
20142 "\n";
20143 static const GLchar* tcs = "#version 430 core\n"
20144 "#extension GL_ARB_enhanced_layouts : require\n"
20145 "\n"
20146 "layout(vertices = 1) out;\n"
20147 "\n"
20148 "in vec4 vs_tcs[];\n"
20149 "out vec4 tcs_tes[];\n"
20150 "\n"
20151 "void main()\n"
20152 "{\n"
20153 "\n"
20154 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
20155 "\n"
20156 " gl_TessLevelOuter[0] = 1.0;\n"
20157 " gl_TessLevelOuter[1] = 1.0;\n"
20158 " gl_TessLevelOuter[2] = 1.0;\n"
20159 " gl_TessLevelOuter[3] = 1.0;\n"
20160 " gl_TessLevelInner[0] = 1.0;\n"
20161 " gl_TessLevelInner[1] = 1.0;\n"
20162 "}\n"
20163 "\n";
20164 static const GLchar* tcs_tested = "#version 430 core\n"
20165 "#extension GL_ARB_enhanced_layouts : require\n"
20166 "\n"
20167 "layout(vertices = 1) out;\n"
20168 "\n"
20169 "VAR_DEFINITION"
20170 "\n"
20171 "in vec4 vs_tcs[];\n"
20172 "out vec4 tcs_tes[];\n"
20173 "\n"
20174 "void main()\n"
20175 "{\n"
20176 " vec4 result = vs_tcs[gl_InvocationID];\n"
20177 "\n"
20178 " tcs_tes[gl_InvocationID] = result;\n"
20179 "\n"
20180 " gl_TessLevelOuter[0] = 1.0;\n"
20181 " gl_TessLevelOuter[1] = 1.0;\n"
20182 " gl_TessLevelOuter[2] = 1.0;\n"
20183 " gl_TessLevelOuter[3] = 1.0;\n"
20184 " gl_TessLevelInner[0] = 1.0;\n"
20185 " gl_TessLevelInner[1] = 1.0;\n"
20186 "}\n"
20187 "\n";
20188 static const GLchar* tes = "#version 430 core\n"
20189 "#extension GL_ARB_enhanced_layouts : require\n"
20190 "\n"
20191 "layout(isolines, point_mode) in;\n"
20192 "\n"
20193 "in vec4 tcs_tes[];\n"
20194 "out vec4 tes_gs;\n"
20195 "\n"
20196 "void main()\n"
20197 "{\n"
20198 " tes_gs = tcs_tes[0];\n"
20199 "}\n"
20200 "\n";
20201 static const GLchar* tes_tested = "#version 430 core\n"
20202 "#extension GL_ARB_enhanced_layouts : require\n"
20203 "\n"
20204 "layout(isolines, point_mode) in;\n"
20205 "\n"
20206 "VAR_DEFINITION"
20207 "\n"
20208 "in vec4 tcs_tes[];\n"
20209 "out vec4 tes_gs;\n"
20210 "\n"
20211 "void main()\n"
20212 "{\n"
20213 " vec4 result = tcs_tes[0];\n"
20214 "\n"
20215 " tes_gs += result;\n"
20216 "}\n"
20217 "\n";
20218 static const GLchar* vs = "#version 430 core\n"
20219 "#extension GL_ARB_enhanced_layouts : require\n"
20220 "\n"
20221 "in vec4 in_vs;\n"
20222 "out vec4 vs_tcs;\n"
20223 "\n"
20224 "void main()\n"
20225 "{\n"
20226 " vs_tcs = in_vs;\n"
20227 "}\n"
20228 "\n";
20229 static const GLchar* vs_tested = "#version 430 core\n"
20230 "#extension GL_ARB_enhanced_layouts : require\n"
20231 "\n"
20232 "VAR_DEFINITION"
20233 "\n"
20234 "in vec4 in_vs;\n"
20235 "out vec4 vs_tcs;\n"
20236 "\n"
20237 "void main()\n"
20238 "{\n"
20239 " vec4 result = in_vs;\n"
20240 "\n"
20241 " vs_tcs += result;\n"
20242 "}\n"
20243 "\n";
20244
20245 std::string source;
20246 testCase& test_case = m_test_cases[test_case_index];
20247
20248 if (test_case.m_stage == stage)
20249 {
20250 const GLchar* array = "";
20251 size_t position = 0;
20252 const GLchar* var_definition = 0;
20253
20254 switch (test_case.m_qualifier)
20255 {
20256 case BUFFER:
20257 var_definition = buffer_var_definition;
20258 break;
20259 case OFFSET:
20260 var_definition = offset_var_definition;
20261 break;
20262 case STRIDE:
20263 var_definition = stride_var_definition;
20264 break;
20265 default:
20266 TCU_FAIL("Invalid enum");
20267 }
20268
20269 switch (stage)
20270 {
20271 case Utils::Shader::FRAGMENT:
20272 source = fs_tested;
20273 break;
20274 case Utils::Shader::GEOMETRY:
20275 source = gs_tested;
20276 array = "[]";
20277 break;
20278 case Utils::Shader::TESS_CTRL:
20279 source = tcs_tested;
20280 array = "[]";
20281 break;
20282 case Utils::Shader::TESS_EVAL:
20283 source = tes_tested;
20284 array = "[]";
20285 break;
20286 case Utils::Shader::VERTEX:
20287 source = vs_tested;
20288 break;
20289 default:
20290 TCU_FAIL("Invalid enum");
20291 }
20292
20293 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
20294 position = 0;
20295 Utils::replaceToken("ARRAY", position, array, source);
20296 }
20297 else
20298 {
20299 switch (stage)
20300 {
20301 case Utils::Shader::FRAGMENT:
20302 source = fs;
20303 break;
20304 case Utils::Shader::GEOMETRY:
20305 source = gs;
20306 break;
20307 case Utils::Shader::TESS_CTRL:
20308 source = tcs;
20309 break;
20310 case Utils::Shader::TESS_EVAL:
20311 source = tes;
20312 break;
20313 case Utils::Shader::VERTEX:
20314 source = vs;
20315 break;
20316 default:
20317 TCU_FAIL("Invalid enum");
20318 }
20319 }
20320
20321 return source;
20322 }
20323
20324 /** Get description of test case
20325 *
20326 * @param test_case_index Index of test case
20327 *
20328 * @return Test case description
20329 **/
20330 std::string XFBInputTest::getTestCaseName(GLuint test_case_index)
20331 {
20332 std::stringstream stream;
20333 testCase& test_case = m_test_cases[test_case_index];
20334
20335 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", qualifier: ";
20336
20337 switch (test_case.m_qualifier)
20338 {
20339 case BUFFER:
20340 stream << "xfb_buffer";
20341 break;
20342 case OFFSET:
20343 stream << "xfb_offset";
20344 break;
20345 case STRIDE:
20346 stream << "xfb_stride";
20347 break;
20348 default:
20349 TCU_FAIL("Invalid enum");
20350 }
20351
20352 return stream.str();
20353 }
20354
20355 /** Get number of test cases
20356 *
20357 * @return Number of test cases
20358 **/
20359 GLuint XFBInputTest::getTestCaseNumber()
20360 {
20361 return static_cast<GLuint>(m_test_cases.size());
20362 }
20363
20364 /** Selects if "compute" stage is relevant for test
20365 *
20366 * @param ignored
20367 *
20368 * @return false
20369 **/
20370 bool XFBInputTest::isComputeRelevant(GLuint /* test_case_index */)
20371 {
20372 return false;
20373 }
20374
20375 /** Prepare all test cases
20376 *
20377 **/
20378 void XFBInputTest::testInit()
20379 {
20380 for (GLuint qualifier = 0; qualifier < QUALIFIERS_MAX; ++qualifier)
20381 {
20382 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
20383 {
20384 if (Utils::Shader::COMPUTE == stage)
20385 {
20386 continue;
20387 }
20388
20389 testCase test_case = { (QUALIFIERS)qualifier, (Utils::Shader::STAGES)stage };
20390
20391 m_test_cases.push_back(test_case);
20392 }
20393 }
20394 }
20395
20396 /* Constants used by XFBAllStagesTest */
20397 const GLuint XFBAllStagesTest::m_gs_index = 3;
20398
20399 /** Constructor
20400 *
20401 * @param context Test context
20402 **/
20403 XFBAllStagesTest::XFBAllStagesTest(deqp::Context& context)
20404 : BufferTestBase(context, "xfb_all_stages",
20405 "Test verifies that only last stage in vertex processing can output to transform feedback")
20406 {
20407 /* Nothing to be done here */
20408 }
20409
20410 /** Get descriptors of buffers necessary for test
20411 *
20412 * @param ignored
20413 * @param out_descriptors Descriptors of buffers used by test
20414 **/
20415 void XFBAllStagesTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
20416 bufferDescriptor::Vector& out_descriptors)
20417 {
20418 static const GLuint n_stages = 4;
20419 const Utils::Type& vec4 = Utils::Type::vec4;
20420
20421 /* Data */
20422 tcu::Vec4 sum;
20423
20424 /* Test uses single uniform and xfb per stage + uniform for fragment shader */
20425 out_descriptors.resize(n_stages * 2 + 1);
20426
20427 /* */
20428 for (GLuint i = 0; i < n_stages; ++i)
20429 {
20430 /* Get references */
20431 bufferDescriptor& uniform = out_descriptors[i + 0];
20432 bufferDescriptor& xfb = out_descriptors[i + n_stages];
20433
20434 /* Index */
20435 uniform.m_index = i;
20436 xfb.m_index = i;
20437
20438 /* Target */
20439 uniform.m_target = Utils::Buffer::Uniform;
20440 xfb.m_target = Utils::Buffer::Transform_feedback;
20441
20442 /* Data */
20443 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
20444
20445 sum += var;
20446
20447 uniform.m_initial_data.resize(vec4.GetSize());
20448 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
20449
20450 xfb.m_initial_data = vec4.GenerateDataPacked();
20451
20452 if (m_gs_index != i)
20453 {
20454 xfb.m_expected_data = xfb.m_initial_data;
20455 }
20456 else
20457 {
20458 xfb.m_expected_data.resize(vec4.GetSize());
20459 memcpy(&xfb.m_expected_data[0], sum.getPtr(), vec4.GetSize());
20460 }
20461 }
20462
20463 /* FS */
20464 {
20465 /* Get reference */
20466 bufferDescriptor& uniform = out_descriptors[n_stages * 2];
20467
20468 /* Index */
20469 uniform.m_index = n_stages;
20470
20471 /* Target */
20472 uniform.m_target = Utils::Buffer::Uniform;
20473
20474 /* Data */
20475 const tcu::Vec4 var(Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat(), Utils::GetRandFloat());
20476
20477 uniform.m_initial_data.resize(vec4.GetSize());
20478 memcpy(&uniform.m_initial_data[0], var.getPtr(), vec4.GetSize());
20479 }
20480 }
20481
20482 /** Get body of main function for given shader stage
20483 *
20484 * @param ignored
20485 * @param stage Shader stage
20486 * @param out_assignments Set to empty
20487 * @param out_calculations Set to empty
20488 **/
20489 void XFBAllStagesTest::getShaderBody(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20490 std::string& out_assignments, std::string& out_calculations)
20491 {
20492 out_calculations = "";
20493
20494 static const GLchar* vs = " vs_tcs = uni_vs;\n";
20495 static const GLchar* tcs = " tcs_tes[gl_InvocationID] = uni_tcs + vs_tcs[gl_InvocationID];\n";
20496 static const GLchar* tes = " tes_gs = uni_tes + tcs_tes[0];\n";
20497 static const GLchar* gs = " gs_fs = uni_gs + tes_gs[0];\n";
20498 static const GLchar* fs = " fs_out = uni_fs + gs_fs;\n";
20499
20500 const GLchar* assignments = 0;
20501 switch (stage)
20502 {
20503 case Utils::Shader::FRAGMENT:
20504 assignments = fs;
20505 break;
20506 case Utils::Shader::GEOMETRY:
20507 assignments = gs;
20508 break;
20509 case Utils::Shader::TESS_CTRL:
20510 assignments = tcs;
20511 break;
20512 case Utils::Shader::TESS_EVAL:
20513 assignments = tes;
20514 break;
20515 case Utils::Shader::VERTEX:
20516 assignments = vs;
20517 break;
20518 default:
20519 TCU_FAIL("Invalid enum");
20520 }
20521
20522 out_assignments = assignments;
20523 }
20524
20525 /** Get interface of shader
20526 *
20527 * @param ignored
20528 * @param stage Shader stage
20529 * @param out_interface Set to ""
20530 **/
20531 void XFBAllStagesTest::getShaderInterface(glw::GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20532 std::string& out_interface)
20533 {
20534 static const GLchar* vs = "layout(xfb_buffer = 0, xfb_offset = 0) out vec4 vs_tcs;\n"
20535 "layout(binding = 0) uniform vs_block {\n"
20536 " vec4 uni_vs;\n"
20537 "};\n";
20538 static const GLchar* tcs = " in vec4 vs_tcs[];\n"
20539 "layout(xfb_buffer = 1, xfb_offset = 0) out vec4 tcs_tes[1];\n"
20540 "layout(binding = 1) uniform tcs_block {\n"
20541 " vec4 uni_tcs;\n"
20542 "};\n";
20543 static const GLchar* tes = " in vec4 tcs_tes[];\n"
20544 "layout(xfb_buffer = 2, xfb_offset = 0) out vec4 tes_gs;\n"
20545 "layout(binding = 2) uniform tes_block {\n"
20546 " vec4 uni_tes;\n"
20547 "};\n";
20548 static const GLchar* gs = " in vec4 tes_gs[];\n"
20549 "layout(xfb_buffer = 3, xfb_offset = 0) out vec4 gs_fs;\n"
20550 "layout(binding = 3) uniform gs_block {\n"
20551 " vec4 uni_gs;\n"
20552 "};\n";
20553 static const GLchar* fs = " in vec4 gs_fs;\n"
20554 " out vec4 fs_out;\n"
20555 "layout(binding = 4) uniform fs_block {\n"
20556 " vec4 uni_fs;\n"
20557 "};\n";
20558
20559 const GLchar* interface = 0;
20560 switch (stage)
20561 {
20562 case Utils::Shader::FRAGMENT:
20563 interface = fs;
20564 break;
20565 case Utils::Shader::GEOMETRY:
20566 interface = gs;
20567 break;
20568 case Utils::Shader::TESS_CTRL:
20569 interface = tcs;
20570 break;
20571 case Utils::Shader::TESS_EVAL:
20572 interface = tes;
20573 break;
20574 case Utils::Shader::VERTEX:
20575 interface = vs;
20576 break;
20577 default:
20578 TCU_FAIL("Invalid enum");
20579 }
20580
20581 out_interface = interface;
20582 }
20583
20584 /* Constants used by XFBStrideOfEmptyListTest */
20585 const GLuint XFBStrideOfEmptyListTest::m_stride = 64;
20586
20587 /** Constructor
20588 *
20589 * @param context Test context
20590 **/
20591 XFBStrideOfEmptyListTest::XFBStrideOfEmptyListTest(deqp::Context& context)
20592 : BufferTestBase(
20593 context, "xfb_stride_of_empty_list",
20594 "Test verifies correct behavior when xfb_stride qualifier is specified but no xfb_offset is specified")
20595 {
20596 /* Nothing to be done here */
20597 }
20598
20599 /** Execute drawArrays for single vertex
20600 *
20601 * @param test_case_index Index of test case
20602 *
20603 * @return true if proper error is reported
20604 **/
20605 bool XFBStrideOfEmptyListTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20606 {
20607 const Functions& gl = m_context.getRenderContext().getFunctions();
20608 bool result = true;
20609
20610 /* Draw */
20611 gl.disable(GL_RASTERIZER_DISCARD);
20612 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20613
20614 gl.beginTransformFeedback(GL_POINTS);
20615 GLenum error = gl.getError();
20616 switch (test_case_index)
20617 {
20618 case VALID:
20619 if (GL_NO_ERROR != error)
20620 {
20621 gl.endTransformFeedback();
20622 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20623 }
20624
20625 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20626 error = gl.getError();
20627
20628 gl.endTransformFeedback();
20629 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20630 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20631
20632 break;
20633
20634 case FIRST_MISSING:
20635 if (GL_NO_ERROR == error)
20636 {
20637 gl.endTransformFeedback();
20638 }
20639
20640 if (GL_INVALID_OPERATION != error)
20641 {
20642 m_context.getTestContext().getLog()
20643 << tcu::TestLog::Message << "XFB at index 0, that is written by GS, is missing. It was expected that "
20644 "INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20645 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20646
20647 result = false;
20648 }
20649
20650 break;
20651
20652 case SECOND_MISSING:
20653 if (GL_NO_ERROR != error)
20654 {
20655 gl.endTransformFeedback();
20656 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20657 }
20658
20659 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20660 error = gl.getError();
20661
20662 gl.endTransformFeedback();
20663 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20664 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20665
20666 break;
20667 }
20668
20669 /* Done */
20670 return result;
20671 }
20672
20673 /** Get descriptors of buffers necessary for test
20674 *
20675 * @param test_case_index Index of test case
20676 * @param out_descriptors Descriptors of buffers used by test
20677 **/
20678 void XFBStrideOfEmptyListTest::getBufferDescriptors(glw::GLuint test_case_index,
20679 bufferDescriptor::Vector& out_descriptors)
20680 {
20681 switch (test_case_index)
20682 {
20683 case VALID:
20684 {
20685 /* Test needs single uniform and two xfbs */
20686 out_descriptors.resize(3);
20687
20688 /* Get references */
20689 bufferDescriptor& uniform = out_descriptors[0];
20690 bufferDescriptor& xfb_0 = out_descriptors[1];
20691 bufferDescriptor& xfb_1 = out_descriptors[2];
20692
20693 /* Index */
20694 uniform.m_index = 0;
20695 xfb_0.m_index = 0;
20696 xfb_1.m_index = 1;
20697
20698 /* Target */
20699 uniform.m_target = Utils::Buffer::Uniform;
20700 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20701 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20702
20703 /* Data */
20704 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20705
20706 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20707 xfb_0.m_expected_data = uniform.m_initial_data;
20708
20709 /* Data, contents are the same as no modification is expected */
20710 xfb_1.m_initial_data.resize(m_stride);
20711 xfb_1.m_expected_data.resize(m_stride);
20712
20713 for (GLuint i = 0; i < m_stride; ++i)
20714 {
20715 xfb_1.m_initial_data[0] = (glw::GLubyte)i;
20716 xfb_1.m_expected_data[0] = (glw::GLubyte)i;
20717 }
20718 }
20719
20720 break;
20721
20722 case FIRST_MISSING:
20723 {
20724 /* Test needs single uniform and two xfbs */
20725 out_descriptors.resize(2);
20726
20727 /* Get references */
20728 bufferDescriptor& uniform = out_descriptors[0];
20729 bufferDescriptor& xfb_1 = out_descriptors[1];
20730
20731 /* Index */
20732 uniform.m_index = 0;
20733 xfb_1.m_index = 1;
20734
20735 /* Target */
20736 uniform.m_target = Utils::Buffer::Uniform;
20737 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20738
20739 /* Data */
20740 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20741
20742 /* Draw call will not be executed, contents does not matter */
20743 xfb_1.m_initial_data.resize(m_stride);
20744 }
20745
20746 break;
20747
20748 case SECOND_MISSING:
20749 {
20750 /* Test needs single uniform and two xfbs */
20751 out_descriptors.resize(2);
20752
20753 /* Get references */
20754 bufferDescriptor& uniform = out_descriptors[0];
20755 bufferDescriptor& xfb_0 = out_descriptors[1];
20756
20757 /* Index */
20758 uniform.m_index = 0;
20759 xfb_0.m_index = 0;
20760
20761 /* Target */
20762 uniform.m_target = Utils::Buffer::Uniform;
20763 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20764
20765 /* Data */
20766 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20767
20768 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20769 xfb_0.m_expected_data = uniform.m_initial_data;
20770 }
20771
20772 break;
20773 }
20774 }
20775
20776 /** Get body of main function for given shader stage
20777 *
20778 * @param ignored
20779 * @param stage Shader stage
20780 * @param out_assignments Set to empty
20781 * @param out_calculations Set to empty
20782 **/
20783 void XFBStrideOfEmptyListTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20784 std::string& out_assignments, std::string& out_calculations)
20785 {
20786 out_calculations = "";
20787
20788 static const GLchar* gs = " gs_fs = uni_gs;\n";
20789 static const GLchar* fs = " fs_out = vec4(gs_fs);\n";
20790
20791 const GLchar* assignments = "";
20792 switch (stage)
20793 {
20794 case Utils::Shader::FRAGMENT:
20795 assignments = fs;
20796 break;
20797 case Utils::Shader::GEOMETRY:
20798 assignments = gs;
20799 break;
20800 default:
20801 break;
20802 }
20803
20804 out_assignments = assignments;
20805 }
20806
20807 /** Get interface of shader
20808 *
20809 * @param ignored
20810 * @param stage Shader stage
20811 * @param out_interface Set to ""
20812 **/
20813 void XFBStrideOfEmptyListTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
20814 std::string& out_interface)
20815 {
20816 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out vec4 gs_fs;\n"
20817 "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
20818 "\n"
20819 "layout (binding = 0) uniform gs_block {\n"
20820 " vec4 uni_gs;\n"
20821 "};\n";
20822 static const GLchar* fs = "in vec4 gs_fs;\n"
20823 "out vec4 fs_out;\n";
20824
20825 switch (stage)
20826 {
20827 case Utils::Shader::FRAGMENT:
20828 out_interface = fs;
20829 break;
20830 case Utils::Shader::GEOMETRY:
20831 out_interface = gs;
20832 break;
20833 default:
20834 out_interface = "";
20835 return;
20836 }
20837 }
20838
20839 /** Returns buffer details in human readable form.
20840 *
20841 * @param test_case_index Index of test case
20842 *
20843 * @return Case description
20844 **/
20845 std::string XFBStrideOfEmptyListTest::getTestCaseName(GLuint test_case_index)
20846 {
20847 std::string result;
20848
20849 switch (test_case_index)
20850 {
20851 case VALID:
20852 result = "Valid case";
20853 break;
20854 case FIRST_MISSING:
20855 result = "Missing xfb at index 0";
20856 break;
20857 case SECOND_MISSING:
20858 result = "Missing xfb at index 1";
20859 break;
20860 default:
20861 TCU_FAIL("Invalid enum");
20862 }
20863
20864 return result;
20865 }
20866
20867 /** Get number of test cases
20868 *
20869 * @return 3
20870 **/
20871 GLuint XFBStrideOfEmptyListTest::getTestCaseNumber()
20872 {
20873 return 3;
20874 }
20875
20876 /* Constants used by XFBStrideOfEmptyListTest */
20877 const GLuint XFBStrideOfEmptyListAndAPITest::m_stride = 64;
20878
20879 /** Constructor
20880 *
20881 * @param context Test context
20882 **/
20883 XFBStrideOfEmptyListAndAPITest::XFBStrideOfEmptyListAndAPITest(deqp::Context& context)
20884 : BufferTestBase(context, "xfb_stride_of_empty_list_and_api",
20885 "Test verifies that xfb_stride qualifier is not overriden by API")
20886 {
20887 /* Nothing to be done here */
20888 }
20889
20890 /** Execute drawArrays for single vertex
20891 *
20892 * @param test_case_index Index of test case
20893 *
20894 * @return true if proper error is reported
20895 **/
20896 bool XFBStrideOfEmptyListAndAPITest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
20897 {
20898 const Functions& gl = m_context.getRenderContext().getFunctions();
20899 bool result = true;
20900
20901 /* Draw */
20902 gl.disable(GL_RASTERIZER_DISCARD);
20903 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
20904
20905 gl.beginTransformFeedback(GL_POINTS);
20906 GLenum error = gl.getError();
20907 switch (test_case_index)
20908 {
20909 case VALID:
20910 if (GL_NO_ERROR != error)
20911 {
20912 gl.endTransformFeedback();
20913 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20914 }
20915
20916 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20917 error = gl.getError();
20918
20919 gl.endTransformFeedback();
20920 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20921 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20922
20923 break;
20924
20925 case FIRST_MISSING:
20926 if (GL_NO_ERROR != error)
20927 {
20928 gl.endTransformFeedback();
20929 GLU_EXPECT_NO_ERROR(error, "BeginTransformFeedback");
20930 }
20931
20932 gl.drawArrays(GL_PATCHES, 0 /* first */, 1 /* count */);
20933 error = gl.getError();
20934
20935 gl.endTransformFeedback();
20936 GLU_EXPECT_NO_ERROR(error, "DrawArrays");
20937 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
20938
20939 break;
20940
20941 case SECOND_MISSING:
20942 if (GL_NO_ERROR == error)
20943 {
20944 gl.endTransformFeedback();
20945 }
20946
20947 if (GL_INVALID_OPERATION != error)
20948 {
20949 m_context.getTestContext().getLog()
20950 << tcu::TestLog::Message << "XFB at index 1, that is declared as empty, is missing. It was expected "
20951 "that INVALID_OPERATION will generated by BeginTransformFeedback. Got: "
20952 << glu::getErrorStr(error) << tcu::TestLog::EndMessage;
20953
20954 result = false;
20955 }
20956
20957 break;
20958 }
20959
20960 /* Done */
20961 return result;
20962 }
20963
20964 /** Get descriptors of buffers necessary for test
20965 *
20966 * @param test_case_index Index of test case
20967 * @param out_descriptors Descriptors of buffers used by test
20968 **/
20969 void XFBStrideOfEmptyListAndAPITest::getBufferDescriptors(glw::GLuint test_case_index,
20970 bufferDescriptor::Vector& out_descriptors)
20971 {
20972 switch (test_case_index)
20973 {
20974 case VALID:
20975 {
20976 /* Test needs single uniform and two xfbs */
20977 out_descriptors.resize(3);
20978
20979 /* Get references */
20980 bufferDescriptor& uniform = out_descriptors[0];
20981 bufferDescriptor& xfb_0 = out_descriptors[1];
20982 bufferDescriptor& xfb_1 = out_descriptors[2];
20983
20984 /* Index */
20985 uniform.m_index = 0;
20986 xfb_0.m_index = 0;
20987 xfb_1.m_index = 1;
20988
20989 /* Target */
20990 uniform.m_target = Utils::Buffer::Uniform;
20991 xfb_0.m_target = Utils::Buffer::Transform_feedback;
20992 xfb_1.m_target = Utils::Buffer::Transform_feedback;
20993
20994 /* Data */
20995 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
20996
20997 /* Data, contents are the same as no modification is expected */
20998 xfb_0.m_initial_data.resize(m_stride);
20999 xfb_0.m_expected_data.resize(m_stride);
21000
21001 for (GLuint i = 0; i < m_stride; ++i)
21002 {
21003 xfb_0.m_initial_data[0] = (glw::GLubyte)i;
21004 xfb_0.m_expected_data[0] = (glw::GLubyte)i;
21005 }
21006
21007 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21008 xfb_1.m_expected_data = uniform.m_initial_data;
21009 }
21010
21011 break;
21012
21013 case FIRST_MISSING:
21014 {
21015 /* Test needs single uniform and two xfbs */
21016 out_descriptors.resize(2);
21017
21018 /* Get references */
21019 bufferDescriptor& uniform = out_descriptors[0];
21020 bufferDescriptor& xfb_1 = out_descriptors[1];
21021
21022 /* Index */
21023 uniform.m_index = 0;
21024 xfb_1.m_index = 1;
21025
21026 /* Target */
21027 uniform.m_target = Utils::Buffer::Uniform;
21028 xfb_1.m_target = Utils::Buffer::Transform_feedback;
21029
21030 /* Data */
21031 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21032
21033 /* Data, contents are the same as no modification is expected */
21034 xfb_1.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21035 xfb_1.m_expected_data = uniform.m_initial_data;
21036 }
21037
21038 break;
21039
21040 case SECOND_MISSING:
21041 {
21042 /* Test needs single uniform and two xfbs */
21043 out_descriptors.resize(2);
21044
21045 /* Get references */
21046 bufferDescriptor& uniform = out_descriptors[0];
21047 bufferDescriptor& xfb_0 = out_descriptors[1];
21048
21049 /* Index */
21050 uniform.m_index = 0;
21051 xfb_0.m_index = 0;
21052
21053 /* Target */
21054 uniform.m_target = Utils::Buffer::Uniform;
21055 xfb_0.m_target = Utils::Buffer::Transform_feedback;
21056
21057 /* Data */
21058 uniform.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21059
21060 /* Draw call will not be executed, contents does not matter */
21061 xfb_0.m_initial_data = Utils::Type::vec4.GenerateDataPacked();
21062 }
21063
21064 break;
21065 }
21066 }
21067
21068 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
21069 *
21070 * @param ignored
21071 * @param captured_varyings Vector of varying names to be captured
21072 **/
21073 void XFBStrideOfEmptyListAndAPITest::getCapturedVaryings(glw::GLuint /* test_case_index */,
21074 Utils::Program::NameVector& captured_varyings,
21075 GLint* xfb_components)
21076 {
21077 captured_varyings.push_back("gs_fs1");
21078 captured_varyings.push_back("gs_fs2");
21079 *xfb_components = 4;
21080 }
21081
21082 /** Get body of main function for given shader stage
21083 *
21084 * @param ignored
21085 * @param stage Shader stage
21086 * @param out_assignments Set to empty
21087 * @param out_calculations Set to empty
21088 **/
21089 void XFBStrideOfEmptyListAndAPITest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21090 std::string& out_assignments, std::string& out_calculations)
21091 {
21092 out_calculations = "";
21093
21094 static const GLchar* gs = " gs_fs1 = -uni_gs;\n"
21095 " gs_fs2 = uni_gs;\n";
21096 static const GLchar* fs = " fs_out = vec4(gs_fs2);\n";
21097
21098 const GLchar* assignments = "";
21099 switch (stage)
21100 {
21101 case Utils::Shader::FRAGMENT:
21102 assignments = fs;
21103 break;
21104 case Utils::Shader::GEOMETRY:
21105 assignments = gs;
21106 break;
21107 default:
21108 break;
21109 }
21110
21111 out_assignments = assignments;
21112 }
21113
21114 /** Get interface of shader
21115 *
21116 * @param ignored
21117 * @param stage Shader stage
21118 * @param out_interface Set to ""
21119 **/
21120 void XFBStrideOfEmptyListAndAPITest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
21121 std::string& out_interface)
21122 {
21123 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_stride = 64) out vec4 gs_fs1;\n"
21124 "layout (xfb_buffer = 1, xfb_offset = 0) out vec4 gs_fs2;\n"
21125 "\n"
21126 "layout(binding = 0) uniform gs_block {\n"
21127 " vec4 uni_gs;\n"
21128 "};\n";
21129 static const GLchar* fs = "in vec4 gs_fs2;\n"
21130 "out vec4 fs_out;\n";
21131
21132 switch (stage)
21133 {
21134 case Utils::Shader::FRAGMENT:
21135 out_interface = fs;
21136 break;
21137 case Utils::Shader::GEOMETRY:
21138 out_interface = gs;
21139 break;
21140 default:
21141 out_interface = "";
21142 return;
21143 }
21144 }
21145
21146 /** Returns buffer details in human readable form.
21147 *
21148 * @param test_case_index Index of test case
21149 *
21150 * @return Case description
21151 **/
21152 std::string XFBStrideOfEmptyListAndAPITest::getTestCaseName(GLuint test_case_index)
21153 {
21154 std::string result;
21155
21156 switch (test_case_index)
21157 {
21158 case VALID:
21159 result = "Valid case";
21160 break;
21161 case FIRST_MISSING:
21162 result = "Missing xfb at index 0";
21163 break;
21164 case SECOND_MISSING:
21165 result = "Missing xfb at index 1";
21166 break;
21167 default:
21168 TCU_FAIL("Invalid enum");
21169 }
21170
21171 return result;
21172 }
21173
21174 /** Get number of test cases
21175 *
21176 * @return 2
21177 **/
21178 GLuint XFBStrideOfEmptyListAndAPITest::getTestCaseNumber()
21179 {
21180 return 3;
21181 }
21182
21183 /** Constructor
21184 *
21185 * @param context Test framework context
21186 **/
21187 XFBTooSmallStrideTest::XFBTooSmallStrideTest(deqp::Context& context)
21188 : NegativeTestBase(context, "xfb_too_small_stride",
21189 "Test verifies that compiler reports error when xfb_stride sets not enough space")
21190 {
21191 }
21192
21193 /** Source for given test case and stage
21194 *
21195 * @param test_case_index Index of test case
21196 * @param stage Shader stage
21197 *
21198 * @return Shader source
21199 **/
21200 std::string XFBTooSmallStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21201 {
21202 #if DEBUG_NEG_REMOVE_ERROR
21203 static const GLchar* array_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 32 */ ) out;\n"
21204 #else
21205 static const GLchar* array_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
21206 #endif /* DEBUG_NEG_REMOVE_ERROR */
21207 "\n"
21208 "layout (xfb_offset = 16) out vec4 gohan[4];\n";
21209 #if DEBUG_NEG_REMOVE_ERROR
21210 static const GLchar* block_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 32 */ ) out;\n"
21211 #else
21212 static const GLchar* block_var_definition = "layout (xfb_buffer = 0, xfb_stride = 32) out;\n"
21213 #endif /* DEBUG_NEG_REMOVE_ERROR */
21214 "\n"
21215 "layout (xfb_offset = 0) out Goku {\n"
21216 " vec4 gohan;\n"
21217 " vec4 goten;\n"
21218 " vec4 chichi;\n"
21219 "} goku;\n";
21220 #if DEBUG_NEG_REMOVE_ERROR
21221 static const GLchar* offset_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 40 */ ) out;\n"
21222 #else
21223 static const GLchar* offset_var_definition = "layout (xfb_buffer = 0, xfb_stride = 40) out;\n"
21224 #endif /* DEBUG_NEG_REMOVE_ERROR */
21225 "\n"
21226 "layout (xfb_offset = 32) out vec4 gohan;\n";
21227 // 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;"
21228 // To make the shader failed to compile, change xfb_stride to a value that is smaller than 32
21229 #if DEBUG_NEG_REMOVE_ERROR
21230 static const GLchar* stride_var_definition = "layout (xfb_buffer = 0 /*, xfb_stride = 28 */ ) out;\n"
21231 "\n"
21232 "layout (xfb_offset = 16 /*, xfb_stride = 28 */ ) out vec4 gohan;\n";
21233 #else
21234 static const GLchar* stride_var_definition = "layout (xfb_buffer = 0, xfb_stride = 28) out;\n"
21235 "\n"
21236 "layout (xfb_offset = 16, xfb_stride = 28) out vec4 gohan;\n";
21237 #endif /* DEBUG_NEG_REMOVE_ERROR */
21238 static const GLchar* array_use = " gohan[0] = result / 2;\n"
21239 " gohan[1] = result / 4;\n"
21240 " gohan[2] = result / 6;\n"
21241 " gohan[3] = result / 8;\n";
21242 static const GLchar* block_use = " goku.gohan = result / 2;\n"
21243 " goku.goten = result / 4;\n"
21244 " goku.chichi = result / 6;\n";
21245 static const GLchar* output_use = "gohan = result / 4;\n";
21246 static const GLchar* fs = "#version 430 core\n"
21247 "#extension GL_ARB_enhanced_layouts : require\n"
21248 "\n"
21249 "in vec4 any_fs;\n"
21250 "out vec4 fs_out;\n"
21251 "\n"
21252 "void main()\n"
21253 "{\n"
21254 " fs_out = any_fs;\n"
21255 "}\n"
21256 "\n";
21257 static const GLchar* gs_tested = "#version 430 core\n"
21258 "#extension GL_ARB_enhanced_layouts : require\n"
21259 "\n"
21260 "layout(points) in;\n"
21261 "layout(triangle_strip, max_vertices = 4) out;\n"
21262 "\n"
21263 "VAR_DEFINITION"
21264 "\n"
21265 "in vec4 vs_any[];\n"
21266 "out vec4 any_fs;\n"
21267 "\n"
21268 "void main()\n"
21269 "{\n"
21270 " vec4 result = vs_any[0];\n"
21271 "\n"
21272 "VARIABLE_USE"
21273 "\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 " any_fs = result;\n"
21284 " gl_Position = vec4(1, 1, 0, 1);\n"
21285 " EmitVertex();\n"
21286 "}\n"
21287 "\n";
21288 static const GLchar* tcs = "#version 430 core\n"
21289 "#extension GL_ARB_enhanced_layouts : require\n"
21290 "\n"
21291 "layout(vertices = 1) out;\n"
21292 "\n"
21293 "in vec4 vs_any[];\n"
21294 "out vec4 tcs_tes[];\n"
21295 "\n"
21296 "void main()\n"
21297 "{\n"
21298 "\n"
21299 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
21300 "\n"
21301 " gl_TessLevelOuter[0] = 1.0;\n"
21302 " gl_TessLevelOuter[1] = 1.0;\n"
21303 " gl_TessLevelOuter[2] = 1.0;\n"
21304 " gl_TessLevelOuter[3] = 1.0;\n"
21305 " gl_TessLevelInner[0] = 1.0;\n"
21306 " gl_TessLevelInner[1] = 1.0;\n"
21307 "}\n"
21308 "\n";
21309 static const GLchar* tes_tested = "#version 430 core\n"
21310 "#extension GL_ARB_enhanced_layouts : require\n"
21311 "\n"
21312 "layout(isolines, point_mode) in;\n"
21313 "\n"
21314 "VAR_DEFINITION"
21315 "\n"
21316 "in vec4 tcs_tes[];\n"
21317 "out vec4 any_fs;\n"
21318 "\n"
21319 "void main()\n"
21320 "{\n"
21321 " vec4 result = tcs_tes[0];\n"
21322 "\n"
21323 "VARIABLE_USE"
21324 "\n"
21325 " any_fs += result;\n"
21326 "}\n"
21327 "\n";
21328 static const GLchar* vs = "#version 430 core\n"
21329 "#extension GL_ARB_enhanced_layouts : require\n"
21330 "\n"
21331 "in vec4 in_vs;\n"
21332 "out vec4 vs_any;\n"
21333 "\n"
21334 "void main()\n"
21335 "{\n"
21336 " vs_any = in_vs;\n"
21337 "}\n"
21338 "\n";
21339 static const GLchar* vs_tested = "#version 430 core\n"
21340 "#extension GL_ARB_enhanced_layouts : require\n"
21341 "\n"
21342 "VAR_DEFINITION"
21343 "\n"
21344 "in vec4 in_vs;\n"
21345 "out vec4 any_fs;\n"
21346 "\n"
21347 "void main()\n"
21348 "{\n"
21349 " vec4 result = in_vs;\n"
21350 "\n"
21351 "VARIABLE_USE"
21352 "\n"
21353 " any_fs += result;\n"
21354 "}\n"
21355 "\n";
21356
21357 std::string source;
21358 testCase& test_case = m_test_cases[test_case_index];
21359
21360 if (test_case.m_stage == stage)
21361 {
21362 size_t position = 0;
21363 const GLchar* var_definition = 0;
21364 const GLchar* var_use = 0;
21365
21366 switch (test_case.m_case)
21367 {
21368 case OFFSET:
21369 var_definition = offset_var_definition;
21370 var_use = output_use;
21371 break;
21372 case STRIDE:
21373 var_definition = stride_var_definition;
21374 var_use = output_use;
21375 break;
21376 case BLOCK:
21377 var_definition = block_var_definition;
21378 var_use = block_use;
21379 break;
21380 case ARRAY:
21381 var_definition = array_var_definition;
21382 var_use = array_use;
21383 break;
21384 default:
21385 TCU_FAIL("Invalid enum");
21386 }
21387
21388 switch (stage)
21389 {
21390 case Utils::Shader::GEOMETRY:
21391 source = gs_tested;
21392 break;
21393 case Utils::Shader::TESS_EVAL:
21394 source = tes_tested;
21395 break;
21396 case Utils::Shader::VERTEX:
21397 source = vs_tested;
21398 break;
21399 default:
21400 TCU_FAIL("Invalid enum");
21401 }
21402
21403 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21404 position = 0;
21405 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21406 }
21407 else
21408 {
21409 switch (test_case.m_stage)
21410 {
21411 case Utils::Shader::GEOMETRY:
21412 switch (stage)
21413 {
21414 case Utils::Shader::FRAGMENT:
21415 source = fs;
21416 break;
21417 case Utils::Shader::VERTEX:
21418 source = vs;
21419 break;
21420 default:
21421 source = "";
21422 }
21423 break;
21424 case Utils::Shader::TESS_EVAL:
21425 switch (stage)
21426 {
21427 case Utils::Shader::FRAGMENT:
21428 source = fs;
21429 break;
21430 case Utils::Shader::TESS_CTRL:
21431 source = tcs;
21432 break;
21433 case Utils::Shader::VERTEX:
21434 source = vs;
21435 break;
21436 default:
21437 source = "";
21438 }
21439 break;
21440 case Utils::Shader::VERTEX:
21441 switch (stage)
21442 {
21443 case Utils::Shader::FRAGMENT:
21444 source = fs;
21445 break;
21446 default:
21447 source = "";
21448 }
21449 break;
21450 default:
21451 TCU_FAIL("Invalid enum");
21452 break;
21453 }
21454 }
21455
21456 return source;
21457 }
21458
21459 /** Get description of test case
21460 *
21461 * @param test_case_index Index of test case
21462 *
21463 * @return Test case description
21464 **/
21465 std::string XFBTooSmallStrideTest::getTestCaseName(GLuint test_case_index)
21466 {
21467 std::stringstream stream;
21468 testCase& test_case = m_test_cases[test_case_index];
21469
21470 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
21471
21472 switch (test_case.m_case)
21473 {
21474 case OFFSET:
21475 stream << "buffer stride: 40, vec4 offset: 32";
21476 break;
21477 case STRIDE:
21478 stream << "buffer stride: 32, vec4 off 16 stride: 32";
21479 break;
21480 case BLOCK:
21481 stream << "buffer stride: 32, block 3xvec4 offset 0";
21482 break;
21483 case ARRAY:
21484 stream << "buffer stride: 32, vec4[4] offset 16";
21485 break;
21486 default:
21487 TCU_FAIL("Invalid enum");
21488 }
21489
21490 return stream.str();
21491 }
21492
21493 /** Get number of test cases
21494 *
21495 * @return Number of test cases
21496 **/
21497 GLuint XFBTooSmallStrideTest::getTestCaseNumber()
21498 {
21499 return static_cast<GLuint>(m_test_cases.size());
21500 }
21501
21502 /** Selects if "compute" stage is relevant for test
21503 *
21504 * @param ignored
21505 *
21506 * @return false
21507 **/
21508 bool XFBTooSmallStrideTest::isComputeRelevant(GLuint /* test_case_index */)
21509 {
21510 return false;
21511 }
21512
21513 /** Prepare all test cases
21514 *
21515 **/
21516 void XFBTooSmallStrideTest::testInit()
21517 {
21518 for (GLuint c = 0; c < CASE_MAX; ++c)
21519 {
21520 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21521 {
21522 /*
21523 It is invalid to define transform feedback output in TCS, according to spec:
21524 The data captured in transform feedback mode depends on the active programs on each of the shader stages.
21525 If a program is active for the geometry shader stage, transform feedback captures the vertices of each
21526 primitive emitted by the geometry shader. Otherwise, if a program is active for the tessellation evaluation
21527 shader stage, transform feedback captures each primitive produced by the tessellation primitive generator,
21528 whose vertices are processed by the tessellation evaluation shader. Otherwise, transform feedback captures
21529 each primitive processed by the vertex shader.
21530 */
21531 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21532 (Utils::Shader::FRAGMENT == stage))
21533 {
21534 continue;
21535 }
21536
21537 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
21538
21539 m_test_cases.push_back(test_case);
21540 }
21541 }
21542 }
21543
21544 /** Constructor
21545 *
21546 * @param context Test framework context
21547 **/
21548 XFBVariableStrideTest::XFBVariableStrideTest(deqp::Context& context)
21549 : NegativeTestBase(context, "xfb_variable_stride", "Test verifies that stride qualifier is respected")
21550 {
21551 }
21552
21553 /** Source for given test case and stage
21554 *
21555 * @param test_case_index Index of test case
21556 * @param stage Shader stage
21557 *
21558 * @return Shader source
21559 **/
21560 std::string XFBVariableStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21561 {
21562 static const GLchar* invalid_var_definition = "const uint type_size = SIZE;\n"
21563 "\n"
21564 #if DEBUG_NEG_REMOVE_ERROR
21565 "layout (xfb_stride = 2 * type_size) out;\n"
21566 #else
21567 "layout (xfb_stride = type_size) out;\n"
21568 #endif /* DEBUG_NEG_REMOVE_ERROR */
21569 "\n"
21570 "layout (xfb_offset = 0) out TYPE goku;\n"
21571 "layout (xfb_offset = type_size) out TYPE vegeta;\n";
21572 static const GLchar* valid_var_definition = "const uint type_size = SIZE;\n"
21573 "\n"
21574 "layout (xfb_stride = type_size) out;\n"
21575 "\n"
21576 "layout (xfb_offset = 0) out TYPE goku;\n";
21577 static const GLchar* invalid_use = " goku = TYPE(1);\n"
21578 " vegeta = TYPE(0);\n"
21579 " if (vec4(0) == result)\n"
21580 " {\n"
21581 " goku = TYPE(0);\n"
21582 " vegeta = TYPE(1);\n"
21583 " }\n";
21584 static const GLchar* valid_use = " goku = TYPE(1);\n"
21585 " if (vec4(0) == result)\n"
21586 " {\n"
21587 " goku = TYPE(0);\n"
21588 " }\n";
21589 static const GLchar* fs = "#version 430 core\n"
21590 "#extension GL_ARB_enhanced_layouts : require\n"
21591 "\n"
21592 "in vec4 any_fs;\n"
21593 "out vec4 fs_out;\n"
21594 "\n"
21595 "void main()\n"
21596 "{\n"
21597 " fs_out = any_fs;\n"
21598 "}\n"
21599 "\n";
21600 static const GLchar* gs_tested = "#version 430 core\n"
21601 "#extension GL_ARB_enhanced_layouts : require\n"
21602 "\n"
21603 "layout(points) in;\n"
21604 "layout(triangle_strip, max_vertices = 4) out;\n"
21605 "\n"
21606 "VAR_DEFINITION"
21607 "\n"
21608 "in vec4 vs_any[];\n"
21609 "out vec4 any_fs;\n"
21610 "\n"
21611 "void main()\n"
21612 "{\n"
21613 " vec4 result = vs_any[0];\n"
21614 "\n"
21615 "VARIABLE_USE"
21616 "\n"
21617 " any_fs = result;\n"
21618 " gl_Position = vec4(-1, -1, 0, 1);\n"
21619 " EmitVertex();\n"
21620 " any_fs = result;\n"
21621 " gl_Position = vec4(-1, 1, 0, 1);\n"
21622 " EmitVertex();\n"
21623 " any_fs = result;\n"
21624 " gl_Position = vec4(1, -1, 0, 1);\n"
21625 " EmitVertex();\n"
21626 " any_fs = result;\n"
21627 " gl_Position = vec4(1, 1, 0, 1);\n"
21628 " EmitVertex();\n"
21629 "}\n"
21630 "\n";
21631 static const GLchar* tcs = "#version 430 core\n"
21632 "#extension GL_ARB_enhanced_layouts : require\n"
21633 "\n"
21634 "layout(vertices = 1) out;\n"
21635 "\n"
21636 "in vec4 vs_any[];\n"
21637 "out vec4 tcs_tes[];\n"
21638 "\n"
21639 "void main()\n"
21640 "{\n"
21641 "\n"
21642 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
21643 "\n"
21644 " gl_TessLevelOuter[0] = 1.0;\n"
21645 " gl_TessLevelOuter[1] = 1.0;\n"
21646 " gl_TessLevelOuter[2] = 1.0;\n"
21647 " gl_TessLevelOuter[3] = 1.0;\n"
21648 " gl_TessLevelInner[0] = 1.0;\n"
21649 " gl_TessLevelInner[1] = 1.0;\n"
21650 "}\n"
21651 "\n";
21652 static const GLchar* tes_tested = "#version 430 core\n"
21653 "#extension GL_ARB_enhanced_layouts : require\n"
21654 "\n"
21655 "layout(isolines, point_mode) in;\n"
21656 "\n"
21657 "VAR_DEFINITION"
21658 "\n"
21659 "in vec4 tcs_tes[];\n"
21660 "out vec4 any_fs;\n"
21661 "\n"
21662 "void main()\n"
21663 "{\n"
21664 " vec4 result = tcs_tes[0];\n"
21665 "\n"
21666 "VARIABLE_USE"
21667 "\n"
21668 " any_fs = result;\n"
21669 "}\n"
21670 "\n";
21671 static const GLchar* vs = "#version 430 core\n"
21672 "#extension GL_ARB_enhanced_layouts : require\n"
21673 "\n"
21674 "in vec4 in_vs;\n"
21675 "out vec4 vs_any;\n"
21676 "\n"
21677 "void main()\n"
21678 "{\n"
21679 " vs_any = in_vs;\n"
21680 "}\n"
21681 "\n";
21682 static const GLchar* vs_tested = "#version 430 core\n"
21683 "#extension GL_ARB_enhanced_layouts : require\n"
21684 "\n"
21685 "VAR_DEFINITION"
21686 "\n"
21687 "in vec4 in_vs;\n"
21688 "out vec4 any_fs;\n"
21689 "\n"
21690 "void main()\n"
21691 "{\n"
21692 " vec4 result = in_vs;\n"
21693 "\n"
21694 "VARIABLE_USE"
21695 "\n"
21696 " any_fs = result;\n"
21697 "}\n"
21698 "\n";
21699
21700 std::string source;
21701 testCase& test_case = m_test_cases[test_case_index];
21702
21703 if (test_case.m_stage == stage)
21704 {
21705 GLchar buffer[16];
21706 size_t position = 0;
21707 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
21708 const GLchar* var_definition = 0;
21709 const GLchar* var_use = 0;
21710
21711 sprintf(buffer, "%d", test_case.m_type.GetSize());
21712
21713 switch (test_case.m_case)
21714 {
21715 case VALID:
21716 var_definition = valid_var_definition;
21717 var_use = valid_use;
21718 break;
21719 case INVALID:
21720 var_definition = invalid_var_definition;
21721 var_use = invalid_use;
21722 break;
21723 default:
21724 TCU_FAIL("Invalid enum");
21725 }
21726
21727 switch (stage)
21728 {
21729 case Utils::Shader::GEOMETRY:
21730 source = gs_tested;
21731 break;
21732 case Utils::Shader::TESS_EVAL:
21733 source = tes_tested;
21734 break;
21735 case Utils::Shader::VERTEX:
21736 source = vs_tested;
21737 break;
21738 default:
21739 TCU_FAIL("Invalid enum");
21740 }
21741
21742 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
21743 position = 0;
21744 Utils::replaceToken("SIZE", position, buffer, source);
21745 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
21746
21747 Utils::replaceAllTokens("TYPE", type_name, source);
21748 }
21749 else
21750 {
21751 switch (test_case.m_stage)
21752 {
21753 case Utils::Shader::GEOMETRY:
21754 switch (stage)
21755 {
21756 case Utils::Shader::FRAGMENT:
21757 source = fs;
21758 break;
21759 case Utils::Shader::VERTEX:
21760 source = vs;
21761 break;
21762 default:
21763 source = "";
21764 }
21765 break;
21766 case Utils::Shader::TESS_EVAL:
21767 switch (stage)
21768 {
21769 case Utils::Shader::FRAGMENT:
21770 source = fs;
21771 break;
21772 case Utils::Shader::TESS_CTRL:
21773 source = tcs;
21774 break;
21775 case Utils::Shader::VERTEX:
21776 source = vs;
21777 break;
21778 default:
21779 source = "";
21780 }
21781 break;
21782 case Utils::Shader::VERTEX:
21783 switch (stage)
21784 {
21785 case Utils::Shader::FRAGMENT:
21786 source = fs;
21787 break;
21788 default:
21789 source = "";
21790 }
21791 break;
21792 default:
21793 TCU_FAIL("Invalid enum");
21794 break;
21795 }
21796 }
21797
21798 return source;
21799 }
21800
21801 /** Get description of test case
21802 *
21803 * @param test_case_index Index of test case
21804 *
21805 * @return Test case description
21806 **/
21807 std::string XFBVariableStrideTest::getTestCaseName(GLuint test_case_index)
21808 {
21809 std::stringstream stream;
21810 testCase& test_case = m_test_cases[test_case_index];
21811
21812 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
21813 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
21814
21815 switch (test_case.m_case)
21816 {
21817 case VALID:
21818 stream << "valid";
21819 break;
21820 case INVALID:
21821 stream << "invalid";
21822 break;
21823 default:
21824 TCU_FAIL("Invalid enum");
21825 }
21826
21827 return stream.str();
21828 }
21829
21830 /** Get number of test cases
21831 *
21832 * @return Number of test cases
21833 **/
21834 GLuint XFBVariableStrideTest::getTestCaseNumber()
21835 {
21836 return static_cast<GLuint>(m_test_cases.size());
21837 }
21838
21839 /** Selects if "compute" stage is relevant for test
21840 *
21841 * @param ignored
21842 *
21843 * @return false
21844 **/
21845 bool XFBVariableStrideTest::isComputeRelevant(GLuint /* test_case_index */)
21846 {
21847 return false;
21848 }
21849
21850 /** Selects if compilation failure is expected result
21851 *
21852 * @param test_case_index Index of test case
21853 *
21854 * @return true
21855 **/
21856 bool XFBVariableStrideTest::isFailureExpected(GLuint test_case_index)
21857 {
21858 testCase& test_case = m_test_cases[test_case_index];
21859
21860 return (INVALID == test_case.m_case);
21861 }
21862
21863 /** Prepare all test cases
21864 *
21865 **/
21866 void XFBVariableStrideTest::testInit()
21867 {
21868 const GLuint n_types = getTypesNumber();
21869
21870 for (GLuint i = 0; i < n_types; ++i)
21871 {
21872 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
21873 {
21874 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
21875 (Utils::Shader::FRAGMENT == stage))
21876 {
21877 continue;
21878 }
21879
21880 const Utils::Type& type = getType(i);
21881 for (GLuint c = 0; c < CASE_MAX; ++c)
21882 {
21883 testCase test_case = { static_cast<CASES>(c), static_cast<Utils::Shader::STAGES>(stage), type };
21884
21885 m_test_cases.push_back(test_case);
21886 }
21887 }
21888 }
21889 }
21890
21891 /** Constructor
21892 *
21893 * @param context Test framework context
21894 **/
21895 XFBBlockStrideTest::XFBBlockStrideTest(deqp::Context& context)
21896 : TestBase(context, "xfb_block_stride", "Test verifies that stride qualifier is respected for blocks")
21897 {
21898 }
21899
21900 /** Source for given test case and stage
21901 *
21902 * @param test_case_index Index of test case
21903 * @param stage Shader stage
21904 *
21905 * @return Shader source
21906 **/
21907 std::string XFBBlockStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
21908 {
21909 static const GLchar* var_definition = "layout (xfb_offset = 0, xfb_stride = 128) out Goku {\n"
21910 " vec4 gohan;\n"
21911 " vec4 goten;\n"
21912 " vec4 chichi;\n"
21913 "} gokuARRAY;\n";
21914 static const GLchar* var_use = " gokuINDEX.gohan = vec4(1, 0, 0, 0);\n"
21915 " gokuINDEX.goten = vec4(0, 0, 1, 0);\n"
21916 " gokuINDEX.chichi = vec4(0, 1, 0, 0);\n"
21917 " if (vec4(0) == result)\n"
21918 " {\n"
21919 " gokuINDEX.gohan = vec4(0, 1, 1, 1);\n"
21920 " gokuINDEX.goten = vec4(1, 1, 0, 1);\n"
21921 " gokuINDEX.chichi = vec4(1, 0, 1, 1);\n"
21922 " }\n";
21923 static const GLchar* gs_tested =
21924 "#version 430 core\n"
21925 "#extension GL_ARB_enhanced_layouts : require\n"
21926 "\n"
21927 "layout(points) in;\n"
21928 "layout(triangle_strip, max_vertices = 4) out;\n"
21929 "\n"
21930 "VAR_DEFINITION"
21931 "\n"
21932 "out gl_PerVertex \n"
21933 "{ \n"
21934 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
21935 "}; \n"
21936 "in vec4 tes_gs[];\n"
21937 "out vec4 gs_fs;\n"
21938 "\n"
21939 "void main()\n"
21940 "{\n"
21941 " vec4 result = tes_gs[0];\n"
21942 "\n"
21943 "VARIABLE_USE"
21944 "\n"
21945 " gs_fs = result;\n"
21946 " gl_Position = vec4(-1, -1, 0, 1);\n"
21947 " EmitVertex();\n"
21948 " gs_fs = result;\n"
21949 " gl_Position = vec4(-1, 1, 0, 1);\n"
21950 " EmitVertex();\n"
21951 " gs_fs = result;\n"
21952 " gl_Position = vec4(1, -1, 0, 1);\n"
21953 " EmitVertex();\n"
21954 " gs_fs = result;\n"
21955 " gl_Position = vec4(1, 1, 0, 1);\n"
21956 " EmitVertex();\n"
21957 "}\n"
21958 "\n";
21959 static const GLchar* tcs = "#version 430 core\n"
21960 "#extension GL_ARB_enhanced_layouts : require\n"
21961 "\n"
21962 "layout(vertices = 1) out;\n"
21963 "\n"
21964 "in vec4 vs_tcs[];\n"
21965 "out vec4 tcs_tes[];\n"
21966 "\n"
21967 "void main()\n"
21968 "{\n"
21969 "\n"
21970 " tcs_tes[gl_InvocationID] = vs_tcs[gl_InvocationID];\n"
21971 "\n"
21972 " gl_TessLevelOuter[0] = 1.0;\n"
21973 " gl_TessLevelOuter[1] = 1.0;\n"
21974 " gl_TessLevelOuter[2] = 1.0;\n"
21975 " gl_TessLevelOuter[3] = 1.0;\n"
21976 " gl_TessLevelInner[0] = 1.0;\n"
21977 " gl_TessLevelInner[1] = 1.0;\n"
21978 "}\n"
21979 "\n";
21980 #if 0
21981 static const GLchar* tcs_tested =
21982 "#version 430 core\n"
21983 "#extension GL_ARB_enhanced_layouts : require\n"
21984 "\n"
21985 "layout(vertices = 1) out;\n"
21986 "\n"
21987 "VAR_DEFINITION"
21988 "\n"
21989 "in vec4 vs_tcs[];\n"
21990 "out vec4 tcs_tes[];\n"
21991 "\n"
21992 "void main()\n"
21993 "{\n"
21994 " vec4 result = vs_tcs[gl_InvocationID];\n"
21995 "\n"
21996 "VARIABLE_USE"
21997 "\n"
21998 " tcs_tes[gl_InvocationID] = result;\n"
21999 "\n"
22000 " gl_TessLevelOuter[0] = 1.0;\n"
22001 " gl_TessLevelOuter[1] = 1.0;\n"
22002 " gl_TessLevelOuter[2] = 1.0;\n"
22003 " gl_TessLevelOuter[3] = 1.0;\n"
22004 " gl_TessLevelInner[0] = 1.0;\n"
22005 " gl_TessLevelInner[1] = 1.0;\n"
22006 "}\n"
22007 "\n";
22008 #endif
22009 static const GLchar* tes_tested = "#version 430 core\n"
22010 "#extension GL_ARB_enhanced_layouts : require\n"
22011 "\n"
22012 "layout(isolines, point_mode) in;\n"
22013 "\n"
22014 "VAR_DEFINITION"
22015 "\n"
22016 "in vec4 tcs_tes[];\n"
22017 "out vec4 tes_gs;\n"
22018 "\n"
22019 "void main()\n"
22020 "{\n"
22021 " vec4 result = tcs_tes[0];\n"
22022 "\n"
22023 "VARIABLE_USE"
22024 "\n"
22025 " tes_gs += result;\n"
22026 "}\n"
22027 "\n";
22028 static const GLchar* vs = "#version 430 core\n"
22029 "#extension GL_ARB_enhanced_layouts : require\n"
22030 "\n"
22031 "in vec4 in_vs;\n"
22032 "out vec4 vs_tcs;\n"
22033 "out vec4 tes_gs;\n"
22034 "\n"
22035 "void main()\n"
22036 "{\n"
22037 " vs_tcs = tes_gs = in_vs;\n"
22038 "}\n"
22039 "\n";
22040 static const GLchar* vs_tested = "#version 430 core\n"
22041 "#extension GL_ARB_enhanced_layouts : require\n"
22042 "\n"
22043 "VAR_DEFINITION"
22044 "\n"
22045 "in vec4 in_vs;\n"
22046 "out vec4 vs_tcs;\n"
22047 "\n"
22048 "void main()\n"
22049 "{\n"
22050 " vec4 result = in_vs;\n"
22051 "\n"
22052 "VARIABLE_USE"
22053 "\n"
22054 " vs_tcs += result;\n"
22055 "}\n"
22056 "\n";
22057
22058 std::string source;
22059 Utils::Shader::STAGES test_case = m_test_cases[test_case_index];
22060
22061 if (test_case == stage)
22062 {
22063 const GLchar* array = "";
22064 const GLchar* index = "";
22065 size_t position = 0;
22066 size_t temp;
22067 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
22068 // change array = "[]" to "[1]"
22069 switch (stage)
22070 {
22071 case Utils::Shader::GEOMETRY:
22072 source = gs_tested;
22073 array = "[1]";
22074 index = "[0]";
22075 break;
22076 /*
22077 It is invalid to define transform feedback output in HS
22078 */
22079 #if 0
22080 case Utils::Shader::TESS_CTRL:
22081 source = tcs_tested;
22082 array = "[]";
22083 index = "[gl_InvocationID]";
22084 break;
22085 #endif
22086 case Utils::Shader::TESS_EVAL:
22087 source = tes_tested;
22088 array = "[1]";
22089 index = "[0]";
22090 break;
22091 case Utils::Shader::VERTEX:
22092 source = vs_tested;
22093 break;
22094 default:
22095 TCU_FAIL("Invalid enum");
22096 }
22097
22098 temp = position;
22099 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22100 position = temp;
22101 Utils::replaceToken("ARRAY", position, array, source);
22102 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22103
22104 Utils::replaceAllTokens("INDEX", index, source);
22105 }
22106 else
22107 {
22108 switch (test_case)
22109 {
22110 case Utils::Shader::GEOMETRY:
22111 switch (stage)
22112 {
22113 case Utils::Shader::VERTEX:
22114 source = vs;
22115 break;
22116 default:
22117 source = "";
22118 }
22119 break;
22120 case Utils::Shader::TESS_CTRL:
22121 switch (stage)
22122 {
22123 case Utils::Shader::VERTEX:
22124 source = vs;
22125 break;
22126 default:
22127 source = "";
22128 }
22129 break;
22130 case Utils::Shader::TESS_EVAL:
22131 switch (stage)
22132 {
22133 case Utils::Shader::TESS_CTRL:
22134 source = tcs;
22135 break;
22136 case Utils::Shader::VERTEX:
22137 source = vs;
22138 break;
22139 default:
22140 source = "";
22141 }
22142 break;
22143 case Utils::Shader::VERTEX:
22144 source = "";
22145 break;
22146 default:
22147 TCU_FAIL("Invalid enum");
22148 break;
22149 }
22150 }
22151
22152 return source;
22153 }
22154
22155 /** Get description of test case
22156 *
22157 * @param test_case_index Index of test case
22158 *
22159 * @return Test case description
22160 **/
22161 std::string XFBBlockStrideTest::getTestCaseName(GLuint test_case_index)
22162 {
22163 std::stringstream stream;
22164
22165 stream << "Stage: " << Utils::Shader::GetStageName(m_test_cases[test_case_index]);
22166
22167 return stream.str();
22168 }
22169
22170 /** Get number of test cases
22171 *
22172 * @return Number of test cases
22173 **/
22174 GLuint XFBBlockStrideTest::getTestCaseNumber()
22175 {
22176 return static_cast<GLuint>(m_test_cases.size());
22177 }
22178
22179 /** Inspects program for xfb stride
22180 *
22181 * @param program Program to query
22182 *
22183 * @return true if query results match expected values, false otherwise
22184 **/
22185 bool XFBBlockStrideTest::inspectProgram(Utils::Program& program)
22186 {
22187 GLint stride = 0;
22188
22189 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
22190 1 /* buf_size */, &stride);
22191
22192 return (128 == stride);
22193 }
22194
22195 /** Runs test case
22196 *
22197 * @param test_case_index Id of test case
22198 *
22199 * @return true if test case pass, false otherwise
22200 **/
22201 bool XFBBlockStrideTest::testCase(GLuint test_case_index)
22202 {
22203 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
22204 Utils::Program program(m_context);
22205 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
22206 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
22207 bool test_case_result = true;
22208 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
22209
22210 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
22211
22212 test_case_result = inspectProgram(program);
22213
22214 return test_case_result;
22215 }
22216
22217 /** Prepare all test cases
22218 *
22219 **/
22220 void XFBBlockStrideTest::testInit()
22221 {
22222 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22223 {
22224 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22225 (Utils::Shader::FRAGMENT == stage))
22226 {
22227 continue;
22228 }
22229
22230 m_test_cases.push_back((Utils::Shader::STAGES)stage);
22231 }
22232 }
22233
22234 /** Constructor
22235 *
22236 * @param context Test context
22237 **/
22238 XFBBlockMemberStrideTest::XFBBlockMemberStrideTest(deqp::Context& context)
22239 : BufferTestBase(context, "xfb_block_member_stride",
22240 "Test verifies that xfb_stride qualifier is respected for block member")
22241 {
22242 /* Nothing to be done here */
22243 }
22244
22245 /** Get descriptors of buffers necessary for test
22246 *
22247 * @param ignored
22248 * @param out_descriptors Descriptors of buffers used by test
22249 **/
22250 void XFBBlockMemberStrideTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
22251 bufferDescriptor::Vector& out_descriptors)
22252 {
22253 const Utils::Type& vec4 = Utils::Type::vec4;
22254
22255 /* Test needs single uniform and xfb */
22256 out_descriptors.resize(2);
22257
22258 /* Get references */
22259 bufferDescriptor& uniform = out_descriptors[0];
22260 bufferDescriptor& xfb = out_descriptors[1];
22261
22262 /* Index */
22263 uniform.m_index = 0;
22264 xfb.m_index = 0;
22265
22266 /* Target */
22267 uniform.m_target = Utils::Buffer::Uniform;
22268 xfb.m_target = Utils::Buffer::Transform_feedback;
22269
22270 /* Data */
22271 static const GLuint vec4_size = 16;
22272 const std::vector<GLubyte>& gohan_data = vec4.GenerateDataPacked();
22273 const std::vector<GLubyte>& goten_data = vec4.GenerateDataPacked();
22274 const std::vector<GLubyte>& chichi_data = vec4.GenerateDataPacked();
22275
22276 /* Uniform data */
22277 uniform.m_initial_data.resize(3 * vec4_size);
22278 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], vec4_size);
22279 memcpy(&uniform.m_initial_data[0] + vec4_size, &goten_data[0], vec4_size);
22280 memcpy(&uniform.m_initial_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
22281
22282 /* XFB data */
22283 xfb.m_initial_data.resize(4 * vec4_size);
22284 xfb.m_expected_data.resize(4 * vec4_size);
22285
22286 for (GLuint i = 0; i < 4 * vec4_size; ++i)
22287 {
22288 xfb.m_initial_data[i] = (glw::GLubyte)i;
22289 xfb.m_expected_data[i] = (glw::GLubyte)i;
22290 }
22291
22292 // the xfb_offset of "chichi" should be 32
22293 memcpy(&xfb.m_expected_data[0] + 0, &gohan_data[0], vec4_size);
22294 memcpy(&xfb.m_expected_data[0] + vec4_size, &goten_data[0], vec4_size);
22295 memcpy(&xfb.m_expected_data[0] + 2 * vec4_size, &chichi_data[0], vec4_size);
22296 }
22297
22298 /** Get body of main function for given shader stage
22299 *
22300 * @param ignored
22301 * @param stage Shader stage
22302 * @param out_assignments Set to empty
22303 * @param out_calculations Set to empty
22304 **/
22305 void XFBBlockMemberStrideTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
22306 std::string& out_assignments, std::string& out_calculations)
22307 {
22308 out_calculations = "";
22309
22310 static const GLchar* gs = " gohan = uni_gohan;\n"
22311 " goten = uni_goten;\n"
22312 " chichi = uni_chichi;\n";
22313 static const GLchar* fs = " fs_out = gohan + goten + chichi;\n";
22314
22315 const GLchar* assignments = "";
22316 switch (stage)
22317 {
22318 case Utils::Shader::FRAGMENT:
22319 assignments = fs;
22320 break;
22321 case Utils::Shader::GEOMETRY:
22322 assignments = gs;
22323 break;
22324 default:
22325 break;
22326 }
22327
22328 out_assignments = assignments;
22329 }
22330
22331 /** Get interface of shader
22332 *
22333 * @param ignored
22334 * @param stage Shader stage
22335 * @param out_interface Set to ""
22336 **/
22337 void XFBBlockMemberStrideTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
22338 std::string& out_interface)
22339 {
22340 static const GLchar* gs = "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
22341 " vec4 gohan;\n"
22342 " layout (xfb_stride = 48) vec4 goten;\n"
22343 " vec4 chichi;\n"
22344 "};\n"
22345 "layout(binding = 0) uniform gs_block {\n"
22346 " vec4 uni_gohan;\n"
22347 " vec4 uni_goten;\n"
22348 " vec4 uni_chichi;\n"
22349 "};\n";
22350 static const GLchar* fs = "in Goku {\n"
22351 " vec4 gohan;\n"
22352 " vec4 goten;\n"
22353 " vec4 chichi;\n"
22354 "};\n"
22355 "out vec4 fs_out;\n";
22356
22357 switch (stage)
22358 {
22359 case Utils::Shader::FRAGMENT:
22360 out_interface = fs;
22361 break;
22362 case Utils::Shader::GEOMETRY:
22363 out_interface = gs;
22364 break;
22365 default:
22366 out_interface = "";
22367 return;
22368 }
22369 }
22370
22371 /** Inspects program to check if all resources are as expected
22372 *
22373 * @param ignored
22374 * @param program Program instance
22375 * @param out_stream Error message
22376 *
22377 * @return true if everything is ok, false otherwise
22378 **/
22379 bool XFBBlockMemberStrideTest::inspectProgram(GLuint /* test_case_index*/, Utils::Program& program,
22380 std::stringstream& out_stream)
22381 {
22382 const GLuint gohan_id = program.GetResourceIndex("gohan", GL_TRANSFORM_FEEDBACK_VARYING);
22383 const GLuint goten_id = program.GetResourceIndex("goten", GL_TRANSFORM_FEEDBACK_VARYING);
22384 const GLuint chichi_id = program.GetResourceIndex("chichi", GL_TRANSFORM_FEEDBACK_VARYING);
22385
22386 GLint gohan_offset = 0;
22387 GLint goten_offset = 0;
22388 GLint chichi_offset = 0;
22389
22390 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, gohan_id, GL_OFFSET, 1, &gohan_offset);
22391 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, goten_id, GL_OFFSET, 1, &goten_offset);
22392 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, chichi_id, GL_OFFSET, 1, &chichi_offset);
22393
22394 // the xfb_offset of "chichi" should be 32
22395 if ((0 != gohan_offset) || (16 != goten_offset) || (32 != chichi_offset))
22396 {
22397 out_stream << "Got wrong offset: [" << gohan_offset << ", " << goten_offset << ", " << chichi_offset
22398 << "] expected: [0, 16, 32]";
22399 return false;
22400 }
22401
22402 return true;
22403 }
22404
22405 /** Constructor
22406 *
22407 * @param context Test framework context
22408 **/
22409 XFBDuplicatedStrideTest::XFBDuplicatedStrideTest(deqp::Context& context)
22410 : NegativeTestBase(context, "xfb_duplicated_stride",
22411 "Test verifies that compiler reports error when conflicting stride qualifiers are used")
22412 {
22413 }
22414
22415 /** Source for given test case and stage
22416 *
22417 * @param test_case_index Index of test case
22418 * @param stage Shader stage
22419 *
22420 * @return Shader source
22421 **/
22422 std::string XFBDuplicatedStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
22423 {
22424 static const GLchar* invalid_var_definition = "const uint valid_stride = 64;\n"
22425 #if DEBUG_NEG_REMOVE_ERROR
22426 "const uint conflicting_stride = 64;\n"
22427 #else
22428 "const uint conflicting_stride = 128;\n"
22429 #endif /* DEBUG_NEG_REMOVE_ERROR */
22430 "\n"
22431 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
22432 "layout (xfb_buffer = 0, xfb_stride = conflicting_stride) out;\n";
22433 static const GLchar* valid_var_definition = "const uint valid_stride = 64;\n"
22434 "\n"
22435 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n"
22436 "layout (xfb_buffer = 0, xfb_stride = valid_stride) out;\n";
22437 static const GLchar* fs = "#version 430 core\n"
22438 "#extension GL_ARB_enhanced_layouts : require\n"
22439 "\n"
22440 "in vec4 any_fs;\n"
22441 "out vec4 fs_out;\n"
22442 "\n"
22443 "void main()\n"
22444 "{\n"
22445 " fs_out = any_fs;\n"
22446 "}\n"
22447 "\n";
22448 static const GLchar* gs_tested = "#version 430 core\n"
22449 "#extension GL_ARB_enhanced_layouts : require\n"
22450 "\n"
22451 "layout(points) in;\n"
22452 "layout(triangle_strip, max_vertices = 4) out;\n"
22453 "\n"
22454 "VAR_DEFINITION"
22455 "\n"
22456 "in vec4 vs_any[];\n"
22457 "out vec4 any_fs;\n"
22458 "\n"
22459 "void main()\n"
22460 "{\n"
22461 " vec4 result = vs_any[0];\n"
22462 "\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 " any_fs = result;\n"
22470 " gl_Position = vec4(1, -1, 0, 1);\n"
22471 " EmitVertex();\n"
22472 " any_fs = result;\n"
22473 " gl_Position = vec4(1, 1, 0, 1);\n"
22474 " EmitVertex();\n"
22475 "}\n"
22476 "\n";
22477 static const GLchar* tcs = "#version 430 core\n"
22478 "#extension GL_ARB_enhanced_layouts : require\n"
22479 "\n"
22480 "layout(vertices = 1) out;\n"
22481 "\n"
22482 "in vec4 vs_any[];\n"
22483 "out vec4 tcs_tes[];\n"
22484 "\n"
22485 "void main()\n"
22486 "{\n"
22487 "\n"
22488 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
22489 "\n"
22490 " gl_TessLevelOuter[0] = 1.0;\n"
22491 " gl_TessLevelOuter[1] = 1.0;\n"
22492 " gl_TessLevelOuter[2] = 1.0;\n"
22493 " gl_TessLevelOuter[3] = 1.0;\n"
22494 " gl_TessLevelInner[0] = 1.0;\n"
22495 " gl_TessLevelInner[1] = 1.0;\n"
22496 "}\n"
22497 "\n";
22498 static const GLchar* tes_tested = "#version 430 core\n"
22499 "#extension GL_ARB_enhanced_layouts : require\n"
22500 "\n"
22501 "layout(isolines, point_mode) in;\n"
22502 "\n"
22503 "VAR_DEFINITION"
22504 "\n"
22505 "in vec4 tcs_tes[];\n"
22506 "out vec4 any_fs;\n"
22507 "\n"
22508 "void main()\n"
22509 "{\n"
22510 " vec4 result = tcs_tes[0];\n"
22511 "\n"
22512 " any_fs = result;\n"
22513 "}\n"
22514 "\n";
22515 static const GLchar* vs = "#version 430 core\n"
22516 "#extension GL_ARB_enhanced_layouts : require\n"
22517 "\n"
22518 "in vec4 in_vs;\n"
22519 "out vec4 vs_any;\n"
22520 "\n"
22521 "void main()\n"
22522 "{\n"
22523 " vs_any = in_vs;\n"
22524 "}\n"
22525 "\n";
22526 static const GLchar* vs_tested = "#version 430 core\n"
22527 "#extension GL_ARB_enhanced_layouts : require\n"
22528 "\n"
22529 "VAR_DEFINITION"
22530 "\n"
22531 "in vec4 in_vs;\n"
22532 "out vec4 any_fs;\n"
22533 "\n"
22534 "void main()\n"
22535 "{\n"
22536 " vec4 result = in_vs;\n"
22537 "\n"
22538 " any_fs += result;\n"
22539 "}\n"
22540 "\n";
22541
22542 std::string source;
22543 testCase& test_case = m_test_cases[test_case_index];
22544
22545 if (test_case.m_stage == stage)
22546 {
22547 size_t position = 0;
22548 const GLchar* var_definition = 0;
22549
22550 switch (test_case.m_case)
22551 {
22552 case VALID:
22553 var_definition = valid_var_definition;
22554 break;
22555 case INVALID:
22556 var_definition = invalid_var_definition;
22557 break;
22558 default:
22559 TCU_FAIL("Invalid enum");
22560 }
22561
22562 switch (stage)
22563 {
22564 case Utils::Shader::GEOMETRY:
22565 source = gs_tested;
22566 break;
22567 case Utils::Shader::TESS_EVAL:
22568 source = tes_tested;
22569 break;
22570 case Utils::Shader::VERTEX:
22571 source = vs_tested;
22572 break;
22573 default:
22574 TCU_FAIL("Invalid enum");
22575 }
22576
22577 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22578 }
22579 else
22580 {
22581 switch (test_case.m_stage)
22582 {
22583 case Utils::Shader::GEOMETRY:
22584 switch (stage)
22585 {
22586 case Utils::Shader::FRAGMENT:
22587 source = fs;
22588 break;
22589 case Utils::Shader::VERTEX:
22590 source = vs;
22591 break;
22592 default:
22593 source = "";
22594 }
22595 break;
22596 case Utils::Shader::TESS_EVAL:
22597 switch (stage)
22598 {
22599 case Utils::Shader::FRAGMENT:
22600 source = fs;
22601 break;
22602 case Utils::Shader::TESS_CTRL:
22603 source = tcs;
22604 break;
22605 case Utils::Shader::VERTEX:
22606 source = vs;
22607 break;
22608 default:
22609 source = "";
22610 }
22611 break;
22612 case Utils::Shader::VERTEX:
22613 switch (stage)
22614 {
22615 case Utils::Shader::FRAGMENT:
22616 source = fs;
22617 break;
22618 default:
22619 source = "";
22620 }
22621 break;
22622 default:
22623 TCU_FAIL("Invalid enum");
22624 break;
22625 }
22626 }
22627
22628 return source;
22629 }
22630
22631 /** Get description of test case
22632 *
22633 * @param test_case_index Index of test case
22634 *
22635 * @return Test case description
22636 **/
22637 std::string XFBDuplicatedStrideTest::getTestCaseName(GLuint test_case_index)
22638 {
22639 std::stringstream stream;
22640 testCase& test_case = m_test_cases[test_case_index];
22641
22642 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
22643
22644 switch (test_case.m_case)
22645 {
22646 case VALID:
22647 stream << "valid";
22648 break;
22649 case INVALID:
22650 stream << "invalid";
22651 break;
22652 default:
22653 TCU_FAIL("Invalid enum");
22654 }
22655
22656 return stream.str();
22657 }
22658
22659 /** Get number of test cases
22660 *
22661 * @return Number of test cases
22662 **/
22663 GLuint XFBDuplicatedStrideTest::getTestCaseNumber()
22664 {
22665 return static_cast<GLuint>(m_test_cases.size());
22666 }
22667
22668 /** Selects if "compute" stage is relevant for test
22669 *
22670 * @param ignored
22671 *
22672 * @return false
22673 **/
22674 bool XFBDuplicatedStrideTest::isComputeRelevant(GLuint /* test_case_index */)
22675 {
22676 return false;
22677 }
22678
22679 /** Selects if compilation failure is expected result
22680 *
22681 * @param test_case_index Index of test case
22682 *
22683 * @return true
22684 **/
22685 bool XFBDuplicatedStrideTest::isFailureExpected(GLuint test_case_index)
22686 {
22687 testCase& test_case = m_test_cases[test_case_index];
22688
22689 return (INVALID == test_case.m_case);
22690 }
22691
22692 /** Prepare all test cases
22693 *
22694 **/
22695 void XFBDuplicatedStrideTest::testInit()
22696 {
22697 for (GLuint c = 0; c < CASE_MAX; ++c)
22698 {
22699 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
22700 {
22701 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
22702 (Utils::Shader::FRAGMENT == stage))
22703 {
22704 continue;
22705 }
22706
22707 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
22708
22709 m_test_cases.push_back(test_case);
22710 }
22711 }
22712 }
22713
22714 /** Constructor
22715 *
22716 * @param context Test framework context
22717 **/
22718 XFBGetProgramResourceAPITest::XFBGetProgramResourceAPITest(deqp::Context& context)
22719 : TestBase(context, "xfb_get_program_resource_api",
22720 "Test verifies that get program resource reports correct results for XFB")
22721 {
22722 }
22723
22724 /** Source for given test case and stage
22725 *
22726 * @param test_case_index Index of test case
22727 * @param stage Shader stage
22728 *
22729 * @return Shader source
22730 **/
22731 std::string XFBGetProgramResourceAPITest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
22732 {
22733 static const GLchar* api_var_definition = "out TYPE b0_v1ARRAY;\n"
22734 "out TYPE b1_v1ARRAY;\n"
22735 "out TYPE b0_v3ARRAY;\n"
22736 "out TYPE b0_v0ARRAY;\n";
22737 static const GLchar* xfb_var_definition =
22738 "const uint type_size = SIZE;\n"
22739 "\n"
22740 "layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;\n"
22741 "\n"
22742 "layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out TYPE b0_v1ARRAY;\n"
22743 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out TYPE b1_v1ARRAY;\n"
22744 "layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out TYPE b0_v3ARRAY;\n"
22745 "layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out TYPE b0_v0ARRAY;\n";
22746 static const GLchar* var_use = " b0_v1INDEX = TYPE(0);\n"
22747 " b1_v1INDEX = TYPE(1);\n"
22748 " b0_v3INDEX = TYPE(0);\n"
22749 " b0_v0INDEX = TYPE(1);\n"
22750 " if (vec4(0) == result)\n"
22751 " {\n"
22752 " b0_v1INDEX = TYPE(1);\n"
22753 " b1_v1INDEX = TYPE(0);\n"
22754 " b0_v3INDEX = TYPE(1);\n"
22755 " b0_v0INDEX = TYPE(0);\n"
22756 " }\n";
22757 static const GLchar* gs_tested =
22758 "#version 430 core\n"
22759 "#extension GL_ARB_enhanced_layouts : require\n"
22760 "\n"
22761 "layout(points) in;\n"
22762 "layout(triangle_strip, max_vertices = 4) out;\n"
22763 "\n"
22764 "VAR_DEFINITION"
22765 "\n"
22766 "out gl_PerVertex \n"
22767 "{ \n"
22768 " vec4 gl_Position; \n" // gl_Position must be redeclared in separable program mode
22769 "}; \n"
22770 "in vec4 tes_gs[];\n"
22771 "out vec4 gs_fs;\n"
22772 "\n"
22773 "void main()\n"
22774 "{\n"
22775 " vec4 result = tes_gs[0];\n"
22776 "\n"
22777 "VARIABLE_USE"
22778 "\n"
22779 " gs_fs = result;\n"
22780 " gl_Position = vec4(-1, -1, 0, 1);\n"
22781 " EmitVertex();\n"
22782 " gs_fs = result;\n"
22783 " gl_Position = vec4(-1, 1, 0, 1);\n"
22784 " EmitVertex();\n"
22785 " gs_fs = result;\n"
22786 " gl_Position = vec4(1, -1, 0, 1);\n"
22787 " EmitVertex();\n"
22788 " gs_fs = result;\n"
22789 " gl_Position = vec4(1, 1, 0, 1);\n"
22790 " EmitVertex();\n"
22791 "}\n"
22792 "\n";
22793 #if 0
22794 static const GLchar* tcs_tested =
22795 "#version 430 core\n"
22796 "#extension GL_ARB_enhanced_layouts : require\n"
22797 "\n"
22798 "layout(vertices = 1) out;\n"
22799 "\n"
22800 "VAR_DEFINITION"
22801 "\n"
22802 "in vec4 vs_tcs[];\n"
22803 "out vec4 tcs_tes[];\n"
22804 "\n"
22805 "void main()\n"
22806 "{\n"
22807 " vec4 result = vs_tcs[gl_InvocationID];\n"
22808 "\n"
22809 "VARIABLE_USE"
22810 "\n"
22811 " tcs_tes[gl_InvocationID] = result;\n"
22812 "\n"
22813 " gl_TessLevelOuter[0] = 1.0;\n"
22814 " gl_TessLevelOuter[1] = 1.0;\n"
22815 " gl_TessLevelOuter[2] = 1.0;\n"
22816 " gl_TessLevelOuter[3] = 1.0;\n"
22817 " gl_TessLevelInner[0] = 1.0;\n"
22818 " gl_TessLevelInner[1] = 1.0;\n"
22819 "}\n"
22820 "\n";
22821 #endif
22822 static const GLchar* tes_tested = "#version 430 core\n"
22823 "#extension GL_ARB_enhanced_layouts : require\n"
22824 "\n"
22825 "layout(isolines, point_mode) in;\n"
22826 "\n"
22827 "VAR_DEFINITION"
22828 "\n"
22829 "in vec4 tcs_tes[];\n"
22830 "out vec4 tes_gs;\n"
22831 "\n"
22832 "void main()\n"
22833 "{\n"
22834 " vec4 result = tcs_tes[0];\n"
22835 "\n"
22836 "VARIABLE_USE"
22837 "\n"
22838 " tes_gs = result;\n"
22839 "}\n"
22840 "\n";
22841 static const GLchar* vs_tested = "#version 430 core\n"
22842 "#extension GL_ARB_enhanced_layouts : require\n"
22843 "\n"
22844 "VAR_DEFINITION"
22845 "\n"
22846 "in vec4 in_vs;\n"
22847 "out vec4 vs_tcs;\n"
22848 "\n"
22849 "void main()\n"
22850 "{\n"
22851 " vec4 result = in_vs;\n"
22852 "\n"
22853 "VARIABLE_USE"
22854 "\n"
22855 " vs_tcs = result;\n"
22856 "}\n"
22857 "\n";
22858
22859 std::string source;
22860 const test_Case& test_case = m_test_cases[test_case_index];
22861
22862 if (test_case.m_stage == stage)
22863 {
22864 const GLchar* array = "";
22865 GLchar buffer[16];
22866 const GLchar* index = "";
22867 size_t position = 0;
22868 size_t temp;
22869 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
22870 const GLchar* var_definition = 0;
22871
22872 sprintf(buffer, "%d", test_case.m_type.GetSize());
22873
22874 if (XFB == test_case.m_case)
22875 {
22876 var_definition = xfb_var_definition;
22877 }
22878 else
22879 {
22880 var_definition = api_var_definition;
22881 }
22882
22883 // It is a compile time error to apply xfb_offset to the declaration of an unsized array(GLSL4.5 spec: Page73)
22884 // change array = "[]" to "[1]"
22885 switch (stage)
22886 {
22887 case Utils::Shader::GEOMETRY:
22888 source = gs_tested;
22889 array = "[1]";
22890 index = "[0]";
22891 break;
22892 // It is invalid to output transform feedback varyings in tessellation control shader
22893 #if 0
22894 case Utils::Shader::TESS_CTRL:
22895 source = tcs_tested;
22896 array = "[]";
22897 index = "[gl_InvocationID]";
22898 break;
22899 #endif
22900 case Utils::Shader::TESS_EVAL:
22901 source = tes_tested;
22902 array = "[1]";
22903 index = "[0]";
22904 break;
22905 case Utils::Shader::VERTEX:
22906 source = vs_tested;
22907 break;
22908 default:
22909 TCU_FAIL("Invalid enum");
22910 }
22911
22912 temp = position;
22913 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
22914 if (XFB == test_case.m_case)
22915 {
22916 position = temp;
22917 Utils::replaceToken("SIZE", position, buffer, source);
22918 }
22919 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
22920
22921 Utils::replaceAllTokens("ARRAY", array, source);
22922 Utils::replaceAllTokens("INDEX", index, source);
22923 Utils::replaceAllTokens("TYPE", type_name, source);
22924 }
22925 else
22926 {
22927 source = "";
22928 }
22929
22930 return source;
22931 }
22932
22933 /** Get description of test case
22934 *
22935 * @param test_case_index Index of test case
22936 *
22937 * @return Test case description
22938 **/
22939 std::string XFBGetProgramResourceAPITest::getTestCaseName(GLuint test_case_index)
22940 {
22941 std::stringstream stream;
22942 const test_Case& test_case = m_test_cases[test_case_index];
22943
22944 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
22945 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", case: ";
22946
22947 switch (test_case.m_case)
22948 {
22949 case INTERLEAVED:
22950 stream << "interleaved";
22951 break;
22952 case SEPARATED:
22953 stream << "separated";
22954 break;
22955 case XFB:
22956 stream << "xfb";
22957 break;
22958 default:
22959 TCU_FAIL("Invalid enum");
22960 }
22961
22962 return stream.str();
22963 }
22964
22965 /** Get number of test cases
22966 *
22967 * @return Number of test cases
22968 **/
22969 GLuint XFBGetProgramResourceAPITest::getTestCaseNumber()
22970 {
22971 return static_cast<GLuint>(m_test_cases.size());
22972 }
22973
22974 /** Inspects program for offset, buffer index, buffer stride and type
22975 *
22976 * @param test_case_index Index of test case
22977 * @param program Program to query
22978 *
22979 * @return true if query results match expected values, false otherwise
22980 **/
22981 bool XFBGetProgramResourceAPITest::inspectProgram(glw::GLuint test_case_index, Utils::Program& program)
22982 {
22983 GLint b0_stride = 0;
22984 GLint b1_stride = 0;
22985 GLint b0_v0_buf = 0;
22986 GLint b0_v0_offset = 0;
22987 GLint b0_v0_type = 0;
22988 GLint b0_v1_buf = 0;
22989 GLint b0_v1_offset = 0;
22990 GLint b0_v1_type = 0;
22991 GLint b0_v3_buf = 0;
22992 GLint b0_v3_offset = 0;
22993 GLint b0_v3_type = 0;
22994 GLint b1_v1_buf = 0;
22995 GLint b1_v1_offset = 0;
22996 GLint b1_v1_type = 0;
22997 const test_Case& test_case = m_test_cases[test_case_index];
22998 const GLenum type_enum = test_case.m_type.GetTypeGLenum();
22999 const GLint type_size = test_case.m_type.GetSize();
23000
23001 GLuint b0_v0_index = program.GetResourceIndex("b0_v0", GL_TRANSFORM_FEEDBACK_VARYING);
23002 GLuint b0_v1_index = program.GetResourceIndex("b0_v1", GL_TRANSFORM_FEEDBACK_VARYING);
23003 GLuint b0_v3_index = program.GetResourceIndex("b0_v3", GL_TRANSFORM_FEEDBACK_VARYING);
23004 GLuint b1_v1_index = program.GetResourceIndex("b1_v1", GL_TRANSFORM_FEEDBACK_VARYING);
23005
23006 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_OFFSET, 1 /* buf_size */, &b0_v0_offset);
23007 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_OFFSET, 1 /* buf_size */, &b0_v1_offset);
23008 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_OFFSET, 1 /* buf_size */, &b0_v3_offset);
23009 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_OFFSET, 1 /* buf_size */, &b1_v1_offset);
23010
23011 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TYPE, 1 /* buf_size */, &b0_v0_type);
23012 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TYPE, 1 /* buf_size */, &b0_v1_type);
23013 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TYPE, 1 /* buf_size */, &b0_v3_type);
23014 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TYPE, 1 /* buf_size */, &b1_v1_type);
23015
23016 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v0_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23017 1 /* buf_size */, &b0_v0_buf);
23018 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23019 1 /* buf_size */, &b0_v1_buf);
23020 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b0_v3_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23021 1 /* buf_size */, &b0_v3_buf);
23022 program.GetResource(GL_TRANSFORM_FEEDBACK_VARYING, b1_v1_index, GL_TRANSFORM_FEEDBACK_BUFFER_INDEX,
23023 1 /* buf_size */, &b1_v1_buf);
23024
23025 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b0_v0_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
23026 &b0_stride);
23027 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, b1_v1_buf, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE, 1 /* buf_size */,
23028 &b1_stride);
23029
23030 if (SEPARATED != test_case.m_case)
23031 {
23032 return (((GLint)(4 * type_size) == b0_stride) && ((GLint)(4 * type_size) == b1_stride) &&
23033 ((GLint)(0) == b0_v0_buf) && ((GLint)(0 * type_size) == b0_v0_offset) &&
23034 ((GLint)(type_enum) == b0_v0_type) && ((GLint)(0) == b0_v1_buf) &&
23035 ((GLint)(1 * type_size) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
23036 ((GLint)(0) == b0_v3_buf) && ((GLint)(3 * type_size) == b0_v3_offset) &&
23037 ((GLint)(type_enum) == b0_v3_type) && ((GLint)(1) == b1_v1_buf) &&
23038 ((GLint)(1 * type_size) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
23039 }
23040 else
23041 {
23042 return (((GLint)(1 * type_size) == b0_stride) && ((GLint)(1 * type_size) == b1_stride) &&
23043 ((GLint)(0) == b0_v0_buf) && ((GLint)(0) == b0_v0_offset) && ((GLint)(type_enum) == b0_v0_type) &&
23044 ((GLint)(1) == b0_v1_buf) && ((GLint)(0) == b0_v1_offset) && ((GLint)(type_enum) == b0_v1_type) &&
23045 ((GLint)(2) == b0_v3_buf) && ((GLint)(0) == b0_v3_offset) && ((GLint)(type_enum) == b0_v3_type) &&
23046 ((GLint)(3) == b1_v1_buf) && ((GLint)(0) == b1_v1_offset) && ((GLint)(type_enum) == b1_v1_type));
23047 }
23048 }
23049
23050 /** Insert gl_SkipComponents
23051 *
23052 * @param num_components How many gl_SkipComponents1 need to be inserted
23053 * @param varyings The transform feedback varyings string vector
23054 *
23055 **/
23056 void XFBGetProgramResourceAPITest::insertSkipComponents(int num_components, Utils::Program::NameVector& varyings)
23057 {
23058 int num_component_4 = num_components / 4;
23059 int num_component_1 = num_components % 4;
23060 for (int i = 0; i < num_component_4; i++)
23061 {
23062 varyings.push_back("gl_SkipComponents4");
23063 }
23064 switch (num_component_1)
23065 {
23066 case 1:
23067 varyings.push_back("gl_SkipComponents1");
23068 break;
23069 case 2:
23070 varyings.push_back("gl_SkipComponents2");
23071 break;
23072 case 3:
23073 varyings.push_back("gl_SkipComponents3");
23074 break;
23075 default:
23076 break;
23077 }
23078 }
23079
23080 /** Runs test case
23081 *
23082 * @param test_case_index Id of test case
23083 *
23084 * @return true if test case pass, false otherwise
23085 **/
23086 bool XFBGetProgramResourceAPITest::testCase(GLuint test_case_index)
23087 {
23088 const std::string& gs_source = getShaderSource(test_case_index, Utils::Shader::GEOMETRY);
23089 Utils::Program program(m_context);
23090 const std::string& tcs_source = getShaderSource(test_case_index, Utils::Shader::TESS_CTRL);
23091 const std::string& tes_source = getShaderSource(test_case_index, Utils::Shader::TESS_EVAL);
23092 const test_Case& test_case = m_test_cases[test_case_index];
23093 bool test_case_result = true;
23094 const std::string& vs_source = getShaderSource(test_case_index, Utils::Shader::VERTEX);
23095
23096 // According to spec: gl_SkipComponents1 ~ gl_SkipComponents4 is treated as specifying a one- to four-component floating point output variables with undefined values.
23097 // 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.
23098
23099 if (INTERLEAVED == test_case.m_case)
23100 {
23101 /*
23102 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
23103 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
23104 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
23105 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
23106
23107 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,
23108 we need to calculate how many "gl_SkipComponents" need to be inserted.
23109 */
23110 Utils::Program::NameVector captured_varyings;
23111 captured_varyings.push_back("b0_v0");
23112 captured_varyings.push_back("b0_v1");
23113 // Compute how many gl_SkipComponents to be inserted
23114 int numComponents = test_case.m_type.GetSize() / 4;
23115 insertSkipComponents(numComponents, captured_varyings);
23116 captured_varyings.push_back("b0_v3");
23117 captured_varyings.push_back("gl_NextBuffer");
23118 insertSkipComponents(numComponents, captured_varyings);
23119 captured_varyings.push_back("b1_v1");
23120 insertSkipComponents(numComponents * 2, captured_varyings);
23121
23122 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, true,
23123 true /* separable */);
23124 }
23125 else if (SEPARATED == test_case.m_case)
23126 {
23127 Utils::Program::NameVector captured_varyings;
23128
23129 captured_varyings.push_back("b0_v0");
23130 captured_varyings.push_back("b0_v1");
23131 captured_varyings.push_back("b0_v3");
23132 captured_varyings.push_back("b1_v1");
23133
23134 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, captured_varyings, false,
23135 true /* separable */);
23136 }
23137 else
23138 {
23139
23140 program.Init("" /* cs */, "", gs_source, tcs_source, tes_source, vs_source, true /* separable */);
23141 }
23142
23143 test_case_result = inspectProgram(test_case_index, program);
23144
23145 return test_case_result;
23146 }
23147
23148 /** Prepare all test cases
23149 *
23150 **/
23151 void XFBGetProgramResourceAPITest::testInit()
23152 {
23153 const Functions& gl = m_context.getRenderContext().getFunctions();
23154 const GLuint n_types = getTypesNumber();
23155 GLint max_xfb_int;
23156 GLint max_xfb_sep;
23157
23158 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_xfb_int);
23159 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23160
23161 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_xfb_sep);
23162 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23163
23164 GLint max_varyings;
23165 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings);
23166
23167 for (GLuint i = 0; i < n_types; ++i)
23168 {
23169 // 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,
23170 // 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
23171 // shader valid, we can either skip the dmat4, dmat4x3 or query the implementation-dependent value MAX_VARYING_COMPONENTS before generating the shader
23172 // to guarantee the number of varying not exceeded.
23173 /*
23174 layout (xfb_buffer = 1, xfb_stride = 4 * type_size) out;
23175 layout (xfb_buffer = 0, xfb_offset = 1 * type_size) out type b0_v1;
23176 layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out type b1_v1;
23177 layout (xfb_buffer = 0, xfb_offset = 3 * type_size) out type b0_v3;
23178 layout (xfb_buffer = 0, xfb_offset = 0 * type_size) out type b0_v0;
23179 in vec4 in_vs;
23180 out vec4 vs_tcs;
23181 */
23182 if (i == 7 || i == 9)
23183 continue;
23184 const Utils::Type& type = getType(i);
23185 if (4 * type.GetNumComponents() + 4 > (GLuint)max_varyings)
23186 {
23187 continue;
23188 }
23189 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
23190 {
23191 /*
23192 It is invalid to define transform feedback output in HS
23193 */
23194 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
23195 (Utils::Shader::FRAGMENT == stage))
23196 {
23197 continue;
23198 }
23199
23200 test_Case test_case_int = { INTERLEAVED, (Utils::Shader::STAGES)stage, type };
23201 test_Case test_case_sep = { SEPARATED, (Utils::Shader::STAGES)stage, type };
23202 test_Case test_case_xfb = { XFB, (Utils::Shader::STAGES)stage, type };
23203
23204 if ((int)type.GetSize() <= max_xfb_int)
23205 {
23206 m_test_cases.push_back(test_case_xfb);
23207 m_test_cases.push_back(test_case_int);
23208 }
23209
23210 if ((int)type.GetSize() <= max_xfb_sep)
23211 {
23212 m_test_cases.push_back(test_case_sep);
23213 }
23214 }
23215 }
23216 }
23217
23218 /** Constructor
23219 *
23220 * @param context Test context
23221 **/
23222 XFBOverrideQualifiersWithAPITest::XFBOverrideQualifiersWithAPITest(deqp::Context& context)
23223 : BufferTestBase(context, "xfb_override_qualifiers_with_api",
23224 "Test verifies that xfb_offset qualifier is not overriden with API")
23225 {
23226 /* Nothing to be done here */
23227 }
23228
23229 /** Get descriptors of buffers necessary for test
23230 *
23231 * @param test_case_index Index of test case
23232 * @param out_descriptors Descriptors of buffers used by test
23233 **/
23234 void XFBOverrideQualifiersWithAPITest::getBufferDescriptors(glw::GLuint test_case_index,
23235 bufferDescriptor::Vector& out_descriptors)
23236 {
23237 const Utils::Type& type = getType(test_case_index);
23238
23239 /* Test needs single uniform and xfb */
23240 out_descriptors.resize(2);
23241
23242 /* Get references */
23243 bufferDescriptor& uniform = out_descriptors[0];
23244 bufferDescriptor& xfb = out_descriptors[1];
23245
23246 /* Index */
23247 uniform.m_index = 0;
23248 xfb.m_index = 0;
23249
23250 /* Target */
23251 uniform.m_target = Utils::Buffer::Uniform;
23252 xfb.m_target = Utils::Buffer::Transform_feedback;
23253
23254 /* Data */
23255 const GLuint gen_start = Utils::s_rand;
23256 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
23257 const std::vector<GLubyte>& trunks_data = type.GenerateData();
23258 const std::vector<GLubyte>& goku_data = type.GenerateData();
23259
23260 Utils::s_rand = gen_start;
23261 const std::vector<GLubyte>& vegeta_data_pck = type.GenerateDataPacked();
23262 type.GenerateDataPacked(); // generate the data for trunks
23263 const std::vector<GLubyte>& goku_data_pck = type.GenerateDataPacked();
23264
23265 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
23266 const GLuint type_size_pck = static_cast<GLuint>(vegeta_data_pck.size());
23267
23268 /* Uniform data */
23269 uniform.m_initial_data.resize(3 * type_size);
23270 memcpy(&uniform.m_initial_data[0] + 0, &vegeta_data[0], type_size);
23271 memcpy(&uniform.m_initial_data[0] + type_size, &trunks_data[0], type_size);
23272 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goku_data[0], type_size);
23273
23274 /* XFB data */
23275 xfb.m_initial_data.resize(3 * type_size_pck);
23276 xfb.m_expected_data.resize(3 * type_size_pck);
23277
23278 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
23279 {
23280 xfb.m_initial_data[i] = (glw::GLubyte)i;
23281 xfb.m_expected_data[i] = (glw::GLubyte)i;
23282 }
23283
23284 memcpy(&xfb.m_expected_data[0] + 0, &goku_data_pck[0], type_size_pck);
23285 memcpy(&xfb.m_expected_data[0] + 2 * type_size_pck, &vegeta_data_pck[0], type_size_pck);
23286 }
23287
23288 /** Get list of names of varyings that will be registered with TransformFeedbackVaryings
23289 *
23290 * @param ignored
23291 * @param captured_varyings List of names
23292 **/
23293 void XFBOverrideQualifiersWithAPITest::getCapturedVaryings(glw::GLuint test_case_index,
23294 Utils::Program::NameVector& captured_varyings,
23295 GLint* xfb_components)
23296 {
23297 captured_varyings.resize(1);
23298
23299 captured_varyings[0] = "trunks";
23300
23301 /* The test captures 3 varyings of type 'type' */
23302 Utils::Type type = getType(test_case_index);
23303 GLint type_size = type.GetSize(false);
23304 *xfb_components = 3 * type_size / 4;
23305 }
23306
23307 /** Get body of main function for given shader stage
23308 *
23309 * @param test_case_index Index of test case
23310 * @param stage Shader stage
23311 * @param out_assignments Set to empty
23312 * @param out_calculations Set to empty
23313 **/
23314 void XFBOverrideQualifiersWithAPITest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
23315 std::string& out_assignments, std::string& out_calculations)
23316 {
23317 out_calculations = "";
23318
23319 static const GLchar* gs = " vegeta = uni_vegeta;\n"
23320 " trunks = uni_trunks;\n"
23321 " goku = uni_goku;\n";
23322 static const GLchar* fs = " fs_out = vec4(0);\n"
23323 " if (TYPE(1) == goku + trunks + vegeta)\n"
23324 " {\n"
23325 " fs_out = vec4(1);\n"
23326 " }\n";
23327
23328 const GLchar* assignments = "";
23329 switch (stage)
23330 {
23331 case Utils::Shader::FRAGMENT:
23332 assignments = fs;
23333 break;
23334 case Utils::Shader::GEOMETRY:
23335 assignments = gs;
23336 break;
23337 default:
23338 break;
23339 }
23340
23341 out_assignments = assignments;
23342
23343 if (Utils::Shader::FRAGMENT == stage)
23344 {
23345 const Utils::Type& type = getType(test_case_index);
23346
23347 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_assignments);
23348 }
23349 }
23350
23351 /** Get interface of shader
23352 *
23353 * @param test_case_index Index of test case
23354 * @param stage Shader stage
23355 * @param out_interface Set to ""
23356 **/
23357 void XFBOverrideQualifiersWithAPITest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
23358 std::string& out_interface)
23359 {
23360 static const GLchar* gs = "const uint sizeof_type = SIZE;\n"
23361 "\n"
23362 "layout (xfb_offset = 2 * sizeof_type) flat out TYPE vegeta;\n"
23363 " flat out TYPE trunks;\n"
23364 "layout (xfb_offset = 0) flat out TYPE goku;\n"
23365 "\n"
23366 /*
23367 There is no packing qualifier for uniform block gs_block, according to spec, it should be "shared" by default,
23368 the definition equals to "layout(binding=0, shared)", if the block is declared as shared, each block member will
23369 not be packed, and each block member's layout in memory is implementation dependent, so we can't use the API
23370 glBufferData() to update the UBO directly, we need to query each block member's offset first, then upload the
23371 data to the corresponding offset, otherwise we can't get the correct data from UBO; to make the test passed,
23372 we need to add the qualifier std140, and change the declaration as layout(binding=0, std140), which can make
23373 sure all the block members are packed and the application can upload the data by glBufferData() directly.
23374 */
23375 "layout(binding = 0, std140) uniform gs_block {\n"
23376 " TYPE uni_vegeta;\n"
23377 " TYPE uni_trunks;\n"
23378 " TYPE uni_goku;\n"
23379 "};\n";
23380 static const GLchar* fs = "flat in TYPE vegeta;\n"
23381 "flat in TYPE trunks;\n"
23382 "flat in TYPE goku;\n"
23383 "\n"
23384 "out vec4 fs_out;\n";
23385
23386 const Utils::Type& type = getType(test_case_index);
23387
23388 switch (stage)
23389 {
23390 case Utils::Shader::FRAGMENT:
23391 out_interface = fs;
23392 break;
23393 case Utils::Shader::GEOMETRY:
23394 out_interface = gs;
23395 break;
23396 default:
23397 out_interface = "";
23398 return;
23399 }
23400
23401 if (Utils::Shader::GEOMETRY == stage)
23402 {
23403 GLchar buffer[16];
23404 size_t position = 0;
23405 const GLuint type_size = type.GetSize();
23406
23407 sprintf(buffer, "%d", type_size);
23408
23409 Utils::replaceToken("SIZE", position, buffer, out_interface);
23410 }
23411
23412 Utils::replaceAllTokens("TYPE", type.GetGLSLTypeName(), out_interface);
23413 }
23414
23415 /** Get type name
23416 *
23417 * @param test_case_index Index of test case
23418 *
23419 * @return Name of type test in test_case_index
23420 **/
23421 std::string XFBOverrideQualifiersWithAPITest::getTestCaseName(glw::GLuint test_case_index)
23422 {
23423 return getTypeName(test_case_index);
23424 }
23425
23426 /** Returns number of types to test
23427 *
23428 * @return Number of types, 34
23429 **/
23430 glw::GLuint XFBOverrideQualifiersWithAPITest::getTestCaseNumber()
23431 {
23432 return getTypesNumber();
23433 }
23434
23435 /** Inspects program to check if all resources are as expected
23436 *
23437 * @param test_case_index Index of test case
23438 * @param program Program instance
23439 * @param out_stream Error message
23440 *
23441 * @return true if everything is ok, false otherwise
23442 **/
23443 bool XFBOverrideQualifiersWithAPITest::inspectProgram(GLuint test_case_index, Utils::Program& program,
23444 std::stringstream& out_stream)
23445 {
23446 GLint stride = 0;
23447 const Utils::Type& type = getType(test_case_index);
23448 const GLuint type_size = type.GetSize(false);
23449
23450 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
23451 1 /* buf_size */, &stride);
23452
23453 if ((GLint)(3 * type_size) != stride)
23454 {
23455 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
23456
23457 return false;
23458 }
23459
23460 return true;
23461 }
23462
23463 /** Constructor
23464 *
23465 * @param context Test context
23466 **/
23467 XFBVertexStreamsTest::XFBVertexStreamsTest(deqp::Context& context)
23468 : BufferTestBase(context, "xfb_vertex_streams",
23469 "Test verifies that xfb qualifier works with multiple output streams")
23470 {
23471 /* Nothing to be done here */
23472 }
23473
23474 /** Get descriptors of buffers necessary for test
23475 *
23476 * @param ignored
23477 * @param out_descriptors Descriptors of buffers used by test
23478 **/
23479 void XFBVertexStreamsTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
23480 bufferDescriptor::Vector& out_descriptors)
23481 {
23482 const Utils::Type& type = Utils::Type::vec4;
23483
23484 /* Test needs single uniform and three xfbs */
23485 out_descriptors.resize(4);
23486
23487 /* Get references */
23488 bufferDescriptor& uniform = out_descriptors[0];
23489 bufferDescriptor& xfb_1 = out_descriptors[1];
23490 bufferDescriptor& xfb_2 = out_descriptors[2];
23491 bufferDescriptor& xfb_3 = out_descriptors[3];
23492
23493 /* Index */
23494 uniform.m_index = 0;
23495 xfb_1.m_index = 1;
23496 xfb_2.m_index = 2;
23497 xfb_3.m_index = 3;
23498
23499 /* Target */
23500 uniform.m_target = Utils::Buffer::Uniform;
23501 xfb_1.m_target = Utils::Buffer::Transform_feedback;
23502 xfb_2.m_target = Utils::Buffer::Transform_feedback;
23503 xfb_3.m_target = Utils::Buffer::Transform_feedback;
23504
23505 /* Data */
23506 const std::vector<GLubyte>& goku_data = type.GenerateData();
23507 const std::vector<GLubyte>& gohan_data = type.GenerateData();
23508 const std::vector<GLubyte>& goten_data = type.GenerateData();
23509 const std::vector<GLubyte>& picolo_data = type.GenerateData();
23510 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
23511 const std::vector<GLubyte>& bulma_data = type.GenerateData();
23512
23513 const GLuint type_size = static_cast<GLuint>(vegeta_data.size());
23514
23515 /* Uniform data */
23516 uniform.m_initial_data.resize(6 * type_size);
23517 memcpy(&uniform.m_initial_data[0] + 0, &goku_data[0], type_size);
23518 memcpy(&uniform.m_initial_data[0] + type_size, &gohan_data[0], type_size);
23519 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
23520 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &picolo_data[0], type_size);
23521 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
23522 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &bulma_data[0], type_size);
23523
23524 /* XFB data */
23525 static const GLuint xfb_stride = 64;
23526 xfb_1.m_initial_data.resize(xfb_stride);
23527 xfb_1.m_expected_data.resize(xfb_stride);
23528 xfb_2.m_initial_data.resize(xfb_stride);
23529 xfb_2.m_expected_data.resize(xfb_stride);
23530 xfb_3.m_initial_data.resize(xfb_stride);
23531 xfb_3.m_expected_data.resize(xfb_stride);
23532
23533 for (GLuint i = 0; i < xfb_stride; ++i)
23534 {
23535 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
23536 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
23537 xfb_2.m_initial_data[i] = (glw::GLubyte)i;
23538 xfb_2.m_expected_data[i] = (glw::GLubyte)i;
23539 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
23540 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
23541 }
23542
23543 memcpy(&xfb_1.m_expected_data[0] + 48, &goku_data[0], type_size);
23544 memcpy(&xfb_1.m_expected_data[0] + 32, &gohan_data[0], type_size);
23545 memcpy(&xfb_1.m_expected_data[0] + 16, &goten_data[0], type_size);
23546 memcpy(&xfb_3.m_expected_data[0] + 48, &picolo_data[0], type_size);
23547 memcpy(&xfb_3.m_expected_data[0] + 32, &vegeta_data[0], type_size);
23548 memcpy(&xfb_2.m_expected_data[0] + 32, &bulma_data[0], type_size);
23549 }
23550
23551 /** Get body of main function for given shader stage
23552 *
23553 * @param ignored
23554 * @param stage Shader stage
23555 * @param out_assignments Set to empty
23556 * @param out_calculations Set to empty
23557 **/
23558 void XFBVertexStreamsTest::getShaderBody(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23559 std::string& out_assignments, std::string& out_calculations)
23560 {
23561 out_calculations = "";
23562
23563 // the shader declares the output variables with different "stream" qualifier, to make the data can export to
23564 // each stream, we must call the function EmitStreamVertex() and EndStreamPrimitive() to make each vertex emitted
23565 // by the GS is assigned to specific stream.
23566 static const GLchar* gs = " goku = uni_goku;\n"
23567 " gohan = uni_gohan;\n"
23568 " goten = uni_goten;\n"
23569 " EmitStreamVertex(0);\n"
23570 " EndStreamPrimitive(0);\n"
23571 " picolo = uni_picolo;\n"
23572 " vegeta = uni_vegeta;\n"
23573 " EmitStreamVertex(1);\n"
23574 " EndStreamPrimitive(1);\n"
23575 " bulma = uni_bulma;\n"
23576 " EmitStreamVertex(2);\n"
23577 " EndStreamPrimitive(2);\n";
23578
23579 static const GLchar* fs = " fs_out = gohan + goku + goten;\n";
23580
23581 const GLchar* assignments = "";
23582 switch (stage)
23583 {
23584 case Utils::Shader::FRAGMENT:
23585 assignments = fs;
23586 break;
23587 case Utils::Shader::GEOMETRY:
23588 assignments = gs;
23589 break;
23590 default:
23591 break;
23592 }
23593
23594 out_assignments = assignments;
23595 }
23596
23597 /** Get interface of shader
23598 *
23599 * @param ignored
23600 * @param stage Shader stage
23601 * @param out_interface Set to ""
23602 **/
23603 void XFBVertexStreamsTest::getShaderInterface(GLuint /* test_case_index */, Utils::Shader::STAGES stage,
23604 std::string& out_interface)
23605 {
23606 static const GLchar* gs = "layout (xfb_buffer = 1, xfb_stride = 64) out;\n"
23607 "layout (xfb_buffer = 2, xfb_stride = 64) out;\n"
23608 "layout (xfb_buffer = 3, xfb_stride = 64) out;\n"
23609 "\n"
23610 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23611 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23612 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n"
23613 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 48) out vec4 picolo;\n"
23614 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 32) out vec4 vegeta;\n"
23615 "layout (stream = 2, xfb_buffer = 2, xfb_offset = 32) out vec4 bulma;\n"
23616 "\n"
23617 "layout(binding = 0) uniform gs_block {\n"
23618 " vec4 uni_goku;\n"
23619 " vec4 uni_gohan;\n"
23620 " vec4 uni_goten;\n"
23621 " vec4 uni_picolo;\n"
23622 " vec4 uni_vegeta;\n"
23623 " vec4 uni_bulma;\n"
23624 "};\n";
23625 /*
23626 Fixed incorrect usage of in/out qualifier, the following variable should be input symbols for fragment shader
23627 */
23628 static const GLchar* fs = "in vec4 goku;\n"
23629 "in vec4 gohan;\n"
23630 "in vec4 goten;\n"
23631 "\n"
23632 "out vec4 fs_out;\n";
23633
23634 switch (stage)
23635 {
23636 case Utils::Shader::FRAGMENT:
23637 out_interface = fs;
23638 break;
23639 case Utils::Shader::GEOMETRY:
23640 out_interface = gs;
23641 break;
23642 default:
23643 out_interface = "";
23644 return;
23645 }
23646 }
23647
23648 /** Constructor
23649 *
23650 * @param context Test framework context
23651 **/
23652 XFBMultipleVertexStreamsTest::XFBMultipleVertexStreamsTest(deqp::Context& context)
23653 : NegativeTestBase(
23654 context, "xfb_multiple_vertex_streams",
23655 "Test verifies that compiler reports error when multiple streams are captured with same xfb_buffer")
23656 {
23657 }
23658
23659 /** Source for given test case and stage
23660 *
23661 * @param ignored
23662 * @param stage Shader stage
23663 *
23664 * @return Shader source
23665 **/
23666 std::string XFBMultipleVertexStreamsTest::getShaderSource(GLuint /* test_case_index */, Utils::Shader::STAGES stage)
23667 {
23668 static const GLchar* var_definition = "const uint valid_stride = 64;\n"
23669 "\n"
23670 "layout (xfb_buffer = 1, xfb_stride = valid_stride) out;\n"
23671 "layout (xfb_buffer = 3, xfb_stride = valid_stride) out;\n"
23672 "\n"
23673 "\n"
23674 #if DEBUG_NEG_REMOVE_ERROR
23675 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23676 "layout (stream = 1, xfb_buffer = 3, xfb_offset = 32) out vec4 gohan;\n"
23677 "layout (stream = 2, xfb_buffer = 2, xfb_offset = 16) out vec4 goten;\n";
23678 #else
23679 "layout (stream = 0, xfb_buffer = 1, xfb_offset = 48) out vec4 goku;\n"
23680 "layout (stream = 1, xfb_buffer = 1, xfb_offset = 32) out vec4 gohan;\n"
23681 "layout (stream = 2, xfb_buffer = 1, xfb_offset = 16) out vec4 goten;\n";
23682 #endif /* DEBUG_NEG_REMOVE_ERROR */
23683 static const GLchar* var_use = " goku = result / 2;\n"
23684 " gohan = result / 4;\n"
23685 " goten = result / 6;\n";
23686 static const GLchar* fs = "#version 430 core\n"
23687 "#extension GL_ARB_enhanced_layouts : require\n"
23688 "\n"
23689 "in vec4 gs_fs;\n"
23690 "in vec4 goku;\n"
23691 "out vec4 fs_out;\n"
23692 "\n"
23693 "void main()\n"
23694 "{\n"
23695 " fs_out = gs_fs + goku;\n"
23696 "}\n"
23697 "\n";
23698 static const GLchar* gs = "#version 430 core\n"
23699 "#extension GL_ARB_enhanced_layouts : require\n"
23700 "\n"
23701 "layout(points) in;\n"
23702 "layout(triangle_strip, max_vertices = 4) out;\n"
23703 "\n"
23704 "VAR_DEFINITION"
23705 "\n"
23706 "in vec4 vs_gs[];\n"
23707 "out vec4 gs_fs;\n"
23708 "\n"
23709 "void main()\n"
23710 "{\n"
23711 " vec4 result = vs_gs[0];\n"
23712 "\n"
23713 "VARIABLE_USE"
23714 "\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 " gs_fs = result;\n"
23722 " gl_Position = vec4(1, -1, 0, 1);\n"
23723 " EmitVertex();\n"
23724 " gs_fs = result;\n"
23725 " gl_Position = vec4(1, 1, 0, 1);\n"
23726 " EmitVertex();\n"
23727 "}\n"
23728 "\n";
23729 static const GLchar* vs = "#version 430 core\n"
23730 "#extension GL_ARB_enhanced_layouts : require\n"
23731 "\n"
23732 "in vec4 in_vs;\n"
23733 "out vec4 vs_gs;\n"
23734 "\n"
23735 "void main()\n"
23736 "{\n"
23737 " vs_gs = in_vs;\n"
23738 "}\n"
23739 "\n";
23740
23741 std::string source;
23742
23743 if (Utils::Shader::GEOMETRY == stage)
23744 {
23745 size_t position = 0;
23746
23747 source = gs;
23748
23749 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23750 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23751 }
23752 else
23753 {
23754 switch (stage)
23755 {
23756 case Utils::Shader::FRAGMENT:
23757 source = fs;
23758 break;
23759 case Utils::Shader::VERTEX:
23760 source = vs;
23761 break;
23762 default:
23763 source = "";
23764 }
23765 }
23766
23767 return source;
23768 }
23769
23770 /** Selects if "compute" stage is relevant for test
23771 *
23772 * @param ignored
23773 *
23774 * @return false
23775 **/
23776 bool XFBMultipleVertexStreamsTest::isComputeRelevant(GLuint /* test_case_index */)
23777 {
23778 return false;
23779 }
23780
23781 /** Constructor
23782 *
23783 * @param context Test framework context
23784 **/
23785 XFBExceedBufferLimitTest::XFBExceedBufferLimitTest(deqp::Context& context)
23786 : NegativeTestBase(context, "xfb_exceed_buffer_limit",
23787 "Test verifies that compiler reports error when xfb_buffer qualifier exceeds limit")
23788 {
23789 }
23790
23791 /** Source for given test case and stage
23792 *
23793 * @param test_case_index Index of test case
23794 * @param stage Shader stage
23795 *
23796 * @return Shader source
23797 **/
23798 std::string XFBExceedBufferLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
23799 {
23800 static const GLchar* block_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23801 "\n"
23802 #if DEBUG_NEG_REMOVE_ERROR
23803 "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
23804 #else
23805 "layout (xfb_buffer = buffer_index, xfb_offset = 0) out Goku {\n"
23806 #endif /* DEBUG_NEG_REMOVE_ERROR */
23807 " vec4 member;\n"
23808 "} goku;\n";
23809 static const GLchar* global_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23810 "\n"
23811 #if DEBUG_NEG_REMOVE_ERROR
23812 "layout (xfb_buffer = 0) out;\n";
23813 #else
23814 "layout (xfb_buffer = buffer_index) out;\n";
23815 #endif /* DEBUG_NEG_REMOVE_ERROR */
23816 static const GLchar* vector_var_definition = "const uint buffer_index = MAX_BUFFER;\n"
23817 "\n"
23818 #if DEBUG_NEG_REMOVE_ERROR
23819 "layout (xfb_buffer = 0) out vec4 goku;\n";
23820 #else
23821 "layout (xfb_buffer = buffer_index) out vec4 goku;\n";
23822 #endif /* DEBUG_NEG_REMOVE_ERROR */
23823 static const GLchar* block_use = " goku.member = result / 2;\n";
23824 static const GLchar* global_use = "";
23825 static const GLchar* vector_use = " goku = result / 2;\n";
23826 static const GLchar* fs = "#version 430 core\n"
23827 "#extension GL_ARB_enhanced_layouts : require\n"
23828 "\n"
23829 "in vec4 any_fs;\n"
23830 "out vec4 fs_out;\n"
23831 "\n"
23832 "void main()\n"
23833 "{\n"
23834 " fs_out = any_fs;\n"
23835 "}\n"
23836 "\n";
23837 static const GLchar* gs_tested = "#version 430 core\n"
23838 "#extension GL_ARB_enhanced_layouts : require\n"
23839 "\n"
23840 "layout(points) in;\n"
23841 "layout(triangle_strip, max_vertices = 4) out;\n"
23842 "\n"
23843 "VAR_DEFINITION"
23844 "\n"
23845 "in vec4 vs_any[];\n"
23846 "out vec4 any_fs;\n"
23847 "\n"
23848 "void main()\n"
23849 "{\n"
23850 " vec4 result = vs_any[0];\n"
23851 "\n"
23852 "VARIABLE_USE"
23853 "\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 " any_fs = result;\n"
23861 " gl_Position = vec4(1, -1, 0, 1);\n"
23862 " EmitVertex();\n"
23863 " any_fs = result;\n"
23864 " gl_Position = vec4(1, 1, 0, 1);\n"
23865 " EmitVertex();\n"
23866 "}\n"
23867 "\n";
23868 static const GLchar* tcs = "#version 430 core\n"
23869 "#extension GL_ARB_enhanced_layouts : require\n"
23870 "\n"
23871 "layout(vertices = 1) out;\n"
23872 "\n"
23873 "in vec4 vs_any[];\n"
23874 "out vec4 tcs_tes[];\n"
23875 "\n"
23876 "void main()\n"
23877 "{\n"
23878 "\n"
23879 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
23880 "\n"
23881 " gl_TessLevelOuter[0] = 1.0;\n"
23882 " gl_TessLevelOuter[1] = 1.0;\n"
23883 " gl_TessLevelOuter[2] = 1.0;\n"
23884 " gl_TessLevelOuter[3] = 1.0;\n"
23885 " gl_TessLevelInner[0] = 1.0;\n"
23886 " gl_TessLevelInner[1] = 1.0;\n"
23887 "}\n"
23888 "\n";
23889 static const GLchar* tes_tested = "#version 430 core\n"
23890 "#extension GL_ARB_enhanced_layouts : require\n"
23891 "\n"
23892 "layout(isolines, point_mode) in;\n"
23893 "\n"
23894 "VAR_DEFINITION"
23895 "\n"
23896 "in vec4 tcs_tes[];\n"
23897 "out vec4 any_fs;\n"
23898 "\n"
23899 "void main()\n"
23900 "{\n"
23901 " vec4 result = tcs_tes[0];\n"
23902 "\n"
23903 "VARIABLE_USE"
23904 "\n"
23905 " any_fs += result;\n"
23906 "}\n"
23907 "\n";
23908 static const GLchar* vs = "#version 430 core\n"
23909 "#extension GL_ARB_enhanced_layouts : require\n"
23910 "\n"
23911 "in vec4 in_vs;\n"
23912 "out vec4 vs_any;\n"
23913 "\n"
23914 "void main()\n"
23915 "{\n"
23916 " vs_any = in_vs;\n"
23917 "}\n"
23918 "\n";
23919 static const GLchar* vs_tested = "#version 430 core\n"
23920 "#extension GL_ARB_enhanced_layouts : require\n"
23921 "\n"
23922 "VAR_DEFINITION"
23923 "\n"
23924 "in vec4 in_vs;\n"
23925 "out vec4 any_fs;\n"
23926 "\n"
23927 "void main()\n"
23928 "{\n"
23929 " vec4 result = in_vs;\n"
23930 "\n"
23931 "VARIABLE_USE"
23932 "\n"
23933 " any_fs = result;\n"
23934 "}\n"
23935 "\n";
23936
23937 std::string source;
23938 testCase& test_case = m_test_cases[test_case_index];
23939
23940 if (test_case.m_stage == stage)
23941 {
23942 GLchar buffer[16];
23943 const Functions& gl = m_context.getRenderContext().getFunctions();
23944 GLint max_n_xfb = 0;
23945 size_t position = 0;
23946 const GLchar* var_definition = 0;
23947 const GLchar* var_use = 0;
23948
23949 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_n_xfb);
23950 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
23951
23952 sprintf(buffer, "%d", max_n_xfb);
23953
23954 switch (test_case.m_case)
23955 {
23956 case BLOCK:
23957 var_definition = block_var_definition;
23958 var_use = block_use;
23959 break;
23960 case GLOBAL:
23961 var_definition = global_var_definition;
23962 var_use = global_use;
23963 break;
23964 case VECTOR:
23965 var_definition = vector_var_definition;
23966 var_use = vector_use;
23967 break;
23968 default:
23969 TCU_FAIL("Invalid enum");
23970 }
23971
23972 switch (stage)
23973 {
23974 case Utils::Shader::GEOMETRY:
23975 source = gs_tested;
23976 break;
23977 case Utils::Shader::TESS_EVAL:
23978 source = tes_tested;
23979 break;
23980 case Utils::Shader::VERTEX:
23981 source = vs_tested;
23982 break;
23983 default:
23984 TCU_FAIL("Invalid enum");
23985 }
23986
23987 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
23988 position = 0;
23989 Utils::replaceToken("MAX_BUFFER", position, buffer, source);
23990 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
23991 }
23992 else
23993 {
23994 switch (test_case.m_stage)
23995 {
23996 case Utils::Shader::GEOMETRY:
23997 switch (stage)
23998 {
23999 case Utils::Shader::FRAGMENT:
24000 source = fs;
24001 break;
24002 case Utils::Shader::VERTEX:
24003 source = vs;
24004 break;
24005 default:
24006 source = "";
24007 }
24008 break;
24009 case Utils::Shader::TESS_EVAL:
24010 switch (stage)
24011 {
24012 case Utils::Shader::FRAGMENT:
24013 source = fs;
24014 break;
24015 case Utils::Shader::TESS_CTRL:
24016 source = tcs;
24017 break;
24018 case Utils::Shader::VERTEX:
24019 source = vs;
24020 break;
24021 default:
24022 source = "";
24023 }
24024 break;
24025 case Utils::Shader::VERTEX:
24026 switch (stage)
24027 {
24028 case Utils::Shader::FRAGMENT:
24029 source = fs;
24030 break;
24031 default:
24032 source = "";
24033 }
24034 break;
24035 default:
24036 TCU_FAIL("Invalid enum");
24037 break;
24038 }
24039 }
24040
24041 return source;
24042 }
24043
24044 /** Get description of test case
24045 *
24046 * @param test_case_index Index of test case
24047 *
24048 * @return Test case description
24049 **/
24050 std::string XFBExceedBufferLimitTest::getTestCaseName(GLuint test_case_index)
24051 {
24052 std::stringstream stream;
24053 testCase& test_case = m_test_cases[test_case_index];
24054
24055 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
24056
24057 switch (test_case.m_case)
24058 {
24059 case BLOCK:
24060 stream << "BLOCK";
24061 break;
24062 case GLOBAL:
24063 stream << "GLOBAL";
24064 break;
24065 case VECTOR:
24066 stream << "VECTOR";
24067 break;
24068 default:
24069 TCU_FAIL("Invalid enum");
24070 }
24071
24072 return stream.str();
24073 }
24074
24075 /** Get number of test cases
24076 *
24077 * @return Number of test cases
24078 **/
24079 GLuint XFBExceedBufferLimitTest::getTestCaseNumber()
24080 {
24081 return static_cast<GLuint>(m_test_cases.size());
24082 }
24083
24084 /** Selects if "compute" stage is relevant for test
24085 *
24086 * @param ignored
24087 *
24088 * @return false
24089 **/
24090 bool XFBExceedBufferLimitTest::isComputeRelevant(GLuint /* test_case_index */)
24091 {
24092 return false;
24093 }
24094
24095 /** Prepare all test cases
24096 *
24097 **/
24098 void XFBExceedBufferLimitTest::testInit()
24099 {
24100 for (GLuint c = 0; c < CASE_MAX; ++c)
24101 {
24102 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24103 {
24104 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
24105 (Utils::Shader::FRAGMENT == stage))
24106 {
24107 continue;
24108 }
24109
24110 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
24111
24112 m_test_cases.push_back(test_case);
24113 }
24114 }
24115 }
24116
24117 /** Constructor
24118 *
24119 * @param context Test framework context
24120 **/
24121 XFBExceedOffsetLimitTest::XFBExceedOffsetLimitTest(deqp::Context& context)
24122 : NegativeTestBase(context, "xfb_exceed_offset_limit",
24123 "Test verifies that compiler reports error when xfb_offset qualifier exceeds limit")
24124 {
24125 }
24126
24127 /** Source for given test case and stage
24128 *
24129 * @param test_case_index Index of test case
24130 * @param stage Shader stage
24131 *
24132 * @return Shader source
24133 **/
24134 std::string XFBExceedOffsetLimitTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24135 {
24136 static const GLchar* block_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24137 "\n"
24138 #if DEBUG_NEG_REMOVE_ERROR
24139 "layout (xfb_buffer = 0, xfb_offset = 0) out Goku {\n"
24140 #else
24141 "layout (xfb_buffer = 0, xfb_offset = overflow_offset + 16) out Goku "
24142 "{\n"
24143 #endif /* DEBUG_NEG_REMOVE_ERROR */
24144 " vec4 member;\n"
24145 "} goku;\n";
24146 static const GLchar* global_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24147 "\n"
24148 #if DEBUG_NEG_REMOVE_ERROR
24149 "layout (xfb_buffer = 0, xfb_stride = 0) out;\n";
24150 #else
24151 "layout (xfb_buffer = 0, xfb_stride = overflow_offset) out;\n";
24152 #endif /* DEBUG_NEG_REMOVE_ERROR */
24153 static const GLchar* vector_var_definition = "const uint overflow_offset = MAX_SIZE + 16;\n"
24154 "\n"
24155 #if DEBUG_NEG_REMOVE_ERROR
24156 "layout (xfb_buffer = 0, xfb_offset = 0) out vec4 goku;\n";
24157 #else
24158 "layout (xfb_buffer = 0, xfb_offset = overflow_offset) out vec4 "
24159 "goku;\n";
24160 #endif /* DEBUG_NEG_REMOVE_ERROR */
24161 static const GLchar* block_use = " goku.member = result / 2;\n";
24162 static const GLchar* global_use = "";
24163 static const GLchar* vector_use = " goku = result / 2;\n";
24164 static const GLchar* fs = "#version 430 core\n"
24165 "#extension GL_ARB_enhanced_layouts : require\n"
24166 "\n"
24167 "in vec4 any_fs;\n"
24168 "out vec4 fs_out;\n"
24169 "\n"
24170 "void main()\n"
24171 "{\n"
24172 " fs_out = any_fs;\n"
24173 "}\n"
24174 "\n";
24175 static const GLchar* gs_tested = "#version 430 core\n"
24176 "#extension GL_ARB_enhanced_layouts : require\n"
24177 "\n"
24178 "layout(points) in;\n"
24179 "layout(triangle_strip, max_vertices = 4) out;\n"
24180 "\n"
24181 "VAR_DEFINITION"
24182 "\n"
24183 "in vec4 vs_any[];\n"
24184 "out vec4 any_fs;\n"
24185 "\n"
24186 "void main()\n"
24187 "{\n"
24188 " vec4 result = vs_any[0];\n"
24189 "\n"
24190 "VARIABLE_USE"
24191 "\n"
24192 " any_fs = result;\n"
24193 " gl_Position = vec4(-1, -1, 0, 1);\n"
24194 " EmitVertex();\n"
24195 " any_fs = result;\n"
24196 " gl_Position = vec4(-1, 1, 0, 1);\n"
24197 " EmitVertex();\n"
24198 " any_fs = result;\n"
24199 " gl_Position = vec4(1, -1, 0, 1);\n"
24200 " EmitVertex();\n"
24201 " any_fs = result;\n"
24202 " gl_Position = vec4(1, 1, 0, 1);\n"
24203 " EmitVertex();\n"
24204 "}\n"
24205 "\n";
24206 static const GLchar* tcs = "#version 430 core\n"
24207 "#extension GL_ARB_enhanced_layouts : require\n"
24208 "\n"
24209 "layout(vertices = 1) out;\n"
24210 "\n"
24211 "in vec4 vs_any[];\n"
24212 "out vec4 tcs_tes[];\n"
24213 "\n"
24214 "void main()\n"
24215 "{\n"
24216 "\n"
24217 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
24218 "\n"
24219 " gl_TessLevelOuter[0] = 1.0;\n"
24220 " gl_TessLevelOuter[1] = 1.0;\n"
24221 " gl_TessLevelOuter[2] = 1.0;\n"
24222 " gl_TessLevelOuter[3] = 1.0;\n"
24223 " gl_TessLevelInner[0] = 1.0;\n"
24224 " gl_TessLevelInner[1] = 1.0;\n"
24225 "}\n"
24226 "\n";
24227 static const GLchar* tes_tested = "#version 430 core\n"
24228 "#extension GL_ARB_enhanced_layouts : require\n"
24229 "\n"
24230 "layout(isolines, point_mode) in;\n"
24231 "\n"
24232 "VAR_DEFINITION"
24233 "\n"
24234 "in vec4 tcs_tes[];\n"
24235 "out vec4 any_fs;\n"
24236 "\n"
24237 "void main()\n"
24238 "{\n"
24239 " vec4 result = tcs_tes[0];\n"
24240 "\n"
24241 "VARIABLE_USE"
24242 "\n"
24243 " any_fs += result;\n"
24244 "}\n"
24245 "\n";
24246 static const GLchar* vs = "#version 430 core\n"
24247 "#extension GL_ARB_enhanced_layouts : require\n"
24248 "\n"
24249 "in vec4 in_vs;\n"
24250 "out vec4 vs_any;\n"
24251 "\n"
24252 "void main()\n"
24253 "{\n"
24254 " vs_any = in_vs;\n"
24255 "}\n"
24256 "\n";
24257 static const GLchar* vs_tested = "#version 430 core\n"
24258 "#extension GL_ARB_enhanced_layouts : require\n"
24259 "\n"
24260 "VAR_DEFINITION"
24261 "\n"
24262 "in vec4 in_vs;\n"
24263 "out vec4 any_fs;\n"
24264 "\n"
24265 "void main()\n"
24266 "{\n"
24267 " vec4 result = in_vs;\n"
24268 "\n"
24269 "VARIABLE_USE"
24270 "\n"
24271 " any_fs = result;\n"
24272 "}\n"
24273 "\n";
24274
24275 std::string source;
24276 testCase& test_case = m_test_cases[test_case_index];
24277
24278 if (test_case.m_stage == stage)
24279 {
24280 GLchar buffer[16];
24281 const Functions& gl = m_context.getRenderContext().getFunctions();
24282 GLint max_n_xfb_comp = 0;
24283 GLint max_n_xfb_bytes = 0;
24284 size_t position = 0;
24285 const GLchar* var_definition = 0;
24286 const GLchar* var_use = 0;
24287
24288 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_n_xfb_comp);
24289 GLU_EXPECT_NO_ERROR(gl.getError(), "GetIntegerv");
24290
24291 max_n_xfb_bytes = max_n_xfb_comp * 4;
24292
24293 sprintf(buffer, "%d", max_n_xfb_bytes);
24294
24295 switch (test_case.m_case)
24296 {
24297 case BLOCK:
24298 var_definition = block_var_definition;
24299 var_use = block_use;
24300 break;
24301 case GLOBAL:
24302 var_definition = global_var_definition;
24303 var_use = global_use;
24304 break;
24305 case VECTOR:
24306 var_definition = vector_var_definition;
24307 var_use = vector_use;
24308 break;
24309 default:
24310 TCU_FAIL("Invalid enum");
24311 }
24312
24313 switch (stage)
24314 {
24315 case Utils::Shader::GEOMETRY:
24316 source = gs_tested;
24317 break;
24318 case Utils::Shader::TESS_EVAL:
24319 source = tes_tested;
24320 break;
24321 case Utils::Shader::VERTEX:
24322 source = vs_tested;
24323 break;
24324 default:
24325 TCU_FAIL("Invalid enum");
24326 }
24327
24328 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
24329 position = 0;
24330 Utils::replaceToken("MAX_SIZE", position, buffer, source);
24331 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
24332 }
24333 else
24334 {
24335 switch (test_case.m_stage)
24336 {
24337 case Utils::Shader::GEOMETRY:
24338 switch (stage)
24339 {
24340 case Utils::Shader::FRAGMENT:
24341 source = fs;
24342 break;
24343 case Utils::Shader::VERTEX:
24344 source = vs;
24345 break;
24346 default:
24347 source = "";
24348 }
24349 break;
24350 case Utils::Shader::TESS_EVAL:
24351 switch (stage)
24352 {
24353 case Utils::Shader::FRAGMENT:
24354 source = fs;
24355 break;
24356 case Utils::Shader::TESS_CTRL:
24357 source = tcs;
24358 break;
24359 case Utils::Shader::VERTEX:
24360 source = vs;
24361 break;
24362 default:
24363 source = "";
24364 }
24365 break;
24366 case Utils::Shader::VERTEX:
24367 switch (stage)
24368 {
24369 case Utils::Shader::FRAGMENT:
24370 source = fs;
24371 break;
24372 default:
24373 source = "";
24374 }
24375 break;
24376 default:
24377 TCU_FAIL("Invalid enum");
24378 break;
24379 }
24380 }
24381
24382 return source;
24383 }
24384
24385 /** Get description of test case
24386 *
24387 * @param test_case_index Index of test case
24388 *
24389 * @return Test case description
24390 **/
24391 std::string XFBExceedOffsetLimitTest::getTestCaseName(GLuint test_case_index)
24392 {
24393 std::stringstream stream;
24394 testCase& test_case = m_test_cases[test_case_index];
24395
24396 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage) << ", case: ";
24397
24398 switch (test_case.m_case)
24399 {
24400 case BLOCK:
24401 stream << "BLOCK";
24402 break;
24403 case GLOBAL:
24404 stream << "GLOBAL";
24405 break;
24406 case VECTOR:
24407 stream << "VECTOR";
24408 break;
24409 default:
24410 TCU_FAIL("Invalid enum");
24411 }
24412
24413 return stream.str();
24414 }
24415
24416 /** Get number of test cases
24417 *
24418 * @return Number of test cases
24419 **/
24420 GLuint XFBExceedOffsetLimitTest::getTestCaseNumber()
24421 {
24422 return static_cast<GLuint>(m_test_cases.size());
24423 }
24424
24425 /** Selects if "compute" stage is relevant for test
24426 *
24427 * @param ignored
24428 *
24429 * @return false
24430 **/
24431 bool XFBExceedOffsetLimitTest::isComputeRelevant(GLuint /* test_case_index */)
24432 {
24433 return false;
24434 }
24435
24436 /** Prepare all test cases
24437 *
24438 **/
24439 void XFBExceedOffsetLimitTest::testInit()
24440 {
24441 for (GLuint c = 0; c < CASE_MAX; ++c)
24442 {
24443 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
24444 {
24445 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
24446 (Utils::Shader::FRAGMENT == stage))
24447 {
24448 continue;
24449 }
24450
24451 testCase test_case = { (CASES)c, (Utils::Shader::STAGES)stage };
24452
24453 m_test_cases.push_back(test_case);
24454 }
24455 }
24456 }
24457
24458 /** Constructor
24459 *
24460 * @param context Test context
24461 **/
24462 XFBGlobalBufferTest::XFBGlobalBufferTest(deqp::Context& context)
24463 : BufferTestBase(context, "xfb_global_buffer", "Test verifies that global xfb_buffer qualifier is respected")
24464 {
24465 /* Nothing to be done here */
24466 }
24467
24468 /** Get descriptors of buffers necessary for test
24469 *
24470 * @param test_case_index Index of test case
24471 * @param out_descriptors Descriptors of buffers used by test
24472 **/
24473 void XFBGlobalBufferTest::getBufferDescriptors(glw::GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24474 {
24475 // the function "getType(test_case_index)" can't return correct data type, so change code as following:
24476 const Utils::Type& type = m_test_cases[test_case_index].m_type;
24477
24478 /* Test needs single uniform and two xfbs */
24479 out_descriptors.resize(3);
24480
24481 /* Get references */
24482 bufferDescriptor& uniform = out_descriptors[0];
24483 bufferDescriptor& xfb_1 = out_descriptors[1];
24484 bufferDescriptor& xfb_3 = out_descriptors[2];
24485
24486 /* Index */
24487 uniform.m_index = 0;
24488 xfb_1.m_index = 1;
24489 xfb_3.m_index = 3;
24490
24491 /* Target */
24492 uniform.m_target = Utils::Buffer::Uniform;
24493 xfb_1.m_target = Utils::Buffer::Transform_feedback;
24494 xfb_3.m_target = Utils::Buffer::Transform_feedback;
24495
24496 /* Data */
24497 const GLuint gen_start = Utils::s_rand;
24498 const std::vector<GLubyte>& chichi_data = type.GenerateData();
24499 const std::vector<GLubyte>& bulma_data = type.GenerateData();
24500 const std::vector<GLubyte>& trunks_data = type.GenerateData();
24501 const std::vector<GLubyte>& bra_data = type.GenerateData();
24502 const std::vector<GLubyte>& gohan_data = type.GenerateData();
24503 const std::vector<GLubyte>& goten_data = type.GenerateData();
24504
24505 Utils::s_rand = gen_start;
24506 const std::vector<GLubyte>& chichi_data_pck = type.GenerateDataPacked();
24507 const std::vector<GLubyte>& bulma_data_pck = type.GenerateDataPacked();
24508 const std::vector<GLubyte>& trunks_data_pck = type.GenerateDataPacked();
24509 const std::vector<GLubyte>& bra_data_pck = type.GenerateDataPacked();
24510 const std::vector<GLubyte>& gohan_data_pck = type.GenerateDataPacked();
24511 const std::vector<GLubyte>& goten_data_pck = type.GenerateDataPacked();
24512
24513 const GLuint type_size = static_cast<GLuint>(chichi_data.size());
24514 const GLuint type_size_pck = static_cast<GLuint>(chichi_data_pck.size());
24515
24516 /* Uniform data */
24517 uniform.m_initial_data.resize(6 * type_size);
24518 memcpy(&uniform.m_initial_data[0] + 0, &chichi_data[0], type_size);
24519 memcpy(&uniform.m_initial_data[0] + type_size, &bulma_data[0], type_size);
24520 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &trunks_data[0], type_size);
24521 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &bra_data[0], type_size);
24522 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &gohan_data[0], type_size);
24523 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &goten_data[0], type_size);
24524
24525 /* XFB data */
24526 xfb_1.m_initial_data.resize(3 * type_size_pck);
24527 xfb_1.m_expected_data.resize(3 * type_size_pck);
24528 xfb_3.m_initial_data.resize(3 * type_size_pck);
24529 xfb_3.m_expected_data.resize(3 * type_size_pck);
24530
24531 for (GLuint i = 0; i < 3 * type_size_pck; ++i)
24532 {
24533 xfb_1.m_initial_data[i] = (glw::GLubyte)i;
24534 xfb_1.m_expected_data[i] = (glw::GLubyte)i;
24535 xfb_3.m_initial_data[i] = (glw::GLubyte)i;
24536 xfb_3.m_expected_data[i] = (glw::GLubyte)i;
24537 }
24538
24539 memcpy(&xfb_3.m_expected_data[0] + 2 * type_size_pck, &chichi_data_pck[0], type_size_pck);
24540 memcpy(&xfb_1.m_expected_data[0] + 0 * type_size_pck, &bulma_data_pck[0], type_size_pck);
24541 memcpy(&xfb_1.m_expected_data[0] + 1 * type_size_pck, &trunks_data_pck[0], type_size_pck);
24542 memcpy(&xfb_1.m_expected_data[0] + 2 * type_size_pck, &bra_data_pck[0], type_size_pck);
24543 memcpy(&xfb_3.m_expected_data[0] + 0 * type_size_pck, &gohan_data_pck[0], type_size_pck);
24544 memcpy(&xfb_3.m_expected_data[0] + 1 * type_size_pck, &goten_data_pck[0], type_size_pck);
24545 }
24546
24547 /** Source for given test case and stage
24548 *
24549 * @param test_case_index Index of test case
24550 * @param stage Shader stage
24551 *
24552 * @return Shader source
24553 **/
24554 std::string XFBGlobalBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
24555 {
24556 static const GLchar* fs =
24557 "#version 430 core\n"
24558 "#extension GL_ARB_enhanced_layouts : require\n"
24559 "\n"
24560 "flat in TYPE chichi;\n"
24561 "flat in TYPE bulma;\n"
24562 "in Vegeta {\n"
24563 " flat TYPE trunk;\n"
24564 " flat TYPE bra;\n"
24565 "} vegeta;\n"
24566 "in Goku {\n"
24567 " flat TYPE gohan;\n"
24568 " flat TYPE goten;\n"
24569 "} goku;\n"
24570 "\n"
24571 "out vec4 fs_out;\n"
24572 "\n"
24573 "void main()\n"
24574 "{\n"
24575 " fs_out = vec4(1);\n"
24576 " if (TYPE(1) != chichi + bulma + vegeta.trunk + vegeta.bra + goku.gohan + goku.goten)\n"
24577 " {\n"
24578 " fs_out = vec4(0);\n"
24579 " }\n"
24580 "}\n"
24581 "\n";
24582
24583 static const GLchar* gs = "#version 430 core\n"
24584 "#extension GL_ARB_enhanced_layouts : require\n"
24585 "\n"
24586 "layout(points) in;\n"
24587 "layout(points, max_vertices = 1) out;\n"
24588 "\n"
24589 "INTERFACE"
24590 "\n"
24591 "void main()\n"
24592 "{\n"
24593 "ASSIGNMENTS"
24594 " EmitVertex();\n"
24595 "}\n"
24596 "\n";
24597
24598 static const GLchar* tcs = "#version 430 core\n"
24599 "#extension GL_ARB_enhanced_layouts : require\n"
24600 "\n"
24601 "layout(vertices = 1) out;\n"
24602 "\n"
24603 "\n"
24604 "void main()\n"
24605 "{\n"
24606 " gl_TessLevelOuter[0] = 1.0;\n"
24607 " gl_TessLevelOuter[1] = 1.0;\n"
24608 " gl_TessLevelOuter[2] = 1.0;\n"
24609 " gl_TessLevelOuter[3] = 1.0;\n"
24610 " gl_TessLevelInner[0] = 1.0;\n"
24611 " gl_TessLevelInner[1] = 1.0;\n"
24612 "}\n"
24613 "\n";
24614
24615 static const GLchar* tes = "#version 430 core\n"
24616 "#extension GL_ARB_enhanced_layouts : require\n"
24617 "\n"
24618 "layout(isolines, point_mode) in;\n"
24619 "\n"
24620 "INTERFACE"
24621 "\n"
24622 "void main()\n"
24623 "{\n"
24624 "ASSIGNMENTS"
24625 "}\n"
24626 "\n";
24627
24628 static const GLchar* vs = "#version 430 core\n"
24629 "#extension GL_ARB_enhanced_layouts : require\n"
24630 "\n"
24631 "void main()\n"
24632 "{\n"
24633 "}\n"
24634 "\n";
24635
24636 static const GLchar* vs_tested = "#version 430 core\n"
24637 "#extension GL_ARB_enhanced_layouts : require\n"
24638 "\n"
24639 "INTERFACE"
24640 "\n"
24641 "void main()\n"
24642 "{\n"
24643 "ASSIGNMENTS"
24644 "}\n"
24645 "\n";
24646
24647 std::string source;
24648 const _testCase& test_case = m_test_cases[test_case_index];
24649 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
24650
24651 if (test_case.m_stage == stage)
24652 {
24653 std::string assignments = " chichi = uni_chichi;\n"
24654 " bulma = uni_bulma;\n"
24655 " vegeta.trunk = uni_trunk;\n"
24656 " vegeta.bra = uni_bra;\n"
24657 " goku.gohan = uni_gohan;\n"
24658 " goku.goten = uni_goten;\n";
24659
24660 std::string interface = "layout (xfb_buffer = 3) out;\n"
24661 "\n"
24662 "const uint type_size = SIZE;\n"
24663 "\n"
24664 "layout ( xfb_offset = 2 * type_size) flat out TYPE chichi;\n"
24665 "layout (xfb_buffer = 1, xfb_offset = 0) flat out TYPE bulma;\n"
24666 "layout (xfb_buffer = 1, xfb_offset = 1 * type_size) out Vegeta {\n"
24667 " flat TYPE trunk;\n"
24668 " flat TYPE bra;\n"
24669 "} vegeta;\n"
24670 "layout ( xfb_offset = 0) out Goku {\n"
24671 " flat TYPE gohan;\n"
24672 " flat TYPE goten;\n"
24673 "} goku;\n"
24674 "\n"
24675 // Uniform block must be declared with std140, otherwise each block member is not packed
24676 "layout(binding = 0, std140) uniform block {\n"
24677 " TYPE uni_chichi;\n"
24678 " TYPE uni_bulma;\n"
24679 " TYPE uni_trunk;\n"
24680 " TYPE uni_bra;\n"
24681 " TYPE uni_gohan;\n"
24682 " TYPE uni_goten;\n"
24683 "};\n";
24684
24685 /* Prepare interface string */
24686 {
24687 GLchar buffer[16];
24688 size_t position = 0;
24689 const GLuint type_size = test_case.m_type.GetSize();
24690
24691 sprintf(buffer, "%d", type_size);
24692
24693 Utils::replaceToken("SIZE", position, buffer, interface);
24694 Utils::replaceAllTokens("TYPE", type_name, interface);
24695 }
24696
24697 switch (stage)
24698 {
24699 case Utils::Shader::GEOMETRY:
24700 source = gs;
24701 break;
24702 case Utils::Shader::TESS_EVAL:
24703 source = tes;
24704 break;
24705 case Utils::Shader::VERTEX:
24706 source = vs_tested;
24707 break;
24708 default:
24709 TCU_FAIL("Invalid enum");
24710 }
24711
24712 /* Replace tokens */
24713 {
24714 size_t position = 0;
24715
24716 Utils::replaceToken("INTERFACE", position, interface.c_str(), source);
24717 Utils::replaceToken("ASSIGNMENTS", position, assignments.c_str(), source);
24718 }
24719 }
24720 else
24721 {
24722 switch (test_case.m_stage)
24723 {
24724 case Utils::Shader::GEOMETRY:
24725 switch (stage)
24726 {
24727 case Utils::Shader::FRAGMENT:
24728 source = fs;
24729 Utils::replaceAllTokens("TYPE", type_name, source);
24730 break;
24731 case Utils::Shader::VERTEX:
24732 source = vs;
24733 break;
24734 default:
24735 source = "";
24736 }
24737 break;
24738 case Utils::Shader::TESS_EVAL:
24739 switch (stage)
24740 {
24741 case Utils::Shader::FRAGMENT:
24742 source = fs;
24743 Utils::replaceAllTokens("TYPE", type_name, source);
24744 break;
24745 case Utils::Shader::TESS_CTRL:
24746 source = tcs;
24747 break;
24748 case Utils::Shader::VERTEX:
24749 source = vs;
24750 break;
24751 default:
24752 source = "";
24753 }
24754 break;
24755 case Utils::Shader::VERTEX:
24756 switch (stage)
24757 {
24758 case Utils::Shader::FRAGMENT:
24759 source = fs;
24760 Utils::replaceAllTokens("TYPE", type_name, source);
24761 break;
24762 default:
24763 source = "";
24764 }
24765 break;
24766 default:
24767 TCU_FAIL("Invalid enum");
24768 break;
24769 }
24770 }
24771
24772 return source;
24773 }
24774
24775 /** Get name of test case
24776 *
24777 * @param test_case_index Index of test case
24778 *
24779 * @return Name of case
24780 **/
24781 std::string XFBGlobalBufferTest::getTestCaseName(GLuint test_case_index)
24782 {
24783 std::string name;
24784 const _testCase& test_case = m_test_cases[test_case_index];
24785
24786 name = "Tested stage: ";
24787 name.append(Utils::Shader::GetStageName(test_case.m_stage));
24788 name.append(". Tested type: ");
24789 name.append(test_case.m_type.GetGLSLTypeName());
24790
24791 return name;
24792 }
24793
24794 /** Get number of cases
24795 *
24796 * @return Number of test cases
24797 **/
24798 GLuint XFBGlobalBufferTest::getTestCaseNumber()
24799 {
24800 return static_cast<GLuint>(m_test_cases.size());
24801 }
24802
24803 /** Prepare set of test cases
24804 *
24805 **/
24806 void XFBGlobalBufferTest::testInit()
24807 {
24808 GLuint n_types = getTypesNumber();
24809
24810 for (GLuint i = 0; i < n_types; ++i)
24811 {
24812 const Utils::Type& type = getType(i);
24813 /*
24814 When the tfx varying is the following type, the number of output exceeds the gl_MaxVaryingComponents, which will
24815 cause a link time error.
24816 */
24817 if (strcmp(type.GetGLSLTypeName(), "dmat3") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4") == 0 ||
24818 strcmp(type.GetGLSLTypeName(), "dmat3x4") == 0 || strcmp(type.GetGLSLTypeName(), "dmat4x3") == 0)
24819 {
24820 continue;
24821 }
24822 const _testCase test_cases[] = { { Utils::Shader::VERTEX, type },
24823 { Utils::Shader::GEOMETRY, type },
24824 { Utils::Shader::TESS_EVAL, type } };
24825
24826 m_test_cases.push_back(test_cases[0]);
24827 m_test_cases.push_back(test_cases[1]);
24828 m_test_cases.push_back(test_cases[2]);
24829 }
24830 }
24831
24832 /** Constructor
24833 *
24834 * @param context Test context
24835 **/
24836 XFBStrideTest::XFBStrideTest(deqp::Context& context)
24837 : BufferTestBase(context, "xfb_stride", "Test verifies that correct stride is used for all types")
24838 {
24839 /* Nothing to be done here */
24840 }
24841
24842 /** Execute drawArrays for single vertex
24843 *
24844 * @param test_case_index
24845 *
24846 * @return true
24847 **/
24848 bool XFBStrideTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
24849 {
24850 const Functions& gl = m_context.getRenderContext().getFunctions();
24851 GLenum primitive_type = GL_PATCHES;
24852 const testCase& test_case = m_test_cases[test_case_index];
24853
24854 if (Utils::Shader::VERTEX == test_case.m_stage)
24855 {
24856 primitive_type = GL_POINTS;
24857 }
24858
24859 gl.disable(GL_RASTERIZER_DISCARD);
24860 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
24861
24862 gl.beginTransformFeedback(GL_POINTS);
24863 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
24864
24865 gl.drawArrays(primitive_type, 0 /* first */, 2 /* count */);
24866 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
24867
24868 gl.endTransformFeedback();
24869 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
24870
24871 return true;
24872 }
24873
24874 /** Get descriptors of buffers necessary for test
24875 *
24876 * @param test_case_index Index of test case
24877 * @param out_descriptors Descriptors of buffers used by test
24878 **/
24879 void XFBStrideTest::getBufferDescriptors(GLuint test_case_index, bufferDescriptor::Vector& out_descriptors)
24880 {
24881 const testCase& test_case = m_test_cases[test_case_index];
24882 const Utils::Type& type = test_case.m_type;
24883
24884 /* Test needs single uniform and xfb */
24885 out_descriptors.resize(2);
24886
24887 /* Get references */
24888 bufferDescriptor& uniform = out_descriptors[0];
24889 bufferDescriptor& xfb = out_descriptors[1];
24890
24891 /* Index */
24892 uniform.m_index = 0;
24893 xfb.m_index = 0;
24894
24895 /* Target */
24896 uniform.m_target = Utils::Buffer::Uniform;
24897 xfb.m_target = Utils::Buffer::Transform_feedback;
24898
24899 /* Data */
24900 const GLuint rand_start = Utils::s_rand;
24901 const std::vector<GLubyte>& uniform_data = type.GenerateData();
24902
24903 Utils::s_rand = rand_start;
24904 const std::vector<GLubyte>& xfb_data = type.GenerateDataPacked();
24905
24906 const GLuint uni_type_size = static_cast<GLuint>(uniform_data.size());
24907 const GLuint xfb_type_size = static_cast<GLuint>(xfb_data.size());
24908 /*
24909 Note: If xfb varying output from vertex shader, the variable "goku" will only output once to transform feedback buffer,
24910 if xfb varying output from TES or GS, because the input primitive type in TES is defined as "layout(isolines, point_mode) in;",
24911 the primitive type is line which make the variable "goku" will output twice to transform feedback buffer, so for vertex shader
24912 only one valid data should be initialized in xfb.m_expected_data
24913 */
24914 const GLuint xfb_data_size = (test_case.m_stage == Utils::Shader::VERTEX) ? xfb_type_size : xfb_type_size * 2;
24915 /* Uniform data */
24916 uniform.m_initial_data.resize(uni_type_size);
24917 memcpy(&uniform.m_initial_data[0] + 0 * uni_type_size, &uniform_data[0], uni_type_size);
24918
24919 /* XFB data */
24920 xfb.m_initial_data.resize(xfb_data_size);
24921 xfb.m_expected_data.resize(xfb_data_size);
24922
24923 for (GLuint i = 0; i < xfb_data_size; ++i)
24924 {
24925 xfb.m_initial_data[i] = (glw::GLubyte)i;
24926 xfb.m_expected_data[i] = (glw::GLubyte)i;
24927 }
24928
24929 if (test_case.m_stage == Utils::Shader::VERTEX)
24930 {
24931 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24932 }
24933 else
24934 {
24935 memcpy(&xfb.m_expected_data[0] + 0 * xfb_type_size, &xfb_data[0], xfb_type_size);
24936 memcpy(&xfb.m_expected_data[0] + 1 * xfb_type_size, &xfb_data[0], xfb_type_size);
24937 }
24938 }
24939
24940 /** Get body of main function for given shader stage
24941 *
24942 * @param test_case_index Index of test case
24943 * @param stage Shader stage
24944 * @param out_assignments Set to empty
24945 * @param out_calculations Set to empty
24946 **/
24947 void XFBStrideTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_assignments,
24948 std::string& out_calculations)
24949 {
24950 const testCase& test_case = m_test_cases[test_case_index];
24951
24952 out_calculations = "";
24953
24954 static const GLchar* vs_tes_gs = " goku = uni_goku;\n";
24955 static const GLchar* fs = " fs_out = vec4(1, 0.25, 0.5, 0.75);\n"
24956 " if (TYPE(0) == goku)\n"
24957 " {\n"
24958 " fs_out = vec4(1, 0.75, 0.5, 0.5);\n"
24959 " }\n";
24960
24961 const GLchar* assignments = "";
24962
24963 if (test_case.m_stage == stage)
24964 {
24965 switch (stage)
24966 {
24967 case Utils::Shader::GEOMETRY:
24968 assignments = vs_tes_gs;
24969 break;
24970 case Utils::Shader::TESS_EVAL:
24971 assignments = vs_tes_gs;
24972 break;
24973 case Utils::Shader::VERTEX:
24974 assignments = vs_tes_gs;
24975 break;
24976 default:
24977 TCU_FAIL("Invalid enum");
24978 }
24979 }
24980 else
24981 {
24982 switch (stage)
24983 {
24984 case Utils::Shader::FRAGMENT:
24985 assignments = fs;
24986 break;
24987 case Utils::Shader::GEOMETRY:
24988 case Utils::Shader::TESS_CTRL:
24989 case Utils::Shader::TESS_EVAL:
24990 case Utils::Shader::VERTEX:
24991 break;
24992 default:
24993 TCU_FAIL("Invalid enum");
24994 }
24995 }
24996
24997 out_assignments = assignments;
24998
24999 if (Utils::Shader::FRAGMENT == stage)
25000 {
25001 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_assignments);
25002 }
25003 }
25004
25005 /** Get interface of shader
25006 *
25007 * @param test_case_index Index of test case
25008 * @param stage Shader stage
25009 * @param out_interface Set to ""
25010 **/
25011 void XFBStrideTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage, std::string& out_interface)
25012 {
25013 static const GLchar* vs_tes_gs = "layout (xfb_offset = 0) FLAT out TYPE goku;\n"
25014 "\n"
25015 "layout(std140, binding = 0) uniform Goku {\n"
25016 " TYPE uni_goku;\n"
25017 "};\n";
25018 static const GLchar* fs = "FLAT in TYPE goku;\n"
25019 "\n"
25020 "out vec4 fs_out;\n";
25021
25022 const testCase& test_case = m_test_cases[test_case_index];
25023 const GLchar* interface = "";
25024 const GLchar* flat = "";
25025
25026 if (test_case.m_stage == stage)
25027 {
25028 switch (stage)
25029 {
25030 case Utils::Shader::GEOMETRY:
25031 interface = vs_tes_gs;
25032 break;
25033 case Utils::Shader::TESS_EVAL:
25034 interface = vs_tes_gs;
25035 break;
25036 case Utils::Shader::VERTEX:
25037 interface = vs_tes_gs;
25038 break;
25039 default:
25040 TCU_FAIL("Invalid enum");
25041 }
25042 }
25043 else
25044 {
25045 switch (stage)
25046 {
25047 case Utils::Shader::FRAGMENT:
25048 interface = fs;
25049 break;
25050 case Utils::Shader::GEOMETRY:
25051 case Utils::Shader::TESS_CTRL:
25052 case Utils::Shader::TESS_EVAL:
25053 case Utils::Shader::VERTEX:
25054 break;
25055 default:
25056 TCU_FAIL("Invalid enum");
25057 }
25058 }
25059
25060 out_interface = interface;
25061
25062 if (Utils::Type::Float != test_case.m_type.m_basic_type)
25063 {
25064 flat = "flat";
25065 }
25066
25067 Utils::replaceAllTokens("FLAT", flat, out_interface);
25068 Utils::replaceAllTokens("TYPE", test_case.m_type.GetGLSLTypeName(), out_interface);
25069 }
25070
25071 /** Get source code of shader
25072 *
25073 * @param test_case_index Index of test case
25074 * @param stage Shader stage
25075 *
25076 * @return Source
25077 **/
25078 std::string XFBStrideTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25079 {
25080 std::string source;
25081 const testCase& test_case = m_test_cases[test_case_index];
25082
25083 switch (test_case.m_stage)
25084 {
25085 case Utils::Shader::VERTEX:
25086 switch (stage)
25087 {
25088 case Utils::Shader::FRAGMENT:
25089 case Utils::Shader::VERTEX:
25090 source = BufferTestBase::getShaderSource(test_case_index, stage);
25091 break;
25092 default:
25093 break;
25094 }
25095 break;
25096
25097 case Utils::Shader::TESS_EVAL:
25098 switch (stage)
25099 {
25100 case Utils::Shader::FRAGMENT:
25101 case Utils::Shader::TESS_CTRL:
25102 case Utils::Shader::TESS_EVAL:
25103 case Utils::Shader::VERTEX:
25104 source = BufferTestBase::getShaderSource(test_case_index, stage);
25105 break;
25106 default:
25107 break;
25108 }
25109 break;
25110
25111 case Utils::Shader::GEOMETRY:
25112 source = BufferTestBase::getShaderSource(test_case_index, stage);
25113 break;
25114
25115 default:
25116 TCU_FAIL("Invalid enum");
25117 break;
25118 }
25119
25120 /* */
25121 return source;
25122 }
25123
25124 /** Get name of test case
25125 *
25126 * @param test_case_index Index of test case
25127 *
25128 * @return Name of tested stage
25129 **/
25130 std::string XFBStrideTest::getTestCaseName(glw::GLuint test_case_index)
25131 {
25132 std::stringstream stream;
25133 const testCase& test_case = m_test_cases[test_case_index];
25134
25135 stream << "Type: " << test_case.m_type.GetGLSLTypeName()
25136 << ", stage: " << Utils::Shader::GetStageName(test_case.m_stage);
25137
25138 return stream.str();
25139 }
25140
25141 /** Returns number of test cases
25142 *
25143 * @return TEST_MAX
25144 **/
25145 glw::GLuint XFBStrideTest::getTestCaseNumber()
25146 {
25147 return static_cast<GLuint>(m_test_cases.size());
25148 }
25149
25150 /** Prepare all test cases
25151 *
25152 **/
25153 void XFBStrideTest::testInit()
25154 {
25155 const GLuint n_types = getTypesNumber();
25156
25157 for (GLuint i = 0; i < n_types; ++i)
25158 {
25159 const Utils::Type& type = getType(i);
25160
25161 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25162 {
25163 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::FRAGMENT == stage) ||
25164 (Utils::Shader::TESS_CTRL == stage))
25165 {
25166 continue;
25167 }
25168
25169 testCase test_case = { (Utils::Shader::STAGES)stage, type };
25170
25171 m_test_cases.push_back(test_case);
25172 }
25173 }
25174 }
25175
25176 /** Constructor
25177 *
25178 * @param context Test framework context
25179 **/
25180 XFBBlockMemberBufferTest::XFBBlockMemberBufferTest(deqp::Context& context)
25181 : NegativeTestBase(
25182 context, "xfb_block_member_buffer",
25183 "Test verifies that compiler reports error when block member has different xfb_buffer qualifier than buffer")
25184 {
25185 }
25186
25187 /** Source for given test case and stage
25188 *
25189 * @param test_case_index Index of test case
25190 * @param stage Shader stage
25191 *
25192 * @return Shader source
25193 **/
25194 std::string XFBBlockMemberBufferTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25195 {
25196 static const GLchar* var_definition = "layout (xfb_offset = 0) out Goku {\n"
25197 " vec4 gohan;\n"
25198 #if DEBUG_NEG_REMOVE_ERROR
25199 " /* layout (xfb_buffer = 1) */ vec4 goten;\n"
25200 #else
25201 " layout (xfb_buffer = 1) vec4 goten;\n"
25202 #endif /* DEBUG_NEG_REMOVE_ERROR */
25203 "} goku;\n";
25204 static const GLchar* var_use = " goku.gohan = result / 2;\n"
25205 " goku.goten = result / 4;\n";
25206 static const GLchar* fs = "#version 430 core\n"
25207 "#extension GL_ARB_enhanced_layouts : require\n"
25208 "\n"
25209 "in vec4 any_fs;\n"
25210 "out vec4 fs_out;\n"
25211 "\n"
25212 "void main()\n"
25213 "{\n"
25214 " fs_out = any_fs;\n"
25215 "}\n"
25216 "\n";
25217 static const GLchar* gs_tested = "#version 430 core\n"
25218 "#extension GL_ARB_enhanced_layouts : require\n"
25219 "\n"
25220 "layout(points) in;\n"
25221 "layout(triangle_strip, max_vertices = 4) out;\n"
25222 "\n"
25223 "VAR_DEFINITION"
25224 "\n"
25225 "in vec4 vs_any[];\n"
25226 "out vec4 any_fs;\n"
25227 "\n"
25228 "void main()\n"
25229 "{\n"
25230 " vec4 result = vs_any[0];\n"
25231 "\n"
25232 "VARIABLE_USE"
25233 "\n"
25234 " any_fs = result;\n"
25235 " gl_Position = vec4(-1, -1, 0, 1);\n"
25236 " EmitVertex();\n"
25237 " any_fs = result;\n"
25238 " gl_Position = vec4(-1, 1, 0, 1);\n"
25239 " EmitVertex();\n"
25240 " any_fs = result;\n"
25241 " gl_Position = vec4(1, -1, 0, 1);\n"
25242 " EmitVertex();\n"
25243 " any_fs = result;\n"
25244 " gl_Position = vec4(1, 1, 0, 1);\n"
25245 " EmitVertex();\n"
25246 "}\n"
25247 "\n";
25248 static const GLchar* tcs = "#version 430 core\n"
25249 "#extension GL_ARB_enhanced_layouts : require\n"
25250 "\n"
25251 "layout(vertices = 1) out;\n"
25252 "\n"
25253 "in vec4 vs_any[];\n"
25254 "out vec4 tcs_tes[];\n"
25255 "\n"
25256 "void main()\n"
25257 "{\n"
25258 "\n"
25259 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25260 "\n"
25261 " gl_TessLevelOuter[0] = 1.0;\n"
25262 " gl_TessLevelOuter[1] = 1.0;\n"
25263 " gl_TessLevelOuter[2] = 1.0;\n"
25264 " gl_TessLevelOuter[3] = 1.0;\n"
25265 " gl_TessLevelInner[0] = 1.0;\n"
25266 " gl_TessLevelInner[1] = 1.0;\n"
25267 "}\n"
25268 "\n";
25269 static const GLchar* tes_tested = "#version 430 core\n"
25270 "#extension GL_ARB_enhanced_layouts : require\n"
25271 "\n"
25272 "layout(isolines, point_mode) in;\n"
25273 "\n"
25274 "VAR_DEFINITION"
25275 "\n"
25276 "in vec4 tcs_tes[];\n"
25277 "out vec4 any_fs;\n"
25278 "\n"
25279 "void main()\n"
25280 "{\n"
25281 " vec4 result = tcs_tes[0];\n"
25282 "\n"
25283 "VARIABLE_USE"
25284 "\n"
25285 " any_fs += result;\n"
25286 "}\n"
25287 "\n";
25288 static const GLchar* vs = "#version 430 core\n"
25289 "#extension GL_ARB_enhanced_layouts : require\n"
25290 "\n"
25291 "in vec4 in_vs;\n"
25292 "out vec4 vs_any;\n"
25293 "\n"
25294 "void main()\n"
25295 "{\n"
25296 " vs_any = in_vs;\n"
25297 "}\n"
25298 "\n";
25299 static const GLchar* vs_tested = "#version 430 core\n"
25300 "#extension GL_ARB_enhanced_layouts : require\n"
25301 "\n"
25302 "VAR_DEFINITION"
25303 "\n"
25304 "in vec4 in_vs;\n"
25305 "out vec4 any_fs;\n"
25306 "\n"
25307 "void main()\n"
25308 "{\n"
25309 " vec4 result = in_vs;\n"
25310 "\n"
25311 "VARIABLE_USE"
25312 "\n"
25313 " any_fs = result;\n"
25314 "}\n"
25315 "\n";
25316
25317 std::string source;
25318 testCase& test_case = m_test_cases[test_case_index];
25319
25320 if (test_case.m_stage == stage)
25321 {
25322 size_t position = 0;
25323
25324 switch (stage)
25325 {
25326 case Utils::Shader::GEOMETRY:
25327 source = gs_tested;
25328 break;
25329 case Utils::Shader::TESS_EVAL:
25330 source = tes_tested;
25331 break;
25332 case Utils::Shader::VERTEX:
25333 source = vs_tested;
25334 break;
25335 default:
25336 TCU_FAIL("Invalid enum");
25337 }
25338
25339 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25340 position = 0;
25341 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25342 }
25343 else
25344 {
25345 switch (test_case.m_stage)
25346 {
25347 case Utils::Shader::GEOMETRY:
25348 switch (stage)
25349 {
25350 case Utils::Shader::FRAGMENT:
25351 source = fs;
25352 break;
25353 case Utils::Shader::VERTEX:
25354 source = vs;
25355 break;
25356 default:
25357 source = "";
25358 }
25359 break;
25360 case Utils::Shader::TESS_EVAL:
25361 switch (stage)
25362 {
25363 case Utils::Shader::FRAGMENT:
25364 source = fs;
25365 break;
25366 case Utils::Shader::TESS_CTRL:
25367 source = tcs;
25368 break;
25369 case Utils::Shader::VERTEX:
25370 source = vs;
25371 break;
25372 default:
25373 source = "";
25374 }
25375 break;
25376 case Utils::Shader::VERTEX:
25377 switch (stage)
25378 {
25379 case Utils::Shader::FRAGMENT:
25380 source = fs;
25381 break;
25382 default:
25383 source = "";
25384 }
25385 break;
25386 default:
25387 TCU_FAIL("Invalid enum");
25388 break;
25389 }
25390 }
25391
25392 return source;
25393 }
25394
25395 /** Get description of test case
25396 *
25397 * @param test_case_index Index of test case
25398 *
25399 * @return Test case description
25400 **/
25401 std::string XFBBlockMemberBufferTest::getTestCaseName(GLuint test_case_index)
25402 {
25403 std::stringstream stream;
25404 testCase& test_case = m_test_cases[test_case_index];
25405
25406 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
25407
25408 return stream.str();
25409 }
25410
25411 /** Get number of test cases
25412 *
25413 * @return Number of test cases
25414 **/
25415 GLuint XFBBlockMemberBufferTest::getTestCaseNumber()
25416 {
25417 return static_cast<GLuint>(m_test_cases.size());
25418 }
25419
25420 /** Selects if "compute" stage is relevant for test
25421 *
25422 * @param ignored
25423 *
25424 * @return false
25425 **/
25426 bool XFBBlockMemberBufferTest::isComputeRelevant(GLuint /* test_case_index */)
25427 {
25428 return false;
25429 }
25430
25431 /** Prepare all test cases
25432 *
25433 **/
25434 void XFBBlockMemberBufferTest::testInit()
25435 {
25436 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25437 {
25438 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25439 (Utils::Shader::FRAGMENT == stage))
25440 {
25441 continue;
25442 }
25443
25444 testCase test_case = { (Utils::Shader::STAGES)stage };
25445
25446 m_test_cases.push_back(test_case);
25447 }
25448 }
25449
25450 /** Constructor
25451 *
25452 * @param context Test framework context
25453 **/
25454 XFBOutputOverlappingTest::XFBOutputOverlappingTest(deqp::Context& context)
25455 : NegativeTestBase(context, "xfb_output_overlapping",
25456 "Test verifies that compiler reports error when two xfb qualified outputs overlap")
25457 {
25458 }
25459
25460 /** Source for given test case and stage
25461 *
25462 * @param test_case_index Index of test case
25463 * @param stage Shader stage
25464 *
25465 * @return Shader source
25466 **/
25467 std::string XFBOutputOverlappingTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25468 {
25469 static const GLchar* var_definition = "layout (xfb_offset = 0) out TYPE gohan;\n"
25470 #if DEBUG_NEG_REMOVE_ERROR
25471 "/* layout (xfb_offset = OFFSET) */ out TYPE goten;\n";
25472 #else
25473 "layout (xfb_offset = OFFSET) out TYPE goten;\n";
25474 #endif /* DEBUG_NEG_REMOVE_ERROR */
25475 static const GLchar* var_use = " gohan = TYPE(0);\n"
25476 " goten = TYPE(1);\n"
25477 " if (vec4(0) == result)\n"
25478 " {\n"
25479 " gohan = TYPE(1);\n"
25480 " goten = TYPE(0);\n"
25481 " }\n";
25482 static const GLchar* fs = "#version 430 core\n"
25483 "#extension GL_ARB_enhanced_layouts : require\n"
25484 "\n"
25485 "in vec4 any_fs;\n"
25486 "out vec4 fs_out;\n"
25487 "\n"
25488 "void main()\n"
25489 "{\n"
25490 " fs_out = any_fs;\n"
25491 "}\n"
25492 "\n";
25493 static const GLchar* gs_tested = "#version 430 core\n"
25494 "#extension GL_ARB_enhanced_layouts : require\n"
25495 "\n"
25496 "layout(points) in;\n"
25497 "layout(triangle_strip, max_vertices = 4) out;\n"
25498 "\n"
25499 "VAR_DEFINITION"
25500 "\n"
25501 "in vec4 vs_any[];\n"
25502 "out vec4 any_fs;\n"
25503 "\n"
25504 "void main()\n"
25505 "{\n"
25506 " vec4 result = vs_any[0];\n"
25507 "\n"
25508 "VARIABLE_USE"
25509 "\n"
25510 " any_fs = result;\n"
25511 " gl_Position = vec4(-1, -1, 0, 1);\n"
25512 " EmitVertex();\n"
25513 " any_fs = result;\n"
25514 " gl_Position = vec4(-1, 1, 0, 1);\n"
25515 " EmitVertex();\n"
25516 " any_fs = result;\n"
25517 " gl_Position = vec4(1, -1, 0, 1);\n"
25518 " EmitVertex();\n"
25519 " any_fs = result;\n"
25520 " gl_Position = vec4(1, 1, 0, 1);\n"
25521 " EmitVertex();\n"
25522 "}\n"
25523 "\n";
25524 static const GLchar* tcs = "#version 430 core\n"
25525 "#extension GL_ARB_enhanced_layouts : require\n"
25526 "\n"
25527 "layout(vertices = 1) out;\n"
25528 "\n"
25529 "in vec4 vs_any[];\n"
25530 "out vec4 tcs_tes[];\n"
25531 "\n"
25532 "void main()\n"
25533 "{\n"
25534 "\n"
25535 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25536 "\n"
25537 " gl_TessLevelOuter[0] = 1.0;\n"
25538 " gl_TessLevelOuter[1] = 1.0;\n"
25539 " gl_TessLevelOuter[2] = 1.0;\n"
25540 " gl_TessLevelOuter[3] = 1.0;\n"
25541 " gl_TessLevelInner[0] = 1.0;\n"
25542 " gl_TessLevelInner[1] = 1.0;\n"
25543 "}\n"
25544 "\n";
25545 static const GLchar* tes_tested = "#version 430 core\n"
25546 "#extension GL_ARB_enhanced_layouts : require\n"
25547 "\n"
25548 "layout(isolines, point_mode) in;\n"
25549 "\n"
25550 "VAR_DEFINITION"
25551 "\n"
25552 "in vec4 tcs_tes[];\n"
25553 "out vec4 any_fs;\n"
25554 "\n"
25555 "void main()\n"
25556 "{\n"
25557 " vec4 result = tcs_tes[0];\n"
25558 "\n"
25559 "VARIABLE_USE"
25560 "\n"
25561 " any_fs += result;\n"
25562 "}\n"
25563 "\n";
25564 static const GLchar* vs = "#version 430 core\n"
25565 "#extension GL_ARB_enhanced_layouts : require\n"
25566 "\n"
25567 "in vec4 in_vs;\n"
25568 "out vec4 vs_any;\n"
25569 "\n"
25570 "void main()\n"
25571 "{\n"
25572 " vs_any = in_vs;\n"
25573 "}\n"
25574 "\n";
25575 static const GLchar* vs_tested = "#version 430 core\n"
25576 "#extension GL_ARB_enhanced_layouts : require\n"
25577 "\n"
25578 "VAR_DEFINITION"
25579 "\n"
25580 "in vec4 in_vs;\n"
25581 "out vec4 any_fs;\n"
25582 "\n"
25583 "void main()\n"
25584 "{\n"
25585 " vec4 result = in_vs;\n"
25586 "\n"
25587 "VARIABLE_USE"
25588 "\n"
25589 " any_fs = result;\n"
25590 "}\n"
25591 "\n";
25592
25593 std::string source;
25594 testCase& test_case = m_test_cases[test_case_index];
25595
25596 if (test_case.m_stage == stage)
25597 {
25598 GLchar offset[16];
25599 size_t position = 0;
25600 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25601
25602 sprintf(offset, "%d", test_case.m_offset);
25603
25604 switch (stage)
25605 {
25606 case Utils::Shader::GEOMETRY:
25607 source = gs_tested;
25608 break;
25609 case Utils::Shader::TESS_EVAL:
25610 source = tes_tested;
25611 break;
25612 case Utils::Shader::VERTEX:
25613 source = vs_tested;
25614 break;
25615 default:
25616 TCU_FAIL("Invalid enum");
25617 }
25618
25619 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25620 position = 0;
25621 Utils::replaceToken("OFFSET", position, offset, source);
25622 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25623
25624 Utils::replaceAllTokens("TYPE", type_name, source);
25625 }
25626 else
25627 {
25628 switch (test_case.m_stage)
25629 {
25630 case Utils::Shader::GEOMETRY:
25631 switch (stage)
25632 {
25633 case Utils::Shader::FRAGMENT:
25634 source = fs;
25635 break;
25636 case Utils::Shader::VERTEX:
25637 source = vs;
25638 break;
25639 default:
25640 source = "";
25641 }
25642 break;
25643 case Utils::Shader::TESS_EVAL:
25644 switch (stage)
25645 {
25646 case Utils::Shader::FRAGMENT:
25647 source = fs;
25648 break;
25649 case Utils::Shader::TESS_CTRL:
25650 source = tcs;
25651 break;
25652 case Utils::Shader::VERTEX:
25653 source = vs;
25654 break;
25655 default:
25656 source = "";
25657 }
25658 break;
25659 case Utils::Shader::VERTEX:
25660 switch (stage)
25661 {
25662 case Utils::Shader::FRAGMENT:
25663 source = fs;
25664 break;
25665 default:
25666 source = "";
25667 }
25668 break;
25669 default:
25670 TCU_FAIL("Invalid enum");
25671 break;
25672 }
25673 }
25674
25675 return source;
25676 }
25677
25678 /** Get description of test case
25679 *
25680 * @param test_case_index Index of test case
25681 *
25682 * @return Test case description
25683 **/
25684 std::string XFBOutputOverlappingTest::getTestCaseName(GLuint test_case_index)
25685 {
25686 std::stringstream stream;
25687 testCase& test_case = m_test_cases[test_case_index];
25688
25689 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25690 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
25691
25692 return stream.str();
25693 }
25694
25695 /** Get number of test cases
25696 *
25697 * @return Number of test cases
25698 **/
25699 GLuint XFBOutputOverlappingTest::getTestCaseNumber()
25700 {
25701 return static_cast<GLuint>(m_test_cases.size());
25702 }
25703
25704 /** Selects if "compute" stage is relevant for test
25705 *
25706 * @param ignored
25707 *
25708 * @return false
25709 **/
25710 bool XFBOutputOverlappingTest::isComputeRelevant(GLuint /* test_case_index */)
25711 {
25712 return false;
25713 }
25714
25715 /** Prepare all test cases
25716 *
25717 **/
25718 void XFBOutputOverlappingTest::testInit()
25719 {
25720 const GLuint n_types = getTypesNumber();
25721
25722 for (GLuint i = 0; i < n_types; ++i)
25723 {
25724 const Utils::Type& type = getType(i);
25725 const GLuint basic_type_size = Utils::Type::GetTypeSize(type.m_basic_type);
25726
25727 /* Skip scalars, not applicable as:
25728 *
25729 * The offset must be a multiple of the size of the first component of the first
25730 * qualified variable or block member, or a compile-time error results.
25731 */
25732 if ((1 == type.m_n_columns) && (1 == type.m_n_rows))
25733 {
25734 continue;
25735 }
25736
25737 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
25738 {
25739 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
25740 (Utils::Shader::FRAGMENT == stage))
25741 {
25742 continue;
25743 }
25744
25745 testCase test_case = { basic_type_size /* offset */, (Utils::Shader::STAGES)stage, type };
25746
25747 m_test_cases.push_back(test_case);
25748 }
25749 }
25750 }
25751
25752 /** Constructor
25753 *
25754 * @param context Test framework context
25755 **/
25756 XFBInvalidOffsetAlignmentTest::XFBInvalidOffsetAlignmentTest(deqp::Context& context)
25757 : NegativeTestBase(context, "xfb_invalid_offset_alignment",
25758 "Test verifies that compiler reports error when xfb_offset has invalid alignment")
25759 {
25760 }
25761
25762 /** Source for given test case and stage
25763 *
25764 * @param test_case_index Index of test case
25765 * @param stage Shader stage
25766 *
25767 * @return Shader source
25768 **/
25769 std::string XFBInvalidOffsetAlignmentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
25770 {
25771 #if DEBUG_NEG_REMOVE_ERROR
25772 static const GLchar* var_definition = "/* layout (xfb_offset = OFFSET) */ out TYPE gohan;\n";
25773 #else
25774 static const GLchar* var_definition = "layout (xfb_offset = OFFSET) out TYPE gohan;\n";
25775 #endif /* DEBUG_NEG_REMOVE_ERROR */
25776 static const GLchar* var_use = " gohan = TYPE(0);\n"
25777 " if (vec4(0) == result)\n"
25778 " {\n"
25779 " gohan = TYPE(1);\n"
25780 " }\n";
25781 static const GLchar* fs = "#version 430 core\n"
25782 "#extension GL_ARB_enhanced_layouts : require\n"
25783 "\n"
25784 "in vec4 any_fs;\n"
25785 "out vec4 fs_out;\n"
25786 "\n"
25787 "void main()\n"
25788 "{\n"
25789 " fs_out = any_fs;\n"
25790 "}\n"
25791 "\n";
25792 static const GLchar* gs_tested = "#version 430 core\n"
25793 "#extension GL_ARB_enhanced_layouts : require\n"
25794 "\n"
25795 "layout(points) in;\n"
25796 "layout(triangle_strip, max_vertices = 4) out;\n"
25797 "\n"
25798 "VAR_DEFINITION"
25799 "\n"
25800 "in vec4 vs_any[];\n"
25801 "out vec4 any_fs;\n"
25802 "\n"
25803 "void main()\n"
25804 "{\n"
25805 " vec4 result = vs_any[0];\n"
25806 "\n"
25807 "VARIABLE_USE"
25808 "\n"
25809 " any_fs = result;\n"
25810 " gl_Position = vec4(-1, -1, 0, 1);\n"
25811 " EmitVertex();\n"
25812 " any_fs = result;\n"
25813 " gl_Position = vec4(-1, 1, 0, 1);\n"
25814 " EmitVertex();\n"
25815 " any_fs = result;\n"
25816 " gl_Position = vec4(1, -1, 0, 1);\n"
25817 " EmitVertex();\n"
25818 " any_fs = result;\n"
25819 " gl_Position = vec4(1, 1, 0, 1);\n"
25820 " EmitVertex();\n"
25821 "}\n"
25822 "\n";
25823 static const GLchar* tcs = "#version 430 core\n"
25824 "#extension GL_ARB_enhanced_layouts : require\n"
25825 "\n"
25826 "layout(vertices = 1) out;\n"
25827 "\n"
25828 "in vec4 vs_any[];\n"
25829 "out vec4 tcs_tes[];\n"
25830 "\n"
25831 "void main()\n"
25832 "{\n"
25833 "\n"
25834 " tcs_tes[gl_InvocationID] = vs_any[gl_InvocationID];\n"
25835 "\n"
25836 " gl_TessLevelOuter[0] = 1.0;\n"
25837 " gl_TessLevelOuter[1] = 1.0;\n"
25838 " gl_TessLevelOuter[2] = 1.0;\n"
25839 " gl_TessLevelOuter[3] = 1.0;\n"
25840 " gl_TessLevelInner[0] = 1.0;\n"
25841 " gl_TessLevelInner[1] = 1.0;\n"
25842 "}\n"
25843 "\n";
25844 static const GLchar* tes_tested = "#version 430 core\n"
25845 "#extension GL_ARB_enhanced_layouts : require\n"
25846 "\n"
25847 "layout(isolines, point_mode) in;\n"
25848 "\n"
25849 "VAR_DEFINITION"
25850 "\n"
25851 "in vec4 tcs_tes[];\n"
25852 "out vec4 any_fs;\n"
25853 "\n"
25854 "void main()\n"
25855 "{\n"
25856 " vec4 result = tcs_tes[0];\n"
25857 "\n"
25858 "VARIABLE_USE"
25859 "\n"
25860 " any_fs += result;\n"
25861 "}\n"
25862 "\n";
25863 static const GLchar* vs = "#version 430 core\n"
25864 "#extension GL_ARB_enhanced_layouts : require\n"
25865 "\n"
25866 "in vec4 in_vs;\n"
25867 "out vec4 vs_any;\n"
25868 "\n"
25869 "void main()\n"
25870 "{\n"
25871 " vs_any = in_vs;\n"
25872 "}\n"
25873 "\n";
25874 static const GLchar* vs_tested = "#version 430 core\n"
25875 "#extension GL_ARB_enhanced_layouts : require\n"
25876 "\n"
25877 "VAR_DEFINITION"
25878 "\n"
25879 "in vec4 in_vs;\n"
25880 "out vec4 any_fs;\n"
25881 "\n"
25882 "void main()\n"
25883 "{\n"
25884 " vec4 result = in_vs;\n"
25885 "\n"
25886 "VARIABLE_USE"
25887 "\n"
25888 " any_fs = result;\n"
25889 "}\n"
25890 "\n";
25891
25892 std::string source;
25893 testCase& test_case = m_test_cases[test_case_index];
25894
25895 if (test_case.m_stage == stage)
25896 {
25897 GLchar offset[16];
25898 size_t position = 0;
25899 const GLchar* type_name = test_case.m_type.GetGLSLTypeName();
25900
25901 sprintf(offset, "%d", test_case.m_offset);
25902
25903 switch (stage)
25904 {
25905 case Utils::Shader::GEOMETRY:
25906 source = gs_tested;
25907 break;
25908 case Utils::Shader::TESS_EVAL:
25909 source = tes_tested;
25910 break;
25911 case Utils::Shader::VERTEX:
25912 source = vs_tested;
25913 break;
25914 default:
25915 TCU_FAIL("Invalid enum");
25916 }
25917
25918 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
25919 position = 0;
25920 Utils::replaceToken("OFFSET", position, offset, source);
25921 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
25922
25923 Utils::replaceAllTokens("TYPE", type_name, source);
25924 }
25925 else
25926 {
25927 switch (test_case.m_stage)
25928 {
25929 case Utils::Shader::GEOMETRY:
25930 switch (stage)
25931 {
25932 case Utils::Shader::FRAGMENT:
25933 source = fs;
25934 break;
25935 case Utils::Shader::VERTEX:
25936 source = vs;
25937 break;
25938 default:
25939 source = "";
25940 }
25941 break;
25942 case Utils::Shader::TESS_EVAL:
25943 switch (stage)
25944 {
25945 case Utils::Shader::FRAGMENT:
25946 source = fs;
25947 break;
25948 case Utils::Shader::TESS_CTRL:
25949 source = tcs;
25950 break;
25951 case Utils::Shader::VERTEX:
25952 source = vs;
25953 break;
25954 default:
25955 source = "";
25956 }
25957 break;
25958 case Utils::Shader::VERTEX:
25959 switch (stage)
25960 {
25961 case Utils::Shader::FRAGMENT:
25962 source = fs;
25963 break;
25964 default:
25965 source = "";
25966 }
25967 break;
25968 default:
25969 TCU_FAIL("Invalid enum");
25970 break;
25971 }
25972 }
25973
25974 return source;
25975 }
25976
25977 /** Get description of test case
25978 *
25979 * @param test_case_index Index of test case
25980 *
25981 * @return Test case description
25982 **/
25983 std::string XFBInvalidOffsetAlignmentTest::getTestCaseName(GLuint test_case_index)
25984 {
25985 std::stringstream stream;
25986 testCase& test_case = m_test_cases[test_case_index];
25987
25988 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage)
25989 << ", type: " << test_case.m_type.GetGLSLTypeName() << ", offset: " << test_case.m_offset;
25990
25991 return stream.str();
25992 }
25993
25994 /** Get number of test cases
25995 *
25996 * @return Number of test cases
25997 **/
25998 GLuint XFBInvalidOffsetAlignmentTest::getTestCaseNumber()
25999 {
26000 return static_cast<GLuint>(m_test_cases.size());
26001 }
26002
26003 /** Selects if "compute" stage is relevant for test
26004 *
26005 * @param ignored
26006 *
26007 * @return false
26008 **/
26009 bool XFBInvalidOffsetAlignmentTest::isComputeRelevant(GLuint /* test_case_index */)
26010 {
26011 return false;
26012 }
26013
26014 /** Prepare all test cases
26015 *
26016 **/
26017 void XFBInvalidOffsetAlignmentTest::testInit()
26018 {
26019 const GLuint n_types = getTypesNumber();
26020
26021 for (GLuint i = 0; i < n_types; ++i)
26022 {
26023 const Utils::Type& type = getType(i);
26024 const GLuint basic_type_size = Utils::Type::GetTypeSize(type.m_basic_type);
26025
26026 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
26027 {
26028 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
26029 (Utils::Shader::FRAGMENT == stage))
26030 {
26031 continue;
26032 }
26033
26034 for (GLuint offset = basic_type_size + 1; offset < 2 * basic_type_size; ++offset)
26035 {
26036 testCase test_case = { offset, (Utils::Shader::STAGES)stage, type };
26037
26038 m_test_cases.push_back(test_case);
26039 }
26040 }
26041 }
26042 }
26043
26044 /** Constructor
26045 *
26046 * @param context Test context
26047 **/
26048 XFBCaptureInactiveOutputVariableTest::XFBCaptureInactiveOutputVariableTest(deqp::Context& context)
26049 : BufferTestBase(context, "xfb_capture_inactive_output_variable",
26050 "Test verifies that inactive variables are captured")
26051 {
26052 /* Nothing to be done here */
26053 }
26054
26055 /** Execute drawArrays for single vertex
26056 *
26057 * @param test_case_index
26058 *
26059 * @return true
26060 **/
26061 bool XFBCaptureInactiveOutputVariableTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26062 {
26063 const Functions& gl = m_context.getRenderContext().getFunctions();
26064 GLenum primitive_type = GL_PATCHES;
26065
26066 if (TEST_VS == test_case_index)
26067 {
26068 primitive_type = GL_POINTS;
26069 }
26070
26071 gl.disable(GL_RASTERIZER_DISCARD);
26072 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26073
26074 gl.beginTransformFeedback(GL_POINTS);
26075 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26076
26077 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26078 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26079
26080 gl.endTransformFeedback();
26081 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26082
26083 return true;
26084 }
26085
26086 /** Get descriptors of buffers necessary for test
26087 *
26088 * @param ignored
26089 * @param out_descriptors Descriptors of buffers used by test
26090 **/
26091 void XFBCaptureInactiveOutputVariableTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26092 bufferDescriptor::Vector& out_descriptors)
26093 {
26094 const Utils::Type& type = Utils::Type::vec4;
26095
26096 /* Test needs single uniform and xfb */
26097 out_descriptors.resize(2);
26098
26099 /* Get references */
26100 bufferDescriptor& uniform = out_descriptors[0];
26101 bufferDescriptor& xfb = out_descriptors[1];
26102
26103 /* Index */
26104 uniform.m_index = 0;
26105 xfb.m_index = 0;
26106
26107 /* Target */
26108 uniform.m_target = Utils::Buffer::Uniform;
26109 xfb.m_target = Utils::Buffer::Transform_feedback;
26110
26111 /* Data */
26112 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26113 const std::vector<GLubyte>& goten_data = type.GenerateData();
26114
26115 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26116
26117 /* Uniform data */
26118 uniform.m_initial_data.resize(2 * type_size);
26119 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
26120 memcpy(&uniform.m_initial_data[0] + type_size, &goten_data[0], type_size);
26121
26122 /* XFB data */
26123 xfb.m_initial_data.resize(3 * type_size);
26124 xfb.m_expected_data.resize(3 * type_size);
26125
26126 for (GLuint i = 0; i < 3 * type_size; ++i)
26127 {
26128 xfb.m_initial_data[i] = (glw::GLubyte)i;
26129 xfb.m_expected_data[i] = (glw::GLubyte)i;
26130 }
26131
26132 memcpy(&xfb.m_expected_data[0] + 2 * type_size, &gohan_data[0], type_size);
26133 memcpy(&xfb.m_expected_data[0] + 0 * type_size, &goten_data[0], type_size);
26134 }
26135
26136 /** Get body of main function for given shader stage
26137 *
26138 * @param test_case_index Index of test case
26139 * @param stage Shader stage
26140 * @param out_assignments Set to empty
26141 * @param out_calculations Set to empty
26142 **/
26143 void XFBCaptureInactiveOutputVariableTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26144 std::string& out_assignments, std::string& out_calculations)
26145 {
26146 out_calculations = "";
26147
26148 static const GLchar* vs_tes_gs = " goten = uni_goten;\n"
26149 " gohan = uni_gohan;\n";
26150 static const GLchar* fs = " fs_out = goku + gohan + goten;\n";
26151
26152 const GLchar* assignments = "";
26153
26154 switch (stage)
26155 {
26156 case Utils::Shader::FRAGMENT:
26157 assignments = fs;
26158 break;
26159
26160 case Utils::Shader::GEOMETRY:
26161 if (TEST_GS == test_case_index)
26162 {
26163 assignments = vs_tes_gs;
26164 }
26165 break;
26166
26167 case Utils::Shader::TESS_CTRL:
26168 break;
26169
26170 case Utils::Shader::TESS_EVAL:
26171 if (TEST_TES == test_case_index)
26172 {
26173 assignments = vs_tes_gs;
26174 }
26175 break;
26176
26177 case Utils::Shader::VERTEX:
26178 if (TEST_VS == test_case_index)
26179 {
26180 assignments = vs_tes_gs;
26181 }
26182 break;
26183
26184 default:
26185 TCU_FAIL("Invalid enum");
26186 }
26187
26188 out_assignments = assignments;
26189 }
26190
26191 /** Get interface of shader
26192 *
26193 * @param test_case_index Index of test case
26194 * @param stage Shader stage
26195 * @param out_interface Set to ""
26196 **/
26197 void XFBCaptureInactiveOutputVariableTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26198 std::string& out_interface)
26199 {
26200 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26201 "\n"
26202 "layout (xfb_offset = 1 * sizeof_type) out vec4 goku;\n"
26203 "layout (xfb_offset = 2 * sizeof_type) out vec4 gohan;\n"
26204 "layout (xfb_offset = 0 * sizeof_type) out vec4 goten;\n"
26205 "\n"
26206 "layout(binding = 0) uniform block {\n"
26207 " vec4 uni_gohan;\n"
26208 " vec4 uni_goten;\n"
26209 "};\n";
26210 static const GLchar* fs = "in vec4 goku;\n"
26211 "in vec4 gohan;\n"
26212 "in vec4 goten;\n"
26213 "out vec4 fs_out;\n";
26214
26215 const GLchar* interface = "";
26216
26217 switch (stage)
26218 {
26219 case Utils::Shader::FRAGMENT:
26220 interface = fs;
26221 break;
26222
26223 case Utils::Shader::GEOMETRY:
26224 if (TEST_GS == test_case_index)
26225 {
26226 interface = vs_tes_gs;
26227 }
26228 break;
26229
26230 case Utils::Shader::TESS_CTRL:
26231 break;
26232
26233 case Utils::Shader::TESS_EVAL:
26234 if (TEST_TES == test_case_index)
26235 {
26236 interface = vs_tes_gs;
26237 }
26238 break;
26239
26240 case Utils::Shader::VERTEX:
26241 if (TEST_VS == test_case_index)
26242 {
26243 interface = vs_tes_gs;
26244 }
26245 break;
26246
26247 default:
26248 TCU_FAIL("Invalid enum");
26249 }
26250
26251 out_interface = interface;
26252 }
26253
26254 /** Get source code of shader
26255 *
26256 * @param test_case_index Index of test case
26257 * @param stage Shader stage
26258 *
26259 * @return Source
26260 **/
26261 std::string XFBCaptureInactiveOutputVariableTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26262 {
26263 std::string source;
26264
26265 switch (test_case_index)
26266 {
26267 case TEST_VS:
26268 switch (stage)
26269 {
26270 case Utils::Shader::FRAGMENT:
26271 case Utils::Shader::VERTEX:
26272 source = BufferTestBase::getShaderSource(test_case_index, stage);
26273 break;
26274 default:
26275 break;
26276 }
26277 break;
26278
26279 case TEST_TES:
26280 switch (stage)
26281 {
26282 case Utils::Shader::FRAGMENT:
26283 case Utils::Shader::TESS_CTRL:
26284 case Utils::Shader::TESS_EVAL:
26285 case Utils::Shader::VERTEX:
26286 source = BufferTestBase::getShaderSource(test_case_index, stage);
26287 break;
26288 default:
26289 break;
26290 }
26291 break;
26292
26293 case TEST_GS:
26294 source = BufferTestBase::getShaderSource(test_case_index, stage);
26295 break;
26296
26297 default:
26298 TCU_FAIL("Invalid enum");
26299 break;
26300 }
26301
26302 /* */
26303 return source;
26304 }
26305
26306 /** Get name of test case
26307 *
26308 * @param test_case_index Index of test case
26309 *
26310 * @return Name of tested stage
26311 **/
26312 std::string XFBCaptureInactiveOutputVariableTest::getTestCaseName(glw::GLuint test_case_index)
26313 {
26314 const GLchar* name = 0;
26315
26316 switch (test_case_index)
26317 {
26318 case TEST_VS:
26319 name = "vertex";
26320 break;
26321 case TEST_TES:
26322 name = "tessellation evaluation";
26323 break;
26324 case TEST_GS:
26325 name = "geometry";
26326 break;
26327 default:
26328 TCU_FAIL("Invalid enum");
26329 }
26330
26331 return name;
26332 }
26333
26334 /** Returns number of test cases
26335 *
26336 * @return TEST_MAX
26337 **/
26338 glw::GLuint XFBCaptureInactiveOutputVariableTest::getTestCaseNumber()
26339 {
26340 return TEST_MAX;
26341 }
26342
26343 /** Inspects program to check if all resources are as expected
26344 *
26345 * @param ignored
26346 * @param program Program instance
26347 * @param out_stream Error message
26348 *
26349 * @return true if everything is ok, false otherwise
26350 **/
26351 bool XFBCaptureInactiveOutputVariableTest::inspectProgram(GLuint /* test_case_index */, Utils::Program& program,
26352 std::stringstream& out_stream)
26353 {
26354 GLint stride = 0;
26355 const Utils::Type& type = Utils::Type::vec4;
26356 const GLuint type_size = type.GetSize();
26357
26358 program.GetResource(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, GL_TRANSFORM_FEEDBACK_BUFFER_STRIDE,
26359 1 /* buf_size */, &stride);
26360
26361 if ((GLint)(3 * type_size) != stride)
26362 {
26363 out_stream << "Stride is: " << stride << " expected: " << (3 * type_size);
26364
26365 return false;
26366 }
26367
26368 return true;
26369 }
26370
26371 /** Verify contents of buffers
26372 *
26373 * @param buffers Collection of buffers to be verified
26374 *
26375 * @return true if everything is as expected, false otherwise
26376 **/
26377 bool XFBCaptureInactiveOutputVariableTest::verifyBuffers(bufferCollection& buffers)
26378 {
26379 bool result = true;
26380
26381 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26382 Utils::Buffer* buffer = pair.m_buffer;
26383 bufferDescriptor* descriptor = pair.m_descriptor;
26384
26385 /* Get pointer to contents of buffer */
26386 buffer->Bind();
26387 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26388
26389 /* Get pointer to expected data */
26390 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26391
26392 /* Compare */
26393 static const GLuint vec4_size = 16;
26394
26395 int res_gohan = memcmp(buffer_data + 2 * vec4_size, expected_data + 2 * vec4_size, vec4_size);
26396 int res_goten = memcmp(buffer_data + 0 * vec4_size, expected_data + 0 * vec4_size, vec4_size);
26397
26398 if ((0 != res_gohan) || (0 != res_goten))
26399 {
26400 m_context.getTestContext().getLog()
26401 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26402 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26403
26404 result = false;
26405 }
26406
26407 /* Release buffer mapping */
26408 buffer->UnMap();
26409
26410 return result;
26411 }
26412
26413 /** Constructor
26414 *
26415 * @param context Test context
26416 **/
26417 XFBCaptureInactiveOutputComponentTest::XFBCaptureInactiveOutputComponentTest(deqp::Context& context)
26418 : BufferTestBase(context, "xfb_capture_inactive_output_component",
26419 "Test verifies that inactive components are not modified")
26420 {
26421 /* Nothing to be done here */
26422 }
26423
26424 /** Execute drawArrays for single vertex
26425 *
26426 * @param test_case_index
26427 *
26428 * @return true
26429 **/
26430 bool XFBCaptureInactiveOutputComponentTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26431 {
26432 const Functions& gl = m_context.getRenderContext().getFunctions();
26433 GLenum primitive_type = GL_PATCHES;
26434
26435 if (TEST_VS == test_case_index)
26436 {
26437 primitive_type = GL_POINTS;
26438 }
26439
26440 gl.disable(GL_RASTERIZER_DISCARD);
26441 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26442
26443 gl.beginTransformFeedback(GL_POINTS);
26444 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26445
26446 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26447 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26448
26449 gl.endTransformFeedback();
26450 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26451
26452 return true;
26453 }
26454
26455 /** Get descriptors of buffers necessary for test
26456 *
26457 * @param ignored
26458 * @param out_descriptors Descriptors of buffers used by test
26459 **/
26460 void XFBCaptureInactiveOutputComponentTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26461 bufferDescriptor::Vector& out_descriptors)
26462 {
26463 const Utils::Type& type = Utils::Type::vec4;
26464
26465 /* Test needs single uniform and xfb */
26466 out_descriptors.resize(2);
26467
26468 /* Get references */
26469 bufferDescriptor& uniform = out_descriptors[0];
26470 bufferDescriptor& xfb = out_descriptors[1];
26471
26472 /* Index */
26473 uniform.m_index = 0;
26474 xfb.m_index = 0;
26475
26476 /* Target */
26477 uniform.m_target = Utils::Buffer::Uniform;
26478 xfb.m_target = Utils::Buffer::Transform_feedback;
26479
26480 /* Data */
26481 const std::vector<GLubyte>& goku_data = type.GenerateData();
26482 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26483 const std::vector<GLubyte>& goten_data = type.GenerateData();
26484 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26485 const std::vector<GLubyte>& vegeta_data = type.GenerateData();
26486 const std::vector<GLubyte>& trunks_data = type.GenerateData();
26487 const std::vector<GLubyte>& bra_data = type.GenerateData();
26488 const std::vector<GLubyte>& bulma_data = type.GenerateData();
26489
26490 const GLuint comp_size = Utils::Type::GetTypeSize(type.m_basic_type);
26491 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26492
26493 /* Uniform data */
26494 uniform.m_initial_data.resize(8 * type_size);
26495 memcpy(&uniform.m_initial_data[0] + 0 * type_size, &goku_data[0], type_size);
26496 memcpy(&uniform.m_initial_data[0] + 1 * type_size, &gohan_data[0], type_size);
26497 memcpy(&uniform.m_initial_data[0] + 2 * type_size, &goten_data[0], type_size);
26498 memcpy(&uniform.m_initial_data[0] + 3 * type_size, &chichi_data[0], type_size);
26499 memcpy(&uniform.m_initial_data[0] + 4 * type_size, &vegeta_data[0], type_size);
26500 memcpy(&uniform.m_initial_data[0] + 5 * type_size, &trunks_data[0], type_size);
26501 memcpy(&uniform.m_initial_data[0] + 6 * type_size, &bra_data[0], type_size);
26502 memcpy(&uniform.m_initial_data[0] + 7 * type_size, &bulma_data[0], type_size);
26503
26504 /* XFB data */
26505 xfb.m_initial_data.resize(8 * type_size);
26506 xfb.m_expected_data.resize(8 * type_size);
26507
26508 for (GLuint i = 0; i < 8 * type_size; ++i)
26509 {
26510 xfb.m_initial_data[i] = (glw::GLubyte)i;
26511 xfb.m_expected_data[i] = (glw::GLubyte)i;
26512 }
26513
26514 /* goku - x, z - 32 */
26515 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 0 * comp_size, &goku_data[0] + 0 * comp_size, comp_size);
26516 memcpy(&xfb.m_expected_data[0] + 2 * type_size + 2 * comp_size, &goku_data[0] + 2 * comp_size, comp_size);
26517
26518 /* gohan - y, w - 0 */
26519 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 1 * comp_size, &gohan_data[0] + 1 * comp_size, comp_size);
26520 memcpy(&xfb.m_expected_data[0] + 0 * type_size + 3 * comp_size, &gohan_data[0] + 3 * comp_size, comp_size);
26521
26522 /* goten - x, y - 16 */
26523 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 0 * comp_size, &goten_data[0] + 0 * comp_size, comp_size);
26524 memcpy(&xfb.m_expected_data[0] + 1 * type_size + 1 * comp_size, &goten_data[0] + 1 * comp_size, comp_size);
26525
26526 /* chichi - z, w - 48 */
26527 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 2 * comp_size, &chichi_data[0] + 2 * comp_size, comp_size);
26528 memcpy(&xfb.m_expected_data[0] + 3 * type_size + 3 * comp_size, &chichi_data[0] + 3 * comp_size, comp_size);
26529
26530 /* vegeta - x - 112 */
26531 memcpy(&xfb.m_expected_data[0] + 7 * type_size + 0 * comp_size, &vegeta_data[0] + 0 * comp_size, comp_size);
26532
26533 /* trunks - y - 96 */
26534 memcpy(&xfb.m_expected_data[0] + 6 * type_size + 1 * comp_size, &trunks_data[0] + 1 * comp_size, comp_size);
26535
26536 /* bra - z - 80 */
26537 memcpy(&xfb.m_expected_data[0] + 5 * type_size + 2 * comp_size, &bra_data[0] + 2 * comp_size, comp_size);
26538
26539 /* bulma - w - 64 */
26540 memcpy(&xfb.m_expected_data[0] + 4 * type_size + 3 * comp_size, &bulma_data[0] + 3 * comp_size, comp_size);
26541 }
26542
26543 /** Get body of main function for given shader stage
26544 *
26545 * @param test_case_index Index of test case
26546 * @param stage Shader stage
26547 * @param out_assignments Set to empty
26548 * @param out_calculations Set to empty
26549 **/
26550 void XFBCaptureInactiveOutputComponentTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26551 std::string& out_assignments, std::string& out_calculations)
26552 {
26553 out_calculations = "";
26554
26555 static const GLchar* vs_tes_gs = " goku.x = uni_goku.x ;\n"
26556 " goku.z = uni_goku.z ;\n"
26557 " gohan.y = uni_gohan.y ;\n"
26558 " gohan.w = uni_gohan.w ;\n"
26559 " goten.x = uni_goten.x ;\n"
26560 " goten.y = uni_goten.y ;\n"
26561 " chichi.z = uni_chichi.z ;\n"
26562 " chichi.w = uni_chichi.w ;\n"
26563 " vegeta.x = uni_vegeta.x ;\n"
26564 " trunks.y = uni_trunks.y ;\n"
26565 " bra.z = uni_bra.z ;\n"
26566 " bulma.w = uni_bulma.w ;\n";
26567 static const GLchar* fs = " fs_out = goku + gohan + goten + chichi + vegeta + trunks + bra + bulma;\n";
26568
26569 const GLchar* assignments = "";
26570
26571 switch (stage)
26572 {
26573 case Utils::Shader::FRAGMENT:
26574 assignments = fs;
26575 break;
26576
26577 case Utils::Shader::GEOMETRY:
26578 if (TEST_GS == test_case_index)
26579 {
26580 assignments = vs_tes_gs;
26581 }
26582 break;
26583
26584 case Utils::Shader::TESS_CTRL:
26585 break;
26586
26587 case Utils::Shader::TESS_EVAL:
26588 if (TEST_TES == test_case_index)
26589 {
26590 assignments = vs_tes_gs;
26591 }
26592 break;
26593
26594 case Utils::Shader::VERTEX:
26595 if (TEST_VS == test_case_index)
26596 {
26597 assignments = vs_tes_gs;
26598 }
26599 break;
26600
26601 default:
26602 TCU_FAIL("Invalid enum");
26603 }
26604
26605 out_assignments = assignments;
26606 }
26607
26608 /** Get interface of shader
26609 *
26610 * @param test_case_index Index of test case
26611 * @param stage Shader stage
26612 * @param out_interface Set to ""
26613 **/
26614 void XFBCaptureInactiveOutputComponentTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
26615 std::string& out_interface)
26616 {
26617 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
26618 "\n"
26619 "layout (xfb_offset = 2 * sizeof_type) out vec4 goku;\n"
26620 "layout (xfb_offset = 0 * sizeof_type) out vec4 gohan;\n"
26621 "layout (xfb_offset = 1 * sizeof_type) out vec4 goten;\n"
26622 "layout (xfb_offset = 3 * sizeof_type) out vec4 chichi;\n"
26623 "layout (xfb_offset = 7 * sizeof_type) out vec4 vegeta;\n"
26624 "layout (xfb_offset = 6 * sizeof_type) out vec4 trunks;\n"
26625 "layout (xfb_offset = 5 * sizeof_type) out vec4 bra;\n"
26626 "layout (xfb_offset = 4 * sizeof_type) out vec4 bulma;\n"
26627 "\n"
26628 "layout(binding = 0) uniform block {\n"
26629 " vec4 uni_goku;\n"
26630 " vec4 uni_gohan;\n"
26631 " vec4 uni_goten;\n"
26632 " vec4 uni_chichi;\n"
26633 " vec4 uni_vegeta;\n"
26634 " vec4 uni_trunks;\n"
26635 " vec4 uni_bra;\n"
26636 " vec4 uni_bulma;\n"
26637 "};\n";
26638 static const GLchar* fs = "in vec4 vegeta;\n"
26639 "in vec4 trunks;\n"
26640 "in vec4 bra;\n"
26641 "in vec4 bulma;\n"
26642 "in vec4 goku;\n"
26643 "in vec4 gohan;\n"
26644 "in vec4 goten;\n"
26645 "in vec4 chichi;\n"
26646 "\n"
26647 "out vec4 fs_out;\n";
26648
26649 const GLchar* interface = "";
26650
26651 switch (stage)
26652 {
26653 case Utils::Shader::FRAGMENT:
26654 interface = fs;
26655 break;
26656
26657 case Utils::Shader::GEOMETRY:
26658 if (TEST_GS == test_case_index)
26659 {
26660 interface = vs_tes_gs;
26661 }
26662 break;
26663
26664 case Utils::Shader::TESS_CTRL:
26665 break;
26666
26667 case Utils::Shader::TESS_EVAL:
26668 if (TEST_TES == test_case_index)
26669 {
26670 interface = vs_tes_gs;
26671 }
26672 break;
26673
26674 case Utils::Shader::VERTEX:
26675 if (TEST_VS == test_case_index)
26676 {
26677 interface = vs_tes_gs;
26678 }
26679 break;
26680
26681 default:
26682 TCU_FAIL("Invalid enum");
26683 }
26684
26685 out_interface = interface;
26686 }
26687
26688 /** Get source code of shader
26689 *
26690 * @param test_case_index Index of test case
26691 * @param stage Shader stage
26692 *
26693 * @return Source
26694 **/
26695 std::string XFBCaptureInactiveOutputComponentTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
26696 {
26697 std::string source;
26698
26699 switch (test_case_index)
26700 {
26701 case TEST_VS:
26702 switch (stage)
26703 {
26704 case Utils::Shader::FRAGMENT:
26705 case Utils::Shader::VERTEX:
26706 source = BufferTestBase::getShaderSource(test_case_index, stage);
26707 break;
26708 default:
26709 break;
26710 }
26711 break;
26712
26713 case TEST_TES:
26714 switch (stage)
26715 {
26716 case Utils::Shader::FRAGMENT:
26717 case Utils::Shader::TESS_CTRL:
26718 case Utils::Shader::TESS_EVAL:
26719 case Utils::Shader::VERTEX:
26720 source = BufferTestBase::getShaderSource(test_case_index, stage);
26721 break;
26722 default:
26723 break;
26724 }
26725 break;
26726
26727 case TEST_GS:
26728 source = BufferTestBase::getShaderSource(test_case_index, stage);
26729 break;
26730
26731 default:
26732 TCU_FAIL("Invalid enum");
26733 break;
26734 }
26735
26736 /* */
26737 return source;
26738 }
26739
26740 /** Get name of test case
26741 *
26742 * @param test_case_index Index of test case
26743 *
26744 * @return Name of tested stage
26745 **/
26746 std::string XFBCaptureInactiveOutputComponentTest::getTestCaseName(glw::GLuint test_case_index)
26747 {
26748 const GLchar* name = 0;
26749
26750 switch (test_case_index)
26751 {
26752 case TEST_VS:
26753 name = "vertex";
26754 break;
26755 case TEST_TES:
26756 name = "tessellation evaluation";
26757 break;
26758 case TEST_GS:
26759 name = "geometry";
26760 break;
26761 default:
26762 TCU_FAIL("Invalid enum");
26763 }
26764
26765 return name;
26766 }
26767
26768 /** Returns number of test cases
26769 *
26770 * @return TEST_MAX
26771 **/
26772 glw::GLuint XFBCaptureInactiveOutputComponentTest::getTestCaseNumber()
26773 {
26774 return TEST_MAX;
26775 }
26776
26777 /** Verify contents of buffers
26778 *
26779 * @param buffers Collection of buffers to be verified
26780 *
26781 * @return true if everything is as expected, false otherwise
26782 **/
26783 bool XFBCaptureInactiveOutputComponentTest::verifyBuffers(bufferCollection& buffers)
26784 {
26785 bool result = true;
26786
26787 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
26788 Utils::Buffer* buffer = pair.m_buffer;
26789 bufferDescriptor* descriptor = pair.m_descriptor;
26790
26791 /* Get pointer to contents of buffer */
26792 buffer->Bind();
26793 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
26794
26795 /* Get pointer to expected data */
26796 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
26797
26798 /* Compare */
26799 static const GLuint comp_size = 4;
26800 static const GLuint vec4_size = 16;
26801
26802 int res_goku_x =
26803 memcmp(buffer_data + 2 * vec4_size + 0 * comp_size, expected_data + 2 * vec4_size + 0 * comp_size, comp_size);
26804 int res_goku_z =
26805 memcmp(buffer_data + 2 * vec4_size + 2 * comp_size, expected_data + 2 * vec4_size + 2 * comp_size, comp_size);
26806
26807 int res_gohan_y =
26808 memcmp(buffer_data + 0 * vec4_size + 1 * comp_size, expected_data + 0 * vec4_size + 1 * comp_size, comp_size);
26809 int res_gohan_w =
26810 memcmp(buffer_data + 0 * vec4_size + 3 * comp_size, expected_data + 0 * vec4_size + 3 * comp_size, comp_size);
26811
26812 int res_goten_x =
26813 memcmp(buffer_data + 1 * vec4_size + 0 * comp_size, expected_data + 1 * vec4_size + 0 * comp_size, comp_size);
26814 int res_goten_y =
26815 memcmp(buffer_data + 1 * vec4_size + 1 * comp_size, expected_data + 1 * vec4_size + 1 * comp_size, comp_size);
26816
26817 int res_chichi_z =
26818 memcmp(buffer_data + 3 * vec4_size + 2 * comp_size, expected_data + 3 * vec4_size + 2 * comp_size, comp_size);
26819 int res_chichi_w =
26820 memcmp(buffer_data + 3 * vec4_size + 3 * comp_size, expected_data + 3 * vec4_size + 3 * comp_size, comp_size);
26821
26822 int res_vegeta_x =
26823 memcmp(buffer_data + 7 * vec4_size + 0 * comp_size, expected_data + 7 * vec4_size + 0 * comp_size, comp_size);
26824
26825 int res_trunks_y =
26826 memcmp(buffer_data + 6 * vec4_size + 1 * comp_size, expected_data + 6 * vec4_size + 1 * comp_size, comp_size);
26827
26828 int res_bra_z =
26829 memcmp(buffer_data + 5 * vec4_size + 2 * comp_size, expected_data + 5 * vec4_size + 2 * comp_size, comp_size);
26830
26831 int res_bulma_w =
26832 memcmp(buffer_data + 4 * vec4_size + 3 * comp_size, expected_data + 4 * vec4_size + 3 * comp_size, comp_size);
26833
26834 if ((0 != res_goku_x) || (0 != res_goku_z) || (0 != res_gohan_y) || (0 != res_gohan_w) || (0 != res_goten_x) ||
26835 (0 != res_goten_y) || (0 != res_chichi_z) || (0 != res_chichi_w) || (0 != res_vegeta_x) ||
26836 (0 != res_trunks_y) || (0 != res_bra_z) || (0 != res_bulma_w))
26837 {
26838 m_context.getTestContext().getLog()
26839 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
26840 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
26841
26842 result = false;
26843 }
26844
26845 /* Release buffer mapping */
26846 buffer->UnMap();
26847
26848 return result;
26849 }
26850
26851 /** Constructor
26852 *
26853 * @param context Test context
26854 **/
26855 XFBCaptureInactiveOutputBlockMemberTest::XFBCaptureInactiveOutputBlockMemberTest(deqp::Context& context)
26856 : BufferTestBase(context, "xfb_capture_inactive_output_block_member",
26857 "Test verifies that inactive block members are captured")
26858 {
26859 /* Nothing to be done here */
26860 }
26861
26862 /** Execute drawArrays for single vertex
26863 *
26864 * @param test_case_index
26865 *
26866 * @return true
26867 **/
26868 bool XFBCaptureInactiveOutputBlockMemberTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
26869 {
26870 const Functions& gl = m_context.getRenderContext().getFunctions();
26871 GLenum primitive_type = GL_PATCHES;
26872
26873 if (TEST_VS == test_case_index)
26874 {
26875 primitive_type = GL_POINTS;
26876 }
26877
26878 gl.disable(GL_RASTERIZER_DISCARD);
26879 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
26880
26881 gl.beginTransformFeedback(GL_POINTS);
26882 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
26883
26884 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
26885 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
26886
26887 gl.endTransformFeedback();
26888 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
26889
26890 return true;
26891 }
26892
26893 /** Get descriptors of buffers necessary for test
26894 *
26895 * @param ignored
26896 * @param out_descriptors Descriptors of buffers used by test
26897 **/
26898 void XFBCaptureInactiveOutputBlockMemberTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
26899 bufferDescriptor::Vector& out_descriptors)
26900 {
26901 const Utils::Type& type = Utils::Type::vec4;
26902
26903 /* Test needs single uniform and xfb */
26904 out_descriptors.resize(2);
26905
26906 /* Get references */
26907 bufferDescriptor& uniform = out_descriptors[0];
26908 bufferDescriptor& xfb = out_descriptors[1];
26909
26910 /* Index */
26911 uniform.m_index = 0;
26912 xfb.m_index = 0;
26913
26914 /* Target */
26915 uniform.m_target = Utils::Buffer::Uniform;
26916 xfb.m_target = Utils::Buffer::Transform_feedback;
26917
26918 /* Data */
26919 const std::vector<GLubyte>& gohan_data = type.GenerateData();
26920 const std::vector<GLubyte>& chichi_data = type.GenerateData();
26921
26922 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
26923
26924 /* Uniform data */
26925 uniform.m_initial_data.resize(2 * type_size);
26926 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
26927 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
26928
26929 /* XFB data */
26930 xfb.m_initial_data.resize(4 * type_size);
26931 xfb.m_expected_data.resize(4 * type_size);
26932
26933 for (GLuint i = 0; i < 4 * type_size; ++i)
26934 {
26935 xfb.m_initial_data[i] = (glw::GLubyte)i;
26936 xfb.m_expected_data[i] = (glw::GLubyte)i;
26937 }
26938
26939 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
26940 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
26941 }
26942
26943 /** Get body of main function for given shader stage
26944 *
26945 * @param test_case_index Index of test case
26946 * @param stage Shader stage
26947 * @param out_assignments Set to empty
26948 * @param out_calculations Set to empty
26949 **/
26950 void XFBCaptureInactiveOutputBlockMemberTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
26951 std::string& out_assignments, std::string& out_calculations)
26952 {
26953 out_calculations = "";
26954
26955 static const GLchar* vs_tes_gs = " chichi = uni_chichi;\n"
26956 " gohan = uni_gohan;\n";
26957 static const GLchar* fs = " fs_out = goten + gohan + chichi;\n";
26958
26959 const GLchar* assignments = "";
26960
26961 switch (stage)
26962 {
26963 case Utils::Shader::FRAGMENT:
26964 assignments = fs;
26965 break;
26966
26967 case Utils::Shader::GEOMETRY:
26968 if (TEST_GS == test_case_index)
26969 {
26970 assignments = vs_tes_gs;
26971 }
26972 break;
26973
26974 case Utils::Shader::TESS_CTRL:
26975 break;
26976
26977 case Utils::Shader::TESS_EVAL:
26978 if (TEST_TES == test_case_index)
26979 {
26980 assignments = vs_tes_gs;
26981 }
26982 break;
26983
26984 case Utils::Shader::VERTEX:
26985 if (TEST_VS == test_case_index)
26986 {
26987 assignments = vs_tes_gs;
26988 }
26989 break;
26990
26991 default:
26992 TCU_FAIL("Invalid enum");
26993 }
26994
26995 out_assignments = assignments;
26996 }
26997
26998 /** Get interface of shader
26999 *
27000 * @param test_case_index Index of test case
27001 * @param stage Shader stage
27002 * @param out_interface Set to ""
27003 **/
27004 void XFBCaptureInactiveOutputBlockMemberTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
27005 std::string& out_interface)
27006 {
27007 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
27008 "\n"
27009 "layout (xfb_offset = 1 * sizeof_type) out Goku {\n"
27010 " vec4 gohan;\n"
27011 " vec4 goten;\n"
27012 " vec4 chichi;\n"
27013 "};\n"
27014 "\n"
27015 "layout(binding = 0) uniform block {\n"
27016 " vec4 uni_gohan;\n"
27017 " vec4 uni_chichi;\n"
27018 "};\n";
27019 static const GLchar* fs = "in Goku {\n"
27020 " vec4 gohan;\n"
27021 " vec4 goten;\n"
27022 " vec4 chichi;\n"
27023 "};\n"
27024 "out vec4 fs_out;\n";
27025
27026 const GLchar* interface = "";
27027
27028 switch (stage)
27029 {
27030 case Utils::Shader::FRAGMENT:
27031 interface = fs;
27032 break;
27033
27034 case Utils::Shader::GEOMETRY:
27035 if (TEST_GS == test_case_index)
27036 {
27037 interface = vs_tes_gs;
27038 }
27039 break;
27040
27041 case Utils::Shader::TESS_CTRL:
27042 break;
27043
27044 case Utils::Shader::TESS_EVAL:
27045 if (TEST_TES == test_case_index)
27046 {
27047 interface = vs_tes_gs;
27048 }
27049 break;
27050
27051 case Utils::Shader::VERTEX:
27052 if (TEST_VS == test_case_index)
27053 {
27054 interface = vs_tes_gs;
27055 }
27056 break;
27057
27058 default:
27059 TCU_FAIL("Invalid enum");
27060 }
27061
27062 out_interface = interface;
27063 }
27064
27065 /** Get source code of shader
27066 *
27067 * @param test_case_index Index of test case
27068 * @param stage Shader stage
27069 *
27070 * @return Source
27071 **/
27072 std::string XFBCaptureInactiveOutputBlockMemberTest::getShaderSource(GLuint test_case_index,
27073 Utils::Shader::STAGES stage)
27074 {
27075 std::string source;
27076
27077 switch (test_case_index)
27078 {
27079 case TEST_VS:
27080 switch (stage)
27081 {
27082 case Utils::Shader::FRAGMENT:
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_TES:
27092 switch (stage)
27093 {
27094 case Utils::Shader::FRAGMENT:
27095 case Utils::Shader::TESS_CTRL:
27096 case Utils::Shader::TESS_EVAL:
27097 case Utils::Shader::VERTEX:
27098 source = BufferTestBase::getShaderSource(test_case_index, stage);
27099 break;
27100 default:
27101 break;
27102 }
27103 break;
27104
27105 case TEST_GS:
27106 source = BufferTestBase::getShaderSource(test_case_index, stage);
27107 break;
27108
27109 default:
27110 TCU_FAIL("Invalid enum");
27111 break;
27112 }
27113
27114 /* */
27115 return source;
27116 }
27117
27118 /** Get name of test case
27119 *
27120 * @param test_case_index Index of test case
27121 *
27122 * @return Name of tested stage
27123 **/
27124 std::string XFBCaptureInactiveOutputBlockMemberTest::getTestCaseName(glw::GLuint test_case_index)
27125 {
27126 const GLchar* name = 0;
27127
27128 switch (test_case_index)
27129 {
27130 case TEST_VS:
27131 name = "vertex";
27132 break;
27133 case TEST_TES:
27134 name = "tessellation evaluation";
27135 break;
27136 case TEST_GS:
27137 name = "geometry";
27138 break;
27139 default:
27140 TCU_FAIL("Invalid enum");
27141 }
27142
27143 return name;
27144 }
27145
27146 /** Returns number of test cases
27147 *
27148 * @return TEST_MAX
27149 **/
27150 glw::GLuint XFBCaptureInactiveOutputBlockMemberTest::getTestCaseNumber()
27151 {
27152 return TEST_MAX;
27153 }
27154
27155 /** Verify contents of buffers
27156 *
27157 * @param buffers Collection of buffers to be verified
27158 *
27159 * @return true if everything is as expected, false otherwise
27160 **/
27161 bool XFBCaptureInactiveOutputBlockMemberTest::verifyBuffers(bufferCollection& buffers)
27162 {
27163 bool result = true;
27164
27165 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27166 Utils::Buffer* buffer = pair.m_buffer;
27167 bufferDescriptor* descriptor = pair.m_descriptor;
27168
27169 /* Get pointer to contents of buffer */
27170 buffer->Bind();
27171 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27172
27173 /* Get pointer to expected data */
27174 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27175
27176 /* Compare */
27177 static const GLuint vec4_size = 16;
27178
27179 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27180 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27181 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27182
27183 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27184 {
27185 m_context.getTestContext().getLog()
27186 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27187 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27188
27189 result = false;
27190 }
27191
27192 /* Release buffer mapping */
27193 buffer->UnMap();
27194
27195 return result;
27196 }
27197
27198 /** Constructor
27199 *
27200 * @param context Test context
27201 **/
27202 XFBCaptureStructTest::XFBCaptureStructTest(deqp::Context& context)
27203 : BufferTestBase(context, "xfb_capture_struct", "Test verifies that inactive structure members are captured")
27204 {
27205 /* Nothing to be done here */
27206 }
27207
27208 /** Execute drawArrays for single vertex
27209 *
27210 * @param test_case_index
27211 *
27212 * @return true
27213 **/
27214 bool XFBCaptureStructTest::executeDrawCall(bool /* tesEnabled */, GLuint test_case_index)
27215 {
27216 const Functions& gl = m_context.getRenderContext().getFunctions();
27217 GLenum primitive_type = GL_PATCHES;
27218
27219 if (TEST_VS == test_case_index)
27220 {
27221 primitive_type = GL_POINTS;
27222 }
27223
27224 gl.disable(GL_RASTERIZER_DISCARD);
27225 GLU_EXPECT_NO_ERROR(gl.getError(), "Disable");
27226
27227 gl.beginTransformFeedback(GL_POINTS);
27228 GLU_EXPECT_NO_ERROR(gl.getError(), "BeginTransformFeedback");
27229
27230 gl.drawArrays(primitive_type, 0 /* first */, 1 /* count */);
27231 GLU_EXPECT_NO_ERROR(gl.getError(), "DrawArrays");
27232
27233 gl.endTransformFeedback();
27234 GLU_EXPECT_NO_ERROR(gl.getError(), "EndTransformFeedback");
27235
27236 return true;
27237 }
27238
27239 /** Get descriptors of buffers necessary for test
27240 *
27241 * @param ignored
27242 * @param out_descriptors Descriptors of buffers used by test
27243 **/
27244 void XFBCaptureStructTest::getBufferDescriptors(glw::GLuint /* test_case_index */,
27245 bufferDescriptor::Vector& out_descriptors)
27246 {
27247 const Utils::Type& type = Utils::Type::vec4;
27248
27249 /* Test needs single uniform and xfb */
27250 out_descriptors.resize(2);
27251
27252 /* Get references */
27253 bufferDescriptor& uniform = out_descriptors[0];
27254 bufferDescriptor& xfb = out_descriptors[1];
27255
27256 /* Index */
27257 uniform.m_index = 0;
27258 xfb.m_index = 0;
27259
27260 /* Target */
27261 uniform.m_target = Utils::Buffer::Uniform;
27262 xfb.m_target = Utils::Buffer::Transform_feedback;
27263
27264 /* Data */
27265 const std::vector<GLubyte>& gohan_data = type.GenerateData();
27266 const std::vector<GLubyte>& chichi_data = type.GenerateData();
27267
27268 const GLuint type_size = static_cast<GLuint>(gohan_data.size());
27269
27270 /* Uniform data */
27271 uniform.m_initial_data.resize(2 * type_size);
27272 memcpy(&uniform.m_initial_data[0] + 0, &gohan_data[0], type_size);
27273 memcpy(&uniform.m_initial_data[0] + type_size, &chichi_data[0], type_size);
27274
27275 /* XFB data */
27276 xfb.m_initial_data.resize(4 * type_size);
27277 xfb.m_expected_data.resize(4 * type_size);
27278
27279 for (GLuint i = 0; i < 4 * type_size; ++i)
27280 {
27281 xfb.m_initial_data[i] = (glw::GLubyte)i;
27282 xfb.m_expected_data[i] = (glw::GLubyte)i;
27283 }
27284
27285 memcpy(&xfb.m_expected_data[0] + 1 * type_size, &gohan_data[0], type_size);
27286 memcpy(&xfb.m_expected_data[0] + 3 * type_size, &chichi_data[0], type_size);
27287 }
27288
27289 /** Get body of main function for given shader stage
27290 *
27291 * @param test_case_index Index of test case
27292 * @param stage Shader stage
27293 * @param out_assignments Set to empty
27294 * @param out_calculations Set to empty
27295 **/
27296 void XFBCaptureStructTest::getShaderBody(GLuint test_case_index, Utils::Shader::STAGES stage,
27297 std::string& out_assignments, std::string& out_calculations)
27298 {
27299 out_calculations = "";
27300
27301 static const GLchar* vs_tes_gs = " goku.chichi = uni_chichi;\n"
27302 " goku.gohan = uni_gohan;\n";
27303 static const GLchar* fs = " fs_out = goku.goten + goku.gohan + goku.chichi;\n";
27304
27305 const GLchar* assignments = "";
27306
27307 switch (stage)
27308 {
27309 case Utils::Shader::FRAGMENT:
27310 assignments = fs;
27311 break;
27312
27313 case Utils::Shader::GEOMETRY:
27314 if (TEST_GS == test_case_index)
27315 {
27316 assignments = vs_tes_gs;
27317 }
27318 break;
27319
27320 case Utils::Shader::TESS_CTRL:
27321 break;
27322
27323 case Utils::Shader::TESS_EVAL:
27324 if (TEST_TES == test_case_index)
27325 {
27326 assignments = vs_tes_gs;
27327 }
27328 break;
27329
27330 case Utils::Shader::VERTEX:
27331 if (TEST_VS == test_case_index)
27332 {
27333 assignments = vs_tes_gs;
27334 }
27335 break;
27336
27337 default:
27338 TCU_FAIL("Invalid enum");
27339 }
27340
27341 out_assignments = assignments;
27342 }
27343
27344 /** Get interface of shader
27345 *
27346 * @param test_case_index Index of test case
27347 * @param stage Shader stage
27348 * @param out_interface Set to ""
27349 **/
27350 void XFBCaptureStructTest::getShaderInterface(GLuint test_case_index, Utils::Shader::STAGES stage,
27351 std::string& out_interface)
27352 {
27353 static const GLchar* vs_tes_gs = "const uint sizeof_type = 16;\n"
27354 "\n"
27355 "struct Goku {\n"
27356 " vec4 gohan;\n"
27357 " vec4 goten;\n"
27358 " vec4 chichi;\n"
27359 "};\n"
27360 "\n"
27361 "layout (xfb_offset = sizeof_type) out Goku goku;\n"
27362 "\n"
27363 "layout(binding = 0, std140) uniform block {\n"
27364 " vec4 uni_gohan;\n"
27365 " vec4 uni_chichi;\n"
27366 "};\n";
27367 static const GLchar* fs = "struct Goku {\n"
27368 " vec4 gohan;\n"
27369 " vec4 goten;\n"
27370 " vec4 chichi;\n"
27371 "};\n"
27372 "\n"
27373 "in Goku goku;\n"
27374 "\n"
27375 "out vec4 fs_out;\n";
27376
27377 const GLchar* interface = "";
27378
27379 switch (stage)
27380 {
27381 case Utils::Shader::FRAGMENT:
27382 interface = fs;
27383 break;
27384
27385 case Utils::Shader::GEOMETRY:
27386 if (TEST_GS == test_case_index)
27387 {
27388 interface = vs_tes_gs;
27389 }
27390 break;
27391
27392 case Utils::Shader::TESS_CTRL:
27393 break;
27394
27395 case Utils::Shader::TESS_EVAL:
27396 if (TEST_TES == test_case_index)
27397 {
27398 interface = vs_tes_gs;
27399 }
27400 break;
27401
27402 case Utils::Shader::VERTEX:
27403 if (TEST_VS == test_case_index)
27404 {
27405 interface = vs_tes_gs;
27406 }
27407 break;
27408
27409 default:
27410 TCU_FAIL("Invalid enum");
27411 }
27412
27413 out_interface = interface;
27414 }
27415
27416 /** Get source code of shader
27417 *
27418 * @param test_case_index Index of test case
27419 * @param stage Shader stage
27420 *
27421 * @return Source
27422 **/
27423 std::string XFBCaptureStructTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27424 {
27425 std::string source;
27426
27427 switch (test_case_index)
27428 {
27429 case TEST_VS:
27430 switch (stage)
27431 {
27432 case Utils::Shader::FRAGMENT:
27433 case Utils::Shader::VERTEX:
27434 source = BufferTestBase::getShaderSource(test_case_index, stage);
27435 break;
27436 default:
27437 break;
27438 }
27439 break;
27440
27441 case TEST_TES:
27442 switch (stage)
27443 {
27444 case Utils::Shader::FRAGMENT:
27445 case Utils::Shader::TESS_CTRL:
27446 case Utils::Shader::TESS_EVAL:
27447 case Utils::Shader::VERTEX:
27448 source = BufferTestBase::getShaderSource(test_case_index, stage);
27449 break;
27450 default:
27451 break;
27452 }
27453 break;
27454
27455 case TEST_GS:
27456 source = BufferTestBase::getShaderSource(test_case_index, stage);
27457 break;
27458
27459 default:
27460 TCU_FAIL("Invalid enum");
27461 break;
27462 }
27463
27464 /* */
27465 return source;
27466 }
27467
27468 /** Get name of test case
27469 *
27470 * @param test_case_index Index of test case
27471 *
27472 * @return Name of tested stage
27473 **/
27474 std::string XFBCaptureStructTest::getTestCaseName(glw::GLuint test_case_index)
27475 {
27476 const GLchar* name = 0;
27477
27478 switch (test_case_index)
27479 {
27480 case TEST_VS:
27481 name = "vertex";
27482 break;
27483 case TEST_TES:
27484 name = "tessellation evaluation";
27485 break;
27486 case TEST_GS:
27487 name = "geometry";
27488 break;
27489 default:
27490 TCU_FAIL("Invalid enum");
27491 }
27492
27493 return name;
27494 }
27495
27496 /** Returns number of test cases
27497 *
27498 * @return TEST_MAX
27499 **/
27500 glw::GLuint XFBCaptureStructTest::getTestCaseNumber()
27501 {
27502 return TEST_MAX;
27503 }
27504
27505 /** Verify contents of buffers
27506 *
27507 * @param buffers Collection of buffers to be verified
27508 *
27509 * @return true if everything is as expected, false otherwise
27510 **/
27511 bool XFBCaptureStructTest::verifyBuffers(bufferCollection& buffers)
27512 {
27513 bool result = true;
27514
27515 bufferCollection::pair& pair = buffers.m_vector[1] /* xfb */;
27516 Utils::Buffer* buffer = pair.m_buffer;
27517 bufferDescriptor* descriptor = pair.m_descriptor;
27518
27519 /* Get pointer to contents of buffer */
27520 buffer->Bind();
27521 GLubyte* buffer_data = (GLubyte*)buffer->Map(Utils::Buffer::ReadOnly);
27522
27523 /* Get pointer to expected data */
27524 GLubyte* expected_data = (GLubyte*)&descriptor->m_expected_data[0];
27525
27526 /* Compare */
27527 static const GLuint vec4_size = 16;
27528
27529 int res_before = memcmp(buffer_data, expected_data, vec4_size);
27530 int res_gohan = memcmp(buffer_data + 1 * vec4_size, expected_data + 1 * vec4_size, vec4_size);
27531 int res_chichi = memcmp(buffer_data + 3 * vec4_size, expected_data + 3 * vec4_size, vec4_size);
27532
27533 if ((0 != res_before) || (0 != res_gohan) || (0 != res_chichi))
27534 {
27535 m_context.getTestContext().getLog()
27536 << tcu::TestLog::Message << "Invalid result. Buffer: " << Utils::Buffer::GetBufferName(descriptor->m_target)
27537 << ". Index: " << descriptor->m_index << tcu::TestLog::EndMessage;
27538
27539 result = false;
27540 }
27541
27542 /* Release buffer mapping */
27543 buffer->UnMap();
27544
27545 return result;
27546 }
27547
27548 /** Constructor
27549 *
27550 * @param context Test framework context
27551 **/
27552 XFBCaptureUnsizedArrayTest::XFBCaptureUnsizedArrayTest(deqp::Context& context)
27553 : NegativeTestBase(context, "xfb_capture_unsized_array",
27554 "Test verifies that compiler reports error when unsized array is qualified with xfb_offset")
27555 {
27556 }
27557
27558 /** Source for given test case and stage
27559 *
27560 * @param test_case_index Index of test case
27561 * @param stage Shader stage
27562 *
27563 * @return Shader source
27564 **/
27565 std::string XFBCaptureUnsizedArrayTest::getShaderSource(GLuint test_case_index, Utils::Shader::STAGES stage)
27566 {
27567 #if DEBUG_NEG_REMOVE_ERROR
27568 static const GLchar* var_definition = "/* layout (xfb_offset = 0) */ out vec4 goku[];\n";
27569 #else
27570 static const GLchar* var_definition = "layout (xfb_offset = 0) out vec4 goku[];\n";
27571 #endif /* DEBUG_NEG_REMOVE_ERROR */
27572 static const GLchar* var_use = " goku[0] = result / 2;\n";
27573 static const GLchar* fs = "#version 430 core\n"
27574 "#extension GL_ARB_enhanced_layouts : require\n"
27575 "\n"
27576 "in vec4 any_fs;\n"
27577 "out vec4 fs_out;\n"
27578 "\n"
27579 "void main()\n"
27580 "{\n"
27581 " fs_out = any_fs;\n"
27582 "}\n"
27583 "\n";
27584 static const GLchar* vs_tested = "#version 430 core\n"
27585 "#extension GL_ARB_enhanced_layouts : require\n"
27586 "\n"
27587 "VAR_DEFINITION"
27588 "\n"
27589 "in vec4 in_vs;\n"
27590 "out vec4 any_fs;\n"
27591 "\n"
27592 "void main()\n"
27593 "{\n"
27594 " vec4 result = in_vs;\n"
27595 "\n"
27596 "VARIABLE_USE"
27597 "\n"
27598 " any_fs = result;\n"
27599 "}\n"
27600 "\n";
27601
27602 std::string source;
27603 testCase& test_case = m_test_cases[test_case_index];
27604
27605 if (test_case.m_stage == stage)
27606 {
27607 size_t position = 0;
27608
27609 switch (stage)
27610 {
27611 case Utils::Shader::VERTEX:
27612 source = vs_tested;
27613 break;
27614 default:
27615 TCU_FAIL("Invalid enum");
27616 }
27617
27618 Utils::replaceToken("VAR_DEFINITION", position, var_definition, source);
27619 position = 0;
27620 Utils::replaceToken("VARIABLE_USE", position, var_use, source);
27621 }
27622 else
27623 {
27624 switch (test_case.m_stage)
27625 {
27626 case Utils::Shader::VERTEX:
27627 switch (stage)
27628 {
27629 case Utils::Shader::FRAGMENT:
27630 source = fs;
27631 break;
27632 default:
27633 source = "";
27634 }
27635 break;
27636 default:
27637 TCU_FAIL("Invalid enum");
27638 break;
27639 }
27640 }
27641
27642 return source;
27643 }
27644
27645 /** Get description of test case
27646 *
27647 * @param test_case_index Index of test case
27648 *
27649 * @return Test case description
27650 **/
27651 std::string XFBCaptureUnsizedArrayTest::getTestCaseName(GLuint test_case_index)
27652 {
27653 std::stringstream stream;
27654 testCase& test_case = m_test_cases[test_case_index];
27655
27656 stream << "Stage: " << Utils::Shader::GetStageName(test_case.m_stage);
27657
27658 return stream.str();
27659 }
27660
27661 /** Get number of test cases
27662 *
27663 * @return Number of test cases
27664 **/
27665 GLuint XFBCaptureUnsizedArrayTest::getTestCaseNumber()
27666 {
27667 return static_cast<GLuint>(m_test_cases.size());
27668 }
27669
27670 /** Selects if "compute" stage is relevant for test
27671 *
27672 * @param ignored
27673 *
27674 * @return false
27675 **/
27676 bool XFBCaptureUnsizedArrayTest::isComputeRelevant(GLuint /* test_case_index */)
27677 {
27678 return false;
27679 }
27680
27681 /** Prepare all test cases
27682 *
27683 **/
27684 void XFBCaptureUnsizedArrayTest::testInit()
27685 {
27686 for (GLuint stage = 0; stage < Utils::Shader::STAGE_MAX; ++stage)
27687 {
27688 /* Not aplicable for */
27689 if ((Utils::Shader::COMPUTE == stage) || (Utils::Shader::TESS_CTRL == stage) ||
27690 (Utils::Shader::FRAGMENT == stage) || (Utils::Shader::GEOMETRY == stage) ||
27691 (Utils::Shader::TESS_EVAL == stage))
27692 {
27693 continue;
27694 }
27695
27696 testCase test_case = { (Utils::Shader::STAGES)stage };
27697
27698 m_test_cases.push_back(test_case);
27699 }
27700 }
27701 } /* EnhancedLayouts namespace */
27702
27703 /** Constructor.
27704 *
27705 * @param context Rendering context.
27706 **/
EnhancedLayoutsTests(deqp::Context & context)27707 EnhancedLayoutsTests::EnhancedLayoutsTests(deqp::Context& context)
27708 : TestCaseGroup(context, "enhanced_layouts", "Verifies \"enhanced layouts\" functionality")
27709 {
27710 /* Left blank on purpose */
27711 }
27712
27713 /** Initializes a texture_storage_multisample test group.
27714 *
27715 **/
init(void)27716 void EnhancedLayoutsTests::init(void)
27717 {
27718 addChild(new EnhancedLayouts::APIConstantValuesTest(m_context));
27719 addChild(new EnhancedLayouts::APIErrorsTest(m_context));
27720 addChild(new EnhancedLayouts::GLSLContantValuesTest(m_context));
27721 addChild(new EnhancedLayouts::GLSLContantImmutablityTest(m_context));
27722 addChild(new EnhancedLayouts::GLSLConstantIntegralExpressionTest(m_context));
27723 addChild(new EnhancedLayouts::UniformBlockLayoutQualifierConflictTest(m_context));
27724 addChild(new EnhancedLayouts::SSBMemberInvalidOffsetAlignmentTest(m_context));
27725 addChild(new EnhancedLayouts::SSBMemberOverlappingOffsetsTest(m_context));
27726 addChild(new EnhancedLayouts::VaryingInvalidValueComponentTest(m_context));
27727 addChild(new EnhancedLayouts::VaryingExceedingComponentsTest(m_context));
27728 addChild(new EnhancedLayouts::VaryingComponentOfInvalidTypeTest(m_context));
27729 addChild(new EnhancedLayouts::OutputComponentAliasingTest(m_context));
27730 addChild(new EnhancedLayouts::VertexAttribLocationAPITest(m_context));
27731 addChild(new EnhancedLayouts::XFBInputTest(m_context));
27732 addChild(new EnhancedLayouts::XFBAllStagesTest(m_context));
27733 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputVariableTest(m_context));
27734 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputComponentTest(m_context));
27735 addChild(new EnhancedLayouts::XFBCaptureInactiveOutputBlockMemberTest(m_context));
27736 addChild(new EnhancedLayouts::XFBStrideTest(m_context));
27737
27738 addChild(new EnhancedLayouts::UniformBlockMemberOffsetAndAlignTest(m_context));
27739 addChild(new EnhancedLayouts::UniformBlockMemberInvalidOffsetAlignmentTest(m_context));
27740 addChild(new EnhancedLayouts::UniformBlockMemberOverlappingOffsetsTest(m_context));
27741 addChild(new EnhancedLayouts::UniformBlockMemberAlignNonPowerOf2Test(m_context));
27742 addChild(new EnhancedLayouts::SSBLayoutQualifierConflictTest(m_context));
27743 addChild(new EnhancedLayouts::SSBMemberAlignNonPowerOf2Test(m_context));
27744 addChild(new EnhancedLayouts::SSBAlignmentTest(m_context));
27745 addChild(new EnhancedLayouts::VaryingStructureMemberLocationTest(m_context));
27746 addChild(new EnhancedLayouts::VaryingBlockAutomaticMemberLocationsTest(m_context));
27747 addChild(new EnhancedLayouts::VaryingComponentWithoutLocationTest(m_context));
27748 addChild(new EnhancedLayouts::InputComponentAliasingTest(m_context));
27749 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedTypesTest(m_context));
27750 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedInterpolationTest(m_context));
27751 addChild(new EnhancedLayouts::VaryingLocationAliasingWithMixedAuxiliaryStorageTest(m_context));
27752 addChild(new EnhancedLayouts::XFBStrideOfEmptyListTest(m_context));
27753 addChild(new EnhancedLayouts::XFBStrideOfEmptyListAndAPITest(m_context));
27754 addChild(new EnhancedLayouts::XFBTooSmallStrideTest(m_context));
27755 addChild(new EnhancedLayouts::XFBBlockMemberStrideTest(m_context));
27756 addChild(new EnhancedLayouts::XFBDuplicatedStrideTest(m_context));
27757 addChild(new EnhancedLayouts::XFBGetProgramResourceAPITest(m_context));
27758 addChild(new EnhancedLayouts::XFBMultipleVertexStreamsTest(m_context));
27759 addChild(new EnhancedLayouts::XFBExceedBufferLimitTest(m_context));
27760 addChild(new EnhancedLayouts::XFBExceedOffsetLimitTest(m_context));
27761 addChild(new EnhancedLayouts::XFBBlockMemberBufferTest(m_context));
27762 addChild(new EnhancedLayouts::XFBOutputOverlappingTest(m_context));
27763 addChild(new EnhancedLayouts::XFBInvalidOffsetAlignmentTest(m_context));
27764 addChild(new EnhancedLayouts::XFBCaptureStructTest(m_context));
27765 addChild(new EnhancedLayouts::XFBCaptureUnsizedArrayTest(m_context));
27766 addChild(new EnhancedLayouts::UniformBlockAlignmentTest(m_context));
27767 addChild(new EnhancedLayouts::SSBMemberOffsetAndAlignTest(m_context));
27768 addChild(new EnhancedLayouts::VertexAttribLocationsTest(m_context));
27769 addChild(new EnhancedLayouts::VaryingLocationsTest(m_context));
27770 addChild(new EnhancedLayouts::VaryingArrayLocationsTest(m_context));
27771 addChild(new EnhancedLayouts::VaryingStructureLocationsTest(m_context));
27772 addChild(new EnhancedLayouts::VaryingBlockLocationsTest(m_context));
27773 addChild(new EnhancedLayouts::VaryingBlockMemberLocationsTest(m_context));
27774 addChild(new EnhancedLayouts::XFBVariableStrideTest(m_context));
27775 addChild(new EnhancedLayouts::XFBBlockStrideTest(m_context));
27776 addChild(new EnhancedLayouts::XFBOverrideQualifiersWithAPITest(m_context));
27777 addChild(new EnhancedLayouts::XFBVertexStreamsTest(m_context));
27778 addChild(new EnhancedLayouts::XFBGlobalBufferTest(m_context));
27779 addChild(new EnhancedLayouts::FragmentDataLocationAPITest(m_context));
27780 addChild(new EnhancedLayouts::VaryingLocationLimitTest(m_context));
27781 addChild(new EnhancedLayouts::VaryingComponentsTest(m_context));
27782 addChild(new EnhancedLayouts::VaryingArrayComponentsTest(m_context));
27783 }
27784
27785 } /* gl4cts namespace */
27786