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