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