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