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 #include "esextcGeometryShaderInput.hpp"
25
26 #include "gluContextInfo.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 #include <cstring>
31
32 namespace glcts
33 {
34 /* Vertex shader for GeometryShader_gl_in_ArrayContents */
35 const char* const GeometryShader_gl_in_ArrayContentsTest::m_vertex_shader_code =
36 "${VERSION}\n"
37 "\n"
38 " out vec2 vs_gs_a;\n"
39 "flat out ivec4 vs_gs_b;\n"
40 "\n"
41 "void main()\n"
42 "{\n"
43 " vs_gs_a = vec2 (gl_VertexID, 0);\n"
44 " vs_gs_b = ivec4(0, gl_VertexID, 0, 1);\n"
45 "}\n";
46
47 /* Geometry shader for GeometryShader_gl_in_ArrayContents */
48 const char* const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_preamble_code =
49 "${VERSION}\n"
50 "\n"
51 "${GEOMETRY_SHADER_REQUIRE}\n"
52 "\n"
53 "layout(triangles) in;\n"
54 "layout(triangle_strip, max_vertices=3) out;\n"
55 "\n";
56
57 const char* const GeometryShader_gl_in_ArrayContentsTest::m_geometry_shader_code =
58 "#ifdef USE_UNSIZED_ARRAYS\n"
59 " in vec2 vs_gs_a[];\n"
60 " flat in ivec4 vs_gs_b[];\n"
61 "#else\n"
62 " in vec2 vs_gs_a[3];\n"
63 " flat in ivec4 vs_gs_b[3];\n"
64 "#endif\n"
65 "\n"
66 " out vec2 gs_fs_a;\n"
67 "flat out ivec4 gs_fs_b;\n"
68 "\n"
69 "void main()\n"
70 "{\n"
71 " gl_Position = vec4(-1, -1, 0, 1);\n"
72 " gs_fs_a = vs_gs_a[0];\n"
73 " gs_fs_b = vs_gs_b[0];\n"
74 " EmitVertex();\n"
75 " \n"
76 " gl_Position = vec4(-1, 1, 0, 1);\n"
77 " gs_fs_a = vs_gs_a[1];\n"
78 " gs_fs_b = vs_gs_b[1];\n"
79 " EmitVertex();\n"
80 " \n"
81 " gl_Position = vec4(1, 1, 0, 1);\n"
82 " gs_fs_a = vs_gs_a[2];\n"
83 " gs_fs_b = vs_gs_b[2];\n"
84 " EmitVertex();\n"
85 " \n"
86 " EndPrimitive();\n"
87 "}\n";
88
89 /* Fragment shader for GeometryShader_gl_in_ArrayContents */
90 const char* const GeometryShader_gl_in_ArrayContentsTest::m_fragment_shader_code =
91 "${VERSION}\n"
92 "\n"
93 "precision highp float;\n"
94 "\n"
95 "layout(location = 0) out vec4 fs_out_color;\n"
96 "\n"
97 "void main()\n"
98 "{\n"
99 " fs_out_color = vec4(1, 1, 1, 1);\n"
100 "}\n";
101
102 /* Vertex Shader for GeometryShader_gl_in_ArrayLengthTest*/
103 const char* const GeometryShader_gl_in_ArrayLengthTest::m_vertex_shader_code =
104 "${VERSION}\n"
105 "\n"
106 "void main()\n"
107 "{\n"
108 " gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
109 "}\n";
110
111 /* Geometry shader body parts for GeometryShader_gl_in_ArrayLengthTest */
112 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_preamble = "${VERSION}\n"
113 "\n"
114 "${GEOMETRY_SHADER_REQUIRE}\n"
115 "\n";
116
117 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_points =
118 "layout(points) in;\n";
119
120 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines =
121 "layout(lines) in;\n";
122
123 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_lines_with_adjacency =
124 "layout(lines_adjacency) in;\n";
125
126 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles =
127 "layout(triangles) in;\n";
128
129 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_input_triangles_with_adjacency =
130 "layout(triangles_adjacency) in;\n";
131
132 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_points =
133 "layout(points, max_vertices=1) out;\n"
134 "\n"
135 "#define N_OUT_VERTICES (1)\n";
136
137 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_line_strip =
138 "layout(line_strip, max_vertices=2) out;\n"
139 "\n"
140 "#define N_OUT_VERTICES (2)\n";
141
142 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_output_triangle_strip =
143 "layout(triangle_strip, max_vertices=3) out;\n"
144 "\n"
145 "#define N_OUT_VERTICES (3)\n";
146
147 const char* const GeometryShader_gl_in_ArrayLengthTest::m_geometry_shader_code_main =
148 "\n"
149 "flat out int in_array_size;\n"
150 "\n"
151 "void main()\n"
152 "{\n"
153 " for (int n = 0; n < N_OUT_VERTICES; n++)\n"
154 " {\n"
155 " in_array_size = gl_in.length();\n"
156 " EmitVertex();\n"
157 " }\n"
158 "\n"
159 " EndPrimitive();\n"
160 "}\n";
161
162 /* Fragment Shader for GeometryShader_gl_in_ArrayLengthTest */
163 const char* const GeometryShader_gl_in_ArrayLengthTest::m_fragment_shader_code = "${VERSION}\n"
164 "\n"
165 "precision highp float;\n"
166 "\n"
167 "void main()\n"
168 "{\n"
169 "}\n";
170
171 /* Vertex Shader for GeometryShader_gl_PointSize_ValueTest */
172 const char* const GeometryShader_gl_PointSize_ValueTest::m_vertex_shader_code =
173 "${VERSION}\n"
174 "\n"
175 "void main()\n"
176 "{\n"
177 " // See test description for explanation of magic numbers\n"
178 " switch (gl_VertexID)\n"
179 " {\n"
180 " case 0:\n"
181 " {\n"
182 " gl_Position = vec4(-7.0/8.0, 0, 0, 1);\n"
183 "\n"
184 " break;\n"
185 " }\n"
186 "\n"
187 " case 1:\n"
188 " {\n"
189 " gl_Position = vec4(6.0/8.0, 0, 0, 1);\n"
190 "\n"
191 " break;\n"
192 " }\n"
193 " }\n"
194 "\n"
195 " gl_PointSize = float(2 * (gl_VertexID + 1));\n"
196 "}\n";
197
198 /* Geometry Shader for GeometryShader_gl_PointSize_ValueTest */
199 const char* const GeometryShader_gl_PointSize_ValueTest::m_geometry_shader_code =
200 "${VERSION}\n"
201 "\n"
202 "${GEOMETRY_SHADER_REQUIRE}\n"
203 "${GEOMETRY_POINT_SIZE_REQUIRE}\n"
204 "\n"
205 "layout(points) in;\n"
206 "layout(points, max_vertices=1) out;\n"
207 "\n"
208 "void main()\n"
209 "{\n"
210 " gl_Position = gl_in[0].gl_Position;\n"
211 " gl_PointSize = gl_in[0].gl_PointSize * 2.0;\n"
212 " EmitVertex();\n"
213 " \n"
214 " EndPrimitive();\n"
215 "}\n";
216
217 /* Fragment Shader for GeometryShader_gl_PointSize_ValueTest */
218 const char* const GeometryShader_gl_PointSize_ValueTest::m_fragment_shader_code =
219 "${VERSION}\n"
220 "\n"
221 "precision highp float;\n"
222 "\n"
223 "layout(location = 0) out vec4 fs_out_color;\n"
224 "\n"
225 "void main()\n"
226 "{\n"
227 " fs_out_color = vec4(1, 1, 1, 1);\n"
228 "}\n";
229
230 /* Vertex Shader for GeometryShader_gl_Position_ValueTest */
231 const char* const GeometryShader_gl_Position_ValueTest::m_vertex_shader_code =
232 "${VERSION}\n"
233 "\n"
234 "void main()\n"
235 "{\n"
236 " gl_Position = vec4(gl_VertexID, gl_VertexID, 0, 1);\n"
237 "\n"
238 "}\n";
239
240 /* Geometry Shader for GeometryShader_gl_Position_ValueTest */
241 const char* const GeometryShader_gl_Position_ValueTest::m_geometry_shader_code =
242 "${VERSION}\n"
243 "\n"
244 "${GEOMETRY_SHADER_REQUIRE}\n"
245 "${GEOMETRY_POINT_SIZE_REQUIRE}\n"
246 "\n"
247 "layout(points) in;\n"
248 "layout(points, max_vertices=1) out;\n"
249 "\n"
250 "void main()\n"
251 "{\n"
252 " // See test description for discussion on the magic numbers\n"
253 " gl_Position = vec4(-1.0 + 4.0/32.0 + gl_in[0].gl_Position.x / 4.0, 0, 0, 1);\n"
254 " gl_PointSize = 8.0;\n"
255 " EmitVertex();\n"
256 "\n"
257 " EndPrimitive();\n"
258 "}\n";
259
260 /* Fragment Shader for GeometryShader_gl_Position_ValueTest */
261 const char* const GeometryShader_gl_Position_ValueTest::m_fragment_shader_code =
262 "${VERSION}\n"
263 "\n"
264 "precision highp float;\n"
265 "\n"
266 "layout(location = 0) out vec4 fs_out_color;\n"
267 "\n"
268 "void main()\n"
269 "{\n"
270 " fs_out_color = vec4(1, 1, 1, 1);\n"
271 "}\n";
272
273 /* Constants for GeometryShader_gl_in_ArrayContentsTest */
274 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex =
275 2 * sizeof(glw::GLfloat) + 4 * sizeof(glw::GLint);
276 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives = 1;
277 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive = 3;
278
279 const unsigned int GeometryShader_gl_in_ArrayContentsTest::m_buffer_size =
280 GeometryShader_gl_in_ArrayContentsTest::m_n_bytes_emitted_per_vertex *
281 GeometryShader_gl_in_ArrayContentsTest::m_n_vertices_emitted_per_primitive *
282 GeometryShader_gl_in_ArrayContentsTest::m_n_emitted_primitives;
283
284 /* Constants for GeometryShader_gl_in_ArrayLengthTest */
285 const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_max_primitive_emitted = 6;
286 const glw::GLuint GeometryShader_gl_in_ArrayLengthTest::m_buffer_size = sizeof(glw::GLint) * m_max_primitive_emitted;
287
288 /* Constants for GeometryShader_gl_PointSize_ValueTest */
289 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_height = 16;
290 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_pixel_size = 4;
291 const glw::GLuint GeometryShader_gl_PointSize_ValueTest::m_texture_width = 16;
292
293 /* Constants for GeometryShader_gl_Position_ValueTest */
294 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_height = 64;
295 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_pixel_size = 4;
296 const glw::GLuint GeometryShader_gl_Position_ValueTest::m_texture_width = 64;
297
298 /** Constructor
299 *
300 * @param context Test context
301 * @param name Test case's name
302 * @param description Test case's desricption
303 **/
GeometryShader_gl_in_ArrayContentsTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)304 GeometryShader_gl_in_ArrayContentsTest::GeometryShader_gl_in_ArrayContentsTest(Context& context,
305 const ExtParameters& extParams,
306 const char* name,
307 const char* description)
308 : TestCaseBase(context, extParams, name, description)
309 , m_fragment_shader_id(0)
310 , m_geometry_shader_sized_arrays_id(0)
311 , m_geometry_shader_unsized_arrays_id(0)
312 , m_program_object_sized_arrays_id(0)
313 , m_program_object_unsized_arrays_id(0)
314 , m_vertex_shader_id(0)
315 , m_buffer_object_id(0)
316 , m_vertex_array_object_id(0)
317 {
318 /* Nothing to be done here */
319 }
320
321 /** Initializes GLES objects used during the test.
322 *
323 **/
initTest()324 void GeometryShader_gl_in_ArrayContentsTest::initTest()
325 {
326 /* Varing names */
327 const glw::GLchar* const captured_varyings[] = {
328 "gs_fs_a", "gs_fs_b",
329 };
330
331 /* Number of varings */
332 const glw::GLuint n_captured_varyings_size = sizeof(captured_varyings) / sizeof(captured_varyings[0]);
333
334 /* GL */
335 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
336
337 /* Create program and shaders */
338 m_program_object_sized_arrays_id = gl.createProgram();
339 m_program_object_unsized_arrays_id = gl.createProgram();
340
341 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
342 m_geometry_shader_unsized_arrays_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
343 m_geometry_shader_sized_arrays_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
344 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
345
346 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
347
348 /* Set up transform feedback */
349 gl.transformFeedbackVaryings(m_program_object_sized_arrays_id, n_captured_varyings_size, captured_varyings,
350 GL_INTERLEAVED_ATTRIBS);
351 gl.transformFeedbackVaryings(m_program_object_unsized_arrays_id, n_captured_varyings_size, captured_varyings,
352 GL_INTERLEAVED_ATTRIBS);
353
354 /* Build programs */
355 const char* geometry_shader_unsized_arrays_code[] = { m_geometry_shader_preamble_code,
356 "#define USE_UNSIZED_ARRAYS\n", m_geometry_shader_code };
357 const char* geometry_shader_sized_arrays_code[] = { m_geometry_shader_preamble_code, m_geometry_shader_code };
358
359 if (false ==
360 buildProgram(m_program_object_unsized_arrays_id, m_fragment_shader_id, 1 /* number of fragment shader parts */,
361 &m_fragment_shader_code, m_geometry_shader_unsized_arrays_id,
362 DE_LENGTH_OF_ARRAY(geometry_shader_unsized_arrays_code), geometry_shader_unsized_arrays_code,
363 m_vertex_shader_id, 1 /* number of vertex shader parts */, &m_vertex_shader_code))
364 {
365 TCU_FAIL("Could not create a program from valid vertex/geometry (unsized arrays version)/fragment shaders");
366 }
367
368 if (false == buildProgram(m_program_object_sized_arrays_id, m_fragment_shader_id,
369 1 /* number of fragment shader parts */, &m_fragment_shader_code,
370 m_geometry_shader_sized_arrays_id, DE_LENGTH_OF_ARRAY(geometry_shader_sized_arrays_code),
371 geometry_shader_sized_arrays_code, m_vertex_shader_id,
372 1 /* number of vertex shader parts */, &m_vertex_shader_code))
373 {
374 TCU_FAIL("Could not create a program from valid vertex/geometry (sized arrays version)/fragment shaders");
375 }
376
377 /* Generate, bind and allocate buffer */
378 gl.genBuffers(1, &m_buffer_object_id);
379 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
380 gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
381
382 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
383
384 /* Generate and bind VAO */
385 gl.genVertexArrays(1, &m_vertex_array_object_id);
386 gl.bindVertexArray(m_vertex_array_object_id);
387
388 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
389 }
390
391 /** Executes the test.
392 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
393 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
394 * Note the function throws exception should an error occur!
395 **/
iterate()396 tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayContentsTest::iterate()
397 {
398 /* This test should only run if EXT_geometry_shader is supported */
399 if (true != m_is_geometry_shader_extension_supported)
400 {
401 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
402 }
403
404 initTest();
405
406 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
407 unsigned char reference_data[m_buffer_size] = { 0 };
408 bool result = true;
409
410 /* Prepare reference data */
411 {
412 glw::GLint* ivec4_data_ptr;
413 glw::GLfloat* vec2_data_ptr;
414
415 const unsigned int ivec4_offset_from_vertex = 2 * sizeof(glw::GLfloat);
416 const unsigned int vec2_offset_from_vertex = 0;
417
418 /* Expected data for vertex:
419 * vec2 = {VertexID, 0.0f}
420 * ivec4 = {0, VertexID, 0, 1}
421 */
422 for (unsigned int vertex_id = 0; vertex_id < m_n_vertices_emitted_per_primitive * m_n_emitted_primitives;
423 ++vertex_id)
424 {
425 const unsigned int vertex_offset = vertex_id * m_n_bytes_emitted_per_vertex;
426 const unsigned int ivec4_offset = vertex_offset + ivec4_offset_from_vertex;
427 const unsigned int vec2_offset = vertex_offset + vec2_offset_from_vertex;
428
429 ivec4_data_ptr = (glw::GLint*)(reference_data + ivec4_offset);
430 vec2_data_ptr = (glw::GLfloat*)(reference_data + vec2_offset);
431
432 ivec4_data_ptr[0] = 0;
433 ivec4_data_ptr[1] = vertex_id;
434 ivec4_data_ptr[2] = 0;
435 ivec4_data_ptr[3] = 1;
436
437 vec2_data_ptr[0] = (float)vertex_id;
438 vec2_data_ptr[1] = 0.0f;
439 }
440 }
441
442 /* Setup transform feedback */
443 gl.enable(GL_RASTERIZER_DISCARD);
444 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
445
446 /* Draw the geometry */
447 for (int n_case = 0; n_case < 2 /* unsized/sized array cases */; ++n_case)
448 {
449 glw::GLuint po_id = (n_case == 0) ? m_program_object_unsized_arrays_id : m_program_object_sized_arrays_id;
450
451 gl.useProgram(po_id);
452 gl.beginTransformFeedback(GL_TRIANGLES);
453 {
454 gl.drawArrays(GL_TRIANGLES, 0 /* first */, 3 /* one triangle */);
455 }
456 gl.endTransformFeedback();
457
458 GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
459
460 /* Map buffer object storage holding XFB result into process space. */
461 glw::GLchar* transform_feedback_data = (glw::GLchar*)gl.mapBufferRange(
462 GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, m_buffer_size, GL_MAP_READ_BIT);
463
464 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
465
466 /* Verify data extracted from transform feedback */
467 if (0 != memcmp(transform_feedback_data, reference_data, m_buffer_size))
468 {
469 m_testCtx.getLog() << tcu::TestLog::Message << "Data extracted from transform feedback is invalid."
470 << tcu::TestLog::EndMessage;
471
472 result = false;
473 }
474
475 /* Unmap the buffer object. */
476 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
477
478 GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
479
480 /* Verify results */
481 if (true != result)
482 {
483 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
484 return STOP;
485 }
486 }
487
488 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
489 return STOP;
490 }
491
492 /** Deinitializes GLES objects created during the test.
493 *
494 */
deinit()495 void GeometryShader_gl_in_ArrayContentsTest::deinit()
496 {
497 /* GL */
498 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
499
500 /* Bind default values */
501 gl.useProgram(0);
502 gl.bindVertexArray(0);
503 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
504 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
505
506 /* Delete everything */
507 if (0 != m_vertex_array_object_id)
508 {
509 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
510 }
511
512 if (0 != m_buffer_object_id)
513 {
514 gl.deleteBuffers(1, &m_buffer_object_id);
515 }
516
517 if (0 != m_program_object_sized_arrays_id)
518 {
519 gl.deleteProgram(m_program_object_sized_arrays_id);
520 }
521
522 if (0 != m_program_object_unsized_arrays_id)
523 {
524 gl.deleteProgram(m_program_object_unsized_arrays_id);
525 }
526
527 if (0 != m_fragment_shader_id)
528 {
529 gl.deleteShader(m_fragment_shader_id);
530 }
531
532 if (0 != m_geometry_shader_sized_arrays_id)
533 {
534 gl.deleteShader(m_geometry_shader_sized_arrays_id);
535 }
536
537 if (0 != m_geometry_shader_unsized_arrays_id)
538 {
539 gl.deleteShader(m_geometry_shader_unsized_arrays_id);
540 }
541
542 if (0 != m_vertex_shader_id)
543 {
544 gl.deleteShader(m_vertex_shader_id);
545 }
546
547 /* Deinitialize Base */
548 TestCaseBase::deinit();
549 }
550
551 /** Constructor
552 *
553 * @param context Test context
554 * @param name Test case's name
555 * @param description Test case's desricption
556 **/
GeometryShader_gl_in_ArrayLengthTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)557 GeometryShader_gl_in_ArrayLengthTest::GeometryShader_gl_in_ArrayLengthTest(Context& context,
558 const ExtParameters& extParams,
559 const char* name, const char* description)
560 : TestCaseBase(context, extParams, name, description), m_buffer_object_id(0), m_vertex_array_object_id(0)
561 {
562 /* Nothing to be done here */
563 }
564
565 /** Initialize test case
566 *
567 **/
init()568 void GeometryShader_gl_in_ArrayLengthTest::init()
569 {
570 /* Initialize Base */
571 TestCaseBase::init();
572
573 /* Captured variables */
574 const char* captured_varyings[] = { "in_array_size" };
575
576 /* This test should only run if EXT_geometry_shader is supported */
577 if (true != m_is_geometry_shader_extension_supported)
578 {
579 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
580 }
581
582 /* GL */
583 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
584
585 /* Set up test descriptors */
586 initCase(m_test_lines, GL_LINES, 2, /* number of vertices */
587 2, /* as per spec */
588 GL_POINTS, m_geometry_shader_code_input_lines, m_geometry_shader_code_output_points);
589
590 m_tests.push_back(&m_test_lines);
591
592 initCase(m_test_lines_adjacency, m_glExtTokens.LINES_ADJACENCY, 4, /* number of vertices */
593 4, /* as per spec */
594 GL_POINTS, m_geometry_shader_code_input_lines_with_adjacency, m_geometry_shader_code_output_points);
595
596 m_tests.push_back(&m_test_lines_adjacency);
597
598 initCase(m_test_points, GL_POINTS, 1, /* number of vertices */
599 1, /* as per spec */
600 GL_POINTS, m_geometry_shader_code_input_points, m_geometry_shader_code_output_points);
601
602 m_tests.push_back(&m_test_points);
603
604 initCase(m_test_triangles, GL_TRIANGLES, 3, /* number of vertices */
605 3, /* as per spec */
606 GL_POINTS, m_geometry_shader_code_input_triangles, m_geometry_shader_code_output_points);
607
608 m_tests.push_back(&m_test_triangles);
609
610 initCase(m_test_triangles_adjacency, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY, 6, /* number of vertices */
611 6, /* as per spec */
612 GL_POINTS, m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_points);
613
614 m_tests.push_back(&m_test_triangles_adjacency);
615
616 initCase(m_test_lines_adjacency_to_line_strip, m_glExtTokens.LINES_ADJACENCY, 4 /* number of vertices */,
617 4 /* expected array length */, GL_LINES, m_geometry_shader_code_input_lines_with_adjacency,
618 m_geometry_shader_code_output_line_strip);
619
620 m_tests.push_back(&m_test_lines_adjacency_to_line_strip);
621
622 initCase(m_test_triangles_adjacency_to_triangle_strip, m_glExtTokens.TRIANGLE_STRIP_ADJACENCY,
623 6 /* number of vertices */, 6 /* expected array length */, GL_TRIANGLES,
624 m_geometry_shader_code_input_triangles_with_adjacency, m_geometry_shader_code_output_triangle_strip);
625
626 m_tests.push_back(&m_test_triangles_adjacency_to_triangle_strip);
627
628 /* Initialize program objects */
629 for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
630 {
631 /* Case instance */
632 Case* test = *it;
633
634 /* Init program */
635 initCaseProgram(*test, captured_varyings, sizeof(captured_varyings) / sizeof(captured_varyings[0]));
636 }
637
638 /* Generate, bind and allocate buffer */
639 gl.genBuffers(1, &m_buffer_object_id);
640 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_object_id);
641 gl.bufferData(GL_ARRAY_BUFFER, m_buffer_size, 0 /* no start data */, GL_STATIC_DRAW);
642
643 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create buffer object");
644
645 /* Generate and bind VAO */
646 gl.genVertexArrays(1, &m_vertex_array_object_id);
647 gl.bindVertexArray(m_vertex_array_object_id);
648
649 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
650 }
651
652 /** Executes the test.
653 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
654 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
655 * Note the function throws exception should an error occur!
656 **/
iterate()657 tcu::TestCase::IterateResult GeometryShader_gl_in_ArrayLengthTest::iterate()
658 {
659 /* GL */
660 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
661
662 /* This test should only run if EXT_geometry_shader is supported */
663 if (true != m_is_geometry_shader_extension_supported)
664 {
665 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
666 }
667
668 /* Setup transform feedback */
669 gl.enable(GL_RASTERIZER_DISCARD);
670 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_object_id);
671
672 /* Execute tests */
673 for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
674 {
675 glw::GLint result_value = 0;
676 Case* test = *it;
677
678 /* Execute */
679 gl.useProgram(test->po_id);
680
681 gl.beginTransformFeedback(test->tf_mode);
682 {
683 gl.drawArrays(test->draw_call_mode, 0, /* first */
684 test->draw_call_n_vertices);
685 }
686 gl.endTransformFeedback();
687
688 GLU_EXPECT_NO_ERROR(gl.getError(), "Error doing a draw call");
689
690 /* Map transform feedback results */
691 glw::GLint* result = (glw::GLint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */,
692 sizeof(glw::GLint), GL_MAP_READ_BIT);
693
694 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not map the buffer object into process space");
695
696 /* Extract value from transform feedback */
697 result_value = *result;
698
699 /* Unmap transform feedback buffer */
700 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
701
702 GLU_EXPECT_NO_ERROR(gl.getError(), "Error unmapping the buffer object");
703
704 /* Verify results */
705 if (result_value != test->expected_array_length)
706 {
707 m_testCtx.getLog() << tcu::TestLog::Message << "Expected array length: " << test->expected_array_length
708 << " but found: " << result_value << tcu::TestLog::EndMessage;
709
710 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
711 return STOP;
712 }
713 }
714
715 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
716 return STOP;
717 }
718
719 /** Deinitializes test case
720 *
721 **/
deinit()722 void GeometryShader_gl_in_ArrayLengthTest::deinit()
723 {
724 /* GL */
725 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
726
727 /* Bind default values */
728 gl.useProgram(0);
729 gl.bindVertexArray(0);
730 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* offset */, 0 /* id */);
731 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
732 /* Delete everything */
733 if (0 != m_vertex_array_object_id)
734 {
735 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
736 }
737
738 if (0 != m_buffer_object_id)
739 {
740 gl.deleteBuffers(1, &m_buffer_object_id);
741 }
742
743 /* Deinit test cases */
744 for (testContainer::iterator it = m_tests.begin(); it != m_tests.end(); ++it)
745 {
746 Case* test = *it;
747
748 deinitCase(*test);
749 }
750
751 m_tests.clear();
752
753 /* Deinitialize Base */
754 TestCaseBase::deinit();
755 }
756
757 /** Deinitialize test case instance
758 *
759 * @param info Case instance
760 **/
deinitCase(Case & info)761 void GeometryShader_gl_in_ArrayLengthTest::deinitCase(Case& info)
762 {
763 /* GL */
764 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
765
766 /* Delete everything */
767 if (0 != info.po_id)
768 {
769 gl.deleteProgram(info.po_id);
770 }
771
772 if (0 != info.vs_id)
773 {
774 gl.deleteShader(info.vs_id);
775 }
776
777 if (0 != info.gs_id)
778 {
779 gl.deleteShader(info.gs_id);
780 }
781
782 if (0 != info.fs_id)
783 {
784 gl.deleteShader(info.fs_id);
785 }
786
787 /* Clear case */
788 resetCase(info);
789 }
790
791 /** Initialize test case instance with provided data.
792 *
793 * @param info Case instance;
794 * @param draw_call_mode Primitive type used by a draw call;
795 * @param draw_call_n_vertices Number of vertices used by a draw call;
796 * @param expected_array_length Expected size of gl_in array;
797 * @param tf_mode Primitive type used by transform feedback;
798 * @param input_body_part Part of geometry shader which specifies input layout;
799 * @param output_body_part Part of geometry shader which specifies output layout;
800 **/
initCase(Case & info,glw::GLenum draw_call_mode,glw::GLint draw_call_n_vertices,glw::GLint expected_array_length,glw::GLenum tf_mode,const glw::GLchar * input_body_part,const glw::GLchar * output_body_part)801 void GeometryShader_gl_in_ArrayLengthTest::initCase(Case& info, glw::GLenum draw_call_mode,
802 glw::GLint draw_call_n_vertices, glw::GLint expected_array_length,
803 glw::GLenum tf_mode, const glw::GLchar* input_body_part,
804 const glw::GLchar* output_body_part)
805 {
806 /* Reset case descriptor */
807 resetCase(info);
808
809 /* Set fields */
810 info.draw_call_mode = draw_call_mode;
811 info.draw_call_n_vertices = draw_call_n_vertices;
812 info.expected_array_length = expected_array_length;
813 info.input_body_part = input_body_part;
814 info.output_body_part = output_body_part;
815 info.tf_mode = tf_mode;
816 }
817
818 /** Creates and build program for given Case
819 *
820 * @param info Case instance
821 * @param captured_varyings Name of varyings captured by transform feedback
822 * @param n_captured_varyings_size Number of varyings captured by transform feedback
823 **/
initCaseProgram(Case & info,const glw::GLchar ** captured_varyings,glw::GLuint n_captured_varyings_size)824 void GeometryShader_gl_in_ArrayLengthTest::initCaseProgram(Case& info, const glw::GLchar** captured_varyings,
825 glw::GLuint n_captured_varyings_size)
826 {
827 /* GL */
828 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
829
830 /* Create program and shader objects */
831 info.po_id = gl.createProgram();
832
833 info.vs_id = gl.createShader(GL_VERTEX_SHADER);
834 info.gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
835 info.fs_id = gl.createShader(GL_FRAGMENT_SHADER);
836
837 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create program object");
838
839 /* Prepare geometry shader parts */
840 const char* const geometry_shader_parts[] = { m_geometry_shader_code_preamble, info.input_body_part,
841 info.output_body_part, m_geometry_shader_code_main };
842
843 /* Set up transform feedback */
844 gl.transformFeedbackVaryings(info.po_id, n_captured_varyings_size, captured_varyings, GL_SEPARATE_ATTRIBS);
845
846 /* Build program */
847 if (false == buildProgram(info.po_id, info.fs_id, 1 /* number of fragment shader code parts */,
848 &m_fragment_shader_code, info.gs_id, DE_LENGTH_OF_ARRAY(geometry_shader_parts),
849 geometry_shader_parts, info.vs_id, 1 /* number of vertex shader code parts */,
850 &m_vertex_shader_code))
851 {
852 TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
853 }
854 }
855
856 /** Reset Case instance descriptor's contents.
857 *
858 * @param info Case instance
859 **/
resetCase(Case & info)860 void GeometryShader_gl_in_ArrayLengthTest::resetCase(Case& info)
861 {
862 memset(&info, 0, sizeof(info));
863 }
864
865 /** Constructor
866 *
867 * @param context Test context
868 * @param name Test case's name
869 * @param description Test case's desricption
870 **/
GeometryShader_gl_PointSize_ValueTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)871 GeometryShader_gl_PointSize_ValueTest::GeometryShader_gl_PointSize_ValueTest(Context& context,
872 const ExtParameters& extParams,
873 const char* name, const char* description)
874 : TestCaseBase(context, extParams, name, description)
875 , m_fragment_shader_id(0)
876 , m_geometry_shader_id(0)
877 , m_program_object_id(0)
878 , m_vertex_shader_id(0)
879 , m_vertex_array_object_id(0)
880 , m_color_texture_id(0)
881 , m_framebuffer_object_id(0)
882 {
883 /* Nothing to be done here */
884 }
885
886 /** Initialize test case
887 *
888 **/
init()889 void GeometryShader_gl_PointSize_ValueTest::init()
890 {
891 /* Initialize Base */
892 TestCaseBase::init();
893
894 /* This test should only run if EXT_geometry_shader and EXT_geometry_point_size both are supported */
895 if (true != m_is_geometry_shader_extension_supported)
896 {
897 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
898 }
899
900 if (true != m_is_geometry_shader_point_size_supported)
901 {
902 throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
903 }
904
905 /* GL */
906 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
907
908 /* Verify that point size range is supported */
909 glw::GLfloat point_size_range[2] = { 0 };
910
911 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
912 {
913 gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
914 }
915 else
916 {
917 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
918 }
919
920 if (8.0f > point_size_range[1])
921 {
922 m_testCtx.getLog() << tcu::TestLog::Message
923 << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
924 << point_size_range[1] << tcu::TestLog::EndMessage;
925
926 throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
927 }
928
929 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
930 {
931 gl.enable(GL_PROGRAM_POINT_SIZE);
932 }
933
934 /* Create program and shaders */
935 m_program_object_id = gl.createProgram();
936
937 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
938 m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
939 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
940
941 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
942
943 /* Build program */
944 if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
945 &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
946 &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
947 &m_vertex_shader_code))
948 {
949 TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
950 }
951
952 /* Set up texture object and a FBO */
953 gl.genTextures(1, &m_color_texture_id);
954 gl.genFramebuffers(1, &m_framebuffer_object_id);
955
956 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
957
958 if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
959 m_texture_width, m_texture_height))
960 {
961 TCU_FAIL("Failed to setup framebuffer");
962 }
963
964 /* Set up a vertex array object */
965 gl.genVertexArrays(1, &m_vertex_array_object_id);
966 gl.bindVertexArray(m_vertex_array_object_id);
967
968 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
969 }
970
971 /** Executes the test.
972 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
973 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
974 * Note the function throws exception should an error occur!
975 **/
iterate()976 tcu::TestCase::IterateResult GeometryShader_gl_PointSize_ValueTest::iterate()
977 {
978 /* Buffer to store results of rendering */
979 unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
980
981 /* This test should only run if EXT_geometry_shader is supported */
982 if (true != m_is_geometry_shader_extension_supported)
983 {
984 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
985 }
986
987 if (true != m_is_geometry_shader_point_size_supported)
988 {
989 throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
990 }
991
992 /* GL */
993 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
994
995 /* Render */
996 gl.useProgram(m_program_object_id);
997
998 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
999
1000 gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1001 gl.clear(GL_COLOR_BUFFER_BIT);
1002
1003 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1004
1005 gl.drawArrays(GL_POINTS, 0 /* first */, 2 /* count */);
1006
1007 GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1008
1009 /* Check if the data was modified during the rendering process */
1010 gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1011
1012 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1013
1014 /* 1) pixel at (2, 8) is (255, 255, 255, 255) */
1015 unsigned int referencePixelCoordinates[2] = { 2, 8 };
1016
1017 if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1018 m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1019 255 /* blue */, 255 /* alpha */))
1020 {
1021 const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1022 referencePixelCoordinates[0] * m_texture_pixel_size;
1023
1024 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1025 << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1026 << result_image[texel_offset + 3] << "]"
1027 << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1028
1029 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1030 return STOP;
1031 }
1032
1033 /* 2) pixel at (14, 8) is (255, 255, 255, 255) */
1034 referencePixelCoordinates[0] = 14;
1035 referencePixelCoordinates[1] = 8;
1036
1037 if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1038 m_texture_width, m_texture_height, m_texture_pixel_size, 255 /* red */, 255 /* green */,
1039 255 /* blue */, 255 /* alpha */))
1040 {
1041 const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1042 referencePixelCoordinates[0] * m_texture_pixel_size;
1043
1044 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1045 << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1046 << result_image[texel_offset + 3] << "]"
1047 << " is different from reference data [255, 255, 255, 255]!" << tcu::TestLog::EndMessage;
1048
1049 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1050 return STOP;
1051 }
1052
1053 /* 3) pixel at (6, 8) is (0, 0, 0, 0) */
1054 referencePixelCoordinates[0] = 6;
1055 referencePixelCoordinates[1] = 8;
1056
1057 if (false == comparePixel(result_image, referencePixelCoordinates[0] /* x */, referencePixelCoordinates[1] /* y */,
1058 m_texture_width, m_texture_height, m_texture_pixel_size, 0 /* red */, 0 /* green */,
1059 0 /* blue */, 0 /* alpha */))
1060 {
1061 const unsigned int texel_offset = referencePixelCoordinates[1] * m_texture_width * m_texture_pixel_size +
1062 referencePixelCoordinates[0] * m_texture_pixel_size;
1063
1064 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1065 << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1066 << result_image[texel_offset + 3] << "]"
1067 << "is different from reference data [0, 0, 0, 0]!" << tcu::TestLog::EndMessage;
1068
1069 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1070 return STOP;
1071 }
1072
1073 /* Done */
1074 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1075 return STOP;
1076 }
1077
1078 /** Deinitializes test case
1079 *
1080 **/
deinit()1081 void GeometryShader_gl_PointSize_ValueTest::deinit()
1082 {
1083 /* GL */
1084 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1085
1086 /* Bind defaults */
1087 gl.useProgram(0);
1088 gl.bindVertexArray(0);
1089 gl.bindTexture(GL_TEXTURE_2D, 0);
1090 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1091 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1092 {
1093 gl.disable(GL_PROGRAM_POINT_SIZE);
1094 }
1095
1096 /* Delete everything */
1097 if (m_program_object_id != 0)
1098 {
1099 gl.deleteProgram(m_program_object_id);
1100 }
1101
1102 if (m_fragment_shader_id != 0)
1103 {
1104 gl.deleteShader(m_fragment_shader_id);
1105 }
1106
1107 if (m_geometry_shader_id != 0)
1108 {
1109 gl.deleteShader(m_geometry_shader_id);
1110 }
1111
1112 if (m_vertex_shader_id != 0)
1113 {
1114 gl.deleteShader(m_vertex_shader_id);
1115 }
1116
1117 if (m_vertex_array_object_id != 0)
1118 {
1119 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1120 }
1121
1122 if (m_color_texture_id != 0)
1123 {
1124 gl.deleteTextures(1, &m_color_texture_id);
1125 }
1126
1127 if (m_framebuffer_object_id != 0)
1128 {
1129 gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1130 }
1131
1132 /* Release base class */
1133 TestCaseBase::deinit();
1134 }
1135
1136 /** Constructor
1137 *
1138 * @param context Test context
1139 * @param name Test case's name
1140 * @param description Test case's desricption
1141 **/
GeometryShader_gl_Position_ValueTest(Context & context,const ExtParameters & extParams,const char * name,const char * description)1142 GeometryShader_gl_Position_ValueTest::GeometryShader_gl_Position_ValueTest(Context& context,
1143 const ExtParameters& extParams,
1144 const char* name, const char* description)
1145 : TestCaseBase(context, extParams, name, description)
1146 , m_fragment_shader_id(0)
1147 , m_geometry_shader_id(0)
1148 , m_program_object_id(0)
1149 , m_vertex_shader_id(0)
1150 , m_vertex_array_object_id(0)
1151 , m_color_texture_id(0)
1152 , m_framebuffer_object_id(0)
1153 {
1154 /* Nothing to be done here */
1155 }
1156
1157 /** Initialize test case
1158 *
1159 **/
init()1160 void GeometryShader_gl_Position_ValueTest::init()
1161 {
1162 /* Initialize base */
1163 TestCaseBase::init();
1164
1165 /* This test should only run if EXT_geometry_shader is supported */
1166 if (true != m_is_geometry_shader_extension_supported)
1167 {
1168 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1169 }
1170
1171 if (true != m_is_geometry_shader_point_size_supported)
1172 {
1173 throw tcu::NotSupportedError(GEOMETRY_SHADER_POINT_SIZE_NOT_SUPPORTED, "", __FILE__, __LINE__);
1174 }
1175
1176 /* GL */
1177 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1178
1179 /* Verify that point size range is supported */
1180 glw::GLfloat point_size_range[2] = { 0 };
1181
1182 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1183 {
1184 gl.getFloatv(GL_POINT_SIZE_RANGE, point_size_range);
1185 }
1186 else
1187 {
1188 gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, point_size_range);
1189 }
1190
1191 if (8.0f > point_size_range[1])
1192 {
1193 m_testCtx.getLog() << tcu::TestLog::Message
1194 << "Test requires a minimum maximum point size of 8, implementation reports a maximum of : "
1195 << point_size_range[1] << tcu::TestLog::EndMessage;
1196
1197 throw tcu::NotSupportedError("Not supported point size", "", __FILE__, __LINE__);
1198 }
1199
1200 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1201 {
1202 gl.enable(GL_PROGRAM_POINT_SIZE);
1203 }
1204
1205 /* Create program and shaders */
1206 m_program_object_id = gl.createProgram();
1207
1208 m_fragment_shader_id = gl.createShader(GL_FRAGMENT_SHADER);
1209 m_geometry_shader_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
1210 m_vertex_shader_id = gl.createShader(GL_VERTEX_SHADER);
1211
1212 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create program");
1213
1214 /* Build program */
1215 if (false == buildProgram(m_program_object_id, m_fragment_shader_id, 1 /* fragment shader parts number */,
1216 &m_fragment_shader_code, m_geometry_shader_id, 1 /* geometry shader parts number */,
1217 &m_geometry_shader_code, m_vertex_shader_id, 1 /* vertex shader parts number */,
1218 &m_vertex_shader_code))
1219 {
1220 TCU_FAIL("Could not create program from valid vertex/geometry/fragment shader");
1221 }
1222
1223 /* Set up a texture object and a FBO */
1224 gl.genTextures(1, &m_color_texture_id);
1225 gl.genFramebuffers(1, &m_framebuffer_object_id);
1226
1227 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create framebuffer");
1228
1229 if (false == setupFramebufferWithTextureAsAttachment(m_framebuffer_object_id, m_color_texture_id, GL_RGBA8,
1230 m_texture_width, m_texture_height))
1231 {
1232 TCU_FAIL("Failed to setup framebuffer");
1233 }
1234
1235 /* Set up a vertex array object */
1236 gl.genVertexArrays(1, &m_vertex_array_object_id);
1237 gl.bindVertexArray(m_vertex_array_object_id);
1238
1239 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not create vertex array object");
1240 }
1241
1242 /** Executes the test.
1243 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1244 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1245 * Note the function throws exception should an error occur!
1246 **/
iterate()1247 tcu::TestCase::IterateResult GeometryShader_gl_Position_ValueTest::iterate()
1248 {
1249 /* Variables used for image verification purposes */
1250 unsigned char result_image[m_texture_width * m_texture_height * m_texture_pixel_size];
1251
1252 /* This test should only run if EXT_geometry_shader is supported */
1253 if (true != m_is_geometry_shader_extension_supported)
1254 {
1255 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1256 }
1257
1258 /* GL */
1259 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1260
1261 /* Render */
1262 gl.useProgram(m_program_object_id);
1263
1264 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to use program");
1265
1266 gl.clearColor(0 /* red */, 0 /* green */, 0 /* blue */, 0 /* alpha */);
1267 gl.clear(GL_COLOR_BUFFER_BIT);
1268
1269 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not clear the color buffer");
1270
1271 gl.drawArrays(GL_POINTS, 0 /* first */, 8 /* count */);
1272
1273 GLU_EXPECT_NO_ERROR(gl.getError(), "Call drawArrays() failed");
1274
1275 /* Check if the data was modified during the rendering process */
1276 gl.readPixels(0 /* x */, 0 /* y */, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, result_image);
1277
1278 GLU_EXPECT_NO_ERROR(gl.getError(), "Could not read back pixels from color buffer");
1279
1280 /* The test passes if centers of the rendered points are lit at expected locations. */
1281 for (unsigned int x = 4; x < m_texture_width; x += 8)
1282 {
1283 if (false == comparePixel(result_image, x, 32 /* y */, m_texture_width, m_texture_height, m_texture_pixel_size,
1284 255 /* red */, 255 /* green */, 255 /* blue */, 255 /* alpha */))
1285 {
1286 const unsigned int texel_offset = 32 * m_texture_width * m_texture_pixel_size + x * m_texture_pixel_size;
1287
1288 m_testCtx.getLog() << tcu::TestLog::Message << "Rendered data [" << result_image[texel_offset + 0] << ", "
1289 << result_image[texel_offset + 1] << ", " << result_image[texel_offset + 2] << ", "
1290 << result_image[texel_offset + 3] << "]"
1291 << "is different from reference data [255, 255, 255, 255] !" << tcu::TestLog::EndMessage;
1292
1293 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1294 return STOP;
1295 }
1296 }
1297
1298 /* Done */
1299 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1300 return STOP;
1301 }
1302
1303 /** Deinitializes test case
1304 *
1305 **/
deinit()1306 void GeometryShader_gl_Position_ValueTest::deinit()
1307 {
1308 /* GL */
1309 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1310
1311 /* Bind default values */
1312 gl.useProgram(0);
1313 gl.bindVertexArray(0);
1314 gl.bindTexture(GL_TEXTURE_2D, 0);
1315 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
1316 if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
1317 {
1318 gl.disable(GL_PROGRAM_POINT_SIZE);
1319 }
1320
1321 /* Delete everything */
1322 if (m_program_object_id != 0)
1323 {
1324 gl.deleteProgram(m_program_object_id);
1325 }
1326
1327 if (m_fragment_shader_id != 0)
1328 {
1329 gl.deleteShader(m_fragment_shader_id);
1330 }
1331
1332 if (m_geometry_shader_id != 0)
1333 {
1334 gl.deleteShader(m_geometry_shader_id);
1335 }
1336
1337 if (m_vertex_shader_id != 0)
1338 {
1339 gl.deleteShader(m_vertex_shader_id);
1340 }
1341
1342 if (m_vertex_array_object_id != 0)
1343 {
1344 gl.deleteVertexArrays(1, &m_vertex_array_object_id);
1345 }
1346
1347 if (m_color_texture_id != 0)
1348 {
1349 gl.deleteTextures(1, &m_color_texture_id);
1350 }
1351
1352 if (m_framebuffer_object_id != 0)
1353 {
1354 gl.deleteFramebuffers(1, &m_framebuffer_object_id);
1355 }
1356
1357 /* Release base class */
1358 TestCaseBase::deinit();
1359 }
1360
1361 } /* glcts */
1362