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