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