1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-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 #include "esextcGeometryShaderAPI.hpp"
24
25 #include "gluDefs.hpp"
26 #include "glwEnums.hpp"
27 #include "glwFunctions.hpp"
28 #include "tcuTestLog.hpp"
29 #include <cstring>
30
31 namespace glcts
32 {
33
34 static const char* minimal_fs_code =
35 "${VERSION}\n"
36 "\n"
37 "precision highp float;\n"
38 "\n"
39 "out vec4 result;\n"
40 "\n"
41 "void main()\n"
42 "{\n"
43 " result = vec4(1.0);\n"
44 "}\n";
45
46 static const char* minimal_gs_code =
47 "${VERSION}\n"
48 "${GEOMETRY_SHADER_REQUIRE}\n"
49 "\n"
50 "layout (points) in;\n"
51 "layout (points, max_vertices = 1) out;\n"
52 "\n"
53 "${OUT_PER_VERTEX_DECL}"
54 "${IN_DATA_DECL}"
55 "void main()\n"
56 "{\n"
57 "${POSITION_WITH_IN_DATA}"
58 " EmitVertex();\n"
59 "}\n";
60
61 static const char* minimal_vs_code =
62 "${VERSION}\n"
63 "\n"
64 "${OUT_PER_VERTEX_DECL}"
65 "\n"
66 "void main()\n"
67 "{\n"
68 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
69 "}\n";
70
71 /* createShaderProgramv conformance test shaders */
72 const char* GeometryShaderCreateShaderProgramvTest::fs_code = "${VERSION}\n"
73 "\n"
74 "precision highp float;\n"
75 "\n"
76 "out vec4 result;\n"
77 "\n"
78 "void main()\n"
79 "{\n"
80 " result = vec4(0.0, 1.0, 0.0, 0.0);\n"
81 "}\n";
82
83 const char* GeometryShaderCreateShaderProgramvTest::gs_code = "${VERSION}\n"
84 "${GEOMETRY_SHADER_REQUIRE}\n"
85 "\n"
86 "layout (points) in;\n"
87 "layout (triangle_strip, max_vertices = 4) out;\n"
88 "\n"
89 "${OUT_PER_VERTEX_DECL}"
90 "\n"
91 "void main()\n"
92 "{\n"
93 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
94 " EmitVertex();\n"
95 "\n"
96 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
97 " EmitVertex();\n"
98 "\n"
99 " gl_Position = vec4(1.0, -1.0, 0.0, 1.0);\n"
100 " EmitVertex();\n"
101 "\n"
102 " gl_Position = vec4(1.0, 1.0, 0.0, 1.0);\n"
103 " EmitVertex();\n"
104 " EndPrimitive();\n"
105 "}\n";
106
107 const char* GeometryShaderCreateShaderProgramvTest::vs_code = "${VERSION}\n"
108 "\n"
109 "${OUT_PER_VERTEX_DECL}"
110 "\n"
111 "void main()\n"
112 "{\n"
113 " gl_Position = vec4(-10.0, -10.0, -10.0, 0.0);\n"
114 "}\n";
115
116 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_height = 4;
117 const unsigned int GeometryShaderCreateShaderProgramvTest::m_to_width = 4;
118
119 /** Constructor
120 *
121 * @param context Test context
122 * @param extParams Not used.
123 * @param name Test case's name
124 * @param description Test case's description
125 **/
GeometryShaderCreateShaderProgramvTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)126 GeometryShaderCreateShaderProgramvTest::GeometryShaderCreateShaderProgramvTest(Context& context,
127 const ExtParameters& extParams,
128 const char* name,
129 const char* description)
130 : TestCaseBase(context, extParams, name, description)
131 , m_fbo_id(0)
132 , m_fs_po_id(0)
133 , m_gs_po_id(0)
134 , m_pipeline_object_id(0)
135 , m_to_id(0)
136 , m_vao_id(0)
137 , m_vs_po_id(0)
138 {
139 }
140
141 /** Deinitializes GLES objects created during the test. */
deinit()142 void GeometryShaderCreateShaderProgramvTest::deinit()
143 {
144 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
145
146 if (m_fbo_id != 0)
147 {
148 gl.deleteFramebuffers(1, &m_fbo_id);
149
150 m_fbo_id = 0;
151 }
152
153 if (m_fs_po_id != 0)
154 {
155 gl.deleteProgram(m_fs_po_id);
156
157 m_fs_po_id = 0;
158 }
159
160 if (m_gs_po_id != 0)
161 {
162 gl.deleteProgram(m_gs_po_id);
163
164 m_gs_po_id = 0;
165 }
166
167 if (m_pipeline_object_id != 0)
168 {
169 gl.deleteProgramPipelines(1, &m_pipeline_object_id);
170
171 m_pipeline_object_id = 0;
172 }
173
174 if (m_to_id != 0)
175 {
176 gl.deleteTextures(1, &m_to_id);
177
178 m_to_id = 0;
179 }
180
181 if (m_vao_id != 0)
182 {
183 gl.deleteVertexArrays(1, &m_vao_id);
184
185 m_vao_id = 0;
186 }
187
188 if (m_vs_po_id != 0)
189 {
190 gl.deleteProgram(m_vs_po_id);
191
192 m_vs_po_id = 0;
193 }
194
195 /* Release base class */
196 TestCaseBase::deinit();
197 }
198
199 /** Initializes a framebuffer object used by the conformance test. */
initFBO()200 void GeometryShaderCreateShaderProgramvTest::initFBO()
201 {
202 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
203
204 /* Generate a FBO */
205 gl.genFramebuffers(1, &m_fbo_id);
206 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
207
208 /* Generate a TO */
209 gl.genTextures(1, &m_to_id);
210 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
211
212 /* Set the TO up */
213 gl.bindTexture(GL_TEXTURE_2D, m_to_id);
214 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
215
216 gl.texStorage2D(GL_TEXTURE_2D, 1, /* levels */
217 GL_RGBA8, m_to_width, m_to_height);
218 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
219
220 /* Set up the FBO */
221 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
222 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
223
224 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_to_id, 0); /* level */
225 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
226
227 /* Set up the viewport */
228 gl.viewport(0, /* x */
229 0, /* y */
230 m_to_width, m_to_height);
231
232 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport() call failed.");
233 }
234
235 /* Initializes a pipeline object used by the conformance test */
initPipelineObject()236 void GeometryShaderCreateShaderProgramvTest::initPipelineObject()
237 {
238 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
239
240 DE_ASSERT(m_fs_po_id != 0 && m_gs_po_id != 0 && m_vs_po_id != 0);
241
242 gl.genProgramPipelines(1, &m_pipeline_object_id);
243 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
244
245 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
246 gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
247 gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
248
249 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
250 }
251
252 /** Executes the test.
253 *
254 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
255 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
256 * Note the function throws exception should an error occur!
257 **/
iterate()258 tcu::TestNode::IterateResult GeometryShaderCreateShaderProgramvTest::iterate()
259 {
260 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
261 const unsigned int n_so_po_ids = 3;
262 bool result = true;
263 glw::GLuint so_po_ids[n_so_po_ids];
264
265 /* This test should only run if EXT_geometry_shader is supported. */
266 if (!m_is_geometry_shader_extension_supported)
267 {
268 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
269 }
270
271 /* Initialize off-screen rendering */
272 initFBO();
273
274 /* Form shader sources */
275 std::string fs_specialized_code = specializeShader(1,
276 /* parts */ &fs_code);
277 const char* fs_specialized_code_raw = fs_specialized_code.c_str();
278 std::string gs_specialized_code = specializeShader(1,
279 /* parts */ &gs_code);
280 const char* gs_specialized_code_raw = gs_specialized_code.c_str();
281 std::string vs_specialized_code = specializeShader(1,
282 /* parts */ &vs_code);
283 const char* vs_specialized_code_raw = vs_specialized_code.c_str();
284
285 /* Try to create an invalid geometry shader program first */
286 glw::GLint link_status = GL_TRUE;
287
288 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
289 &gs_code);
290
291 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
292
293 if (m_gs_po_id == 0)
294 {
295 m_testCtx.getLog() << tcu::TestLog::Message << "glCreateShaderProgramv() call returned 0."
296 << tcu::TestLog::EndMessage;
297
298 result = false;
299 goto end;
300 }
301
302 gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
303 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
304
305 if (link_status != GL_FALSE)
306 {
307 m_testCtx.getLog() << tcu::TestLog::Message << "An invalid shader program was linked successfully."
308 << tcu::TestLog::EndMessage;
309
310 result = false;
311 goto end;
312 }
313
314 gl.deleteProgram(m_gs_po_id);
315 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram() call failed.");
316
317 /* Create shader programs */
318 m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
319 &fs_specialized_code_raw);
320 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
321 &gs_specialized_code_raw);
322 m_vs_po_id = gl.createShaderProgramv(GL_VERTEX_SHADER, 1, /* count */
323 &vs_specialized_code_raw);
324
325 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
326
327 if (m_fs_po_id == 0 || m_gs_po_id == 0 || m_vs_po_id == 0)
328 {
329 m_testCtx.getLog() << tcu::TestLog::Message << "At least one glCreateShaderProgramv() call returned 0."
330 << tcu::TestLog::EndMessage;
331
332 result = false;
333 goto end;
334 }
335
336 /* Make sure all shader programs were linked successfully */
337 so_po_ids[0] = m_fs_po_id;
338 so_po_ids[1] = m_gs_po_id;
339 so_po_ids[2] = m_vs_po_id;
340
341 for (unsigned int n_po_id = 0; n_po_id != n_so_po_ids; ++n_po_id)
342 {
343 gl.getProgramiv(so_po_ids[n_po_id], GL_LINK_STATUS, &link_status);
344 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
345
346 if (link_status != GL_TRUE)
347 {
348 m_testCtx.getLog() << tcu::TestLog::Message << "A valid shader program with id [" << so_po_ids[n_po_id]
349 << "] was not linked successfully." << tcu::TestLog::EndMessage;
350
351 result = false;
352 goto end;
353 }
354 }
355
356 /* Set up the vertex array object */
357 gl.genVertexArrays(1, &m_vao_id);
358 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
359
360 gl.bindVertexArray(m_vao_id);
361 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
362
363 /* Set up the pipeline object */
364 initPipelineObject();
365
366 /* Render a full-screen quad */
367 gl.bindProgramPipeline(m_pipeline_object_id);
368 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
369
370 gl.drawArrays(GL_POINTS, 0, /* first */
371 1); /* count */
372 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed.");
373
374 /* Verify the rendering result */
375 unsigned char result_data[m_to_width * m_to_height * 4 /* rgba */];
376
377 gl.readPixels(0, /* x */
378 0, /* y */
379 m_to_width, m_to_height, GL_RGBA, GL_UNSIGNED_BYTE, result_data);
380 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
381
382 for (unsigned int y = 0; y < m_to_height; ++y)
383 {
384 unsigned char* traveller_ptr = result_data + 4 * y;
385
386 for (unsigned int x = 0; x < m_to_width; ++x)
387 {
388 if (traveller_ptr[0] != 0 || traveller_ptr[1] != 255 || traveller_ptr[2] != 0 || traveller_ptr[3] != 0)
389 {
390 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid result texel found at (" << x << ", " << y
391 << ")." << tcu::TestLog::EndMessage;
392
393 result = false;
394 }
395
396 traveller_ptr += 4; /* rgba */
397 }
398 }
399
400 end:
401 if (result)
402 {
403 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
404 }
405 else
406 {
407 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
408 }
409
410 return STOP;
411 }
412
413 /** Constructor
414 *
415 * @param context Test context
416 * @param extParams Not used.
417 * @param name Test case's name
418 * @param description Test case's description
419 **/
GeometryShaderGetShaderivTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)420 GeometryShaderGetShaderivTest::GeometryShaderGetShaderivTest(Context& context, const ExtParameters& extParams,
421 const char* name, const char* description)
422 : TestCaseBase(context, extParams, name, description), m_gs_id(0)
423 {
424 }
425
426 /** Deinitializes GLES objects created during the test. */
deinit()427 void GeometryShaderGetShaderivTest::deinit()
428 {
429 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
430
431 if (m_gs_id != 0)
432 {
433 gl.deleteShader(m_gs_id);
434
435 m_gs_id = 0;
436 }
437
438 /* Release base class */
439 TestCaseBase::deinit();
440 }
441
442 /** Executes the test.
443 *
444 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
445 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
446 * Note the function throws exception should an error occur!
447 **/
iterate()448 tcu::TestNode::IterateResult GeometryShaderGetShaderivTest::iterate()
449 {
450 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
451 bool result = true;
452
453 /* This test should only run if EXT_geometry_shader is supported. */
454 if (!m_is_geometry_shader_extension_supported)
455 {
456 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
457 }
458
459 /* Create a GS */
460 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
461
462 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call failed.");
463
464 /* Check the type reported for the SO */
465 glw::GLint shader_type = GL_NONE;
466
467 gl.getShaderiv(m_gs_id, GL_SHADER_TYPE, &shader_type);
468 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
469
470 if ((glw::GLenum)shader_type != m_glExtTokens.GEOMETRY_SHADER)
471 {
472 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid shader type [" << shader_type
473 << "] reported for a Geometry Shader" << tcu::TestLog::EndMessage;
474
475 result = false;
476 }
477
478 if (result)
479 {
480 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
481 }
482 else
483 {
484 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
485 }
486
487 return STOP;
488 }
489
490 /** Constructor
491 *
492 * @param context Test context
493 * @param extParams Not used.
494 * @param name Test case's name
495 * @param description Test case's description
496 **/
GeometryShaderGetProgramivTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)497 GeometryShaderGetProgramivTest::GeometryShaderGetProgramivTest(Context& context, const ExtParameters& extParams,
498 const char* name, const char* description)
499 : TestCaseBase(context, extParams, name, description), m_po_id(0)
500 {
501 }
502
503 /** Deinitializes GLES objects created during the test. */
deinit()504 void GeometryShaderGetProgramivTest::deinit()
505 {
506 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
507
508 if (m_po_id != 0)
509 {
510 gl.deleteProgram(m_po_id);
511
512 m_po_id = 0;
513 }
514
515 /* Release base class */
516 TestCaseBase::deinit();
517 }
518
519 /** Executes the test.
520 *
521 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
522 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
523 * Note the function throws exception should an error occur!
524 **/
iterate()525 tcu::TestNode::IterateResult GeometryShaderGetProgramivTest::iterate()
526 {
527 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
528 bool result = true;
529
530 /* This test should only run if EXT_geometry_shader is supported. */
531 if (!m_is_geometry_shader_extension_supported)
532 {
533 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
534 }
535
536 /* Create a program object */
537 m_po_id = gl.createProgram();
538
539 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
540
541 /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error */
542 const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
543 m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE,
544 m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS };
545 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
546
547 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
548 {
549 glw::GLenum error_code = GL_NO_ERROR;
550 glw::GLenum pname = pnames[n_pname];
551 glw::GLint rv = -1;
552
553 gl.getProgramiv(m_po_id, pname, &rv);
554
555 error_code = gl.getError();
556
557 if (error_code != GL_INVALID_OPERATION)
558 {
559 m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
560 << "]" << tcu::TestLog::EndMessage;
561
562 result = false;
563 }
564 } /* for (all pnames) */
565
566 if (result)
567 {
568 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
569 }
570 else
571 {
572 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
573 }
574
575 return STOP;
576 }
577
578 /** Constructor
579 *
580 * @param context Test context
581 * @param extParams Not used.
582 * @param name Test case's name
583 * @param description Test case's description
584 **/
GeometryShaderGetProgramiv2Test(Context& context, const ExtParameters& extParams, const char* name, const char* description)585 GeometryShaderGetProgramiv2Test::GeometryShaderGetProgramiv2Test(Context& context, const ExtParameters& extParams,
586 const char* name, const char* description)
587 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_po_id(0), m_vs_id(0)
588 {
589 }
590
591 /** Deinitializes GLES objects created during the test. */
deinit()592 void GeometryShaderGetProgramiv2Test::deinit()
593 {
594 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
595
596 if (m_fs_id != 0)
597 {
598 gl.deleteShader(m_fs_id);
599
600 m_fs_id = 0;
601 }
602
603 if (m_po_id != 0)
604 {
605 gl.deleteProgram(m_po_id);
606
607 m_po_id = 0;
608 }
609
610 if (m_vs_id != 0)
611 {
612 gl.deleteShader(m_vs_id);
613
614 m_vs_id = 0;
615 }
616
617 /* Release base class */
618 TestCaseBase::deinit();
619 }
620
621 /** Executes the test.
622 *
623 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
624 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
625 * Note the function throws exception should an error occur!
626 **/
iterate()627 tcu::TestNode::IterateResult GeometryShaderGetProgramiv2Test::iterate()
628 {
629 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
630 const glw::GLenum pnames[] = { m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE,
631 m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE,
632 m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS };
633 const unsigned int n_pnames = sizeof(pnames) / sizeof(pnames[0]);
634 bool result = true;
635
636 /* This test should only run if EXT_geometry_shader is supported. */
637 if (!m_is_geometry_shader_extension_supported)
638 {
639 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
640 }
641
642 /* Initialize the program object */
643 std::string specialized_minimal_fs = specializeShader(1,
644 /* parts */ &minimal_fs_code);
645 const char* specialized_minimal_fs_raw = specialized_minimal_fs.c_str();
646 std::string specialized_minimal_vs = specializeShader(1,
647 /* parts */ &minimal_vs_code);
648 const char* specialized_minimal_vs_raw = specialized_minimal_vs.c_str();
649
650 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
651 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
652
653 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
654
655 m_po_id = gl.createProgram();
656
657 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
658
659 if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, &specialized_minimal_fs_raw, m_vs_id, 1,
660 &specialized_minimal_vs_raw))
661 {
662 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to build a minimal test program object"
663 << tcu::TestLog::EndMessage;
664
665 result = false;
666 goto end;
667 }
668
669 /* Verify that GS-specific queries cause a GL_INVALID_OPERATION error
670 * for a linked PO lacking the GS stage.
671 */
672 for (unsigned int n_pname = 0; n_pname < n_pnames; ++n_pname)
673 {
674 glw::GLenum error_code = GL_NO_ERROR;
675 glw::GLenum pname = pnames[n_pname];
676 glw::GLint rv = -1;
677
678 gl.getProgramiv(m_po_id, pname, &rv);
679
680 error_code = gl.getError();
681
682 if (error_code != GL_INVALID_OPERATION)
683 {
684 m_testCtx.getLog() << tcu::TestLog::Message << "No error generated by glGetProgramiv() for pname [" << pname
685 << "]" << tcu::TestLog::EndMessage;
686
687 result = false;
688 }
689 } /* for (all pnames) */
690
691 end:
692 if (result)
693 {
694 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
695 }
696 else
697 {
698 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
699 }
700
701 return STOP;
702 }
703
704 /** Constructor
705 *
706 * @param context Test context
707 * @param extParams Not used.
708 * @param name Test case's name
709 * @param description Test case's description
710 **/
GeometryShaderGetProgramiv3Test(Context& context, const ExtParameters& extParams, const char* name, const char* description)711 GeometryShaderGetProgramiv3Test::GeometryShaderGetProgramiv3Test(Context& context, const ExtParameters& extParams,
712 const char* name, const char* description)
713 : TestCaseBase(context, extParams, name, description)
714 , m_fs_id(0)
715 , m_fs_po_id(0)
716 , m_gs_id(0)
717 , m_gs_po_id(0)
718 , m_pipeline_object_id(0)
719 , m_po_id(0)
720 , m_vs_id(0)
721 , m_vs_po_id(0)
722 {
723 }
724
725 /* Compiles a shader object using caller-specified data.
726 *
727 * @param so_id ID of a Shader Object to compile.
728 * @param so_body Body to use for the compilation process.
729 *
730 * @return true if the compilation succeeded, false otherwise */
buildShader(glw::GLuint so_id, const char* so_body)731 bool GeometryShaderGetProgramiv3Test::buildShader(glw::GLuint so_id, const char* so_body)
732 {
733 glw::GLint compile_status = GL_FALSE;
734 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
735 bool result = false;
736
737 gl.shaderSource(so_id, 1, /* count */
738 &so_body, DE_NULL); /* length */
739 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() call failed.");
740
741 gl.compileShader(so_id);
742 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() call failed.");
743
744 gl.getShaderiv(so_id, GL_COMPILE_STATUS, &compile_status);
745 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() call failed.");
746
747 result = (compile_status == GL_TRUE);
748
749 return result;
750 }
751
752 /** Builds a single shader program object using caller-specified data.
753 *
754 * @param out_spo_id Deref will be set to the ID of the created shader program object.
755 * Must not be NULL.
756 * @param spo_bits Bits to be passed to the glCreateShaderProgramv() call.
757 * @param spo_body Body to use for the glCreateShaderProgramv() call.
758 *
759 * @return true if the shader program object was linked successfully, false otherwise.
760 */
buildShaderProgram(glw::GLuint* out_spo_id, glw::GLenum spo_bits, const char* spo_body)761 bool GeometryShaderGetProgramiv3Test::buildShaderProgram(glw::GLuint* out_spo_id, glw::GLenum spo_bits,
762 const char* spo_body)
763 {
764 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
765 glw::GLint link_status = GL_FALSE;
766 bool result = true;
767
768 *out_spo_id = gl.createShaderProgramv(spo_bits, 1, /* count */
769 &spo_body);
770
771 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call failed.");
772
773 gl.getProgramiv(*out_spo_id, GL_LINK_STATUS, &link_status);
774 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() call failed.");
775
776 result = (link_status == GL_TRUE);
777
778 return result;
779 }
780
781 /** Deinitializes GLES objects created during the test. */
deinit()782 void GeometryShaderGetProgramiv3Test::deinit()
783 {
784 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
785
786 deinitPO();
787 deinitSOs(true);
788 deinitSPOs(true);
789
790 if (m_pipeline_object_id != 0)
791 {
792 gl.deleteProgramPipelines(1, &m_pipeline_object_id);
793
794 m_pipeline_object_id = 0;
795 }
796
797 /* Release base class */
798 TestCaseBase::deinit();
799 }
800
801 /** Deinitializes a program object created for the conformance test. */
deinitPO()802 void GeometryShaderGetProgramiv3Test::deinitPO()
803 {
804 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
805
806 if (m_po_id != 0)
807 {
808 gl.deleteProgram(m_po_id);
809
810 m_po_id = 0;
811 }
812 }
813
814 /** Deinitializes shader objects created for the conformance test. */
deinitSOs(bool release_all_SOs)815 void GeometryShaderGetProgramiv3Test::deinitSOs(bool release_all_SOs)
816 {
817 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
818
819 if (m_fs_id != 0 && release_all_SOs)
820 {
821 gl.deleteShader(m_fs_id);
822
823 m_fs_id = 0;
824 }
825
826 if (m_gs_id != 0)
827 {
828 gl.deleteShader(m_gs_id);
829
830 m_gs_id = 0;
831 }
832
833 if (m_vs_id != 0 && release_all_SOs)
834 {
835 gl.deleteShader(m_vs_id);
836
837 m_vs_id = 0;
838 }
839 }
840
841 /** Deinitializes shader program objects created for the conformance test. */
deinitSPOs(bool release_all_SPOs)842 void GeometryShaderGetProgramiv3Test::deinitSPOs(bool release_all_SPOs)
843 {
844 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
845
846 if (m_fs_po_id != 0 && release_all_SPOs)
847 {
848 gl.deleteProgram(m_fs_po_id);
849
850 m_fs_po_id = 0;
851 }
852
853 if (m_gs_po_id != 0)
854 {
855 gl.deleteProgram(m_gs_po_id);
856
857 m_gs_po_id = 0;
858 }
859
860 if (m_vs_po_id != 0 && release_all_SPOs)
861 {
862 gl.deleteProgram(m_vs_po_id);
863
864 m_vs_po_id = 0;
865 }
866 }
867
868 /** Retrieves ES SL layout qualifier, corresponding to user-specified
869 * primitive type.
870 *
871 * @param primitive_type Primitive type (described by a GLenum value)
872 * to use for the query.
873 *
874 * @return Requested layout qualifier.
875 */
getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)876 std::string GeometryShaderGetProgramiv3Test::getLayoutQualifierForPrimitiveType(glw::GLenum primitive_type)
877 {
878 std::string result;
879
880 switch (primitive_type)
881 {
882 case GL_LINE_STRIP:
883 result = "line_strip";
884 break;
885 case GL_LINES_ADJACENCY:
886 result = "lines_adjacency";
887 break;
888 case GL_POINTS:
889 result = "points";
890 break;
891 case GL_TRIANGLES:
892 result = "triangles";
893 break;
894 case GL_TRIANGLE_STRIP:
895 result = "triangle_strip";
896 break;
897
898 default:
899 {
900 DE_ASSERT(0);
901 }
902 } /* switch (primitive_type) */
903
904 return result;
905 }
906
907 /** Retrieves body of a geometry shadet to be used for the conformance test.
908 * The body is generated, according to the properties described by the
909 * run descriptor passed as an argument.
910 *
911 * @param run Test run descriptor.
912 *
913 * @return Requested string.
914 */
getGSCode(const _run& run)915 std::string GeometryShaderGetProgramiv3Test::getGSCode(const _run& run)
916 {
917 std::stringstream code_sstream;
918
919 code_sstream << "${VERSION}\n"
920 "${GEOMETRY_SHADER_REQUIRE}\n"
921 "\n"
922 "layout("
923 << getLayoutQualifierForPrimitiveType(run.input_primitive_type) << ", "
924 "invocations = "
925 << run.invocations << ") in;\n"
926 "layout("
927 << getLayoutQualifierForPrimitiveType(run.output_primitive_type) << ", "
928 "max_vertices = "
929 << run.max_vertices << ") out;\n"
930 "\n"
931 "out gl_PerVertex {\n"
932 " vec4 gl_Position;\n"
933 "};\n"
934 "\n"
935 "void main()\n"
936 "{\n"
937 " for (int n = 0; n < "
938 << run.max_vertices << "; ++n)\n"
939 " {\n"
940 " gl_Position = vec4(n, 0.0, 0.0, 1.0);\n"
941 " EmitVertex();\n"
942 " }\n"
943 "\n"
944 " EndPrimitive();\n"
945 "}\n";
946
947 return code_sstream.str();
948 }
949
950 /** Initializes internal _runs member with test iteration settings for all test runs. */
initTestRuns()951 void GeometryShaderGetProgramiv3Test::initTestRuns()
952 {
953 /* input primitive type | invocations | max vertices | output primitive type *
954 *----------------------------------------+-------------+--------------+-----------------------*/
955 _runs.push_back(_run(GL_LINES_ADJACENCY, 3, 16, GL_POINTS));
956 _runs.push_back(_run(GL_TRIANGLES, 12, 37, GL_LINE_STRIP));
957 _runs.push_back(_run(GL_POINTS, 31, 75, GL_TRIANGLE_STRIP));
958 }
959
960 /** Executes the test.
961 *
962 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
963 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
964 * Note the function throws exception should an error occur!
965 **/
iterate()966 tcu::TestNode::IterateResult GeometryShaderGetProgramiv3Test::iterate()
967 {
968 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
969 glw::GLint gs_spo_id = 0;
970 unsigned int n_run = 0;
971 unsigned int n_separable_object_case = 0;
972 bool result = true;
973
974 /* This test should only run if EXT_geometry_shader is supported. */
975 if (!m_is_geometry_shader_extension_supported)
976 {
977 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
978 }
979
980 /* Prepare specialized versions of minimal fragment & vertex shaders */
981 std::string minimal_fs_specialized = specializeShader(1,
982 /* parts */ &minimal_fs_code);
983 const char* minimal_fs_specialized_raw = minimal_fs_specialized.c_str();
984 std::string minimal_vs_specialized = specializeShader(1, &minimal_vs_code);
985 const char* minimal_vs_specialized_raw = minimal_vs_specialized.c_str();
986
987 /* Set up the fragment & the vertex shaders */
988 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
989 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
990 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
991
992 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
993
994 if (!buildShader(m_fs_id, minimal_fs_specialized_raw) || !buildShader(m_vs_id, minimal_vs_specialized_raw))
995 {
996 m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS failed to build." << tcu::TestLog::EndMessage;
997
998 result = false;
999 goto end;
1000 }
1001
1002 /* Set up the test program object */
1003 m_po_id = gl.createProgram();
1004
1005 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1006
1007 gl.attachShader(m_po_id, m_fs_id);
1008 gl.attachShader(m_po_id, m_gs_id);
1009 gl.attachShader(m_po_id, m_vs_id);
1010 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() call(s) failed.");
1011
1012 /* Set up the fragment & the vertex shader programs */
1013 if (!buildShaderProgram(&m_fs_po_id, GL_FRAGMENT_SHADER, minimal_fs_specialized_raw) ||
1014 !buildShaderProgram(&m_vs_po_id, GL_VERTEX_SHADER, minimal_vs_specialized_raw))
1015 {
1016 m_testCtx.getLog() << tcu::TestLog::Message << "Either FS or VS SPOs failed to build."
1017 << tcu::TestLog::EndMessage;
1018
1019 result = false;
1020 goto end;
1021 }
1022
1023 /* Set up test runs */
1024 initTestRuns();
1025
1026 /* The test should check both a geometry shader program object and a full-blown PO
1027 * consisting of FS, GS and VS. */
1028 for (n_separable_object_case = 0; n_separable_object_case < 2; /* PO, SPO cases */
1029 ++n_separable_object_case)
1030 {
1031 bool should_use_separable_object = (n_separable_object_case != 0);
1032
1033 /* Iterate over all test runs */
1034 for (n_run = 0; n_run < _runs.size(); ++n_run)
1035 {
1036 const _run& current_run = _runs[n_run];
1037 std::string gs_code = getGSCode(current_run);
1038 const char* gs_code_raw = gs_code.c_str();
1039 std::string gs_code_specialized = specializeShader(1, /* parts */
1040 &gs_code_raw);
1041 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
1042
1043 if (should_use_separable_object)
1044 {
1045 /* Deinitialize any objects that may have been created in previous iterations */
1046 deinitSPOs(false);
1047
1048 /* Set up the geometry shader program object */
1049 if (!buildShaderProgram(&m_gs_po_id, GL_GEOMETRY_SHADER, gs_code_specialized_raw))
1050 {
1051 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader program object"
1052 << tcu::TestLog::EndMessage;
1053
1054 result = false;
1055 goto end;
1056 }
1057 } /* if (should_use_pipeline_object) */
1058 else
1059 {
1060 gl.bindProgramPipeline(0);
1061 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
1062
1063 /* Set up the geometry shader object */
1064 if (!buildShader(m_gs_id, gs_code_specialized_raw))
1065 {
1066 m_testCtx.getLog() << tcu::TestLog::Message << "Failed to compile a geometry shader object."
1067 << tcu::TestLog::EndMessage;
1068
1069 result = false;
1070 goto end;
1071 }
1072
1073 /* Set up the program object */
1074 glw::GLint link_status = GL_FALSE;
1075
1076 gl.linkProgram(m_po_id);
1077 GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() call failed.");
1078
1079 gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
1080
1081 if (link_status == GL_FALSE)
1082 {
1083 m_testCtx.getLog() << tcu::TestLog::Message << "Test program object failed to link"
1084 << tcu::TestLog::EndMessage;
1085
1086 result = false;
1087 goto end;
1088 }
1089
1090 /* Bind the PO to the rendering context */
1091 gl.useProgram(m_po_id);
1092 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1093 }
1094
1095 /* Execute the queries */
1096 glw::GLuint po_id = (should_use_separable_object) ? m_gs_po_id : m_po_id;
1097 glw::GLint result_geometry_linked_vertices_out = 0;
1098 glw::GLint result_geometry_linked_input_type = 0;
1099 glw::GLint result_geometry_linked_output_type = 0;
1100 glw::GLint result_geometry_shader_invocations = 0;
1101
1102 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_VERTICES_OUT, &result_geometry_linked_vertices_out);
1103 GLU_EXPECT_NO_ERROR(gl.getError(),
1104 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_VERTICES_OUT_EXT query.");
1105
1106 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_INPUT_TYPE, &result_geometry_linked_input_type);
1107 GLU_EXPECT_NO_ERROR(gl.getError(),
1108 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
1109
1110 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_LINKED_OUTPUT_TYPE, &result_geometry_linked_output_type);
1111 GLU_EXPECT_NO_ERROR(gl.getError(),
1112 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query.");
1113
1114 gl.getProgramiv(po_id, m_glExtTokens.GEOMETRY_SHADER_INVOCATIONS, &result_geometry_shader_invocations);
1115 GLU_EXPECT_NO_ERROR(gl.getError(),
1116 "glGetProgramiv() call failed for GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query.");
1117
1118 if (current_run.input_primitive_type != (glw::GLenum)result_geometry_linked_input_type)
1119 {
1120 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_INPUT_TYPE_EXT query value "
1121 << "[" << result_geometry_linked_input_type
1122 << "]"
1123 " does not match the test run setting "
1124 "["
1125 << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
1126
1127 result = false;
1128 }
1129
1130 if (current_run.invocations != result_geometry_shader_invocations)
1131 {
1132 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_SHADER_INVOCATIONS_EXT query value "
1133 << "[" << result_geometry_shader_invocations
1134 << "]"
1135 " does not match the test run setting "
1136 "["
1137 << current_run.input_primitive_type << "]" << tcu::TestLog::EndMessage;
1138
1139 result = false;
1140 }
1141
1142 if (current_run.max_vertices != result_geometry_linked_vertices_out)
1143 {
1144 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_VERTICES_OUT query value "
1145 << "[" << result_geometry_linked_vertices_out
1146 << "]"
1147 " does not match the test run setting "
1148 "["
1149 << current_run.max_vertices << "]" << tcu::TestLog::EndMessage;
1150
1151 result = false;
1152 }
1153
1154 if (current_run.output_primitive_type != (glw::GLenum)result_geometry_linked_output_type)
1155 {
1156 m_testCtx.getLog() << tcu::TestLog::Message << "GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT query value "
1157 << "[" << result_geometry_linked_output_type
1158 << "]"
1159 " does not match the test run setting "
1160 "["
1161 << current_run.output_primitive_type << "]" << tcu::TestLog::EndMessage;
1162
1163 result = false;
1164 }
1165 } /* for (all test runs) */
1166 } /* for (PO & SPO cases) */
1167
1168 /* One more check: build a pipeline object which only defines a FS & VS stages,
1169 * and check what GS SPO ID the object reports. */
1170 gl.genProgramPipelines(1, &m_pipeline_object_id);
1171 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
1172
1173 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
1174 gl.useProgramStages(m_pipeline_object_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
1175 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
1176
1177 gl.getProgramPipelineiv(m_pipeline_object_id, m_glExtTokens.GEOMETRY_SHADER, &gs_spo_id);
1178 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramPipelineiv() call failed.");
1179
1180 if (gs_spo_id != 0)
1181 {
1182 m_testCtx.getLog() << tcu::TestLog::Message << "Pipeline object reported [" << gs_spo_id << "]"
1183 << " for GL_GEOMETRY_SHADER_EXT query, even though no GS SPO was bound."
1184 << tcu::TestLog::EndMessage;
1185
1186 result = false;
1187 }
1188
1189 end:
1190 if (result)
1191 {
1192 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1193 }
1194 else
1195 {
1196 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1197 }
1198
1199 return STOP;
1200 }
1201
1202 /** Constructor
1203 *
1204 * @param context Test context
1205 * @param extParams Not used.
1206 * @param name Test case's name
1207 * @param description Test case's description
1208 **/
GeometryShaderDrawCallWithFSAndGS(Context& context, const ExtParameters& extParams, const char* name, const char* description)1209 GeometryShaderDrawCallWithFSAndGS::GeometryShaderDrawCallWithFSAndGS(Context& context, const ExtParameters& extParams,
1210 const char* name, const char* description)
1211 : TestCaseBase(context, extParams, name, description)
1212 , m_fs_po_id(0)
1213 , m_gs_po_id(0)
1214 , m_pipeline_object_id(0)
1215 , m_vao_id(0)
1216 {
1217 }
1218
1219 /** Deinitializes GLES objects created during the test. */
deinit()1220 void GeometryShaderDrawCallWithFSAndGS::deinit()
1221 {
1222 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1223
1224 if (m_fs_po_id != 0)
1225 {
1226 gl.deleteProgram(m_fs_po_id);
1227
1228 m_fs_po_id = 0;
1229 }
1230
1231 if (m_gs_po_id != 0)
1232 {
1233 gl.deleteProgram(m_gs_po_id);
1234
1235 m_gs_po_id = 0;
1236 }
1237
1238 if (m_pipeline_object_id != 0)
1239 {
1240 gl.deleteProgramPipelines(1, &m_pipeline_object_id);
1241
1242 m_pipeline_object_id = 0;
1243 }
1244
1245 if (m_vao_id != 0)
1246 {
1247 gl.deleteVertexArrays(1, &m_vao_id);
1248
1249 m_vao_id = 0;
1250 }
1251
1252 /* Release base class */
1253 TestCaseBase::deinit();
1254 }
1255
1256 /** Executes the test.
1257 *
1258 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1259 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1260 * Note the function throws exception should an error occur!
1261 **/
iterate()1262 tcu::TestNode::IterateResult GeometryShaderDrawCallWithFSAndGS::iterate()
1263 {
1264 glw::GLenum error_code = GL_NO_ERROR;
1265 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1266 bool result = true;
1267
1268 /* This test should only run if EXT_geometry_shader is supported. */
1269 if (!m_is_geometry_shader_extension_supported)
1270 {
1271 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1272 }
1273
1274 /* Create & bind a VAO */
1275 gl.genVertexArrays(1, &m_vao_id);
1276 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1277
1278 gl.bindVertexArray(m_vao_id);
1279 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1280
1281 /* Create shader program objects */
1282 std::string code_fs_specialized = specializeShader(1, /* parts */
1283 &minimal_fs_code);
1284 const char* code_fs_specialized_raw = code_fs_specialized.c_str();
1285 std::string code_gs_specialized = specializeShader(1, /* parts */
1286 &minimal_gs_code);
1287 const char* code_gs_specialized_raw = code_gs_specialized.c_str();
1288 glw::GLint link_status = GL_FALSE;
1289
1290 m_fs_po_id = gl.createShaderProgramv(GL_FRAGMENT_SHADER, 1, /* count */
1291 &code_fs_specialized_raw);
1292 m_gs_po_id = gl.createShaderProgramv(GL_GEOMETRY_SHADER, 1, /* count */
1293 &code_gs_specialized_raw);
1294
1295 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShaderProgramv() call(s) failed.");
1296
1297 gl.getProgramiv(m_fs_po_id, GL_LINK_STATUS, &link_status);
1298
1299 if (link_status != GL_TRUE)
1300 {
1301 m_testCtx.getLog() << tcu::TestLog::Message << "Minimal fragment shader program failed to link."
1302 << tcu::TestLog::EndMessage;
1303
1304 result = false;
1305 goto end;
1306 }
1307
1308 gl.getProgramiv(m_gs_po_id, GL_LINK_STATUS, &link_status);
1309
1310 if (link_status != GL_TRUE)
1311 {
1312 m_testCtx.getLog() << tcu::TestLog::Message << "Minimal geometry shader program failed to link."
1313 << tcu::TestLog::EndMessage;
1314
1315 result = false;
1316 goto end;
1317 }
1318
1319 /* Create & set up a pipeline object */
1320 gl.genProgramPipelines(1, &m_pipeline_object_id);
1321 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
1322
1323 gl.useProgramStages(m_pipeline_object_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
1324 gl.useProgramStages(m_pipeline_object_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
1325 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
1326
1327 gl.bindProgramPipeline(m_pipeline_object_id);
1328 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
1329
1330 /* Try to do a draw call */
1331 gl.drawArrays(GL_POINTS, 0, /* first */
1332 1); /* count */
1333
1334 error_code = gl.getError();
1335 if (error_code != GL_INVALID_OPERATION)
1336 {
1337 m_testCtx.getLog() << tcu::TestLog::Message << "Invalid draw call generated an error code [" << error_code
1338 << "]"
1339 " which is different from the expected GL_INVALID_OPERATION."
1340 << tcu::TestLog::EndMessage;
1341
1342 result = false;
1343 }
1344
1345 end:
1346 // m_pipeline_object_id is generated in this function, need to be freed
1347 if (m_pipeline_object_id)
1348 {
1349 gl.deleteProgramPipelines(1, &m_pipeline_object_id);
1350 m_pipeline_object_id = 0;
1351 }
1352
1353 // m_gs_po_id is generated in this function, need to be freed
1354 if (m_gs_po_id)
1355 {
1356 gl.deleteProgram(m_gs_po_id);
1357 m_gs_po_id = 0;
1358 }
1359
1360 // m_fs_po_id is generated in this function, need to be freed
1361 if (m_fs_po_id)
1362 {
1363 gl.deleteProgram(m_fs_po_id);
1364 m_fs_po_id = 0;
1365 }
1366
1367 // m_vao_id is generated in this function, need to be freed
1368 if (m_vao_id)
1369 {
1370 gl.deleteVertexArrays(1, &m_vao_id);
1371 m_vao_id = 0;
1372 }
1373
1374 /* All done */
1375 if (result)
1376 {
1377 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1378 }
1379 else
1380 {
1381 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1382 }
1383
1384 return STOP;
1385 }
1386
1387 /** Constructor
1388 *
1389 * @param context Test context
1390 * @param extParams Not used.
1391 * @param name Test case's name
1392 * @param description Test case's description
1393 **/
GeometryShaderMaxImageUniformsTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)1394 GeometryShaderMaxImageUniformsTest::GeometryShaderMaxImageUniformsTest(Context& context, const ExtParameters& extParams,
1395 const char* name, const char* description)
1396 : TestCaseBase(context, extParams, name, description)
1397 , m_fs_id(0)
1398 , m_gl_max_geometry_image_uniforms_ext_value(0)
1399 , m_gs_id(0)
1400 , m_po_id(0)
1401 , m_texture_ids(NULL)
1402 , m_tfbo_id(0)
1403 , m_vao_id(0)
1404 , m_vs_id(0)
1405 {
1406 //Bug-15063 Only GLSL 4.50 supports opaque types
1407 if (m_glslVersion >= glu::GLSL_VERSION_130)
1408 {
1409 m_glslVersion = glu::GLSL_VERSION_450;
1410 }
1411 }
1412
1413 /** Deinitializes GLES objects created during the test. */
deinit()1414 void GeometryShaderMaxImageUniformsTest::deinit()
1415 {
1416 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1417
1418 if (m_fs_id != 0)
1419 {
1420 gl.deleteShader(m_fs_id);
1421
1422 m_fs_id = 0;
1423 }
1424
1425 if (m_gs_id != 0)
1426 {
1427 gl.deleteShader(m_gs_id);
1428
1429 m_gs_id = 0;
1430 }
1431
1432 if (m_po_id != 0)
1433 {
1434 gl.deleteProgram(m_po_id);
1435
1436 m_po_id = 0;
1437 }
1438
1439 if (m_texture_ids != NULL)
1440 {
1441 gl.deleteTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1442
1443 delete[] m_texture_ids;
1444 m_texture_ids = NULL;
1445 }
1446
1447 if (m_tfbo_id != 0)
1448 {
1449 gl.deleteBuffers(1, &m_tfbo_id);
1450 m_tfbo_id = 0;
1451 }
1452
1453 if (m_vao_id != 0)
1454 {
1455 gl.deleteVertexArrays(1, &m_vao_id);
1456 m_vao_id = 0;
1457 }
1458
1459 if (m_vs_id != 0)
1460 {
1461 gl.deleteShader(m_vs_id);
1462
1463 m_vs_id = 0;
1464 }
1465
1466 /* Set GL_PACK_ALIGNMENT to default value. */
1467 gl.pixelStorei(GL_PACK_ALIGNMENT, 4 /*default value taken from specification*/);
1468 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1469
1470 /* Release base class */
1471 TestCaseBase::deinit();
1472 }
1473
1474 /* Retrieves test-specific geometry shader source code.
1475 *
1476 * @return Requested string.
1477 */
getGSCode()1478 std::string GeometryShaderMaxImageUniformsTest::getGSCode()
1479 {
1480 std::stringstream code_sstream;
1481
1482 /* Form the GS */
1483 code_sstream << "${VERSION}\n"
1484 "${GEOMETRY_SHADER_REQUIRE}\n"
1485 "\n"
1486 "layout (points) in;\n"
1487 "layout (points, max_vertices = 1) out;\n"
1488 "\n"
1489 "precision highp iimage2D;\n"
1490 "\n"
1491 "ivec4 counter = ivec4(0);\n"
1492 "\n";
1493
1494 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1495 {
1496 code_sstream << "layout(binding = " << n_img << ", r32i) uniform iimage2D img" << n_img << ";\n";
1497 }
1498
1499 code_sstream << "\n"
1500 "void main()\n"
1501 "{\n";
1502
1503 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1504 {
1505 code_sstream << " counter += imageLoad(img" << n_img << ", ivec2(0, 0));\n";
1506 }
1507
1508 code_sstream << "\n"
1509 " gl_Position = vec4(float(counter.x), 0.0, 0.0, 1.0);\n"
1510 " EmitVertex();\n"
1511 "}\n";
1512
1513 /* Form a specialized version of the GS source code */
1514 std::string gs_code = code_sstream.str();
1515 const char* gs_code_raw = gs_code.c_str();
1516 std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1517
1518 return gs_code_specialized;
1519 }
1520
1521 /** Executes the test.
1522 *
1523 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1524 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1525 * Note the function throws exception should an error occur!
1526 **/
iterate()1527 tcu::TestNode::IterateResult GeometryShaderMaxImageUniformsTest::iterate()
1528 {
1529 glw::GLint counter = 0;
1530 glw::GLint expectedValue = 0;
1531 bool has_shader_compilation_failed = true;
1532 glw::GLfloat* ptr = DE_NULL;
1533 bool result = true;
1534 const glw::GLchar* feedbackVaryings[] = { "gl_Position" };
1535
1536 std::string fs_code_specialized = "";
1537 const char* fs_code_specialized_raw = DE_NULL;
1538 std::string gs_code_specialized = "";
1539 const char* gs_code_specialized_raw = DE_NULL;
1540 std::string vs_code_specialized = "";
1541 const char* vs_code_specialized_raw = DE_NULL;
1542
1543 /* This test should only run if EXT_geometry_shader is supported. */
1544 if (!m_is_geometry_shader_extension_supported)
1545 {
1546 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1547 }
1548
1549 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1550
1551 /* Retrieve GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname value */
1552 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_IMAGE_UNIFORMS, &m_gl_max_geometry_image_uniforms_ext_value);
1553 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
1554
1555 /* Retrieve GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT pname value */
1556 glw::GLint m_gl_max_geometry_texture_image_units_ext_value = 0;
1557 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_TEXTURE_IMAGE_UNITS, &m_gl_max_geometry_texture_image_units_ext_value);
1558 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT pname");
1559
1560 /* Retrieve GL_MAX_IMAGE_UNITS pname value */
1561 glw::GLint m_gl_max_image_units_value = 0;
1562 gl.getIntegerv(GL_MAX_IMAGE_UNITS, &m_gl_max_image_units_value);
1563 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_IMAGE_UNITS pname");
1564
1565 /* Check if m_gl_max_geometry_image_uniforms_value is less than or equal zero. */
1566 if (m_gl_max_geometry_image_uniforms_ext_value <= 0)
1567 {
1568 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1569 << "[" << m_gl_max_geometry_image_uniforms_ext_value
1570 << "]"
1571 " is less than or equal zero. Image uniforms in Geometry Shader"
1572 " are not supported."
1573 << tcu::TestLog::EndMessage;
1574
1575 if (m_gl_max_geometry_image_uniforms_ext_value == 0)
1576 {
1577 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT is 0");
1578 }
1579 else
1580 {
1581 result = false;
1582 goto end;
1583 }
1584 }
1585
1586 /* Check if m_gl_max_image_units_value is less than m_gl_max_geometry_image_uniforms_value. */
1587 if (m_gl_max_image_units_value < m_gl_max_geometry_image_uniforms_ext_value)
1588 {
1589 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT query value "
1590 << "[" << m_gl_max_geometry_image_uniforms_ext_value
1591 << "]"
1592 " is greater than GL_MAX_IMAGE_UNITS query value "
1593 "["
1594 << m_gl_max_image_units_value << "]." << tcu::TestLog::EndMessage;
1595
1596 result = false;
1597 goto end;
1598 }
1599
1600 /* Create a program object. */
1601 m_po_id = gl.createProgram();
1602 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1603
1604 /* Create shader objects. */
1605 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1606 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1607 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1608
1609 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1610
1611 /* Configure which outputs should be captured by Transform Feedback. */
1612 gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1613
1614 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1615
1616 /* Try to link the test program object */
1617 fs_code_specialized = specializeShader(1, &minimal_fs_code);
1618 fs_code_specialized_raw = fs_code_specialized.c_str();
1619
1620 gs_code_specialized = getGSCode();
1621 gs_code_specialized_raw = gs_code_specialized.c_str();
1622
1623 vs_code_specialized = specializeShader(1, &minimal_vs_code);
1624 vs_code_specialized_raw = vs_code_specialized.c_str();
1625
1626 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */
1627 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1628 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1629 &fs_code_specialized_raw, &has_shader_compilation_failed))
1630 {
1631 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1632
1633 result = false;
1634 goto end;
1635 }
1636
1637 /* Use program. */
1638 gl.useProgram(m_po_id);
1639 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
1640
1641 /* Allocate memory for m_max_image_units_value Texture Objects. */
1642 m_texture_ids = new glw::GLuint[m_gl_max_geometry_image_uniforms_ext_value];
1643
1644 /* Generate m_max_image_units_value Texture Objects. */
1645 gl.genTextures(m_gl_max_geometry_image_uniforms_ext_value, m_texture_ids);
1646 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
1647
1648 /* Set GL_PACK_ALIGNMENT to 1. */
1649 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1650 GLU_EXPECT_NO_ERROR(gl.getError(), "glPixelStorei() call failed for GL_PACK_ALIGNMENT pname.");
1651
1652 /* Bind integer 2D texture objects of resolution 1x1 to image units. */
1653 for (glw::GLint n_img = 0; n_img < (m_gl_max_geometry_image_uniforms_ext_value); ++n_img)
1654 {
1655 glw::GLint texture = m_texture_ids[n_img];
1656 glw::GLint value = n_img + 1;
1657
1658 gl.bindTexture(GL_TEXTURE_2D, texture);
1659 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
1660
1661 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_R32I, 1 /*width*/, 1 /*height*/);
1662 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
1663
1664 gl.texSubImage2D(GL_TEXTURE_2D, 0 /*level*/, 0 /*xoffset*/, 0 /*yoffset*/, 1 /*width*/, 1 /*height*/,
1665 GL_RED_INTEGER, GL_INT, &value);
1666 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexSubImage2D() call failed.");
1667
1668 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1669 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1670
1671 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1672 GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri() call failed.");
1673
1674 gl.bindImageTexture(n_img, texture, 0 /*level*/, GL_FALSE /*is layered?*/, 0 /*layer*/, GL_READ_ONLY, GL_R32I);
1675 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindImageTexture() call failed.");
1676 }
1677
1678 /* Configure VAO. */
1679 gl.genVertexArrays(1, &m_vao_id);
1680 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
1681
1682 gl.bindVertexArray(m_vao_id);
1683 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
1684
1685 /* Create a Buffer Object for Transform Feedback's outputs. */
1686 gl.genBuffers(1, &m_tfbo_id);
1687 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
1688
1689 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
1690 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
1691
1692 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, NULL, GL_STATIC_READ);
1693 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
1694
1695 /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
1696 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_tfbo_id);
1697 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
1698
1699 /* Disable rasterization and make a draw call. After that, turn on rasterization. */
1700 gl.enable(GL_RASTERIZER_DISCARD);
1701 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
1702
1703 gl.beginTransformFeedback(GL_POINTS);
1704 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
1705
1706 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
1707 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
1708
1709 gl.endTransformFeedback();
1710 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
1711
1712 gl.disable(GL_RASTERIZER_DISCARD);
1713 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
1714
1715 /* Retrieve value from Transform Feedback. */
1716 counter = 0;
1717 ptr = (glw::GLfloat*)gl.mapBufferRange(
1718 GL_ARRAY_BUFFER, 0, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
1719
1720 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
1721
1722 counter = int(ptr[0] + 0.5f);
1723
1724 gl.unmapBuffer(GL_ARRAY_BUFFER);
1725 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
1726
1727 /* Calculate expected value. */
1728 expectedValue = m_gl_max_geometry_image_uniforms_ext_value * (m_gl_max_geometry_image_uniforms_ext_value + 1) / 2;
1729
1730 if (counter != expectedValue)
1731 {
1732 result = false;
1733 }
1734
1735 end:
1736 if (result)
1737 {
1738 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1739 }
1740 else
1741 {
1742 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1743 }
1744
1745 return STOP;
1746 }
1747
1748 /** Constructor
1749 *
1750 * @param context Test context
1751 * @param extParams Not used.
1752 * @param name Test case's name
1753 * @param description Test case's description
1754 **/
GeometryShaderMaxShaderStorageBlocksTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)1755 GeometryShaderMaxShaderStorageBlocksTest::GeometryShaderMaxShaderStorageBlocksTest(Context& context,
1756 const ExtParameters& extParams,
1757 const char* name,
1758 const char* description)
1759 : TestCaseBase(context, extParams, name, description)
1760 , m_fs_id(0)
1761 , m_gl_max_geometry_shader_storage_blocks_ext_value(0)
1762 , m_gs_id(0)
1763 , m_po_id(0)
1764 , m_ssbo_id(0)
1765 , m_tfbo_id(0)
1766 , m_vao_id(0)
1767 , m_vs_id(0)
1768 {
1769 }
1770
1771 /** Deinitializes GLES objects created during the test. */
deinit()1772 void GeometryShaderMaxShaderStorageBlocksTest::deinit()
1773 {
1774 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1775
1776 if (m_fs_id != 0)
1777 {
1778 gl.deleteShader(m_fs_id);
1779 m_fs_id = 0;
1780 }
1781
1782 if (m_gs_id != 0)
1783 {
1784 gl.deleteShader(m_gs_id);
1785 m_gs_id = 0;
1786 }
1787
1788 if (m_po_id != 0)
1789 {
1790 gl.deleteProgram(m_po_id);
1791 m_po_id = 0;
1792 }
1793
1794 if (m_ssbo_id != 0)
1795 {
1796 gl.deleteBuffers(1, &m_ssbo_id);
1797 m_ssbo_id = 0;
1798 }
1799
1800 if (m_tfbo_id != 0)
1801 {
1802 gl.deleteBuffers(1, &m_tfbo_id);
1803 m_tfbo_id = 0;
1804 }
1805
1806 if (m_vao_id != 0)
1807 {
1808 gl.deleteVertexArrays(1, &m_vao_id);
1809 m_vao_id = 0;
1810 }
1811
1812 if (m_vs_id != 0)
1813 {
1814 gl.deleteShader(m_vs_id);
1815 m_vs_id = 0;
1816 }
1817
1818 /* Release base class */
1819 TestCaseBase::deinit();
1820 }
1821
1822 /* Retrieves test-specific geometry shader source code.
1823 *
1824 * @return Requested string.
1825 */
getGSCode()1826 std::string GeometryShaderMaxShaderStorageBlocksTest::getGSCode()
1827 {
1828 std::stringstream code_sstream;
1829
1830 /* Form the GS */
1831 code_sstream << "${VERSION}\n"
1832 "${GEOMETRY_SHADER_REQUIRE}\n"
1833 "\n"
1834 "layout (points) in;\n"
1835 "layout (points, max_vertices = 1) out;\n"
1836 "\n"
1837 "int counter = 0;\n"
1838 "\n";
1839
1840 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1841 {
1842 code_sstream << "layout(binding = " << n_ssb << ") buffer ssb" << n_ssb << " \n{\n"
1843 << " int value;\n"
1844 << "} S_SSB" << n_ssb << ";\n\n";
1845 }
1846
1847 code_sstream << "\n"
1848 "void main()\n"
1849 "{\n";
1850
1851 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
1852 {
1853 code_sstream << " counter += S_SSB" << n_ssb << ".value++;\n";
1854 }
1855
1856 code_sstream << "\n"
1857 " gl_Position = vec4(float(counter), 0.0, 0.0, 1.0);\n"
1858 " EmitVertex();\n"
1859 "}\n";
1860
1861 /* Form a specialized version of the GS source code */
1862 std::string gs_code = code_sstream.str();
1863 const char* gs_code_raw = gs_code.c_str();
1864 std::string gs_code_specialized = specializeShader(1 /* parts */, &gs_code_raw);
1865
1866 return gs_code_specialized;
1867 }
1868
1869 /** Executes the test.
1870 *
1871 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
1872 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
1873 * Note the function throws exception should an error occur!
1874 **/
iterate()1875 tcu::TestNode::IterateResult GeometryShaderMaxShaderStorageBlocksTest::iterate()
1876 {
1877 glw::GLint counter = 0;
1878 glw::GLint expectedValue = 0;
1879 const glw::GLchar* feedbackVaryings[] = { "gl_Position" };
1880 bool has_shader_compilation_failed = true;
1881 const glw::GLfloat initial_buffer_data[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
1882 glw::GLint int_alignment = 0;
1883 const glw::GLint int_size = sizeof(glw::GLint);
1884 glw::GLint* ptrSSBO_data = DE_NULL;
1885 glw::GLfloat* ptrTF_data = DE_NULL;
1886 bool result = true;
1887 glw::GLint ssbo_alignment = 0;
1888 glw::GLint* ssbo_data = DE_NULL;
1889 glw::GLint ssbo_data_size = 0;
1890
1891 std::string fs_code_specialized = "";
1892 const char* fs_code_specialized_raw = DE_NULL;
1893 std::string gs_code_specialized = "";
1894 const char* gs_code_specialized_raw = DE_NULL;
1895 std::string vs_code_specialized = "";
1896 const char* vs_code_specialized_raw = DE_NULL;
1897
1898 /* This test should only run if EXT_geometry_shader is supported. */
1899 if (!m_is_geometry_shader_extension_supported)
1900 {
1901 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
1902 }
1903
1904 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1905
1906 /* Retrieve GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname value */
1907 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_SHADER_STORAGE_BLOCKS,
1908 &m_gl_max_geometry_shader_storage_blocks_ext_value);
1909 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT pname");
1910
1911 /* Retrieve GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname value */
1912 glw::GLint m_gl_max_shader_storage_buffer_bindings_value = 0;
1913
1914 gl.getIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &m_gl_max_shader_storage_buffer_bindings_value);
1915 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS pname");
1916
1917 /* Check if m_gl_max_shader_storage_blocks_value is less than or equal zero. */
1918 if (m_gl_max_geometry_shader_storage_blocks_ext_value <= 0)
1919 {
1920 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1921 << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1922 << "]"
1923 " is less than or equal zero. Shader Storage Blocks"
1924 " in Geometry Shader are not supported."
1925 << tcu::TestLog::EndMessage;
1926
1927 if (m_gl_max_geometry_shader_storage_blocks_ext_value == 0)
1928 {
1929 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT is 0");
1930 }
1931 else
1932 {
1933 result = false;
1934 goto end;
1935 }
1936 }
1937
1938 /* Check if m_gl_max_shader_storage_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
1939 if (m_gl_max_shader_storage_buffer_bindings_value < m_gl_max_geometry_shader_storage_blocks_ext_value)
1940 {
1941 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT query value "
1942 << "[" << m_gl_max_geometry_shader_storage_blocks_ext_value
1943 << "]"
1944 " is greater than GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS query value "
1945 "["
1946 << m_gl_max_shader_storage_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
1947
1948 result = false;
1949 goto end;
1950 }
1951
1952 /* Create a program object. */
1953 m_po_id = gl.createProgram();
1954 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
1955
1956 /* Create shader objects. */
1957 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
1958 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
1959 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
1960
1961 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
1962
1963 /* Configure which outputs should be captured by Transform Feedback. */
1964 gl.transformFeedbackVaryings(m_po_id, 1 /* varyings count */, feedbackVaryings, GL_INTERLEAVED_ATTRIBS);
1965
1966 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call failed.");
1967
1968 /* Try to link the test program object */
1969 fs_code_specialized = specializeShader(1, &minimal_fs_code);
1970 fs_code_specialized_raw = fs_code_specialized.c_str();
1971
1972 gs_code_specialized = getGSCode();
1973 gs_code_specialized_raw = gs_code_specialized.c_str();
1974
1975 vs_code_specialized = specializeShader(1, &minimal_vs_code);
1976 vs_code_specialized_raw = vs_code_specialized.c_str();
1977
1978 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */
1979 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
1980 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
1981 &fs_code_specialized_raw, &has_shader_compilation_failed))
1982 {
1983 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
1984
1985 result = false;
1986 goto end;
1987 }
1988
1989 /* Prepare data for Shader Storage Buffer Object. */
1990 gl.getIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &ssbo_alignment);
1991 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() call failed.");
1992
1993 int_alignment = ssbo_alignment / int_size;
1994 ssbo_data_size = m_gl_max_geometry_shader_storage_blocks_ext_value * ssbo_alignment;
1995 ssbo_data = new glw::GLint[ssbo_data_size];
1996
1997 if ((ssbo_alignment % int_size) != 0)
1998 {
1999 m_testCtx.getLog() << tcu::TestLog::Message << "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT query value "
2000 "["
2001 << ssbo_alignment << "]"
2002 "divide with remainder by the size of GLint "
2003 "["
2004 << int_size << "]" << tcu::TestLog::EndMessage;
2005
2006 result = false;
2007 goto end;
2008 }
2009
2010 for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2011 {
2012 ssbo_data[i * int_alignment] = i + 1;
2013 }
2014
2015 /* Create Shader Storage Buffer Object. */
2016 gl.genBuffers(1, &m_ssbo_id);
2017 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2018
2019 gl.bindBuffer(GL_SHADER_STORAGE_BUFFER, m_ssbo_id);
2020 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2021
2022 gl.bufferData(GL_SHADER_STORAGE_BUFFER, ssbo_data_size, ssbo_data, GL_DYNAMIC_COPY);
2023 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2024
2025 /* Free unused memory. */
2026 delete[] ssbo_data;
2027 ssbo_data = NULL;
2028
2029 /* Bind specific m_ssbo_id buffer region to a specific Shader Storage Buffer binding point. */
2030 for (glw::GLint n_ssb = 0; n_ssb < (m_gl_max_geometry_shader_storage_blocks_ext_value); ++n_ssb)
2031 {
2032 glw::GLuint offset = n_ssb * ssbo_alignment;
2033
2034 gl.bindBufferRange(GL_SHADER_STORAGE_BUFFER, n_ssb /*binding index*/, m_ssbo_id, offset, int_size);
2035 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2036 }
2037
2038 /* Configure VAO. */
2039 gl.genVertexArrays(1, &m_vao_id);
2040 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2041
2042 gl.bindVertexArray(m_vao_id);
2043 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2044
2045 /* Create a Buffer Object for Transform Feedback's outputs. */
2046 gl.genBuffers(1, &m_tfbo_id);
2047 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2048
2049 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
2050 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2051
2052 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4 /* four float vector components */, initial_buffer_data,
2053 GL_STATIC_READ);
2054 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2055
2056 /* Bind Buffer Object m_tfbo_id to GL_TRANSFORM_FEEDBACK_BUFFER binding point. */
2057 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
2058 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call failed.");
2059
2060 /* Use program. */
2061 gl.useProgram(m_po_id);
2062 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2063
2064 /* Disable rasterization and make a draw call. After that, turn on rasterization. */
2065 gl.enable(GL_RASTERIZER_DISCARD);
2066 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call failed for GL_RASTERIZER_DISCARD pname.");
2067
2068 gl.beginTransformFeedback(GL_POINTS);
2069 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call failed.");
2070
2071 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2072 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2073
2074 gl.endTransformFeedback();
2075 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call failed.");
2076
2077 gl.disable(GL_RASTERIZER_DISCARD);
2078 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call failed for GL_RASTERIZER_DISCARD pname.");
2079
2080 /* Retrieve value from Transform Feedback. */
2081 ptrTF_data = (glw::GLfloat*)gl.mapBufferRange(
2082 GL_ARRAY_BUFFER, 0 /*offset*/, sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
2083 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2084
2085 counter = int(ptrTF_data[0] + 0.5f);
2086
2087 gl.unmapBuffer(GL_ARRAY_BUFFER);
2088 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2089
2090 ptrTF_data = NULL;
2091
2092 /* Retrieve values from Shader Storage Buffer Object. */
2093 ptrSSBO_data =
2094 (glw::GLint*)gl.mapBufferRange(GL_SHADER_STORAGE_BUFFER, 0 /*offset*/, ssbo_data_size, GL_MAP_READ_BIT);
2095 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2096
2097 for (int i = 0; i < m_gl_max_geometry_shader_storage_blocks_ext_value; ++i)
2098 {
2099 if (ptrSSBO_data[i * int_alignment] != i + 2)
2100 {
2101 result = false;
2102
2103 m_testCtx.getLog() << tcu::TestLog::Message << "Value read from Shader Storage Buffer "
2104 "["
2105 << ptrSSBO_data[i * int_alignment] << "] "
2106 "at index "
2107 "["
2108 << i * int_alignment << "]"
2109 "is not equal to expected value "
2110 "["
2111 << i + 2 << "]" << tcu::TestLog::EndMessage;
2112
2113 break;
2114 }
2115 }
2116
2117 gl.unmapBuffer(GL_SHADER_STORAGE_BUFFER);
2118 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2119
2120 ptrSSBO_data = NULL;
2121
2122 /* Calculate expected value. */
2123 expectedValue =
2124 m_gl_max_geometry_shader_storage_blocks_ext_value * (m_gl_max_geometry_shader_storage_blocks_ext_value + 1) / 2;
2125
2126 if (counter != expectedValue)
2127 {
2128 result = false;
2129 }
2130
2131 end:
2132 if (result)
2133 {
2134 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2135 }
2136 else
2137 {
2138 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2139 }
2140
2141 return STOP;
2142 }
2143
2144 /** Constructor
2145 *
2146 * @param context Test context
2147 * @param extParams Not used.
2148 * @param name Test case's name
2149 * @param description Test case's description
2150 **/
GeometryShaderMaxAtomicCountersTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)2151 GeometryShaderMaxAtomicCountersTest::GeometryShaderMaxAtomicCountersTest(Context& context,
2152 const ExtParameters& extParams,
2153 const char* name, const char* description)
2154 : TestCaseBase(context, extParams, name, description)
2155 , m_acbo_id(0)
2156 , m_fs_id(0)
2157 , m_gl_max_geometry_atomic_counters_ext_value(0)
2158 , m_gs_id(0)
2159 , m_po_id(0)
2160 , m_vao_id(0)
2161 , m_vs_id(0)
2162 {
2163 }
2164
2165 /** Deinitializes GLES objects created during the test. */
deinit()2166 void GeometryShaderMaxAtomicCountersTest::deinit()
2167 {
2168 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2169
2170 if (m_acbo_id != 0)
2171 {
2172 gl.deleteBuffers(1, &m_acbo_id);
2173 m_acbo_id = 0;
2174 }
2175
2176 if (m_fs_id != 0)
2177 {
2178 gl.deleteShader(m_fs_id);
2179 m_fs_id = 0;
2180 }
2181
2182 if (m_gs_id != 0)
2183 {
2184 gl.deleteShader(m_gs_id);
2185 m_gs_id = 0;
2186 }
2187
2188 if (m_po_id != 0)
2189 {
2190 gl.deleteProgram(m_po_id);
2191 m_po_id = 0;
2192 }
2193
2194 if (m_vao_id != 0)
2195 {
2196 gl.deleteVertexArrays(1, &m_vao_id);
2197 m_vao_id = 0;
2198 }
2199
2200 if (m_vs_id != 0)
2201 {
2202 gl.deleteShader(m_vs_id);
2203 m_vs_id = 0;
2204 }
2205
2206 /* Release base class */
2207 TestCaseBase::deinit();
2208 }
2209
2210 /* Retrieves test-specific geometry shader source code.
2211 *
2212 * @return Requested string.
2213 */
getGSCode()2214 std::string GeometryShaderMaxAtomicCountersTest::getGSCode()
2215 {
2216 std::stringstream code_sstream;
2217
2218 /* Form the GS */
2219 code_sstream << "${VERSION}\n"
2220 "${GEOMETRY_SHADER_REQUIRE}\n"
2221 "\n"
2222 "layout (points) in;\n"
2223 "layout (points, max_vertices = 1) out;\n"
2224 "\n"
2225 "uniform int n_loop_iterations;\n"
2226 "flat in int vertex_id[];\n"
2227 "\n";
2228
2229 code_sstream << "layout(binding = 0) uniform atomic_uint acs[" << m_gl_max_geometry_atomic_counters_ext_value
2230 << "];\n"
2231 << "\n"
2232 "void main()\n"
2233 "{\n"
2234 " for (int counter_id = 1;\n"
2235 " counter_id <= n_loop_iterations;\n"
2236 " ++counter_id)\n"
2237 " {\n"
2238 " if ((vertex_id[0] % counter_id) == 0)\n"
2239 " {\n"
2240 " atomicCounterIncrement(acs[counter_id - 1]);\n"
2241 " }\n"
2242 " }\n"
2243 "\n"
2244 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2245 " EmitVertex();\n"
2246 "}\n";
2247
2248 /* Form a specialized version of the GS source code */
2249 std::string gs_code = code_sstream.str();
2250 const char* gs_code_raw = gs_code.c_str();
2251 std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2252
2253 return gs_code_specialized;
2254 }
2255
2256 /** Executes the test.
2257 *
2258 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2259 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2260 * Note the function throws exception should an error occur!
2261 **/
iterate()2262 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCountersTest::iterate()
2263 {
2264 /* Define Vertex Shader's code for the purpose of this test. */
2265 const char* vs_code = "${VERSION}\n"
2266 "\n"
2267 "flat out int vertex_id;\n"
2268 "\n"
2269 "void main()\n"
2270 "{\n"
2271 " vertex_id = gl_VertexID;\n"
2272 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2273 "}\n";
2274
2275 bool has_shader_compilation_failed = true;
2276 glw::GLuint* initial_ac_data = DE_NULL;
2277 const unsigned int n_draw_call_vertices = 4;
2278 glw::GLint n_loop_iterations_uniform_location = -1;
2279 glw::GLuint* ptrACBO_data = DE_NULL;
2280 bool result = true;
2281
2282 std::string fs_code_specialized = "";
2283 const char* fs_code_specialized_raw = DE_NULL;
2284 std::string gs_code_specialized = "";
2285 const char* gs_code_specialized_raw = DE_NULL;
2286 std::string vs_code_specialized = "";
2287 const char* vs_code_specialized_raw = DE_NULL;
2288
2289 /* This test should only run if EXT_geometry_shader is supported. */
2290 if (!m_is_geometry_shader_extension_supported)
2291 {
2292 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2293 }
2294
2295 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2296
2297 /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname value */
2298 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTERS, &m_gl_max_geometry_atomic_counters_ext_value);
2299 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT pname");
2300
2301 /* Check if m_gl_max_atomic_counters_value is less than or equal zero. */
2302 if (m_gl_max_geometry_atomic_counters_ext_value <= 0)
2303 {
2304 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT query value "
2305 << "[" << m_gl_max_geometry_atomic_counters_ext_value
2306 << "]"
2307 " is less than or equal to zero. Atomic Counters"
2308 " in Geometry Shader are not supported."
2309 << tcu::TestLog::EndMessage;
2310
2311 if (m_gl_max_geometry_atomic_counters_ext_value == 0)
2312 {
2313 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT is 0");
2314 }
2315 else
2316 {
2317 result = false;
2318 goto end;
2319 }
2320 }
2321
2322 /* Create a program object. */
2323 m_po_id = gl.createProgram();
2324 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2325
2326 /* Create shader objects. */
2327 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2328 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2329 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2330
2331 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2332
2333 /* Try to link the test program object */
2334 fs_code_specialized = specializeShader(1, &minimal_fs_code);
2335 fs_code_specialized_raw = fs_code_specialized.c_str();
2336
2337 gs_code_specialized = getGSCode();
2338 gs_code_specialized_raw = gs_code_specialized.c_str();
2339
2340 vs_code_specialized = specializeShader(1, &vs_code);
2341 vs_code_specialized_raw = vs_code_specialized.c_str();
2342
2343 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */
2344 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2345 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2346 &fs_code_specialized_raw, &has_shader_compilation_failed))
2347 {
2348 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2349
2350 result = false;
2351 goto end;
2352 }
2353
2354 /* Create Atomic Counter Buffer Objects. */
2355 gl.genBuffers(1, &m_acbo_id);
2356 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2357
2358 /* Prepare initial data - zeroes - to fill the Atomic Counter Buffer Object. */
2359 initial_ac_data = new glw::GLuint[m_gl_max_geometry_atomic_counters_ext_value];
2360 memset(initial_ac_data, 0, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value);
2361
2362 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_id);
2363 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2364
2365 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value, NULL,
2366 GL_DYNAMIC_COPY);
2367 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2368
2369 gl.bufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2370 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2371 initial_ac_data /*initialize with zeroes*/);
2372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferSubData() call failed.");
2373
2374 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0 /*binding index*/, m_acbo_id /*buffer*/);
2375 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2376
2377 /* Configure VAO. */
2378 gl.genVertexArrays(1, &m_vao_id);
2379 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2380
2381 gl.bindVertexArray(m_vao_id);
2382 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2383
2384 /* Use program. */
2385 n_loop_iterations_uniform_location = gl.getUniformLocation(m_po_id, "n_loop_iterations");
2386
2387 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation() call failed.");
2388 if (n_loop_iterations_uniform_location == -1)
2389 {
2390 TCU_FAIL("n_loop_iterations uniform is considered inactive");
2391 }
2392 else
2393 {
2394 gl.useProgram(m_po_id);
2395 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2396
2397 gl.uniform1i(n_loop_iterations_uniform_location, m_gl_max_geometry_atomic_counters_ext_value);
2398 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i() call failed.");
2399 }
2400
2401 /* Issue the draw call */
2402 gl.drawArrays(GL_POINTS, 0, n_draw_call_vertices);
2403 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2404
2405 /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2406 ptrACBO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2407 sizeof(glw::GLuint) * m_gl_max_geometry_atomic_counters_ext_value,
2408 GL_MAP_READ_BIT);
2409 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2410
2411 for (glw::GLint n_ac = 0; n_ac < m_gl_max_geometry_atomic_counters_ext_value; ++n_ac)
2412 {
2413 unsigned int expected_value = 0;
2414
2415 for (unsigned int n_draw_call_vertex = 0; n_draw_call_vertex < n_draw_call_vertices; ++n_draw_call_vertex)
2416 {
2417 if ((n_draw_call_vertex % (n_ac + 1)) == 0)
2418 {
2419 ++expected_value;
2420 }
2421 }
2422
2423 if (ptrACBO_data[n_ac] != expected_value)
2424 {
2425 result = false;
2426 break;
2427 }
2428 }
2429
2430 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2431 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2432
2433 ptrACBO_data = NULL;
2434
2435 end:
2436 if (result)
2437 {
2438 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2439 }
2440 else
2441 {
2442 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2443 }
2444
2445 return STOP;
2446 }
2447
2448 /** Constructor
2449 *
2450 * @param context Test context
2451 * @param extParams Not used.
2452 * @param name Test case's name
2453 * @param description Test case's description
2454 **/
GeometryShaderMaxAtomicCounterBuffersTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)2455 GeometryShaderMaxAtomicCounterBuffersTest::GeometryShaderMaxAtomicCounterBuffersTest(Context& context,
2456 const ExtParameters& extParams,
2457 const char* name,
2458 const char* description)
2459 : TestCaseBase(context, extParams, name, description)
2460 , m_acbo_ids(NULL)
2461 , m_fs_id(0)
2462 , m_gl_max_atomic_counter_buffer_bindings_value(0)
2463 , m_gl_max_geometry_atomic_counter_buffers_ext_value(0)
2464 , m_gs_id(0)
2465 , m_po_id(0)
2466 , m_vao_id(0)
2467 , m_vs_id(0)
2468 {
2469 }
2470
2471 /** Deinitializes GLES objects created during the test. */
deinit()2472 void GeometryShaderMaxAtomicCounterBuffersTest::deinit()
2473 {
2474 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2475
2476 if (m_acbo_ids != NULL)
2477 {
2478 if (m_gl_max_geometry_atomic_counter_buffers_ext_value > 0)
2479 {
2480 gl.deleteBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2481
2482 delete[] m_acbo_ids;
2483 m_acbo_ids = NULL;
2484 }
2485 }
2486
2487 if (m_fs_id != 0)
2488 {
2489 gl.deleteShader(m_fs_id);
2490 m_fs_id = 0;
2491 }
2492
2493 if (m_gs_id != 0)
2494 {
2495 gl.deleteShader(m_gs_id);
2496 m_gs_id = 0;
2497 }
2498
2499 if (m_po_id != 0)
2500 {
2501 gl.deleteProgram(m_po_id);
2502 m_po_id = 0;
2503 }
2504
2505 if (m_vao_id != 0)
2506 {
2507 gl.deleteVertexArrays(1, &m_vao_id);
2508 m_vao_id = 0;
2509 }
2510
2511 if (m_vs_id != 0)
2512 {
2513 gl.deleteShader(m_vs_id);
2514 m_vs_id = 0;
2515 }
2516
2517 /* Release base class */
2518 TestCaseBase::deinit();
2519 }
2520
2521 /* Retrieves test-specific geometry shader source code.
2522 *
2523 * @return Requested string.
2524 */
getGSCode()2525 std::string GeometryShaderMaxAtomicCounterBuffersTest::getGSCode()
2526 {
2527 std::stringstream code_sstream;
2528
2529 /* Form the GS */
2530 code_sstream << "${VERSION}\n"
2531 "${GEOMETRY_SHADER_REQUIRE}\n"
2532 "\n"
2533 "layout (points) in;\n"
2534 "layout (points, max_vertices = 1) out;\n"
2535 "\n"
2536 "flat in int vertex_id[];\n"
2537 "\n";
2538
2539 for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2540 {
2541 code_sstream << "layout(binding = " << n_ac << ") uniform atomic_uint ac" << n_ac << ";\n";
2542 }
2543
2544 code_sstream << "\n"
2545 "void main()\n"
2546 "{\n"
2547 " for(int counter_id = 1; counter_id <= "
2548 << m_gl_max_geometry_atomic_counter_buffers_ext_value
2549 << "; ++counter_id)\n"
2550 " {\n"
2551 " if((vertex_id[0] % counter_id) == 0)\n"
2552 " {\n";
2553
2554 for (glw::GLint n_ac = 0; n_ac < (m_gl_max_geometry_atomic_counter_buffers_ext_value); ++n_ac)
2555 {
2556 code_sstream << " atomicCounterIncrement(ac" << n_ac << ");\n";
2557 }
2558
2559 code_sstream << " }\n"
2560 " }\n";
2561
2562 code_sstream << "\n"
2563 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2564 " EmitVertex();\n"
2565 "}\n";
2566
2567 /* Form a specialized version of the GS source code */
2568 std::string gs_code = code_sstream.str();
2569 const char* gs_code_raw = gs_code.c_str();
2570 std::string gs_code_specialized = specializeShader(1, /* parts */ &gs_code_raw);
2571
2572 return gs_code_specialized;
2573 }
2574
2575 /** Executes the test.
2576 *
2577 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2578 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2579 * Note the function throws exception should an error occur!
2580 **/
iterate()2581 tcu::TestNode::IterateResult GeometryShaderMaxAtomicCounterBuffersTest::iterate()
2582 {
2583 /* Define Vertex Shader's code for the purpose of this test. */
2584 const char* vs_code = "${VERSION}\n"
2585 "\n"
2586 "flat out int vertex_id;\n"
2587 "\n"
2588 "void main()\n"
2589 "{\n"
2590 " vertex_id = gl_VertexID;\n"
2591 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
2592 "}\n";
2593
2594 unsigned int expected_value = 0;
2595 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2596 bool has_shader_compilation_failed = true;
2597 const glw::GLuint initial_ac_data = 0;
2598 const glw::GLuint number_of_indices = 128 * m_gl_max_geometry_atomic_counter_buffers_ext_value;
2599 bool result = true;
2600
2601 std::string fs_code_specialized = "";
2602 const char* fs_code_specialized_raw = DE_NULL;
2603 std::string gs_code_specialized = "";
2604 const char* gs_code_specialized_raw = DE_NULL;
2605 std::string vs_code_specialized = "";
2606 const char* vs_code_specialized_raw = DE_NULL;
2607
2608 /* This test should only run if EXT_geometry_shader is supported. */
2609 if (!m_is_geometry_shader_extension_supported)
2610 {
2611 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2612 }
2613
2614 /* Retrieve GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname value */
2615 gl.getIntegerv(m_glExtTokens.MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS,
2616 &m_gl_max_geometry_atomic_counter_buffers_ext_value);
2617 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT pname");
2618
2619 /* Retrieve GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname value */
2620 gl.getIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &m_gl_max_atomic_counter_buffer_bindings_value);
2621 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS pname");
2622
2623 /* Check if m_gl_max_geometry_atomic_counter_buffers_ext_value is less than or equal zero. */
2624 if (m_gl_max_geometry_atomic_counter_buffers_ext_value <= 0)
2625 {
2626 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2627 << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2628 << "]"
2629 " is less than or equal to zero. Atomic Counter Buffers"
2630 " are not supported."
2631 << tcu::TestLog::EndMessage;
2632
2633 if (m_gl_max_geometry_atomic_counter_buffers_ext_value == 0)
2634 {
2635 throw tcu::NotSupportedError("GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT is 0");
2636 }
2637 else
2638 {
2639 result = false;
2640 goto end;
2641 }
2642 }
2643
2644 /* Check if m_gl_max_atomic_counter_buffer_bindings_value is less than m_gl_max_shader_storage_blocks_value. */
2645 if (m_gl_max_atomic_counter_buffer_bindings_value < m_gl_max_geometry_atomic_counter_buffers_ext_value)
2646 {
2647 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT query value "
2648 << "[" << m_gl_max_geometry_atomic_counter_buffers_ext_value
2649 << "]"
2650 " is greater than GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS query value "
2651 "["
2652 << m_gl_max_atomic_counter_buffer_bindings_value << "]." << tcu::TestLog::EndMessage;
2653
2654 result = false;
2655 goto end;
2656 }
2657
2658 /* Create a program object. */
2659 m_po_id = gl.createProgram();
2660 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2661
2662 /* Create shader objects. */
2663 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2664 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2665 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
2666
2667 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2668
2669 /* Try to link the test program object */
2670 fs_code_specialized = specializeShader(1, &minimal_fs_code);
2671 fs_code_specialized_raw = fs_code_specialized.c_str();
2672
2673 gs_code_specialized = getGSCode();
2674 gs_code_specialized_raw = gs_code_specialized.c_str();
2675
2676 vs_code_specialized = specializeShader(1, &vs_code);
2677 vs_code_specialized_raw = vs_code_specialized.c_str();
2678
2679 if (!TestCaseBase::buildProgram(m_po_id, m_gs_id, 1, /* n_sh1_body_parts */
2680 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh2_body_parts */
2681 &vs_code_specialized_raw, m_fs_id, 1, /* n_sh3_body_parts */
2682 &fs_code_specialized_raw, &has_shader_compilation_failed))
2683 {
2684 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed." << tcu::TestLog::EndMessage;
2685
2686 result = false;
2687 goto end;
2688 }
2689
2690 /* Create Atomic Counter Buffer Objects. */
2691 m_acbo_ids = new glw::GLuint[m_gl_max_geometry_atomic_counter_buffers_ext_value];
2692
2693 gl.genBuffers(m_gl_max_geometry_atomic_counter_buffers_ext_value, m_acbo_ids);
2694 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call failed.");
2695
2696 for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2697 {
2698 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2699 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed for GL_SHADER_STORAGE_BUFFER pname.");
2700
2701 gl.bufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(glw::GLuint), &initial_ac_data /*initialize with zeroes*/,
2702 GL_DYNAMIC_COPY);
2703 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call failed.");
2704
2705 gl.bindBufferBase(GL_ATOMIC_COUNTER_BUFFER, n_acb /*binding index*/, m_acbo_ids[n_acb] /*buffer*/);
2706 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferRange() call failed.");
2707 }
2708
2709 /* Configure VAO. */
2710 gl.genVertexArrays(1, &m_vao_id);
2711 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2712
2713 gl.bindVertexArray(m_vao_id);
2714 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2715
2716 /* Use program. */
2717 gl.useProgram(m_po_id);
2718 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
2719
2720 gl.drawArrays(GL_POINTS, 0 /*starting index*/, number_of_indices);
2721 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
2722
2723 /* Calculate expected value. */
2724 /* For each point being processed by Geometry Shader. */
2725 for (glw::GLuint vertex_id = 0; vertex_id < number_of_indices; ++vertex_id)
2726 {
2727 /* And for each atomic counter ID. */
2728 for (int atomic_counter_id = 1; atomic_counter_id <= m_gl_max_geometry_atomic_counter_buffers_ext_value;
2729 ++atomic_counter_id)
2730 {
2731 /* Check if (vertex_id % atomic_counter_id) == 0. If it is true, increment expected_value. */
2732 if (vertex_id % atomic_counter_id == 0)
2733 {
2734 ++expected_value;
2735 }
2736 }
2737 }
2738
2739 /* Retrieve values from Atomic Counter Buffer Objects and check if these values are valid. */
2740 for (glw::GLint n_acb = 0; n_acb < m_gl_max_geometry_atomic_counter_buffers_ext_value; ++n_acb)
2741 {
2742 gl.bindBuffer(GL_ATOMIC_COUNTER_BUFFER, m_acbo_ids[n_acb]);
2743 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call failed.");
2744
2745 glw::GLuint* ptrABO_data = (glw::GLuint*)gl.mapBufferRange(GL_ATOMIC_COUNTER_BUFFER, 0 /*offset*/,
2746 sizeof(glw::GLuint) /*length*/, GL_MAP_READ_BIT);
2747 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
2748
2749 if (ptrABO_data[0] != expected_value)
2750 {
2751 result = false;
2752 break;
2753 }
2754
2755 gl.unmapBuffer(GL_ATOMIC_COUNTER_BUFFER);
2756 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
2757
2758 ptrABO_data = NULL;
2759 }
2760
2761 end:
2762 if (result)
2763 {
2764 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2765 }
2766 else
2767 {
2768 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2769 }
2770
2771 return STOP;
2772 }
2773
2774 /** Constructor
2775 *
2776 * @param context Test context
2777 * @param extParams Not used.
2778 * @param name Test case's name
2779 * @param description Test case's description
2780 **/
2781 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::
GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)2782 GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest(Context& context, const ExtParameters& extParams,
2783 const char* name, const char* description)
2784 : TestCaseBase(context, extParams, name, description)
2785 , m_fs_id(0)
2786 , m_fs_po_id(0)
2787 , m_gs_id(0)
2788 , m_gs_po_id(0)
2789 , m_ppo_id(0)
2790 , m_vao_id(0)
2791 {
2792 }
2793
2794 /** Deinitializes GLES objects created during the test. */
deinit()2795 void GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::deinit()
2796 {
2797 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2798
2799 if (m_fs_id != 0)
2800 {
2801 gl.deleteShader(m_fs_id);
2802 m_fs_id = 0;
2803 }
2804
2805 if (m_fs_po_id != 0)
2806 {
2807 gl.deleteProgram(m_fs_po_id);
2808 m_fs_po_id = 0;
2809 }
2810
2811 if (m_gs_id != 0)
2812 {
2813 gl.deleteShader(m_gs_id);
2814 m_gs_id = 0;
2815 }
2816
2817 if (m_gs_po_id != 0)
2818 {
2819 gl.deleteProgram(m_gs_po_id);
2820 m_gs_po_id = 0;
2821 }
2822
2823 if (m_ppo_id != 0)
2824 {
2825 gl.deleteProgramPipelines(1, &m_ppo_id);
2826 m_ppo_id = 0;
2827 }
2828
2829 if (m_vao_id != 0)
2830 {
2831 gl.deleteVertexArrays(1, &m_vao_id);
2832 m_vao_id = 0;
2833 }
2834
2835 /* Release base class */
2836 TestCaseBase::deinit();
2837 }
2838
2839 /** Executes the test.
2840 *
2841 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
2842 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
2843 * Note the function throws exception should an error occur!
2844 **/
iterate()2845 tcu::TestNode::IterateResult GeometryShaderPiplineProgramObjectWithoutActiveVSProgramTest::iterate()
2846 {
2847 bool has_shader_compilation_failed = true;
2848 bool result = true;
2849 glw::GLenum error = GL_NO_ERROR;
2850
2851 /* This test should only run if EXT_geometry_shader is supported. */
2852 if (!m_is_geometry_shader_extension_supported)
2853 {
2854 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
2855 }
2856
2857 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2858
2859 /* Create separable program objects. */
2860 m_fs_po_id = gl.createProgram();
2861 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2862
2863 gl.programParameteri(m_fs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2864 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2865
2866 m_gs_po_id = gl.createProgram();
2867 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
2868
2869 gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
2870 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
2871
2872 /* Create shader objects. */
2873 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
2874 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
2875
2876 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
2877
2878 /* Try to link the test program object */
2879 std::string fs_code_specialized = specializeShader(1, &minimal_fs_code);
2880 const char* fs_code_specialized_raw = fs_code_specialized.c_str();
2881 std::string gs_code_specialized = specializeShader(1, &minimal_gs_code);
2882 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
2883
2884 if (!TestCaseBase::buildProgram(m_fs_po_id, m_fs_id, 1, /* n_sh1_body_parts */
2885 &fs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2886 NULL, 0, 0, /* n_sh3_body_parts */
2887 NULL, &has_shader_compilation_failed))
2888 {
2889 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment Shader Program object linking failed."
2890 << tcu::TestLog::EndMessage;
2891
2892 result = false;
2893 goto end;
2894 }
2895
2896 if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1, /* n_sh1_body_parts */
2897 &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
2898 NULL, 0, 0, /* n_sh3_body_parts */
2899 NULL, &has_shader_compilation_failed))
2900 {
2901 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
2902 << tcu::TestLog::EndMessage;
2903
2904 result = false;
2905 goto end;
2906 }
2907
2908 /* Configure Pipeline Object. */
2909 gl.genProgramPipelines(1, &m_ppo_id);
2910 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call failed.");
2911
2912 gl.useProgramStages(m_ppo_id, GL_FRAGMENT_SHADER_BIT, m_fs_po_id);
2913 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2914
2915 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
2916 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call failed.");
2917
2918 /* Configure VAO. */
2919 gl.genVertexArrays(1, &m_vao_id);
2920 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
2921
2922 gl.bindVertexArray(m_vao_id);
2923 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
2924
2925 /* Use Program Pipeline Object. */
2926 gl.bindProgramPipeline(m_ppo_id);
2927 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call failed.");
2928
2929 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
2930
2931 error = gl.getError();
2932
2933 /* Check if correct error was generated. */
2934 if (GL_INVALID_OPERATION != error)
2935 {
2936 result = false;
2937
2938 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
2939 << tcu::TestLog::EndMessage;
2940 }
2941
2942 end:
2943 if (result)
2944 {
2945 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2946 }
2947 else
2948 {
2949 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2950 }
2951
2952 return STOP;
2953 }
2954
2955 /** Constructor
2956 *
2957 * @param context Test context
2958 * @param extParams Not used.
2959 * @param name Test case's name
2960 * @param description Test case's description
2961 **/
GeometryShaderIncompatibleDrawCallModeTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)2962 GeometryShaderIncompatibleDrawCallModeTest::GeometryShaderIncompatibleDrawCallModeTest(Context& context,
2963 const ExtParameters& extParams,
2964 const char* name,
2965 const char* description)
2966 : TestCaseBase(context, extParams, name, description)
2967 , m_fs_id(0)
2968 , m_gs_ids(NULL)
2969 , m_number_of_gs(5 /*taken from test spec*/)
2970 , m_po_ids(NULL)
2971 {
2972 m_vao_id = 0;
2973 m_vs_id = 0;
2974 }
2975
2976 /** Deinitializes GLES objects created during the test. */
deinit()2977 void GeometryShaderIncompatibleDrawCallModeTest::deinit()
2978 {
2979 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2980
2981 if (m_fs_id != 0)
2982 {
2983 gl.deleteShader(m_fs_id);
2984 m_fs_id = 0;
2985 }
2986
2987 if (m_gs_ids != 0)
2988 {
2989 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
2990 {
2991 gl.deleteShader(m_gs_ids[i]);
2992 m_gs_ids[i] = 0;
2993 }
2994
2995 delete[] m_gs_ids;
2996 m_gs_ids = NULL;
2997 }
2998
2999 if (m_po_ids != 0)
3000 {
3001 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3002 {
3003 gl.deleteProgram(m_po_ids[i]);
3004 m_po_ids[i] = 0;
3005 }
3006
3007 delete[] m_po_ids;
3008 m_po_ids = NULL;
3009 }
3010
3011 if (m_vao_id != 0)
3012 {
3013 gl.deleteVertexArrays(1, &m_vao_id);
3014 m_vao_id = 0;
3015 }
3016
3017 if (m_vs_id != 0)
3018 {
3019 gl.deleteShader(m_vs_id);
3020 m_vs_id = 0;
3021 }
3022
3023 /* Release base class */
3024 TestCaseBase::deinit();
3025 }
3026
3027 /** Executes the test.
3028 *
3029 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3030 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3031 * Note the function throws exception should an error occur!
3032 **/
iterate()3033 tcu::TestNode::IterateResult GeometryShaderIncompatibleDrawCallModeTest::iterate()
3034 {
3035 /* Define 5 Geometry Shaders for purpose of this test. */
3036 const char* gs_code_points = "${VERSION}\n"
3037 "${GEOMETRY_SHADER_REQUIRE}\n"
3038 "\n"
3039 "layout (points) in;\n"
3040 "layout (points, max_vertices = 1) out;\n"
3041 "\n"
3042 "${IN_PER_VERTEX_DECL_ARRAY}"
3043 "\n"
3044 "void main()\n"
3045 "{\n"
3046 " gl_Position = gl_in[0].gl_Position;\n"
3047 " EmitVertex();\n"
3048 "}\n";
3049
3050 const char* gs_code_lines = "${VERSION}\n"
3051 "${GEOMETRY_SHADER_REQUIRE}\n"
3052 "\n"
3053 "layout (lines) in;\n"
3054 "layout (points, max_vertices = 1) out;\n"
3055 "\n"
3056 "${IN_PER_VERTEX_DECL_ARRAY}"
3057 "\n"
3058 "void main()\n"
3059 "{\n"
3060 " gl_Position = gl_in[0].gl_Position;\n"
3061 " EmitVertex();\n"
3062 "}\n";
3063
3064 const char* gs_code_lines_adjacency = "${VERSION}\n"
3065 "${GEOMETRY_SHADER_REQUIRE}\n"
3066 "\n"
3067 "layout (lines_adjacency) in;\n"
3068 "layout (points, max_vertices = 1) out;\n"
3069 "\n"
3070 "${IN_PER_VERTEX_DECL_ARRAY}"
3071 "\n"
3072 "void main()\n"
3073 "{\n"
3074 " gl_Position = gl_in[0].gl_Position;\n"
3075 " EmitVertex();\n"
3076 "}\n";
3077
3078 const char* gs_code_triangles = "${VERSION}\n"
3079 "${GEOMETRY_SHADER_REQUIRE}\n"
3080 "\n"
3081 "layout (triangles) in;\n"
3082 "layout (points, max_vertices = 1) out;\n"
3083 "\n"
3084 "${IN_PER_VERTEX_DECL_ARRAY}"
3085 "\n"
3086 "void main()\n"
3087 "{\n"
3088 " gl_Position = gl_in[0].gl_Position;\n"
3089 " EmitVertex();\n"
3090 "}\n";
3091
3092 const char* gs_code_triangles_adjacency = "${VERSION}\n"
3093 "${GEOMETRY_SHADER_REQUIRE}\n"
3094 "\n"
3095 "layout (triangles_adjacency) in;\n"
3096 "layout (points, max_vertices = 1) out;\n"
3097 "\n"
3098 "${IN_PER_VERTEX_DECL_ARRAY}"
3099 "\n"
3100 "void main()\n"
3101 "{\n"
3102 " gl_Position = gl_in[0].gl_Position;\n"
3103 " EmitVertex();\n"
3104 "}\n";
3105
3106 bool has_shader_compilation_failed = true;
3107 bool result = true;
3108
3109 m_gs_ids = new glw::GLuint[m_number_of_gs];
3110 m_po_ids = new glw::GLuint[m_number_of_gs];
3111
3112 /* This test should only run if EXT_geometry_shader is supported. */
3113 if (!m_is_geometry_shader_extension_supported)
3114 {
3115 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3116 }
3117
3118 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3119
3120 /* Create program objects & geometry shader objects. */
3121 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3122 {
3123 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3124 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3125
3126 m_po_ids[i] = gl.createProgram();
3127 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3128 }
3129
3130 /* Create shader object. */
3131 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3132 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3133 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3134
3135 /* Try to link the test program object */
3136 std::string fs_code_specialized = specializeShader(1, &minimal_fs_code);
3137 const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3138
3139 std::string gs_codes_specialized[] = { specializeShader(1, &gs_code_points), specializeShader(1, &gs_code_lines),
3140 specializeShader(1, &gs_code_lines_adjacency),
3141 specializeShader(1, &gs_code_triangles),
3142 specializeShader(1, &gs_code_triangles_adjacency) };
3143
3144 const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str(),
3145 gs_codes_specialized[2].c_str(), gs_codes_specialized[3].c_str(),
3146 gs_codes_specialized[4].c_str() };
3147 std::string vs_code_specialized = specializeShader(1, &minimal_vs_code);
3148 const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3149
3150 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3151 {
3152 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */
3153 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3154 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3155 &vs_code_specialized_raw, &has_shader_compilation_failed))
3156 {
3157 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3158 << "[" << i << "]." << tcu::TestLog::EndMessage;
3159
3160 result = false;
3161 break;
3162 }
3163 }
3164
3165 if (result)
3166 {
3167 /* Configure VAO. */
3168 gl.genVertexArrays(1, &m_vao_id);
3169 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3170
3171 gl.bindVertexArray(m_vao_id);
3172 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3173
3174 for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3175 {
3176 /* Use Program Object. */
3177 gl.useProgram(m_po_ids[po]);
3178 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3179
3180 if (po != 0)
3181 {
3182 gl.drawArrays(GL_POINTS, 0 /*starting index*/, 1 /*number of indices*/);
3183
3184 if (GL_INVALID_OPERATION != gl.getError())
3185 {
3186 result = false;
3187
3188 m_testCtx.getLog() << tcu::TestLog::Message
3189 << "Error different than GL_INVALID_OPEARATION was generated."
3190 << tcu::TestLog::EndMessage;
3191
3192 break;
3193 }
3194 }
3195
3196 if (po != 1)
3197 {
3198 gl.drawArrays(GL_LINES, 0 /*starting index*/, 2 /*number of indices*/);
3199
3200 if (GL_INVALID_OPERATION != gl.getError())
3201 {
3202 result = false;
3203
3204 m_testCtx.getLog() << tcu::TestLog::Message
3205 << "Error different than GL_INVALID_OPEARATION was generated."
3206 << tcu::TestLog::EndMessage;
3207
3208 break;
3209 }
3210
3211 gl.drawArrays(GL_LINE_LOOP, 0 /*starting index*/, 2 /*number of indices*/);
3212
3213 if (GL_INVALID_OPERATION != gl.getError())
3214 {
3215 result = false;
3216
3217 m_testCtx.getLog() << tcu::TestLog::Message
3218 << "Error different than GL_INVALID_OPEARATION was generated."
3219 << tcu::TestLog::EndMessage;
3220
3221 break;
3222 }
3223
3224 gl.drawArrays(GL_LINE_STRIP, 0 /*starting index*/, 2 /*number of indices*/);
3225
3226 if (GL_INVALID_OPERATION != gl.getError())
3227 {
3228 result = false;
3229
3230 m_testCtx.getLog() << tcu::TestLog::Message
3231 << "Error different than GL_INVALID_OPEARATION was generated."
3232 << tcu::TestLog::EndMessage;
3233
3234 break;
3235 }
3236 }
3237
3238 if (po != 2)
3239 {
3240 gl.drawArrays(GL_LINES_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3241
3242 if (GL_INVALID_OPERATION != gl.getError())
3243 {
3244 result = false;
3245
3246 m_testCtx.getLog() << tcu::TestLog::Message
3247 << "Error different than GL_INVALID_OPEARATION was generated."
3248 << tcu::TestLog::EndMessage;
3249
3250 break;
3251 }
3252
3253 gl.drawArrays(GL_LINE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 4 /*number of indices*/);
3254
3255 if (GL_INVALID_OPERATION != gl.getError())
3256 {
3257 result = false;
3258
3259 m_testCtx.getLog() << tcu::TestLog::Message
3260 << "Error different than GL_INVALID_OPEARATION was generated."
3261 << tcu::TestLog::EndMessage;
3262
3263 break;
3264 }
3265 }
3266
3267 if (po != 3)
3268 {
3269 gl.drawArrays(GL_TRIANGLES, 0 /*starting index*/, 3 /*number of indices*/);
3270
3271 if (GL_INVALID_OPERATION != gl.getError())
3272 {
3273 result = false;
3274
3275 m_testCtx.getLog() << tcu::TestLog::Message
3276 << "Error different than GL_INVALID_OPEARATION was generated."
3277 << tcu::TestLog::EndMessage;
3278
3279 break;
3280 }
3281
3282 gl.drawArrays(GL_TRIANGLE_FAN, 0 /*starting index*/, 3 /*number of indices*/);
3283
3284 if (GL_INVALID_OPERATION != gl.getError())
3285 {
3286 result = false;
3287
3288 m_testCtx.getLog() << tcu::TestLog::Message
3289 << "Error different than GL_INVALID_OPEARATION was generated."
3290 << tcu::TestLog::EndMessage;
3291
3292 break;
3293 }
3294
3295 gl.drawArrays(GL_TRIANGLE_STRIP, 0 /*starting index*/, 3 /*number of indices*/);
3296
3297 if (GL_INVALID_OPERATION != gl.getError())
3298 {
3299 result = false;
3300
3301 m_testCtx.getLog() << tcu::TestLog::Message
3302 << "Error different than GL_INVALID_OPEARATION was generated."
3303 << tcu::TestLog::EndMessage;
3304
3305 break;
3306 }
3307 }
3308
3309 if (po != 4)
3310 {
3311 gl.drawArrays(GL_TRIANGLES_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3312
3313 if (GL_INVALID_OPERATION != gl.getError())
3314 {
3315 result = false;
3316
3317 m_testCtx.getLog() << tcu::TestLog::Message
3318 << "Error different than GL_INVALID_OPEARATION was generated."
3319 << tcu::TestLog::EndMessage;
3320
3321 break;
3322 }
3323
3324 gl.drawArrays(GL_TRIANGLE_STRIP_ADJACENCY_EXT, 0 /*starting index*/, 6 /*number of indices*/);
3325
3326 if (GL_INVALID_OPERATION != gl.getError())
3327 {
3328 result = false;
3329
3330 m_testCtx.getLog() << tcu::TestLog::Message
3331 << "Error different than GL_INVALID_OPEARATION was generated."
3332 << tcu::TestLog::EndMessage;
3333
3334 break;
3335 }
3336 }
3337 }
3338 }
3339
3340 if (result)
3341 {
3342 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3343 }
3344 else
3345 {
3346 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3347 }
3348
3349 return STOP;
3350 }
3351
3352 /** Constructor
3353 *
3354 * @param context Test context
3355 * @param extParams Not used.
3356 * @param name Test case's name
3357 * @param description Test case's description
3358 **/
GeometryShaderInsufficientEmittedVerticesTest( Context& context, const ExtParameters& extParams, const char* name, const char* description)3359 GeometryShaderInsufficientEmittedVerticesTest::GeometryShaderInsufficientEmittedVerticesTest(
3360 Context& context, const ExtParameters& extParams, const char* name, const char* description)
3361 : TestCaseBase(context, extParams, name, description)
3362 , m_fbo_id(0)
3363 , m_fs_id(0)
3364 , m_gs_ids(NULL)
3365 , m_number_of_color_components(4)
3366 , m_number_of_gs(2 /*taken from test spec*/)
3367 , m_po_ids(NULL)
3368 , m_texture_height(16)
3369 , m_texture_id(0)
3370 , m_texture_width(16)
3371 {
3372 m_vao_id = 0;
3373 m_vs_id = 0;
3374
3375 /* Allocate enough memory for glReadPixels() data which is respectively: width, height, RGBA components number. */
3376 m_pixels = new glw::GLubyte[m_texture_height * m_texture_width * m_number_of_color_components];
3377 }
3378
3379 /** Deinitializes GLES objects created during the test. */
deinit()3380 void GeometryShaderInsufficientEmittedVerticesTest::deinit()
3381 {
3382 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3383
3384 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
3385
3386 if (m_pixels != NULL)
3387 {
3388 delete[] m_pixels;
3389 m_pixels = NULL;
3390 }
3391
3392 if (m_fbo_id != 0)
3393 {
3394 gl.deleteFramebuffers(1, &m_fbo_id);
3395 m_fbo_id = 0;
3396 }
3397
3398 if (m_fs_id != 0)
3399 {
3400 gl.deleteShader(m_fs_id);
3401 m_fs_id = 0;
3402 }
3403
3404 if (m_gs_ids != 0)
3405 {
3406 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3407 {
3408 gl.deleteShader(m_gs_ids[i]);
3409 m_gs_ids[i] = 0;
3410 }
3411
3412 delete[] m_gs_ids;
3413 m_gs_ids = NULL;
3414 }
3415
3416 if (m_po_ids != 0)
3417 {
3418 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3419 {
3420 gl.deleteProgram(m_po_ids[i]);
3421 m_po_ids[i] = 0;
3422 }
3423
3424 delete[] m_po_ids;
3425 m_po_ids = NULL;
3426 }
3427
3428 if (m_texture_id != 0)
3429 {
3430 gl.deleteTextures(1, &m_texture_id);
3431 m_texture_id = 0;
3432 }
3433
3434 if (m_vao_id != 0)
3435 {
3436 gl.deleteVertexArrays(1, &m_vao_id);
3437 m_vao_id = 0;
3438 }
3439
3440 if (m_vs_id != 0)
3441 {
3442 gl.deleteShader(m_vs_id);
3443 m_vs_id = 0;
3444 }
3445
3446 /* Release base class */
3447 TestCaseBase::deinit();
3448 }
3449
3450 /** Executes the test.
3451 *
3452 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3453 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3454 * Note the function throws exception should an error occur!
3455 **/
iterate()3456 tcu::TestNode::IterateResult GeometryShaderInsufficientEmittedVerticesTest::iterate()
3457 {
3458 /* Define Fragment Shader for purpose of this test. */
3459 const char* fs_code = "${VERSION}\n"
3460 "\n"
3461 "precision highp float;\n"
3462 "\n"
3463 "out vec4 result;\n"
3464 "\n"
3465 "void main()\n"
3466 "{\n"
3467 " result = vec4(1.0, 0.0, 0.0, 0.0);\n"
3468 "}\n";
3469
3470 /* Define 2 Geometry Shaders for purpose of this test. */
3471 const char* gs_line_strip = "${VERSION}\n"
3472 "${GEOMETRY_SHADER_REQUIRE}\n"
3473 "\n"
3474 "layout (points) in;\n"
3475 "layout (line_strip, max_vertices = 2) out;\n"
3476 "\n"
3477 "${IN_PER_VERTEX_DECL_ARRAY}"
3478 "\n"
3479 "void main()\n"
3480 "{\n"
3481 " gl_Position = gl_in[0].gl_Position;\n"
3482 " gl_Position.zw = vec2(0.0, 1.0);\n"
3483 " EmitVertex();\n"
3484 "}\n";
3485
3486 const char* gs_triangle_strip = "${VERSION}\n"
3487 "${GEOMETRY_SHADER_REQUIRE}\n"
3488 "\n"
3489 "layout (points) in;\n"
3490 "layout (triangle_strip, max_vertices = 3) out;\n"
3491 "\n"
3492 "${IN_PER_VERTEX_DECL_ARRAY}"
3493 "\n"
3494 "void main()\n"
3495 "{\n"
3496 " gl_Position = gl_in[0].gl_Position;\n"
3497 " gl_Position.zw = vec2(0.0, 1.0);\n"
3498 " EmitVertex();\n"
3499
3500 " gl_Position = gl_in[0].gl_Position;\n"
3501 " gl_Position.zw = vec2(0.0, 1.0);\n"
3502 " EmitVertex();\n"
3503 "}\n";
3504
3505 bool has_shader_compilation_failed = true;
3506 bool result = true;
3507
3508 m_gs_ids = new glw::GLuint[m_number_of_gs];
3509 m_po_ids = new glw::GLuint[m_number_of_gs];
3510
3511 /* This test should only run if EXT_geometry_shader is supported. */
3512 if (!m_is_geometry_shader_extension_supported)
3513 {
3514 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3515 }
3516
3517 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3518
3519 /* Create program objects & geometry shader objects. */
3520 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3521 {
3522 m_gs_ids[i] = gl.createShader(GL_GEOMETRY_SHADER);
3523 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3524
3525 m_po_ids[i] = gl.createProgram();
3526 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3527 }
3528
3529 /* Create shader object. */
3530 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
3531 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3532 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3533
3534 /* Try to link the test program object */
3535 std::string fs_code_specialized = specializeShader(1, &fs_code);
3536 const char* fs_code_specialized_raw = fs_code_specialized.c_str();
3537
3538 std::string gs_codes_specialized[] = { specializeShader(1, &gs_line_strip),
3539 specializeShader(1, &gs_triangle_strip) };
3540
3541 const char* gs_codes_specialized_raw[] = { gs_codes_specialized[0].c_str(), gs_codes_specialized[1].c_str() };
3542
3543 std::string vs_code_specialized = specializeShader(1, &minimal_vs_code);
3544 const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3545
3546 for (glw::GLuint i = 0; i < m_number_of_gs; ++i)
3547 {
3548 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */
3549 &fs_code_specialized_raw, m_gs_ids[i], 1, /* n_sh2_body_parts */
3550 &gs_codes_specialized_raw[i], m_vs_id, 1, /* n_sh3_body_parts */
3551 &vs_code_specialized_raw, &has_shader_compilation_failed))
3552 {
3553 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed for i = "
3554 << "[" << i << "]." << tcu::TestLog::EndMessage;
3555
3556 result = false;
3557 break;
3558 }
3559 }
3560
3561 if (result)
3562 {
3563 /* Create a 2D texture. */
3564 gl.genTextures(1, &m_texture_id);
3565 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures() call failed.");
3566
3567 gl.bindTexture(GL_TEXTURE_2D, m_texture_id);
3568 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture() call failed.");
3569
3570 gl.texStorage2D(GL_TEXTURE_2D, 1 /*levels*/, GL_RGBA8, 16 /*width taken from spec*/,
3571 16 /*height taken from spec*/);
3572 GLU_EXPECT_NO_ERROR(gl.getError(), "glTexStorage2D() call failed.");
3573
3574 /* Configure FBO. */
3575 gl.genFramebuffers(1, &m_fbo_id);
3576 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers() call failed.");
3577
3578 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
3579 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer() call failed.");
3580
3581 gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_texture_id, 0 /*level*/);
3582 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferTexture2D() call failed.");
3583
3584 /* Configure VAO. */
3585 gl.genVertexArrays(1, &m_vao_id);
3586 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call failed.");
3587
3588 gl.bindVertexArray(m_vao_id);
3589 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call failed.");
3590
3591 gl.clearColor(0.0f, 1.0f, 0.0f, 0.0f);
3592 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor() call failed.");
3593
3594 for (glw::GLuint po = 0; po < m_number_of_gs; ++po)
3595 {
3596 /* Use Program Object. */
3597 gl.useProgram(m_po_ids[po]);
3598 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call failed.");
3599
3600 gl.clear(GL_COLOR_BUFFER_BIT);
3601 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear() call failed.");
3602
3603 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3604 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call failed for GL_POINTS pname.");
3605
3606 gl.readPixels(0 /*x*/, 0 /*y*/, m_texture_width, m_texture_height, GL_RGBA, GL_UNSIGNED_BYTE, m_pixels);
3607 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels() call failed.");
3608
3609 for (glw::GLuint pixel = 0; pixel < (m_texture_width * m_texture_height * m_number_of_color_components -
3610 m_number_of_color_components);
3611 pixel += m_number_of_color_components)
3612 {
3613 if (m_pixels[pixel] != 0 && m_pixels[pixel + 1] != 255 && m_pixels[pixel + 2] != 0 &&
3614 m_pixels[pixel + 3] != 0)
3615 {
3616 result = false;
3617
3618 m_testCtx.getLog() << tcu::TestLog::Message << "Pixel [" << pixel << "] has color = ["
3619 << m_pixels[pixel] << ", " << m_pixels[pixel + 1] << ", " << m_pixels[pixel + 2]
3620 << ", " << m_pixels[pixel + 3] << "] "
3621 << "instead of [0, 255, 0, 0]." << tcu::TestLog::EndMessage;
3622
3623 break;
3624 }
3625 }
3626 }
3627 }
3628
3629 if (result)
3630 {
3631 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3632 }
3633 else
3634 {
3635 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3636 }
3637
3638 return STOP;
3639 }
3640
3641 /** Constructor
3642 *
3643 * @param context Test context
3644 * @param extParams Not used.
3645 * @param name Test case's name
3646 * @param description Test case's description
3647 **/
3648 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::
GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context& context, const ExtParameters& extParams, const char* name, const char* description)3649 GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest(Context& context,
3650 const ExtParameters& extParams,
3651 const char* name,
3652 const char* description)
3653 : TestCaseBase(context, extParams, name, description)
3654 , m_gs_id(0)
3655 , m_gs_po_id(0)
3656 , m_ppo_id(0)
3657 , m_tfbo_id(0)
3658 , m_vao_id(0)
3659 , m_vs_id(0)
3660 , m_vs_po_id(0)
3661 {
3662 }
3663
3664 /** Deinitializes GLES objects created during the test. */
deinit()3665 void GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::deinit()
3666 {
3667 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3668
3669 if (m_gs_id != 0)
3670 {
3671 gl.deleteShader(m_gs_id);
3672 m_gs_id = 0;
3673 }
3674
3675 if (m_gs_po_id != 0)
3676 {
3677 gl.deleteProgram(m_gs_po_id);
3678 m_gs_po_id = 0;
3679 }
3680
3681 if (m_ppo_id != 0)
3682 {
3683 gl.deleteProgramPipelines(1, &m_ppo_id);
3684 m_ppo_id = 0;
3685 }
3686
3687 if (m_tfbo_id != 0)
3688 {
3689 gl.deleteBuffers(1, &m_tfbo_id);
3690 m_tfbo_id = 0;
3691 }
3692
3693 if (m_vao_id != 0)
3694 {
3695 gl.deleteVertexArrays(1, &m_vao_id);
3696 m_vao_id = 0;
3697 }
3698
3699 if (m_vs_id != 0)
3700 {
3701 gl.deleteShader(m_vs_id);
3702 m_vs_id = 0;
3703 }
3704
3705 if (m_vs_po_id != 0)
3706 {
3707 gl.deleteProgram(m_vs_po_id);
3708 m_vs_po_id = 0;
3709 }
3710
3711 /* Release base class */
3712 TestCaseBase::deinit();
3713 }
3714
3715 /** Executes the test.
3716 *
3717 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
3718 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
3719 * Note the function throws exception should an error occur!
3720 **/
iterate()3721 tcu::TestNode::IterateResult GeometryShaderPipelineObjectTransformFeedbackVertexAndGeometryShaderCaptureTest::iterate()
3722 {
3723 /* Define Geometry Shader for purpose of this test. */
3724 const char* gs_code =
3725 "${VERSION}\n"
3726 "${GEOMETRY_SHADER_REQUIRE}\n"
3727 "${IN_PER_VERTEX_DECL_ARRAY}\n"
3728 "${OUT_PER_VERTEX_DECL}\n"
3729 "\n"
3730 "layout (points) in;\n"
3731 "layout (points, max_vertices = 1) out;\n"
3732 "\n"
3733 "flat in int vertexID[];\n"
3734 "flat in ivec4 out_vs_1[];\n"
3735 "\n"
3736 "out vec4 out_gs_1;\n"
3737 "\n"
3738 "void main()\n"
3739 "{\n"
3740 " out_gs_1 = vec4(vertexID[0] * 2, vertexID[0] * 2 + 1, vertexID[0] * 2 + 2, vertexID[0] * 2 + 3);\n"
3741 " gl_Position = vec4(0, 0, 0, 1);\n"
3742 " EmitVertex();\n"
3743 "}\n";
3744
3745 /* Define Vertex Shader for purpose of this test. */
3746 const char* vs_code = "${VERSION}\n"
3747 "${OUT_PER_VERTEX_DECL}\n"
3748 "\n"
3749 "flat out ivec4 out_vs_1;\n"
3750 "flat out int vertexID;\n"
3751 "\n"
3752 "void main()\n"
3753 "{\n"
3754 " vertexID = gl_VertexID;\n"
3755 " out_vs_1 = ivec4(gl_VertexID, gl_VertexID + 1, gl_VertexID + 2, gl_VertexID + 3);\n"
3756 " gl_Position = vec4(1.0, 0.0, 0.0, 1.0);\n"
3757 "}\n";
3758
3759 bool has_shader_compilation_failed = true;
3760 bool result = true;
3761 glw::GLfloat* ptrTF_data_f = NULL;
3762 glw::GLuint* ptrTF_data_ui = NULL;
3763 glw::GLfloat expected_geom_results[] = { 0.0f, 1.0f, 2.0f, 3.0f };
3764 glw::GLuint expected_vertex_results[] = { 0, 1, 2, 3 };
3765 glw::GLfloat epsilon = 1e-5f;
3766
3767 /* This test should only run if EXT_geometry_shader is supported. */
3768 if (!m_is_geometry_shader_extension_supported)
3769 {
3770 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
3771 }
3772
3773 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3774
3775 /* Create separable program objects. */
3776 m_gs_po_id = gl.createProgram();
3777 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3778
3779 gl.programParameteri(m_gs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3780 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3781
3782 m_vs_po_id = gl.createProgram();
3783 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
3784
3785 gl.programParameteri(m_vs_po_id, GL_PROGRAM_SEPARABLE, GL_TRUE);
3786 GLU_EXPECT_NO_ERROR(gl.getError(), "glProgramParameteri() call failed.");
3787
3788 /* Create shader objects. */
3789 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
3790 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
3791 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
3792
3793 /* Try to link the test program object */
3794 std::string gs_code_specialized = specializeShader(1, &gs_code);
3795 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
3796
3797 std::string vs_code_specialized = specializeShader(1, &vs_code);
3798 const char* vs_code_specialized_raw = vs_code_specialized.c_str();
3799
3800 /* Specify output variables to be captured. */
3801 const char* tf_varyings[2] = { "out_gs_1", "out_vs_1" };
3802
3803 gl.transformFeedbackVaryings(m_gs_po_id, 1 /*count*/, &tf_varyings[0], GL_INTERLEAVED_ATTRIBS);
3804 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3805
3806 gl.transformFeedbackVaryings(m_vs_po_id, 1 /*count*/, &tf_varyings[1], GL_INTERLEAVED_ATTRIBS);
3807 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
3808
3809 if (!TestCaseBase::buildProgram(m_gs_po_id, m_gs_id, 1, /* n_sh1_body_parts */
3810 &gs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3811 NULL, 0, 0, /* n_sh3_body_parts */
3812 NULL, &has_shader_compilation_failed))
3813 {
3814 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3815 << tcu::TestLog::EndMessage;
3816
3817 result = false;
3818 goto end;
3819 }
3820
3821 if (!TestCaseBase::buildProgram(m_vs_po_id, m_vs_id, 1, /* n_sh1_body_parts */
3822 &vs_code_specialized_raw, 0, 0, /* n_sh2_body_parts */
3823 NULL, 0, 0, /* n_sh3_body_parts */
3824 NULL, &has_shader_compilation_failed))
3825 {
3826 m_testCtx.getLog() << tcu::TestLog::Message << "Geometry Shader Program object linking failed."
3827 << tcu::TestLog::EndMessage;
3828
3829 result = false;
3830 goto end;
3831 }
3832
3833 /* Create and configure Program Pipeline Object. */
3834 gl.genProgramPipelines(1, &m_ppo_id);
3835 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenProgramPipelines() call(s) failed.");
3836
3837 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, m_gs_po_id);
3838 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3839
3840 gl.useProgramStages(m_ppo_id, GL_VERTEX_SHADER_BIT, m_vs_po_id);
3841 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3842
3843 /* Create Vertex Array Object. */
3844 gl.genVertexArrays(1, &m_vao_id);
3845 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
3846
3847 gl.bindVertexArray(m_vao_id);
3848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
3849
3850 /* Create Buffer Object for Transform Feedback data. */
3851 gl.genBuffers(1, &m_tfbo_id);
3852 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
3853
3854 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
3855 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
3856
3857 gl.bufferData(GL_ARRAY_BUFFER, sizeof(glw::GLfloat) * 4, NULL, GL_STREAM_READ);
3858 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
3859
3860 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
3861 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
3862
3863 /* Ensure that there is no program object already bound and bind program pipeline. */
3864 gl.useProgram(0);
3865 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
3866
3867 gl.bindProgramPipeline(m_ppo_id);
3868 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindProgramPipeline() call(s) failed.");
3869
3870 gl.enable(GL_RASTERIZER_DISCARD);
3871 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
3872
3873 /* First pass - Vertex and Geometry Shaders On. */
3874 gl.beginTransformFeedback(GL_POINTS);
3875 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3876
3877 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3878 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3879
3880 gl.endTransformFeedback();
3881 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3882
3883 /* Retrieve data and check if it is correct. */
3884 ptrTF_data_f =
3885 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3886 sizeof(glw::GLfloat) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3887 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3888
3889 for (size_t i = 0; i < 4; ++i)
3890 {
3891 if (fabs(ptrTF_data_f[i] - expected_geom_results[i]) >= epsilon)
3892 {
3893 result = false;
3894 break;
3895 }
3896 }
3897
3898 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3899 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3900
3901 ptrTF_data_f = NULL;
3902
3903 if (!result)
3904 {
3905 goto end;
3906 }
3907
3908 /* Deactivate Geometry Shader Program Object from Program Pipeline Object. */
3909 gl.useProgramStages(m_ppo_id, GL_GEOMETRY_SHADER_BIT, 0 /* program */);
3910 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgramStages() call(s) failed.");
3911
3912 /* Second pass - only Vertex Shader Program On. */
3913 gl.beginTransformFeedback(GL_POINTS);
3914 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
3915
3916 gl.drawArrays(GL_POINTS, 0 /*first*/, 1 /*count*/);
3917 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() call(s) failed.");
3918
3919 gl.endTransformFeedback();
3920 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
3921
3922 gl.disable(GL_RASTERIZER_DISCARD);
3923 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
3924
3925 /* Retrieve data and check if it is correct. */
3926 ptrTF_data_ui =
3927 (glw::GLuint*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*offset*/,
3928 sizeof(glw::GLuint) * 4 /* four float vector components */, GL_MAP_READ_BIT);
3929 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange() call failed.");
3930
3931 for (size_t i = 0; i < 4; ++i)
3932 {
3933 if (ptrTF_data_ui[i] != expected_vertex_results[i])
3934 {
3935 result = false;
3936 break;
3937 }
3938 }
3939
3940 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3941 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() call failed.");
3942
3943 ptrTF_data_ui = NULL;
3944
3945 end:
3946 if (result)
3947 {
3948 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3949 }
3950 else
3951 {
3952 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3953 }
3954
3955 return STOP;
3956 }
3957
3958 /** Constructor
3959 *
3960 * @param context Test context
3961 * @param extParams Not used.
3962 * @param name Test case's name
3963 * @param description Test case's description
3964 **/
GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives( Context& context, const ExtParameters& extParams, const char* name, const char* description)3965 GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives(
3966 Context& context, const ExtParameters& extParams, const char* name, const char* description)
3967 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_po_id(0), m_tfbo_id(0)
3968 {
3969 m_vao_id = 0;
3970 m_vs_id = 0;
3971 }
3972
3973 /** Deinitializes GLES objects created during the test. */
deinit()3974 void GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::deinit()
3975 {
3976 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3977
3978 if (m_fs_id != 0)
3979 {
3980 gl.deleteShader(m_fs_id);
3981 m_fs_id = 0;
3982 }
3983
3984 if (m_gs_id != 0)
3985 {
3986 gl.deleteShader(m_gs_id);
3987 m_gs_id = 0;
3988 }
3989
3990 if (m_po_id != 0)
3991 {
3992 gl.deleteProgram(m_po_id);
3993 m_po_id = 0;
3994 }
3995
3996 if (m_tfbo_id != 0)
3997 {
3998 gl.deleteBuffers(1, &m_tfbo_id);
3999 m_tfbo_id = 0;
4000 }
4001
4002 if (m_vao_id != 0)
4003 {
4004 gl.deleteVertexArrays(1, &m_vao_id);
4005 m_vao_id = 0;
4006 }
4007
4008 if (m_vs_id != 0)
4009 {
4010 gl.deleteShader(m_vs_id);
4011 m_vs_id = 0;
4012 }
4013
4014 /* Release base class */
4015 TestCaseBase::deinit();
4016 }
4017
4018 /** Executes the test.
4019 *
4020 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4021 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4022 * Note the function throws exception should an error occur!
4023 **/
iterate()4024 tcu::TestNode::IterateResult GeometryShaderDrawPrimitivesDoNotMatchOutputPrimitives::iterate()
4025 {
4026 /* Define Geometry Shader for purpose of this test. */
4027 const char* gs_code = "${VERSION}\n"
4028 "${GEOMETRY_SHADER_REQUIRE}\n"
4029 "\n"
4030 "layout (lines) in;\n"
4031 "layout (triangle_strip, max_vertices = 3) out;\n"
4032 "\n"
4033 "out vec4 out_gs_1;\n"
4034 "\n"
4035 "void main()\n"
4036 "{\n"
4037 " out_gs_1 = vec4(4.0, 3.0, 2.0, 1.0);\n"
4038 "\n"
4039 " gl_Position = vec4(0, 0, 0, 1);\n"
4040 " EmitVertex();\n"
4041 "\n"
4042 " gl_Position = vec4(1, 0, 0, 1);\n"
4043 " EmitVertex();\n"
4044 "\n"
4045 " gl_Position = vec4(1, 1, 0, 1);\n"
4046 " EmitVertex();\n"
4047 "\n"
4048 " EndPrimitive();"
4049 "}\n";
4050
4051 bool has_shader_compilation_failed = true;
4052 bool result = true;
4053 glw::GLenum error = GL_NO_ERROR;
4054
4055 /* This test should only run if EXT_geometry_shader is supported. */
4056 if (!m_is_geometry_shader_extension_supported)
4057 {
4058 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4059 }
4060
4061 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4062
4063 /* Create program object. */
4064 m_po_id = gl.createProgram();
4065 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call failed.");
4066
4067 /* Specify output variables to be captured. */
4068 const char* tf_varyings[] = { "out_gs_1" };
4069
4070 gl.transformFeedbackVaryings(m_po_id, 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4071 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4072
4073 /* Create shader objects. */
4074 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4075 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4076 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4077 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4078
4079 /* Try to link the test program object */
4080 std::string fs_code_specialized = specializeShader(1, &minimal_fs_code);
4081 const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4082
4083 std::string gs_code_specialized = specializeShader(1, &gs_code);
4084 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4085
4086 std::string vs_code_specialized = specializeShader(1, &minimal_vs_code);
4087 const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4088
4089 if (!TestCaseBase::buildProgram(m_po_id, m_fs_id, 1, /* n_sh1_body_parts */
4090 &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4091 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4092 &vs_code_specialized_raw, &has_shader_compilation_failed))
4093 {
4094 m_testCtx.getLog() << tcu::TestLog::Message << "Program object linking failed whereas a success was expected."
4095 << tcu::TestLog::EndMessage;
4096
4097 result = false;
4098 goto end;
4099 }
4100
4101 /* Create Vertex Array Object. */
4102 gl.genVertexArrays(1, &m_vao_id);
4103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4104
4105 gl.bindVertexArray(m_vao_id);
4106 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4107
4108 /* Create Buffer Object for Transform Feedback data. */
4109 gl.genBuffers(1, &m_tfbo_id);
4110 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4111
4112 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4113 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4114
4115 gl.bufferData(GL_ARRAY_BUFFER,
4116 sizeof(glw::GLfloat) * 4 * 3 /* capture 4 float vector components times 3 triangle vertices */, NULL,
4117 GL_STREAM_READ);
4118 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4119
4120 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4121 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4122
4123 /* Turn on program object. */
4124 gl.useProgram(m_po_id);
4125 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4126
4127 gl.enable(GL_RASTERIZER_DISCARD);
4128 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4129
4130 gl.beginTransformFeedback(GL_LINES);
4131 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4132
4133 gl.drawArrays(GL_TRIANGLES, 0 /*first*/, 3 /*count*/);
4134
4135 error = gl.getError();
4136
4137 if (error != GL_INVALID_OPERATION)
4138 {
4139 result = false;
4140
4141 m_testCtx.getLog() << tcu::TestLog::Message << "Error different than GL_INVALID_OPEARATION was generated."
4142 << tcu::TestLog::EndMessage;
4143 }
4144
4145 gl.endTransformFeedback();
4146 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4147
4148 gl.disable(GL_RASTERIZER_DISCARD);
4149 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4150
4151 end:
4152
4153 if (result)
4154 {
4155 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4156 }
4157 else
4158 {
4159 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4160 }
4161
4162 return STOP;
4163 }
4164
4165 /** Constructor
4166 *
4167 * @param context Test context
4168 * @param extParams Not used.
4169 * @param name Test case's name
4170 * @param description Test case's description
4171 **/
GeometryShaderDrawCallsWhileTFPaused(Context& context, const ExtParameters& extParams, const char* name, const char* description)4172 GeometryShaderDrawCallsWhileTFPaused::GeometryShaderDrawCallsWhileTFPaused(Context& context,
4173 const ExtParameters& extParams,
4174 const char* name, const char* description)
4175 : TestCaseBase(context, extParams, name, description), m_fs_id(0), m_gs_id(0), m_tfbo_id(0)
4176 {
4177 m_vao_id = 0;
4178 m_vs_id = 0;
4179 }
4180
4181 /** Deinitializes GLES objects created during the test. */
deinit()4182 void GeometryShaderDrawCallsWhileTFPaused::deinit()
4183 {
4184 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4185
4186 if (m_fs_id != 0)
4187 {
4188 gl.deleteShader(m_fs_id);
4189 m_fs_id = 0;
4190 }
4191
4192 if (m_gs_id != 0)
4193 {
4194 gl.deleteShader(m_gs_id);
4195 m_gs_id = 0;
4196 }
4197
4198 for (int i = 0; i < 15 /* All combinations of possible inputs and outputs in GS */; ++i)
4199 {
4200 if (m_po_ids[i] != 0)
4201 {
4202 gl.deleteProgram(m_po_ids[i]);
4203 m_po_ids[i] = 0;
4204 }
4205 }
4206
4207 if (m_tfbo_id != 0)
4208 {
4209 gl.deleteBuffers(1, &m_tfbo_id);
4210 m_tfbo_id = 0;
4211 }
4212
4213 if (m_vao_id != 0)
4214 {
4215 gl.deleteVertexArrays(1, &m_vao_id);
4216 m_vao_id = 0;
4217 }
4218
4219 if (m_vs_id != 0)
4220 {
4221 gl.deleteShader(m_vs_id);
4222 m_vs_id = 0;
4223 }
4224
4225 /* Release base class */
4226 TestCaseBase::deinit();
4227 }
4228
4229 /** Executes the test.
4230 *
4231 * Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
4232 * @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
4233 * Note the function throws exception should an error occur!
4234 **/
iterate()4235 tcu::TestNode::IterateResult GeometryShaderDrawCallsWhileTFPaused::iterate()
4236 {
4237 /* Define 15 (all combinations of possible inputs and outputs in geometry shader) Geometry Shaders for purpose of this test. */
4238 const std::string gs_inputs[] = { "points", "lines", "lines_adjacency", "triangles", "triangles_adjacency" };
4239 const std::string gs_outputs[] = { "points", "line_strip", "triangle_strip" };
4240 const std::string gs_max_output_vertices[] = { "1", "2", "3" };
4241
4242 const unsigned short number_of_combinations =
4243 (sizeof(gs_inputs) / sizeof(gs_inputs[0]) * (sizeof(gs_outputs) / sizeof(gs_outputs[0])));
4244
4245 std::string gs_codes[number_of_combinations];
4246 glw::GLenum errorCode;
4247
4248 for (size_t i = 0; i < (sizeof(gs_inputs) / sizeof(gs_inputs[0])) /*5 possible GS inputs*/; ++i)
4249 {
4250 for (size_t j = 0; j < (sizeof(gs_outputs) / sizeof(gs_outputs[0])) /*3 possible GS outputs*/; ++j)
4251 {
4252 /* This shader will not emit primitives for anything but points.
4253 * We do so, because we just need to make sure that, while transform feedback
4254 * is paused, all draw calls executed with an active program object which
4255 * includes a geometry shader, are valid.
4256 */
4257 gs_codes[j + 3 * i] = "${VERSION}\n"
4258 "${GEOMETRY_SHADER_REQUIRE}\n"
4259 "\n"
4260 "layout (" +
4261 gs_inputs[i] + ") in;\n"
4262 "layout (" +
4263 gs_outputs[j] + ", max_vertices = " + gs_max_output_vertices[j] +
4264 ") out;\n"
4265 "\n"
4266 "out vec2 out_gs_1;\n"
4267 "\n"
4268 "void main()\n"
4269 "{\n"
4270 " out_gs_1 = vec2(1.0, 2.0);\n"
4271 " gl_Position = vec4(0, 0, 0, 1);\n"
4272 " EmitVertex();\n"
4273 "}\n";
4274 }
4275 }
4276
4277 bool has_shader_compilation_failed = true;
4278 bool result = true;
4279 const glw::GLuint tf_modes[3] = { GL_POINTS, GL_LINES, GL_TRIANGLES };
4280 const glw::GLuint draw_call_modes[5] = { GL_POINTS, GL_LINES, GL_LINES_ADJACENCY, GL_TRIANGLES,
4281 GL_TRIANGLES_ADJACENCY };
4282
4283 /* This test should only run if EXT_geometry_shader is supported. */
4284 if (!m_is_geometry_shader_extension_supported)
4285 {
4286 throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
4287 }
4288
4289 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4290
4291 /* Create program objects. */
4292 for (int i = 0; i < number_of_combinations; ++i)
4293 {
4294 m_po_ids[i] = gl.createProgram();
4295 }
4296 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() call(s) failed.");
4297
4298 /* Specify output variables to be captured. */
4299 const char* tf_varyings[] = { "out_gs_1" };
4300
4301 for (int i = 0; i < number_of_combinations; ++i)
4302 {
4303 gl.transformFeedbackVaryings(m_po_ids[i], 1 /*count*/, tf_varyings, GL_INTERLEAVED_ATTRIBS);
4304 }
4305 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() call(s) failed.");
4306
4307 /* Create shader objects. */
4308 m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
4309 m_gs_id = gl.createShader(GL_GEOMETRY_SHADER);
4310 m_vs_id = gl.createShader(GL_VERTEX_SHADER);
4311 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() call(s) failed.");
4312
4313 /* Try to link the test program object */
4314 std::string fs_code_specialized = specializeShader(1, &minimal_fs_code);
4315 const char* fs_code_specialized_raw = fs_code_specialized.c_str();
4316
4317 std::string vs_code_specialized = specializeShader(1, &minimal_vs_code);
4318 const char* vs_code_specialized_raw = vs_code_specialized.c_str();
4319
4320 for (int i = 0; i < number_of_combinations; ++i)
4321 {
4322 const char* gs_code = gs_codes[i].c_str();
4323 std::string gs_code_specialized = specializeShader(1, &gs_code);
4324 const char* gs_code_specialized_raw = gs_code_specialized.c_str();
4325
4326 if (!TestCaseBase::buildProgram(m_po_ids[i], m_fs_id, 1, /* n_sh1_body_parts */
4327 &fs_code_specialized_raw, m_gs_id, 1, /* n_sh2_body_parts */
4328 &gs_code_specialized_raw, m_vs_id, 1, /* n_sh3_body_parts */
4329 &vs_code_specialized_raw, &has_shader_compilation_failed))
4330 {
4331 m_testCtx.getLog() << tcu::TestLog::Message
4332 << "Program object linking failed whereas a success was expected."
4333 << tcu::TestLog::EndMessage;
4334
4335 result = false;
4336 }
4337 }
4338
4339 if (!result)
4340 {
4341 goto end;
4342 }
4343
4344 /* Create Vertex Array Object. */
4345 gl.genVertexArrays(1, &m_vao_id);
4346 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays() call(s) failed.");
4347
4348 gl.bindVertexArray(m_vao_id);
4349 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray() call(s) failed.");
4350
4351 /* Create Buffer Object for Transform Feedback data. */
4352 gl.genBuffers(1, &m_tfbo_id);
4353 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() call(s) failed.");
4354
4355 gl.bindBuffer(GL_ARRAY_BUFFER, m_tfbo_id);
4356 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() call(s) failed.");
4357
4358 gl.bufferData(GL_ARRAY_BUFFER,
4359 sizeof(glw::GLfloat) * 2 * 3 /* capture 2 float vector components times 3 triangle vertices */, NULL,
4360 GL_STREAM_READ);
4361 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() call(s) failed.");
4362
4363 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /*binding index*/, m_tfbo_id);
4364 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase() call(s) failed.");
4365
4366 gl.enable(GL_RASTERIZER_DISCARD);
4367 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable() call(s) failed.");
4368
4369 for (int i = 0; i < 3 /* number of TF modes */ && result; ++i)
4370 {
4371 for (int j = 0; j < 5 /*number of draw call modes*/ && result; ++j)
4372 {
4373 for (int k = 0; k < 3 /* number of output GS primitive types */; ++k)
4374 {
4375 /* Turn on program object. */
4376 gl.useProgram(m_po_ids[k + 3 * j]);
4377 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() call(s) failed.");
4378
4379 gl.beginTransformFeedback(tf_modes[i]);
4380 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() call(s) failed.");
4381
4382 gl.pauseTransformFeedback();
4383 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback() call(s) failed.");
4384
4385 gl.drawArrays(draw_call_modes[j], 0 /*first*/, 3 /*count*/);
4386 errorCode = gl.getError();
4387
4388 gl.resumeTransformFeedback();
4389 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback() call(s) failed.");
4390
4391 gl.endTransformFeedback();
4392 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() call(s) failed.");
4393
4394 /* If draw call fails stop test execution. */
4395 if (GL_NO_ERROR != errorCode)
4396 {
4397 m_testCtx.getLog() << tcu::TestLog::Message
4398 << "glDrawArrays() call generated an error while transform feedback was paused."
4399 << tcu::TestLog::EndMessage;
4400
4401 result = false;
4402 break;
4403 }
4404 }
4405 }
4406 }
4407
4408 gl.disable(GL_RASTERIZER_DISCARD);
4409 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable() call(s) failed.");
4410
4411 end:
4412
4413 if (result)
4414 {
4415 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4416 }
4417 else
4418 {
4419 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4420 }
4421
4422 return STOP;
4423 }
4424
4425 } // namespace glcts
4426