Home | History | Annotate | Download | only in geometry_shader
      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  **/
    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  */
    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  **/
    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  */
    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  **/
    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  */
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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 
   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  **/
   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  **/
   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  **/
   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  **/
   1923 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  **/
   1953 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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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 
   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  **/
   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  **/
   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  **/
   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  **/
   2238 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  **/
   2268 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  **/
   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  **/
   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  **/
   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  **/
   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 
   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  **/
   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  **/
   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  **/
   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  **/
   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  */
   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  **/
   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  */
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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  **/
   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 
   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  **/
   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  **/
   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  **/
   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