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