• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 /*!
24  * \file esextcGeometryShaderLimits.cpp
25  * \brief Geometry Shader Limits (Test Group 16)
26  */ /*-------------------------------------------------------------------*/
27 
28 #include "esextcGeometryShaderLimits.hpp"
29 
30 #include "gluContextInfo.hpp"
31 #include "glwEnums.hpp"
32 #include "glwFunctions.hpp"
33 #include "tcuTestLog.hpp"
34 
35 #include <cstring>
36 #include <sstream>
37 #include <string>
38 
39 namespace glcts
40 {
41 /* Vertex Shader for GeometryShaderMaxUniformComponentsTest */
42 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_vertex_shader_code =
43 	"${VERSION}\n"
44 	"\n"
45 	"${GEOMETRY_SHADER_REQUIRE}\n"
46 	"\n"
47 	"void main()\n"
48 	"{\n"
49 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
50 	"}\n";
51 
52 /* Geometry Shader parts for GeometryShaderMaxUniformComponentsTest */
53 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_geometry_shader_code_preamble =
54 	"${VERSION}\n"
55 	"\n"
56 	"${GEOMETRY_SHADER_REQUIRE}\n"
57 	"\n"
58 	"layout(points)                 in;\n"
59 	"layout(points, max_vertices=1) out;\n"
60 	"\n"
61 	"// definition of NUMBER_OF_UNIFORMS goes here\n";
62 
63 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_geometry_shader_code_number_of_uniforms =
64 	"#define NUMBER_OF_UNIFORMS ";
65 
66 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_geometry_shader_code_body =
67 	"u\n"
68 	"\n"
69 	"uniform ivec4 uni_array[NUMBER_OF_UNIFORMS];\n"
70 	"\n"
71 	"flat out uint gs_out_sum;\n"
72 	"\n"
73 	"void main()\n"
74 	"{\n"
75 	"    gs_out_sum = 0u;\n"
76 	"\n"
77 	"    for (uint i = 0u; i < NUMBER_OF_UNIFORMS; ++i)\n"
78 	"    {\n"
79 	"        gs_out_sum += uint(uni_array[i].x);\n"
80 	"        gs_out_sum += uint(uni_array[i].y);\n"
81 	"        gs_out_sum += uint(uni_array[i].z);\n"
82 	"        gs_out_sum += uint(uni_array[i].w);\n"
83 	"    }\n"
84 	"    EmitVertex();\n"
85 	"    \n"
86 	"    EndPrimitive();\n"
87 	"}\n";
88 
89 /* Fragment Shader for GeometryShaderMaxUniformComponentsTest */
90 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_fragment_shader_code =
91 	"${VERSION}\n"
92 	"${GEOMETRY_SHADER_REQUIRE}\n"
93 	"precision mediump float;\n"
94 	"out vec4 fs_out_color;\n"
95 	"void main()\n"
96 	"{\n"
97 	"    fs_out_color = vec4(1, 1, 1, 1);\n"
98 	"}\n";
99 
100 /** ***************************************************************************************************** **/
101 /* Vertex Shader for GeometryShaderMaxUniformBlocksTest */
102 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_vertex_shader_code =
103 	"${VERSION}\n"
104 	"\n"
105 	"${GEOMETRY_SHADER_REQUIRE}\n"
106 	"\n"
107 	"void main()\n"
108 	"{\n"
109 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
110 	"}\n";
111 
112 /* Geometry Shader Parts for GeometryShaderMaxUniformBlocksTest */
113 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_geometry_shader_code_preamble =
114 	"${VERSION}\n"
115 	"\n"
116 	"${GEOMETRY_SHADER_REQUIRE}\n"
117 	"\n"
118 	"layout(points)                 in;\n"
119 	"layout(points, max_vertices=1) out;\n"
120 	"\n"
121 	"// definition of NUMBER_OF_UNIFORMS goes here\n";
122 
123 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_geometry_shader_code_number_of_uniforms =
124 	"#define NUMBER_OF_UNIFORM_BLOCKS ";
125 
126 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_geometry_shader_code_body_str =
127 	"u\n"
128 	"\n"
129 	"layout(binding = 0) uniform UniformBlock\n"
130 	"{\n"
131 	"    int entry;\n"
132 	"} uni_block_array[NUMBER_OF_UNIFORM_BLOCKS];\n"
133 	"\n"
134 	"flat out int gs_out_sum;\n"
135 	"\n"
136 	"void main()\n"
137 	"{\n"
138 	"    gs_out_sum = 0;\n"
139 	"\n";
140 
141 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_geometry_shader_code_body_end = "\n"
142 																							   "    EmitVertex();\n"
143 																							   "\n"
144 																							   "    EndPrimitive();\n"
145 																							   "}\n";
146 
147 /* Fragment Shader for GeometryShaderMaxUniformBlocksTest */
148 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_fragment_shader_code =
149 	"${VERSION}\n"
150 	"${GEOMETRY_SHADER_REQUIRE}\n"
151 	"precision mediump float;\n"
152 	"out vec4 fs_out_color;\n"
153 	"void main()\n"
154 	"{\n"
155 	"    fs_out_color = vec4(1, 1, 1, 1);\n"
156 	"}\n";
157 
158 /** ****************************************************************************************** **/
159 /* Vertex Shader for GeometryShaderMaxInputComponentsTest */
160 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_vertex_shader_code_preamble =
161 	"${VERSION}\n"
162 	"\n"
163 	"${GEOMETRY_SHADER_REQUIRE}\n"
164 	"\n"
165 	"// definition of NUMBER_OF_GEOMETRY_INPUT_VECTORS\n";
166 
167 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_vertex_shader_code_number_of_uniforms =
168 	"#define NUMBER_OF_GEOMETRY_INPUT_VECTORS ";
169 
170 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_vertex_shader_code_body =
171 	"u\n"
172 	"\n"
173 	"out Vertex\n"
174 	"{"
175 	"   flat out ivec4 vs_gs_out[NUMBER_OF_GEOMETRY_INPUT_VECTORS];\n"
176 	"};\n"
177 	"\n"
178 	"void main()\n"
179 	"{\n"
180 	"   int index = 1;\n"
181 	"\n"
182 	"   for (uint i = 0u; i < NUMBER_OF_GEOMETRY_INPUT_VECTORS; ++i)\n"
183 	"   {\n"
184 	"       vs_gs_out[i] = ivec4(index, index + 1, index + 2, index + 3);\n"
185 	"       index       += 4;\n"
186 	"   }\n"
187 	"}\n";
188 
189 /* Geometry Shader Parts for GeometryShaderMaxInputComponentsTest */
190 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_geometry_shader_code_preamble =
191 	"${VERSION}\n"
192 	"\n"
193 	"${GEOMETRY_SHADER_REQUIRE}\n"
194 	"\n"
195 	"layout(points)                 in;\n"
196 	"layout(points, max_vertices=1) out;\n"
197 	"\n"
198 	"// definition of NUMBER_OF_GEOMETRY_INPUT_VECTORS goes here\n";
199 
200 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_geometry_shader_code_number_of_uniforms =
201 	"#define NUMBER_OF_GEOMETRY_INPUT_VECTORS ";
202 
203 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_geometry_shader_code_body =
204 	"u\n"
205 	"\n"
206 	"in Vertex\n"
207 	"{\n"
208 	"    flat in ivec4 vs_gs_out[NUMBER_OF_GEOMETRY_INPUT_VECTORS];\n"
209 	"} vertex[1];\n"
210 	"\n"
211 	"flat out int gs_out_sum;\n"
212 	"\n"
213 	"void main()\n"
214 	"{\n"
215 	"    gs_out_sum = 0;\n"
216 	"\n"
217 	"    for (uint i = 0u; i < NUMBER_OF_GEOMETRY_INPUT_VECTORS; ++i)\n"
218 	"    {\n"
219 	"        gs_out_sum += vertex[0].vs_gs_out[i].x;\n"
220 	"        gs_out_sum += vertex[0].vs_gs_out[i].y;\n"
221 	"        gs_out_sum += vertex[0].vs_gs_out[i].z;\n"
222 	"        gs_out_sum += vertex[0].vs_gs_out[i].w;\n"
223 	"    }\n"
224 	"    EmitVertex();\n"
225 	"    \n"
226 	"    EndPrimitive();\n"
227 	"}\n";
228 
229 /* Fragment Shader for GeometryShaderMaxInputComponentsTest */
230 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_fragment_shader_code =
231 	"${VERSION}\n"
232 	"${GEOMETRY_SHADER_REQUIRE}\n"
233 	"precision mediump float;\n"
234 	"out vec4 fs_out_color;\n"
235 	"void main()\n"
236 	"{\n"
237 	"    fs_out_color = vec4(1, 1, 1, 1);\n"
238 	"}\n";
239 
240 /** **************************************************************************************************/
241 /* Common shader parts for GeometryShaderMaxOutputComponentsTest */
242 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_common_shader_code_gs_fs_out = "gs_fs_out_";
243 
244 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_common_shader_code_number_of_points =
245 	"#define NUMBER_OF_POINTS ";
246 
247 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_common_shader_code_gs_fs_out_definitions =
248 	"// definitions of gs_fs_out_ varyings go here\n";
249 
250 /* Vertex Shader for GeometryShaderMaxOutputComponentsTest */
251 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_vertex_shader_code =
252 	"${VERSION}\n"
253 	"\n"
254 	"${GEOMETRY_SHADER_REQUIRE}\n"
255 	"\n"
256 	"void main()\n"
257 	"{\n"
258 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
259 	"}\n";
260 
261 /* Geometry Shader Parts for GeometryShaderMaxOutputComponentsTest */
262 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_preamble =
263 	"${VERSION}\n"
264 	"\n"
265 	"${GEOMETRY_SHADER_REQUIRE}\n"
266 	"${GEOMETRY_POINT_SIZE_ENABLE}\n"
267 	"\n"
268 	"// definition of NUMBER_OF_POINTS goes here\n";
269 
270 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_layout =
271 	"u\n"
272 	"\n"
273 	"layout(points)                                in;\n"
274 	"layout(points, max_vertices=NUMBER_OF_POINTS) out;\n"
275 	"\n";
276 
277 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_flat_out_ivec4 =
278 	"flat out ivec4";
279 
280 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_assignment =
281 	" = ivec4(index++, index++, index++, index++);\n";
282 
283 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_body_begin =
284 	"\n"
285 	"void main()\n"
286 	"{\n"
287 	"    int index = 1;\n"
288 	"\n"
289 	"    for (uint point = 0u; point < NUMBER_OF_POINTS; ++point)\n"
290 	"    {\n"
291 	"        // gs_fs_out assignments go here\n";
292 
293 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_geometry_shader_code_body_end =
294 	"\n"
295 	"        gl_PointSize = 2.0;\n"
296 	"        gl_Position = vec4(-1.0 + ((2.0 / float(NUMBER_OF_POINTS)) * float(point)) + (1.0 / "
297 	"float(NUMBER_OF_POINTS)), 0.0, 0.0, 1.0);\n"
298 	"\n"
299 	"        EmitVertex();\n"
300 	"        EndPrimitive();\n"
301 	"    }\n"
302 	"}\n";
303 
304 /* Fragment Shader for GeometryShaderMaxOutputComponentsTest */
305 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_fragment_shader_code_preamble =
306 	"${VERSION}\n"
307 	"\n"
308 	"${GEOMETRY_SHADER_REQUIRE}\n"
309 	"precision highp int;\n"
310 	"\n";
311 
312 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_fragment_shader_code_flat_in_ivec4 = "flat in ivec4";
313 
314 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_fragment_shader_code_sum = "sum += ";
315 
316 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_fragment_shader_code_body_begin =
317 	"\n"
318 	"layout(location = 0) out int fs_out;\n"
319 	"\n"
320 	"void main()\n"
321 	"{\n"
322 	"    int sum = 0;\n"
323 	"\n"
324 	"    // sum calculation go here\n";
325 
326 const glw::GLchar* const GeometryShaderMaxOutputComponentsTest::m_fragment_shader_code_body_end = "\n"
327 																								  "    fs_out = sum;\n"
328 																								  "}\n";
329 
330 /** ******************************************************************************************* **/
331 /* Vertex Shader for GeometryShaderMaxOutputVerticesTest */
332 const glw::GLchar* const GeometryShaderMaxOutputVerticesTest::m_vertex_shader_code =
333 	"${VERSION}\n"
334 	"\n"
335 	"${GEOMETRY_SHADER_REQUIRE}\n"
336 	"\n"
337 	"void main()\n"
338 	"{\n"
339 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
340 	"}\n";
341 
342 /* Geometry Shader for GeometryShaderMaxOutputVerticesTest */
343 const glw::GLchar* const GeometryShaderMaxOutputVerticesTest::m_geometry_shader_code_preamble =
344 	"${VERSION}\n"
345 	"\n"
346 	"${GEOMETRY_SHADER_REQUIRE}\n"
347 	"\n"
348 	"// definition of NUMBER_OF_POINTS goes here\n"
349 	"#define NUMBER_OF_POINTS ";
350 
351 const glw::GLchar* const GeometryShaderMaxOutputVerticesTest::m_geometry_shader_code_body =
352 	"u\n"
353 	"\n"
354 	"layout(points)                                in;\n"
355 	"layout(points, max_vertices=NUMBER_OF_POINTS) out;\n"
356 	"\n"
357 	"void main()\n"
358 	"{\n"
359 	"    int index = 0;\n"
360 	"\n"
361 	"    for (uint point = 0u; point < NUMBER_OF_POINTS; ++point)\n"
362 	"    {\n"
363 	"        EmitVertex();\n"
364 	"        EndPrimitive();\n"
365 	"    }\n"
366 	"\n"
367 	"}\n";
368 
369 /* Fragment Shader for GeometryShaderMaxOutputVerticesTest */
370 const glw::GLchar* const GeometryShaderMaxOutputVerticesTest::m_fragment_shader_code =
371 	"${VERSION}\n"
372 	"\n"
373 	"${GEOMETRY_SHADER_REQUIRE}\n"
374 	"\n"
375 	"precision highp float;\n"
376 	"\n"
377 	"layout(location = 0) out vec4 fs_out;\n"
378 	"\n"
379 	"void main()\n"
380 	"{\n"
381 	"    fs_out = vec4(1, 1, 1, 1);\n"
382 	"}\n";
383 
384 /** ***************************************************************************************************************** **/
385 /* Common shader parts for GeometryShaderMaxOutputComponentsSinglePointTest */
386 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_common_shader_code_gs_fs_out =
387 	"gs_fs_out_";
388 
389 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_common_shader_code_gs_fs_out_definitions =
390 	"// definitions of gs_fs_out_ varyings go here\n";
391 
392 /* Vertex Shader for GeometryShaderMaxOutputComponentsSinglePointTest */
393 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_vertex_shader_code =
394 	"${VERSION}\n"
395 	"\n"
396 	"${GEOMETRY_SHADER_REQUIRE}\n"
397 	"\n"
398 	"void main()\n"
399 	"{\n"
400 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
401 	"}\n";
402 
403 /* Geometry Shader Parts for GeometryShaderMaxOutputComponentsSinglePointTest */
404 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_geometry_shader_code_preamble =
405 	"${VERSION}\n"
406 	"\n"
407 	"${GEOMETRY_SHADER_REQUIRE}\n"
408 	"${GEOMETRY_POINT_SIZE_ENABLE}\n"
409 	"\n"
410 	"layout(points)                 in;\n"
411 	"layout(points, max_vertices=1) out;\n"
412 	"\n";
413 
414 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_geometry_shader_code_flat_out_ivec4 =
415 	"flat out ivec4";
416 
417 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_geometry_shader_code_assignment =
418 	" = ivec4(index++, index++, index++, index++);\n";
419 
420 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_geometry_shader_code_body_begin =
421 	"\n"
422 	"void main()\n"
423 	"{\n"
424 	"    int index = 1;\n"
425 	"\n"
426 	"    // gs_fs_out assignments go here\n";
427 
428 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_geometry_shader_code_body_end =
429 	"\n"
430 	"    gl_PointSize = 2.0;\n"
431 	"    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
432 	"\n"
433 	"    EmitVertex();\n"
434 	"    EndPrimitive();\n"
435 	"}\n";
436 
437 /* Fragment Shader for GeometryShaderMaxOutputComponentsSinglePointTest */
438 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_fragment_shader_code_preamble =
439 	"${VERSION}\n"
440 	"\n"
441 	"${GEOMETRY_SHADER_REQUIRE}\n"
442 	"\n";
443 
444 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_fragment_shader_code_flat_in_ivec4 =
445 	"flat in ivec4";
446 
447 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_fragment_shader_code_sum = "sum += ";
448 
449 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_fragment_shader_code_body_begin =
450 	"\n"
451 	"layout(location = 0) out int fs_out;\n"
452 	"\n"
453 	"void main()\n"
454 	"{\n"
455 	"    int sum = 0;\n"
456 	"\n"
457 	"    // sum calculation go here\n";
458 
459 const glw::GLchar* const GeometryShaderMaxOutputComponentsSinglePointTest::m_fragment_shader_code_body_end =
460 	"\n"
461 	"    fs_out = sum;\n"
462 	"}\n";
463 
464 /** ******************************************************************************************************************** **/
465 /* Vertex Shader for GeometryShaderMaxTextureUnitsTest */
466 const glw::GLchar* const GeometryShaderMaxTextureUnitsTest::m_vertex_shader_code_preamble =
467 	"${VERSION}\n"
468 	"\n"
469 	"${GEOMETRY_SHADER_REQUIRE}\n"
470 	"\n"
471 	"precision highp float;\n"
472 	"\n"
473 	"#define NUMBER_OF_POINTS ";
474 
475 const glw::GLchar* const GeometryShaderMaxTextureUnitsTest::m_vertex_shader_code_body =
476 	"u\n"
477 	"\n"
478 	"flat out int vs_gs_vertex_id;\n"
479 	"\n"
480 	"void main()\n"
481 	"{\n"
482 	"    gl_Position     = vec4(-1.0 + ((2.0 / float(NUMBER_OF_POINTS)) * float(gl_VertexID)) + (1.0 / "
483 	"float(NUMBER_OF_POINTS)), 0, 0, 1.0);\n"
484 	"    vs_gs_vertex_id = gl_VertexID;\n"
485 	"}\n";
486 
487 /* Geometry Shader for GeometryShaderMaxTextureUnitsTest */
488 const glw::GLchar* const GeometryShaderMaxTextureUnitsTest::m_geometry_shader_code_preamble =
489 	"${VERSION}\n"
490 	"\n"
491 	"${GEOMETRY_SHADER_REQUIRE}\n"
492 	"${GEOMETRY_POINT_SIZE_ENABLE}\n"
493 	"${GPU_SHADER5_REQUIRE}\n"
494 	"\n"
495 	"precision highp float;\n"
496 	"\n"
497 	"layout(points)                           in;\n"
498 	"layout(triangle_strip, max_vertices = 4) out;\n"
499 	"\n"
500 	"#define NUMBER_OF_POINTS ";
501 
502 const glw::GLchar* const GeometryShaderMaxTextureUnitsTest::m_geometry_shader_code_body =
503 	"u\n"
504 	"\n"
505 	"// NUMBER_OF_POINTS == NUMBER_OF_SAMPLERS\n"
506 	"     uniform lowp isampler2D gs_texture[NUMBER_OF_POINTS];\n"
507 	"flat in      int        vs_gs_vertex_id[1];\n"
508 	"flat out     int        gs_fs_color;\n"
509 	"\n"
510 	"void main()\n"
511 	"{\n"
512 	"    float half_of_edge = (1.0 / float(NUMBER_OF_POINTS));\n"
513 	"    int   color        = 0;\n"
514 	"\n"
515 	"    for (uint i = 0u; i <= uint(vs_gs_vertex_id[0]); ++i)\n"
516 	"    {\n"
517 	"        color += texture(gs_texture[i], vec2(0.0, 0.0)).r;\n"
518 	"    }\n"
519 	"\n"
520 	"    gl_Position = gl_in[0].gl_Position + vec4(-half_of_edge,  1.0, 0, 0);\n"
521 	"    gs_fs_color = color;\n"
522 	"    EmitVertex();\n"
523 	"\n"
524 	"    gl_Position = gl_in[0].gl_Position + vec4( half_of_edge,  1.0, 0, 0);\n"
525 	"    gs_fs_color = color;\n"
526 	"    EmitVertex();\n"
527 	"\n"
528 	"    gl_Position = gl_in[0].gl_Position + vec4(-half_of_edge, -1.0, 0, 0);\n"
529 	"    gs_fs_color = color;\n"
530 	"    EmitVertex();\n"
531 	"\n"
532 	"    gl_Position = gl_in[0].gl_Position + vec4( half_of_edge, -1.0, 0, 0);\n"
533 	"    gs_fs_color = color;\n"
534 	"    EmitVertex();\n"
535 	"    EndPrimitive();\n"
536 	"}\n";
537 
538 /* Fragment Shader for GeometryShaderMaxTextureUnitsTest */
539 const glw::GLchar* const GeometryShaderMaxTextureUnitsTest::m_fragment_shader_code =
540 	"${VERSION}\n"
541 	"\n"
542 	"${GEOMETRY_SHADER_REQUIRE}\n"
543 	"\n"
544 	"precision highp float;\n"
545 	"\n"
546 	"flat                 in  int gs_fs_color;\n"
547 	"layout(location = 0) out int fs_out_color;\n"
548 	"\n"
549 	"void main()\n"
550 	"{\n"
551 	"    fs_out_color = gs_fs_color;\n"
552 	"}\n";
553 
554 /** *******************************************************************************************************/
555 /* Vertex Shader for GeometryShaderMaxInvocationsTest */
556 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_vertex_shader_code =
557 	"${VERSION}\n"
558 	"\n"
559 	"${GEOMETRY_SHADER_REQUIRE}\n"
560 	"\n"
561 	"precision highp float;\n"
562 	"\n"
563 	"void main()\n"
564 	"{\n"
565 	"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
566 	"}\n";
567 
568 /* Geometry Shader for GeometryShaderMaxInvocationsTest */
569 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_geometry_shader_code_preamble =
570 	"${VERSION}\n"
571 	"\n"
572 	"${GEOMETRY_SHADER_REQUIRE}\n"
573 	"\n"
574 	"precision highp float;\n"
575 	"\n"
576 	"#define GEOMETRY_SHADER_INVOCATIONS ";
577 
578 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_geometry_shader_code_layout =
579 	"u\n"
580 	"\n"
581 	"layout(points) in;\n"
582 	"layout(triangle_strip, max_vertices = 3) out;\n";
583 
584 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_geometry_shader_code_layout_invocations =
585 	"layout(invocations = GEOMETRY_SHADER_INVOCATIONS) in;\n";
586 
587 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_geometry_shader_code_body =
588 	"\n"
589 	"void main()\n"
590 	"{\n"
591 	"    float dx = (2.0 / float(GEOMETRY_SHADER_INVOCATIONS));\n"
592 	"    \n"
593 	"    gl_Position = vec4(-1.0 + (dx * float(gl_InvocationID)),      -1.001, 0.0, 1.0);\n"
594 	"    EmitVertex();\n"
595 	"    \n"
596 	"    gl_Position = vec4(-1.0 + (dx * float(gl_InvocationID)),       1.001, 0.0, 1.0);\n"
597 	"    EmitVertex();\n"
598 	"    \n"
599 	"    gl_Position = vec4(-1.0 + (dx * float(gl_InvocationID + 1)),   1.001, 0.0, 1.0);\n"
600 	"    EmitVertex();\n"
601 	"}\n";
602 
603 /* Fragment Shader for GeometryShaderMaxInvocationsTest */
604 const glw::GLchar* const GeometryShaderMaxInvocationsTest::m_fragment_shader_code =
605 	"${VERSION}\n"
606 	"\n"
607 	"${GEOMETRY_SHADER_REQUIRE}\n"
608 	"\n"
609 	"precision highp float;\n"
610 	"\n"
611 	"layout(location = 0) out vec4 fs_out_color;\n"
612 	"\n"
613 	"void main()\n"
614 	"{\n"
615 	"    fs_out_color = vec4(0.0, 1.0, 0.0, 0.0);\n"
616 	"}\n";
617 
618 /** ***************************************************************************************************** **/
619 /* Vertex Shader for GeometryShaderMaxCombinedTextureUnitsTest */
620 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_vertex_shader_code_preamble =
621 	"${VERSION}\n"
622 	"\n"
623 	"${GEOMETRY_SHADER_REQUIRE}\n"
624 	"${GPU_SHADER5_ENABLE}\n"
625 	"\n"
626 	"precision highp float;\n"
627 	"\n"
628 	"#define NUMBER_OF_POINTS ";
629 
630 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_vertex_shader_code_body =
631 	"u\n"
632 	"\n"
633 	"// NUMBER_OF_POINTS == NUMBER_OF_SAMPLERS\n"
634 	"     uniform highp usampler2D sampler[NUMBER_OF_POINTS];"
635 	"flat out     int        vs_gs_vertex_id;\n"
636 	"flat out     uint       vs_gs_sum;\n"
637 	"\n"
638 	"void main()\n"
639 	"{\n"
640 	"    uint sum = 0u;\n"
641 	"\n"
642 	"    for (uint i = 0u; i < uint(gl_VertexID); ++i)\n"
643 	"    {\n"
644 	"        sum += texture(sampler[i], vec2(0.0, 0.0)).r;\n"
645 	"    }\n"
646 	"\n"
647 	"    gl_Position     = vec4(-1.0 + ((2.0 / float(NUMBER_OF_POINTS)) * float(gl_VertexID)) + (1.0 / "
648 	"float(NUMBER_OF_POINTS)), 0, 0, 1.0);\n"
649 	"    vs_gs_vertex_id = gl_VertexID;\n"
650 	"    vs_gs_sum       = sum;\n"
651 	"}\n";
652 
653 /* Geometry Shader for GeometryShaderMaxCombinedTextureUnitsTest */
654 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_geometry_shader_code_preamble =
655 	"${VERSION}\n"
656 	"\n"
657 	"${GEOMETRY_SHADER_REQUIRE}\n"
658 	"${GPU_SHADER5_ENABLE}\n"
659 	"\n"
660 	"precision highp float;\n"
661 	"\n"
662 	"layout(points)                   in;\n"
663 	"layout(points, max_vertices = 1) out;\n"
664 	"\n"
665 	"#define NUMBER_OF_POINTS ";
666 
667 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_geometry_shader_code_body =
668 	"u\n"
669 	"\n"
670 	"// NUMBER_OF_POINTS == NUMBER_OF_SAMPLERS\n"
671 	"     uniform highp usampler2D sampler[NUMBER_OF_POINTS];\n"
672 	"flat in      int        vs_gs_vertex_id[1];\n"
673 	"flat in      uint       vs_gs_sum      [1];\n"
674 	"flat out     int        gs_fs_vertex_id;\n"
675 	"flat out     uint       gs_fs_vertex_sum;\n"
676 	"flat out     uint       gs_fs_geometry_sum;\n"
677 	"\n"
678 	"void main()\n"
679 	"{\n"
680 	"    uint sum = 0u;\n"
681 	"\n"
682 	"    for (uint i = 0u; i < uint(vs_gs_vertex_id[0]); ++i)\n"
683 	"    {\n"
684 	"        sum += texture(sampler[i], vec2(0.0, 0.0)).r;\n"
685 	"    }\n"
686 	"\n"
687 	"    gl_Position        = gl_in[0].gl_Position;\n"
688 	"    gs_fs_vertex_id    = vs_gs_vertex_id[0];\n"
689 	"    gs_fs_vertex_sum   = vs_gs_sum      [0];\n"
690 	"    gs_fs_geometry_sum = sum;\n"
691 	"    EmitVertex();\n"
692 	"    EndPrimitive();\n"
693 	"}\n";
694 
695 /* Fragment Shader for GeometryShaderMaxCombinedTextureUnitsTest */
696 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_fragment_shader_code_preamble =
697 	"${VERSION}\n"
698 	"\n"
699 	"${GEOMETRY_SHADER_REQUIRE}\n"
700 	"${GPU_SHADER5_ENABLE}\n"
701 	"\n"
702 	"precision highp float;\n"
703 	"\n"
704 	"// NUMBER_OF_POINTS == NUMBER_OF_SAMPLERS\n"
705 	"#define NUMBER_OF_POINTS ";
706 
707 const glw::GLchar* const GeometryShaderMaxCombinedTextureUnitsTest::m_fragment_shader_code_body =
708 	"u\n"
709 	"\n"
710 	"                     uniform highp usampler2D sampler[NUMBER_OF_POINTS];\n"
711 	"flat                 in      int        gs_fs_vertex_id;\n"
712 	"flat                 in      uint       gs_fs_vertex_sum;\n"
713 	"flat                 in      uint       gs_fs_geometry_sum;\n"
714 	"layout(location = 0) out     uint       fs_out_color;\n"
715 	"\n"
716 	"void main()\n"
717 	"{\n"
718 	"    uint sum = 0u;\n"
719 	"\n"
720 	"    for (uint i = 0u; i < uint(gs_fs_vertex_id); ++i)\n"
721 	"    {\n"
722 	"        sum += texture(sampler[i], vec2(0.0, 0.0)).r;\n"
723 	"    }\n"
724 	"    fs_out_color = sum + gs_fs_vertex_sum + gs_fs_geometry_sum;\n"
725 	"}\n";
726 
727 /** ***************************************************************************************************************** **/
728 
729 /* Constants for GeometryShaderMaxUniformComponentsTest */
730 const unsigned int		 GeometryShaderMaxUniformComponentsTest::m_buffer_size			   = sizeof(glw::GLint);
731 const glw::GLchar* const GeometryShaderMaxUniformComponentsTest::m_captured_varyings_names = "gs_out_sum";
732 
733 /* Constants for GeometryShaderMaxUniformBlocksTest */
734 const unsigned int		 GeometryShaderMaxUniformBlocksTest::m_buffer_size			   = sizeof(glw::GLint);
735 const glw::GLchar* const GeometryShaderMaxUniformBlocksTest::m_captured_varyings_names = "gs_out_sum";
736 
737 /* Constants for GeometryShaderMaxInputComponentsTest */
738 const unsigned int		 GeometryShaderMaxInputComponentsTest::m_buffer_size			 = sizeof(glw::GLint);
739 const glw::GLchar* const GeometryShaderMaxInputComponentsTest::m_captured_varyings_names = "gs_out_sum";
740 
741 /* Constants for GeometryShaderMaxOutputComponentsTest */
742 const unsigned int GeometryShaderMaxOutputComponentsTest::m_point_size		   = 2;
743 const unsigned int GeometryShaderMaxOutputComponentsTest::m_texture_height	 = m_point_size;
744 const unsigned int GeometryShaderMaxOutputComponentsTest::m_texture_pixel_size = 4 * sizeof(glw::GLint);
745 
746 /* Constants for GeometryShaderMaxOutputComponentsSinglePointTest */
747 const unsigned int GeometryShaderMaxOutputComponentsSinglePointTest::m_point_size		  = 2;
748 const unsigned int GeometryShaderMaxOutputComponentsSinglePointTest::m_texture_height	 = m_point_size;
749 const unsigned int GeometryShaderMaxOutputComponentsSinglePointTest::m_texture_pixel_size = 4 * sizeof(glw::GLint);
750 const unsigned int GeometryShaderMaxOutputComponentsSinglePointTest::m_texture_width	  = m_point_size;
751 
752 /* Constants for GeometryShaderMaxTextureUnitsTest */
753 const unsigned int GeometryShaderMaxTextureUnitsTest::m_point_size		   = 2;
754 const unsigned int GeometryShaderMaxTextureUnitsTest::m_texture_height	 = m_point_size;
755 const unsigned int GeometryShaderMaxTextureUnitsTest::m_texture_pixel_size = 4 * sizeof(glw::GLint);
756 
757 /* Constants for GeometryShaderMaxInvocationsTest */
758 const unsigned int GeometryShaderMaxInvocationsTest::m_triangle_edge_length = 9;
759 const unsigned int GeometryShaderMaxInvocationsTest::m_texture_height		= m_triangle_edge_length;
760 const unsigned int GeometryShaderMaxInvocationsTest::m_texture_pixel_size   = 4 * sizeof(glw::GLubyte);
761 
762 /* Constants for GeometryShaderMaxCombinedTextureUnitsTest */
763 const unsigned int GeometryShaderMaxCombinedTextureUnitsTest::m_point_size		   = 1;
764 const unsigned int GeometryShaderMaxCombinedTextureUnitsTest::m_texture_height	 = m_point_size;
765 const unsigned int GeometryShaderMaxCombinedTextureUnitsTest::m_texture_pixel_size = 4 * sizeof(glw::GLint);
766 
767 /** Constructor
768  *
769  *  @param context     Test context
770  *  @param name        Test case's name
771  *  @param description Test case's description
772  **/
GeometryShaderLimitsTransformFeedbackBase(Context & context,const ExtParameters & extParams,const char * name,const char * description)773 GeometryShaderLimitsTransformFeedbackBase::GeometryShaderLimitsTransformFeedbackBase(Context&			  context,
774 																					 const ExtParameters& extParams,
775 																					 const char*		  name,
776 																					 const char*		  description)
777 	: TestCaseBase(context, extParams, name, description)
778 	, m_fragment_shader_id(0)
779 	, m_geometry_shader_id(0)
780 	, m_program_object_id(0)
781 	, m_vertex_shader_id(0)
782 	, m_buffer_object_id(0)
783 	, m_vertex_array_object_id(0)
784 	, m_fragment_shader_parts(0)
785 	, m_geometry_shader_parts(0)
786 	, m_vertex_shader_parts(0)
787 	, m_n_fragment_shader_parts(0)
788 	, m_n_geometry_shader_parts(0)
789 	, m_n_vertex_shader_parts(0)
790 	, m_captured_varyings_names(0)
791 	, m_n_captured_varyings(0)
792 	, m_buffer_size(0)
793 {
794 	/* Nothing to be done here */
795 }
796 
797 /** Initializes GLES objects used during the test.
798  *
799  */
initTest()800 void GeometryShaderLimitsTransformFeedbackBase::initTest()
801 {
802 	/* This test should only run if EXT_geometry_shader is supported */
803 	if (!m_is_geometry_shader_extension_supported)
804 	{
805 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
806 	}
807 
808 	/* Retrieve ES entrypoints */
809 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
810 
811 	/* Get shaders code from child class */
812 	getShaderParts(m_fragment_shader_parts, m_n_fragment_shader_parts, m_geometry_shader_parts,
813 				   m_n_geometry_shader_parts, m_vertex_shader_parts, m_n_vertex_shader_parts);
814 
815 	/* Get captured varyings from inheriting class */
816 	getCapturedVaryings(m_captured_varyings_names, m_n_captured_varyings);
817 
818 	/* Create program and shaders */
819 	m_program_object_id = gl.createProgram();
820 
821 	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
822 	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
823 	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
824 
825 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program or shader object(s)");
826 
827 	/* Set up transform feedback */
828 	gl.transformFeedbackVaryings(m_program_object_id, m_n_captured_varyings, m_captured_varyings_names,
829 								 GL_INTERLEAVED_ATTRIBS);
830 
831 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set transform feedback varyings");
832 
833 	/* Build program */
834 	if (false == buildProgram(m_program_object_id, m_fragment_shader_id, m_n_fragment_shader_parts,
835 							  m_fragment_shader_parts, m_geometry_shader_id, m_n_geometry_shader_parts,
836 							  m_geometry_shader_parts, m_vertex_shader_id, m_n_vertex_shader_parts,
837 							  m_vertex_shader_parts))
838 	{
839 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
840 	}
841 
842 	/* Generate and bind VAO */
843 	gl.genVertexArrays(1, &m_vertex_array_object_id);
844 	gl.bindVertexArray(m_vertex_array_object_id);
845 
846 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
847 
848 	/* Get size of buffer used by transform feedback from child class */
849 	getTransformFeedbackBufferSize(m_buffer_size);
850 
851 	/* Generate, bind and allocate buffer */
852 	gl.genBuffers(1, &m_buffer_object_id);
853 	gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
854 	gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_COPY);
855 
856 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
857 }
858 
859 /** Executes the test.
860  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
861  *
862  *  Note the function throws exception should an error occur!
863  *
864  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
865  *
866  **/
iterate()867 tcu::TestCase::IterateResult GeometryShaderLimitsTransformFeedbackBase::iterate()
868 {
869 	initTest();
870 
871 	/* Retrieve ES entrypoints */
872 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
873 
874 	/* Verification result */
875 	bool result = false;
876 
877 	/* Setup transform feedback */
878 	gl.enable(GL_RASTERIZER_DISCARD);
879 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(GL_RASTERIZER_DISCARD) call failed");
880 
881 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
882 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
883 
884 	/* Setup draw call */
885 	gl.useProgram(m_program_object_id);
886 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
887 
888 	gl.beginTransformFeedback(GL_POINTS);
889 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed");
890 	{
891 		/* Let child class prepare input data */
892 		prepareProgramInput();
893 
894 		/* Draw */
895 		gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* one point */);
896 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
897 	}
898 	/* Stop transform feedback */
899 	gl.endTransformFeedback();
900 	GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed");
901 
902 	/* Map transfrom feedback results */
903 	const void* transform_feedback_data =
904 		gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, m_buffer_size, GL_MAP_READ_BIT);
905 
906 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
907 
908 	/* Verify data extracted from transfrom feedback */
909 	result = verifyResult(transform_feedback_data);
910 
911 	/* Unmap transform feedback buffer */
912 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
913 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
914 
915 	/* Let child class clean itself */
916 	clean();
917 
918 	/* Verify results */
919 	if (true != result)
920 	{
921 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
922 	}
923 	else
924 	{
925 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
926 	}
927 
928 	return STOP;
929 }
930 
931 /** Deinitializes GLES objects created during the test.
932  *
933  */
deinit()934 void GeometryShaderLimitsTransformFeedbackBase::deinit()
935 {
936 	/* Retrieve ES entrypoints */
937 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
938 
939 	/* Bind default values */
940 	gl.useProgram(0);
941 	gl.bindVertexArray(0);
942 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
943 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
944 
945 	/* Delete program object and shaders */
946 	if (0 != m_program_object_id)
947 	{
948 		gl.deleteProgram(m_program_object_id);
949 
950 		m_program_object_id = 0;
951 	}
952 
953 	if (0 != m_fragment_shader_id)
954 	{
955 		gl.deleteShader(m_fragment_shader_id);
956 
957 		m_fragment_shader_id = 0;
958 	}
959 
960 	if (0 != m_geometry_shader_id)
961 	{
962 		gl.deleteShader(m_geometry_shader_id);
963 
964 		m_geometry_shader_id = 0;
965 	}
966 
967 	if (0 != m_vertex_shader_id)
968 	{
969 		gl.deleteShader(m_vertex_shader_id);
970 
971 		m_vertex_shader_id = 0;
972 	}
973 
974 	/* Delete buffer objects */
975 	if (0 != m_buffer_object_id)
976 	{
977 		gl.deleteBuffers(1, &m_buffer_object_id);
978 
979 		m_buffer_object_id = 0;
980 	}
981 
982 	if (0 != m_vertex_array_object_id)
983 	{
984 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
985 
986 		m_vertex_array_object_id = 0;
987 	}
988 
989 	/* Deinitialize base class */
990 	TestCaseBase::deinit();
991 }
992 
993 /** Constructor
994  *
995  * @param context       Test context
996  * @param name          Test case's name
997  * @param description   Test case's description
998  **/
GeometryShaderLimitsRenderingBase(Context & context,const ExtParameters & extParams,const char * name,const char * description)999 GeometryShaderLimitsRenderingBase::GeometryShaderLimitsRenderingBase(Context& context, const ExtParameters& extParams,
1000 																	 const char* name, const char* description)
1001 	: TestCaseBase(context, extParams, name, description)
1002 	, m_fragment_shader_id(0)
1003 	, m_geometry_shader_id(0)
1004 	, m_program_object_id(0)
1005 	, m_vertex_shader_id(0)
1006 	, m_framebuffer_object_id(0)
1007 	, m_color_texture_id(0)
1008 	, m_vertex_array_object_id(0)
1009 	, m_fragment_shader_parts(0)
1010 	, m_geometry_shader_parts(0)
1011 	, m_vertex_shader_parts(0)
1012 	, m_n_fragment_shader_parts(0)
1013 	, m_n_geometry_shader_parts(0)
1014 	, m_n_vertex_shader_parts(0)
1015 	, m_texture_format(GL_RGBA8)
1016 	, m_texture_height(0)
1017 	, m_texture_pixel_size(0)
1018 	, m_texture_read_format(GL_RGBA)
1019 	, m_texture_read_type(GL_UNSIGNED_BYTE)
1020 	, m_texture_width(0)
1021 {
1022 	/* Nothing to be done here */
1023 }
1024 
1025 /** Initializes GLES objects used during the test.
1026  *
1027  */
initTest()1028 void GeometryShaderLimitsRenderingBase::initTest()
1029 {
1030 	/* This test should only run if EXT_geometry_shader is supported */
1031 	if (!m_is_geometry_shader_extension_supported)
1032 	{
1033 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1034 	}
1035 
1036 	/* Query on support of EXT_gpu_shader5 */
1037 	if (!m_is_gpu_shader5_supported)
1038 	{
1039 		throw tcu::NotSupportedError(GPU_SHADER5_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1040 	}
1041 
1042 	/* Retrieve ES entry-points */
1043 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1044 
1045 	/* Verify that point size range is supported */
1046 	glw::GLfloat point_size_range[2] = { 0 };
1047 	glw::GLfloat required_point_size = 0.0f;
1048 
1049 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1050 	{
1051 		gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
1052 	}
1053 	else
1054 	{
1055 		gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
1056 	}
1057 
1058 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() call failed");
1059 
1060 	getRequiredPointSize(required_point_size);
1061 
1062 	if (required_point_size > point_size_range[1])
1063 	{
1064 		m_testCtx.getLog() << tcu::TestLog::Message
1065 						   << "Test requires a minimum maximum point size of: " << required_point_size
1066 						   << ", implementation reports a maximum of : " << point_size_range[1]
1067 						   << tcu::TestLog::EndMessage;
1068 
1069 		throw tcu::NotSupportedError("Required point size is not supported", "", __FILE__, __LINE__);
1070 	}
1071 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1072 	{
1073 		gl.enable(GL_PROGRAM_POINT_SIZE);
1074 	}
1075 
1076 	/* Get shaders code from child class */
1077 	getShaderParts(m_fragment_shader_parts, m_n_fragment_shader_parts, m_geometry_shader_parts,
1078 				   m_n_geometry_shader_parts, m_vertex_shader_parts, m_n_vertex_shader_parts);
1079 
1080 	/* Create program and shaders */
1081 	m_program_object_id = gl.createProgram();
1082 
1083 	m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1084 	m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1085 	m_vertex_shader_id   = gl.createShader(GL_VERTEX_SHADER);
1086 
1087 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program or shader object(s)");
1088 
1089 	/* Build program */
1090 	if (false == buildProgram(m_program_object_id, m_fragment_shader_id, m_n_fragment_shader_parts,
1091 							  m_fragment_shader_parts, m_geometry_shader_id, m_n_geometry_shader_parts,
1092 							  m_geometry_shader_parts, m_vertex_shader_id, m_n_vertex_shader_parts,
1093 							  m_vertex_shader_parts))
1094 	{
1095 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
1096 	}
1097 
1098 	/* Set up a vertex array object */
1099 	gl.genVertexArrays(1, &m_vertex_array_object_id);
1100 	gl.bindVertexArray(m_vertex_array_object_id);
1101 
1102 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
1103 
1104 	/* Get framebuffer details */
1105 	getFramebufferDetails(m_texture_format, m_texture_read_format, m_texture_read_type, m_texture_width,
1106 						  m_texture_height, m_texture_pixel_size);
1107 
1108 	/* Set up texture object and a FBO */
1109 	gl.genTextures(1, &m_color_texture_id);
1110 	gl.genFramebuffers(1, &m_framebuffer_object_id);
1111 
1112 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
1113 
1114 	if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, m_texture_format,
1115 														 m_texture_width, m_texture_height))
1116 	{
1117 		TCU_FAIL("Failed to setup framebuffer");
1118 	}
1119 }
1120 
1121 /** Executes the test.
1122  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1123  *
1124  *  Note the function throws exception should an error occur!
1125  *
1126  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1127  *
1128  **/
iterate()1129 tcu::TestCase::IterateResult GeometryShaderLimitsRenderingBase::iterate()
1130 {
1131 	initTest();
1132 
1133 	/* Retrieve ES entry-points */
1134 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1135 
1136 	/* Variables used for image verification purposes */
1137 	std::vector<unsigned char> result_image(m_texture_width * m_texture_height * m_texture_pixel_size);
1138 
1139 	/* Render */
1140 	gl.useProgram(m_program_object_id);
1141 
1142 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
1143 
1144 	/* Let child class prepare input for program */
1145 	prepareProgramInput();
1146 
1147 	gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1148 	gl.clear(GL_COLOR_BUFFER_BIT);
1149 
1150 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1151 
1152 	/* Get draw call details from child class */
1153 	glw::GLenum primitive_type = GL_POINTS;
1154 	glw::GLuint n_vertices	 = 1;
1155 
1156 	getDrawCallDetails(primitive_type, n_vertices);
1157 
1158 	gl.drawArrays(primitive_type, 0 /* first */, n_vertices);
1159 	GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed");
1160 
1161 	/* Extract image from FBO */
1162 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, m_texture_read_format, m_texture_read_type,
1163 				  &result_image[0]);
1164 
1165 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1166 
1167 	/* Run verification */
1168 	if (true == verifyResult(&result_image[0]))
1169 	{
1170 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1171 	}
1172 	else
1173 	{
1174 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1175 	}
1176 
1177 	/* Let child class clean itself */
1178 	clean();
1179 
1180 	return STOP;
1181 }
1182 
1183 /** Deinitializes GLES objects created during the test.
1184  *
1185  */
deinit()1186 void GeometryShaderLimitsRenderingBase::deinit()
1187 {
1188 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1189 
1190 	/* Reset OpenGL ES state */
1191 	gl.useProgram(0);
1192 	gl.bindVertexArray(0);
1193 	gl.bindTexture(GL_TEXTURE_2D, 0);
1194 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1195 	if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1196 	{
1197 		gl.disable(GL_PROGRAM_POINT_SIZE);
1198 	}
1199 
1200 	/* Delete program object and shaders */
1201 	if (m_program_object_id != 0)
1202 	{
1203 		gl.deleteProgram(m_program_object_id);
1204 
1205 		m_program_object_id = 0;
1206 	}
1207 
1208 	if (m_fragment_shader_id != 0)
1209 	{
1210 		gl.deleteShader(m_fragment_shader_id);
1211 
1212 		m_fragment_shader_id = 0;
1213 	}
1214 
1215 	if (m_geometry_shader_id != 0)
1216 	{
1217 		gl.deleteShader(m_geometry_shader_id);
1218 
1219 		m_geometry_shader_id = 0;
1220 	}
1221 
1222 	if (m_vertex_shader_id != 0)
1223 	{
1224 		gl.deleteShader(m_vertex_shader_id);
1225 
1226 		m_vertex_shader_id = 0;
1227 	}
1228 
1229 	/* Delete frambuffer and textures */
1230 	if (m_framebuffer_object_id != 0)
1231 	{
1232 		gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1233 
1234 		m_framebuffer_object_id = 0;
1235 	}
1236 
1237 	if (m_color_texture_id != 0)
1238 	{
1239 		gl.deleteTextures(1, &m_color_texture_id);
1240 
1241 		m_color_texture_id = 0;
1242 	}
1243 
1244 	if (m_vertex_array_object_id != 0)
1245 	{
1246 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1247 
1248 		m_vertex_array_object_id = 0;
1249 	}
1250 
1251 	/* Deinitialize base class */
1252 	TestCaseBase::deinit();
1253 }
1254 
1255 /** Constructor
1256  *
1257  *  @param context       Test context
1258  *  @param name          Test case's name
1259  *  @param description   Test case's description
1260  **/
GeometryShaderMaxUniformComponentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1261 GeometryShaderMaxUniformComponentsTest::GeometryShaderMaxUniformComponentsTest(Context&				context,
1262 																			   const ExtParameters& extParams,
1263 																			   const char*			name,
1264 																			   const char*			description)
1265 	: GeometryShaderLimitsTransformFeedbackBase(context, extParams, name, description)
1266 	, m_max_uniform_components(0)
1267 	, m_max_uniform_vectors(0)
1268 	, m_uniform_location(0)
1269 {
1270 	/* Nothing to be done here */
1271 }
1272 
1273 /** Clears data after draw call and result verification
1274  *
1275  **/
clean()1276 void GeometryShaderMaxUniformComponentsTest::clean()
1277 {
1278 	m_uniform_data.clear();
1279 }
1280 
1281 /** Get names and number of varyings to be captured by transform feedback
1282  *
1283  *  @param out_captured_varyings_names Array of varying names
1284  *  @param out_n_captured_varyings     Number of varying names
1285  **/
getCapturedVaryings(const glw::GLchar * const * & out_captured_varyings_names,glw::GLuint & out_n_captured_varyings)1286 void GeometryShaderMaxUniformComponentsTest::getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
1287 																 glw::GLuint&				out_n_captured_varyings)
1288 {
1289 	/* Varying names */
1290 	out_captured_varyings_names = &m_captured_varyings_names;
1291 
1292 	/* Number of varyings */
1293 	out_n_captured_varyings = 1;
1294 }
1295 
1296 /** Get parts of shaders
1297  *
1298  *  @param out_fragment_shader_parts   Array of fragment shader parts
1299  *  @param out_n_fragment_shader_parts Number of fragment shader parts
1300  *  @param out_geometry_shader_parts   Array of geometry shader parts
1301  *  @param out_n_geometry_shader_parts Number of geometry shader parts
1302  *  @param out_vertex_shader_parts     Array of vertex shader parts
1303  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
1304  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)1305 void GeometryShaderMaxUniformComponentsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
1306 															unsigned int&			   out_n_fragment_shader_parts,
1307 															const glw::GLchar* const*& out_geometry_shader_parts,
1308 															unsigned int&			   out_n_geometry_shader_parts,
1309 															const glw::GLchar* const*& out_vertex_shader_parts,
1310 															unsigned int&			   out_n_vertex_shader_parts)
1311 {
1312 	/* Retrieve ES entry-points */
1313 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1314 
1315 	/* Fragment Shader */
1316 	out_fragment_shader_parts   = &m_fragment_shader_code;
1317 	out_n_fragment_shader_parts = 1;
1318 
1319 	/* Get maximum number of uniform */
1320 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_UNIFORM_COMPONENTS, &m_max_uniform_components);
1321 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT pname.");
1322 
1323 	m_max_uniform_vectors = m_max_uniform_components / 4 /* 4 components per vector */;
1324 
1325 	std::stringstream stream;
1326 	stream << m_max_uniform_vectors;
1327 	m_max_uniform_vectors_string = stream.str();
1328 
1329 	/* Geometry Shader */
1330 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
1331 	m_geometry_shader_parts[1] = m_geometry_shader_code_number_of_uniforms;
1332 	m_geometry_shader_parts[2] = m_max_uniform_vectors_string.c_str();
1333 	m_geometry_shader_parts[3] = m_geometry_shader_code_body;
1334 
1335 	out_geometry_shader_parts   = m_geometry_shader_parts;
1336 	out_n_geometry_shader_parts = 4;
1337 
1338 	/* Vertex Shader */
1339 	out_vertex_shader_parts   = &m_vertex_shader_code;
1340 	out_n_vertex_shader_parts = 1;
1341 }
1342 
1343 /** Get size of buffer used by transform feedback
1344  *
1345  *  @param out_buffer_size Size of buffer in bytes
1346  **/
getTransformFeedbackBufferSize(unsigned int & out_buffer_size)1347 void GeometryShaderMaxUniformComponentsTest::getTransformFeedbackBufferSize(unsigned int& out_buffer_size)
1348 {
1349 	out_buffer_size = m_buffer_size;
1350 }
1351 
1352 /** Prepare test specific program input for draw call
1353  *
1354  **/
prepareProgramInput()1355 void GeometryShaderMaxUniformComponentsTest::prepareProgramInput()
1356 {
1357 	/* Retrieve ES entry-points */
1358 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1359 
1360 	/* Uniform location */
1361 	m_uniform_location = gl.getUniformLocation(m_program_object_id, "uni_array");
1362 
1363 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to get uniform location");
1364 
1365 	if (-1 == m_uniform_location)
1366 	{
1367 		TCU_FAIL("Invalid uniform location");
1368 	}
1369 
1370 	/* 3. Configure the uniforms to use subsequently increasing values, starting
1371 	 *  from 1 for R component of first vector, 2 for G component of that vector,
1372 	 *  5 for first component of second vector, and so on.
1373 	 **/
1374 	m_uniform_data.resize(m_max_uniform_components);
1375 
1376 	for (glw::GLint i = 0; i < m_max_uniform_components; ++i)
1377 	{
1378 		m_uniform_data[i] = i + 1;
1379 	}
1380 
1381 	/* Set uniform data */
1382 	gl.uniform4iv(m_uniform_location, m_max_uniform_vectors, &m_uniform_data[0]);
1383 
1384 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set uniform data");
1385 }
1386 
1387 /** Verification of results
1388  *
1389  *  @param result Pointer to data mapped from transform feedback buffer.
1390  (                Size of data is equal to buffer_size set by getTransformFeedbackBufferSize()
1391  *
1392  *  @return true  Result matches expected value
1393  *          false Result has wrong value
1394  **/
verifyResult(const void * data)1395 bool GeometryShaderMaxUniformComponentsTest::verifyResult(const void* data)
1396 {
1397 	/* Expected data, sum of elements in range <x;y> with length n = ((x + y) / 2) * n */
1398 	const glw::GLint expected_data = ((1 + m_max_uniform_components) * m_max_uniform_components) / 2;
1399 
1400 	/* Cast to const GLint */
1401 	const glw::GLint* transform_feedback_data = (const glw::GLint*)data;
1402 
1403 	/* Verify data extracted from transfrom feedback */
1404 	if (0 != memcmp(transform_feedback_data, &expected_data, m_buffer_size))
1405 	{
1406 		m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_data
1407 						   << " Extracted: " << *transform_feedback_data << tcu::TestLog::EndMessage;
1408 
1409 		return false;
1410 	}
1411 	else
1412 	{
1413 		return true;
1414 	}
1415 }
1416 
1417 /** Constructor
1418  *
1419  *  @param context       Test context
1420  *  @param name          Test case's name
1421  *  @param description   Test case's description
1422  **/
GeometryShaderMaxUniformBlocksTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1423 GeometryShaderMaxUniformBlocksTest::GeometryShaderMaxUniformBlocksTest(Context& context, const ExtParameters& extParams,
1424 																	   const char* name, const char* description)
1425 	: GeometryShaderLimitsTransformFeedbackBase(context, extParams, name, description), m_max_uniform_blocks(0)
1426 {
1427 	/* Nothing to be done here */
1428 }
1429 
1430 /** Clears data after draw call and result verification
1431  *
1432  **/
clean()1433 void GeometryShaderMaxUniformBlocksTest::clean()
1434 {
1435 	/* Retrieve ES entry-points */
1436 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1437 
1438 	/* Bind default to uniform binding point */
1439 	gl.bindBuffer(GL_UNIFORM_BUFFER, 0);
1440 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed");
1441 
1442 	/* Release buffers */
1443 	for (glw::GLint i = 0; i < m_max_uniform_blocks; ++i)
1444 	{
1445 		/* Bind default to uniform block */
1446 		gl.bindBufferBase(GL_UNIFORM_BUFFER, i, 0);
1447 		GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed");
1448 
1449 		/* Delete buffer */
1450 		gl.deleteBuffers(1, &m_uniform_blocks[i].buffer_object_id);
1451 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers() call failed");
1452 	}
1453 
1454 	/* Free memory */
1455 	m_uniform_blocks.clear();
1456 }
1457 
1458 /** Get names and number of varyings to be captured by transform feedback
1459  *
1460  *  @param out_captured_varyings_names Array of varying names
1461  *  @param out_n_captured_varyings     Number of varying names
1462  **/
getCapturedVaryings(const glw::GLchar * const * & out_captured_varyings_names,glw::GLuint & out_n_captured_varyings)1463 void GeometryShaderMaxUniformBlocksTest::getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
1464 															 glw::GLuint&				out_n_captured_varyings)
1465 {
1466 	/* Varying names */
1467 	out_captured_varyings_names = &m_captured_varyings_names;
1468 
1469 	/* Number of varyings */
1470 	out_n_captured_varyings = 1;
1471 }
1472 
1473 /** Get parts of shaders
1474  *
1475  *  @param out_fragment_shader_parts   Array of fragment shader parts
1476  *  @param out_n_fragment_shader_parts Number of fragment shader parts
1477  *  @param out_geometry_shader_parts   Array of geometry shader parts
1478  *  @param out_n_geometry_shader_parts Number of geometry shader parts
1479  *  @param out_vertex_shader_parts     Array of vertex shader parts
1480  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
1481  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)1482 void GeometryShaderMaxUniformBlocksTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
1483 														unsigned int&			   out_n_fragment_shader_parts,
1484 														const glw::GLchar* const*& out_geometry_shader_parts,
1485 														unsigned int&			   out_n_geometry_shader_parts,
1486 														const glw::GLchar* const*& out_vertex_shader_parts,
1487 														unsigned int&			   out_n_vertex_shader_parts)
1488 {
1489 	/* Retrieve ES entry-points */
1490 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1491 
1492 	/* Fragment Shader */
1493 	out_fragment_shader_parts   = &m_fragment_shader_code;
1494 	out_n_fragment_shader_parts = 1;
1495 
1496 	/* Get maximum number of uniform blocks */
1497 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_UNIFORM_BLOCKS, &m_max_uniform_blocks);
1498 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT");
1499 
1500 	std::stringstream stream;
1501 	stream << m_max_uniform_blocks;
1502 	m_max_uniform_blocks_string = stream.str();
1503 
1504 	/* Geometry Shader */
1505 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
1506 	m_geometry_shader_parts[1] = m_geometry_shader_code_number_of_uniforms;
1507 	m_geometry_shader_parts[2] = m_max_uniform_blocks_string.c_str();
1508 	m_geometry_shader_parts[3] = m_geometry_shader_code_body_str;
1509 
1510 	stream.str(std::string());
1511 	stream.clear();
1512 	for (glw::GLint uniform_block_nr = 0; uniform_block_nr < m_max_uniform_blocks; ++uniform_block_nr)
1513 	{
1514 		stream << "    gs_out_sum += uni_block_array[" << uniform_block_nr << "].entry;\n";
1515 	}
1516 	m_uniform_block_access_string = stream.str();
1517 
1518 	m_geometry_shader_parts[4] = m_uniform_block_access_string.c_str();
1519 	m_geometry_shader_parts[5] = m_geometry_shader_code_body_end;
1520 
1521 	out_geometry_shader_parts   = m_geometry_shader_parts;
1522 	out_n_geometry_shader_parts = 6;
1523 
1524 	/* Vertex Shader */
1525 	out_vertex_shader_parts   = &m_vertex_shader_code;
1526 	out_n_vertex_shader_parts = 1;
1527 }
1528 
1529 /** Get size of buffer used by transform feedback
1530  *
1531  *  @param out_buffer_size Size of buffer in bytes
1532  **/
getTransformFeedbackBufferSize(unsigned int & out_buffer_size)1533 void GeometryShaderMaxUniformBlocksTest::getTransformFeedbackBufferSize(unsigned int& out_buffer_size)
1534 {
1535 	out_buffer_size = m_buffer_size;
1536 }
1537 
1538 /** Prepare test specific program input for draw call
1539  *
1540  **/
prepareProgramInput()1541 void GeometryShaderMaxUniformBlocksTest::prepareProgramInput()
1542 {
1543 	/* Retrieve ES entry-points */
1544 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1545 
1546 	/* Allocate memory */
1547 	m_uniform_blocks.resize(m_max_uniform_blocks);
1548 
1549 	/* Setup uniform blocks */
1550 	for (glw::GLint i = 0; i < m_max_uniform_blocks; ++i)
1551 	{
1552 		/* Generate and bind */
1553 		gl.genBuffers(1, &m_uniform_blocks[i].buffer_object_id);
1554 		gl.bindBuffer(GL_UNIFORM_BUFFER, m_uniform_blocks[i].buffer_object_id);
1555 
1556 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed create buffer object");
1557 
1558 		/** Expected data is range <1;GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT>
1559 		 *  See test description for details
1560 		 **/
1561 		m_uniform_blocks[i].data = i + 1;
1562 
1563 		gl.bufferData(GL_UNIFORM_BUFFER, sizeof(glw::GLint), &m_uniform_blocks[i].data, GL_STATIC_DRAW);
1564 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set buffer data");
1565 
1566 		/* Bind buffer to uniform block */
1567 		gl.bindBufferBase(GL_UNIFORM_BUFFER, i, m_uniform_blocks[i].buffer_object_id);
1568 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to bind buffer to uniform block");
1569 	}
1570 }
1571 
1572 /** Verification of results
1573  *
1574  *  @param result Pointer to data mapped from transform feedback buffer.
1575  *                Size of data is equal to buffer_size set by getTransformFeedbackBufferSize()
1576  *
1577  *  @return true  Result match expected value
1578  *          false Result has wrong value
1579  **/
verifyResult(const void * data)1580 bool GeometryShaderMaxUniformBlocksTest::verifyResult(const void* data)
1581 {
1582 	/* Expected data, sum of elements in range <x;y> with length n = ((x + y) / 2) * n */
1583 	const glw::GLint expected_data = ((1 + m_max_uniform_blocks) * m_max_uniform_blocks) / 2;
1584 
1585 	/* Cast to const GLint */
1586 	const glw::GLint* transform_feedback_data = (const glw::GLint*)data;
1587 
1588 	/* Verify data extracted from transfrom feedback */
1589 	if (0 != memcmp(transform_feedback_data, &expected_data, m_buffer_size))
1590 	{
1591 		m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_data
1592 						   << " Extracted: " << *transform_feedback_data << tcu::TestLog::EndMessage;
1593 
1594 		return false;
1595 	}
1596 	else
1597 	{
1598 		return true;
1599 	}
1600 }
1601 
1602 /** Constructor
1603  *
1604  *  @param context       Test context
1605  *  @param name          Test case's name
1606  *  @param description   Test case's description
1607  **/
GeometryShaderMaxInputComponentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1608 GeometryShaderMaxInputComponentsTest::GeometryShaderMaxInputComponentsTest(Context&				context,
1609 																		   const ExtParameters& extParams,
1610 																		   const char* name, const char* description)
1611 	: GeometryShaderLimitsTransformFeedbackBase(context, extParams, name, description)
1612 	, m_max_geometry_input_components(0)
1613 	, m_max_geometry_input_vectors(0)
1614 {
1615 	/* Nothing to be done here */
1616 }
1617 
1618 /** Clears data after draw call and result verification
1619  *
1620  **/
clean()1621 void GeometryShaderMaxInputComponentsTest::clean()
1622 {
1623 	/* Nothing to be done here */
1624 }
1625 
1626 /** Get names and number of varyings to be captured by transform feedback
1627  *
1628  *  @param out_captured_varyings_names Array of varying names
1629  *  @param out_n_captured_varyings     Number of varying names
1630  **/
getCapturedVaryings(const glw::GLchar * const * & out_captured_varyings_names,glw::GLuint & out_n_captured_varyings)1631 void GeometryShaderMaxInputComponentsTest::getCapturedVaryings(const glw::GLchar* const*& out_captured_varyings_names,
1632 															   glw::GLuint&				  out_n_captured_varyings)
1633 {
1634 	/* Varying names */
1635 	out_captured_varyings_names = &m_captured_varyings_names;
1636 
1637 	/* Number of varyings */
1638 	out_n_captured_varyings = 1;
1639 }
1640 
1641 /** Get parts of shaders
1642  *
1643  *  @param out_fragment_shader_parts   Array of fragment shader parts
1644  *  @param out_n_fragment_shader_parts Number of fragment shader parts
1645  *  @param out_geometry_shader_parts   Array of geometry shader parts
1646  *  @param out_n_geometry_shader_parts Number of geometry shader parts
1647  *  @param out_vertex_shader_parts     Array of vertex shader parts
1648  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
1649  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)1650 void GeometryShaderMaxInputComponentsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
1651 														  unsigned int&				 out_n_fragment_shader_parts,
1652 														  const glw::GLchar* const*& out_geometry_shader_parts,
1653 														  unsigned int&				 out_n_geometry_shader_parts,
1654 														  const glw::GLchar* const*& out_vertex_shader_parts,
1655 														  unsigned int&				 out_n_vertex_shader_parts)
1656 {
1657 	/* Retrieve ES entry-points */
1658 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1659 
1660 	/* Fragment Shader */
1661 	out_fragment_shader_parts   = &m_fragment_shader_code;
1662 	out_n_fragment_shader_parts = 1;
1663 
1664 	/* Get maximum number of uniform */
1665 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_INPUT_COMPONENTS, &m_max_geometry_input_components);
1666 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT pname");
1667 
1668 	m_max_geometry_input_vectors = m_max_geometry_input_components / 4 /* 4 components per vector */;
1669 
1670 	std::stringstream stream;
1671 	stream << m_max_geometry_input_vectors;
1672 	m_max_geometry_input_vectors_string = stream.str();
1673 
1674 	/* Geometry Shader */
1675 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
1676 	m_geometry_shader_parts[1] = m_geometry_shader_code_number_of_uniforms;
1677 	m_geometry_shader_parts[2] = m_max_geometry_input_vectors_string.c_str();
1678 	m_geometry_shader_parts[3] = m_geometry_shader_code_body;
1679 
1680 	out_geometry_shader_parts   = m_geometry_shader_parts;
1681 	out_n_geometry_shader_parts = 4;
1682 
1683 	/* Vertex Shader */
1684 	m_vertex_shader_parts[0] = m_vertex_shader_code_preamble;
1685 	m_vertex_shader_parts[1] = m_vertex_shader_code_number_of_uniforms;
1686 	m_vertex_shader_parts[2] = m_max_geometry_input_vectors_string.c_str();
1687 	m_vertex_shader_parts[3] = m_vertex_shader_code_body;
1688 
1689 	out_vertex_shader_parts   = m_vertex_shader_parts;
1690 	out_n_vertex_shader_parts = 4;
1691 }
1692 
1693 /** Get size of buffer used by transform feedback
1694  *
1695  *  @param out_buffer_size  Size of buffer in bytes
1696  **/
getTransformFeedbackBufferSize(unsigned int & out_buffer_size)1697 void GeometryShaderMaxInputComponentsTest::getTransformFeedbackBufferSize(unsigned int& out_buffer_size)
1698 {
1699 	out_buffer_size = m_buffer_size;
1700 }
1701 
1702 /** Prepare test specific program input for draw call
1703  *
1704  **/
prepareProgramInput()1705 void GeometryShaderMaxInputComponentsTest::prepareProgramInput()
1706 {
1707 	/* Nothing to be done here */
1708 }
1709 
1710 /** Verification of results
1711  *
1712  *  @param result Pointer to data mapped from transform feedback buffer.
1713  *                Size of data is equal to buffer_size set by getTransformFeedbackBufferSize()
1714  *
1715  *  @return true  Result match expected value
1716  *          false Result has wrong value
1717  **/
verifyResult(const void * data)1718 bool GeometryShaderMaxInputComponentsTest::verifyResult(const void* data)
1719 {
1720 	/* Expected data, sum of elements in range <x;y> with length n = ((x + y) / 2) * n */
1721 	const glw::GLint expected_data = ((1 + m_max_geometry_input_components) * m_max_geometry_input_components) / 2;
1722 
1723 	/* Cast to const GLint */
1724 	const glw::GLint* transform_feedback_data = (const glw::GLint*)data;
1725 
1726 	/* Verify data extracted from transfrom feedback */
1727 	if (0 != memcmp(transform_feedback_data, &expected_data, m_buffer_size))
1728 	{
1729 		m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_data
1730 						   << " Extracted: " << *transform_feedback_data << tcu::TestLog::EndMessage;
1731 
1732 		return false;
1733 	}
1734 	else
1735 	{
1736 		return true;
1737 	}
1738 }
1739 
1740 /** Constructor
1741  *
1742  * @param context       Test context
1743  * @param name          Test case's name
1744  * @param description   Test case's description
1745  **/
GeometryShaderMaxOutputComponentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1746 GeometryShaderMaxOutputComponentsTest::GeometryShaderMaxOutputComponentsTest(Context&			  context,
1747 																			 const ExtParameters& extParams,
1748 																			 const char* name, const char* description)
1749 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
1750 	, m_fragment_shader_code_c_str(0)
1751 	, m_geometry_shader_code_c_str(0)
1752 	, m_texture_width(0)
1753 	, m_max_output_components(0)
1754 	, m_max_output_vectors(0)
1755 	, m_max_total_output_components(0)
1756 	, m_n_available_vectors(0)
1757 	, m_n_output_points(0)
1758 {
1759 	/* Nothing to be done here */
1760 }
1761 
1762 /** Clears data after draw call and result verification
1763  *
1764  **/
clean()1765 void GeometryShaderMaxOutputComponentsTest::clean()
1766 {
1767 	/* Nothing to be done here */
1768 }
1769 
1770 /** Get details for draw call
1771  *
1772  *  @param out_primitive_type Type of primitive that will be used by next draw call
1773  *  @param out_n_vertices     Number of vertices that will used with next draw call
1774  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)1775 void GeometryShaderMaxOutputComponentsTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
1776 															   glw::GLuint& out_n_vertices)
1777 {
1778 	/* Draw one point */
1779 	out_primitive_type = GL_POINTS;
1780 	out_n_vertices	 = 1;
1781 }
1782 
1783 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
1784  *
1785  *  @param out_texture_format      Format for texture used as color attachment 0
1786  *  @param out_texture_read_format Format of data used with glReadPixels
1787  *  @param out_texture_read_type   Type of data used with glReadPixels
1788  *  @param out_texture_width       Width of texture used as color attachment 0
1789  *  @param out_texture_height      Height of texture used as color attachment 0
1790  *  @param out_texture_pixel_size  Size of single pixel in bytes
1791  **/
getFramebufferDetails(glw::GLenum & out_texture_format,glw::GLenum & out_texture_read_format,glw::GLenum & out_texture_read_type,glw::GLuint & out_texture_width,glw::GLuint & out_texture_height,unsigned int & out_texture_pixel_size)1792 void GeometryShaderMaxOutputComponentsTest::getFramebufferDetails(
1793 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
1794 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
1795 {
1796 	out_texture_format		= GL_R32I;
1797 	out_texture_read_format = GL_RGBA_INTEGER;
1798 	out_texture_read_type   = GL_INT;
1799 	out_texture_width		= m_texture_width;
1800 	out_texture_height		= m_texture_height;
1801 	out_texture_pixel_size  = 4 * 4;
1802 }
1803 
getRequiredPointSize(glw::GLfloat & out_point_size)1804 void GeometryShaderMaxOutputComponentsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
1805 {
1806 	/* This test should only run if EXT_geometry_point_size is supported */
1807 	if (!m_is_geometry_shader_point_size_supported)
1808 	{
1809 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
1810 	}
1811 
1812 	out_point_size = (float)m_point_size;
1813 }
1814 
1815 /** Get parts of shaders
1816  *
1817  *  @param out_fragment_shader_parts   Array of fragment shader parts
1818  *  @param out_n_fragment_shader_parts Number of fragment shader parts
1819  *  @param out_geometry_shader_parts   Array of geometry shader parts
1820  *  @param out_n_geometry_shader_parts Number of geometry shader parts
1821  *  @param out_vertex_shader_parts     Array of vertex shader parts
1822  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
1823  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)1824 void GeometryShaderMaxOutputComponentsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
1825 														   unsigned int&			  out_n_fragment_shader_parts,
1826 														   const glw::GLchar* const*& out_geometry_shader_parts,
1827 														   unsigned int&			  out_n_geometry_shader_parts,
1828 														   const glw::GLchar* const*& out_vertex_shader_parts,
1829 														   unsigned int&			  out_n_vertex_shader_parts)
1830 {
1831 	/* GL functions */
1832 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1833 
1834 	/* Get maximum number of output components */
1835 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &m_max_total_output_components);
1836 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_output_components);
1837 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed");
1838 
1839 	m_n_output_points	 = m_max_total_output_components / m_max_output_components;
1840 	m_max_output_vectors  = m_max_output_components / 4; /* 4 components per vector */
1841 	m_n_available_vectors = m_max_output_vectors - 2;	/* 2 vectors are reserved for gl_Position and gl_PointSize */
1842 
1843 	/* Framebuffer width */
1844 	m_texture_width = m_point_size * m_n_output_points;
1845 
1846 	/* Fragment shader parts */
1847 	prepareFragmentShader(m_fragment_shader_code);
1848 
1849 	m_fragment_shader_code_c_str = m_fragment_shader_code.c_str();
1850 	out_fragment_shader_parts	= &m_fragment_shader_code_c_str;
1851 	out_n_fragment_shader_parts  = 1;
1852 
1853 	/* Geometry shader parts */
1854 	prepareGeometryShader(m_geometry_shader_code);
1855 
1856 	m_geometry_shader_code_c_str = m_geometry_shader_code.c_str();
1857 	out_geometry_shader_parts	= &m_geometry_shader_code_c_str;
1858 	out_n_geometry_shader_parts  = 1;
1859 
1860 	/* Vertex shader */
1861 	out_vertex_shader_parts   = &m_vertex_shader_code;
1862 	out_n_vertex_shader_parts = 1;
1863 }
1864 
1865 /** Prepare test specific program input for draw call
1866  *
1867  **/
prepareProgramInput()1868 void GeometryShaderMaxOutputComponentsTest::prepareProgramInput()
1869 {
1870 	/* Nothing to be done here */
1871 }
1872 
1873 /** Verify rendered image
1874  *
1875  *  @param data Image to verify
1876  *
1877  *  @return true  Image pixels match expected values
1878  *          false Some pixels have wrong values
1879  **/
verifyResult(const void * data)1880 bool GeometryShaderMaxOutputComponentsTest::verifyResult(const void* data)
1881 {
1882 	const unsigned char* result_image			= (const unsigned char*)data;
1883 	const unsigned int   line_size				= m_texture_width * m_texture_pixel_size;
1884 	const glw::GLint	 n_components_per_point = m_n_available_vectors * 4; /* 4 components per vector */
1885 
1886 	/* For each drawn point */
1887 	for (glw::GLint point = 0; point < m_n_output_points; ++point)
1888 	{
1889 		const glw::GLint   first_value	= point * n_components_per_point + 1;
1890 		const glw::GLint   last_value	 = (point + 1) * n_components_per_point;
1891 		const glw::GLint   expected_value = ((first_value + last_value) * n_components_per_point) / 2;
1892 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
1893 
1894 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
1895 		for (unsigned int y = 0; y < m_point_size; ++y)
1896 		{
1897 			const unsigned int line_offset		  = y * line_size;
1898 			const unsigned int first_texel_offset = line_offset + point_offset;
1899 
1900 			for (unsigned int x = 0; x < m_point_size; ++x)
1901 			{
1902 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
1903 
1904 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
1905 				{
1906 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
1907 
1908 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_value
1909 									   << " Extracted: " << *result_value << " Point: " << point << " X: " << x
1910 									   << " Y: " << y << tcu::TestLog::EndMessage;
1911 
1912 					return false;
1913 				}
1914 			}
1915 		}
1916 	}
1917 
1918 	return true;
1919 }
1920 
1921 /** Prepare fragment shader code
1922  *
1923  *  @param out_shader_code String that will be used to store shaders code
1924  **/
prepareFragmentShader(std::string & out_shader_code) const1925 void GeometryShaderMaxOutputComponentsTest::prepareFragmentShader(std::string& out_shader_code) const
1926 {
1927 	std::stringstream stream;
1928 
1929 	stream << m_fragment_shader_code_preamble;
1930 	stream << m_common_shader_code_gs_fs_out_definitions;
1931 
1932 	for (int i = 0; i < m_n_available_vectors; ++i)
1933 	{
1934 		stream << m_fragment_shader_code_flat_in_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
1935 	}
1936 
1937 	stream << m_fragment_shader_code_body_begin;
1938 
1939 	for (int i = 0; i < m_n_available_vectors; ++i)
1940 	{
1941 		stream << "    " << m_fragment_shader_code_sum << m_common_shader_code_gs_fs_out << i << ".x + "
1942 			   << m_common_shader_code_gs_fs_out << i << ".y + " << m_common_shader_code_gs_fs_out << i << ".z + "
1943 			   << m_common_shader_code_gs_fs_out << i << ".w;\n";
1944 	}
1945 
1946 	stream << m_fragment_shader_code_body_end;
1947 
1948 	out_shader_code = stream.str();
1949 }
1950 
1951 /** Prepare geometry shader code
1952  *
1953  *  @param out_shader_code String that will be used to store shaders code
1954  **/
prepareGeometryShader(std::string & out_shader_code) const1955 void GeometryShaderMaxOutputComponentsTest::prepareGeometryShader(std::string& out_shader_code) const
1956 {
1957 	std::stringstream stream;
1958 
1959 	stream << m_geometry_shader_code_preamble;
1960 	stream << m_common_shader_code_number_of_points;
1961 	stream << m_n_output_points;
1962 	stream << m_geometry_shader_code_layout;
1963 	stream << m_common_shader_code_gs_fs_out_definitions;
1964 
1965 	for (int i = 0; i < m_n_available_vectors; ++i)
1966 	{
1967 		stream << m_geometry_shader_code_flat_out_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
1968 	}
1969 
1970 	stream << m_geometry_shader_code_body_begin;
1971 
1972 	for (int i = 0; i < m_n_available_vectors; ++i)
1973 	{
1974 		stream << "        " << m_common_shader_code_gs_fs_out << i << m_geometry_shader_code_assignment;
1975 	}
1976 
1977 	stream << m_geometry_shader_code_body_end;
1978 
1979 	out_shader_code = stream.str();
1980 }
1981 
1982 /** Constructor
1983  *
1984  * @param context       Test context
1985  * @param name          Test case's name
1986  * @param description   Test case's description
1987  **/
GeometryShaderMaxOutputVerticesTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1988 GeometryShaderMaxOutputVerticesTest::GeometryShaderMaxOutputVerticesTest(Context&			  context,
1989 																		 const ExtParameters& extParams,
1990 																		 const char* name, const char* description)
1991 	: TestCaseBase(context, extParams, name, description)
1992 {
1993 	/* Nothing to be done here */
1994 }
1995 
1996 /** Executes the test.
1997  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1998  *
1999  *  Note the function throws exception should an error occur!
2000  *
2001  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2002  *
2003  **/
iterate()2004 tcu::TestCase::IterateResult GeometryShaderMaxOutputVerticesTest::iterate()
2005 {
2006 	/* This test should only run if EXT_geometry_shader is supported */
2007 	if (!m_is_geometry_shader_extension_supported)
2008 	{
2009 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2010 	}
2011 
2012 	/* GL */
2013 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2014 
2015 	/* Get maximum number of output vertices and prepare strings */
2016 	glw::GLint  max_output_vertices;
2017 	std::string valid_output_vertices_string;
2018 	std::string invalid_output_vertices_string;
2019 
2020 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_VERTICES, &max_output_vertices);
2021 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT pname");
2022 
2023 	std::stringstream stream_valid;
2024 	stream_valid << max_output_vertices;
2025 	valid_output_vertices_string = stream_valid.str();
2026 
2027 	std::stringstream stream_invalid;
2028 	stream_invalid << max_output_vertices + 1;
2029 	invalid_output_vertices_string = stream_invalid.str();
2030 
2031 	/* Geometry shader parts */
2032 	const glw::GLchar* geometry_shader_valid_parts[] = { m_geometry_shader_code_preamble,
2033 														 valid_output_vertices_string.c_str(),
2034 														 m_geometry_shader_code_body };
2035 
2036 	const glw::GLchar* geometry_shader_invalid_parts[] = { m_geometry_shader_code_preamble,
2037 														   invalid_output_vertices_string.c_str(),
2038 														   m_geometry_shader_code_body };
2039 
2040 	/* Try to build programs */
2041 	bool does_valid_build =
2042 		doesProgramBuild(1, &m_fragment_shader_code, 3, geometry_shader_valid_parts, 1, &m_vertex_shader_code);
2043 
2044 	bool does_invalid_build =
2045 		doesProgramBuild(1, &m_fragment_shader_code, 3, geometry_shader_invalid_parts, 1, &m_vertex_shader_code);
2046 
2047 	/* Verify results */
2048 	if ((true == does_valid_build) && (false == does_invalid_build))
2049 	{
2050 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2051 	}
2052 	else
2053 	{
2054 		if (true != does_valid_build)
2055 		{
2056 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build valid program! GS::max_vertices "
2057 														   "set to MAX_GEOMETRY_OUTPUT_VERTICES.\n"
2058 							   << tcu::TestLog::EndMessage;
2059 		}
2060 
2061 		if (false != does_invalid_build)
2062 		{
2063 			m_testCtx.getLog() << tcu::TestLog::Message << "Build of invalid program was successful! GS::max_vertices "
2064 														   "set to MAX_GEOMETRY_OUTPUT_VERTICES + 1.\n"
2065 							   << tcu::TestLog::EndMessage;
2066 		}
2067 
2068 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2069 	}
2070 
2071 	return STOP;
2072 }
2073 
2074 /** Constructor
2075  *
2076  * @param context       Test context
2077  * @param name          Test case's name
2078  * @param description   Test case's decsription
2079  **/
GeometryShaderMaxOutputComponentsSinglePointTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2080 GeometryShaderMaxOutputComponentsSinglePointTest::GeometryShaderMaxOutputComponentsSinglePointTest(
2081 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
2082 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
2083 	, m_fragment_shader_code_c_str(0)
2084 	, m_geometry_shader_code_c_str(0)
2085 	, m_max_output_components(0)
2086 	, m_max_output_vectors(0)
2087 	, m_n_available_vectors(0)
2088 {
2089 	/* Nothing to be done here */
2090 }
2091 
2092 /** Clears data after draw call and result verification
2093  *
2094  **/
clean()2095 void GeometryShaderMaxOutputComponentsSinglePointTest::clean()
2096 {
2097 	/* Nothing to be done here */
2098 }
2099 
2100 /** Get details for draw call
2101  *
2102  *  @param out_primitive_type Type of primitive that will be used by next draw call
2103  *  @param out_n_vertices     Number of vertices that will used with next draw call
2104  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)2105 void GeometryShaderMaxOutputComponentsSinglePointTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
2106 																		  glw::GLuint& out_n_vertices)
2107 {
2108 	/* Draw one point */
2109 	out_primitive_type = GL_POINTS;
2110 	out_n_vertices	 = 1;
2111 }
2112 
2113 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
2114  *
2115  *  @param out_texture_format      Format for texture used as color attachment 0
2116  *  @param out_texture_read_format Format of data used with glReadPixels
2117  *  @param out_texture_read_type   Type of data used with glReadPixels
2118  *  @param out_texture_width       Width of texture used as color attachment 0
2119  *  @param out_texture_height      Height of texture used as color attachment 0
2120  *  @param out_texture_pixel_size  Size of single pixel in bytes
2121  **/
getFramebufferDetails(glw::GLenum & out_texture_format,glw::GLenum & out_texture_read_format,glw::GLenum & out_texture_read_type,glw::GLuint & out_texture_width,glw::GLuint & out_texture_height,unsigned int & out_texture_pixel_size)2122 void GeometryShaderMaxOutputComponentsSinglePointTest::getFramebufferDetails(
2123 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
2124 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
2125 {
2126 	out_texture_format		= GL_R32I;
2127 	out_texture_read_format = GL_RGBA_INTEGER;
2128 	out_texture_read_type   = GL_INT;
2129 	out_texture_width		= m_texture_width;
2130 	out_texture_height		= m_texture_height;
2131 	out_texture_pixel_size  = 4 * 4;
2132 }
2133 
getRequiredPointSize(glw::GLfloat & out_point_size)2134 void GeometryShaderMaxOutputComponentsSinglePointTest::getRequiredPointSize(glw::GLfloat& out_point_size)
2135 {
2136 	/* This test should only run if EXT_geometry_point_size is supported */
2137 	if (!m_is_geometry_shader_point_size_supported)
2138 	{
2139 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
2140 	}
2141 
2142 	out_point_size = (float)m_point_size;
2143 }
2144 
2145 /** Get parts of shaders
2146  *
2147  *  @param out_fragment_shader_parts   Array of fragment shader parts
2148  *  @param out_n_fragment_shader_parts Number of fragment shader parts
2149  *  @param out_geometry_shader_parts   Array of geometry shader parts
2150  *  @param out_n_geometry_shader_parts Number of geometry shader parts
2151  *  @param out_vertex_shader_parts     Array of vertex shader parts
2152  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
2153  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)2154 void GeometryShaderMaxOutputComponentsSinglePointTest::getShaderParts(
2155 	const glw::GLchar* const*& out_fragment_shader_parts, unsigned int& out_n_fragment_shader_parts,
2156 	const glw::GLchar* const*& out_geometry_shader_parts, unsigned int& out_n_geometry_shader_parts,
2157 	const glw::GLchar* const*& out_vertex_shader_parts, unsigned int& out_n_vertex_shader_parts)
2158 {
2159 	/* Retrieve ES entry-points */
2160 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2161 
2162 	/* Get maximum number of output components */
2163 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_output_components);
2164 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT pname");
2165 
2166 	m_max_output_vectors  = m_max_output_components / 4; /* 4 components per vector */
2167 	m_n_available_vectors = m_max_output_vectors - 2;	/* 2 vectors are reserved for gl_Position and gl_PointSize */
2168 
2169 	/* Fragment shader parts */
2170 	prepareFragmentShader(m_fragment_shader_code);
2171 
2172 	m_fragment_shader_code_c_str = m_fragment_shader_code.c_str();
2173 	out_fragment_shader_parts	= &m_fragment_shader_code_c_str;
2174 	out_n_fragment_shader_parts  = 1;
2175 
2176 	/* Geometry shader parts */
2177 	prepareGeometryShader(m_geometry_shader_code);
2178 
2179 	m_geometry_shader_code_c_str = m_geometry_shader_code.c_str();
2180 	out_geometry_shader_parts	= &m_geometry_shader_code_c_str;
2181 	out_n_geometry_shader_parts  = 1;
2182 
2183 	/* Vertex shader */
2184 	out_vertex_shader_parts   = &m_vertex_shader_code;
2185 	out_n_vertex_shader_parts = 1;
2186 }
2187 
2188 /** Prepare test specific program input for draw call
2189  *
2190  **/
prepareProgramInput()2191 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareProgramInput()
2192 {
2193 	/* Nothing to be done here */
2194 }
2195 
2196 /** Verify rendered image
2197  *
2198  *  @param data Image to verify
2199  *
2200  *  @return true  Image pixels match expected values
2201  *          false Some pixels have wrong values
2202  **/
verifyResult(const void * data)2203 bool GeometryShaderMaxOutputComponentsSinglePointTest::verifyResult(const void* data)
2204 {
2205 	const unsigned char* result_image			= (const unsigned char*)data;
2206 	const unsigned int   line_size				= m_texture_width * m_texture_pixel_size;
2207 	const glw::GLint	 n_components_per_point = m_n_available_vectors * 4; /* 4 components per vector */
2208 
2209 	const glw::GLint first_value	= 1;
2210 	const glw::GLint last_value		= n_components_per_point;
2211 	const glw::GLint expected_value = ((first_value + last_value) * n_components_per_point) / 2;
2212 
2213 	/* Verify all pixels that belong to point, area m_point_size x m_point_size */
2214 	for (unsigned int y = 0; y < m_point_size; ++y)
2215 	{
2216 		const unsigned int line_offset = y * line_size;
2217 
2218 		for (unsigned int x = 0; x < m_point_size; ++x)
2219 		{
2220 			const unsigned int texel_offset = line_offset + x * m_texture_pixel_size;
2221 
2222 			if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
2223 			{
2224 				const glw::GLint* result_value = (const glw::GLint*)(result_image + texel_offset);
2225 
2226 				m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_value
2227 								   << " Extracted: " << *result_value << "  X: " << x << " Y: " << y
2228 								   << tcu::TestLog::EndMessage;
2229 
2230 				return false;
2231 			}
2232 		}
2233 	}
2234 
2235 	return true;
2236 }
2237 
2238 /** Prepare fragment shader code
2239  *
2240  *  @param out_shader_code String that will be used to store shaders code
2241  **/
prepareFragmentShader(std::string & out_shader_code) const2242 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareFragmentShader(std::string& out_shader_code) const
2243 {
2244 	std::stringstream stream;
2245 
2246 	stream << m_fragment_shader_code_preamble;
2247 	stream << m_common_shader_code_gs_fs_out_definitions;
2248 
2249 	for (int i = 0; i < m_n_available_vectors; ++i)
2250 	{
2251 		stream << m_fragment_shader_code_flat_in_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
2252 	}
2253 
2254 	stream << m_fragment_shader_code_body_begin;
2255 
2256 	for (int i = 0; i < m_n_available_vectors; ++i)
2257 	{
2258 		stream << "    " << m_fragment_shader_code_sum << m_common_shader_code_gs_fs_out << i << ".x + "
2259 			   << m_common_shader_code_gs_fs_out << i << ".y + " << m_common_shader_code_gs_fs_out << i << ".z + "
2260 			   << m_common_shader_code_gs_fs_out << i << ".w;\n";
2261 	}
2262 
2263 	stream << m_fragment_shader_code_body_end;
2264 
2265 	out_shader_code = stream.str();
2266 }
2267 
2268 /** Prepare geometry shader code
2269  *
2270  *  @param out_shader_code String that will be used to store shaders code
2271  **/
prepareGeometryShader(std::string & out_shader_code) const2272 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareGeometryShader(std::string& out_shader_code) const
2273 {
2274 	std::stringstream stream;
2275 
2276 	stream << m_geometry_shader_code_preamble;
2277 	stream << m_common_shader_code_gs_fs_out_definitions;
2278 
2279 	for (int i = 0; i < m_n_available_vectors; ++i)
2280 	{
2281 		stream << m_geometry_shader_code_flat_out_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
2282 	}
2283 
2284 	stream << m_geometry_shader_code_body_begin;
2285 
2286 	for (int i = 0; i < m_n_available_vectors; ++i)
2287 	{
2288 		stream << "    " << m_common_shader_code_gs_fs_out << i << m_geometry_shader_code_assignment;
2289 	}
2290 
2291 	stream << m_geometry_shader_code_body_end;
2292 
2293 	out_shader_code = stream.str();
2294 }
2295 
2296 /** Constructor
2297  *
2298  * @param context     Test context
2299  * @param name        Test case's name
2300  * @param description Test case's description
2301  **/
GeometryShaderMaxTextureUnitsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2302 GeometryShaderMaxTextureUnitsTest::GeometryShaderMaxTextureUnitsTest(Context& context, const ExtParameters& extParams,
2303 																	 const char* name, const char* description)
2304 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
2305 	, m_texture_width(0)
2306 	, m_max_texture_units(0)
2307 {
2308 	/* Nothing to be done here */
2309 }
2310 
2311 /** Clears data after draw call and result verification
2312  *
2313  **/
clean()2314 void GeometryShaderMaxTextureUnitsTest::clean()
2315 {
2316 	/* GL functions */
2317 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2318 
2319 	/* Bind 0 to all texture units */
2320 	for (int i = 0; i < m_max_texture_units; ++i)
2321 	{
2322 		gl.activeTexture(GL_TEXTURE0 + i);
2323 		gl.bindTexture(GL_TEXTURE_2D, 0);
2324 	}
2325 	gl.activeTexture(GL_TEXTURE0);
2326 
2327 	/* Delete textures */
2328 	for (int i = 0; i < m_max_texture_units; ++i)
2329 	{
2330 		gl.deleteTextures(1, &m_textures[i].texture_id);
2331 	}
2332 
2333 	m_textures.clear();
2334 }
2335 
2336 /** Get details for draw call
2337  *
2338  *  @param out_primitive_type Type of primitive that will be used by next draw call
2339  *  @param out_n_vertices     Number of vertices that will used with next draw call
2340  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)2341 void GeometryShaderMaxTextureUnitsTest::getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices)
2342 {
2343 	/* Draw GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points */
2344 	out_primitive_type = GL_POINTS;
2345 	out_n_vertices	 = m_max_texture_units;
2346 }
2347 
2348 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
2349  *
2350  *  @param out_texture_format      Format for texture used as color attachment 0
2351  *  @param out_texture_read_format Format of data used with glReadPixels
2352  *  @param out_texture_read_type   Type of data used with glReadPixels
2353  *  @param out_texture_width       Width of texture used as color attachment 0
2354  *  @param out_texture_height      Height of texture used as color attachment 0
2355  *  @param out_texture_pixel_size  Size of single pixel in bytes
2356  **/
getFramebufferDetails(glw::GLenum & out_texture_format,glw::GLenum & out_texture_read_format,glw::GLenum & out_texture_read_type,glw::GLuint & out_texture_width,glw::GLuint & out_texture_height,unsigned int & out_texture_pixel_size)2357 void GeometryShaderMaxTextureUnitsTest::getFramebufferDetails(
2358 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
2359 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
2360 {
2361 	out_texture_format		= GL_R32I;
2362 	out_texture_read_format = GL_RGBA_INTEGER;
2363 	out_texture_read_type   = GL_INT;
2364 	out_texture_width		= m_texture_width;
2365 	out_texture_height		= m_texture_height;
2366 	out_texture_pixel_size  = 4 * 4;
2367 }
2368 
getRequiredPointSize(glw::GLfloat & out_point_size)2369 void GeometryShaderMaxTextureUnitsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
2370 {
2371 	/* This test should only run if EXT_geometry_point_size is supported */
2372 	if (!m_is_geometry_shader_point_size_supported)
2373 	{
2374 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
2375 	}
2376 
2377 	out_point_size = (float)m_point_size;
2378 }
2379 
2380 /** Get parts of shaders
2381  *
2382  *  @param out_fragment_shader_parts   Array of fragment shader parts
2383  *  @param out_n_fragment_shader_parts Number of fragment shader parts
2384  *  @param out_geometry_shader_parts   Array of geometry shader parts
2385  *  @param out_n_geometry_shader_parts Number of geometry shader parts
2386  *  @param out_vertex_shader_parts     Array of vertex shader parts
2387  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
2388  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)2389 void GeometryShaderMaxTextureUnitsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
2390 													   unsigned int&			  out_n_fragment_shader_parts,
2391 													   const glw::GLchar* const*& out_geometry_shader_parts,
2392 													   unsigned int&			  out_n_geometry_shader_parts,
2393 													   const glw::GLchar* const*& out_vertex_shader_parts,
2394 													   unsigned int&			  out_n_vertex_shader_parts)
2395 {
2396 	/* Retrieve ES entry-points */
2397 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2398 
2399 	/* Get maximum number of texture units */
2400 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_max_texture_units);
2401 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname");
2402 
2403 	/* Number of drawn points is equal to GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */
2404 	m_texture_width = m_max_texture_units * m_point_size;
2405 
2406 	/* Prepare texture units string */
2407 	std::stringstream stream;
2408 	stream << m_max_texture_units;
2409 	m_max_texture_units_string = stream.str();
2410 
2411 	/* Fragment shader parts */
2412 	out_fragment_shader_parts   = &m_fragment_shader_code;
2413 	out_n_fragment_shader_parts = 1;
2414 
2415 	/* Geometry shader parts */
2416 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
2417 	m_geometry_shader_parts[1] = m_max_texture_units_string.c_str();
2418 	m_geometry_shader_parts[2] = m_geometry_shader_code_body;
2419 
2420 	out_geometry_shader_parts   = m_geometry_shader_parts;
2421 	out_n_geometry_shader_parts = 3;
2422 
2423 	/* Vertex shader parts */
2424 	m_vertex_shader_parts[0] = m_vertex_shader_code_preamble;
2425 	m_vertex_shader_parts[1] = m_max_texture_units_string.c_str();
2426 	m_vertex_shader_parts[2] = m_vertex_shader_code_body;
2427 
2428 	out_vertex_shader_parts   = m_vertex_shader_parts;
2429 	out_n_vertex_shader_parts = 3;
2430 }
2431 
2432 /** Prepare test specific program input for draw call
2433  *
2434  **/
prepareProgramInput()2435 void GeometryShaderMaxTextureUnitsTest::prepareProgramInput()
2436 {
2437 	/* Retrieve ES entry-points */
2438 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2439 
2440 	m_textures.resize(m_max_texture_units);
2441 
2442 	/* Prepare texture storage and fill data */
2443 	for (int i = 0; i < m_max_texture_units; ++i)
2444 	{
2445 		/* (starting from 1, delta: 2) */
2446 		m_textures[i].data = i * 2 + 1;
2447 
2448 		/* Generate and bind texture */
2449 		gl.genTextures(1, &m_textures[i].texture_id);
2450 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
2451 
2452 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create texture");
2453 
2454 		/* Allocate and upload texture data */
2455 		gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, 1 /* width */, 1 /* height */, 0 /* border */,
2456 					  GL_RED_INTEGER, GL_INT, &m_textures[i].data);
2457 
2458 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2459 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2460 
2461 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create storage and fill texture with data");
2462 	}
2463 
2464 	/* Prepare sampler uniforms */
2465 	for (int i = 0; i < m_max_texture_units; ++i)
2466 	{
2467 		/* Prepare name of sampler */
2468 		std::stringstream stream;
2469 
2470 		stream << "gs_texture[" << i << "]";
2471 
2472 		/* Get sampler location */
2473 		glw::GLint gs_texture_location = gl.getUniformLocation(m_program_object_id, stream.str().c_str());
2474 
2475 		if (-1 == gs_texture_location || (GL_NO_ERROR != gl.getError()))
2476 		{
2477 			TCU_FAIL("Failed to get uniform isampler2D location");
2478 		}
2479 
2480 		/* Set uniform at sampler location value to index of texture unit */
2481 		gl.uniform1i(gs_texture_location, i);
2482 
2483 		if (GL_NO_ERROR != gl.getError())
2484 		{
2485 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to set uniform at location: " << gs_texture_location
2486 							   << " to value: " << i << tcu::TestLog::EndMessage;
2487 
2488 			TCU_FAIL("Failed to get uniform isampler2D location");
2489 		}
2490 	}
2491 
2492 	/* Bind textures to texture units */
2493 	for (int i = 0; i < m_max_texture_units; ++i)
2494 	{
2495 		gl.activeTexture(GL_TEXTURE0 + i);
2496 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
2497 	}
2498 
2499 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set texture units up");
2500 }
2501 
2502 /** Verify rendered image
2503  *
2504  *  @param data Image to verify
2505  *
2506  *  @return true  Image pixels match expected values
2507  *          false Some pixels have wrong values
2508  **/
verifyResult(const void * data)2509 bool GeometryShaderMaxTextureUnitsTest::verifyResult(const void* data)
2510 {
2511 	const unsigned char* result_image = (const unsigned char*)data;
2512 	const unsigned int   line_size	= m_texture_width * m_texture_pixel_size;
2513 
2514 	/* For each drawn point */
2515 	for (glw::GLint point = 0; point < m_max_texture_units; ++point)
2516 	{
2517 		const glw::GLint   first_value	= m_textures[0].data;
2518 		const glw::GLint   last_value	 = m_textures[point].data;
2519 		const glw::GLint   expected_value = ((first_value + last_value) * (point + 1)) / 2;
2520 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
2521 
2522 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
2523 		for (unsigned int y = 0; y < m_point_size; ++y)
2524 		{
2525 			const unsigned int line_offset		  = y * line_size;
2526 			const unsigned int first_texel_offset = line_offset + point_offset;
2527 
2528 			for (unsigned int x = 0; x < m_point_size; ++x)
2529 			{
2530 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
2531 
2532 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
2533 				{
2534 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
2535 
2536 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! "
2537 																   "Expected: "
2538 									   << expected_value << " Extracted: " << *result_value << " Point: " << point
2539 									   << " X: " << x << " Y: " << y << tcu::TestLog::EndMessage;
2540 
2541 					return false;
2542 				}
2543 			}
2544 		}
2545 	}
2546 
2547 	return true;
2548 }
2549 
2550 /** Constructor
2551  *
2552  * @param context     Test context
2553  * @param name        Test case's name
2554  * @param description Test case's description
2555  **/
GeometryShaderMaxInvocationsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2556 GeometryShaderMaxInvocationsTest::GeometryShaderMaxInvocationsTest(Context& context, const ExtParameters& extParams,
2557 																   const char* name, const char* description)
2558 	: TestCaseBase(context, extParams, name, description)
2559 	, m_fragment_shader_id_for_multiple_invocations_pass(0)
2560 	, m_geometry_shader_id_for_multiple_invocations_pass(0)
2561 	, m_program_object_id_for_multiple_invocations_pass(0)
2562 	, m_vertex_shader_id_for_multiple_invocations_pass(0)
2563 	, m_fragment_shader_id_for_single_invocation_pass(0)
2564 	, m_geometry_shader_id_for_single_invocation_pass(0)
2565 	, m_program_object_id_for_single_invocation_pass(0)
2566 	, m_vertex_shader_id_for_single_invocation_pass(0)
2567 	, m_max_geometry_shader_invocations(0)
2568 	, m_framebuffer_object_id(0)
2569 	, m_color_texture_id(0)
2570 	, m_texture_width(0)
2571 	, m_vertex_array_object_id(0)
2572 {
2573 	/* Nothing to be done here */
2574 }
2575 
2576 /** Initializes GLES objects used during the test.
2577  *
2578  */
initTest()2579 void GeometryShaderMaxInvocationsTest::initTest()
2580 {
2581 	/* This test should only run if EXT_geometry_shader is supported */
2582 	if (!m_is_geometry_shader_extension_supported)
2583 	{
2584 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2585 	}
2586 
2587 	/* Retrieve ES entry-points */
2588 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2589 
2590 	/* Get GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT */
2591 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_INVOCATIONS, &m_max_geometry_shader_invocations);
2592 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT");
2593 
2594 	/* Prepare string for GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT */
2595 	std::stringstream stream;
2596 	stream << m_max_geometry_shader_invocations;
2597 	m_max_geometry_shader_invocations_string = stream.str();
2598 
2599 	/* Prepare gemetry shader parts for multiple invocations pass */
2600 	const glw::GLuint n_geometry_shader_parts_for_multiple_invocations_pass = 5;
2601 
2602 	m_geometry_shader_parts_for_multiple_invocations_pass[0] = m_geometry_shader_code_preamble;
2603 	m_geometry_shader_parts_for_multiple_invocations_pass[1] = m_max_geometry_shader_invocations_string.c_str();
2604 	m_geometry_shader_parts_for_multiple_invocations_pass[2] = m_geometry_shader_code_layout;
2605 	m_geometry_shader_parts_for_multiple_invocations_pass[3] = m_geometry_shader_code_layout_invocations;
2606 	m_geometry_shader_parts_for_multiple_invocations_pass[4] = m_geometry_shader_code_body;
2607 
2608 	/* Prepare gemetry shader parts for single invocation pass */
2609 	const glw::GLuint n_geometry_shader_parts_for_single_invocation_pass = 4;
2610 
2611 	m_geometry_shader_parts_for_single_invocation_pass[0] = m_geometry_shader_code_preamble;
2612 	m_geometry_shader_parts_for_single_invocation_pass[1] = m_max_geometry_shader_invocations_string.c_str();
2613 	m_geometry_shader_parts_for_single_invocation_pass[2] = m_geometry_shader_code_layout;
2614 	m_geometry_shader_parts_for_single_invocation_pass[3] = m_geometry_shader_code_body;
2615 
2616 	/* Create program and shaders for multiple GS invocations */
2617 	m_program_object_id_for_multiple_invocations_pass = gl.createProgram();
2618 
2619 	m_fragment_shader_id_for_multiple_invocations_pass = gl.createShader(GL_FRAGMENT_SHADER);
2620 	m_geometry_shader_id_for_multiple_invocations_pass = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
2621 	m_vertex_shader_id_for_multiple_invocations_pass   = gl.createShader(GL_VERTEX_SHADER);
2622 
2623 	/* Create program and shaders for single GS invocations */
2624 	m_program_object_id_for_single_invocation_pass = gl.createProgram();
2625 
2626 	m_fragment_shader_id_for_single_invocation_pass = gl.createShader(GL_FRAGMENT_SHADER);
2627 	m_geometry_shader_id_for_single_invocation_pass = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
2628 	m_vertex_shader_id_for_single_invocation_pass   = gl.createShader(GL_VERTEX_SHADER);
2629 
2630 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program or shader objects");
2631 
2632 	/* Build program for multiple GS invocations */
2633 	if (false == buildProgram(m_program_object_id_for_multiple_invocations_pass,
2634 							  m_fragment_shader_id_for_multiple_invocations_pass, 1, &m_fragment_shader_code,
2635 							  m_geometry_shader_id_for_multiple_invocations_pass,
2636 							  n_geometry_shader_parts_for_multiple_invocations_pass,
2637 							  m_geometry_shader_parts_for_multiple_invocations_pass,
2638 							  m_vertex_shader_id_for_multiple_invocations_pass, 1, &m_vertex_shader_code))
2639 	{
2640 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
2641 	}
2642 
2643 	/* Build program for single GS invocations */
2644 	if (false == buildProgram(m_program_object_id_for_single_invocation_pass,
2645 							  m_fragment_shader_id_for_single_invocation_pass, 1, &m_fragment_shader_code,
2646 							  m_geometry_shader_id_for_single_invocation_pass,
2647 							  n_geometry_shader_parts_for_single_invocation_pass,
2648 							  m_geometry_shader_parts_for_single_invocation_pass,
2649 							  m_vertex_shader_id_for_single_invocation_pass, 1, &m_vertex_shader_code))
2650 	{
2651 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
2652 	}
2653 
2654 	/* Set up texture object and a FBO */
2655 	gl.genTextures(1, &m_color_texture_id);
2656 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create texture object");
2657 
2658 	gl.genFramebuffers(1, &m_framebuffer_object_id);
2659 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer object");
2660 
2661 	m_texture_width = m_triangle_edge_length * m_max_geometry_shader_invocations;
2662 
2663 	if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
2664 														 m_texture_width, m_texture_height))
2665 	{
2666 		TCU_FAIL("Failed to setup framebuffer");
2667 	}
2668 
2669 	/* Set up a vertex array object */
2670 	gl.genVertexArrays(1, &m_vertex_array_object_id);
2671 	gl.bindVertexArray(m_vertex_array_object_id);
2672 
2673 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
2674 }
2675 
2676 /** Executes the test.
2677  *
2678  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2679  *
2680  *  Note the function throws exception should an error occur!
2681  *
2682  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2683  **/
iterate()2684 tcu::TestCase::IterateResult GeometryShaderMaxInvocationsTest::iterate()
2685 {
2686 	initTest();
2687 
2688 	/* Variables used for image verification purposes */
2689 	std::vector<unsigned char> result_image(m_texture_width * m_texture_height * m_texture_pixel_size);
2690 
2691 	/* Retrieve ES entry-points */
2692 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2693 
2694 	/* Render with multiple GS invocations */
2695 	gl.useProgram(m_program_object_id_for_multiple_invocations_pass);
2696 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
2697 
2698 	gl.clearColor(255 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
2699 	gl.clear(GL_COLOR_BUFFER_BIT);
2700 
2701 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
2702 
2703 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2704 	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
2705 
2706 	/* Extract image from FBO */
2707 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &result_image[0]);
2708 
2709 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
2710 
2711 	/* Run verification */
2712 	bool result_of_multiple_invocations_pass = verifyResultOfMultipleInvocationsPass(&result_image[0]);
2713 
2714 	/* Render with single GS invocations */
2715 	gl.useProgram(m_program_object_id_for_single_invocation_pass);
2716 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
2717 
2718 	gl.clearColor(255 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
2719 	gl.clear(GL_COLOR_BUFFER_BIT);
2720 
2721 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
2722 
2723 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2724 	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
2725 
2726 	/* Extract image from FBO */
2727 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &result_image[0]);
2728 
2729 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
2730 
2731 	/* Run verification */
2732 	bool result_of_single_invocation_pass = verifyResultOfSingleInvocationPass(&result_image[0]);
2733 
2734 	/* Set test result */
2735 	if (result_of_multiple_invocations_pass && result_of_single_invocation_pass)
2736 	{
2737 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2738 	}
2739 	else
2740 	{
2741 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2742 	}
2743 
2744 	return STOP;
2745 }
2746 
2747 /** Deinitializes GLES objects created during the test.
2748  *
2749  */
deinit()2750 void GeometryShaderMaxInvocationsTest::deinit()
2751 {
2752 	/* Retrieve ES entry-points */
2753 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2754 
2755 	/* Reset OpenGL ES state */
2756 	gl.useProgram(0);
2757 	gl.bindVertexArray(0);
2758 	gl.bindTexture(GL_TEXTURE_2D, 0);
2759 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
2760 
2761 	/* Delete everything */
2762 	if (m_program_object_id_for_multiple_invocations_pass != 0)
2763 	{
2764 		gl.deleteProgram(m_program_object_id_for_multiple_invocations_pass);
2765 
2766 		m_program_object_id_for_multiple_invocations_pass = 0;
2767 	}
2768 
2769 	if (m_fragment_shader_id_for_multiple_invocations_pass != 0)
2770 	{
2771 		gl.deleteShader(m_fragment_shader_id_for_multiple_invocations_pass);
2772 
2773 		m_fragment_shader_id_for_multiple_invocations_pass = 0;
2774 	}
2775 
2776 	if (m_geometry_shader_id_for_multiple_invocations_pass != 0)
2777 	{
2778 		gl.deleteShader(m_geometry_shader_id_for_multiple_invocations_pass);
2779 
2780 		m_geometry_shader_id_for_multiple_invocations_pass = 0;
2781 	}
2782 
2783 	if (m_vertex_shader_id_for_multiple_invocations_pass != 0)
2784 	{
2785 		gl.deleteShader(m_vertex_shader_id_for_multiple_invocations_pass);
2786 
2787 		m_vertex_shader_id_for_multiple_invocations_pass = 0;
2788 	}
2789 
2790 	if (m_program_object_id_for_single_invocation_pass != 0)
2791 	{
2792 		gl.deleteProgram(m_program_object_id_for_single_invocation_pass);
2793 
2794 		m_program_object_id_for_single_invocation_pass = 0;
2795 	}
2796 
2797 	if (m_fragment_shader_id_for_single_invocation_pass != 0)
2798 	{
2799 		gl.deleteShader(m_fragment_shader_id_for_single_invocation_pass);
2800 
2801 		m_fragment_shader_id_for_single_invocation_pass = 0;
2802 	}
2803 
2804 	if (m_geometry_shader_id_for_single_invocation_pass != 0)
2805 	{
2806 		gl.deleteShader(m_geometry_shader_id_for_single_invocation_pass);
2807 
2808 		m_geometry_shader_id_for_single_invocation_pass = 0;
2809 	}
2810 
2811 	if (m_vertex_shader_id_for_single_invocation_pass != 0)
2812 	{
2813 		gl.deleteShader(m_vertex_shader_id_for_single_invocation_pass);
2814 
2815 		m_vertex_shader_id_for_single_invocation_pass = 0;
2816 	}
2817 
2818 	if (m_vertex_array_object_id != 0)
2819 	{
2820 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
2821 
2822 		m_vertex_array_object_id = 0;
2823 	}
2824 
2825 	if (m_color_texture_id != 0)
2826 	{
2827 		gl.deleteTextures(1, &m_color_texture_id);
2828 
2829 		m_color_texture_id = 0;
2830 	}
2831 
2832 	if (m_framebuffer_object_id != 0)
2833 	{
2834 		gl.deleteFramebuffers(1, &m_framebuffer_object_id);
2835 
2836 		m_framebuffer_object_id = 0;
2837 	}
2838 
2839 	/* Deinitilize base class */
2840 	TestCaseBase::deinit();
2841 }
2842 
2843 /** Verify image rendered during draw call for multiple invocations pass
2844  *
2845  *  @param result_image Image data
2846  *
2847  *  @return true  When image is as expected
2848  *          false When image is wrong
2849  **/
verifyResultOfMultipleInvocationsPass(unsigned char * result_image)2850 bool GeometryShaderMaxInvocationsTest::verifyResultOfMultipleInvocationsPass(unsigned char* result_image)
2851 {
2852 	for (unsigned int i = 0; i < (unsigned int)m_max_geometry_shader_invocations; ++i)
2853 	{
2854 		/* Verify that pixel at triangle's center was modified */
2855 		const unsigned int x1 = m_triangle_edge_length * i;
2856 		const unsigned int x2 = m_triangle_edge_length * i;
2857 		const unsigned int x3 = m_triangle_edge_length * (i + 1) - 1;
2858 
2859 		const unsigned int y1 = 0;
2860 		const unsigned int y2 = m_triangle_edge_length - 1;
2861 		const unsigned int y3 = m_triangle_edge_length - 1;
2862 
2863 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2864 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2865 
2866 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2867 										   m_texture_pixel_size, 0, 255, 0, 0);
2868 
2869 		if (false == is_pixel_valid)
2870 		{
2871 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at "
2872 														   "["
2873 							   << center_x << ";" << center_y << "]! "
2874 																 "Triangle index: "
2875 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2876 							   << tcu::TestLog::EndMessage;
2877 
2878 			return false;
2879 		}
2880 
2881 		/* Verify that background's pixel was not modified */
2882 		const unsigned int x4 = m_triangle_edge_length * (i + 1) - 1;
2883 		const unsigned int y4 = m_triangle_edge_length - 1;
2884 
2885 		is_pixel_valid =
2886 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2887 
2888 		if (false == is_pixel_valid)
2889 		{
2890 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2891 							   << "]! "
2892 								  "Background for index: "
2893 							   << i << "from range <0:" << m_max_geometry_shader_invocations << ")."
2894 							   << tcu::TestLog::EndMessage;
2895 
2896 			return false;
2897 		}
2898 	}
2899 
2900 	return true;
2901 }
2902 
2903 /** Verify image rendered during draw call for single invocation pass
2904  *
2905  *  @param result_image Image data
2906  *
2907  *  @return true  When image is as expected
2908  *          false When image is wrong
2909  **/
verifyResultOfSingleInvocationPass(unsigned char * result_image)2910 bool GeometryShaderMaxInvocationsTest::verifyResultOfSingleInvocationPass(unsigned char* result_image)
2911 {
2912 	/* Only one triangle should be drawn, verify that pixel at its center was modified */
2913 	{
2914 		const unsigned int x1 = 0;
2915 		const unsigned int x2 = 0;
2916 		const unsigned int x3 = m_triangle_edge_length - 1;
2917 
2918 		const unsigned int y1 = 0;
2919 		const unsigned int y2 = m_triangle_edge_length - 1;
2920 		const unsigned int y3 = m_triangle_edge_length - 1;
2921 
2922 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2923 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2924 
2925 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2926 										   m_texture_pixel_size, 0, 255, 0, 0);
2927 
2928 		if (false == is_pixel_valid)
2929 		{
2930 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << center_x << ";" << center_y
2931 							   << "]! "
2932 								  "Triangle index: "
2933 							   << 0 << " from range <0:" << m_max_geometry_shader_invocations << ")."
2934 							   << tcu::TestLog::EndMessage;
2935 
2936 			return false;
2937 		}
2938 
2939 		/* Verify that background's pixel was not modified */
2940 		const unsigned int x4 = m_triangle_edge_length - 1;
2941 		const unsigned int y4 = m_triangle_edge_length - 1;
2942 
2943 		is_pixel_valid =
2944 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2945 
2946 		if (false == is_pixel_valid)
2947 		{
2948 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2949 							   << "]! "
2950 								  "Background for index: "
2951 							   << 0 << " from range <0:" << m_max_geometry_shader_invocations << ")."
2952 							   << tcu::TestLog::EndMessage;
2953 
2954 			return false;
2955 		}
2956 	}
2957 
2958 	for (unsigned int i = 1; i < (unsigned int)m_max_geometry_shader_invocations; ++i)
2959 	{
2960 		/* Verify that pixel at triangle's center was not modified */
2961 		const unsigned int x1 = m_triangle_edge_length * i;
2962 		const unsigned int x2 = m_triangle_edge_length * i;
2963 		const unsigned int x3 = m_triangle_edge_length * (i + 1) - 1;
2964 
2965 		const unsigned int y1 = 0;
2966 		const unsigned int y2 = m_triangle_edge_length - 1;
2967 		const unsigned int y3 = m_triangle_edge_length - 1;
2968 
2969 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2970 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2971 
2972 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2973 										   m_texture_pixel_size, 255, 0, 0, 0);
2974 
2975 		if (false == is_pixel_valid)
2976 		{
2977 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << center_x << ";" << center_y
2978 							   << "]! "
2979 								  "Triangle index: "
2980 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2981 							   << tcu::TestLog::EndMessage;
2982 
2983 			return false;
2984 		}
2985 
2986 		/* Verify that background's pixel was not modified */
2987 		const unsigned int x4 = m_triangle_edge_length * (i + 1) - 1;
2988 		const unsigned int y4 = m_triangle_edge_length - 1;
2989 
2990 		is_pixel_valid =
2991 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2992 
2993 		if (false == is_pixel_valid)
2994 		{
2995 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2996 							   << "]! "
2997 								  "Background for index: "
2998 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2999 							   << tcu::TestLog::EndMessage;
3000 
3001 			return false;
3002 		}
3003 	}
3004 
3005 	return true;
3006 }
3007 
3008 /** Constructor
3009  *
3010  * @param context       Test context
3011  * @param name          Test case's name
3012  * @param description   Test case's description
3013  **/
GeometryShaderMaxCombinedTextureUnitsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3014 GeometryShaderMaxCombinedTextureUnitsTest::GeometryShaderMaxCombinedTextureUnitsTest(Context&			  context,
3015 																					 const ExtParameters& extParams,
3016 																					 const char*		  name,
3017 																					 const char*		  description)
3018 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
3019 	, m_texture_width(0)
3020 	, m_max_combined_texture_units(0)
3021 	, m_max_fragment_texture_units(0)
3022 	, m_max_geometry_texture_units(0)
3023 	, m_max_vertex_texture_units(0)
3024 	, m_min_texture_units(0)
3025 	, m_n_fragment_texture_units(0)
3026 	, m_n_geometry_texture_units(0)
3027 	, m_n_texture_units(0)
3028 	, m_n_vertex_texture_units(0)
3029 {
3030 	/* Nothing to be done here */
3031 }
3032 
3033 /** Clears data after draw call and result verification
3034  *
3035  **/
clean()3036 void GeometryShaderMaxCombinedTextureUnitsTest::clean()
3037 {
3038 	/* GL functions */
3039 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3040 
3041 	/* Bind 0 to all texture units */
3042 	for (int i = 0; i < m_n_texture_units; ++i)
3043 	{
3044 		gl.activeTexture(GL_TEXTURE0 + i);
3045 		gl.bindTexture(GL_TEXTURE_2D, 0);
3046 	}
3047 
3048 	/* Delete textures */
3049 	for (int i = 0; i < m_n_texture_units; ++i)
3050 	{
3051 		gl.deleteTextures(1, &m_textures[i].texture_id);
3052 	}
3053 
3054 	m_textures.clear();
3055 }
3056 
3057 /** Get details for draw call
3058  *
3059  *  @param out_primitive_type Type of primitive that will be used by next draw call
3060  *  @param out_n_vertices     Number of vertices that will used with next draw call
3061  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)3062 void GeometryShaderMaxCombinedTextureUnitsTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
3063 																   glw::GLuint& out_n_vertices)
3064 {
3065 	/* Draw GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points */
3066 	out_primitive_type = GL_POINTS;
3067 	out_n_vertices	 = m_min_texture_units;
3068 }
3069 
3070 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
3071  *
3072  *  @param out_texture_format      Format for texture used as color attachment 0
3073  *  @param out_texture_read_format Format of data used with glReadPixels
3074  *  @param out_texture_read_type   Type of data used with glReadPixels
3075  *  @param out_texture_width       Width of texture used as color attachment 0
3076  *  @param out_texture_height      Height of texture used as color attachment 0
3077  *  @param out_texture_pixel_size  Size of single pixel in bytes
3078  **/
getFramebufferDetails(glw::GLenum & out_texture_format,glw::GLenum & out_texture_read_format,glw::GLenum & out_texture_read_type,glw::GLuint & out_texture_width,glw::GLuint & out_texture_height,unsigned int & out_texture_pixel_size)3079 void GeometryShaderMaxCombinedTextureUnitsTest::getFramebufferDetails(
3080 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
3081 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
3082 {
3083 	out_texture_format		= GL_R32UI;
3084 	out_texture_read_format = GL_RGBA_INTEGER;
3085 	out_texture_read_type   = GL_UNSIGNED_INT;
3086 	out_texture_width		= m_texture_width;
3087 	out_texture_height		= m_texture_height;
3088 	out_texture_pixel_size  = 4 * 4;
3089 }
3090 
getRequiredPointSize(glw::GLfloat & out_point_size)3091 void GeometryShaderMaxCombinedTextureUnitsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
3092 {
3093 	out_point_size = (float)m_point_size;
3094 }
3095 
3096 /** Get parts of shaders
3097  *
3098  *  @param out_fragment_shader_parts   Array of fragment shader parts
3099  *  @param out_n_fragment_shader_parts Number of fragment shader parts
3100  *  @param out_geometry_shader_parts   Array of geometry shader parts
3101  *  @param out_n_geometry_shader_parts Number of geometry shader parts
3102  *  @param out_vertex_shader_parts     Array of vertex shader parts
3103  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
3104  **/
getShaderParts(const glw::GLchar * const * & out_fragment_shader_parts,unsigned int & out_n_fragment_shader_parts,const glw::GLchar * const * & out_geometry_shader_parts,unsigned int & out_n_geometry_shader_parts,const glw::GLchar * const * & out_vertex_shader_parts,unsigned int & out_n_vertex_shader_parts)3105 void GeometryShaderMaxCombinedTextureUnitsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
3106 															   unsigned int&			  out_n_fragment_shader_parts,
3107 															   const glw::GLchar* const*& out_geometry_shader_parts,
3108 															   unsigned int&			  out_n_geometry_shader_parts,
3109 															   const glw::GLchar* const*& out_vertex_shader_parts,
3110 															   unsigned int&			  out_n_vertex_shader_parts)
3111 {
3112 	/* GL functions */
3113 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3114 
3115 	/* Get maximum number of texture units */
3116 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_max_combined_texture_units);
3117 	gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &m_max_vertex_texture_units);
3118 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_max_geometry_texture_units);
3119 	gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_fragment_texture_units);
3120 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed");
3121 
3122 	m_n_texture_units =
3123 		de::max(m_max_vertex_texture_units, de::max(m_max_geometry_texture_units, m_max_fragment_texture_units));
3124 	m_n_vertex_texture_units = de::max(1, de::min(m_max_combined_texture_units - 2, m_max_vertex_texture_units));
3125 	m_n_fragment_texture_units =
3126 		de::max(1, de::min(m_max_combined_texture_units - m_n_vertex_texture_units - 1, m_max_fragment_texture_units));
3127 	m_n_geometry_texture_units =
3128 		de::max(1, de::min(m_max_combined_texture_units - m_n_vertex_texture_units - m_n_fragment_texture_units,
3129 						   m_max_geometry_texture_units));
3130 	m_min_texture_units =
3131 		de::min(m_n_vertex_texture_units, de::min(m_n_fragment_texture_units, m_n_geometry_texture_units));
3132 
3133 	/* Number of drawn points is equal to GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */
3134 	m_texture_width = m_n_texture_units * m_point_size;
3135 
3136 	/* Prepare texture units string */
3137 	std::stringstream stream_fragment;
3138 	stream_fragment << m_n_fragment_texture_units;
3139 	m_n_fragment_texture_units_string = stream_fragment.str();
3140 
3141 	std::stringstream stream_geometry;
3142 	stream_geometry << m_n_geometry_texture_units;
3143 	m_n_geometry_texture_units_string = stream_geometry.str();
3144 
3145 	std::stringstream stream_vertex;
3146 	stream_vertex << m_n_vertex_texture_units;
3147 	m_n_vertex_texture_units_string = stream_vertex.str();
3148 
3149 	/* Fragment shader parts */
3150 	m_fragment_shader_parts[0] = m_fragment_shader_code_preamble;
3151 	m_fragment_shader_parts[1] = m_n_fragment_texture_units_string.c_str();
3152 	m_fragment_shader_parts[2] = m_fragment_shader_code_body;
3153 
3154 	out_fragment_shader_parts   = m_fragment_shader_parts;
3155 	out_n_fragment_shader_parts = 3;
3156 
3157 	/* Geometry shader parts */
3158 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
3159 	m_geometry_shader_parts[1] = m_n_geometry_texture_units_string.c_str();
3160 	m_geometry_shader_parts[2] = m_geometry_shader_code_body;
3161 
3162 	out_geometry_shader_parts   = m_geometry_shader_parts;
3163 	out_n_geometry_shader_parts = 3;
3164 
3165 	/* Vertex shader parts */
3166 	m_vertex_shader_parts[0] = m_vertex_shader_code_preamble;
3167 	m_vertex_shader_parts[1] = m_n_vertex_texture_units_string.c_str();
3168 	m_vertex_shader_parts[2] = m_vertex_shader_code_body;
3169 
3170 	out_vertex_shader_parts   = m_vertex_shader_parts;
3171 	out_n_vertex_shader_parts = 3;
3172 }
3173 
3174 /** Prepare test specific program input for draw call
3175  *
3176  **/
prepareProgramInput()3177 void GeometryShaderMaxCombinedTextureUnitsTest::prepareProgramInput()
3178 {
3179 	/* Retrieve ES entry-points */
3180 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3181 
3182 	m_textures.resize(m_n_texture_units);
3183 
3184 	/* Prepare texture storage and fill data */
3185 	for (int i = 0; i < m_n_texture_units; ++i)
3186 	{
3187 		/* Reset texture data to 0 after each 16 iterations */
3188 		m_textures[i].data = i % 16;
3189 
3190 		/* Generate and bind texture */
3191 		gl.genTextures(1, &m_textures[i].texture_id);
3192 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
3193 
3194 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create texture");
3195 
3196 		/* Allocate and upload texture data */
3197 		gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32UI, 1 /* width*/, 1 /* height */, 0 /* border */,
3198 					  GL_RED_INTEGER, GL_UNSIGNED_INT, &m_textures[i].data);
3199 
3200 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3201 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3202 
3203 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create storage and fill texture with data");
3204 	}
3205 
3206 	/* Prepare sampler uniforms */
3207 	for (int i = 0; i < m_n_texture_units; ++i)
3208 	{
3209 		/* Prepare name of sampler */
3210 		std::stringstream stream;
3211 
3212 		stream << "sampler[" << i << "]";
3213 
3214 		/* Get sampler location */
3215 		glw::GLint sampler_location = gl.getUniformLocation(m_program_object_id, stream.str().c_str());
3216 
3217 		if (-1 == sampler_location || GL_NO_ERROR != gl.getError())
3218 		{
3219 			TCU_FAIL("Failed to get uniform usampler2D location");
3220 		}
3221 
3222 		/* Set uniform at sampler location value to index of texture unit */
3223 		gl.uniform1i(sampler_location, i);
3224 
3225 		if (GL_NO_ERROR != gl.getError())
3226 		{
3227 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to set uniform at location: " << sampler_location
3228 							   << " to value: " << i << tcu::TestLog::EndMessage;
3229 
3230 			TCU_FAIL("Failed to get uniform isampler2D location");
3231 		}
3232 	}
3233 
3234 	/* Bind textures to texture units */
3235 	for (int i = 0; i < m_n_texture_units; ++i)
3236 	{
3237 		gl.activeTexture(GL_TEXTURE0 + i);
3238 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
3239 
3240 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3241 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3242 	}
3243 
3244 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set texture units up");
3245 }
3246 
3247 /** Verify rendered image
3248  *
3249  *  @param data Image to verify
3250  *
3251  *  @return true  Image pixels match expected values
3252  *          false Some pixels have wrong values
3253  **/
verifyResult(const void * data)3254 bool GeometryShaderMaxCombinedTextureUnitsTest::verifyResult(const void* data)
3255 {
3256 	const unsigned char* result_image = (const unsigned char*)data;
3257 	const unsigned int   line_size	= m_texture_width * m_texture_pixel_size;
3258 
3259 	/* For each drawn point */
3260 	for (glw::GLint point = 0; point < m_n_texture_units; ++point)
3261 	{
3262 		const unsigned int last_vertex_index = de::min(point, m_n_vertex_texture_units);
3263 
3264 		glw::GLint expected_vertex_value   = 0;
3265 		glw::GLint expected_geometry_value = 0;
3266 		glw::GLint expected_fragment_value = 0;
3267 
3268 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3269 		{
3270 			expected_vertex_value += m_textures[i].data;
3271 		}
3272 
3273 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3274 		{
3275 			expected_geometry_value += m_textures[i].data;
3276 		}
3277 
3278 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3279 		{
3280 			expected_fragment_value += m_textures[i].data;
3281 		}
3282 
3283 		const glw::GLint   expected_value = expected_vertex_value + expected_geometry_value + expected_fragment_value;
3284 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
3285 
3286 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
3287 		for (unsigned int y = 0; y < m_point_size; ++y)
3288 		{
3289 			const unsigned int line_offset		  = y * line_size;
3290 			const unsigned int first_texel_offset = line_offset + point_offset;
3291 
3292 			for (unsigned int x = 0; x < m_point_size; ++x)
3293 			{
3294 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
3295 
3296 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
3297 				{
3298 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
3299 
3300 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result!"
3301 																   " Expected: "
3302 									   << expected_value << " Extracted: " << *result_value << " Point: " << point
3303 									   << " X: " << x << " Y: " << y << tcu::TestLog::EndMessage;
3304 
3305 					return false;
3306 				}
3307 			}
3308 		}
3309 	}
3310 
3311 	return true;
3312 }
3313 
3314 } /* glcts */
3315