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_texture_width(0)
1751 	, m_max_output_components(0)
1752 	, m_max_output_vectors(0)
1753 	, m_max_total_output_components(0)
1754 	, m_n_available_vectors(0)
1755 	, m_n_output_points(0)
1756 {
1757 	/* Nothing to be done here */
1758 }
1759 
1760 /** Clears data after draw call and result verification
1761  *
1762  **/
clean()1763 void GeometryShaderMaxOutputComponentsTest::clean()
1764 {
1765 	/* Nothing to be done here */
1766 }
1767 
1768 /** Get details for draw call
1769  *
1770  *  @param out_primitive_type Type of primitive that will be used by next draw call
1771  *  @param out_n_vertices     Number of vertices that will used with next draw call
1772  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)1773 void GeometryShaderMaxOutputComponentsTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
1774 															   glw::GLuint& out_n_vertices)
1775 {
1776 	/* Draw one point */
1777 	out_primitive_type = GL_POINTS;
1778 	out_n_vertices	 = 1;
1779 }
1780 
1781 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
1782  *
1783  *  @param out_texture_format      Format for texture used as color attachment 0
1784  *  @param out_texture_read_format Format of data used with glReadPixels
1785  *  @param out_texture_read_type   Type of data used with glReadPixels
1786  *  @param out_texture_width       Width of texture used as color attachment 0
1787  *  @param out_texture_height      Height of texture used as color attachment 0
1788  *  @param out_texture_pixel_size  Size of single pixel in bytes
1789  **/
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)1790 void GeometryShaderMaxOutputComponentsTest::getFramebufferDetails(
1791 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
1792 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
1793 {
1794 	out_texture_format		= GL_R32I;
1795 	out_texture_read_format = GL_RGBA_INTEGER;
1796 	out_texture_read_type   = GL_INT;
1797 	out_texture_width		= m_texture_width;
1798 	out_texture_height		= m_texture_height;
1799 	out_texture_pixel_size  = 4 * 4;
1800 }
1801 
getRequiredPointSize(glw::GLfloat & out_point_size)1802 void GeometryShaderMaxOutputComponentsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
1803 {
1804 	/* This test should only run if EXT_geometry_point_size is supported */
1805 	if (!m_is_geometry_shader_point_size_supported)
1806 	{
1807 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
1808 	}
1809 
1810 	out_point_size = (float)m_point_size;
1811 }
1812 
1813 /** Get parts of shaders
1814  *
1815  *  @param out_fragment_shader_parts   Array of fragment shader parts
1816  *  @param out_n_fragment_shader_parts Number of fragment shader parts
1817  *  @param out_geometry_shader_parts   Array of geometry shader parts
1818  *  @param out_n_geometry_shader_parts Number of geometry shader parts
1819  *  @param out_vertex_shader_parts     Array of vertex shader parts
1820  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
1821  **/
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)1822 void GeometryShaderMaxOutputComponentsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
1823 														   unsigned int&			  out_n_fragment_shader_parts,
1824 														   const glw::GLchar* const*& out_geometry_shader_parts,
1825 														   unsigned int&			  out_n_geometry_shader_parts,
1826 														   const glw::GLchar* const*& out_vertex_shader_parts,
1827 														   unsigned int&			  out_n_vertex_shader_parts)
1828 {
1829 	/* GL functions */
1830 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1831 
1832 	/* Get maximum number of output components */
1833 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &m_max_total_output_components);
1834 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_output_components);
1835 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed");
1836 
1837 	m_n_output_points	 = m_max_total_output_components / m_max_output_components;
1838 	m_max_output_vectors  = m_max_output_components / 4; /* 4 components per vector */
1839 	m_n_available_vectors = m_max_output_vectors - 2;	/* 2 vectors are reserved for gl_Position and gl_PointSize */
1840 
1841 	/* Framebuffer width */
1842 	m_texture_width = m_point_size * m_n_output_points;
1843 
1844 	/* Fragment shader parts */
1845 	prepareFragmentShader(m_fragment_shader_code);
1846 
1847 	m_fragment_shader_code_c_str = m_fragment_shader_code.c_str();
1848 	out_fragment_shader_parts	= &m_fragment_shader_code_c_str;
1849 	out_n_fragment_shader_parts  = 1;
1850 
1851 	/* Geometry shader parts */
1852 	prepareGeometryShader(m_geometry_shader_code);
1853 
1854 	m_geometry_shader_code_c_str = m_geometry_shader_code.c_str();
1855 	out_geometry_shader_parts	= &m_geometry_shader_code_c_str;
1856 	out_n_geometry_shader_parts  = 1;
1857 
1858 	/* Vertex shader */
1859 	out_vertex_shader_parts   = &m_vertex_shader_code;
1860 	out_n_vertex_shader_parts = 1;
1861 }
1862 
1863 /** Prepare test specific program input for draw call
1864  *
1865  **/
prepareProgramInput()1866 void GeometryShaderMaxOutputComponentsTest::prepareProgramInput()
1867 {
1868 	/* Nothing to be done here */
1869 }
1870 
1871 /** Verify rendered image
1872  *
1873  *  @param data Image to verify
1874  *
1875  *  @return true  Image pixels match expected values
1876  *          false Some pixels have wrong values
1877  **/
verifyResult(const void * data)1878 bool GeometryShaderMaxOutputComponentsTest::verifyResult(const void* data)
1879 {
1880 	const unsigned char* result_image			= (const unsigned char*)data;
1881 	const unsigned int   line_size				= m_texture_width * m_texture_pixel_size;
1882 	const glw::GLint	 n_components_per_point = m_n_available_vectors * 4; /* 4 components per vector */
1883 
1884 	/* For each drawn point */
1885 	for (glw::GLint point = 0; point < m_n_output_points; ++point)
1886 	{
1887 		const glw::GLint   first_value	= point * n_components_per_point + 1;
1888 		const glw::GLint   last_value	 = (point + 1) * n_components_per_point;
1889 		const glw::GLint   expected_value = ((first_value + last_value) * n_components_per_point) / 2;
1890 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
1891 
1892 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
1893 		for (unsigned int y = 0; y < m_point_size; ++y)
1894 		{
1895 			const unsigned int line_offset		  = y * line_size;
1896 			const unsigned int first_texel_offset = line_offset + point_offset;
1897 
1898 			for (unsigned int x = 0; x < m_point_size; ++x)
1899 			{
1900 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
1901 
1902 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
1903 				{
1904 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
1905 
1906 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_value
1907 									   << " Extracted: " << *result_value << " Point: " << point << " X: " << x
1908 									   << " Y: " << y << tcu::TestLog::EndMessage;
1909 
1910 					return false;
1911 				}
1912 			}
1913 		}
1914 	}
1915 
1916 	return true;
1917 }
1918 
1919 /** Prepare fragment shader code
1920  *
1921  *  @param out_shader_code String that will be used to store shaders code
1922  **/
prepareFragmentShader(std::string & out_shader_code) const1923 void GeometryShaderMaxOutputComponentsTest::prepareFragmentShader(std::string& out_shader_code) const
1924 {
1925 	std::stringstream stream;
1926 
1927 	stream << m_fragment_shader_code_preamble;
1928 	stream << m_common_shader_code_gs_fs_out_definitions;
1929 
1930 	for (int i = 0; i < m_n_available_vectors; ++i)
1931 	{
1932 		stream << m_fragment_shader_code_flat_in_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
1933 	}
1934 
1935 	stream << m_fragment_shader_code_body_begin;
1936 
1937 	for (int i = 0; i < m_n_available_vectors; ++i)
1938 	{
1939 		stream << "    " << m_fragment_shader_code_sum << m_common_shader_code_gs_fs_out << i << ".x + "
1940 			   << m_common_shader_code_gs_fs_out << i << ".y + " << m_common_shader_code_gs_fs_out << i << ".z + "
1941 			   << m_common_shader_code_gs_fs_out << i << ".w;\n";
1942 	}
1943 
1944 	stream << m_fragment_shader_code_body_end;
1945 
1946 	out_shader_code = stream.str();
1947 }
1948 
1949 /** Prepare geometry shader code
1950  *
1951  *  @param out_shader_code String that will be used to store shaders code
1952  **/
prepareGeometryShader(std::string & out_shader_code) const1953 void GeometryShaderMaxOutputComponentsTest::prepareGeometryShader(std::string& out_shader_code) const
1954 {
1955 	std::stringstream stream;
1956 
1957 	stream << m_geometry_shader_code_preamble;
1958 	stream << m_common_shader_code_number_of_points;
1959 	stream << m_n_output_points;
1960 	stream << m_geometry_shader_code_layout;
1961 	stream << m_common_shader_code_gs_fs_out_definitions;
1962 
1963 	for (int i = 0; i < m_n_available_vectors; ++i)
1964 	{
1965 		stream << m_geometry_shader_code_flat_out_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
1966 	}
1967 
1968 	stream << m_geometry_shader_code_body_begin;
1969 
1970 	for (int i = 0; i < m_n_available_vectors; ++i)
1971 	{
1972 		stream << "        " << m_common_shader_code_gs_fs_out << i << m_geometry_shader_code_assignment;
1973 	}
1974 
1975 	stream << m_geometry_shader_code_body_end;
1976 
1977 	out_shader_code = stream.str();
1978 }
1979 
1980 /** Constructor
1981  *
1982  * @param context       Test context
1983  * @param name          Test case's name
1984  * @param description   Test case's description
1985  **/
GeometryShaderMaxOutputVerticesTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1986 GeometryShaderMaxOutputVerticesTest::GeometryShaderMaxOutputVerticesTest(Context&			  context,
1987 																		 const ExtParameters& extParams,
1988 																		 const char* name, const char* description)
1989 	: TestCaseBase(context, extParams, name, description)
1990 {
1991 	/* Nothing to be done here */
1992 }
1993 
1994 /** Executes the test.
1995  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1996  *
1997  *  Note the function throws exception should an error occur!
1998  *
1999  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2000  *
2001  **/
iterate()2002 tcu::TestCase::IterateResult GeometryShaderMaxOutputVerticesTest::iterate()
2003 {
2004 	/* This test should only run if EXT_geometry_shader is supported */
2005 	if (!m_is_geometry_shader_extension_supported)
2006 	{
2007 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2008 	}
2009 
2010 	/* GL */
2011 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2012 
2013 	/* Get maximum number of output vertices and prepare strings */
2014 	glw::GLint  max_output_vertices;
2015 	std::string valid_output_vertices_string;
2016 	std::string invalid_output_vertices_string;
2017 
2018 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_VERTICES, &max_output_vertices);
2019 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT pname");
2020 
2021 	std::stringstream stream_valid;
2022 	stream_valid << max_output_vertices;
2023 	valid_output_vertices_string = stream_valid.str();
2024 
2025 	std::stringstream stream_invalid;
2026 	stream_invalid << max_output_vertices + 1;
2027 	invalid_output_vertices_string = stream_invalid.str();
2028 
2029 	/* Geometry shader parts */
2030 	const glw::GLchar* geometry_shader_valid_parts[] = { m_geometry_shader_code_preamble,
2031 														 valid_output_vertices_string.c_str(),
2032 														 m_geometry_shader_code_body };
2033 
2034 	const glw::GLchar* geometry_shader_invalid_parts[] = { m_geometry_shader_code_preamble,
2035 														   invalid_output_vertices_string.c_str(),
2036 														   m_geometry_shader_code_body };
2037 
2038 	/* Try to build programs */
2039 	bool does_valid_build =
2040 		doesProgramBuild(1, &m_fragment_shader_code, 3, geometry_shader_valid_parts, 1, &m_vertex_shader_code);
2041 
2042 	bool does_invalid_build =
2043 		doesProgramBuild(1, &m_fragment_shader_code, 3, geometry_shader_invalid_parts, 1, &m_vertex_shader_code);
2044 
2045 	/* Verify results */
2046 	if ((true == does_valid_build) && (false == does_invalid_build))
2047 	{
2048 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2049 	}
2050 	else
2051 	{
2052 		if (true != does_valid_build)
2053 		{
2054 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build valid program! GS::max_vertices "
2055 														   "set to MAX_GEOMETRY_OUTPUT_VERTICES.\n"
2056 							   << tcu::TestLog::EndMessage;
2057 		}
2058 
2059 		if (false != does_invalid_build)
2060 		{
2061 			m_testCtx.getLog() << tcu::TestLog::Message << "Build of invalid program was successful! GS::max_vertices "
2062 														   "set to MAX_GEOMETRY_OUTPUT_VERTICES + 1.\n"
2063 							   << tcu::TestLog::EndMessage;
2064 		}
2065 
2066 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2067 	}
2068 
2069 	return STOP;
2070 }
2071 
2072 /** Constructor
2073  *
2074  * @param context       Test context
2075  * @param name          Test case's name
2076  * @param description   Test case's decsription
2077  **/
GeometryShaderMaxOutputComponentsSinglePointTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2078 GeometryShaderMaxOutputComponentsSinglePointTest::GeometryShaderMaxOutputComponentsSinglePointTest(
2079 	Context& context, const ExtParameters& extParams, const char* name, const char* description)
2080 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
2081 	, m_max_output_components(0)
2082 	, m_max_output_vectors(0)
2083 	, m_n_available_vectors(0)
2084 {
2085 	/* Nothing to be done here */
2086 }
2087 
2088 /** Clears data after draw call and result verification
2089  *
2090  **/
clean()2091 void GeometryShaderMaxOutputComponentsSinglePointTest::clean()
2092 {
2093 	/* Nothing to be done here */
2094 }
2095 
2096 /** Get details for draw call
2097  *
2098  *  @param out_primitive_type Type of primitive that will be used by next draw call
2099  *  @param out_n_vertices     Number of vertices that will used with next draw call
2100  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)2101 void GeometryShaderMaxOutputComponentsSinglePointTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
2102 																		  glw::GLuint& out_n_vertices)
2103 {
2104 	/* Draw one point */
2105 	out_primitive_type = GL_POINTS;
2106 	out_n_vertices	 = 1;
2107 }
2108 
2109 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
2110  *
2111  *  @param out_texture_format      Format for texture used as color attachment 0
2112  *  @param out_texture_read_format Format of data used with glReadPixels
2113  *  @param out_texture_read_type   Type of data used with glReadPixels
2114  *  @param out_texture_width       Width of texture used as color attachment 0
2115  *  @param out_texture_height      Height of texture used as color attachment 0
2116  *  @param out_texture_pixel_size  Size of single pixel in bytes
2117  **/
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)2118 void GeometryShaderMaxOutputComponentsSinglePointTest::getFramebufferDetails(
2119 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
2120 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
2121 {
2122 	out_texture_format		= GL_R32I;
2123 	out_texture_read_format = GL_RGBA_INTEGER;
2124 	out_texture_read_type   = GL_INT;
2125 	out_texture_width		= m_texture_width;
2126 	out_texture_height		= m_texture_height;
2127 	out_texture_pixel_size  = 4 * 4;
2128 }
2129 
getRequiredPointSize(glw::GLfloat & out_point_size)2130 void GeometryShaderMaxOutputComponentsSinglePointTest::getRequiredPointSize(glw::GLfloat& out_point_size)
2131 {
2132 	/* This test should only run if EXT_geometry_point_size is supported */
2133 	if (!m_is_geometry_shader_point_size_supported)
2134 	{
2135 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
2136 	}
2137 
2138 	out_point_size = (float)m_point_size;
2139 }
2140 
2141 /** Get parts of shaders
2142  *
2143  *  @param out_fragment_shader_parts   Array of fragment shader parts
2144  *  @param out_n_fragment_shader_parts Number of fragment shader parts
2145  *  @param out_geometry_shader_parts   Array of geometry shader parts
2146  *  @param out_n_geometry_shader_parts Number of geometry shader parts
2147  *  @param out_vertex_shader_parts     Array of vertex shader parts
2148  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
2149  **/
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)2150 void GeometryShaderMaxOutputComponentsSinglePointTest::getShaderParts(
2151 	const glw::GLchar* const*& out_fragment_shader_parts, unsigned int& out_n_fragment_shader_parts,
2152 	const glw::GLchar* const*& out_geometry_shader_parts, unsigned int& out_n_geometry_shader_parts,
2153 	const glw::GLchar* const*& out_vertex_shader_parts, unsigned int& out_n_vertex_shader_parts)
2154 {
2155 	/* Retrieve ES entry-points */
2156 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2157 
2158 	/* Get maximum number of output components */
2159 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_output_components);
2160 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT pname");
2161 
2162 	m_max_output_vectors  = m_max_output_components / 4; /* 4 components per vector */
2163 	m_n_available_vectors = m_max_output_vectors - 2;	/* 2 vectors are reserved for gl_Position and gl_PointSize */
2164 
2165 	/* Fragment shader parts */
2166 	prepareFragmentShader(m_fragment_shader_code);
2167 
2168 	m_fragment_shader_code_c_str = m_fragment_shader_code.c_str();
2169 	out_fragment_shader_parts	= &m_fragment_shader_code_c_str;
2170 	out_n_fragment_shader_parts  = 1;
2171 
2172 	/* Geometry shader parts */
2173 	prepareGeometryShader(m_geometry_shader_code);
2174 
2175 	m_geometry_shader_code_c_str = m_geometry_shader_code.c_str();
2176 	out_geometry_shader_parts	= &m_geometry_shader_code_c_str;
2177 	out_n_geometry_shader_parts  = 1;
2178 
2179 	/* Vertex shader */
2180 	out_vertex_shader_parts   = &m_vertex_shader_code;
2181 	out_n_vertex_shader_parts = 1;
2182 }
2183 
2184 /** Prepare test specific program input for draw call
2185  *
2186  **/
prepareProgramInput()2187 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareProgramInput()
2188 {
2189 	/* Nothing to be done here */
2190 }
2191 
2192 /** Verify rendered image
2193  *
2194  *  @param data Image to verify
2195  *
2196  *  @return true  Image pixels match expected values
2197  *          false Some pixels have wrong values
2198  **/
verifyResult(const void * data)2199 bool GeometryShaderMaxOutputComponentsSinglePointTest::verifyResult(const void* data)
2200 {
2201 	const unsigned char* result_image			= (const unsigned char*)data;
2202 	const unsigned int   line_size				= m_texture_width * m_texture_pixel_size;
2203 	const glw::GLint	 n_components_per_point = m_n_available_vectors * 4; /* 4 components per vector */
2204 
2205 	const glw::GLint first_value	= 1;
2206 	const glw::GLint last_value		= n_components_per_point;
2207 	const glw::GLint expected_value = ((first_value + last_value) * n_components_per_point) / 2;
2208 
2209 	/* Verify all pixels that belong to point, area m_point_size x m_point_size */
2210 	for (unsigned int y = 0; y < m_point_size; ++y)
2211 	{
2212 		const unsigned int line_offset = y * line_size;
2213 
2214 		for (unsigned int x = 0; x < m_point_size; ++x)
2215 		{
2216 			const unsigned int texel_offset = line_offset + x * m_texture_pixel_size;
2217 
2218 			if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
2219 			{
2220 				const glw::GLint* result_value = (const glw::GLint*)(result_image + texel_offset);
2221 
2222 				m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! Expected: " << expected_value
2223 								   << " Extracted: " << *result_value << "  X: " << x << " Y: " << y
2224 								   << tcu::TestLog::EndMessage;
2225 
2226 				return false;
2227 			}
2228 		}
2229 	}
2230 
2231 	return true;
2232 }
2233 
2234 /** Prepare fragment shader code
2235  *
2236  *  @param out_shader_code String that will be used to store shaders code
2237  **/
prepareFragmentShader(std::string & out_shader_code) const2238 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareFragmentShader(std::string& out_shader_code) const
2239 {
2240 	std::stringstream stream;
2241 
2242 	stream << m_fragment_shader_code_preamble;
2243 	stream << m_common_shader_code_gs_fs_out_definitions;
2244 
2245 	for (int i = 0; i < m_n_available_vectors; ++i)
2246 	{
2247 		stream << m_fragment_shader_code_flat_in_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
2248 	}
2249 
2250 	stream << m_fragment_shader_code_body_begin;
2251 
2252 	for (int i = 0; i < m_n_available_vectors; ++i)
2253 	{
2254 		stream << "    " << m_fragment_shader_code_sum << m_common_shader_code_gs_fs_out << i << ".x + "
2255 			   << m_common_shader_code_gs_fs_out << i << ".y + " << m_common_shader_code_gs_fs_out << i << ".z + "
2256 			   << m_common_shader_code_gs_fs_out << i << ".w;\n";
2257 	}
2258 
2259 	stream << m_fragment_shader_code_body_end;
2260 
2261 	out_shader_code = stream.str();
2262 }
2263 
2264 /** Prepare geometry shader code
2265  *
2266  *  @param out_shader_code String that will be used to store shaders code
2267  **/
prepareGeometryShader(std::string & out_shader_code) const2268 void GeometryShaderMaxOutputComponentsSinglePointTest::prepareGeometryShader(std::string& out_shader_code) const
2269 {
2270 	std::stringstream stream;
2271 
2272 	stream << m_geometry_shader_code_preamble;
2273 	stream << m_common_shader_code_gs_fs_out_definitions;
2274 
2275 	for (int i = 0; i < m_n_available_vectors; ++i)
2276 	{
2277 		stream << m_geometry_shader_code_flat_out_ivec4 << " " << m_common_shader_code_gs_fs_out << i << ";\n";
2278 	}
2279 
2280 	stream << m_geometry_shader_code_body_begin;
2281 
2282 	for (int i = 0; i < m_n_available_vectors; ++i)
2283 	{
2284 		stream << "    " << m_common_shader_code_gs_fs_out << i << m_geometry_shader_code_assignment;
2285 	}
2286 
2287 	stream << m_geometry_shader_code_body_end;
2288 
2289 	out_shader_code = stream.str();
2290 }
2291 
2292 /** Constructor
2293  *
2294  * @param context     Test context
2295  * @param name        Test case's name
2296  * @param description Test case's description
2297  **/
GeometryShaderMaxTextureUnitsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2298 GeometryShaderMaxTextureUnitsTest::GeometryShaderMaxTextureUnitsTest(Context& context, const ExtParameters& extParams,
2299 																	 const char* name, const char* description)
2300 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
2301 	, m_texture_width(0)
2302 	, m_max_texture_units(0)
2303 {
2304 	/* Nothing to be done here */
2305 }
2306 
2307 /** Clears data after draw call and result verification
2308  *
2309  **/
clean()2310 void GeometryShaderMaxTextureUnitsTest::clean()
2311 {
2312 	/* GL functions */
2313 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2314 
2315 	/* Bind 0 to all texture units */
2316 	for (int i = 0; i < m_max_texture_units; ++i)
2317 	{
2318 		gl.activeTexture(GL_TEXTURE0 + i);
2319 		gl.bindTexture(GL_TEXTURE_2D, 0);
2320 	}
2321 	gl.activeTexture(GL_TEXTURE0);
2322 
2323 	/* Delete textures */
2324 	for (int i = 0; i < m_max_texture_units; ++i)
2325 	{
2326 		gl.deleteTextures(1, &m_textures[i].texture_id);
2327 	}
2328 
2329 	m_textures.clear();
2330 }
2331 
2332 /** Get details for draw call
2333  *
2334  *  @param out_primitive_type Type of primitive that will be used by next draw call
2335  *  @param out_n_vertices     Number of vertices that will used with next draw call
2336  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)2337 void GeometryShaderMaxTextureUnitsTest::getDrawCallDetails(glw::GLenum& out_primitive_type, glw::GLuint& out_n_vertices)
2338 {
2339 	/* Draw GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points */
2340 	out_primitive_type = GL_POINTS;
2341 	out_n_vertices	 = m_max_texture_units;
2342 }
2343 
2344 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
2345  *
2346  *  @param out_texture_format      Format for texture used as color attachment 0
2347  *  @param out_texture_read_format Format of data used with glReadPixels
2348  *  @param out_texture_read_type   Type of data used with glReadPixels
2349  *  @param out_texture_width       Width of texture used as color attachment 0
2350  *  @param out_texture_height      Height of texture used as color attachment 0
2351  *  @param out_texture_pixel_size  Size of single pixel in bytes
2352  **/
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)2353 void GeometryShaderMaxTextureUnitsTest::getFramebufferDetails(
2354 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
2355 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
2356 {
2357 	out_texture_format		= GL_R32I;
2358 	out_texture_read_format = GL_RGBA_INTEGER;
2359 	out_texture_read_type   = GL_INT;
2360 	out_texture_width		= m_texture_width;
2361 	out_texture_height		= m_texture_height;
2362 	out_texture_pixel_size  = 4 * 4;
2363 }
2364 
getRequiredPointSize(glw::GLfloat & out_point_size)2365 void GeometryShaderMaxTextureUnitsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
2366 {
2367 	/* This test should only run if EXT_geometry_point_size is supported */
2368 	if (!m_is_geometry_shader_point_size_supported)
2369 	{
2370 		throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
2371 	}
2372 
2373 	out_point_size = (float)m_point_size;
2374 }
2375 
2376 /** Get parts of shaders
2377  *
2378  *  @param out_fragment_shader_parts   Array of fragment shader parts
2379  *  @param out_n_fragment_shader_parts Number of fragment shader parts
2380  *  @param out_geometry_shader_parts   Array of geometry shader parts
2381  *  @param out_n_geometry_shader_parts Number of geometry shader parts
2382  *  @param out_vertex_shader_parts     Array of vertex shader parts
2383  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
2384  **/
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)2385 void GeometryShaderMaxTextureUnitsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
2386 													   unsigned int&			  out_n_fragment_shader_parts,
2387 													   const glw::GLchar* const*& out_geometry_shader_parts,
2388 													   unsigned int&			  out_n_geometry_shader_parts,
2389 													   const glw::GLchar* const*& out_vertex_shader_parts,
2390 													   unsigned int&			  out_n_vertex_shader_parts)
2391 {
2392 	/* Retrieve ES entry-points */
2393 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2394 
2395 	/* Get maximum number of texture units */
2396 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_max_texture_units);
2397 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname");
2398 
2399 	/* Number of drawn points is equal to GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */
2400 	m_texture_width = m_max_texture_units * m_point_size;
2401 
2402 	/* Prepare texture units string */
2403 	std::stringstream stream;
2404 	stream << m_max_texture_units;
2405 	m_max_texture_units_string = stream.str();
2406 
2407 	/* Fragment shader parts */
2408 	out_fragment_shader_parts   = &m_fragment_shader_code;
2409 	out_n_fragment_shader_parts = 1;
2410 
2411 	/* Geometry shader parts */
2412 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
2413 	m_geometry_shader_parts[1] = m_max_texture_units_string.c_str();
2414 	m_geometry_shader_parts[2] = m_geometry_shader_code_body;
2415 
2416 	out_geometry_shader_parts   = m_geometry_shader_parts;
2417 	out_n_geometry_shader_parts = 3;
2418 
2419 	/* Vertex shader parts */
2420 	m_vertex_shader_parts[0] = m_vertex_shader_code_preamble;
2421 	m_vertex_shader_parts[1] = m_max_texture_units_string.c_str();
2422 	m_vertex_shader_parts[2] = m_vertex_shader_code_body;
2423 
2424 	out_vertex_shader_parts   = m_vertex_shader_parts;
2425 	out_n_vertex_shader_parts = 3;
2426 }
2427 
2428 /** Prepare test specific program input for draw call
2429  *
2430  **/
prepareProgramInput()2431 void GeometryShaderMaxTextureUnitsTest::prepareProgramInput()
2432 {
2433 	/* Retrieve ES entry-points */
2434 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2435 
2436 	m_textures.resize(m_max_texture_units);
2437 
2438 	/* Prepare texture storage and fill data */
2439 	for (int i = 0; i < m_max_texture_units; ++i)
2440 	{
2441 		/* (starting from 1, delta: 2) */
2442 		m_textures[i].data = i * 2 + 1;
2443 
2444 		/* Generate and bind texture */
2445 		gl.genTextures(1, &m_textures[i].texture_id);
2446 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
2447 
2448 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create texture");
2449 
2450 		/* Allocate and upload texture data */
2451 		gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32I, 1 /* width */, 1 /* height */, 0 /* border */,
2452 					  GL_RED_INTEGER, GL_INT, &m_textures[i].data);
2453 
2454 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2455 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2456 
2457 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create storage and fill texture with data");
2458 	}
2459 
2460 	/* Prepare sampler uniforms */
2461 	for (int i = 0; i < m_max_texture_units; ++i)
2462 	{
2463 		/* Prepare name of sampler */
2464 		std::stringstream stream;
2465 
2466 		stream << "gs_texture[" << i << "]";
2467 
2468 		/* Get sampler location */
2469 		glw::GLint gs_texture_location = gl.getUniformLocation(m_program_object_id, stream.str().c_str());
2470 
2471 		if (-1 == gs_texture_location || (GL_NO_ERROR != gl.getError()))
2472 		{
2473 			TCU_FAIL("Failed to get uniform isampler2D location");
2474 		}
2475 
2476 		/* Set uniform at sampler location value to index of texture unit */
2477 		gl.uniform1i(gs_texture_location, i);
2478 
2479 		if (GL_NO_ERROR != gl.getError())
2480 		{
2481 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to set uniform at location: " << gs_texture_location
2482 							   << " to value: " << i << tcu::TestLog::EndMessage;
2483 
2484 			TCU_FAIL("Failed to get uniform isampler2D location");
2485 		}
2486 	}
2487 
2488 	/* Bind textures to texture units */
2489 	for (int i = 0; i < m_max_texture_units; ++i)
2490 	{
2491 		gl.activeTexture(GL_TEXTURE0 + i);
2492 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
2493 	}
2494 
2495 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set texture units up");
2496 }
2497 
2498 /** Verify rendered image
2499  *
2500  *  @param data Image to verify
2501  *
2502  *  @return true  Image pixels match expected values
2503  *          false Some pixels have wrong values
2504  **/
verifyResult(const void * data)2505 bool GeometryShaderMaxTextureUnitsTest::verifyResult(const void* data)
2506 {
2507 	const unsigned char* result_image = (const unsigned char*)data;
2508 	const unsigned int   line_size	= m_texture_width * m_texture_pixel_size;
2509 
2510 	/* For each drawn point */
2511 	for (glw::GLint point = 0; point < m_max_texture_units; ++point)
2512 	{
2513 		const glw::GLint   first_value	= m_textures[0].data;
2514 		const glw::GLint   last_value	 = m_textures[point].data;
2515 		const glw::GLint   expected_value = ((first_value + last_value) * (point + 1)) / 2;
2516 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
2517 
2518 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
2519 		for (unsigned int y = 0; y < m_point_size; ++y)
2520 		{
2521 			const unsigned int line_offset		  = y * line_size;
2522 			const unsigned int first_texel_offset = line_offset + point_offset;
2523 
2524 			for (unsigned int x = 0; x < m_point_size; ++x)
2525 			{
2526 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
2527 
2528 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
2529 				{
2530 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
2531 
2532 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result! "
2533 																   "Expected: "
2534 									   << expected_value << " Extracted: " << *result_value << " Point: " << point
2535 									   << " X: " << x << " Y: " << y << tcu::TestLog::EndMessage;
2536 
2537 					return false;
2538 				}
2539 			}
2540 		}
2541 	}
2542 
2543 	return true;
2544 }
2545 
2546 /** Constructor
2547  *
2548  * @param context     Test context
2549  * @param name        Test case's name
2550  * @param description Test case's description
2551  **/
GeometryShaderMaxInvocationsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)2552 GeometryShaderMaxInvocationsTest::GeometryShaderMaxInvocationsTest(Context& context, const ExtParameters& extParams,
2553 																   const char* name, const char* description)
2554 	: TestCaseBase(context, extParams, name, description)
2555 	, m_fragment_shader_id_for_multiple_invocations_pass(0)
2556 	, m_geometry_shader_id_for_multiple_invocations_pass(0)
2557 	, m_program_object_id_for_multiple_invocations_pass(0)
2558 	, m_vertex_shader_id_for_multiple_invocations_pass(0)
2559 	, m_fragment_shader_id_for_single_invocation_pass(0)
2560 	, m_geometry_shader_id_for_single_invocation_pass(0)
2561 	, m_program_object_id_for_single_invocation_pass(0)
2562 	, m_vertex_shader_id_for_single_invocation_pass(0)
2563 	, m_max_geometry_shader_invocations(0)
2564 	, m_framebuffer_object_id(0)
2565 	, m_color_texture_id(0)
2566 	, m_texture_width(0)
2567 	, m_vertex_array_object_id(0)
2568 {
2569 	/* Nothing to be done here */
2570 }
2571 
2572 /** Initializes GLES objects used during the test.
2573  *
2574  */
initTest()2575 void GeometryShaderMaxInvocationsTest::initTest()
2576 {
2577 	/* This test should only run if EXT_geometry_shader is supported */
2578 	if (!m_is_geometry_shader_extension_supported)
2579 	{
2580 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2581 	}
2582 
2583 	/* Retrieve ES entry-points */
2584 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2585 
2586 	/* Get GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT */
2587 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_INVOCATIONS, &m_max_geometry_shader_invocations);
2588 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed for GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT");
2589 
2590 	/* Prepare string for GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT */
2591 	std::stringstream stream;
2592 	stream << m_max_geometry_shader_invocations;
2593 	m_max_geometry_shader_invocations_string = stream.str();
2594 
2595 	/* Prepare gemetry shader parts for multiple invocations pass */
2596 	const glw::GLuint n_geometry_shader_parts_for_multiple_invocations_pass = 5;
2597 
2598 	m_geometry_shader_parts_for_multiple_invocations_pass[0] = m_geometry_shader_code_preamble;
2599 	m_geometry_shader_parts_for_multiple_invocations_pass[1] = m_max_geometry_shader_invocations_string.c_str();
2600 	m_geometry_shader_parts_for_multiple_invocations_pass[2] = m_geometry_shader_code_layout;
2601 	m_geometry_shader_parts_for_multiple_invocations_pass[3] = m_geometry_shader_code_layout_invocations;
2602 	m_geometry_shader_parts_for_multiple_invocations_pass[4] = m_geometry_shader_code_body;
2603 
2604 	/* Prepare gemetry shader parts for single invocation pass */
2605 	const glw::GLuint n_geometry_shader_parts_for_single_invocation_pass = 4;
2606 
2607 	m_geometry_shader_parts_for_single_invocation_pass[0] = m_geometry_shader_code_preamble;
2608 	m_geometry_shader_parts_for_single_invocation_pass[1] = m_max_geometry_shader_invocations_string.c_str();
2609 	m_geometry_shader_parts_for_single_invocation_pass[2] = m_geometry_shader_code_layout;
2610 	m_geometry_shader_parts_for_single_invocation_pass[3] = m_geometry_shader_code_body;
2611 
2612 	/* Create program and shaders for multiple GS invocations */
2613 	m_program_object_id_for_multiple_invocations_pass = gl.createProgram();
2614 
2615 	m_fragment_shader_id_for_multiple_invocations_pass = gl.createShader(GL_FRAGMENT_SHADER);
2616 	m_geometry_shader_id_for_multiple_invocations_pass = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
2617 	m_vertex_shader_id_for_multiple_invocations_pass   = gl.createShader(GL_VERTEX_SHADER);
2618 
2619 	/* Create program and shaders for single GS invocations */
2620 	m_program_object_id_for_single_invocation_pass = gl.createProgram();
2621 
2622 	m_fragment_shader_id_for_single_invocation_pass = gl.createShader(GL_FRAGMENT_SHADER);
2623 	m_geometry_shader_id_for_single_invocation_pass = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
2624 	m_vertex_shader_id_for_single_invocation_pass   = gl.createShader(GL_VERTEX_SHADER);
2625 
2626 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program or shader objects");
2627 
2628 	/* Build program for multiple GS invocations */
2629 	if (false == buildProgram(m_program_object_id_for_multiple_invocations_pass,
2630 							  m_fragment_shader_id_for_multiple_invocations_pass, 1, &m_fragment_shader_code,
2631 							  m_geometry_shader_id_for_multiple_invocations_pass,
2632 							  n_geometry_shader_parts_for_multiple_invocations_pass,
2633 							  m_geometry_shader_parts_for_multiple_invocations_pass,
2634 							  m_vertex_shader_id_for_multiple_invocations_pass, 1, &m_vertex_shader_code))
2635 	{
2636 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
2637 	}
2638 
2639 	/* Build program for single GS invocations */
2640 	if (false == buildProgram(m_program_object_id_for_single_invocation_pass,
2641 							  m_fragment_shader_id_for_single_invocation_pass, 1, &m_fragment_shader_code,
2642 							  m_geometry_shader_id_for_single_invocation_pass,
2643 							  n_geometry_shader_parts_for_single_invocation_pass,
2644 							  m_geometry_shader_parts_for_single_invocation_pass,
2645 							  m_vertex_shader_id_for_single_invocation_pass, 1, &m_vertex_shader_code))
2646 	{
2647 		TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
2648 	}
2649 
2650 	/* Set up texture object and a FBO */
2651 	gl.genTextures(1, &m_color_texture_id);
2652 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create texture object");
2653 
2654 	gl.genFramebuffers(1, &m_framebuffer_object_id);
2655 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer object");
2656 
2657 	m_texture_width = m_triangle_edge_length * m_max_geometry_shader_invocations;
2658 
2659 	if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
2660 														 m_texture_width, m_texture_height))
2661 	{
2662 		TCU_FAIL("Failed to setup framebuffer");
2663 	}
2664 
2665 	/* Set up a vertex array object */
2666 	gl.genVertexArrays(1, &m_vertex_array_object_id);
2667 	gl.bindVertexArray(m_vertex_array_object_id);
2668 
2669 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
2670 }
2671 
2672 /** Executes the test.
2673  *
2674  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2675  *
2676  *  Note the function throws exception should an error occur!
2677  *
2678  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2679  **/
iterate()2680 tcu::TestCase::IterateResult GeometryShaderMaxInvocationsTest::iterate()
2681 {
2682 	initTest();
2683 
2684 	/* Variables used for image verification purposes */
2685 	std::vector<unsigned char> result_image(m_texture_width * m_texture_height * m_texture_pixel_size);
2686 
2687 	/* Retrieve ES entry-points */
2688 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2689 
2690 	/* Render with multiple GS invocations */
2691 	gl.useProgram(m_program_object_id_for_multiple_invocations_pass);
2692 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
2693 
2694 	gl.clearColor(255 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
2695 	gl.clear(GL_COLOR_BUFFER_BIT);
2696 
2697 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
2698 
2699 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2700 	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
2701 
2702 	/* Extract image from FBO */
2703 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &result_image[0]);
2704 
2705 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
2706 
2707 	/* Run verification */
2708 	bool result_of_multiple_invocations_pass = verifyResultOfMultipleInvocationsPass(&result_image[0]);
2709 
2710 	/* Render with single GS invocations */
2711 	gl.useProgram(m_program_object_id_for_single_invocation_pass);
2712 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not use program");
2713 
2714 	gl.clearColor(255 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
2715 	gl.clear(GL_COLOR_BUFFER_BIT);
2716 
2717 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
2718 
2719 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
2720 	GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
2721 
2722 	/* Extract image from FBO */
2723 	gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, &result_image[0]);
2724 
2725 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
2726 
2727 	/* Run verification */
2728 	bool result_of_single_invocation_pass = verifyResultOfSingleInvocationPass(&result_image[0]);
2729 
2730 	/* Set test result */
2731 	if (result_of_multiple_invocations_pass && result_of_single_invocation_pass)
2732 	{
2733 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2734 	}
2735 	else
2736 	{
2737 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2738 	}
2739 
2740 	return STOP;
2741 }
2742 
2743 /** Deinitializes GLES objects created during the test.
2744  *
2745  */
deinit()2746 void GeometryShaderMaxInvocationsTest::deinit()
2747 {
2748 	/* Retrieve ES entry-points */
2749 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2750 
2751 	/* Reset OpenGL ES state */
2752 	gl.useProgram(0);
2753 	gl.bindVertexArray(0);
2754 	gl.bindTexture(GL_TEXTURE_2D, 0);
2755 	gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
2756 
2757 	/* Delete everything */
2758 	if (m_program_object_id_for_multiple_invocations_pass != 0)
2759 	{
2760 		gl.deleteProgram(m_program_object_id_for_multiple_invocations_pass);
2761 
2762 		m_program_object_id_for_multiple_invocations_pass = 0;
2763 	}
2764 
2765 	if (m_fragment_shader_id_for_multiple_invocations_pass != 0)
2766 	{
2767 		gl.deleteShader(m_fragment_shader_id_for_multiple_invocations_pass);
2768 
2769 		m_fragment_shader_id_for_multiple_invocations_pass = 0;
2770 	}
2771 
2772 	if (m_geometry_shader_id_for_multiple_invocations_pass != 0)
2773 	{
2774 		gl.deleteShader(m_geometry_shader_id_for_multiple_invocations_pass);
2775 
2776 		m_geometry_shader_id_for_multiple_invocations_pass = 0;
2777 	}
2778 
2779 	if (m_vertex_shader_id_for_multiple_invocations_pass != 0)
2780 	{
2781 		gl.deleteShader(m_vertex_shader_id_for_multiple_invocations_pass);
2782 
2783 		m_vertex_shader_id_for_multiple_invocations_pass = 0;
2784 	}
2785 
2786 	if (m_program_object_id_for_single_invocation_pass != 0)
2787 	{
2788 		gl.deleteProgram(m_program_object_id_for_single_invocation_pass);
2789 
2790 		m_program_object_id_for_single_invocation_pass = 0;
2791 	}
2792 
2793 	if (m_fragment_shader_id_for_single_invocation_pass != 0)
2794 	{
2795 		gl.deleteShader(m_fragment_shader_id_for_single_invocation_pass);
2796 
2797 		m_fragment_shader_id_for_single_invocation_pass = 0;
2798 	}
2799 
2800 	if (m_geometry_shader_id_for_single_invocation_pass != 0)
2801 	{
2802 		gl.deleteShader(m_geometry_shader_id_for_single_invocation_pass);
2803 
2804 		m_geometry_shader_id_for_single_invocation_pass = 0;
2805 	}
2806 
2807 	if (m_vertex_shader_id_for_single_invocation_pass != 0)
2808 	{
2809 		gl.deleteShader(m_vertex_shader_id_for_single_invocation_pass);
2810 
2811 		m_vertex_shader_id_for_single_invocation_pass = 0;
2812 	}
2813 
2814 	if (m_vertex_array_object_id != 0)
2815 	{
2816 		gl.deleteVertexArrays(1, &m_vertex_array_object_id);
2817 
2818 		m_vertex_array_object_id = 0;
2819 	}
2820 
2821 	if (m_color_texture_id != 0)
2822 	{
2823 		gl.deleteTextures(1, &m_color_texture_id);
2824 
2825 		m_color_texture_id = 0;
2826 	}
2827 
2828 	if (m_framebuffer_object_id != 0)
2829 	{
2830 		gl.deleteFramebuffers(1, &m_framebuffer_object_id);
2831 
2832 		m_framebuffer_object_id = 0;
2833 	}
2834 
2835 	/* Deinitilize base class */
2836 	TestCaseBase::deinit();
2837 }
2838 
2839 /** Verify image rendered during draw call for multiple invocations pass
2840  *
2841  *  @param result_image Image data
2842  *
2843  *  @return true  When image is as expected
2844  *          false When image is wrong
2845  **/
verifyResultOfMultipleInvocationsPass(unsigned char * result_image)2846 bool GeometryShaderMaxInvocationsTest::verifyResultOfMultipleInvocationsPass(unsigned char* result_image)
2847 {
2848 	for (unsigned int i = 0; i < (unsigned int)m_max_geometry_shader_invocations; ++i)
2849 	{
2850 		/* Verify that pixel at triangle's center was modified */
2851 		const unsigned int x1 = m_triangle_edge_length * i;
2852 		const unsigned int x2 = m_triangle_edge_length * i;
2853 		const unsigned int x3 = m_triangle_edge_length * (i + 1) - 1;
2854 
2855 		const unsigned int y1 = 0;
2856 		const unsigned int y2 = m_triangle_edge_length - 1;
2857 		const unsigned int y3 = m_triangle_edge_length - 1;
2858 
2859 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2860 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2861 
2862 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2863 										   m_texture_pixel_size, 0, 255, 0, 0);
2864 
2865 		if (false == is_pixel_valid)
2866 		{
2867 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at "
2868 														   "["
2869 							   << center_x << ";" << center_y << "]! "
2870 																 "Triangle index: "
2871 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2872 							   << tcu::TestLog::EndMessage;
2873 
2874 			return false;
2875 		}
2876 
2877 		/* Verify that background's pixel was not modified */
2878 		const unsigned int x4 = m_triangle_edge_length * (i + 1) - 1;
2879 		const unsigned int y4 = m_triangle_edge_length - 1;
2880 
2881 		is_pixel_valid =
2882 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2883 
2884 		if (false == is_pixel_valid)
2885 		{
2886 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2887 							   << "]! "
2888 								  "Background for index: "
2889 							   << i << "from range <0:" << m_max_geometry_shader_invocations << ")."
2890 							   << tcu::TestLog::EndMessage;
2891 
2892 			return false;
2893 		}
2894 	}
2895 
2896 	return true;
2897 }
2898 
2899 /** Verify image rendered during draw call for single invocation pass
2900  *
2901  *  @param result_image Image data
2902  *
2903  *  @return true  When image is as expected
2904  *          false When image is wrong
2905  **/
verifyResultOfSingleInvocationPass(unsigned char * result_image)2906 bool GeometryShaderMaxInvocationsTest::verifyResultOfSingleInvocationPass(unsigned char* result_image)
2907 {
2908 	/* Only one triangle should be drawn, verify that pixel at its center was modified */
2909 	{
2910 		const unsigned int x1 = 0;
2911 		const unsigned int x2 = 0;
2912 		const unsigned int x3 = m_triangle_edge_length - 1;
2913 
2914 		const unsigned int y1 = 0;
2915 		const unsigned int y2 = m_triangle_edge_length - 1;
2916 		const unsigned int y3 = m_triangle_edge_length - 1;
2917 
2918 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2919 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2920 
2921 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2922 										   m_texture_pixel_size, 0, 255, 0, 0);
2923 
2924 		if (false == is_pixel_valid)
2925 		{
2926 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << center_x << ";" << center_y
2927 							   << "]! "
2928 								  "Triangle index: "
2929 							   << 0 << " from range <0:" << m_max_geometry_shader_invocations << ")."
2930 							   << tcu::TestLog::EndMessage;
2931 
2932 			return false;
2933 		}
2934 
2935 		/* Verify that background's pixel was not modified */
2936 		const unsigned int x4 = m_triangle_edge_length - 1;
2937 		const unsigned int y4 = m_triangle_edge_length - 1;
2938 
2939 		is_pixel_valid =
2940 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2941 
2942 		if (false == is_pixel_valid)
2943 		{
2944 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2945 							   << "]! "
2946 								  "Background for index: "
2947 							   << 0 << " from range <0:" << m_max_geometry_shader_invocations << ")."
2948 							   << tcu::TestLog::EndMessage;
2949 
2950 			return false;
2951 		}
2952 	}
2953 
2954 	for (unsigned int i = 1; i < (unsigned int)m_max_geometry_shader_invocations; ++i)
2955 	{
2956 		/* Verify that pixel at triangle's center was not modified */
2957 		const unsigned int x1 = m_triangle_edge_length * i;
2958 		const unsigned int x2 = m_triangle_edge_length * i;
2959 		const unsigned int x3 = m_triangle_edge_length * (i + 1) - 1;
2960 
2961 		const unsigned int y1 = 0;
2962 		const unsigned int y2 = m_triangle_edge_length - 1;
2963 		const unsigned int y3 = m_triangle_edge_length - 1;
2964 
2965 		const unsigned int center_x = (x1 + x2 + x3) / 3;
2966 		const unsigned int center_y = (y1 + y2 + y3) / 3;
2967 
2968 		bool is_pixel_valid = comparePixel(result_image, center_x, center_y, m_texture_width, m_texture_height,
2969 										   m_texture_pixel_size, 255, 0, 0, 0);
2970 
2971 		if (false == is_pixel_valid)
2972 		{
2973 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << center_x << ";" << center_y
2974 							   << "]! "
2975 								  "Triangle index: "
2976 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2977 							   << tcu::TestLog::EndMessage;
2978 
2979 			return false;
2980 		}
2981 
2982 		/* Verify that background's pixel was not modified */
2983 		const unsigned int x4 = m_triangle_edge_length * (i + 1) - 1;
2984 		const unsigned int y4 = m_triangle_edge_length - 1;
2985 
2986 		is_pixel_valid =
2987 			comparePixel(result_image, x4, y4, m_texture_width, m_texture_height, m_texture_pixel_size, 255, 0, 0, 0);
2988 
2989 		if (false == is_pixel_valid)
2990 		{
2991 			m_testCtx.getLog() << tcu::TestLog::Message << "Invalid pixel at [" << x4 << ";" << y4
2992 							   << "]! "
2993 								  "Background for index: "
2994 							   << i << " from range <0:" << m_max_geometry_shader_invocations << ")."
2995 							   << tcu::TestLog::EndMessage;
2996 
2997 			return false;
2998 		}
2999 	}
3000 
3001 	return true;
3002 }
3003 
3004 /** Constructor
3005  *
3006  * @param context       Test context
3007  * @param name          Test case's name
3008  * @param description   Test case's description
3009  **/
GeometryShaderMaxCombinedTextureUnitsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)3010 GeometryShaderMaxCombinedTextureUnitsTest::GeometryShaderMaxCombinedTextureUnitsTest(Context&			  context,
3011 																					 const ExtParameters& extParams,
3012 																					 const char*		  name,
3013 																					 const char*		  description)
3014 	: GeometryShaderLimitsRenderingBase(context, extParams, name, description)
3015 	, m_texture_width(0)
3016 	, m_max_combined_texture_units(0)
3017 	, m_max_fragment_texture_units(0)
3018 	, m_max_geometry_texture_units(0)
3019 	, m_max_vertex_texture_units(0)
3020 	, m_min_texture_units(0)
3021 	, m_n_fragment_texture_units(0)
3022 	, m_n_geometry_texture_units(0)
3023 	, m_n_texture_units(0)
3024 	, m_n_vertex_texture_units(0)
3025 {
3026 	/* Nothing to be done here */
3027 }
3028 
3029 /** Clears data after draw call and result verification
3030  *
3031  **/
clean()3032 void GeometryShaderMaxCombinedTextureUnitsTest::clean()
3033 {
3034 	/* GL functions */
3035 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3036 
3037 	/* Bind 0 to all texture units */
3038 	for (int i = 0; i < m_n_texture_units; ++i)
3039 	{
3040 		gl.activeTexture(GL_TEXTURE0 + i);
3041 		gl.bindTexture(GL_TEXTURE_2D, 0);
3042 	}
3043 
3044 	/* Delete textures */
3045 	for (int i = 0; i < m_n_texture_units; ++i)
3046 	{
3047 		gl.deleteTextures(1, &m_textures[i].texture_id);
3048 	}
3049 
3050 	m_textures.clear();
3051 }
3052 
3053 /** Get details for draw call
3054  *
3055  *  @param out_primitive_type Type of primitive that will be used by next draw call
3056  *  @param out_n_vertices     Number of vertices that will used with next draw call
3057  **/
getDrawCallDetails(glw::GLenum & out_primitive_type,glw::GLuint & out_n_vertices)3058 void GeometryShaderMaxCombinedTextureUnitsTest::getDrawCallDetails(glw::GLenum& out_primitive_type,
3059 																   glw::GLuint& out_n_vertices)
3060 {
3061 	/* Draw GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT points */
3062 	out_primitive_type = GL_POINTS;
3063 	out_n_vertices	 = m_min_texture_units;
3064 }
3065 
3066 /** Get dimensions and format for texture bind to color attachment 0, get format and type for glReadPixels
3067  *
3068  *  @param out_texture_format      Format for texture used as color attachment 0
3069  *  @param out_texture_read_format Format of data used with glReadPixels
3070  *  @param out_texture_read_type   Type of data used with glReadPixels
3071  *  @param out_texture_width       Width of texture used as color attachment 0
3072  *  @param out_texture_height      Height of texture used as color attachment 0
3073  *  @param out_texture_pixel_size  Size of single pixel in bytes
3074  **/
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)3075 void GeometryShaderMaxCombinedTextureUnitsTest::getFramebufferDetails(
3076 	glw::GLenum& out_texture_format, glw::GLenum& out_texture_read_format, glw::GLenum& out_texture_read_type,
3077 	glw::GLuint& out_texture_width, glw::GLuint& out_texture_height, unsigned int& out_texture_pixel_size)
3078 {
3079 	out_texture_format		= GL_R32UI;
3080 	out_texture_read_format = GL_RGBA_INTEGER;
3081 	out_texture_read_type   = GL_UNSIGNED_INT;
3082 	out_texture_width		= m_texture_width;
3083 	out_texture_height		= m_texture_height;
3084 	out_texture_pixel_size  = 4 * 4;
3085 }
3086 
getRequiredPointSize(glw::GLfloat & out_point_size)3087 void GeometryShaderMaxCombinedTextureUnitsTest::getRequiredPointSize(glw::GLfloat& out_point_size)
3088 {
3089 	out_point_size = (float)m_point_size;
3090 }
3091 
3092 /** Get parts of shaders
3093  *
3094  *  @param out_fragment_shader_parts   Array of fragment shader parts
3095  *  @param out_n_fragment_shader_parts Number of fragment shader parts
3096  *  @param out_geometry_shader_parts   Array of geometry shader parts
3097  *  @param out_n_geometry_shader_parts Number of geometry shader parts
3098  *  @param out_vertex_shader_parts     Array of vertex shader parts
3099  *  @param out_n_vertex_shader_parts   Number of vertex shader parts
3100  **/
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)3101 void GeometryShaderMaxCombinedTextureUnitsTest::getShaderParts(const glw::GLchar* const*& out_fragment_shader_parts,
3102 															   unsigned int&			  out_n_fragment_shader_parts,
3103 															   const glw::GLchar* const*& out_geometry_shader_parts,
3104 															   unsigned int&			  out_n_geometry_shader_parts,
3105 															   const glw::GLchar* const*& out_vertex_shader_parts,
3106 															   unsigned int&			  out_n_vertex_shader_parts)
3107 {
3108 	/* GL functions */
3109 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3110 
3111 	/* Get maximum number of texture units */
3112 	gl.getIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &m_max_combined_texture_units);
3113 	gl.getIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &m_max_vertex_texture_units);
3114 	gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_max_geometry_texture_units);
3115 	gl.getIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &m_max_fragment_texture_units);
3116 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call(s) failed");
3117 
3118 	m_n_texture_units =
3119 		de::max(m_max_vertex_texture_units, de::max(m_max_geometry_texture_units, m_max_fragment_texture_units));
3120 	m_n_vertex_texture_units = de::max(1, de::min(m_max_combined_texture_units - 2, m_max_vertex_texture_units));
3121 	m_n_fragment_texture_units =
3122 		de::max(1, de::min(m_max_combined_texture_units - m_n_vertex_texture_units - 1, m_max_fragment_texture_units));
3123 	m_n_geometry_texture_units =
3124 		de::max(1, de::min(m_max_combined_texture_units - m_n_vertex_texture_units - m_n_fragment_texture_units,
3125 						   m_max_geometry_texture_units));
3126 	m_min_texture_units =
3127 		de::min(m_n_vertex_texture_units, de::min(m_n_fragment_texture_units, m_n_geometry_texture_units));
3128 
3129 	/* Number of drawn points is equal to GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT */
3130 	m_texture_width = m_n_texture_units * m_point_size;
3131 
3132 	/* Prepare texture units string */
3133 	std::stringstream stream_fragment;
3134 	stream_fragment << m_n_fragment_texture_units;
3135 	m_n_fragment_texture_units_string = stream_fragment.str();
3136 
3137 	std::stringstream stream_geometry;
3138 	stream_geometry << m_n_geometry_texture_units;
3139 	m_n_geometry_texture_units_string = stream_geometry.str();
3140 
3141 	std::stringstream stream_vertex;
3142 	stream_vertex << m_n_vertex_texture_units;
3143 	m_n_vertex_texture_units_string = stream_vertex.str();
3144 
3145 	/* Fragment shader parts */
3146 	m_fragment_shader_parts[0] = m_fragment_shader_code_preamble;
3147 	m_fragment_shader_parts[1] = m_n_fragment_texture_units_string.c_str();
3148 	m_fragment_shader_parts[2] = m_fragment_shader_code_body;
3149 
3150 	out_fragment_shader_parts   = m_fragment_shader_parts;
3151 	out_n_fragment_shader_parts = 3;
3152 
3153 	/* Geometry shader parts */
3154 	m_geometry_shader_parts[0] = m_geometry_shader_code_preamble;
3155 	m_geometry_shader_parts[1] = m_n_geometry_texture_units_string.c_str();
3156 	m_geometry_shader_parts[2] = m_geometry_shader_code_body;
3157 
3158 	out_geometry_shader_parts   = m_geometry_shader_parts;
3159 	out_n_geometry_shader_parts = 3;
3160 
3161 	/* Vertex shader parts */
3162 	m_vertex_shader_parts[0] = m_vertex_shader_code_preamble;
3163 	m_vertex_shader_parts[1] = m_n_vertex_texture_units_string.c_str();
3164 	m_vertex_shader_parts[2] = m_vertex_shader_code_body;
3165 
3166 	out_vertex_shader_parts   = m_vertex_shader_parts;
3167 	out_n_vertex_shader_parts = 3;
3168 }
3169 
3170 /** Prepare test specific program input for draw call
3171  *
3172  **/
prepareProgramInput()3173 void GeometryShaderMaxCombinedTextureUnitsTest::prepareProgramInput()
3174 {
3175 	/* Retrieve ES entry-points */
3176 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3177 
3178 	m_textures.resize(m_n_texture_units);
3179 
3180 	/* Prepare texture storage and fill data */
3181 	for (int i = 0; i < m_n_texture_units; ++i)
3182 	{
3183 		/* unique intensity equal to index of the texture */
3184 		m_textures[i].data = i;
3185 
3186 		/* Generate and bind texture */
3187 		gl.genTextures(1, &m_textures[i].texture_id);
3188 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
3189 
3190 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create texture");
3191 
3192 		/* Allocate and upload texture data */
3193 		gl.texImage2D(GL_TEXTURE_2D, 0 /* level */, GL_R32UI, 1 /* width*/, 1 /* height */, 0 /* border */,
3194 					  GL_RED_INTEGER, GL_UNSIGNED_INT, &m_textures[i].data);
3195 
3196 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3197 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3198 
3199 		GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create storage and fill texture with data");
3200 	}
3201 
3202 	/* Prepare sampler uniforms */
3203 	for (int i = 0; i < m_n_texture_units; ++i)
3204 	{
3205 		/* Prepare name of sampler */
3206 		std::stringstream stream;
3207 
3208 		stream << "sampler[" << i << "]";
3209 
3210 		/* Get sampler location */
3211 		glw::GLint sampler_location = gl.getUniformLocation(m_program_object_id, stream.str().c_str());
3212 
3213 		if (-1 == sampler_location || GL_NO_ERROR != gl.getError())
3214 		{
3215 			TCU_FAIL("Failed to get uniform usampler2D location");
3216 		}
3217 
3218 		/* Set uniform at sampler location value to index of texture unit */
3219 		gl.uniform1i(sampler_location, i);
3220 
3221 		if (GL_NO_ERROR != gl.getError())
3222 		{
3223 			m_testCtx.getLog() << tcu::TestLog::Message << "Failed to set uniform at location: " << sampler_location
3224 							   << " to value: " << i << tcu::TestLog::EndMessage;
3225 
3226 			TCU_FAIL("Failed to get uniform isampler2D location");
3227 		}
3228 	}
3229 
3230 	/* Bind textures to texture units */
3231 	for (int i = 0; i < m_n_texture_units; ++i)
3232 	{
3233 		gl.activeTexture(GL_TEXTURE0 + i);
3234 		gl.bindTexture(GL_TEXTURE_2D, m_textures[i].texture_id);
3235 
3236 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3237 		gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3238 	}
3239 
3240 	GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set texture units up");
3241 }
3242 
3243 /** Verify rendered image
3244  *
3245  *  @param data Image to verify
3246  *
3247  *  @return true  Image pixels match expected values
3248  *          false Some pixels have wrong values
3249  **/
verifyResult(const void * data)3250 bool GeometryShaderMaxCombinedTextureUnitsTest::verifyResult(const void* data)
3251 {
3252 	const unsigned char* result_image = (const unsigned char*)data;
3253 	const unsigned int   line_size	= m_texture_width * m_texture_pixel_size;
3254 
3255 	/* For each drawn point */
3256 	for (glw::GLint point = 0; point < m_n_texture_units; ++point)
3257 	{
3258 		const unsigned int last_vertex_index = de::min(point, m_n_vertex_texture_units);
3259 
3260 		glw::GLint expected_vertex_value   = 0;
3261 		glw::GLint expected_geometry_value = 0;
3262 		glw::GLint expected_fragment_value = 0;
3263 
3264 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3265 		{
3266 			expected_vertex_value += m_textures[i].data;
3267 		}
3268 
3269 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3270 		{
3271 			expected_geometry_value += m_textures[i].data;
3272 		}
3273 
3274 		for (unsigned int i = 0; i < last_vertex_index; ++i)
3275 		{
3276 			expected_fragment_value += m_textures[i].data;
3277 		}
3278 
3279 		const glw::GLint   expected_value = expected_vertex_value + expected_geometry_value + expected_fragment_value;
3280 		const unsigned int point_offset   = point * m_texture_pixel_size * m_point_size;
3281 
3282 		/* Verify all pixels that belong to point, area m_point_size x m_point_size */
3283 		for (unsigned int y = 0; y < m_point_size; ++y)
3284 		{
3285 			const unsigned int line_offset		  = y * line_size;
3286 			const unsigned int first_texel_offset = line_offset + point_offset;
3287 
3288 			for (unsigned int x = 0; x < m_point_size; ++x)
3289 			{
3290 				const unsigned int texel_offset = first_texel_offset + x * m_texture_pixel_size;
3291 
3292 				if (0 != memcmp(result_image + texel_offset, &expected_value, sizeof(expected_value)))
3293 				{
3294 					glw::GLint* result_value = (glw::GLint*)(result_image + texel_offset);
3295 
3296 					m_testCtx.getLog() << tcu::TestLog::Message << "Wrong result!"
3297 																   " Expected: "
3298 									   << expected_value << " Extracted: " << *result_value << " Point: " << point
3299 									   << " X: " << x << " Y: " << y << tcu::TestLog::EndMessage;
3300 
3301 					return false;
3302 				}
3303 			}
3304 		}
3305 	}
3306 
3307 	return true;
3308 }
3309 
3310 } /* glcts */
3311