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